1 /*
2 * kdd.c -- stub for debugging guest OSes with the windows kernel debugger.
3 *
4 * Tim Deegan <Tim.Deegan@citrix.com>
5 *
6 * Copyright (c) 2007-2010, Citrix Systems Inc.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <ctype.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <inttypes.h>
43 #include <netdb.h>
44 #include <stddef.h>
45
46 #include <sys/socket.h>
47 #include <sys/types.h>
48 #include <sys/select.h>
49
50 #include <netinet/in.h>
51 #include <netinet/tcp.h>
52
53 #include "kdd.h"
54
55 /*
56 * TODO: kdd_os is a type which is used to represent os array. Adding a
57 * variable here would result in adding a new field to each element in array.
58 * However, since most of the fields are part of the same struct that we are
59 * trying to read from memory, we have added kddl to this structure. If
60 * required, we can possibly separate the kddl value to someplace else
61 *
62 * We also use kddl of size uint32_t which is actually used to represent the
63 * offset from image base rather than actual address
64 */
65 /* Windows version details */
66 typedef struct {
67 uint32_t build;
68 int w64;
69 int mp;
70 const char *name;
71 uint64_t base; /* KernBase: start looking here */
72 uint32_t range; /* | and search an area this size */
73 uint32_t version; /* +-> NtBuildNumber */
74 uint32_t modules; /* +-> PsLoadedModuleList */
75 uint32_t prcbs; /* +-> KiProcessorBlock */
76 uint32_t kddl; /* +-> KdDebuggerList */
77 } kdd_os;
78
79 /* State of the debugger stub */
80 typedef struct {
81 union {
82 uint8_t txb[sizeof (kdd_pkt)]; /* Marshalling area for tx */
83 kdd_pkt txp; /* Also readable as a packet structure */
84 };
85 union {
86 uint8_t rxb[sizeof (kdd_pkt)]; /* Marshalling area for rx */
87 kdd_pkt rxp; /* Also readable as a packet structure */
88 };
89 unsigned int cur; /* Offset into rx where we'll put the next byte */
90 uint32_t next_id; /* ID of next packet we will send */
91 int running; /* Are the guest's processors active? */
92 int cpuid; /* Current selected CPU */
93 int fd; /* TCP socket for client comms */
94 FILE *log; /* For tracing output */
95 int verbosity; /* How much detail to trace */
96 kdd_guest *guest; /* Arch-specific state for guest control */
97 kdd_os os; /* OS-specific magic numbers */
98 } kdd_state;
99
100 /**
101 * @brief Structure to represent DBGKD_GET_VERSION64
102 *
103 * reference: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdbgexts/ns-wdbgexts-_dbgkd_get_version64
104 */
105 typedef struct {
106 uint16_t MajorVersion; /* usually 0xf for free build */
107 uint16_t MinorVersion; /* build number of target OS */
108 uint8_t ProtocolVersion; /* version of the debugger protocol */
109 uint8_t KdSecondaryVersion; /* secondary version number */
110 uint16_t Flags; /* set of bit flags for the current debugging session */
111 uint16_t MachineType; /* type of the target's processor */
112 uint8_t MaxPacketType; /* one plus the highest number for a debugger */
113 /* packet type recognized by the target */
114 uint8_t MaxStateChagne; /* one plus the highest number for a state */
115 /* change generated by the target */
116 uint8_t MaxManipulate; /* one more that the highest number, recognized */
117 /* by the target, for a command to manipulate the target */
118 uint8_t Simulation; /* indication if target is in simulated execution */
119 uint16_t Unused[1];
120 uint64_t KernBase; /* base address of the kernel image */
121 uint64_t PsLoadedModuleList; /* value of the kernel variable */
122 /* PsLoadedModuleList */
123 uint64_t DebuggerDataList; /* value of the kernel variable */
124 /* KdDebuggerDataBlock */
125 } PACKED DBGKD_GET_VERSION64;
126
127 /**
128 * @brief Structure to represent the section in PE headers
129 *
130 * reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
131 */
132 typedef struct {
133 uint8_t Name[8]; /* name of section */
134 uint32_t VirtualSize; /* total size of section in memory */
135 uint32_t VirtualAddr; /* offset from image base */
136 uint32_t SizeOfRawData; /* size of section in for object files */
137 uint32_t PointerToRawData; /* file pointer to first page in COFF */
138 uint32_t PointerToRelocations; /* file pointer to beginning of relocation entry */
139 uint32_t PointerToLinenumbers; /* file pointer to the beginning of line-number entries */
140 uint16_t NumberOfRelocations; /* number of relocation entries for the section */
141 uint16_t NumberOfLinenumbers; /* number of line-number entries for the section */
142 uint32_t Characteristics; /* flags that describe the characteristics of the section */
143 } PACKED PE_SECTION_ENTRY;
144
145 /**
146 * @brief Size of pointer on 64 machine
147 */
148 #define SIZE_PTR64 8
149
150 /**
151 * @brief Size of pointer on 32 machine
152 */
153 #define SIZE_PTR32 4
154
155
156 /*****************************************************************************
157 * PE and DOS Header related offsets
158 */
159
160 /**
161 * @brief Offset in DOS header to look for PE header
162 */
163 #define DOS_HDR_PE_OFF 0x3c
164
165 /**
166 * @brief Size of PE header offset field in DOS header
167 */
168 #define DOS_HDR_PE_SZ 4
169
170 /**
171 * @brief Offset of number of sections field in PE header
172 */
173 #define PE_NUM_SECTION_OFF 0x6
174
175 /**
176 * @brief Size of number of sections field in PE header
177 */
178 #define PE_NUM_SECTION_SZ 2
179
180 /**
181 * @brief Offset of optional header size field in PE header
182 */
183 #define PE_OPT_HDR_SZ_OFF 0x14
184
185 /**
186 * @brief Size of optional header size field in PE header
187 */
188 #define PE_OPT_HDR_SZ_SZ 2
189
190 /**
191 * @brief Size of PE header
192 */
193 #define PE_HDR_SZ 0x18
194
195 /**
196 * @brief MZ header
197 */
198 #define MZ_HEADER 0x5a4d
199
200 /**
201 * @brief Limit on the number of sections to look for while iterating through
202 * PE sections
203 */
204 #define NUM_SECT_LIMIT 100
205
206 /**
207 * @brief Major Version for the DBGKD_GET_VERSION64 structure
208 */
209 #define NT_MAJOR_VERSION 0xf
210
211 /*****************************************************************************
212 * Utility functions
213 */
214
215 /* Get the instruction pointer */
kdd_get_ip(kdd_state * s)216 static uint64_t kdd_get_ip(kdd_state *s)
217 {
218 kdd_regs r;
219 if (!s->os.w64 && kdd_get_regs(s->guest, s->cpuid, &r, 0) == 0)
220 return r.r32.eip;
221 else if (s->os.w64 && kdd_get_regs(s->guest, s->cpuid, &r, 1) == 0)
222 return r.r64.rip;
223 else
224 return -1ULL;
225 }
226
227 /* Turn write(2) into a proper blocking write. */
blocking_write(int fd,const void * buf,size_t count)228 static size_t blocking_write(int fd, const void *buf, size_t count)
229 {
230 size_t left = count;
231 ssize_t r;
232 while (left > 0 && ((r = write(fd, buf, left)) >= 0 || errno == EINTR)) {
233 buf += r;
234 left -= r;
235 }
236 return count - left;
237 }
238
239 /* Dump the contents of a complete serial packet into a log file. */
kdd_log_pkt(kdd_state * s,const char * name,kdd_pkt * p)240 static void kdd_log_pkt(kdd_state *s, const char *name, kdd_pkt *p)
241 {
242 uint32_t sum = 0;
243 unsigned int i, j;
244 uint8_t ascii[17] = {0};
245 FILE *f = s->log;
246
247 if (s->verbosity < 2)
248 return;
249
250 /* Re-check the checksum */
251 for (i = 0; i < p->h.len; i++)
252 sum += p->payload[i];
253
254 fprintf(f, "\n"
255 "%s: %s type 0x%4.4"PRIx16" len 0x%4.4"PRIx16
256 " id 0x%8.8"PRIx32" sum 0x%"PRIx32" (%s: 0x%"PRIx32")\n",
257 name,
258 p->h.dir == KDD_DIR_PKT ? "pkt" :
259 p->h.dir == KDD_DIR_ACK ? "ack" : "???",
260 (unsigned) p->h.type, p->h.len, p->h.id, p->h.sum,
261 sum == p->h.sum ? "OK" : "BAD", sum);
262
263 /* Hexdump the payload in "canonical" format*/
264 for (i = 0; i < p->h.len; i ++) {
265 if (i % 16 == 0) {
266 memset(ascii, 0, 17);
267 fprintf(f, "%8.8x ", i);
268 } else if (i % 8 == 0)
269 fprintf(f, " ");
270 fprintf(f, " %2.2x", p->payload[i]);
271 ascii[i % 16] = (isprint(((int)p->payload[i])) ? p->payload[i] : 0x2e);
272 if (i % 16 == 15)
273 fprintf(f, " |%s|\n", ascii);
274 }
275 if (i % 16 != 0) {
276 for (j = i % 16 ; j < 16; j++) {
277 fprintf(f, "%s", (j == 8) ? " " : " ");
278 }
279 fprintf(f, " |%s|\n%8.8x\n", ascii, i);
280 }
281
282 fprintf(f, "\n");
283 (void) fflush(f);
284 }
285
286
287 /*****************************************************************************
288 * Memory access: virtual addresses and syntactic sugar.
289 */
290
kdd_read_physical(kdd_state * s,uint64_t addr,uint32_t len,void * buf)291 static uint32_t kdd_read_physical(kdd_state *s, uint64_t addr,
292 uint32_t len, void *buf)
293 {
294 return kdd_access_physical(s->guest, addr, len, buf, 0);
295 }
296
kdd_write_physical(kdd_state * s,uint64_t addr,uint32_t len,void * buf)297 static uint32_t kdd_write_physical(kdd_state *s, uint64_t addr,
298 uint32_t len, void *buf)
299 {
300 return kdd_access_physical(s->guest, addr, len, buf, 1);
301 }
302
303
304 /* VA->PA conversion. Returns -1ULL for failure. */
v2p(kdd_state * s,int cpuid,uint64_t va)305 static uint64_t v2p(kdd_state *s, int cpuid, uint64_t va)
306 {
307 int pg, pae, pse, lma;
308 int levels, width, bits, shift, offset, i;
309 uint64_t efer, entry = 0, mask, pa;
310 kdd_ctrl ctrl;
311
312 if (kdd_get_ctrl(s->guest, cpuid, &ctrl, s->os.w64) != 0
313 || kdd_rdmsr(s->guest, cpuid, 0xc0000080, &efer) != 0)
314 return -1ULL;
315
316 if (s->os.w64) {
317 pg = !!(ctrl.c64.cr0 & 0x80000000);
318 lma = !!(efer & 0x00000400);
319 pae = !!(ctrl.c64.cr4 & 0x00000020);
320 pse = !!(ctrl.c64.cr4 & 0x00000010) || pae || lma;
321 pa = ctrl.c64.cr3 & ~0x0fULL;
322 } else {
323 pg = !!(ctrl.c32.cr0 & 0x80000000);
324 pae = !!(ctrl.c32.cr4 & 0x00000020);
325 lma = 0;
326 pse = !!(ctrl.c32.cr4 & 0x00000010) || pae;
327 pa = ctrl.c32.cr3 & ~0x0fULL;
328 }
329 KDD_DEBUG(s, "w64 = %u, pg = %u, pae = %u, pse = %u, lma = %u\n",
330 s->os.w64, pg, pae, pse, lma);
331
332 /* Paging disabled? */
333 if (!pg)
334 return va;
335
336 /* 32/PAE64? */
337 if (lma) {
338 va &= (1ULL<<48) - 1;
339 width = 8; levels = 4; bits = 9;
340 } else {
341 va &= (1ULL<<32) - 1;
342 if (pae) {
343 width = 8; levels = 3; bits = 9;
344 } else {
345 width = 4; levels = 2; bits = 10;
346 }
347 }
348 KDD_DEBUG(s, "%i levels, va 0x%16.16"PRIx64"\n", levels, va);
349
350 /* Walk the appropriate number of levels */
351 for (i = levels; i > 0; i--) {
352 shift = KDD_PAGE_SHIFT + bits * (i-1);
353 mask = ((1ULL << bits) - 1) << shift;
354 offset = ((va & mask) >> shift) * width;
355 KDD_DEBUG(s, "level %i: mask 0x%16.16"PRIx64" pa 0x%16.16"PRIx64
356 " offset %i\n",i, mask, pa, offset);
357 if (kdd_read_physical(s, pa + offset, width, &entry) != width)
358 return -1ULL; // Bad entry PA
359 KDD_DEBUG(s, "level %i: entry 0x%16.16"PRIx64"\n", i, entry);
360 if (!(entry & 0x1))
361 return -1ULL; // Not present
362 pa = entry & 0x000ffffffffff000ULL;
363 if (pse && (i == 2) && (entry & 0x80)) { // Superpage
364 mask = ((1ULL << (KDD_PAGE_SHIFT + bits)) - 1);
365 return (pa & ~mask) + (va & mask);
366 }
367 }
368
369 return pa + (va & (KDD_PAGE_SIZE - 1));
370 }
371
kdd_access_virtual(kdd_state * s,int cpuid,uint64_t addr,uint32_t len,void * buf,int write)372 static uint32_t kdd_access_virtual(kdd_state *s, int cpuid, uint64_t addr,
373 uint32_t len, void *buf, int write)
374 {
375 uint64_t pa;
376 uint32_t chunk, rv, done = 0;
377
378 /* Process one page at a time */
379 while (len > 0) {
380 chunk = KDD_PAGE_SIZE - (addr & (KDD_PAGE_SIZE - 1));
381 if (chunk > len)
382 chunk = len;
383 pa = v2p(s, cpuid, addr);
384 KDD_DEBUG(s, "va 0x%"PRIx64" -> pa 0x%"PRIx64"\n", addr, pa);
385 if (pa == (uint64_t) -1ULL)
386 return done;
387 rv = kdd_access_physical(s->guest, pa, chunk, buf, write);
388 done += rv;
389 if (rv != chunk)
390 return done;
391 addr += chunk;
392 buf += chunk;
393 len -= chunk;
394 }
395 return done;
396 }
397
kdd_read_virtual(kdd_state * s,int cpuid,uint64_t addr,uint32_t len,void * buf)398 static uint32_t kdd_read_virtual(kdd_state *s, int cpuid, uint64_t addr,
399 uint32_t len, void *buf)
400 {
401 return kdd_access_virtual(s, cpuid, addr, len, buf, 0);
402 }
403
kdd_write_virtual(kdd_state * s,int cpuid,uint64_t addr,uint32_t len,void * buf)404 static uint32_t kdd_write_virtual(kdd_state *s, int cpuid, uint64_t addr,
405 uint32_t len, void *buf)
406 {
407 return kdd_access_virtual(s, cpuid, addr, len, buf, 1);
408 }
409
410
411 /*****************************************************************************
412 * Version information and related runes for different Windows flavours
413 */
414
415 static kdd_os os[] = {
416 /* Build 64 MP Name &Kernel search base Range +Version +Modules +PRCBs (64b) +KDDL */
417 {2195, 0, 0, "w2k sp4 x32 UP", 0xffffffff80400000ULL, 0x00000000, 0x0006d57c, 0x0006e1b8, 0x0, 0},
418 {2195, 0, 1, "w2k sp4 x32 SMP", 0xffffffff80400000ULL, 0x00000000, 0x0006fa1c, 0x00084520, 0x0, 0},
419 // PAE/UP, PAE/SMP
420
421 {2600, 0, 0, "xp sp2 x32 UP", 0xffffffff804d7000ULL, 0x00000000, 0x00075568, 0x00083b20, 0x0, 0},
422 {2600, 0, 1, "xp sp2 x32 SMP", 0xffffffff804d7000ULL, 0x00000000, 0x0007d0e8, 0x0008d4a0, 0x0, 0},
423 // PAE/UP, PAE/SMP
424
425 {2600, 0, 0, "xp sp3 x32 UP", 0xffffffff804d7000ULL, 0x00000000, 0x00075be8, 0x000841c0, 0x0, 0},
426 {2600, 0, 1, "xp sp3 x32 SMP", 0xffffffff804d7000ULL, 0x00000000, 0x0007c0e8, 0x0008c4c0, 0x0, 0},
427 {2600, 0, 0, "xp sp3 x32p UP", 0xffffffff804d7000ULL, 0x00000000, 0x0006e8e8, 0x0007cfc0, 0x0, 0},
428 {2600, 0, 1, "xp sp3 x32p SMP", 0xffffffff804d7000ULL, 0x00000000, 0x000760e8, 0x00086720, 0x0, 0},
429
430 {3790, 0, 0, "w2k3 sp2 x32 UP", 0xffffffff80800000ULL, 0x00000000, 0x00097128, 0x000a8e48, 0x0, 0},
431 {3790, 0, 1, "w2k3 sp2 x32 SMP", 0xffffffff80800000ULL, 0x00000000, 0x0009d128, 0x000af9c8, 0x0, 0},
432 {3790, 0, 0, "w2k3 sp2 x32p UP", 0xffffffff80800000ULL, 0x00000000, 0x0008e128, 0x0009ffa8, 0x0, 0},
433 {3790, 0, 1, "w2k3 sp2 x32p SMP", 0xffffffff80800000ULL, 0x00000000, 0x00094128, 0x000a6ea8, 0x0, 0},
434 {3790, 1, 0, "w2k3 sp2 x64 UP", 0xfffff80001000000ULL, 0x00000000, 0x001765d0, 0x0019aae0, 0x0017b100, 0},
435 {3790, 1, 1, "w2k3 sp2 x64 SMP", 0xfffff80001000000ULL, 0x00000000, 0x001b05e0, 0x001d5100, 0x001b5300, 0},
436
437 {6000, 0, 1, "vista sp0 x32p", 0xffffffff81800000ULL, 0x00000000, 0x000a4de4, 0x00111db0, 0x0, 0},
438 {6001, 0, 1, "vista sp1 x32p", 0xffffffff81000000ULL, 0x0f000000, 0x000af0c4, 0x00117c70, 0x0, 0},
439
440 {6001, 1, 1, "w2k8 sp0 x64", 0xfffff80001000000ULL, 0x0f000000, 0x00140bf0, 0x001c5db0, 0x00229640, 0},
441
442 {7600, 1, 1, "win7 sp0 x64", 0xfffff80001000000ULL, 0x0f000000, 0x001af770, 0x0023de50, 0x002a8900, 0},
443
444 {7601, 0, 1, "win7 sp1 x32p", 0xffffffff81800000ULL, 0x0f000000, 0x000524c4, 0x00149850, 0x0, 0},
445 {7601, 1, 1, "win7 sp1 x64", 0xfffff80001000000ULL, 0x0f000000, 0x001b2770, 0x00240e90, 0x002ab900, 0},
446 };
447
448 // 1381, 0, 0, "NT4 sp?", 0xffffffff80100000, ?, ?
449
450 static kdd_os unknown_os = {0, 0, 0, "unknown OS", 0, 0, 0, 0, 0, 0};
451
check_os(kdd_state * s)452 static int check_os(kdd_state *s)
453 {
454 kdd_os *v = &s->os;
455 uint64_t addr, val;
456 uint32_t width;
457 int i;
458
459 /* Kernel address must be a DOS executable */
460 val = 0;
461 if (kdd_read_virtual(s, 0, v->base, 2, &val) != 2 || val != 0x5a4d) {
462 KDD_DEBUG(s, "not %s: krnl 0x%"PRIx64"\n", v->name, val);
463 return 0;
464 }
465
466 /* OS version must match. */
467 val = 0;
468 if (kdd_read_virtual(s, 0, v->base + v->version, 4, &val) != 4
469 || val != (v->build | 0xf0000000) ) {
470 KDD_DEBUG(s, "not %s: version 0x%"PRIx64"\n", v->name, val);
471 return 0;
472 }
473
474 /* Module list address must be a circular linked list */
475 addr = v->base + v->modules;
476 val = 0;
477 width = v->w64 ? 8 : 4;
478 for (i = 0; val != v->base + v->modules && i < 250; i++) {
479 val = 0;
480 if (kdd_read_virtual(s, 0, addr, width, &val) != width) {
481 KDD_DEBUG(s, "not %s: bad module list\n", v->name);
482 return 0;
483 }
484 addr = val;
485 }
486
487 return 1;
488 }
489
490 /**
491 * @brief Parse the memory at \a filebase as a valid DOS header and get virtual
492 * address offset and size for any given section name (if it exists)
493 *
494 * @param s Pointer to the kdd_state structure
495 * @param filebase Base address of the file structure
496 * @param sectname Pointer to the section name c-string to look for
497 * @param vaddr Pointer to write the virtual address of section start to
498 * (if found)
499 * @param visze Pointer to write the section size to (if found)
500 *
501 * @return -1 on failure to find the section name
502 * @return 0 on success
503 */
get_pe64_sections(kdd_state * s,uint64_t filebase,const char * sectname,uint64_t * vaddr,uint32_t * vsize)504 static int get_pe64_sections(kdd_state *s, uint64_t filebase,
505 const char *sectname, uint64_t *vaddr, uint32_t *vsize)
506 {
507 uint64_t pe_hdr = 0;
508 uint64_t sect_start = 0;
509 uint16_t num_sections = 0;
510 uint16_t opt_hdr_sz = 0;
511 PE_SECTION_ENTRY pe_sect;
512
513 if (!s->os.w64)
514 return -1;
515
516 /* read PE header offset */
517 if (kdd_read_virtual(s, s->cpuid, filebase + DOS_HDR_PE_OFF, DOS_HDR_PE_SZ,
518 &pe_hdr) != DOS_HDR_PE_SZ)
519 return -1;
520
521 pe_hdr += filebase;
522
523 /* read number of sections */
524 if (kdd_read_virtual(s, s->cpuid, pe_hdr + PE_NUM_SECTION_OFF,
525 PE_NUM_SECTION_SZ, &num_sections) != PE_NUM_SECTION_SZ)
526 return -1;
527
528 /* read number of section upto a limit */
529 if (num_sections > NUM_SECT_LIMIT)
530 num_sections = NUM_SECT_LIMIT;
531
532 /* read size of optional header */
533 if (kdd_read_virtual(s, s->cpuid, pe_hdr + PE_OPT_HDR_SZ_OFF,
534 PE_OPT_HDR_SZ_SZ, &opt_hdr_sz) != PE_OPT_HDR_SZ_SZ)
535 return -1;
536
537 /* 0x18 is the size of PE header */
538 sect_start = pe_hdr + PE_HDR_SZ + opt_hdr_sz;
539
540 for (int i = 0; i < num_sections; i++) {
541 if (kdd_read_virtual(s, s->cpuid, sect_start + (i * sizeof(pe_sect)),
542 sizeof(pe_sect), &pe_sect) != sizeof(pe_sect))
543 return -1;
544
545 if (!strncmp(sectname, (char *)pe_sect.Name, sizeof(pe_sect.Name))) {
546 *vaddr = filebase + pe_sect.VirtualAddr;
547 *vsize = pe_sect.VirtualSize;
548 return 0;
549 }
550 }
551
552 return -1;
553 }
554
555 /**
556 * @brief Get the OS information like base address, minor version,
557 * PsLoadedModuleList and DebuggerDataList (basically the fields of
558 * DBGKD_GET_VERSION64 struture required to do handshake?).
559 *
560 * This is done by reading the IDT entry for divide-by-zero exception and
561 * searching back into the memory for DOS header (which is our kernel base).
562 * Once we have the kernel base, we parse the PE header and look for kernel
563 * base address in the .data section. Once we have possible values, we look for
564 * DBGKD_GET_VERSION64 block by using following heuristics on the address which
565 * has the kernel base:
566 *
567 * - at address [-0x10], it should have 0xf as the MajorVersion
568 * - at address [+0x8], it should have a valid kernel memory address pointing
569 * in .data
570 * - at address [+0x10], it should have a valid kernel memory address pointing
571 * in .data
572 *
573 * @param s Pointer to the kdd state
574 */
get_os_info_64(kdd_state * s)575 static void get_os_info_64(kdd_state *s)
576 {
577 kdd_ctrl ctrl;
578 int ret;
579 uint64_t buf;
580 uint64_t idt0_addr;
581 uint64_t base;
582 uint64_t caddr;
583 uint64_t data_base;
584 uint32_t data_size;
585 uint64_t modptr = 0;
586 uint64_t kddl = 0;
587 uint16_t minor = 0;
588 uint64_t dbgkd_addr;
589 DBGKD_GET_VERSION64 dbgkd_get_version64;
590 /* Maybe 1GB is too big for the limit to search? */
591 uint32_t search_limit = (1024 * 1024 * 1024) / KDD_PAGE_SIZE; /*1GB/PageSize*/
592 uint64_t efer;
593
594 /* if we are not in 64-bit mode, fail */
595 if (kdd_rdmsr(s->guest, s->cpuid, 0xc0000080, &efer) || !(efer & (1 << 8)))
596 goto fail;
597
598 s->os.w64 = 1;
599
600 /* get control registers for our os */
601 ret = kdd_get_ctrl(s->guest, s->cpuid, &ctrl, s->os.w64);
602 if (ret)
603 goto fail;
604
605 /* read the div-by-zero handler function address */
606 kdd_read_virtual(s, s->cpuid, ctrl.c64.idt_base + 8, 8, &buf);
607 idt0_addr = ((uint64_t)buf << 32) & 0xffffffff00000000;
608
609 kdd_read_virtual(s, s->cpuid, ctrl.c64.idt_base, 8, &buf);
610 idt0_addr |= ((buf >> 32) & 0xffff0000);
611 idt0_addr |= (buf & 0xffff);
612
613 KDD_LOG(s, "idt0 addr: 0x%"PRIx64"\n", idt0_addr);
614
615 /*
616 * get the page start and look for "MZ" file header - we limit the search
617 * in 1GB range above the current page base address
618 */
619
620 base = idt0_addr & ~(KDD_PAGE_SIZE - 1);
621
622 while (search_limit) {
623 uint16_t val;
624 if (kdd_read_virtual(s, s->cpuid, base, 2, &val) != 2) {
625 /* just move going back?? this is bad though */
626 KDD_LOG(s, "ran into unmapped region without finding PE header\n");
627 goto fail;
628 }
629
630 if (val == MZ_HEADER) // MZ
631 break;
632
633 base -= KDD_PAGE_SIZE;
634 search_limit -= 1;
635 }
636
637 KDD_LOG(s, "base: 0x%"PRIx64"\n", base);
638
639 /* found the data section start */
640 if (get_pe64_sections(s, base, ".data", &data_base, &data_size))
641 goto fail;
642
643 /* look for addresses which has kernel base written into it */
644 caddr = data_base;
645
646 search_limit = (1024 * 1024 * 512) / SIZE_PTR64;
647 while (caddr < data_base + data_size && search_limit) {
648 if (kdd_read_virtual(s, s->cpuid, caddr, SIZE_PTR64, &buf) !=
649 SIZE_PTR64)
650 goto fail; /* reached end and found nothing */
651
652 /* if we found base in the memory addresses */
653 if (buf == base) {
654 /* read the DBGKD_GET_VERSION64 struct */
655 dbgkd_addr = caddr - offsetof(DBGKD_GET_VERSION64, KernBase);
656 if (kdd_read_virtual(s, s->cpuid, dbgkd_addr,
657 sizeof(DBGKD_GET_VERSION64), &dbgkd_get_version64) ==
658 sizeof(DBGKD_GET_VERSION64)) {
659 /* check if major version is 0xf */
660 if (dbgkd_get_version64.MajorVersion == NT_MAJOR_VERSION) {
661
662 /* read minor version, PsLoadedModuleList pointer and
663 * DebuggerDataList
664 */
665 modptr = dbgkd_get_version64.PsLoadedModuleList;
666 kddl = dbgkd_get_version64.DebuggerDataList;
667 minor = dbgkd_get_version64.MinorVersion;
668
669 /* do heuristic check */
670 if (modptr && kddl && modptr != kddl && kddl != base &&
671 base != modptr && modptr >= data_base &&
672 modptr < (data_base + data_size) &&
673 kddl >= data_base &&
674 kddl < (data_base + data_size))
675 break;
676 }
677 }
678
679 }
680
681 caddr += SIZE_PTR64;
682 search_limit -= 1;
683 }
684
685 if (caddr < data_base + data_size) {
686 /* if found, set the field and return */
687
688 KDD_LOG(s, "base: 0x%"PRIx64"\n", base);
689 KDD_LOG(s, "modules list: 0x%"PRIx64"\n", modptr);
690 KDD_LOG(s, "kddl: 0x%"PRIx64"\n", kddl);
691 KDD_LOG(s, "minor version: 0x%hx\n", minor);
692
693 s->os.base = base;
694 s->os.modules = modptr - base;
695 s->os.kddl = kddl - base;
696 s->os.build = (uint32_t) minor;
697 return;
698 }
699
700 fail:
701 s->os = unknown_os;
702 }
703
704 /* Figure out what OS we're dealing with */
find_os(kdd_state * s)705 static void find_os(kdd_state *s)
706 {
707 int i;
708 uint64_t limit;
709
710 /* We may already have the right one */
711 if (check_os(s))
712 return;
713
714 /* Try each OS we know about */
715 for (i = 0; i < (sizeof os / sizeof os[0]); i++) {
716 s->os = os[i];
717 /* Try each page in the potential range of kernel load addresses */
718 for (limit = s->os.base + s->os.range;
719 s->os.base <= limit;
720 s->os.base += KDD_PAGE_SIZE)
721 if (check_os(s))
722 return;
723 }
724
725 get_os_info_64(s);
726 }
727
728
729 /*****************************************************************************
730 * How to send packets and acks.
731 */
732
733
734 /* Send a serial packet */
kdd_tx(kdd_state * s)735 static void kdd_tx(kdd_state *s)
736 {
737 uint32_t sum = 0;
738 size_t len;
739 int i;
740
741 /* Fix up the checksum before we send */
742 for (i = 0; i < s->txp.h.len; i++)
743 sum += s->txp.payload[i];
744 s->txp.h.sum = sum;
745
746 kdd_log_pkt(s, "TX", &s->txp);
747
748 len = s->txp.h.len + sizeof (kdd_hdr);
749 if (s->txp.h.dir == KDD_DIR_PKT)
750 /* Append the mysterious 0xaa byte to each packet */
751 s->txb[len++] = 0xaa;
752
753 (void) blocking_write(s->fd, s->txb, len);
754 }
755
756
757 /* Send an acknowledgement to the client */
kdd_send_ack(kdd_state * s,uint32_t id,uint16_t type)758 static void kdd_send_ack(kdd_state *s, uint32_t id, uint16_t type)
759 {
760 s->txp.h.dir = KDD_DIR_ACK;
761 s->txp.h.type = type;
762 s->txp.h.len = 0;
763 s->txp.h.id = id;
764 s->txp.h.sum = 0;
765 kdd_tx(s);
766 }
767
768 /* Send a command_packet to the client */
kdd_send_cmd(kdd_state * s,uint32_t subtype,size_t extra)769 static void kdd_send_cmd(kdd_state *s, uint32_t subtype, size_t extra)
770 {
771 s->txp.h.dir = KDD_DIR_PKT;
772 s->txp.h.type = KDD_PKT_CMD;
773 s->txp.h.len = sizeof (kdd_cmd) + extra;
774 s->txp.h.id = (s->next_id ^= 1);
775 s->txp.h.sum = 0;
776 s->txp.cmd.subtype = subtype;
777 kdd_tx(s);
778 }
779
780 /* Cause the client to print a string */
kdd_send_string(kdd_state * s,const char * fmt,...)781 static void kdd_send_string(kdd_state *s, const char *fmt, ...)
782 {
783 uint32_t len = 0xffff - sizeof (kdd_msg);
784 char *buf = (char *) s->txb + sizeof (kdd_hdr) + sizeof (kdd_msg);
785 va_list ap;
786
787 va_start(ap, fmt);
788 len = vsnprintf(buf, len, fmt, ap);
789 va_end(ap);
790
791 s->txp.h.dir = KDD_DIR_PKT;
792 s->txp.h.type = KDD_PKT_MSG;
793 s->txp.h.len = sizeof (kdd_msg) + len;
794 s->txp.h.id = (s->next_id ^= 1);
795 s->txp.h.sum = 0;
796 s->txp.msg.subtype = KDD_MSG_PRINT;
797 s->txp.msg.length = len;
798 kdd_tx(s);
799 }
800
801
802 /* Stop the guest and prepare for debugging */
kdd_break(kdd_state * s)803 static void kdd_break(kdd_state *s)
804 {
805 uint16_t ilen;
806 KDD_LOG(s, "Break\n");
807
808 if (s->running)
809 kdd_halt(s->guest);
810 s->running = 0;
811
812 {
813 unsigned int i;
814 /* XXX debug pattern */
815 for (i = 0; i < 0x100 ; i++)
816 s->txb[sizeof (kdd_hdr) + i] = i;
817 }
818
819 /* Send a state-change message to the client so it knows we've stopped */
820 s->txp.h.dir = KDD_DIR_PKT;
821 s->txp.h.type = KDD_PKT_STC;
822 s->txp.h.len = sizeof (kdd_stc);
823 s->txp.h.id = (s->next_id ^= 1);
824 s->txp.stc.subtype = KDD_STC_STOP;
825 s->txp.stc.stop.cpu = s->cpuid;
826 s->txp.stc.stop.ncpus = kdd_count_cpus(s->guest);
827 s->txp.stc.stop.kthread = 0; /* Let the debugger figure it out */
828 s->txp.stc.stop.status = KDD_STC_STATUS_BREAKPOINT;
829 s->txp.stc.stop.rip1 = s->txp.stc.stop.rip2 = kdd_get_ip(s);
830 s->txp.stc.stop.nparams = 0;
831 s->txp.stc.stop.first_chance = 1;
832 ilen = kdd_read_virtual(s, s->cpuid, s->txp.stc.stop.rip1,
833 sizeof s->txp.stc.stop.inst, s->txp.stc.stop.inst);
834 s->txp.stc.stop.ilen = ilen;
835 /* XXX other fields */
836
837 kdd_tx(s);
838 }
839
840 /* Handle an acknowledgement received from the client */
kdd_handle_ack(kdd_state * s,uint32_t id,uint16_t type)841 static void kdd_handle_ack(kdd_state *s, uint32_t id, uint16_t type)
842 {
843 switch (type) {
844 case KDD_ACK_OK:
845 case KDD_ACK_BAD:
846 break;
847 case KDD_ACK_RST:
848 if (id == 0) {
849 KDD_LOG(s, "Client requests a reset\n");
850 kdd_send_ack(s, 0xdeadbeef, KDD_ACK_RST);
851 kdd_send_string(s, "[kdd: connected to %s]\r\n",
852 kdd_guest_identify(s->guest));
853 kdd_break(s);
854 }
855 break;
856 default:
857 KDD_LOG(s, "Unhandled ACK type 0x%4.4x\n", type);
858 break;
859 }
860 }
861
862 /*****************************************************************************
863 * Handlers for each kind of client packet
864 */
865
866
867 /* Handle the initial handshake */
kdd_handle_handshake(kdd_state * s)868 static void kdd_handle_handshake(kdd_state *s)
869 {
870 /* Figure out what we're looking at */
871 find_os(s);
872
873 kdd_send_string(s, "[kdd: %s @0x%"PRIx64"]\r\n", s->os.name, s->os.base);
874
875 /* Respond with some details about the debugger stub we simulate */
876 s->txp.cmd.shake.u1 = 0x01010101;
877 s->txp.cmd.shake.status = KDD_STATUS_SUCCESS;
878 s->txp.cmd.shake.u2 = 0x02020202;
879 s->txp.cmd.shake.v_major = NT_MAJOR_VERSION;
880 s->txp.cmd.shake.v_minor = s->os.build;
881 s->txp.cmd.shake.proto = 6;
882 s->txp.cmd.shake.flags = (0x02 /* ??? */
883 | (s->os.mp ? KDD_FLAGS_MP : 0)
884 | (s->os.w64 ? KDD_FLAGS_64 : 0));
885 s->txp.cmd.shake.machine = s->os.w64 ? KDD_MACH_x64 : KDD_MACH_x32;
886 s->txp.cmd.shake.pkts = KDD_PKT_MAX;
887 s->txp.cmd.shake.states = 0xc; /* ??? */
888 s->txp.cmd.shake.manips = 0x2e; /* ??? */
889 s->txp.cmd.shake.u3[0] = 0x33;
890 s->txp.cmd.shake.u3[1] = 0x44;
891 s->txp.cmd.shake.u3[2] = 0x55;
892 s->txp.cmd.shake.kern_addr = s->os.base;
893 s->txp.cmd.shake.mods_addr = s->os.base + s->os.modules;
894 s->txp.cmd.shake.data_addr = s->os.kddl ? s->os.base + s->os.kddl : 0;
895
896 KDD_LOG(s, "Client initial handshake: %s\n", s->os.name);
897 kdd_send_cmd(s, KDD_CMD_SHAKE, 0);
898 }
899
900 /* Handle set-cpu command */
kdd_handle_setcpu(kdd_state * s)901 static void kdd_handle_setcpu(kdd_state *s)
902 {
903 KDD_LOG(s, "Switch to CPU %u\n", s->rxp.cmd.setcpu.cpu);
904
905 /* This command doesn't get a direct response; instead we send a STOP. */
906 s->cpuid = s->rxp.cmd.setcpu.cpu;
907 kdd_break(s);
908
909 /* XXX find out whether kd will be happier if we respond to this command after the break. */
910 }
911
912 /* Handle breakpoint commands */
kdd_handle_soft_breakpoint(kdd_state * s)913 static void kdd_handle_soft_breakpoint(kdd_state *s)
914 {
915 KDD_LOG(s, "Soft breakpoint %#"PRIx32" op %#"PRIx32"/%#"PRIx32"\n",
916 s->rxp.cmd.sbp.bp, s->rxp.cmd.sbp.u1, s->rxp.cmd.sbp.u2);
917
918 /* Pretend we did something */
919 s->txp.cmd.sbp.u1 = s->rxp.cmd.sbp.u1;
920 s->txp.cmd.sbp.status = KDD_STATUS_SUCCESS;
921 s->txp.cmd.sbp.u2 = s->rxp.cmd.sbp.u2;
922 s->txp.cmd.sbp.bp = s->rxp.cmd.sbp.bp;
923 kdd_send_cmd(s, KDD_CMD_SOFT_BP, 0);
924 }
925
kdd_handle_hard_breakpoint(kdd_state * s)926 static void kdd_handle_hard_breakpoint(kdd_state *s)
927 {
928 KDD_LOG(s, "Hard breakpoint @%#"PRIx64"\n", s->rxp.cmd.hbp.address);
929
930 kdd_send_string(s, "[kdd: breakpoints aren't implemented yet]\r\n");
931
932 s->txp.cmd.hbp.status = KDD_STATUS_FAILURE;
933 s->txp.cmd.hbp.address = s->rxp.cmd.hbp.address;
934 kdd_send_cmd(s, KDD_CMD_HARD_BP, 0);
935 }
936
937 /* Register access */
kdd_handle_read_regs(kdd_state * s)938 static void kdd_handle_read_regs(kdd_state *s)
939 {
940 kdd_regs regs;
941 uint32_t len = s->os.w64 ? sizeof regs.r64 : sizeof regs.r32;
942 int cpuid = s->rxp.cmd.regs.cpu;
943
944 KDD_LOG(s, "Read CPU %i register state\n", cpuid);
945 if (kdd_get_regs(s->guest, cpuid, ®s, s->os.w64) == 0) {
946 memcpy(s->txb + sizeof (kdd_hdr) + sizeof (kdd_cmd), ®s, len);
947 s->txp.cmd.regs.status = KDD_STATUS_SUCCESS;
948 } else {
949 len = 0;
950 s->txp.cmd.regs.status = KDD_STATUS_FAILURE;
951 }
952 s->txp.cmd.regs.cpu = cpuid;
953 kdd_send_cmd(s, KDD_CMD_READ_REGS, len);
954 }
955
kdd_handle_write_regs(kdd_state * s)956 static void kdd_handle_write_regs(kdd_state *s)
957 {
958 kdd_regs regs;
959 uint32_t len = s->rxp.h.len - sizeof (kdd_cmd);
960 uint32_t regsz = s->os.w64 ? sizeof regs.r64 : sizeof regs.r32;
961 int cpuid = s->rxp.cmd.regs.cpu;
962
963 KDD_LOG(s, "Write CPU %i register state\n", cpuid);
964 s->txp.cmd.regs.status = KDD_STATUS_FAILURE;
965 if (len >= regsz) {
966 memcpy(®s, s->rxb + sizeof (kdd_hdr) + sizeof (kdd_cmd), regsz);
967 if (kdd_set_regs(s->guest, cpuid, ®s, s->os.w64) == 0)
968 s->txp.cmd.regs.status = KDD_STATUS_SUCCESS;
969 }
970 s->txp.cmd.regs.cpu = cpuid;
971 kdd_send_cmd(s, KDD_CMD_WRITE_REGS, 0);
972 }
973
974 /* Report control state to the guest */
kdd_handle_read_ctrl(kdd_state * s)975 static void kdd_handle_read_ctrl(kdd_state *s)
976 {
977 int i;
978 kdd_ctrl ctrl;
979 uint8_t *buf = s->txb + sizeof (kdd_hdr) + sizeof (kdd_cmd);
980 uint32_t len = s->rxp.cmd.mem.length_req;
981 uint64_t val, addr = s->rxp.cmd.mem.addr;
982 KDD_LOG(s, "Read control state: %"PRIu32" bytes @ 0x%"PRIx64"\n",
983 len, addr);
984
985 if (len > (65536 - sizeof(kdd_cmd)))
986 len = 65536 - sizeof(kdd_cmd);
987
988 /* Default contents: a debug-friendly pattern */
989 for (i = 0; i < len; i++)
990 ((uint8_t*)buf)[i] = (uint8_t) (addr + i);
991
992 if (kdd_get_ctrl(s->guest, s->cpuid, &ctrl, s->os.w64)) {
993 len = 0;
994 } else if (s->os.w64) {
995 /* Annoyingly, 64-bit kd relies on the kernel to point it at
996 * datastructures it could easily find itself with VA reads. */
997 switch (addr) {
998 case 0x0: /* KPCR */
999 case 0x1: /* KPRCB */
1000 case 0x3: /* KTHREAD */
1001 /* First find the PCRB's address */
1002 len = kdd_read_virtual(s, s->cpuid,
1003 s->os.base + s->os.prcbs + 8 * s->cpuid,
1004 8, &val);
1005 if (len != 8)
1006 break;
1007 /* The PCR lives 0x180 bytes before the PRCB */
1008 if (addr == 0)
1009 val -= 0x180;
1010 /* The current thread's address is at offset 0x8 into the PRCB. */
1011 else if (addr == 3)
1012 len = kdd_read_virtual(s, s->cpuid, val + 8, 8, &val);
1013 *(uint64_t *)buf = val;
1014 break;
1015 case 0x2: /* Control registers */
1016 if (len > sizeof ctrl.c64)
1017 len = sizeof ctrl.c64;
1018 memcpy(buf, (uint8_t *)&ctrl, len);
1019 break;
1020 default:
1021 KDD_LOG(s, "Unknown control space 0x%"PRIx64"\n", addr);
1022 len = 0;
1023 }
1024 } else {
1025 /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
1026 uint32_t offset = addr - 0xcc;
1027 if (offset > sizeof ctrl.c32)
1028 offset -= 0x2cc;
1029 if (offset > sizeof ctrl.c32 || len > sizeof ctrl.c32 - offset) {
1030 KDD_LOG(s, "Request outside of known control space\n");
1031 len = 0;
1032 } else {
1033 memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
1034 }
1035 }
1036
1037 s->txp.cmd.mem.addr = addr;
1038 s->txp.cmd.mem.length_req = s->rxp.cmd.mem.length_req;
1039 s->txp.cmd.mem.length_rsp = len;
1040 s->txp.cmd.mem.status = ((len) ? KDD_STATUS_SUCCESS : KDD_STATUS_FAILURE);
1041 kdd_send_cmd(s, KDD_CMD_READ_CTRL, len);
1042 }
1043
1044 /* MSR access */
kdd_handle_read_msr(kdd_state * s)1045 static void kdd_handle_read_msr(kdd_state *s)
1046 {
1047 uint32_t msr = s->rxp.cmd.msr.msr;
1048 uint64_t val;
1049 int ok;
1050 KDD_LOG(s, "Read MSR 0x%"PRIx32"\n", msr);
1051
1052 ok = (kdd_rdmsr(s->guest, s->cpuid, msr, &val) == 0);
1053 s->txp.cmd.msr.msr = msr;
1054 s->txp.cmd.msr.val = val;
1055 s->txp.cmd.msr.status = (ok ? KDD_STATUS_SUCCESS : KDD_STATUS_FAILURE);
1056 kdd_send_cmd(s, KDD_CMD_READ_MSR, 0);
1057 }
1058
kdd_handle_write_msr(kdd_state * s)1059 static void kdd_handle_write_msr(kdd_state *s)
1060 {
1061 uint32_t msr = s->rxp.cmd.msr.msr;
1062 uint64_t val = s->rxp.cmd.msr.val;
1063 int ok;
1064 KDD_LOG(s, "Write MSR 0x%"PRIx32" = 0x%"PRIx64"\n", msr, val);
1065
1066 ok = (kdd_wrmsr(s->guest, s->cpuid, msr, val) == 0);
1067 s->txp.cmd.msr.msr = msr;
1068 s->txp.cmd.msr.status = (ok ? KDD_STATUS_SUCCESS : KDD_STATUS_FAILURE);
1069 kdd_send_cmd(s, KDD_CMD_WRITE_MSR, 0);
1070 }
1071
1072 /* Read and write guest memory */
kdd_handle_memory_access(kdd_state * s)1073 static void kdd_handle_memory_access(kdd_state *s)
1074 {
1075 uint32_t len = s->rxp.cmd.mem.length_req;
1076 uint64_t addr = s->rxp.cmd.mem.addr;
1077 uint8_t *buf;
1078
1079 KDD_LOG(s, "Memory access \"%c%c\" (%s): %"PRIu32" bytes"
1080 " @ 0x%"PRIx64"\n",
1081 s->rxp.cmd.subtype & 0xff, (s->rxp.cmd.subtype >>8) & 0xff,
1082 s->rxp.cmd.subtype == KDD_CMD_READ_VA ? "read virt" :
1083 s->rxp.cmd.subtype == KDD_CMD_WRITE_VA ? "write virt" :
1084 s->rxp.cmd.subtype == KDD_CMD_READ_PA ? "read phys" :
1085 s->rxp.cmd.subtype == KDD_CMD_WRITE_PA ? "write phys" : "unknown",
1086 len, addr);
1087
1088 if (len > (65536 - sizeof(kdd_cmd)))
1089 len = 65536 - sizeof(kdd_cmd);
1090
1091 switch(s->rxp.cmd.subtype) {
1092 case KDD_CMD_READ_VA:
1093 buf = s->txb + sizeof (kdd_hdr) + sizeof (kdd_cmd);
1094 len = kdd_read_virtual(s, s->cpuid, addr, len, buf);
1095 break;
1096 case KDD_CMD_WRITE_VA:
1097 buf = s->rxb + sizeof (kdd_hdr) + sizeof (kdd_cmd);
1098 len = kdd_write_virtual(s, s->cpuid, addr, len, buf);
1099 break;
1100 case KDD_CMD_READ_PA:
1101 buf = s->txb + sizeof (kdd_hdr) + sizeof (kdd_cmd);
1102 len = kdd_read_physical(s, addr, len, buf);
1103 break;
1104 case KDD_CMD_WRITE_PA:
1105 buf = s->rxb + sizeof (kdd_hdr) + sizeof (kdd_cmd);
1106 len = kdd_write_physical(s, addr, len, buf);
1107 break;
1108 }
1109 KDD_DEBUG(s, "access returned %"PRIu32"\n", len);
1110
1111 s->txp.cmd.mem.addr = addr;
1112 s->txp.cmd.mem.length_req = s->rxp.cmd.mem.length_req;
1113 s->txp.cmd.mem.length_rsp = len;
1114 s->txp.cmd.mem.status = (len) ? KDD_STATUS_SUCCESS : KDD_STATUS_FAILURE;
1115 kdd_send_cmd(s, s->rxp.cmd.subtype, len);
1116 }
1117
1118
1119 /* Handle a packet received from the client */
kdd_handle_pkt(kdd_state * s,kdd_pkt * p)1120 static void kdd_handle_pkt(kdd_state *s, kdd_pkt *p)
1121 {
1122 uint32_t sum = 0;
1123 int i;
1124
1125 /* Simple checksum: add all the bytes */
1126 for (i = 0; i < p->h.len; i++)
1127 sum += p->payload[i];
1128 if (p->h.sum != sum) {
1129 kdd_send_ack(s, p->h.id, KDD_ACK_BAD);
1130 return;
1131 }
1132
1133 /* We only understand one kind of packet from the client */
1134 if (p->h.type != KDD_PKT_CMD) {
1135 KDD_LOG(s, "Unhandled PKT type 0x%4.4x\n", p->h.type);
1136 kdd_send_ack(s, p->h.id, KDD_ACK_BAD);
1137 return;
1138 }
1139
1140 /* Ack the packet */
1141 kdd_send_ack(s, p->h.id, KDD_ACK_OK);
1142
1143 /* Clear the TX buffer just for sanity */
1144 memset(s->txb, 0, sizeof(s->txb));
1145
1146 switch (p->cmd.subtype) {
1147 case KDD_CMD_CONT1:
1148 case KDD_CMD_CONT2:
1149 KDD_LOG(s, "Continue: 0x%8.8"PRIx32"\n", p->cmd.cont.reason1);
1150 if (!s->running)
1151 kdd_run(s->guest);
1152 s->running = 1;
1153 /* No reply, just carry on running */
1154 break;
1155 case KDD_CMD_SHAKE:
1156 kdd_handle_handshake(s);
1157 break;
1158 case KDD_CMD_SOFT_BP:
1159 kdd_handle_soft_breakpoint(s);
1160 break;
1161 case KDD_CMD_HARD_BP:
1162 kdd_handle_hard_breakpoint(s);
1163 break;
1164 case KDD_CMD_READ_REGS:
1165 kdd_handle_read_regs(s);
1166 break;
1167 case KDD_CMD_WRITE_REGS:
1168 kdd_handle_write_regs(s);
1169 break;
1170 case KDD_CMD_READ_CTRL:
1171 kdd_handle_read_ctrl(s);
1172 break;
1173 case KDD_CMD_READ_MSR:
1174 kdd_handle_read_msr(s);
1175 break;
1176 case KDD_CMD_WRITE_MSR:
1177 kdd_handle_write_msr(s);
1178 break;
1179 case KDD_CMD_READ_VA:
1180 case KDD_CMD_WRITE_VA:
1181 case KDD_CMD_READ_PA:
1182 case KDD_CMD_WRITE_PA:
1183 kdd_handle_memory_access(s);
1184 break;
1185 case KDD_CMD_WRITE_Z:
1186 /* No response */
1187 break;
1188 case KDD_CMD_SETCPU:
1189 kdd_handle_setcpu(s);
1190 break;
1191 case KDD_CMD_WRITE_CTRL:
1192 default:
1193 KDD_LOG(s, "Unhandled CMD subtype 0x%8.8x\n", p->cmd.subtype);
1194 /* Send back a mirror of the request saying we failed to do
1195 * whatever it was. */
1196 memcpy(s->txb, p, sizeof (kdd_hdr) + sizeof (kdd_cmd));
1197 s->txp.h.len = sizeof (kdd_cmd);
1198 s->txp.cmd.mem.status = KDD_STATUS_FAILURE;
1199 s->txp.h.id = (s->next_id ^= 1);
1200 kdd_tx(s);
1201 break;
1202 }
1203 }
1204
1205
1206 /*****************************************************************************
1207 * Scaffolding to get packets from the client.
1208 */
1209
1210
1211 /* Set up the debugger state ready for use. Returns a file descriptor and
1212 * a state pointer for use in select() loops. */
kdd_init(kdd_state ** sp,struct addrinfo * addr,kdd_guest * guest,FILE * log,int verbosity)1213 static int kdd_init(kdd_state **sp, struct addrinfo *addr,
1214 kdd_guest *guest, FILE *log, int verbosity)
1215 {
1216 kdd_state *s = NULL;
1217 int opt, fd = -1;
1218
1219 s = malloc(sizeof *s);
1220 if (s == NULL) {
1221 fprintf(stderr, "Could not allocate state for kdd: %s\n",
1222 strerror(errno));
1223 goto fail;
1224 }
1225 memset(s, 0, sizeof *s);
1226 s->log = log;
1227 s->verbosity = verbosity;
1228
1229 fd = socket(PF_INET, SOCK_STREAM, 0);
1230 if (fd < 0) {
1231 KDD_LOG(s, "Could not open a socket for kdd: %s\n",
1232 strerror(errno));
1233 goto fail;
1234 }
1235
1236 /* Try to connect to the tcp/serial gateway. */
1237 again:
1238 if (connect(fd, addr->ai_addr, sizeof *addr) != 0) {
1239 if (errno == EINTR)
1240 goto again;
1241 if (addr->ai_next) {
1242 addr = addr->ai_next;
1243 goto again;
1244 }
1245 KDD_LOG(s, "Could not connect TCP stream for kdd: %s\n",
1246 strerror(errno));
1247 goto fail;
1248 }
1249
1250 opt = 1;
1251 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
1252
1253 s->next_id = 0x80800001;
1254 s->fd = fd;
1255 s->running = 1;
1256 s->cpuid = 0;
1257 s->guest = guest;
1258 s->os = unknown_os;
1259
1260 *sp = s;
1261 KDD_LOG(s, "KDD starts\n");
1262
1263 kdd_break(s);
1264
1265 return fd;
1266
1267 fail:
1268 if (fd >= 0)
1269 close(fd);
1270 free(s);
1271 return -1;
1272 }
1273
1274 /* Callback when the fd is readable, to parse packet data from the byte
1275 * stream. When a complete packet is seen, handle it. The packet can
1276 * then be read in the marshalling buffer, but only until the next call
1277 * to kdd_parse_byte(). */
kdd_select_callback(kdd_state * s)1278 void kdd_select_callback(kdd_state *s)
1279 {
1280 kdd_pkt *p = &s->rxp;
1281 unsigned int pkt_len = (unsigned) -1;
1282 ssize_t rc, to_read;
1283
1284 /* For easy parsing, read single bytes until we can check the packet
1285 * length, then read in one go to the end. */
1286 if (s->cur < 8
1287 || (p->h.dir != KDD_DIR_PKT && p->h.dir != KDD_DIR_ACK))
1288 to_read = 1;
1289 else {
1290 /* Extract payload length from the header */
1291 pkt_len = p->h.len + sizeof (kdd_hdr);
1292
1293 /* For some reason, packets always have a trailing 0xAA byte */
1294 if (p->h.dir == KDD_DIR_PKT)
1295 pkt_len++;
1296
1297 to_read = pkt_len - s->cur;
1298 }
1299
1300 rc = read(s->fd, s->rxb + s->cur, to_read);
1301
1302 KDD_DEBUG(s, "read(%i) returns %i\n", (int) to_read, (int) rc);
1303
1304 if (rc <= 0)
1305 /* XXX ignoring failures for now */
1306 return;
1307
1308 /* Break command comes as a single byte */
1309 if (s->cur == 0 && s->rxb[0] == 'b') {
1310 kdd_break(s);
1311 return;
1312 }
1313
1314 /* Remember the bytes we just read */
1315 s->cur += rc;
1316
1317 /* Sync to packet start, which will be "0000" or "iiii" */
1318 if (s->cur < 4)
1319 return;
1320 if (p->h.dir != KDD_DIR_PKT && p->h.dir != KDD_DIR_ACK) {
1321 KDD_LOG(s, "Bad hdr 0x%8.8x: resyncing\n", p->h.dir);
1322 memmove(s->rxb, s->rxb + 1, --s->cur);
1323 return;
1324 }
1325
1326 /* Process complete packets/acks */
1327 if (s->cur >= pkt_len) {
1328 kdd_log_pkt(s, "RX", p);
1329 if (p->h.dir == KDD_DIR_PKT)
1330 kdd_handle_pkt(s, p);
1331 else
1332 kdd_handle_ack(s, p->h.id, p->h.type);
1333 s->cur = 0;
1334 }
1335 }
1336
1337
usage(void)1338 static void __attribute__((noreturn)) usage(void)
1339 {
1340 fprintf(stderr,
1341 " usage: kdd [-v] <domid> <address> <port>\n"
1342 " \n"
1343 " Makes a TCP connection to <address>:<port> and speaks the kd serial\n"
1344 " protocol over it, to debug Xen domain <domid>.\n"
1345 " To connect a debugger, set up a Windows VM with it serial port confgured\n"
1346 " as \"serial='tcp:<address>:<port>,server,nodelay,nowait'\". Run\n"
1347 " windbg or kd in that VM, connecting to COM1; then run kdd.\n\n");
1348 exit(1);
1349 }
1350
1351
main(int argc,char ** argv)1352 int main(int argc, char **argv)
1353 {
1354 int fd;
1355 int verbosity = 0;
1356 kdd_state *s;
1357 kdd_guest *g;
1358 struct addrinfo *addr;
1359 fd_set fds;
1360
1361 while (argc > 4)
1362 if (!strcmp(argv[1], "-v")) {
1363 verbosity++;
1364 argc--;
1365 argv++;
1366 }
1367
1368 if (argc != 4
1369 || !(g = kdd_guest_init(argv[1], stdout, verbosity))
1370 || getaddrinfo(argv[2], argv[3], NULL, &addr) != 0
1371 || (fd = kdd_init(&s, addr, g, stdout, verbosity)) < 0)
1372 usage();
1373
1374 while (1) {
1375 FD_ZERO(&fds);
1376 FD_SET(fd, &fds);
1377 if (select(fd + 1, &fds, NULL, NULL, NULL) > 0)
1378 kdd_select_callback(s);
1379 }
1380
1381 return 0;
1382 }
1383