aboutsummaryrefslogtreecommitdiffstats
path: root/tools/debugger/kdd/kdd.h
blob: bfb00ba5c55ef70b8aa991f49b4855e3aa9ae724 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
/*
 * kdd.h -- Structures, constants and descriptions of the Windows 
 *          kd serial debugger protocol, for the kdd debugging stub.
 *
 * Tim Deegan <Tim.Deegan@citrix.com>
 * 
 * Copyright (c) 2007-2010, Citrix Systems Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _KDD_H_
#define _KDD_H_

#include <stdint.h>

#define PACKED __attribute__((packed))

/*****************************************************************************
 * Serial line protocol: Sender sends a 16-byte header with an optional
 * payload following it.  Receiver responds to each packet with an
 * acknowledgment (16-byte header only).
 *
 * Packet headers start with ASCII "0000" and there is a trailing byte
 * 0xAA after the (optional) payload.  Ack headers start with ASCII
 * "iiii"; no trailing byte).  Each packet and ack has a major type in
 * the packet header; for packets with payload, a minor type is encoded
 * in ASCII in the first four bytes of the payload.
 *
 * Packet IDs seem to start at 0x80800000 and alternate between that and
 * 0x80800001; not clear whether the client's ID is always the ID of the
 * last packet from the kernel or whether they're just oscillating in
 * phase.  Either way there's clearly some state machine in the kernel
 * that requires this exact behaviour from the client.
 *
 * All acks have length 0, id = id of the packet they ack.
 */

#define KDD_DIR_PKT 0x30303030   /* "0000" */
#define KDD_DIR_ACK 0x69696969   /* "iiii" */

typedef struct {
    uint32_t dir;     /* KDD_DIR_PKT or KDD_DIR_ACK */
    uint16_t type;    /* Major type. */
    uint16_t len;     /* Payload length, excl. header and trailing byte */
    uint32_t id;      /* Echoed in responses */
    uint32_t sum;     /* Unsigned sum of all payload bytes */
    uint8_t payload[0];
} PACKED kdd_hdr;

#define KDD_PKT_CMD 0x0002      /* Debugger commands (and replies to them) */
#define KDD_PKT_MSG 0x0003      /* Kernel messages for the user */
#define KDD_PKT_STC 0x0007      /* State change notification */
#define KDD_PKT_REG 0x000b      /* Registry change notification (?) */
#define KDD_PKT_MAX 0x000b

#define KDD_ACK_OK  0x0004      /* Checksum, ID and type all fine */
#define KDD_ACK_BAD 0x0005      /* Something is bogus */
#define KDD_ACK_RST 0x0006      /* Not really an ack; one each way to resync */


/*****************************************************************************
 * Debugger commands, carried over the serial line.  In this protocol,
 * we ignore the serial-level acking; when we talk about a response,
 * it's another packet, sent after the request was acked, and which will
 * itself be acked.
 *
 * The debugger client sends commands to the kernel, all of which have
 * major type 2 and are 56 bytes long (not including the serial header).
 * Not all the 56 bytes are used in every command, but the client
 * doesn't bother to zero unused fields.  Most commands are responded to
 * by a packet with the same subtype, containing at least a status code
 * to indicate success or failure.
 */

#define KDD_STATUS_SUCCESS  0x00000000
#define KDD_STATUS_FAILURE  0xc0000001
#define KDD_STATUS_PENDING  0x00000103

/* Memory access.  Read commands are echoed in the response with the
 * status and length_rsp fields updated, and the read data appended to the
 * packet.  Writes are the same, but with the data appended to the
 * write command, not the response. */

#define KDD_CMD_READ_VA     0x00003130  /* "01" */
#define KDD_CMD_WRITE_VA    0x00003131  /* "11" */
#define KDD_CMD_READ_CTRL   0x00003137  /* "71" */
#define KDD_CMD_WRITE_CTRL  0x00003138  /* "81" */
#define KDD_CMD_READ_PA     0x0000313D  /* "=1" */
#define KDD_CMD_WRITE_PA    0x0000313E  /* ">1" */

/* Not sure what this is, but it doesn't require a response */
#define KDD_CMD_WRITE_Z     0x0000315A  /* "Z1" */

typedef struct {
    uint32_t u1;
    uint32_t status;            /* IN: STATUS_PENDING; OUT: result status. */
    uint32_t u2;
    uint64_t addr;              /* IN: address of start of read/write */
    uint32_t length_req;        /* IN: bytes to read/write */
    uint32_t length_rsp;        /* OUT: bytes successfully read/written */
} PACKED kdd_cmd_mem;

