winedbg/gdbproxy: Replace memory read over a breakpoint with the real value.
[wine.git] / programs / winedbg / gdbproxy.c
blob7b9a4768aca53d738e610fa723cedce4e27638ed
1 /*
2 * A Win32 based proxy implementing the GBD remote protocol.
3 * This makes it possible to debug Wine (and any "emulated"
4 * program) under Linux using GDB.
6 * Copyright (c) Eric Pouech 2002-2004
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* Protocol specification can be found here:
24 * http://sources.redhat.com/gdb/onlinedocs/gdb/Maintenance-Commands.html
27 #include "config.h"
28 #include "wine/port.h"
30 #include <assert.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #ifdef HAVE_SYS_POLL_H
38 # include <sys/poll.h>
39 #endif
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
42 #endif
43 #ifdef HAVE_SYS_SOCKET_H
44 # include <sys/socket.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49 #ifdef HAVE_NETINET_TCP_H
50 # include <netinet/tcp.h>
51 #endif
52 #ifdef HAVE_UNISTD_H
53 # include <unistd.h>
54 #endif
56 /* if we don't have poll support on this system
57 * we won't provide gdb proxy support here...
59 #ifdef HAVE_POLL
61 #include "debugger.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "tlhelp32.h"
67 #define GDBPXY_TRC_LOWLEVEL 0x01
68 #define GDBPXY_TRC_PACKET 0x02
69 #define GDBPXY_TRC_COMMAND 0x04
70 #define GDBPXY_TRC_COMMAND_ERROR 0x08
71 #define GDBPXY_TRC_WIN32_EVENT 0x10
72 #define GDBPXY_TRC_WIN32_ERROR 0x20
73 #define GDBPXY_TRC_COMMAND_FIXME 0x80
75 struct gdb_ctx_Xpoint
77 enum be_xpoint_type type; /* -1 means free */
78 void* addr;
79 unsigned long val;
82 struct gdb_context
84 /* gdb information */
85 int sock;
86 /* incoming buffer */
87 char* in_buf;
88 int in_buf_alloc;
89 int in_len;
90 /* split into individual packet */
91 char* in_packet;
92 int in_packet_len;
93 /* outgoing buffer */
94 char* out_buf;
95 int out_buf_alloc;
96 int out_len;
97 int out_curr_packet;
98 /* generic GDB thread information */
99 struct dbg_thread* exec_thread; /* thread used in step & continue */
100 struct dbg_thread* other_thread; /* thread to be used in any other operation */
101 unsigned trace;
102 /* current Win32 trap env */
103 unsigned last_sig;
104 BOOL in_trap;
105 CONTEXT context;
106 /* Win32 information */
107 struct dbg_process* process;
108 #define NUM_XPOINT 32
109 struct gdb_ctx_Xpoint Xpoints[NUM_XPOINT];
110 /* Unix environment */
111 unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
114 static BOOL tgt_process_gdbproxy_read(HANDLE hProcess, const void* addr,
115 void* buffer, SIZE_T len, SIZE_T* rlen)
117 return ReadProcessMemory( hProcess, addr, buffer, len, rlen );
120 static BOOL tgt_process_gdbproxy_write(HANDLE hProcess, void* addr,
121 const void* buffer, SIZE_T len, SIZE_T* wlen)
123 return WriteProcessMemory( hProcess, addr, buffer, len, wlen );
126 static struct be_process_io be_process_gdbproxy_io =
128 NULL, /* we shouldn't use close_process() in gdbproxy */
129 tgt_process_gdbproxy_read,
130 tgt_process_gdbproxy_write
133 /* =============================================== *
134 * B A S I C M A N I P U L A T I O N S *
135 * =============================================== *
138 static inline int hex_from0(char ch)
140 if (ch >= '0' && ch <= '9') return ch - '0';
141 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
142 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
144 assert(0);
145 return 0;
148 static inline unsigned char hex_to0(int x)
150 assert(x >= 0 && x < 16);
151 return "0123456789abcdef"[x];
154 static int hex_to_int(const char* src, size_t len)
156 unsigned int returnval = 0;
157 while (len--)
159 returnval <<= 4;
160 returnval |= hex_from0(*src++);
162 return returnval;
165 static void hex_from(void* dst, const char* src, size_t len)
167 unsigned char *p = dst;
168 while (len--)
170 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
171 src += 2;
175 static void hex_to(char* dst, const void* src, size_t len)
177 const unsigned char *p = src;
178 while (len--)
180 *dst++ = hex_to0(*p >> 4);
181 *dst++ = hex_to0(*p & 0x0F);
182 p++;
186 static unsigned char checksum(const char* ptr, int len)
188 unsigned cksum = 0;
190 while (len-- > 0)
191 cksum += (unsigned char)*ptr++;
192 return cksum;
195 /* =============================================== *
196 * C P U H A N D L E R S *
197 * =============================================== *
200 /* This struct helps us to manage the different representations of a register:
201 * ctx_offset and ctx_length are the location and size in Win32 CONTEXT
202 * gdb_length is the length gdb expects on the wire
203 * As the two sizes could be different, we have to convert between the two
204 * (for example, on x86_64, Seg?s are 4 bytes on the wire and 2 in CONTEXT)
206 struct cpu_register
208 size_t ctx_offset;
209 size_t ctx_length;
210 size_t gdb_length;
211 ULONG ctx_flags;
214 #define REG(r,gs,m) {FIELD_OFFSET(CONTEXT, r), sizeof(((CONTEXT*)NULL)->r), gs, m}
216 #ifdef __i386__
217 typedef struct DECLSPEC_ALIGN(16) _M128A {
218 ULONGLONG Low;
219 LONGLONG High;
220 } M128A, *PM128A;
222 typedef struct _XMM_SAVE_AREA32 {
223 WORD ControlWord; /* 000 */
224 WORD StatusWord; /* 002 */
225 BYTE TagWord; /* 004 */
226 BYTE Reserved1; /* 005 */
227 WORD ErrorOpcode; /* 006 */
228 DWORD ErrorOffset; /* 008 */
229 WORD ErrorSelector; /* 00c */
230 WORD Reserved2; /* 00e */
231 DWORD DataOffset; /* 010 */
232 WORD DataSelector; /* 014 */
233 WORD Reserved3; /* 016 */
234 DWORD MxCsr; /* 018 */
235 DWORD MxCsr_Mask; /* 01c */
236 M128A FloatRegisters[8]; /* 020 */
237 M128A XmmRegisters[16]; /* 0a0 */
238 BYTE Reserved4[96]; /* 1a0 */
239 } XMM_SAVE_AREA32, *PXMM_SAVE_AREA32;
241 static const char target_xml[] = "";
242 static struct cpu_register cpu_register_map[] = {
243 REG(Eax, 4, CONTEXT_INTEGER),
244 REG(Ecx, 4, CONTEXT_INTEGER),
245 REG(Edx, 4, CONTEXT_INTEGER),
246 REG(Ebx, 4, CONTEXT_INTEGER),
247 REG(Esp, 4, CONTEXT_CONTROL),
248 REG(Ebp, 4, CONTEXT_CONTROL),
249 REG(Esi, 4, CONTEXT_INTEGER),
250 REG(Edi, 4, CONTEXT_INTEGER),
251 REG(Eip, 4, CONTEXT_CONTROL),
252 REG(EFlags, 4, CONTEXT_CONTROL),
253 REG(SegCs, 4, CONTEXT_CONTROL),
254 REG(SegSs, 4, CONTEXT_SEGMENTS),
255 REG(SegDs, 4, CONTEXT_SEGMENTS),
256 REG(SegEs, 4, CONTEXT_SEGMENTS),
257 REG(SegFs, 4, CONTEXT_SEGMENTS),
258 REG(SegGs, 4, CONTEXT_SEGMENTS),
259 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[ 0]), 10, 10, CONTEXT_FLOATING_POINT },
260 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[10]), 10, 10, CONTEXT_FLOATING_POINT },
261 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[20]), 10, 10, CONTEXT_FLOATING_POINT },
262 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[30]), 10, 10, CONTEXT_FLOATING_POINT },
263 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[40]), 10, 10, CONTEXT_FLOATING_POINT },
264 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[50]), 10, 10, CONTEXT_FLOATING_POINT },
265 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[60]), 10, 10, CONTEXT_FLOATING_POINT },
266 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[70]), 10, 10, CONTEXT_FLOATING_POINT },
267 { FIELD_OFFSET(CONTEXT, FloatSave.ControlWord), 2, 4, CONTEXT_FLOATING_POINT },
268 { FIELD_OFFSET(CONTEXT, FloatSave.StatusWord), 2, 4, CONTEXT_FLOATING_POINT },
269 { FIELD_OFFSET(CONTEXT, FloatSave.TagWord), 2, 4, CONTEXT_FLOATING_POINT },
270 { FIELD_OFFSET(CONTEXT, FloatSave.ErrorSelector), 2, 4, CONTEXT_FLOATING_POINT },
271 REG(FloatSave.ErrorOffset, 4, CONTEXT_FLOATING_POINT ),
272 { FIELD_OFFSET(CONTEXT, FloatSave.DataSelector), 2, 4, CONTEXT_FLOATING_POINT },
273 REG(FloatSave.DataOffset, 4, CONTEXT_FLOATING_POINT ),
274 { FIELD_OFFSET(CONTEXT, FloatSave.ErrorSelector)+2, 2, 4, CONTEXT_FLOATING_POINT },
275 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[0]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
276 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[1]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
277 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[2]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
278 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[3]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
279 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[4]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
280 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[5]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
281 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[6]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
282 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, XmmRegisters[7]), 16, 16, CONTEXT_EXTENDED_REGISTERS },
283 { FIELD_OFFSET(CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XMM_SAVE_AREA32, MxCsr), 4, 4, CONTEXT_EXTENDED_REGISTERS },
285 #elif defined(__powerpc__)
286 static const char target_xml[] = "";
287 static struct cpu_register cpu_register_map[] = {
288 REG(Gpr0, 4, CONTEXT_INTEGER),
289 REG(Gpr1, 4, CONTEXT_INTEGER),
290 REG(Gpr2, 4, CONTEXT_INTEGER),
291 REG(Gpr3, 4, CONTEXT_INTEGER),
292 REG(Gpr4, 4, CONTEXT_INTEGER),
293 REG(Gpr5, 4, CONTEXT_INTEGER),
294 REG(Gpr6, 4, CONTEXT_INTEGER),
295 REG(Gpr7, 4, CONTEXT_INTEGER),
296 REG(Gpr8, 4, CONTEXT_INTEGER),
297 REG(Gpr9, 4, CONTEXT_INTEGER),
298 REG(Gpr10, 4, CONTEXT_INTEGER),
299 REG(Gpr11, 4, CONTEXT_INTEGER),
300 REG(Gpr12, 4, CONTEXT_INTEGER),
301 REG(Gpr13, 4, CONTEXT_INTEGER),
302 REG(Gpr14, 4, CONTEXT_INTEGER),
303 REG(Gpr15, 4, CONTEXT_INTEGER),
304 REG(Gpr16, 4, CONTEXT_INTEGER),
305 REG(Gpr17, 4, CONTEXT_INTEGER),
306 REG(Gpr18, 4, CONTEXT_INTEGER),
307 REG(Gpr19, 4, CONTEXT_INTEGER),
308 REG(Gpr20, 4, CONTEXT_INTEGER),
309 REG(Gpr21, 4, CONTEXT_INTEGER),
310 REG(Gpr22, 4, CONTEXT_INTEGER),
311 REG(Gpr23, 4, CONTEXT_INTEGER),
312 REG(Gpr24, 4, CONTEXT_INTEGER),
313 REG(Gpr25, 4, CONTEXT_INTEGER),
314 REG(Gpr26, 4, CONTEXT_INTEGER),
315 REG(Gpr27, 4, CONTEXT_INTEGER),
316 REG(Gpr28, 4, CONTEXT_INTEGER),
317 REG(Gpr29, 4, CONTEXT_INTEGER),
318 REG(Gpr30, 4, CONTEXT_INTEGER),
319 REG(Gpr31, 4, CONTEXT_INTEGER),
320 REG(Fpr0, 4, CONTEXT_FLOATING_POINT),
321 REG(Fpr1, 4, CONTEXT_FLOATING_POINT),
322 REG(Fpr2, 4, CONTEXT_FLOATING_POINT),
323 REG(Fpr3, 4, CONTEXT_FLOATING_POINT),
324 REG(Fpr4, 4, CONTEXT_FLOATING_POINT),
325 REG(Fpr5, 4, CONTEXT_FLOATING_POINT),
326 REG(Fpr6, 4, CONTEXT_FLOATING_POINT),
327 REG(Fpr7, 4, CONTEXT_FLOATING_POINT),
328 REG(Fpr8, 4, CONTEXT_FLOATING_POINT),
329 REG(Fpr9, 4, CONTEXT_FLOATING_POINT),
330 REG(Fpr10, 4, CONTEXT_FLOATING_POINT),
331 REG(Fpr11, 4, CONTEXT_FLOATING_POINT),
332 REG(Fpr12, 4, CONTEXT_FLOATING_POINT),
333 REG(Fpr13, 4, CONTEXT_FLOATING_POINT),
334 REG(Fpr14, 4, CONTEXT_FLOATING_POINT),
335 REG(Fpr15, 4, CONTEXT_FLOATING_POINT),
336 REG(Fpr16, 4, CONTEXT_FLOATING_POINT),
337 REG(Fpr17, 4, CONTEXT_FLOATING_POINT),
338 REG(Fpr18, 4, CONTEXT_FLOATING_POINT),
339 REG(Fpr19, 4, CONTEXT_FLOATING_POINT),
340 REG(Fpr20, 4, CONTEXT_FLOATING_POINT),
341 REG(Fpr21, 4, CONTEXT_FLOATING_POINT),
342 REG(Fpr22, 4, CONTEXT_FLOATING_POINT),
343 REG(Fpr23, 4, CONTEXT_FLOATING_POINT),
344 REG(Fpr24, 4, CONTEXT_FLOATING_POINT),
345 REG(Fpr25, 4, CONTEXT_FLOATING_POINT),
346 REG(Fpr26, 4, CONTEXT_FLOATING_POINT),
347 REG(Fpr27, 4, CONTEXT_FLOATING_POINT),
348 REG(Fpr28, 4, CONTEXT_FLOATING_POINT),
349 REG(Fpr29, 4, CONTEXT_FLOATING_POINT),
350 REG(Fpr30, 4, CONTEXT_FLOATING_POINT),
351 REG(Fpr31, 4, CONTEXT_FLOATING_POINT),
353 REG(Iar, 4, CONTEXT_CONTROL),
354 REG(Msr, 4, CONTEXT_CONTROL),
355 REG(Cr, 4, CONTEXT_INTEGER),
356 REG(Lr, 4, CONTEXT_CONTROL),
357 REG(Ctr, 4, CONTEXT_CONTROL),
358 REG(Xer, 4, CONTEXT_INTEGER),
359 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
360 /* see gdb/nlm/ppc.c */
362 #elif defined(__x86_64__)
363 static const char target_xml[] = "";
364 static struct cpu_register cpu_register_map[] = {
365 REG(Rax, 8, CONTEXT_INTEGER),
366 REG(Rbx, 8, CONTEXT_INTEGER),
367 REG(Rcx, 8, CONTEXT_INTEGER),
368 REG(Rdx, 8, CONTEXT_INTEGER),
369 REG(Rsi, 8, CONTEXT_INTEGER),
370 REG(Rdi, 8, CONTEXT_INTEGER),
371 REG(Rbp, 8, CONTEXT_INTEGER),
372 REG(Rsp, 8, CONTEXT_INTEGER),
373 REG(R8, 8, CONTEXT_INTEGER),
374 REG(R9, 8, CONTEXT_INTEGER),
375 REG(R10, 8, CONTEXT_INTEGER),
376 REG(R11, 8, CONTEXT_INTEGER),
377 REG(R12, 8, CONTEXT_INTEGER),
378 REG(R13, 8, CONTEXT_INTEGER),
379 REG(R14, 8, CONTEXT_INTEGER),
380 REG(R15, 8, CONTEXT_INTEGER),
381 REG(Rip, 8, CONTEXT_CONTROL),
382 REG(EFlags, 4, CONTEXT_CONTROL),
383 REG(SegCs, 4, CONTEXT_CONTROL),
384 REG(SegSs, 4, CONTEXT_CONTROL),
385 REG(SegDs, 4, CONTEXT_SEGMENTS),
386 REG(SegEs, 4, CONTEXT_SEGMENTS),
387 REG(SegFs, 4, CONTEXT_SEGMENTS),
388 REG(SegGs, 4, CONTEXT_SEGMENTS),
389 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 0]), 10, 10, CONTEXT_FLOATING_POINT },
390 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 1]), 10, 10, CONTEXT_FLOATING_POINT },
391 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 2]), 10, 10, CONTEXT_FLOATING_POINT },
392 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 3]), 10, 10, CONTEXT_FLOATING_POINT },
393 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 4]), 10, 10, CONTEXT_FLOATING_POINT },
394 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 5]), 10, 10, CONTEXT_FLOATING_POINT },
395 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 6]), 10, 10, CONTEXT_FLOATING_POINT },
396 { FIELD_OFFSET(CONTEXT, u.FltSave.FloatRegisters[ 7]), 10, 10, CONTEXT_FLOATING_POINT },
397 REG(u.FltSave.ControlWord, 4, CONTEXT_FLOATING_POINT),
398 REG(u.FltSave.StatusWord, 4, CONTEXT_FLOATING_POINT),
399 REG(u.FltSave.TagWord, 4, CONTEXT_FLOATING_POINT),
400 REG(u.FltSave.ErrorSelector, 4, CONTEXT_FLOATING_POINT),
401 REG(u.FltSave.ErrorOffset, 4, CONTEXT_FLOATING_POINT),
402 REG(u.FltSave.DataSelector, 4, CONTEXT_FLOATING_POINT),
403 REG(u.FltSave.DataOffset, 4, CONTEXT_FLOATING_POINT),
404 REG(u.FltSave.ErrorOpcode, 4, CONTEXT_FLOATING_POINT),
405 REG(u.s.Xmm0, 16, CONTEXT_FLOATING_POINT),
406 REG(u.s.Xmm1, 16, CONTEXT_FLOATING_POINT),
407 REG(u.s.Xmm2, 16, CONTEXT_FLOATING_POINT),
408 REG(u.s.Xmm3, 16, CONTEXT_FLOATING_POINT),
409 REG(u.s.Xmm4, 16, CONTEXT_FLOATING_POINT),
410 REG(u.s.Xmm5, 16, CONTEXT_FLOATING_POINT),
411 REG(u.s.Xmm6, 16, CONTEXT_FLOATING_POINT),
412 REG(u.s.Xmm7, 16, CONTEXT_FLOATING_POINT),
413 REG(u.s.Xmm8, 16, CONTEXT_FLOATING_POINT),
414 REG(u.s.Xmm9, 16, CONTEXT_FLOATING_POINT),
415 REG(u.s.Xmm10, 16, CONTEXT_FLOATING_POINT),
416 REG(u.s.Xmm11, 16, CONTEXT_FLOATING_POINT),
417 REG(u.s.Xmm12, 16, CONTEXT_FLOATING_POINT),
418 REG(u.s.Xmm13, 16, CONTEXT_FLOATING_POINT),
419 REG(u.s.Xmm14, 16, CONTEXT_FLOATING_POINT),
420 REG(u.s.Xmm15, 16, CONTEXT_FLOATING_POINT),
421 REG(u.FltSave.MxCsr, 4, CONTEXT_FLOATING_POINT),
423 #elif defined(__arm__)
424 static const char target_xml[] =
425 "l <target><architecture>arm</architecture>\n"
426 "<feature name=\"org.gnu.gdb.arm.core\">\n"
427 " <reg name=\"r0\" bitsize=\"32\" type=\"uint32\"/>\n"
428 " <reg name=\"r1\" bitsize=\"32\" type=\"uint32\"/>\n"
429 " <reg name=\"r2\" bitsize=\"32\" type=\"uint32\"/>\n"
430 " <reg name=\"r3\" bitsize=\"32\" type=\"uint32\"/>\n"
431 " <reg name=\"r4\" bitsize=\"32\" type=\"uint32\"/>\n"
432 " <reg name=\"r5\" bitsize=\"32\" type=\"uint32\"/>\n"
433 " <reg name=\"r6\" bitsize=\"32\" type=\"uint32\"/>\n"
434 " <reg name=\"r7\" bitsize=\"32\" type=\"uint32\"/>\n"
435 " <reg name=\"r8\" bitsize=\"32\" type=\"uint32\"/>\n"
436 " <reg name=\"r9\" bitsize=\"32\" type=\"uint32\"/>\n"
437 " <reg name=\"r10\" bitsize=\"32\" type=\"uint32\"/>\n"
438 " <reg name=\"r11\" bitsize=\"32\" type=\"uint32\"/>\n"
439 " <reg name=\"r12\" bitsize=\"32\" type=\"uint32\"/>\n"
440 " <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n"
441 " <reg name=\"lr\" bitsize=\"32\"/>\n"
442 " <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n"
443 " <reg name=\"cpsr\" bitsize=\"32\"/>\n"
444 "</feature></target>\n";
446 static struct cpu_register cpu_register_map[] = {
447 REG(R0, 4, CONTEXT_INTEGER),
448 REG(R1, 4, CONTEXT_INTEGER),
449 REG(R2, 4, CONTEXT_INTEGER),
450 REG(R3, 4, CONTEXT_INTEGER),
451 REG(R4, 4, CONTEXT_INTEGER),
452 REG(R5, 4, CONTEXT_INTEGER),
453 REG(R6, 4, CONTEXT_INTEGER),
454 REG(R7, 4, CONTEXT_INTEGER),
455 REG(R8, 4, CONTEXT_INTEGER),
456 REG(R9, 4, CONTEXT_INTEGER),
457 REG(R10, 4, CONTEXT_INTEGER),
458 REG(R11, 4, CONTEXT_INTEGER),
459 REG(R12, 4, CONTEXT_INTEGER),
460 REG(Sp, 4, CONTEXT_CONTROL),
461 REG(Lr, 4, CONTEXT_CONTROL),
462 REG(Pc, 4, CONTEXT_CONTROL),
463 REG(Cpsr, 4, CONTEXT_CONTROL),
465 #elif defined(__aarch64__)
466 static const char target_xml[] = "";
467 static struct cpu_register cpu_register_map[] = {
468 REG(Cpsr, 4, CONTEXT_CONTROL),
469 REG(u.s.X0, 8, CONTEXT_INTEGER),
470 REG(u.s.X1, 8, CONTEXT_INTEGER),
471 REG(u.s.X2, 8, CONTEXT_INTEGER),
472 REG(u.s.X3, 8, CONTEXT_INTEGER),
473 REG(u.s.X4, 8, CONTEXT_INTEGER),
474 REG(u.s.X5, 8, CONTEXT_INTEGER),
475 REG(u.s.X6, 8, CONTEXT_INTEGER),
476 REG(u.s.X7, 8, CONTEXT_INTEGER),
477 REG(u.s.X8, 8, CONTEXT_INTEGER),
478 REG(u.s.X9, 8, CONTEXT_INTEGER),
479 REG(u.s.X10, 8, CONTEXT_INTEGER),
480 REG(u.s.X11, 8, CONTEXT_INTEGER),
481 REG(u.s.X12, 8, CONTEXT_INTEGER),
482 REG(u.s.X13, 8, CONTEXT_INTEGER),
483 REG(u.s.X14, 8, CONTEXT_INTEGER),
484 REG(u.s.X15, 8, CONTEXT_INTEGER),
485 REG(u.s.X16, 8, CONTEXT_INTEGER),
486 REG(u.s.X17, 8, CONTEXT_INTEGER),
487 REG(u.s.X18, 8, CONTEXT_INTEGER),
488 REG(u.s.X19, 8, CONTEXT_INTEGER),
489 REG(u.s.X20, 8, CONTEXT_INTEGER),
490 REG(u.s.X21, 8, CONTEXT_INTEGER),
491 REG(u.s.X22, 8, CONTEXT_INTEGER),
492 REG(u.s.X23, 8, CONTEXT_INTEGER),
493 REG(u.s.X24, 8, CONTEXT_INTEGER),
494 REG(u.s.X25, 8, CONTEXT_INTEGER),
495 REG(u.s.X26, 8, CONTEXT_INTEGER),
496 REG(u.s.X27, 8, CONTEXT_INTEGER),
497 REG(u.s.X28, 8, CONTEXT_INTEGER),
498 REG(Fp, 8, CONTEXT_INTEGER),
499 REG(Lr, 8, CONTEXT_INTEGER),
500 REG(Sp, 8, CONTEXT_CONTROL),
501 REG(Pc, 8, CONTEXT_CONTROL),
503 #else
504 # error Define the registers map for your CPU
505 #endif
506 #undef REG
508 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
510 static inline void* cpu_register_ptr(CONTEXT* ctx, unsigned idx)
512 assert(idx < cpu_num_regs);
513 return (char*)ctx + cpu_register_map[idx].ctx_offset;
516 static inline DWORD64 cpu_register(CONTEXT* ctx, unsigned idx)
518 switch (cpu_register_map[idx].ctx_length)
520 case 2: return *(WORD*)cpu_register_ptr(ctx, idx);
521 case 4: return *(DWORD*)cpu_register_ptr(ctx, idx);
522 case 8: return *(DWORD64*)cpu_register_ptr(ctx, idx);
523 default:
524 fprintf(stderr, "got unexpected size: %u\n", (unsigned)cpu_register_map[idx].ctx_length);
525 assert(0);
526 return 0;
530 static inline void cpu_register_hex_from(CONTEXT* ctx, unsigned idx, const char** phex)
532 if (cpu_register_map[idx].gdb_length == cpu_register_map[idx].ctx_length)
533 hex_from(cpu_register_ptr(ctx, idx), *phex, cpu_register_map[idx].gdb_length);
534 else
536 DWORD64 val = 0;
537 unsigned i;
538 BYTE b;
540 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
542 hex_from(&b, *phex, 1);
543 *phex += 2;
544 val += (DWORD64)b << (8 * i);
546 switch (cpu_register_map[idx].ctx_length)
548 case 2: *(WORD*)cpu_register_ptr(ctx, idx) = (WORD)val; break;
549 case 4: *(DWORD*)cpu_register_ptr(ctx, idx) = (DWORD)val; break;
550 case 8: *(DWORD64*)cpu_register_ptr(ctx, idx) = val; break;
551 default: assert(0);
556 /* =============================================== *
557 * W I N 3 2 D E B U G I N T E R F A C E *
558 * =============================================== *
561 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
563 ctx->ContextFlags = CONTEXT_CONTROL
564 | CONTEXT_INTEGER
565 #if defined(__powerpc__) || defined(__i386__) || defined(__x86_64__)
566 | CONTEXT_FLOATING_POINT
567 #endif
568 #ifdef CONTEXT_SEGMENTS
569 | CONTEXT_SEGMENTS
570 #endif
571 #ifdef CONTEXT_DEBUG_REGISTERS
572 | CONTEXT_DEBUG_REGISTERS
573 #endif
574 #ifdef CONTEXT_EXTENDED_REGISTERS
575 | CONTEXT_EXTENDED_REGISTERS
576 #endif
578 if (!GetThreadContext(h, ctx))
580 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
581 fprintf(stderr, "Can't get thread's context\n");
582 return FALSE;
584 return TRUE;
587 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
589 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
590 BOOL ret = FALSE;
592 switch (rec->ExceptionCode)
594 case EXCEPTION_ACCESS_VIOLATION:
595 case EXCEPTION_PRIV_INSTRUCTION:
596 case EXCEPTION_STACK_OVERFLOW:
597 case EXCEPTION_GUARD_PAGE:
598 gdbctx->last_sig = SIGSEGV;
599 ret = TRUE;
600 break;
601 case EXCEPTION_DATATYPE_MISALIGNMENT:
602 gdbctx->last_sig = SIGBUS;
603 ret = TRUE;
604 break;
605 case EXCEPTION_SINGLE_STEP:
606 /* fall through */
607 case EXCEPTION_BREAKPOINT:
608 gdbctx->last_sig = SIGTRAP;
609 ret = TRUE;
610 break;
611 case EXCEPTION_FLT_DENORMAL_OPERAND:
612 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
613 case EXCEPTION_FLT_INEXACT_RESULT:
614 case EXCEPTION_FLT_INVALID_OPERATION:
615 case EXCEPTION_FLT_OVERFLOW:
616 case EXCEPTION_FLT_STACK_CHECK:
617 case EXCEPTION_FLT_UNDERFLOW:
618 gdbctx->last_sig = SIGFPE;
619 ret = TRUE;
620 break;
621 case EXCEPTION_INT_DIVIDE_BY_ZERO:
622 case EXCEPTION_INT_OVERFLOW:
623 gdbctx->last_sig = SIGFPE;
624 ret = TRUE;
625 break;
626 case EXCEPTION_ILLEGAL_INSTRUCTION:
627 gdbctx->last_sig = SIGILL;
628 ret = TRUE;
629 break;
630 case CONTROL_C_EXIT:
631 gdbctx->last_sig = SIGINT;
632 ret = TRUE;
633 break;
634 case STATUS_POSSIBLE_DEADLOCK:
635 gdbctx->last_sig = SIGALRM;
636 ret = TRUE;
637 /* FIXME: we could also add here a O packet with additional information */
638 break;
639 default:
640 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
641 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
642 gdbctx->last_sig = SIGABRT;
643 ret = TRUE;
644 break;
646 return ret;
649 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
651 union {
652 char bufferA[256];
653 WCHAR buffer[256];
654 } u;
656 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
658 switch (de->dwDebugEventCode)
660 case CREATE_PROCESS_DEBUG_EVENT:
661 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
662 de->u.CreateProcessInfo.hProcess);
663 if (!gdbctx->process) break;
664 memory_get_string_indirect(gdbctx->process,
665 de->u.CreateProcessInfo.lpImageName,
666 de->u.CreateProcessInfo.fUnicode,
667 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
668 dbg_set_process_name(gdbctx->process, u.buffer);
670 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
671 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
672 de->dwProcessId, de->dwThreadId,
673 dbg_W2A(u.buffer, -1),
674 de->u.CreateProcessInfo.lpImageName,
675 de->u.CreateProcessInfo.lpStartAddress,
676 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
677 de->u.CreateProcessInfo.nDebugInfoSize);
679 /* de->u.CreateProcessInfo.lpStartAddress; */
680 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
681 fprintf(stderr, "Couldn't initiate DbgHelp\n");
683 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
684 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
685 de->dwProcessId, de->dwThreadId,
686 de->u.CreateProcessInfo.lpStartAddress);
688 assert(dbg_curr_thread == NULL); /* shouldn't be there */
689 dbg_add_thread(gdbctx->process, de->dwThreadId,
690 de->u.CreateProcessInfo.hThread,
691 de->u.CreateProcessInfo.lpThreadLocalBase);
692 break;
694 case LOAD_DLL_DEBUG_EVENT:
695 assert(dbg_curr_thread);
696 memory_get_string_indirect(gdbctx->process,
697 de->u.LoadDll.lpImageName,
698 de->u.LoadDll.fUnicode,
699 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
700 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
701 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
702 de->dwProcessId, de->dwThreadId,
703 dbg_W2A(u.buffer, -1),
704 de->u.LoadDll.lpBaseOfDll,
705 de->u.LoadDll.dwDebugInfoFileOffset,
706 de->u.LoadDll.nDebugInfoSize);
707 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
708 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
709 break;
711 case UNLOAD_DLL_DEBUG_EVENT:
712 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
713 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
714 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
715 SymUnloadModule(gdbctx->process->handle,
716 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
717 break;
719 case EXCEPTION_DEBUG_EVENT:
720 assert(dbg_curr_thread);
721 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
722 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
723 de->dwProcessId, de->dwThreadId,
724 de->u.Exception.ExceptionRecord.ExceptionCode);
726 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
728 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
730 break;
732 case CREATE_THREAD_DEBUG_EVENT:
733 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
734 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
735 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
737 dbg_add_thread(gdbctx->process,
738 de->dwThreadId,
739 de->u.CreateThread.hThread,
740 de->u.CreateThread.lpThreadLocalBase);
741 break;
743 case EXIT_THREAD_DEBUG_EVENT:
744 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
745 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
746 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
748 assert(dbg_curr_thread);
749 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
750 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
751 dbg_del_thread(dbg_curr_thread);
752 break;
754 case EXIT_PROCESS_DEBUG_EVENT:
755 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
756 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
757 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
759 dbg_del_process(gdbctx->process);
760 gdbctx->process = NULL;
761 /* now signal gdb that we're done */
762 gdbctx->last_sig = SIGTERM;
763 gdbctx->in_trap = TRUE;
764 break;
766 case OUTPUT_DEBUG_STRING_EVENT:
767 assert(dbg_curr_thread);
768 memory_get_string(gdbctx->process,
769 de->u.DebugString.lpDebugStringData, TRUE,
770 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
771 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
772 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
773 de->dwProcessId, de->dwThreadId, u.bufferA);
774 break;
776 case RIP_EVENT:
777 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
778 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
779 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
780 de->u.RipInfo.dwType);
781 break;
783 default:
784 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
785 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
786 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
790 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
792 if (dbg_curr_thread)
794 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
795 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
796 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
797 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
798 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
799 fprintf(stderr, "Cannot continue on %04x (%x)\n",
800 dbg_curr_thread->tid, cont);
802 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
803 fprintf(stderr, "Cannot find last thread\n");
807 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
810 if (dbg_curr_thread)
812 if(dbg_curr_thread->tid == threadid){
813 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
814 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
815 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
816 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
817 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
818 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
819 fprintf(stderr, "Cannot continue on %04x (%x)\n",
820 dbg_curr_thread->tid, cont);
823 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
824 fprintf(stderr, "Cannot find last thread\n");
827 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
829 struct pollfd pollfd;
830 int ret;
831 char pkt;
833 pollfd.fd = gdbctx->sock;
834 pollfd.events = POLLIN;
835 pollfd.revents = 0;
837 if ((ret = poll(&pollfd, 1, 0)) == 1) {
838 ret = read(gdbctx->sock, &pkt, 1);
839 if (ret != 1) {
840 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
841 fprintf(stderr, "read failed\n");
843 return FALSE;
845 if (pkt != '\003') {
846 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
847 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
849 return FALSE;
851 return TRUE;
852 } else if (ret == -1) {
853 fprintf(stderr, "poll failed\n");
855 return FALSE;
858 static void wait_for_debuggee(struct gdb_context* gdbctx)
860 DEBUG_EVENT de;
862 gdbctx->in_trap = FALSE;
863 for (;;)
865 if (!WaitForDebugEvent(&de, 10))
867 if (GetLastError() == ERROR_SEM_TIMEOUT)
869 if (check_for_interrupt(gdbctx)) {
870 if (!DebugBreakProcess(gdbctx->process->handle)) {
871 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
872 fprintf(stderr, "Failed to break into debugee\n");
874 break;
876 WaitForDebugEvent(&de, INFINITE);
877 } else {
878 continue;
880 } else {
881 break;
884 handle_debug_event(gdbctx, &de);
885 assert(!gdbctx->process ||
886 gdbctx->process->pid == 0 ||
887 de.dwProcessId == gdbctx->process->pid);
888 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
889 if (gdbctx->in_trap) break;
890 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
894 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
896 be_cpu->single_step(&gdbctx->context, FALSE);
897 resume_debuggee(gdbctx, DBG_CONTINUE);
898 if (!kill)
899 DebugActiveProcessStop(gdbctx->process->pid);
900 dbg_del_process(gdbctx->process);
901 gdbctx->process = NULL;
904 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
906 DWORD status;
908 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
910 strcpy(buffer, "Unknown process");
911 return;
913 if (status == STILL_ACTIVE)
915 strcpy(buffer, "Running");
917 else
918 snprintf(buffer, len, "Terminated (%u)", status);
920 switch (GetPriorityClass(gdbctx->process->handle))
922 case 0: break;
923 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
924 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
925 #endif
926 #ifdef BELOW_NORMAL_PRIORITY_CLASS
927 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
928 #endif
929 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
930 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
931 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
932 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
934 strcat(buffer, "\n");
937 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
938 char* buffer, size_t len)
940 struct dbg_thread* thd;
941 DWORD status;
942 int prio;
944 /* FIXME: use the size of buffer */
945 thd = dbg_get_thread(gdbctx->process, tid);
946 if (thd == NULL)
948 strcpy(buffer, "No information");
949 return;
951 if (GetExitCodeThread(thd->handle, &status))
953 if (status == STILL_ACTIVE)
955 /* FIXME: this is a bit brutal... some nicer way shall be found */
956 switch (status = SuspendThread(thd->handle))
958 case -1: break;
959 case 0: strcpy(buffer, "Running"); break;
960 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
962 ResumeThread(thd->handle);
964 else
965 snprintf(buffer, len, "Terminated (exit code = %u)", status);
967 else
969 strcpy(buffer, "Unknown threadID");
971 switch (prio = GetThreadPriority(thd->handle))
973 case THREAD_PRIORITY_ERROR_RETURN: break;
974 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
975 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
976 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
977 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
978 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
979 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
980 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
981 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
983 assert(strlen(buffer) < len);
986 /* =============================================== *
987 * P A C K E T U T I L S *
988 * =============================================== *
991 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
992 packet_last_f = 0x80};
994 static char* packet_realloc(char* buf, int size)
996 if (!buf)
997 return HeapAlloc(GetProcessHeap(), 0, size);
998 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
1002 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
1004 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
1006 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
1007 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
1011 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
1013 packet_reply_grow(gdbctx, len * 2);
1014 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
1015 gdbctx->out_len += len * 2;
1018 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
1020 packet_reply_hex_to(gdbctx, src, strlen(src));
1023 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
1025 int i, shift;
1027 shift = (len - 1) * 8;
1028 packet_reply_grow(gdbctx, len * 2);
1029 for (i = 0; i < len; i++, shift -= 8)
1031 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
1032 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
1036 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
1038 packet_reply_grow(gdbctx, len);
1039 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
1040 gdbctx->out_len += len;
1043 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
1045 packet_reply_add(gdbctx, str, strlen(str));
1048 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
1050 packet_reply_add(gdbctx, &ch, 1);
1053 static void packet_reply_open(struct gdb_context* gdbctx)
1055 assert(gdbctx->out_curr_packet == -1);
1056 packet_reply_catc(gdbctx, '$');
1057 gdbctx->out_curr_packet = gdbctx->out_len;
1060 static void packet_reply_close(struct gdb_context* gdbctx)
1062 unsigned char cksum;
1063 int plen;
1065 plen = gdbctx->out_len - gdbctx->out_curr_packet;
1066 packet_reply_catc(gdbctx, '#');
1067 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
1068 packet_reply_hex_to(gdbctx, &cksum, 1);
1069 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1070 fprintf(stderr, "Reply : %*.*s\n",
1071 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
1072 gdbctx->out_curr_packet = -1;
1075 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
1077 packet_reply_open(gdbctx);
1079 if (len == -1) len = strlen(packet);
1080 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
1082 packet_reply_add(gdbctx, packet, len);
1084 packet_reply_close(gdbctx);
1086 return packet_done;
1089 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
1091 packet_reply_open(gdbctx);
1093 packet_reply_add(gdbctx, "E", 1);
1094 packet_reply_val(gdbctx, error, 1);
1096 packet_reply_close(gdbctx);
1098 return packet_done;
1101 static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, unsigned idx)
1103 if (cpu_register_map[idx].gdb_length == cpu_register_map[idx].ctx_length)
1104 packet_reply_hex_to(gdbctx, cpu_register_ptr(&gdbctx->context, idx), cpu_register_map[idx].gdb_length);
1105 else
1107 DWORD64 val = cpu_register(&gdbctx->context, idx);
1108 unsigned i;
1110 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
1112 BYTE b = val;
1113 packet_reply_hex_to(gdbctx, &b, 1);
1114 val >>= 8;
1119 /* =============================================== *
1120 * P A C K E T H A N D L E R S *
1121 * =============================================== *
1124 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
1126 enum packet_return ret = packet_done;
1128 packet_reply_open(gdbctx);
1130 if (gdbctx->process != NULL)
1132 unsigned char sig;
1133 unsigned i;
1135 packet_reply_catc(gdbctx, 'T');
1136 sig = gdbctx->last_sig;
1137 packet_reply_val(gdbctx, sig, 1);
1138 packet_reply_add(gdbctx, "thread:", 7);
1139 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
1140 packet_reply_catc(gdbctx, ';');
1142 for (i = 0; i < cpu_num_regs; i++)
1144 ULONG flags = cpu_register_map[i].ctx_flags;
1145 if ((gdbctx->context.ContextFlags & flags) != flags)
1146 break;
1148 /* FIXME: this call will also grow the buffer...
1149 * unneeded, but not harmful
1151 packet_reply_val(gdbctx, i, 1);
1152 packet_reply_catc(gdbctx, ':');
1153 packet_reply_register_hex_to(gdbctx, i);
1154 packet_reply_catc(gdbctx, ';');
1157 else
1159 /* Try to put an exit code
1160 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1161 * just indicate the end of process and exit */
1162 packet_reply_add(gdbctx, "W00", 3);
1163 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1166 packet_reply_close(gdbctx);
1168 return ret;
1171 #if 0
1172 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1174 gdbctx->extended = 1;
1175 return packet_ok;
1177 #endif
1179 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1181 assert(gdbctx->in_packet_len == 0);
1182 return packet_reply_status(gdbctx);
1185 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1187 /* FIXME: add support for address in packet */
1188 assert(gdbctx->in_packet_len == 0);
1189 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1190 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1191 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1192 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1193 resume_debuggee(gdbctx, DBG_CONTINUE);
1194 wait_for_debuggee(gdbctx);
1195 return packet_reply_status(gdbctx);
1198 static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
1200 int i;
1201 int defaultAction = -1; /* magic non action */
1202 unsigned char sig;
1203 int actions =0;
1204 int actionIndex[20]; /* allow for up to 20 actions */
1205 int threadIndex[20];
1206 int threadCount = 0;
1207 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1208 unsigned int threadID = 0;
1209 struct dbg_thread* thd;
1211 /* OK we have vCont followed by..
1212 * ? for query
1213 * c for packet_continue
1214 * Csig for packet_continue_signal
1215 * s for step
1216 * Ssig for step signal
1217 * and then an optional thread ID at the end..
1218 * *******************************************/
1220 /* Query */
1221 if (gdbctx->in_packet[4] == '?')
1224 Reply:
1225 `vCont[;action]...'
1226 The vCont packet is supported. Each action is a supported command in the vCont packet.
1228 The vCont packet is not supported. (this didn't seem to be obeyed!)
1230 packet_reply_open(gdbctx);
1231 packet_reply_add(gdbctx, "vCont", 5);
1232 /* add all the supported actions to the reply (all of them for now) */
1233 packet_reply_add(gdbctx, ";c", 2);
1234 packet_reply_add(gdbctx, ";C", 2);
1235 packet_reply_add(gdbctx, ";s", 2);
1236 packet_reply_add(gdbctx, ";S", 2);
1237 packet_reply_close(gdbctx);
1238 return packet_done;
1241 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1242 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1243 now if only gdb talked XML.... */
1244 #if 0 /* handy for debugging */
1245 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1246 #endif
1248 /* go through the packet and identify where all the actions start at */
1249 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1251 if (gdbctx->in_packet[i] == ';')
1253 threadIndex[actions] = 0;
1254 actionIndex[actions++] = i;
1256 else if (gdbctx->in_packet[i] == ':')
1258 threadIndex[actions - 1] = i;
1262 /* now look up the default action */
1263 for (i = 0 ; i < actions; i++)
1265 if (threadIndex[i] == 0)
1267 if (defaultAction != -1)
1269 fprintf(stderr,"Too many default actions specified\n");
1270 return packet_error;
1272 defaultAction = i;
1276 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1278 /* go through all the threads and stick their ids in the to be done list. */
1279 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1281 threadIDs[threadCount++] = thd->tid;
1282 /* check to see if we have more threads than I counted on, and tell the user what to do
1283 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1284 if (threadCount == 100)
1286 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1287 break;
1291 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1292 * that remains is to apply the actions to the threads and the default action to any threads
1293 * left */
1294 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1295 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1296 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1297 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1299 /* deal with the threaded stuff first */
1300 for (i = 0; i < actions ; i++)
1302 if (threadIndex[i] != 0)
1304 int j, idLength = 0;
1305 if (i < actions - 1)
1307 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1309 else
1311 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1314 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1315 /* process the action */
1316 switch (gdbctx->in_packet[actionIndex[i] + 1])
1318 case 's': /* step */
1319 be_cpu->single_step(&gdbctx->context, TRUE);
1320 /* fall through*/
1321 case 'c': /* continue */
1322 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1323 break;
1324 case 'S': /* step Sig, */
1325 be_cpu->single_step(&gdbctx->context, TRUE);
1326 /* fall through */
1327 case 'C': /* continue sig */
1328 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1329 /* cannot change signals on the fly */
1330 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1331 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1332 if (sig != gdbctx->last_sig)
1333 return packet_error;
1334 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1335 break;
1337 for (j = 0 ; j < threadCount; j++)
1339 if (threadIDs[j] == threadID)
1341 threadIDs[j] = 0;
1342 break;
1346 } /* for i=0 ; i< actions */
1348 /* now we have manage the default action */
1349 if (defaultAction >= 0)
1351 for (i = 0 ; i< threadCount; i++)
1353 /* check to see if we've already done something to the thread*/
1354 if (threadIDs[i] != 0)
1356 /* if not apply the default action*/
1357 threadID = threadIDs[i];
1358 /* process the action (yes this is almost identical to the one above!) */
1359 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1361 case 's': /* step */
1362 be_cpu->single_step(&gdbctx->context, TRUE);
1363 /* fall through */
1364 case 'c': /* continue */
1365 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1366 break;
1367 case 'S':
1368 be_cpu->single_step(&gdbctx->context, TRUE);
1369 /* fall through */
1370 case 'C': /* continue sig */
1371 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1372 /* cannot change signals on the fly */
1373 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1374 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1375 if (sig != gdbctx->last_sig)
1376 return packet_error;
1377 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1378 break;
1382 } /* if(defaultAction >=0) */
1384 wait_for_debuggee(gdbctx);
1385 be_cpu->single_step(&gdbctx->context, FALSE);
1386 return packet_reply_status(gdbctx);
1389 struct verbose_defail
1391 const char* name;
1392 unsigned len;
1393 enum packet_return (*handler)(struct gdb_context*);
1394 } verbose_details[] =
1396 /* {"Attach", 6}, */
1397 {"Cont", 4, packet_verbose_cont},
1398 /* {"File", 4},
1399 {"FlashErase", 10},
1400 {"FlashWrite", 10},
1401 {"FlashDone", 9},
1402 {"Kill", 4},
1403 {"Run", 3},
1404 {"Stopped", 7},*/
1407 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1409 unsigned i;
1410 unsigned klen;
1412 for (klen = 0; ; klen++)
1414 if (klen == gdbctx->in_packet_len ||
1415 gdbctx->in_packet[klen] == ';' ||
1416 gdbctx->in_packet[klen] == ':' ||
1417 gdbctx->in_packet[klen] == '?')
1419 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1420 fprintf(stderr, "trying to process a verbose packet %*.*s\n",
1421 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1422 for (i = 0; i < sizeof(verbose_details)/sizeof(verbose_details[0]); i++)
1424 if (klen == verbose_details[i].len &&
1425 !memcmp(gdbctx->in_packet, verbose_details[i].name, verbose_details[i].len))
1427 return verbose_details[i].handler(gdbctx);
1430 /* no matching handler found, abort */
1431 break;
1435 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1436 fprintf(stderr, "No support for verbose packet %*.*s\n",
1437 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1438 return packet_error;
1441 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1443 unsigned char sig;
1445 /* FIXME: add support for address in packet */
1446 assert(gdbctx->in_packet_len == 2);
1447 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1448 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1449 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1450 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1451 hex_from(&sig, gdbctx->in_packet, 1);
1452 /* cannot change signals on the fly */
1453 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1454 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1455 if (sig != gdbctx->last_sig)
1456 return packet_error;
1457 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1458 wait_for_debuggee(gdbctx);
1459 return packet_reply_status(gdbctx);
1462 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1464 detach_debuggee(gdbctx, FALSE);
1465 return packet_ok | packet_last_f;
1468 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1470 int i;
1471 CONTEXT ctx;
1473 assert(gdbctx->in_trap);
1475 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1477 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, &ctx))
1478 return packet_error;
1481 packet_reply_open(gdbctx);
1482 for (i = 0; i < cpu_num_regs; i++)
1484 ULONG flags = cpu_register_map[i].ctx_flags;
1485 if ((gdbctx->context.ContextFlags & flags) != flags)
1486 break;
1487 packet_reply_register_hex_to(gdbctx, i);
1489 packet_reply_close(gdbctx);
1490 return packet_done;
1493 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1495 unsigned i;
1496 CONTEXT ctx;
1497 CONTEXT* pctx = &gdbctx->context;
1498 const char* ptr;
1500 assert(gdbctx->in_trap);
1501 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1503 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1504 return packet_error;
1506 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1508 ptr = gdbctx->in_packet;
1509 for (i = 0; i < cpu_num_regs; i++)
1511 ULONG flags = cpu_register_map[i].ctx_flags;
1512 if ((pctx->ContextFlags & flags) != flags)
1513 break;
1514 cpu_register_hex_from(pctx, i, &ptr);
1516 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1518 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1519 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1520 return packet_error;
1522 return packet_ok;
1525 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1527 detach_debuggee(gdbctx, TRUE);
1528 #if 0
1529 if (!gdbctx->extended)
1530 /* dunno whether GDB cares or not */
1531 #endif
1532 wait(NULL);
1533 exit(0);
1534 /* assume we can't really answer something here */
1535 /* return packet_done; */
1538 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1540 char* end;
1541 unsigned thread;
1543 switch (gdbctx->in_packet[0])
1545 case 'c':
1546 case 'g':
1547 if (gdbctx->in_packet[1] == '-')
1548 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1549 else
1550 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1551 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1553 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1554 fprintf(stderr, "Cannot get threadid %*.*s\n",
1555 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1556 gdbctx->in_packet + 1);
1557 return packet_error;
1559 if (gdbctx->in_packet[0] == 'c')
1560 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1561 else
1562 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1563 return packet_ok;
1564 default:
1565 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1566 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1567 return packet_error;
1571 static BOOL read_memory(struct gdb_context *gdbctx, char *addr, char *buffer, SIZE_T blk_len, SIZE_T *r)
1573 /* Wrapper around process_io->read() that replaces values displaced by breakpoints. */
1575 BOOL ret;
1577 ret = gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, r);
1578 if (ret)
1580 struct gdb_ctx_Xpoint *xpt;
1582 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1584 char *xpt_addr = xpt->addr;
1586 if (xpt->type != -1 && xpt_addr >= addr && xpt_addr < addr + blk_len)
1587 buffer[xpt_addr - addr] = xpt->val;
1590 return ret;
1593 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1595 char *addr;
1596 unsigned int len, blk_len, nread;
1597 char buffer[32];
1598 SIZE_T r = 0;
1600 assert(gdbctx->in_trap);
1601 /* FIXME:check in_packet_len for reading %p,%x */
1602 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1603 if (len <= 0) return packet_error;
1604 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1605 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1606 for (nread = 0; nread < len; nread += r, addr += r)
1608 blk_len = min(sizeof(buffer), len - nread);
1609 if (!read_memory(gdbctx, addr, buffer, blk_len, &r) || r == 0)
1611 /* fail at first address, return error */
1612 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1613 /* something has already been read, return partial information */
1614 break;
1616 if (nread == 0) packet_reply_open(gdbctx);
1617 packet_reply_hex_to(gdbctx, buffer, r);
1619 packet_reply_close(gdbctx);
1620 return packet_done;
1623 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1625 char* addr;
1626 unsigned int len, blk_len;
1627 char* ptr;
1628 char buffer[32];
1629 SIZE_T w;
1631 assert(gdbctx->in_trap);
1632 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1633 if (ptr == NULL)
1635 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1636 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1637 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1638 return packet_error;
1640 *ptr++ = '\0';
1642 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1644 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1645 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1646 return packet_error;
1648 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1650 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1651 fprintf(stderr, "Wrong sizes %u <> %u\n",
1652 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1653 return packet_error;
1655 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1656 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1657 while (len > 0)
1659 blk_len = min(sizeof(buffer), len);
1660 hex_from(buffer, ptr, blk_len);
1661 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1662 w != blk_len)
1663 break;
1664 addr += blk_len;
1665 len -= blk_len;
1666 ptr += blk_len;
1668 return packet_ok; /* FIXME: error while writing ? */
1671 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1673 unsigned reg;
1674 CONTEXT ctx;
1675 CONTEXT* pctx = &gdbctx->context;
1677 assert(gdbctx->in_trap);
1678 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1679 if (reg >= cpu_num_regs)
1681 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1682 fprintf(stderr, "Register out of bounds %x\n", reg);
1683 return packet_error;
1685 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1687 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1688 return packet_error;
1690 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1692 if (cpu_register_map[reg].ctx_length <= sizeof(DWORD64))
1693 fprintf(stderr, "Read register %x => %08x%08x\n", reg,
1694 (unsigned)(cpu_register(pctx, reg) >> 32), (unsigned)cpu_register(pctx, reg));
1695 else
1696 fprintf(stderr, "Read register %x\n", reg);
1698 packet_reply_open(gdbctx);
1699 packet_reply_register_hex_to(gdbctx, reg);
1700 packet_reply_close(gdbctx);
1701 return packet_done;
1704 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1706 unsigned reg;
1707 char* ptr;
1708 CONTEXT ctx;
1709 CONTEXT* pctx = &gdbctx->context;
1711 assert(gdbctx->in_trap);
1713 reg = strtoul(gdbctx->in_packet, &ptr, 16);
1714 if (ptr == NULL || reg >= cpu_num_regs || *ptr++ != '=')
1716 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1717 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1718 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1719 * it wouldn't matter too much, and it fakes our support for all regs
1721 return (ptr == NULL) ? packet_error : packet_ok;
1723 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1725 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1726 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
1729 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1731 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1732 return packet_error;
1734 if ((pctx->ContextFlags & cpu_register_map[reg].ctx_flags) != cpu_register_map[reg].ctx_flags)
1736 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1737 fprintf(stderr, "Writing reg %u is not supported on this host\n", reg);
1738 return packet_error;
1741 cpu_register_hex_from(pctx, reg, (const char**)&ptr);
1742 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1744 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1745 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1746 return packet_error;
1749 return packet_ok;
1752 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1754 char buffer[128];
1755 char clsName[128];
1756 char wndName[128];
1757 HWND child;
1759 do {
1760 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1761 strcpy(clsName, "-- Unknown --");
1762 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1763 strcpy(wndName, "-- Empty --");
1765 packet_reply_open(gdbctx);
1766 packet_reply_catc(gdbctx, 'O');
1767 snprintf(buffer, sizeof(buffer),
1768 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1769 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1770 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1771 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1772 wndName);
1773 packet_reply_hex_to_str(gdbctx, buffer);
1774 packet_reply_close(gdbctx);
1776 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1777 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1778 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1781 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1783 char buffer[128];
1785 /* we do the output in several 'O' packets, with the last one being just OK for
1786 * marking the end of the output */
1787 packet_reply_open(gdbctx);
1788 packet_reply_catc(gdbctx, 'O');
1789 snprintf(buffer, sizeof(buffer),
1790 "%-16.16s %-17.17s %-8.8s %s\n",
1791 "hwnd", "Class Name", " Style", " WndProc Text");
1792 packet_reply_hex_to_str(gdbctx, buffer);
1793 packet_reply_close(gdbctx);
1795 /* FIXME: could also add a pmt to this command in str... */
1796 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1797 packet_reply(gdbctx, "OK", 2);
1800 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1802 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1803 char buffer[31+MAX_PATH];
1804 char deco;
1805 PROCESSENTRY32 entry;
1806 BOOL ok;
1808 if (snap == INVALID_HANDLE_VALUE)
1809 return;
1811 entry.dwSize = sizeof(entry);
1812 ok = Process32First(snap, &entry);
1814 /* we do the output in several 'O' packets, with the last one being just OK for
1815 * marking the end of the output */
1817 packet_reply_open(gdbctx);
1818 packet_reply_catc(gdbctx, 'O');
1819 snprintf(buffer, sizeof(buffer),
1820 " %-8.8s %-8.8s %-8.8s %s\n",
1821 "pid", "threads", "parent", "executable");
1822 packet_reply_hex_to_str(gdbctx, buffer);
1823 packet_reply_close(gdbctx);
1825 while (ok)
1827 deco = ' ';
1828 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1829 packet_reply_open(gdbctx);
1830 packet_reply_catc(gdbctx, 'O');
1831 snprintf(buffer, sizeof(buffer),
1832 "%c%08x %-8d %08x '%s'\n",
1833 deco, entry.th32ProcessID, entry.cntThreads,
1834 entry.th32ParentProcessID, entry.szExeFile);
1835 packet_reply_hex_to_str(gdbctx, buffer);
1836 packet_reply_close(gdbctx);
1837 ok = Process32Next(snap, &entry);
1839 CloseHandle(snap);
1840 packet_reply(gdbctx, "OK", 2);
1843 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1845 MEMORY_BASIC_INFORMATION mbi;
1846 char* addr = 0;
1847 const char* state;
1848 const char* type;
1849 char prot[3+1];
1850 char buffer[128];
1852 /* we do the output in several 'O' packets, with the last one being just OK for
1853 * marking the end of the output */
1854 packet_reply_open(gdbctx);
1855 packet_reply_catc(gdbctx, 'O');
1856 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1857 packet_reply_close(gdbctx);
1859 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1861 switch (mbi.State)
1863 case MEM_COMMIT: state = "commit "; break;
1864 case MEM_FREE: state = "free "; break;
1865 case MEM_RESERVE: state = "reserve"; break;
1866 default: state = "??? "; break;
1868 if (mbi.State != MEM_FREE)
1870 switch (mbi.Type)
1872 case MEM_IMAGE: type = "image "; break;
1873 case MEM_MAPPED: type = "mapped "; break;
1874 case MEM_PRIVATE: type = "private"; break;
1875 case 0: type = " "; break;
1876 default: type = "??? "; break;
1878 memset(prot, ' ' , sizeof(prot)-1);
1879 prot[sizeof(prot)-1] = '\0';
1880 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1881 prot[0] = 'R';
1882 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1883 prot[1] = 'W';
1884 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1885 prot[1] = 'C';
1886 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1887 prot[2] = 'X';
1889 else
1891 type = "";
1892 prot[0] = '\0';
1894 packet_reply_open(gdbctx);
1895 snprintf(buffer, sizeof(buffer), "%0*lx %0*lx %s %s %s\n",
1896 (unsigned)sizeof(void*), (DWORD_PTR)addr,
1897 (unsigned)sizeof(void*), mbi.RegionSize, state, type, prot);
1898 packet_reply_catc(gdbctx, 'O');
1899 packet_reply_hex_to_str(gdbctx, buffer);
1900 packet_reply_close(gdbctx);
1902 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1903 break;
1904 addr += mbi.RegionSize;
1906 packet_reply(gdbctx, "OK", 2);
1909 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1910 int len, const char* str)
1912 char buffer[128];
1914 if (len == 0)
1916 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1918 else if (len >= 2 && str[0] == '=')
1920 unsigned val = atoi(&str[1]);
1921 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1922 gdbctx->trace = val;
1924 else
1926 /* FIXME: ugly but can use error packet here */
1927 packet_reply_cat(gdbctx, "E00");
1928 return;
1930 packet_reply_open(gdbctx);
1931 packet_reply_hex_to_str(gdbctx, buffer);
1932 packet_reply_close(gdbctx);
1935 struct query_detail
1937 int with_arg;
1938 const char* name;
1939 size_t len;
1940 void (*handler)(struct gdb_context*, int, const char*);
1941 } query_details[] =
1943 {0, "wnd", 3, packet_query_monitor_wnd},
1944 {0, "window", 6, packet_query_monitor_wnd},
1945 {0, "proc", 4, packet_query_monitor_process},
1946 {0, "process", 7, packet_query_monitor_process},
1947 {0, "mem", 3, packet_query_monitor_mem},
1948 {1, "trace", 5, packet_query_monitor_trace},
1949 {0, NULL, 0, NULL},
1952 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1953 const char* hxcmd, size_t len)
1955 char buffer[128];
1956 struct query_detail* qd;
1958 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1959 len /= 2;
1960 hex_from(buffer, hxcmd, len);
1962 for (qd = query_details; qd->name != NULL; qd++)
1964 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1965 if (!qd->with_arg && len != qd->len) continue;
1967 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1968 return packet_done;
1970 return packet_reply_error(gdbctx, EINVAL);
1973 static enum packet_return packet_query(struct gdb_context* gdbctx)
1975 switch (gdbctx->in_packet[0])
1977 case 'f':
1978 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1980 struct dbg_thread* thd;
1982 packet_reply_open(gdbctx);
1983 packet_reply_add(gdbctx, "m", 1);
1984 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1986 packet_reply_val(gdbctx, thd->tid, 4);
1987 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1988 packet_reply_add(gdbctx, ",", 1);
1990 packet_reply_close(gdbctx);
1991 return packet_done;
1993 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1995 char result[128];
1997 packet_reply_open(gdbctx);
1998 packet_reply_catc(gdbctx, 'O');
1999 get_process_info(gdbctx, result, sizeof(result));
2000 packet_reply_hex_to_str(gdbctx, result);
2001 packet_reply_close(gdbctx);
2002 return packet_done;
2004 break;
2005 case 's':
2006 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
2008 packet_reply(gdbctx, "l", 1);
2009 return packet_done;
2011 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
2013 packet_reply(gdbctx, "l", 1);
2014 return packet_done;
2016 break;
2017 case 'A':
2018 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
2020 char buf[2];
2022 buf[0] = '1';
2023 buf[1] = 0;
2024 return packet_reply(gdbctx, buf, -1);
2026 break;
2027 case 'C':
2028 if (gdbctx->in_packet_len == 1)
2030 struct dbg_thread* thd;
2031 /* FIXME: doc says 16 bit val ??? */
2032 /* grab first created thread, aka last in list */
2033 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
2034 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
2035 packet_reply_open(gdbctx);
2036 packet_reply_add(gdbctx, "QC", 2);
2037 packet_reply_val(gdbctx, thd->tid, 4);
2038 packet_reply_close(gdbctx);
2039 return packet_done;
2041 break;
2042 case 'O':
2043 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
2045 char buf[64];
2047 snprintf(buf, sizeof(buf),
2048 "Text=%08lx;Data=%08lx;Bss=%08lx",
2049 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
2050 gdbctx->wine_segs[2]);
2051 return packet_reply(gdbctx, buf, -1);
2053 break;
2054 case 'R':
2055 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
2057 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
2058 gdbctx->in_packet_len - 5);
2060 break;
2061 case 'S':
2062 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
2063 return packet_ok;
2064 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
2066 if (strlen(target_xml))
2067 return packet_reply(gdbctx, "PacketSize=400;qXfer:features:read+", -1);
2068 else
2070 /* no features supported */
2071 packet_reply_open(gdbctx);
2072 packet_reply_close(gdbctx);
2073 return packet_done;
2076 break;
2077 case 'T':
2078 if (gdbctx->in_packet_len > 15 &&
2079 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
2080 gdbctx->in_packet[15] == ',')
2082 unsigned tid;
2083 char* end;
2084 char result[128];
2086 tid = strtol(gdbctx->in_packet + 16, &end, 16);
2087 if (end == NULL) break;
2088 get_thread_info(gdbctx, tid, result, sizeof(result));
2089 packet_reply_open(gdbctx);
2090 packet_reply_hex_to_str(gdbctx, result);
2091 packet_reply_close(gdbctx);
2092 return packet_done;
2094 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
2096 /* Tracepoints not supported */
2097 packet_reply_open(gdbctx);
2098 packet_reply_close(gdbctx);
2099 return packet_done;
2101 break;
2102 case 'X':
2103 if (strlen(target_xml) && strncmp(gdbctx->in_packet, "Xfer:features:read:target.xml", 29) == 0)
2104 return packet_reply(gdbctx, target_xml, -1);
2105 break;
2107 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2108 fprintf(stderr, "Unknown or malformed query %*.*s\n",
2109 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
2110 return packet_error;
2113 static enum packet_return packet_step(struct gdb_context* gdbctx)
2115 /* FIXME: add support for address in packet */
2116 assert(gdbctx->in_packet_len == 0);
2117 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
2118 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
2119 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
2120 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
2121 be_cpu->single_step(&gdbctx->context, TRUE);
2122 resume_debuggee(gdbctx, DBG_CONTINUE);
2123 wait_for_debuggee(gdbctx);
2124 be_cpu->single_step(&gdbctx->context, FALSE);
2125 return packet_reply_status(gdbctx);
2128 #if 0
2129 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
2131 unsigned char sig;
2133 /* FIXME: add support for address in packet */
2134 assert(gdbctx->in_packet_len == 2);
2135 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
2136 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2137 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
2138 gdbctx->exec_thread, DEBUG_CurrThread->tid);
2139 hex_from(&sig, gdbctx->in_packet, 1);
2140 /* cannot change signals on the fly */
2141 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2142 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
2143 if (sig != gdbctx->last_sig)
2144 return packet_error;
2145 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
2146 wait_for_debuggee(gdbctx);
2147 return packet_reply_status(gdbctx);
2149 #endif
2151 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
2153 char* end;
2154 unsigned tid;
2156 tid = strtol(gdbctx->in_packet, &end, 16);
2157 if (tid == -1 || tid == 0)
2158 return packet_reply_error(gdbctx, EINVAL);
2159 if (dbg_get_thread(gdbctx->process, tid) != NULL)
2160 return packet_ok;
2161 return packet_reply_error(gdbctx, ESRCH);
2164 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
2166 void* addr;
2167 unsigned len;
2168 struct gdb_ctx_Xpoint* xpt;
2169 enum be_xpoint_type t;
2171 /* FIXME: check packet_len */
2172 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2173 gdbctx->in_packet[1] != ',' ||
2174 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2175 return packet_error;
2176 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2177 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
2178 addr, len, gdbctx->in_packet[0]);
2179 switch (gdbctx->in_packet[0])
2181 case '0': t = be_xpoint_break; len = 0; break;
2182 case '1': t = be_xpoint_watch_exec; break;
2183 case '2': t = be_xpoint_watch_read; break;
2184 case '3': t = be_xpoint_watch_write; break;
2185 default: return packet_error;
2187 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2189 if (xpt->addr == addr && xpt->type == t)
2191 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
2192 gdbctx->process->process_io, &gdbctx->context,
2193 t, xpt->addr, xpt->val, len))
2195 xpt->type = -1;
2196 return packet_ok;
2198 break;
2201 return packet_error;
2204 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
2206 void* addr;
2207 unsigned len;
2208 struct gdb_ctx_Xpoint* xpt;
2209 enum be_xpoint_type t;
2211 /* FIXME: check packet_len */
2212 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2213 gdbctx->in_packet[1] != ',' ||
2214 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2215 return packet_error;
2216 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2217 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
2218 addr, len, gdbctx->in_packet[0]);
2219 switch (gdbctx->in_packet[0])
2221 case '0': t = be_xpoint_break; len = 0; break;
2222 case '1': t = be_xpoint_watch_exec; break;
2223 case '2': t = be_xpoint_watch_read; break;
2224 case '3': t = be_xpoint_watch_write; break;
2225 default: return packet_error;
2227 /* because of packet command handling, this should be made idempotent */
2228 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2230 if (xpt->addr == addr && xpt->type == t)
2231 return packet_ok; /* nothing to do */
2233 /* really set the Xpoint */
2234 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2236 if (xpt->type == -1)
2238 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2239 gdbctx->process->process_io, &gdbctx->context,
2240 t, addr, &xpt->val, len))
2242 xpt->addr = addr;
2243 xpt->type = t;
2244 return packet_ok;
2246 fprintf(stderr, "cannot set xpoint\n");
2247 break;
2250 /* no more entries... eech */
2251 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2252 return packet_error;
2255 /* =============================================== *
2256 * P A C K E T I N F R A S T R U C T U R E *
2257 * =============================================== *
2260 struct packet_entry
2262 char key;
2263 enum packet_return (*handler)(struct gdb_context* gdbctx);
2266 static struct packet_entry packet_entries[] =
2268 /*{'!', packet_extended}, */
2269 {'?', packet_last_signal},
2270 {'c', packet_continue},
2271 {'C', packet_continue_signal},
2272 {'D', packet_detach},
2273 {'g', packet_read_registers},
2274 {'G', packet_write_registers},
2275 {'k', packet_kill},
2276 {'H', packet_thread},
2277 {'m', packet_read_memory},
2278 {'M', packet_write_memory},
2279 {'p', packet_read_register},
2280 {'P', packet_write_register},
2281 {'q', packet_query},
2282 /* {'Q', packet_set}, */
2283 /* {'R', packet,restart}, only in extended mode ! */
2284 {'s', packet_step},
2285 /*{'S', packet_step_signal}, hard(er) to implement */
2286 {'T', packet_thread_alive},
2287 {'v', packet_verbose},
2288 {'z', packet_remove_breakpoint},
2289 {'Z', packet_set_breakpoint},
2292 static BOOL extract_packets(struct gdb_context* gdbctx)
2294 char* end;
2295 int plen;
2296 unsigned char in_cksum, loc_cksum;
2297 char* ptr;
2298 enum packet_return ret = packet_error;
2299 int num_packet = 0;
2301 while ((ret & packet_last_f) == 0)
2303 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2304 fprintf(stderr, "In-buf: %*.*s\n",
2305 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2306 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2307 if (ptr == NULL) return FALSE;
2308 if (ptr != gdbctx->in_buf)
2310 int glen = ptr - gdbctx->in_buf; /* garbage len */
2311 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2312 fprintf(stderr, "Removing garbage: %*.*s\n",
2313 glen, glen, gdbctx->in_buf);
2314 gdbctx->in_len -= glen;
2315 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2317 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2318 if (end == NULL) return FALSE;
2319 /* no checksum yet */
2320 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2321 plen = end - gdbctx->in_buf - 1;
2322 hex_from(&in_cksum, end + 1, 1);
2323 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2324 if (loc_cksum == in_cksum)
2326 if (num_packet == 0) {
2327 int i;
2329 ret = packet_error;
2331 write(gdbctx->sock, "+", 1);
2332 assert(plen);
2334 /* FIXME: should use bsearch if packet_entries was sorted */
2335 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2337 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2339 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2341 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2342 fprintf(stderr, "Unknown packet request %*.*s\n",
2343 plen, plen, &gdbctx->in_buf[1]);
2345 else
2347 gdbctx->in_packet = gdbctx->in_buf + 2;
2348 gdbctx->in_packet_len = plen - 1;
2349 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2350 fprintf(stderr, "Packet: %c%*.*s\n",
2351 gdbctx->in_buf[1],
2352 gdbctx->in_packet_len, gdbctx->in_packet_len,
2353 gdbctx->in_packet);
2354 ret = (packet_entries[i].handler)(gdbctx);
2356 switch (ret & ~packet_last_f)
2358 case packet_error: packet_reply(gdbctx, "", 0); break;
2359 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2360 case packet_done: break;
2362 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2363 fprintf(stderr, "Reply-full: %*.*s\n",
2364 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2365 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2366 assert(i == gdbctx->out_len);
2367 /* if this fails, we'll have to use POLLOUT...
2369 gdbctx->out_len = 0;
2370 num_packet++;
2372 else
2374 /* FIXME: If we have more than one packet in our input buffer,
2375 * it's very likely that we took too long to answer to a given packet
2376 * and gdb is sending us the same packet again.
2377 * So we simply drop the second packet. This will lower the risk of error,
2378 * but there are still some race conditions here.
2379 * A better fix (yet not perfect) would be to have two threads:
2380 * - one managing the packets for gdb
2381 * - the second one managing the commands...
2382 * This would allow us to send the reply with the '+' character (Ack of
2383 * the command) way sooner than we do now.
2385 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2386 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2389 else
2391 write(gdbctx->sock, "+", 1);
2392 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2393 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2395 gdbctx->in_len -= plen + 4;
2396 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2398 return TRUE;
2401 static int fetch_data(struct gdb_context* gdbctx)
2403 int len, in_len = gdbctx->in_len;
2405 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2406 for (;;)
2408 #define STEP 128
2409 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2410 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2411 #undef STEP
2412 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2413 fprintf(stderr, "%d %d %*.*s\n",
2414 gdbctx->in_len, gdbctx->in_buf_alloc,
2415 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2416 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2417 if (len <= 0) break;
2418 gdbctx->in_len += len;
2419 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2420 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2422 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2423 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2424 return gdbctx->in_len - in_len;
2427 #define FLAG_NO_START 1
2428 #define FLAG_WITH_XTERM 2
2430 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2432 char buf[MAX_PATH];
2433 int fd;
2434 const char *gdb_path, *tmp_path;
2435 FILE* f;
2437 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2438 if (!(tmp_path = getenv("TMPDIR"))) tmp_path = "/tmp";
2439 strcpy(buf, tmp_path);
2440 strcat(buf, "/winegdb.XXXXXX");
2441 fd = mkstemps(buf, 0);
2442 if (fd == -1) return FALSE;
2443 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2444 fprintf(f, "file %s\n", wine_path);
2445 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2446 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2447 fprintf(f, "set prompt Wine-gdb>\\ \n");
2448 /* gdb 5.1 seems to require it, won't hurt anyway */
2449 fprintf(f, "sharedlibrary\n");
2450 /* This is needed (but not a decent & final fix)
2451 * Without this, gdb would skip our inter-DLL relay code (because
2452 * we don't have any line number information for the relay code)
2453 * With this, we will stop on first instruction of the stub, and
2454 * reusing step, will get us through the relay stub at the actual
2455 * function we're looking at.
2457 fprintf(f, "set step-mode on\n");
2458 /* tell gdb to delete this file when done handling it... */
2459 fprintf(f, "shell rm -f \"%s\"\n", buf);
2460 fclose(f);
2461 if (flags & FLAG_WITH_XTERM)
2462 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2463 else
2464 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2465 assert(0); /* never reached */
2466 return TRUE;
2469 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2471 int sock;
2472 struct sockaddr_in s_addrs;
2473 socklen_t s_len = sizeof(s_addrs);
2474 struct pollfd pollfd;
2475 IMAGEHLP_MODULE64 imh_mod;
2476 BOOL ret = FALSE;
2478 /* step 1: create socket for gdb connection request */
2479 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2481 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2482 fprintf(stderr, "Can't create socket");
2483 return FALSE;
2486 if (listen(sock, 1) == -1 || getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2487 goto cleanup;
2489 /* step 2: do the process internal creation */
2490 handle_debug_event(gdbctx, de);
2492 /* step3: get the wine loader name */
2493 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod))
2494 goto cleanup;
2496 /* step 4: fire up gdb (if requested) */
2497 if (flags & FLAG_NO_START)
2498 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2499 else
2500 switch (fork())
2502 case -1: /* error in parent... */
2503 fprintf(stderr, "Cannot create gdb\n");
2504 goto cleanup;
2505 default: /* in parent... success */
2506 signal(SIGINT, SIG_IGN);
2507 break;
2508 case 0: /* in child... and alive */
2509 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2510 /* if we're here, exec failed, so report failure */
2511 goto cleanup;
2514 /* step 5: wait for gdb to connect actually */
2515 pollfd.fd = sock;
2516 pollfd.events = POLLIN;
2517 pollfd.revents = 0;
2519 switch (poll(&pollfd, 1, -1))
2521 case 1:
2522 if (pollfd.revents & POLLIN)
2524 int dummy = 1;
2525 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2526 if (gdbctx->sock == -1)
2527 break;
2528 ret = TRUE;
2529 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2530 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2531 /* don't keep our small packets too long: send them ASAP back to GDB
2532 * without this, GDB really crawls
2534 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2536 break;
2537 case 0:
2538 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2539 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2540 break;
2541 case -1:
2542 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2543 fprintf(stderr, "Poll for cnx failed (error)\n");
2544 break;
2545 default:
2546 assert(0);
2549 cleanup:
2550 close(sock);
2551 return ret;
2554 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2556 DEBUG_EVENT de;
2557 int i;
2559 gdbctx->sock = -1;
2560 gdbctx->in_buf = NULL;
2561 gdbctx->in_buf_alloc = 0;
2562 gdbctx->in_len = 0;
2563 gdbctx->out_buf = NULL;
2564 gdbctx->out_buf_alloc = 0;
2565 gdbctx->out_len = 0;
2566 gdbctx->out_curr_packet = -1;
2568 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2569 gdbctx->last_sig = 0;
2570 gdbctx->in_trap = FALSE;
2571 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2572 gdbctx->process = NULL;
2573 for (i = 0; i < NUM_XPOINT; i++)
2574 gdbctx->Xpoints[i].type = -1;
2575 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2576 gdbctx->wine_segs[i] = 0;
2578 /* wait for first trap */
2579 while (WaitForDebugEvent(&de, INFINITE))
2581 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2583 /* this should be the first event we get,
2584 * and the only one of this type */
2585 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2586 /* gdbctx->dwProcessId = pid; */
2587 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2588 assert(!gdbctx->in_trap);
2590 else
2592 handle_debug_event(gdbctx, &de);
2593 if (gdbctx->in_trap) break;
2595 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2597 return TRUE;
2600 static int gdb_remote(unsigned flags)
2602 struct pollfd pollfd;
2603 struct gdb_context gdbctx;
2604 BOOL doLoop;
2606 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2608 pollfd.fd = gdbctx.sock;
2609 pollfd.events = POLLIN;
2610 pollfd.revents = 0;
2612 switch (poll(&pollfd, 1, -1))
2614 case 1:
2615 /* got something */
2616 if (pollfd.revents & (POLLHUP | POLLERR))
2618 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2619 fprintf(stderr, "Gdb hung up\n");
2620 /* kill also debuggee process - questionnable - */
2621 detach_debuggee(&gdbctx, TRUE);
2622 doLoop = FALSE;
2623 break;
2625 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2627 if (extract_packets(&gdbctx)) doLoop = FALSE;
2629 break;
2630 case 0:
2631 /* timeout, should never happen (infinite timeout) */
2632 break;
2633 case -1:
2634 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2635 fprintf(stderr, "Poll failed\n");
2636 doLoop = FALSE;
2637 break;
2640 wait(NULL);
2641 return 0;
2643 #endif
2645 int gdb_main(int argc, char* argv[])
2647 #ifdef HAVE_POLL
2648 unsigned gdb_flags = 0;
2650 argc--; argv++;
2651 while (argc > 0 && argv[0][0] == '-')
2653 if (strcmp(argv[0], "--no-start") == 0)
2655 gdb_flags |= FLAG_NO_START;
2656 argc--; argv++;
2657 continue;
2659 if (strcmp(argv[0], "--with-xterm") == 0)
2661 gdb_flags |= FLAG_WITH_XTERM;
2662 argc--; argv++;
2663 continue;
2665 return -1;
2667 if (dbg_active_attach(argc, argv) == start_ok ||
2668 dbg_active_launch(argc, argv) == start_ok)
2669 return gdb_remote(gdb_flags);
2670 #else
2671 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2672 #endif
2673 return -1;