/* CPU register access.  As for memory accesses, but the data is a
 * fixed-length block of register info. */

#define KDD_CMD_READ_REGS   0x00003132  /* "21" */
#define KDD_CMD_WRITE_REGS  0x00003133  /* "31" */

typedef struct {
    uint16_t u1;
    uint16_t cpu;               /* IN: Zero-based processor ID */
    uint32_t status;            /* IN: STATUS_PENDING; OUT: result status. */
} PACKED kdd_cmd_regs;

#define KDD_CMD_READ_MSR    0x00003152  /* "R1" */
#define KDD_CMD_WRITE_MSR   0x00003153  /* "S1" */

typedef struct {
    uint32_t u1;
    uint32_t status;            /* IN: STATUS_PENDING; OUT: result status. */
    uint32_t u2;
    uint32_t msr;               /* IN/OUT: MSR number */
    uint64_t val;               /* IN/OUT: MSR contents */
} PACKED kdd_cmd_msr;

/* Breakpoint commands. */

#define KDD_CMD_SOFT_BP     0x00003135  /* "51" */

typedef struct {
    uint32_t u1;
    uint32_t status;            /* IN: STATUS_PENDING; OUT: result status. */
    uint32_t u2;
    uint32_t bp;                /* IN: ID of breakpoint to operate on */
} PACKED kdd_cmd_soft_bp;

#define KDD_CMD_HARD_BP     0x0000315C  /* "\1" */

typedef struct {
    uint32_t u1;
    uint32_t status;            /* IN: STATUS_PENDING; OUT: result status. */
    uint32_t u2;
    uint64_t address;           /* IN: Address to trap on */
    uint64_t u3;
    uint64_t u4;
    uint64_t u5;
    uint64_t u6;
} PACKED kdd_cmd_hard_bp;

/* Flow control commands.  These commands are _not_ responded to.  */

#define KDD_CMD_CONT1       0x00003136  /* "61" */
#define KDD_CMD_CONT2       0x0000313c  /* "<1" */

#define KDD_DBG_EXCEPTION_HANDLED    0x00010001
#define KDD_DBG_CONTINUE             0x00010002

typedef struct {
    uint32_t u1;
    uint32_t reason1;           /* IN: KDD_DBG_* */
    uint32_t u2;
    uint64_t reason2;           /* IN: always same as reason1 */
} PACKED kdd_cmd_cont;

/* Handshake command. */

#define KDD_CMD_SHAKE       0x00003146 /* "F1" */

#define KDD_MACH_x32        0x014c
#define KDD_MACH_x64        0x8664

#define KDD_FLAGS_MP        0x0001
#define KDD_FLAGS_64        0x0008

typedef struct {
    uint32_t u1;
    uint32_t status;            /* IN: STATUS_PENDING; OUT: result status. */
    uint32_t u2;
    uint16_t v_major;           /* OUT: OS major version (0xf for NT) */
    uint16_t v_minor;           /* OUT: OS minor version (NT build number) */
    uint16_t proto;             /* OUT: Protocol version (6) */
    uint16_t flags;             /* OUT: Some flags (at least 0x3) */
    uint16_t machine;           /* OUT: Machine type */
    uint8_t pkts;               /* OUT: Number of packet types understood */
    uint8_t states;             /* OUT: Number of state-change types used */
    uint8_t manips;             /* OUT: number of "manipulation" types used */
    uint8_t u3[3];
    int64_t kern_addr;          /* OUT: KernBase */
    int64_t mods_addr;          /* OUT: PsLoadedModuleList */
    int64_t data_addr;          /* OUT: DebuggerDataList */
} PACKED kdd_cmd_shake;

/* Change active CPU.  This command is _not_ responded to */

#define KDD_CMD_SETCPU      0x00003150 /* "P1" */

typedef struct {
    uint16_t u1;
    uint16_t cpu;               /* IN: Zero-based processor ID */
    uint32_t status;            /* IN: STATUS_PENDING */
} PACKED kdd_cmd_setcpu;

typedef struct {
    uint32_t subtype;           /* IN: KDD_CMD_x */
    union {
        kdd_cmd_mem mem;
        kdd_cmd_regs regs;
        kdd_cmd_msr msr;
        kdd_cmd_soft_bp sbp;
        kdd_cmd_hard_bp hbp;
        kdd_cmd_cont cont;
        kdd_cmd_shake shake;
        kdd_cmd_setcpu setcpu;
        uint8_t pad[52];
    };
    uint8_t data[0];
} PACKED kdd_cmd;


/*****************************************************************************
 * Kernel messages to the debugger.  The debugger does not respond to these
 * beyond ACKing them and printing approprate things on the debugger
 * console.
 */

/* Messages for the console */

#define KDD_MSG_PRINT       0x00003230  /* "02" */

typedef struct {
    uint32_t subtype;           /* KDD_MSG_PRINT */
    uint32_t u1;
    uint32_t length;            /* Length in bytes of trailing string */
    uint32_t u2;
    uint8_t string[0];          /* Non-terminated character string */
} PACKED kdd_msg;

/* Registry updates (Hive loads?) */

#define KDD_REG_CHANGE      0x00003430  /* "04" */

typedef struct {
    uint32_t subtype;           /* KDD_REG_CHANGE */
    uint32_t u1[15];
    uint16_t string[0];         /* Null-terminated wchar string */
} PACKED kdd_reg;

/* State changes.  After sending a state-change message the kernel halts
 * until it receives a continue command from the debugger. */

#define KDD_STC_STOP        0x00003030  /* "00" : Bug-check */
#define KDD_STC_LOAD        0x00003031  /* "01" : Loaded a module */

#define KDD_STC_STATUS_BREAKPOINT 0x80000003

typedef struct {
    uint16_t u1;
    uint16_t cpu;               /* Zero-based processor ID */
    uint32_t ncpus;             /* Number of processors */
    uint32_t u2;
    int64_t kthread;            /* Kernel thread structure */
    int64_t rip1;               /* Instruction pointer, sign-extended */
    uint64_t status;            /* KDD_STC_STATUS_x */
    uint64_t u3;
    int64_t rip2;               /* Same as rip1 */
    uint64_t nparams;           /* Number of stopcode parameters */
    uint64_t params[15];        /* Stopcode parameters */
    uint64_t first_chance;      /* OS exn handlers not yet been run? */
    uint32_t u4[2];
    uint32_t ilen;              /* Number of bytes of instruction following */
    uint8_t inst[36];           /* VA contents from %eip onwards */
} PACKED kdd_stc_stop;

typedef struct {
    uint32_t u1[3];
    uint64_t u2;
    uint64_t rip;               /* Instruction pointer, sign-extended */
    uint64_t u3[26];
    uint8_t path[0];            /* Null-terminated ASCII path to loaded mod. */
} PACKED kdd_stc_load;

typedef struct {
    uint32_t subtype;           /* KDD_STC_x */
    union {
        kdd_stc_stop stop;
        kdd_stc_load load;
    };
} PACKED kdd_stc;


/*****************************************************************************
 * Overall packet type
 */

typedef struct {
    kdd_hdr h;                  /* Major type disambiguates union below */
    union {
        kdd_cmd cmd;
        kdd_msg msg;
        kdd_reg reg;
        kdd_stc stc;
        uint8_t payload[0];
    };
} PACKED kdd_pkt;


/*****************************************************************************
 * Processor state layouts
 */

/* User-visible register files */
typedef union {
    uint32_t pad[179];
    struct {
        uint32_t u1[7];         /* Flags, DRx?? */
        uint8_t fp[112];        /* FP save state (why 112 not 108?) */
        int32_t gs;
        int32_t fs;
        int32_t es;
        int32_t ds;
        int32_t edi;
        int32_t esi;
        int32_t ebx;
        int32_t edx;
        int32_t ecx;
        int32_t eax;
        int32_t ebp;
        int32_t eip;
        int32_t cs;
        int32_t eflags;
        int32_t esp;
        int32_t ss;
        uint32_t sp2[37];       /* More 0x20202020. fp? */
        uint32_t sp3;           /* 0x00202020 */
    };
} PACKED kdd_regs_x86_32;

typedef union {
    uint64_t pad[154];
    struct {

        uint64_t u1[7];

        uint16_t cs; //2*1c
        uint16_t ds;
        uint16_t es;
        uint16_t fs;
        uint16_t gs;
        uint16_t ss;
        uint32_t rflags;
        uint64_t dr0;
        uint64_t dr1;
        uint64_t dr2;
        uint64_t dr3;
        uint64_t dr6;
        uint64_t dr7;
        int64_t rax;
        int64_t rcx;
        int64_t rdx;
        int64_t rbx;
        int64_t rsp;
        int64_t rbp;
        int64_t rsi;
        int64_t rdi;
        int64_t r8;
        int64_t r9;
        int64_t r10;
        int64_t r11;
        int64_t r12;
        int64_t r13;
        int64_t r14;
        int64_t r15;
        int64_t rip; //2*7c

        uint64_t u2[32];
        
        uint8_t fp[512]; // fp @2*100 .. 150 (+ more??)

        uint64_t u3[26];
    };
} PACKED kdd_regs_x86_64;

typedef union {
    kdd_regs_x86_32 r32;
    kdd_regs_x86_64 r64;
} PACKED kdd_regs;

/* System registers */
typedef struct {
    uint32_t cr0;
    uint32_t cr2;
    uint32_t cr3;
    uint32_t cr4;
    uint32_t dr0;
    uint32_t dr1;
    uint32_t dr2;
    uint32_t dr3;
    uint32_t dr6;
    uint32_t dr7;
    uint16_t gdt_pad;
    uint16_t gdt_limit;
    uint32_t gdt_base;
    uint16_t idt_pad;
    uint16_t idt_limit;
    uint32_t idt_base;
    uint16_t tss_sel;
    uint16_t ldt_sel;
    uint8_t u1[24];
} PACKED kdd_ctrl_x86_32;

typedef struct {
    uint64_t cr0;
    uint64_t cr2;
    uint64_t cr3; 
    uint64_t cr4;
    uint64_t dr0;
    uint64_t dr1;
    uint64_t dr2;
    uint64_t dr3;
    uint64_t dr6;
    uint64_t dr7;   
    uint8_t  gdt_pad[6];
    uint16_t gdt_limit;
    uint64_t gdt_base;
    uint8_t  idt_pad[6];
    uint16_t idt_limit;
    uint64_t idt_base;
    uint16_t tss_sel;
    uint16_t ldt_sel;
    uint8_t u1[44];
    uint64_t cr8;
    uint8_t u2[40];
    uint64_t efer; // XXX find out where EFER actually goes
} PACKED kdd_ctrl_x86_64;

typedef union {
    kdd_ctrl_x86_32 c32;
    kdd_ctrl_x86_64 c64;
} kdd_ctrl;

/*****************************************************************************
 * Functions required from the emulator/hypervisor for the stub to work.
 */

typedef struct kdd_guest kdd_guest;

/* Init and teardown guest-specific state */
extern kdd_guest *kdd_guest_init(char *arg, FILE *log, int verbosity);
extern void kdd_guest_teardown(kdd_guest *g);
extern char *kdd_guest_identify(kdd_guest *g);

/* Halt and restart the running guest */
extern void kdd_halt(kdd_guest *g);
extern void kdd_run(kdd_guest *g);

/* How many CPUs are there? */
extern int kdd_count_cpus(kdd_guest *g);

/* Accessor for guest physical memory, returning bytes read/written */
extern uint32_t kdd_access_physical(kdd_guest *g, uint64_t addr, 
                                    uint32_t len, uint8_t *buf, int write);

/* Accessors for guest registers, returning 0 for success */
extern int kdd_get_regs(kdd_guest *g, int cpuid, kdd_regs *r, int w64);
extern int kdd_set_regs(kdd_guest *g, int cpuid, kdd_regs *r, int w64);

/* Accessors for guest control registers, returning 0 for success */
extern int kdd_get_ctrl(kdd_guest *g, int cpuid, kdd_ctrl *ctrl, int w64);
extern int kdd_set_ctrl(kdd_guest *g, int cpuid, kdd_ctrl *ctrl, int w64);

/* Accessors for guest MSRs, returning 0 for success */
extern int kdd_wrmsr(kdd_guest *g, int cpuid, uint32_t msr, uint64_t value);
extern int kdd_rdmsr(kdd_guest *g, int cpuid, uint32_t msr, uint64_t *value);


/*****************************************************************************
 * Logfile usefulness
 */

/* Verbosity:
 * 0: errors (default)
 * 1: operations
 * 2: packets
 * 3: _everything_ */

#define KDD_LOG_IF(_v, _s, _fmt, _a...) do {    \
        if ((_s)->verbosity >= (_v)) {          \
        fprintf((_s)->log, (_fmt), ##_a);       \
        (void) fflush((_s)->log);               \
    }                                           \
} while (0)

#define KDD_LOG(_s, _fmt, _a...) KDD_LOG_IF(1, (_s), (_fmt), ##_a)
#define KDD_DEBUG(_s, _fmt, _a...) KDD_LOG_IF(3, (_s), (_fmt), ##_a)

#endif /* _KDD_H_ */