msi: Avoid using awstring in MsiGetSourcePathW().
[wine.git] / programs / winedbg / gdbproxy.c
blob3909cb5cdc04a4e9aadc5df72b3ca218d0240e02
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) == be_xpoint_free 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(u.s.Fp, 8, CONTEXT_INTEGER),
499 REG(u.s.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 1: return *(BYTE*)cpu_register_ptr(ctx, idx);
521 case 2: return *(WORD*)cpu_register_ptr(ctx, idx);
522 case 4: return *(DWORD*)cpu_register_ptr(ctx, idx);
523 case 8: return *(DWORD64*)cpu_register_ptr(ctx, idx);
524 default:
525 fprintf(stderr, "got unexpected size: %u\n", (unsigned)cpu_register_map[idx].ctx_length);
526 assert(0);
527 return 0;
531 static inline void cpu_register_hex_from(CONTEXT* ctx, unsigned idx, const char** phex)
533 if (cpu_register_map[idx].gdb_length == cpu_register_map[idx].ctx_length)
534 hex_from(cpu_register_ptr(ctx, idx), *phex, cpu_register_map[idx].gdb_length);
535 else
537 DWORD64 val = 0;
538 unsigned i;
539 BYTE b;
541 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
543 hex_from(&b, *phex, 1);
544 *phex += 2;
545 val += (DWORD64)b << (8 * i);
547 switch (cpu_register_map[idx].ctx_length)
549 case 1: *(BYTE*)cpu_register_ptr(ctx, idx) = (BYTE)val; break;
550 case 2: *(WORD*)cpu_register_ptr(ctx, idx) = (WORD)val; break;
551 case 4: *(DWORD*)cpu_register_ptr(ctx, idx) = (DWORD)val; break;
552 case 8: *(DWORD64*)cpu_register_ptr(ctx, idx) = val; break;
553 default: assert(0);
558 /* =============================================== *
559 * W I N 3 2 D E B U G I N T E R F A C E *
560 * =============================================== *
563 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
565 ctx->ContextFlags = CONTEXT_CONTROL
566 | CONTEXT_INTEGER
567 #if defined(__powerpc__) || defined(__i386__) || defined(__x86_64__)
568 | CONTEXT_FLOATING_POINT
569 #endif
570 #ifdef CONTEXT_SEGMENTS
571 | CONTEXT_SEGMENTS
572 #endif
573 #ifdef CONTEXT_DEBUG_REGISTERS
574 | CONTEXT_DEBUG_REGISTERS
575 #endif
576 #ifdef CONTEXT_EXTENDED_REGISTERS
577 | CONTEXT_EXTENDED_REGISTERS
578 #endif
580 if (!GetThreadContext(h, ctx))
582 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
583 fprintf(stderr, "Can't get thread's context\n");
584 return FALSE;
586 return TRUE;
589 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
591 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
592 BOOL ret = FALSE;
594 switch (rec->ExceptionCode)
596 case EXCEPTION_ACCESS_VIOLATION:
597 case EXCEPTION_PRIV_INSTRUCTION:
598 case EXCEPTION_STACK_OVERFLOW:
599 case EXCEPTION_GUARD_PAGE:
600 gdbctx->last_sig = SIGSEGV;
601 ret = TRUE;
602 break;
603 case EXCEPTION_DATATYPE_MISALIGNMENT:
604 gdbctx->last_sig = SIGBUS;
605 ret = TRUE;
606 break;
607 case EXCEPTION_SINGLE_STEP:
608 /* fall through */
609 case EXCEPTION_BREAKPOINT:
610 gdbctx->last_sig = SIGTRAP;
611 ret = TRUE;
612 break;
613 case EXCEPTION_FLT_DENORMAL_OPERAND:
614 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
615 case EXCEPTION_FLT_INEXACT_RESULT:
616 case EXCEPTION_FLT_INVALID_OPERATION:
617 case EXCEPTION_FLT_OVERFLOW:
618 case EXCEPTION_FLT_STACK_CHECK:
619 case EXCEPTION_FLT_UNDERFLOW:
620 gdbctx->last_sig = SIGFPE;
621 ret = TRUE;
622 break;
623 case EXCEPTION_INT_DIVIDE_BY_ZERO:
624 case EXCEPTION_INT_OVERFLOW:
625 gdbctx->last_sig = SIGFPE;
626 ret = TRUE;
627 break;
628 case EXCEPTION_ILLEGAL_INSTRUCTION:
629 gdbctx->last_sig = SIGILL;
630 ret = TRUE;
631 break;
632 case CONTROL_C_EXIT:
633 gdbctx->last_sig = SIGINT;
634 ret = TRUE;
635 break;
636 case STATUS_POSSIBLE_DEADLOCK:
637 gdbctx->last_sig = SIGALRM;
638 ret = TRUE;
639 /* FIXME: we could also add here a O packet with additional information */
640 break;
641 default:
642 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
643 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
644 gdbctx->last_sig = SIGABRT;
645 ret = TRUE;
646 break;
648 return ret;
651 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
653 union {
654 char bufferA[256];
655 WCHAR buffer[256];
656 } u;
658 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
660 switch (de->dwDebugEventCode)
662 case CREATE_PROCESS_DEBUG_EVENT:
663 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
664 de->u.CreateProcessInfo.hProcess);
665 if (!gdbctx->process) break;
666 memory_get_string_indirect(gdbctx->process,
667 de->u.CreateProcessInfo.lpImageName,
668 de->u.CreateProcessInfo.fUnicode,
669 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
670 dbg_set_process_name(gdbctx->process, u.buffer);
672 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
673 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
674 de->dwProcessId, de->dwThreadId,
675 dbg_W2A(u.buffer, -1),
676 de->u.CreateProcessInfo.lpImageName,
677 de->u.CreateProcessInfo.lpStartAddress,
678 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
679 de->u.CreateProcessInfo.nDebugInfoSize);
681 /* de->u.CreateProcessInfo.lpStartAddress; */
682 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
683 fprintf(stderr, "Couldn't initiate DbgHelp\n");
685 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
686 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
687 de->dwProcessId, de->dwThreadId,
688 de->u.CreateProcessInfo.lpStartAddress);
690 assert(dbg_curr_thread == NULL); /* shouldn't be there */
691 dbg_add_thread(gdbctx->process, de->dwThreadId,
692 de->u.CreateProcessInfo.hThread,
693 de->u.CreateProcessInfo.lpThreadLocalBase);
694 break;
696 case LOAD_DLL_DEBUG_EVENT:
697 assert(dbg_curr_thread);
698 memory_get_string_indirect(gdbctx->process,
699 de->u.LoadDll.lpImageName,
700 de->u.LoadDll.fUnicode,
701 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
702 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
703 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
704 de->dwProcessId, de->dwThreadId,
705 dbg_W2A(u.buffer, -1),
706 de->u.LoadDll.lpBaseOfDll,
707 de->u.LoadDll.dwDebugInfoFileOffset,
708 de->u.LoadDll.nDebugInfoSize);
709 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
710 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
711 break;
713 case UNLOAD_DLL_DEBUG_EVENT:
714 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
715 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
716 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
717 SymUnloadModule(gdbctx->process->handle,
718 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
719 break;
721 case EXCEPTION_DEBUG_EVENT:
722 assert(dbg_curr_thread);
723 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
724 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
725 de->dwProcessId, de->dwThreadId,
726 de->u.Exception.ExceptionRecord.ExceptionCode);
728 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
730 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
732 break;
734 case CREATE_THREAD_DEBUG_EVENT:
735 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
736 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
737 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
739 dbg_add_thread(gdbctx->process,
740 de->dwThreadId,
741 de->u.CreateThread.hThread,
742 de->u.CreateThread.lpThreadLocalBase);
743 break;
745 case EXIT_THREAD_DEBUG_EVENT:
746 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
747 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
748 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
750 assert(dbg_curr_thread);
751 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
752 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
753 dbg_del_thread(dbg_curr_thread);
754 break;
756 case EXIT_PROCESS_DEBUG_EVENT:
757 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
758 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
759 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
761 dbg_del_process(gdbctx->process);
762 gdbctx->process = NULL;
763 /* now signal gdb that we're done */
764 gdbctx->last_sig = SIGTERM;
765 gdbctx->in_trap = TRUE;
766 break;
768 case OUTPUT_DEBUG_STRING_EVENT:
769 assert(dbg_curr_thread);
770 memory_get_string(gdbctx->process,
771 de->u.DebugString.lpDebugStringData, TRUE,
772 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
773 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
774 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
775 de->dwProcessId, de->dwThreadId, u.bufferA);
776 break;
778 case RIP_EVENT:
779 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
780 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
781 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
782 de->u.RipInfo.dwType);
783 break;
785 default:
786 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
787 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
788 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
792 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
794 if (dbg_curr_thread)
796 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
797 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
798 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
799 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
800 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
801 fprintf(stderr, "Cannot continue on %04x (%x)\n",
802 dbg_curr_thread->tid, cont);
804 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
805 fprintf(stderr, "Cannot find last thread\n");
809 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
812 if (dbg_curr_thread)
814 if(dbg_curr_thread->tid == threadid){
815 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
816 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
817 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
818 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
819 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
820 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
821 fprintf(stderr, "Cannot continue on %04x (%x)\n",
822 dbg_curr_thread->tid, cont);
825 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
826 fprintf(stderr, "Cannot find last thread\n");
829 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
831 struct pollfd pollfd;
832 int ret;
833 char pkt;
835 pollfd.fd = gdbctx->sock;
836 pollfd.events = POLLIN;
837 pollfd.revents = 0;
839 if ((ret = poll(&pollfd, 1, 0)) == 1) {
840 ret = read(gdbctx->sock, &pkt, 1);
841 if (ret != 1) {
842 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
843 fprintf(stderr, "read failed\n");
845 return FALSE;
847 if (pkt != '\003') {
848 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
849 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
851 return FALSE;
853 return TRUE;
854 } else if (ret == -1) {
855 fprintf(stderr, "poll failed\n");
857 return FALSE;
860 static void wait_for_debuggee(struct gdb_context* gdbctx)
862 DEBUG_EVENT de;
864 gdbctx->in_trap = FALSE;
865 for (;;)
867 if (!WaitForDebugEvent(&de, 10))
869 if (GetLastError() == ERROR_SEM_TIMEOUT)
871 if (check_for_interrupt(gdbctx)) {
872 if (!DebugBreakProcess(gdbctx->process->handle)) {
873 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
874 fprintf(stderr, "Failed to break into debugee\n");
876 break;
878 WaitForDebugEvent(&de, INFINITE);
879 } else {
880 continue;
882 } else {
883 break;
886 handle_debug_event(gdbctx, &de);
887 assert(!gdbctx->process ||
888 gdbctx->process->pid == 0 ||
889 de.dwProcessId == gdbctx->process->pid);
890 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
891 if (gdbctx->in_trap) break;
892 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
896 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
898 be_cpu->single_step(&gdbctx->context, FALSE);
899 resume_debuggee(gdbctx, DBG_CONTINUE);
900 if (!kill)
901 DebugActiveProcessStop(gdbctx->process->pid);
902 dbg_del_process(gdbctx->process);
903 gdbctx->process = NULL;
906 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
908 DWORD status;
910 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
912 strcpy(buffer, "Unknown process");
913 return;
915 if (status == STILL_ACTIVE)
917 strcpy(buffer, "Running");
919 else
920 snprintf(buffer, len, "Terminated (%u)", status);
922 switch (GetPriorityClass(gdbctx->process->handle))
924 case 0: break;
925 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
926 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
927 #endif
928 #ifdef BELOW_NORMAL_PRIORITY_CLASS
929 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
930 #endif
931 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
932 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
933 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
934 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
936 strcat(buffer, "\n");
939 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
940 char* buffer, size_t len)
942 struct dbg_thread* thd;
943 DWORD status;
944 int prio;
946 /* FIXME: use the size of buffer */
947 thd = dbg_get_thread(gdbctx->process, tid);
948 if (thd == NULL)
950 strcpy(buffer, "No information");
951 return;
953 if (GetExitCodeThread(thd->handle, &status))
955 if (status == STILL_ACTIVE)
957 /* FIXME: this is a bit brutal... some nicer way shall be found */
958 switch (status = SuspendThread(thd->handle))
960 case -1: break;
961 case 0: strcpy(buffer, "Running"); break;
962 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
964 ResumeThread(thd->handle);
966 else
967 snprintf(buffer, len, "Terminated (exit code = %u)", status);
969 else
971 strcpy(buffer, "Unknown threadID");
973 switch (prio = GetThreadPriority(thd->handle))
975 case THREAD_PRIORITY_ERROR_RETURN: break;
976 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
977 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
978 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
979 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
980 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
981 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
982 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
983 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
985 assert(strlen(buffer) < len);
988 /* =============================================== *
989 * P A C K E T U T I L S *
990 * =============================================== *
993 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
994 packet_last_f = 0x80};
996 static char* packet_realloc(char* buf, int size)
998 if (!buf)
999 return HeapAlloc(GetProcessHeap(), 0, size);
1000 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
1004 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
1006 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
1008 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
1009 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
1013 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
1015 packet_reply_grow(gdbctx, len * 2);
1016 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
1017 gdbctx->out_len += len * 2;
1020 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
1022 packet_reply_hex_to(gdbctx, src, strlen(src));
1025 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
1027 int i, shift;
1029 shift = (len - 1) * 8;
1030 packet_reply_grow(gdbctx, len * 2);
1031 for (i = 0; i < len; i++, shift -= 8)
1033 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
1034 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
1038 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
1040 packet_reply_grow(gdbctx, len);
1041 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
1042 gdbctx->out_len += len;
1045 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
1047 packet_reply_add(gdbctx, str, strlen(str));
1050 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
1052 packet_reply_add(gdbctx, &ch, 1);
1055 static void packet_reply_open(struct gdb_context* gdbctx)
1057 assert(gdbctx->out_curr_packet == -1);
1058 packet_reply_catc(gdbctx, '$');
1059 gdbctx->out_curr_packet = gdbctx->out_len;
1062 static void packet_reply_close(struct gdb_context* gdbctx)
1064 unsigned char cksum;
1065 int plen;
1067 plen = gdbctx->out_len - gdbctx->out_curr_packet;
1068 packet_reply_catc(gdbctx, '#');
1069 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
1070 packet_reply_hex_to(gdbctx, &cksum, 1);
1071 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1072 fprintf(stderr, "Reply : %*.*s\n",
1073 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
1074 gdbctx->out_curr_packet = -1;
1077 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
1079 packet_reply_open(gdbctx);
1081 if (len == -1) len = strlen(packet);
1082 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
1084 packet_reply_add(gdbctx, packet, len);
1086 packet_reply_close(gdbctx);
1088 return packet_done;
1091 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
1093 packet_reply_open(gdbctx);
1095 packet_reply_add(gdbctx, "E", 1);
1096 packet_reply_val(gdbctx, error, 1);
1098 packet_reply_close(gdbctx);
1100 return packet_done;
1103 static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, unsigned idx)
1105 if (cpu_register_map[idx].gdb_length == cpu_register_map[idx].ctx_length)
1106 packet_reply_hex_to(gdbctx, cpu_register_ptr(&gdbctx->context, idx), cpu_register_map[idx].gdb_length);
1107 else
1109 DWORD64 val = cpu_register(&gdbctx->context, idx);
1110 unsigned i;
1112 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
1114 BYTE b = val;
1115 packet_reply_hex_to(gdbctx, &b, 1);
1116 val >>= 8;
1121 /* =============================================== *
1122 * P A C K E T H A N D L E R S *
1123 * =============================================== *
1126 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
1128 enum packet_return ret = packet_done;
1130 packet_reply_open(gdbctx);
1132 if (gdbctx->process != NULL)
1134 unsigned char sig;
1135 unsigned i;
1137 packet_reply_catc(gdbctx, 'T');
1138 sig = gdbctx->last_sig;
1139 packet_reply_val(gdbctx, sig, 1);
1140 packet_reply_add(gdbctx, "thread:", 7);
1141 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
1142 packet_reply_catc(gdbctx, ';');
1144 for (i = 0; i < cpu_num_regs; i++)
1146 ULONG flags = cpu_register_map[i].ctx_flags;
1147 if ((gdbctx->context.ContextFlags & flags) != flags)
1148 break;
1150 /* FIXME: this call will also grow the buffer...
1151 * unneeded, but not harmful
1153 packet_reply_val(gdbctx, i, 1);
1154 packet_reply_catc(gdbctx, ':');
1155 packet_reply_register_hex_to(gdbctx, i);
1156 packet_reply_catc(gdbctx, ';');
1159 else
1161 /* Try to put an exit code
1162 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1163 * just indicate the end of process and exit */
1164 packet_reply_add(gdbctx, "W00", 3);
1165 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1168 packet_reply_close(gdbctx);
1170 return ret;
1173 #if 0
1174 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1176 gdbctx->extended = 1;
1177 return packet_ok;
1179 #endif
1181 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1183 assert(gdbctx->in_packet_len == 0);
1184 return packet_reply_status(gdbctx);
1187 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1189 /* FIXME: add support for address in packet */
1190 assert(gdbctx->in_packet_len == 0);
1191 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1192 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1193 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1194 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1195 resume_debuggee(gdbctx, DBG_CONTINUE);
1196 wait_for_debuggee(gdbctx);
1197 return packet_reply_status(gdbctx);
1200 static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
1202 int i;
1203 int defaultAction = -1; /* magic non action */
1204 unsigned char sig;
1205 int actions =0;
1206 int actionIndex[20]; /* allow for up to 20 actions */
1207 int threadIndex[20];
1208 int threadCount = 0;
1209 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1210 unsigned int threadID = 0;
1211 struct dbg_thread* thd;
1213 /* OK we have vCont followed by..
1214 * ? for query
1215 * c for packet_continue
1216 * Csig for packet_continue_signal
1217 * s for step
1218 * Ssig for step signal
1219 * and then an optional thread ID at the end..
1220 * *******************************************/
1222 /* Query */
1223 if (gdbctx->in_packet[4] == '?')
1226 Reply:
1227 `vCont[;action]...'
1228 The vCont packet is supported. Each action is a supported command in the vCont packet.
1230 The vCont packet is not supported. (this didn't seem to be obeyed!)
1232 packet_reply_open(gdbctx);
1233 packet_reply_add(gdbctx, "vCont", 5);
1234 /* add all the supported actions to the reply (all of them for now) */
1235 packet_reply_add(gdbctx, ";c", 2);
1236 packet_reply_add(gdbctx, ";C", 2);
1237 packet_reply_add(gdbctx, ";s", 2);
1238 packet_reply_add(gdbctx, ";S", 2);
1239 packet_reply_close(gdbctx);
1240 return packet_done;
1243 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1244 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1245 now if only gdb talked XML.... */
1246 #if 0 /* handy for debugging */
1247 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1248 #endif
1250 /* go through the packet and identify where all the actions start at */
1251 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1253 if (gdbctx->in_packet[i] == ';')
1255 threadIndex[actions] = 0;
1256 actionIndex[actions++] = i;
1258 else if (gdbctx->in_packet[i] == ':')
1260 threadIndex[actions - 1] = i;
1264 /* now look up the default action */
1265 for (i = 0 ; i < actions; i++)
1267 if (threadIndex[i] == 0)
1269 if (defaultAction != -1)
1271 fprintf(stderr,"Too many default actions specified\n");
1272 return packet_error;
1274 defaultAction = i;
1278 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1280 /* go through all the threads and stick their ids in the to be done list. */
1281 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1283 threadIDs[threadCount++] = thd->tid;
1284 /* check to see if we have more threads than I counted on, and tell the user what to do
1285 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1286 if (threadCount == 100)
1288 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1289 break;
1293 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1294 * that remains is to apply the actions to the threads and the default action to any threads
1295 * left */
1296 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1297 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1298 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1299 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1301 /* deal with the threaded stuff first */
1302 for (i = 0; i < actions ; i++)
1304 if (threadIndex[i] != 0)
1306 int j, idLength = 0;
1307 if (i < actions - 1)
1309 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1311 else
1313 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1316 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1317 /* process the action */
1318 switch (gdbctx->in_packet[actionIndex[i] + 1])
1320 case 's': /* step */
1321 be_cpu->single_step(&gdbctx->context, TRUE);
1322 /* fall through*/
1323 case 'c': /* continue */
1324 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1325 break;
1326 case 'S': /* step Sig, */
1327 be_cpu->single_step(&gdbctx->context, TRUE);
1328 /* fall through */
1329 case 'C': /* continue sig */
1330 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1331 /* cannot change signals on the fly */
1332 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1333 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1334 if (sig != gdbctx->last_sig)
1335 return packet_error;
1336 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1337 break;
1339 for (j = 0 ; j < threadCount; j++)
1341 if (threadIDs[j] == threadID)
1343 threadIDs[j] = 0;
1344 break;
1348 } /* for i=0 ; i< actions */
1350 /* now we have manage the default action */
1351 if (defaultAction >= 0)
1353 for (i = 0 ; i< threadCount; i++)
1355 /* check to see if we've already done something to the thread*/
1356 if (threadIDs[i] != 0)
1358 /* if not apply the default action*/
1359 threadID = threadIDs[i];
1360 /* process the action (yes this is almost identical to the one above!) */
1361 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1363 case 's': /* step */
1364 be_cpu->single_step(&gdbctx->context, TRUE);
1365 /* fall through */
1366 case 'c': /* continue */
1367 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1368 break;
1369 case 'S':
1370 be_cpu->single_step(&gdbctx->context, TRUE);
1371 /* fall through */
1372 case 'C': /* continue sig */
1373 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1374 /* cannot change signals on the fly */
1375 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1376 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1377 if (sig != gdbctx->last_sig)
1378 return packet_error;
1379 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1380 break;
1384 } /* if(defaultAction >=0) */
1386 wait_for_debuggee(gdbctx);
1387 be_cpu->single_step(&gdbctx->context, FALSE);
1388 return packet_reply_status(gdbctx);
1391 struct verbose_defail
1393 const char* name;
1394 unsigned len;
1395 enum packet_return (*handler)(struct gdb_context*);
1396 } verbose_details[] =
1398 /* {"Attach", 6}, */
1399 {"Cont", 4, packet_verbose_cont},
1400 /* {"File", 4},
1401 {"FlashErase", 10},
1402 {"FlashWrite", 10},
1403 {"FlashDone", 9},
1404 {"Kill", 4},
1405 {"Run", 3},
1406 {"Stopped", 7},*/
1409 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1411 unsigned i;
1412 unsigned klen;
1414 for (klen = 0; ; klen++)
1416 if (klen == gdbctx->in_packet_len ||
1417 gdbctx->in_packet[klen] == ';' ||
1418 gdbctx->in_packet[klen] == ':' ||
1419 gdbctx->in_packet[klen] == '?')
1421 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1422 fprintf(stderr, "trying to process a verbose packet %*.*s\n",
1423 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1424 for (i = 0; i < sizeof(verbose_details)/sizeof(verbose_details[0]); i++)
1426 if (klen == verbose_details[i].len &&
1427 !memcmp(gdbctx->in_packet, verbose_details[i].name, verbose_details[i].len))
1429 return verbose_details[i].handler(gdbctx);
1432 /* no matching handler found, abort */
1433 break;
1437 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1438 fprintf(stderr, "No support for verbose packet %*.*s\n",
1439 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1440 return packet_error;
1443 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1445 unsigned char sig;
1447 /* FIXME: add support for address in packet */
1448 assert(gdbctx->in_packet_len == 2);
1449 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1450 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1451 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1452 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1453 hex_from(&sig, gdbctx->in_packet, 1);
1454 /* cannot change signals on the fly */
1455 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1456 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1457 if (sig != gdbctx->last_sig)
1458 return packet_error;
1459 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1460 wait_for_debuggee(gdbctx);
1461 return packet_reply_status(gdbctx);
1464 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1466 detach_debuggee(gdbctx, FALSE);
1467 return packet_ok | packet_last_f;
1470 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1472 int i;
1473 CONTEXT ctx;
1475 assert(gdbctx->in_trap);
1477 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1479 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, &ctx))
1480 return packet_error;
1483 packet_reply_open(gdbctx);
1484 for (i = 0; i < cpu_num_regs; i++)
1486 ULONG flags = cpu_register_map[i].ctx_flags;
1487 if ((gdbctx->context.ContextFlags & flags) != flags)
1488 break;
1489 packet_reply_register_hex_to(gdbctx, i);
1491 packet_reply_close(gdbctx);
1492 return packet_done;
1495 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1497 unsigned i;
1498 CONTEXT ctx;
1499 CONTEXT* pctx = &gdbctx->context;
1500 const char* ptr;
1502 assert(gdbctx->in_trap);
1503 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1505 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1506 return packet_error;
1508 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1510 ptr = gdbctx->in_packet;
1511 for (i = 0; i < cpu_num_regs; i++)
1513 ULONG flags = cpu_register_map[i].ctx_flags;
1514 if ((pctx->ContextFlags & flags) != flags)
1515 break;
1516 cpu_register_hex_from(pctx, i, &ptr);
1518 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1520 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1521 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1522 return packet_error;
1524 return packet_ok;
1527 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1529 detach_debuggee(gdbctx, TRUE);
1530 #if 0
1531 if (!gdbctx->extended)
1532 /* dunno whether GDB cares or not */
1533 #endif
1534 wait(NULL);
1535 exit(0);
1536 /* assume we can't really answer something here */
1537 /* return packet_done; */
1540 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1542 char* end;
1543 unsigned thread;
1545 switch (gdbctx->in_packet[0])
1547 case 'c':
1548 case 'g':
1549 if (gdbctx->in_packet[1] == '-')
1550 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1551 else
1552 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1553 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1555 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1556 fprintf(stderr, "Cannot get threadid %*.*s\n",
1557 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1558 gdbctx->in_packet + 1);
1559 return packet_error;
1561 if (gdbctx->in_packet[0] == 'c')
1562 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1563 else
1564 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1565 return packet_ok;
1566 default:
1567 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1568 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1569 return packet_error;
1573 static BOOL read_memory(struct gdb_context *gdbctx, char *addr, char *buffer, SIZE_T blk_len, SIZE_T *r)
1575 /* Wrapper around process_io->read() that replaces values displaced by breakpoints. */
1577 BOOL ret;
1579 ret = gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, r);
1580 if (ret)
1582 struct gdb_ctx_Xpoint *xpt;
1584 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1586 char *xpt_addr = xpt->addr;
1588 if (xpt->type != be_xpoint_free && xpt_addr >= addr && xpt_addr < addr + blk_len)
1589 buffer[xpt_addr - addr] = xpt->val;
1592 return ret;
1595 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1597 char *addr;
1598 unsigned int len, blk_len, nread;
1599 char buffer[32];
1600 SIZE_T r = 0;
1602 assert(gdbctx->in_trap);
1603 /* FIXME:check in_packet_len for reading %p,%x */
1604 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1605 if (len <= 0) return packet_error;
1606 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1607 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1608 for (nread = 0; nread < len; nread += r, addr += r)
1610 blk_len = min(sizeof(buffer), len - nread);
1611 if (!read_memory(gdbctx, addr, buffer, blk_len, &r) || r == 0)
1613 /* fail at first address, return error */
1614 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1615 /* something has already been read, return partial information */
1616 break;
1618 if (nread == 0) packet_reply_open(gdbctx);
1619 packet_reply_hex_to(gdbctx, buffer, r);
1621 packet_reply_close(gdbctx);
1622 return packet_done;
1625 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1627 char* addr;
1628 unsigned int len, blk_len;
1629 char* ptr;
1630 char buffer[32];
1631 SIZE_T w;
1633 assert(gdbctx->in_trap);
1634 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1635 if (ptr == NULL)
1637 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1638 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1639 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1640 return packet_error;
1642 *ptr++ = '\0';
1644 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1646 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1647 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1648 return packet_error;
1650 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1652 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1653 fprintf(stderr, "Wrong sizes %u <> %u\n",
1654 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1655 return packet_error;
1657 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1658 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1659 while (len > 0)
1661 blk_len = min(sizeof(buffer), len);
1662 hex_from(buffer, ptr, blk_len);
1663 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1664 w != blk_len)
1665 break;
1666 addr += blk_len;
1667 len -= blk_len;
1668 ptr += blk_len;
1670 return packet_ok; /* FIXME: error while writing ? */
1673 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1675 unsigned reg;
1676 CONTEXT ctx;
1677 CONTEXT* pctx = &gdbctx->context;
1679 assert(gdbctx->in_trap);
1680 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1681 if (reg >= cpu_num_regs)
1683 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1684 fprintf(stderr, "Register out of bounds %x\n", reg);
1685 return packet_error;
1687 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1689 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1690 return packet_error;
1692 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1694 if (cpu_register_map[reg].ctx_length <= sizeof(DWORD64))
1695 fprintf(stderr, "Read register %x => %08x%08x\n", reg,
1696 (unsigned)(cpu_register(pctx, reg) >> 32), (unsigned)cpu_register(pctx, reg));
1697 else
1698 fprintf(stderr, "Read register %x\n", reg);
1700 packet_reply_open(gdbctx);
1701 packet_reply_register_hex_to(gdbctx, reg);
1702 packet_reply_close(gdbctx);
1703 return packet_done;
1706 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1708 unsigned reg;
1709 char* ptr;
1710 CONTEXT ctx;
1711 CONTEXT* pctx = &gdbctx->context;
1713 assert(gdbctx->in_trap);
1715 reg = strtoul(gdbctx->in_packet, &ptr, 16);
1716 if (ptr == NULL || reg >= cpu_num_regs || *ptr++ != '=')
1718 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1719 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1720 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1721 * it wouldn't matter too much, and it fakes our support for all regs
1723 return (ptr == NULL) ? packet_error : packet_ok;
1725 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1727 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1728 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
1731 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1733 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1734 return packet_error;
1736 if ((pctx->ContextFlags & cpu_register_map[reg].ctx_flags) != cpu_register_map[reg].ctx_flags)
1738 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1739 fprintf(stderr, "Writing reg %u is not supported on this host\n", reg);
1740 return packet_error;
1743 cpu_register_hex_from(pctx, reg, (const char**)&ptr);
1744 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1746 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1747 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1748 return packet_error;
1751 return packet_ok;
1754 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1756 char buffer[128];
1757 char clsName[128];
1758 char wndName[128];
1759 HWND child;
1761 do {
1762 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1763 strcpy(clsName, "-- Unknown --");
1764 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1765 strcpy(wndName, "-- Empty --");
1767 packet_reply_open(gdbctx);
1768 packet_reply_catc(gdbctx, 'O');
1769 snprintf(buffer, sizeof(buffer),
1770 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1771 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1772 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1773 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1774 wndName);
1775 packet_reply_hex_to_str(gdbctx, buffer);
1776 packet_reply_close(gdbctx);
1778 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1779 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1780 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1783 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1785 char buffer[128];
1787 /* we do the output in several 'O' packets, with the last one being just OK for
1788 * marking the end of the output */
1789 packet_reply_open(gdbctx);
1790 packet_reply_catc(gdbctx, 'O');
1791 snprintf(buffer, sizeof(buffer),
1792 "%-16.16s %-17.17s %-8.8s %s\n",
1793 "hwnd", "Class Name", " Style", " WndProc Text");
1794 packet_reply_hex_to_str(gdbctx, buffer);
1795 packet_reply_close(gdbctx);
1797 /* FIXME: could also add a pmt to this command in str... */
1798 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1799 packet_reply(gdbctx, "OK", 2);
1802 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1804 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1805 char buffer[31+MAX_PATH];
1806 char deco;
1807 PROCESSENTRY32 entry;
1808 BOOL ok;
1810 if (snap == INVALID_HANDLE_VALUE)
1811 return;
1813 entry.dwSize = sizeof(entry);
1814 ok = Process32First(snap, &entry);
1816 /* we do the output in several 'O' packets, with the last one being just OK for
1817 * marking the end of the output */
1819 packet_reply_open(gdbctx);
1820 packet_reply_catc(gdbctx, 'O');
1821 snprintf(buffer, sizeof(buffer),
1822 " %-8.8s %-8.8s %-8.8s %s\n",
1823 "pid", "threads", "parent", "executable");
1824 packet_reply_hex_to_str(gdbctx, buffer);
1825 packet_reply_close(gdbctx);
1827 while (ok)
1829 deco = ' ';
1830 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1831 packet_reply_open(gdbctx);
1832 packet_reply_catc(gdbctx, 'O');
1833 snprintf(buffer, sizeof(buffer),
1834 "%c%08x %-8d %08x '%s'\n",
1835 deco, entry.th32ProcessID, entry.cntThreads,
1836 entry.th32ParentProcessID, entry.szExeFile);
1837 packet_reply_hex_to_str(gdbctx, buffer);
1838 packet_reply_close(gdbctx);
1839 ok = Process32Next(snap, &entry);
1841 CloseHandle(snap);
1842 packet_reply(gdbctx, "OK", 2);
1845 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1847 MEMORY_BASIC_INFORMATION mbi;
1848 char* addr = 0;
1849 const char* state;
1850 const char* type;
1851 char prot[3+1];
1852 char buffer[128];
1854 /* we do the output in several 'O' packets, with the last one being just OK for
1855 * marking the end of the output */
1856 packet_reply_open(gdbctx);
1857 packet_reply_catc(gdbctx, 'O');
1858 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1859 packet_reply_close(gdbctx);
1861 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1863 switch (mbi.State)
1865 case MEM_COMMIT: state = "commit "; break;
1866 case MEM_FREE: state = "free "; break;
1867 case MEM_RESERVE: state = "reserve"; break;
1868 default: state = "??? "; break;
1870 if (mbi.State != MEM_FREE)
1872 switch (mbi.Type)
1874 case MEM_IMAGE: type = "image "; break;
1875 case MEM_MAPPED: type = "mapped "; break;
1876 case MEM_PRIVATE: type = "private"; break;
1877 case 0: type = " "; break;
1878 default: type = "??? "; break;
1880 memset(prot, ' ' , sizeof(prot)-1);
1881 prot[sizeof(prot)-1] = '\0';
1882 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1883 prot[0] = 'R';
1884 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1885 prot[1] = 'W';
1886 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1887 prot[1] = 'C';
1888 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1889 prot[2] = 'X';
1891 else
1893 type = "";
1894 prot[0] = '\0';
1896 packet_reply_open(gdbctx);
1897 snprintf(buffer, sizeof(buffer), "%0*lx %0*lx %s %s %s\n",
1898 (unsigned)sizeof(void*), (DWORD_PTR)addr,
1899 (unsigned)sizeof(void*), mbi.RegionSize, state, type, prot);
1900 packet_reply_catc(gdbctx, 'O');
1901 packet_reply_hex_to_str(gdbctx, buffer);
1902 packet_reply_close(gdbctx);
1904 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1905 break;
1906 addr += mbi.RegionSize;
1908 packet_reply(gdbctx, "OK", 2);
1911 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1912 int len, const char* str)
1914 char buffer[128];
1916 if (len == 0)
1918 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1920 else if (len >= 2 && str[0] == '=')
1922 unsigned val = atoi(&str[1]);
1923 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1924 gdbctx->trace = val;
1926 else
1928 /* FIXME: ugly but can use error packet here */
1929 packet_reply_cat(gdbctx, "E00");
1930 return;
1932 packet_reply_open(gdbctx);
1933 packet_reply_hex_to_str(gdbctx, buffer);
1934 packet_reply_close(gdbctx);
1937 struct query_detail
1939 int with_arg;
1940 const char* name;
1941 size_t len;
1942 void (*handler)(struct gdb_context*, int, const char*);
1943 } query_details[] =
1945 {0, "wnd", 3, packet_query_monitor_wnd},
1946 {0, "window", 6, packet_query_monitor_wnd},
1947 {0, "proc", 4, packet_query_monitor_process},
1948 {0, "process", 7, packet_query_monitor_process},
1949 {0, "mem", 3, packet_query_monitor_mem},
1950 {1, "trace", 5, packet_query_monitor_trace},
1951 {0, NULL, 0, NULL},
1954 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1955 const char* hxcmd, size_t len)
1957 char buffer[128];
1958 struct query_detail* qd;
1960 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1961 len /= 2;
1962 hex_from(buffer, hxcmd, len);
1964 for (qd = query_details; qd->name != NULL; qd++)
1966 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1967 if (!qd->with_arg && len != qd->len) continue;
1969 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1970 return packet_done;
1972 return packet_reply_error(gdbctx, EINVAL);
1975 static enum packet_return packet_query(struct gdb_context* gdbctx)
1977 switch (gdbctx->in_packet[0])
1979 case 'f':
1980 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1982 struct dbg_thread* thd;
1984 packet_reply_open(gdbctx);
1985 packet_reply_add(gdbctx, "m", 1);
1986 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1988 packet_reply_val(gdbctx, thd->tid, 4);
1989 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1990 packet_reply_add(gdbctx, ",", 1);
1992 packet_reply_close(gdbctx);
1993 return packet_done;
1995 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1997 char result[128];
1999 packet_reply_open(gdbctx);
2000 packet_reply_catc(gdbctx, 'O');
2001 get_process_info(gdbctx, result, sizeof(result));
2002 packet_reply_hex_to_str(gdbctx, result);
2003 packet_reply_close(gdbctx);
2004 return packet_done;
2006 break;
2007 case 's':
2008 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
2010 packet_reply(gdbctx, "l", 1);
2011 return packet_done;
2013 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
2015 packet_reply(gdbctx, "l", 1);
2016 return packet_done;
2018 break;
2019 case 'A':
2020 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
2022 char buf[2];
2024 buf[0] = '1';
2025 buf[1] = 0;
2026 return packet_reply(gdbctx, buf, -1);
2028 break;
2029 case 'C':
2030 if (gdbctx->in_packet_len == 1)
2032 struct dbg_thread* thd;
2033 /* FIXME: doc says 16 bit val ??? */
2034 /* grab first created thread, aka last in list */
2035 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
2036 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
2037 packet_reply_open(gdbctx);
2038 packet_reply_add(gdbctx, "QC", 2);
2039 packet_reply_val(gdbctx, thd->tid, 4);
2040 packet_reply_close(gdbctx);
2041 return packet_done;
2043 break;
2044 case 'O':
2045 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
2047 char buf[64];
2049 snprintf(buf, sizeof(buf),
2050 "Text=%08lx;Data=%08lx;Bss=%08lx",
2051 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
2052 gdbctx->wine_segs[2]);
2053 return packet_reply(gdbctx, buf, -1);
2055 break;
2056 case 'R':
2057 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
2059 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
2060 gdbctx->in_packet_len - 5);
2062 break;
2063 case 'S':
2064 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
2065 return packet_ok;
2066 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
2068 if (strlen(target_xml))
2069 return packet_reply(gdbctx, "PacketSize=400;qXfer:features:read+", -1);
2070 else
2072 /* no features supported */
2073 packet_reply_open(gdbctx);
2074 packet_reply_close(gdbctx);
2075 return packet_done;
2078 break;
2079 case 'T':
2080 if (gdbctx->in_packet_len > 15 &&
2081 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
2082 gdbctx->in_packet[15] == ',')
2084 unsigned tid;
2085 char* end;
2086 char result[128];
2088 tid = strtol(gdbctx->in_packet + 16, &end, 16);
2089 if (end == NULL) break;
2090 get_thread_info(gdbctx, tid, result, sizeof(result));
2091 packet_reply_open(gdbctx);
2092 packet_reply_hex_to_str(gdbctx, result);
2093 packet_reply_close(gdbctx);
2094 return packet_done;
2096 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
2098 /* Tracepoints not supported */
2099 packet_reply_open(gdbctx);
2100 packet_reply_close(gdbctx);
2101 return packet_done;
2103 break;
2104 case 'X':
2105 if (strlen(target_xml) && strncmp(gdbctx->in_packet, "Xfer:features:read:target.xml", 29) == 0)
2106 return packet_reply(gdbctx, target_xml, -1);
2107 break;
2109 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2110 fprintf(stderr, "Unknown or malformed query %*.*s\n",
2111 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
2112 return packet_error;
2115 static enum packet_return packet_step(struct gdb_context* gdbctx)
2117 /* FIXME: add support for address in packet */
2118 assert(gdbctx->in_packet_len == 0);
2119 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
2120 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
2121 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
2122 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
2123 be_cpu->single_step(&gdbctx->context, TRUE);
2124 resume_debuggee(gdbctx, DBG_CONTINUE);
2125 wait_for_debuggee(gdbctx);
2126 be_cpu->single_step(&gdbctx->context, FALSE);
2127 return packet_reply_status(gdbctx);
2130 #if 0
2131 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
2133 unsigned char sig;
2135 /* FIXME: add support for address in packet */
2136 assert(gdbctx->in_packet_len == 2);
2137 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
2138 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2139 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
2140 gdbctx->exec_thread, DEBUG_CurrThread->tid);
2141 hex_from(&sig, gdbctx->in_packet, 1);
2142 /* cannot change signals on the fly */
2143 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2144 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
2145 if (sig != gdbctx->last_sig)
2146 return packet_error;
2147 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
2148 wait_for_debuggee(gdbctx);
2149 return packet_reply_status(gdbctx);
2151 #endif
2153 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
2155 char* end;
2156 unsigned tid;
2158 tid = strtol(gdbctx->in_packet, &end, 16);
2159 if (tid == -1 || tid == 0)
2160 return packet_reply_error(gdbctx, EINVAL);
2161 if (dbg_get_thread(gdbctx->process, tid) != NULL)
2162 return packet_ok;
2163 return packet_reply_error(gdbctx, ESRCH);
2166 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
2168 void* addr;
2169 unsigned len;
2170 struct gdb_ctx_Xpoint* xpt;
2171 enum be_xpoint_type t;
2173 /* FIXME: check packet_len */
2174 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2175 gdbctx->in_packet[1] != ',' ||
2176 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2177 return packet_error;
2178 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2179 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
2180 addr, len, gdbctx->in_packet[0]);
2181 switch (gdbctx->in_packet[0])
2183 case '0': t = be_xpoint_break; len = 0; break;
2184 case '1': t = be_xpoint_watch_exec; break;
2185 case '2': t = be_xpoint_watch_read; break;
2186 case '3': t = be_xpoint_watch_write; break;
2187 default: return packet_error;
2189 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2191 if (xpt->addr == addr && xpt->type == t)
2193 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
2194 gdbctx->process->process_io, &gdbctx->context,
2195 t, xpt->addr, xpt->val, len))
2197 xpt->type = be_xpoint_free;
2198 return packet_ok;
2200 break;
2203 return packet_error;
2206 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
2208 void* addr;
2209 unsigned len;
2210 struct gdb_ctx_Xpoint* xpt;
2211 enum be_xpoint_type t;
2213 /* FIXME: check packet_len */
2214 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2215 gdbctx->in_packet[1] != ',' ||
2216 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2217 return packet_error;
2218 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2219 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
2220 addr, len, gdbctx->in_packet[0]);
2221 switch (gdbctx->in_packet[0])
2223 case '0': t = be_xpoint_break; len = 0; break;
2224 case '1': t = be_xpoint_watch_exec; break;
2225 case '2': t = be_xpoint_watch_read; break;
2226 case '3': t = be_xpoint_watch_write; break;
2227 default: return packet_error;
2229 /* because of packet command handling, this should be made idempotent */
2230 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2232 if (xpt->addr == addr && xpt->type == t)
2233 return packet_ok; /* nothing to do */
2235 /* really set the Xpoint */
2236 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2238 if (xpt->type == be_xpoint_free)
2240 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2241 gdbctx->process->process_io, &gdbctx->context,
2242 t, addr, &xpt->val, len))
2244 xpt->addr = addr;
2245 xpt->type = t;
2246 return packet_ok;
2248 fprintf(stderr, "cannot set xpoint\n");
2249 break;
2252 /* no more entries... eech */
2253 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2254 return packet_error;
2257 /* =============================================== *
2258 * P A C K E T I N F R A S T R U C T U R E *
2259 * =============================================== *
2262 struct packet_entry
2264 char key;
2265 enum packet_return (*handler)(struct gdb_context* gdbctx);
2268 static struct packet_entry packet_entries[] =
2270 /*{'!', packet_extended}, */
2271 {'?', packet_last_signal},
2272 {'c', packet_continue},
2273 {'C', packet_continue_signal},
2274 {'D', packet_detach},
2275 {'g', packet_read_registers},
2276 {'G', packet_write_registers},
2277 {'k', packet_kill},
2278 {'H', packet_thread},
2279 {'m', packet_read_memory},
2280 {'M', packet_write_memory},
2281 {'p', packet_read_register},
2282 {'P', packet_write_register},
2283 {'q', packet_query},
2284 /* {'Q', packet_set}, */
2285 /* {'R', packet,restart}, only in extended mode ! */
2286 {'s', packet_step},
2287 /*{'S', packet_step_signal}, hard(er) to implement */
2288 {'T', packet_thread_alive},
2289 {'v', packet_verbose},
2290 {'z', packet_remove_breakpoint},
2291 {'Z', packet_set_breakpoint},
2294 static BOOL extract_packets(struct gdb_context* gdbctx)
2296 char* end;
2297 int plen;
2298 unsigned char in_cksum, loc_cksum;
2299 char* ptr;
2300 enum packet_return ret = packet_error;
2301 int num_packet = 0;
2303 while ((ret & packet_last_f) == 0)
2305 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2306 fprintf(stderr, "In-buf: %*.*s\n",
2307 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2308 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2309 if (ptr == NULL) return FALSE;
2310 if (ptr != gdbctx->in_buf)
2312 int glen = ptr - gdbctx->in_buf; /* garbage len */
2313 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2314 fprintf(stderr, "Removing garbage: %*.*s\n",
2315 glen, glen, gdbctx->in_buf);
2316 gdbctx->in_len -= glen;
2317 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2319 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2320 if (end == NULL) return FALSE;
2321 /* no checksum yet */
2322 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2323 plen = end - gdbctx->in_buf - 1;
2324 hex_from(&in_cksum, end + 1, 1);
2325 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2326 if (loc_cksum == in_cksum)
2328 if (num_packet == 0) {
2329 int i;
2331 ret = packet_error;
2333 write(gdbctx->sock, "+", 1);
2334 assert(plen);
2336 /* FIXME: should use bsearch if packet_entries was sorted */
2337 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2339 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2341 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2343 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2344 fprintf(stderr, "Unknown packet request %*.*s\n",
2345 plen, plen, &gdbctx->in_buf[1]);
2347 else
2349 gdbctx->in_packet = gdbctx->in_buf + 2;
2350 gdbctx->in_packet_len = plen - 1;
2351 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2352 fprintf(stderr, "Packet: %c%*.*s\n",
2353 gdbctx->in_buf[1],
2354 gdbctx->in_packet_len, gdbctx->in_packet_len,
2355 gdbctx->in_packet);
2356 ret = (packet_entries[i].handler)(gdbctx);
2358 switch (ret & ~packet_last_f)
2360 case packet_error: packet_reply(gdbctx, "", 0); break;
2361 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2362 case packet_done: break;
2364 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2365 fprintf(stderr, "Reply-full: %*.*s\n",
2366 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2367 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2368 assert(i == gdbctx->out_len);
2369 /* if this fails, we'll have to use POLLOUT...
2371 gdbctx->out_len = 0;
2372 num_packet++;
2374 else
2376 /* FIXME: If we have more than one packet in our input buffer,
2377 * it's very likely that we took too long to answer to a given packet
2378 * and gdb is sending us the same packet again.
2379 * So we simply drop the second packet. This will lower the risk of error,
2380 * but there are still some race conditions here.
2381 * A better fix (yet not perfect) would be to have two threads:
2382 * - one managing the packets for gdb
2383 * - the second one managing the commands...
2384 * This would allow us to send the reply with the '+' character (Ack of
2385 * the command) way sooner than we do now.
2387 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2388 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2391 else
2393 write(gdbctx->sock, "+", 1);
2394 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2395 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2397 gdbctx->in_len -= plen + 4;
2398 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2400 return TRUE;
2403 static int fetch_data(struct gdb_context* gdbctx)
2405 int len, in_len = gdbctx->in_len;
2407 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2408 for (;;)
2410 #define STEP 128
2411 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2412 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2413 #undef STEP
2414 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2415 fprintf(stderr, "%d %d %*.*s\n",
2416 gdbctx->in_len, gdbctx->in_buf_alloc,
2417 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2418 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2419 if (len <= 0) break;
2420 gdbctx->in_len += len;
2421 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2422 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2424 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2425 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2426 return gdbctx->in_len - in_len;
2429 #define FLAG_NO_START 1
2430 #define FLAG_WITH_XTERM 2
2432 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2434 char buf[MAX_PATH];
2435 int fd;
2436 const char *gdb_path, *tmp_path;
2437 FILE* f;
2439 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2440 if (!(tmp_path = getenv("TMPDIR"))) tmp_path = "/tmp";
2441 strcpy(buf, tmp_path);
2442 strcat(buf, "/winegdb.XXXXXX");
2443 fd = mkstemps(buf, 0);
2444 if (fd == -1) return FALSE;
2445 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2446 fprintf(f, "file %s\n", wine_path);
2447 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2448 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2449 fprintf(f, "set prompt Wine-gdb>\\ \n");
2450 /* gdb 5.1 seems to require it, won't hurt anyway */
2451 fprintf(f, "sharedlibrary\n");
2452 /* This is needed (but not a decent & final fix)
2453 * Without this, gdb would skip our inter-DLL relay code (because
2454 * we don't have any line number information for the relay code)
2455 * With this, we will stop on first instruction of the stub, and
2456 * reusing step, will get us through the relay stub at the actual
2457 * function we're looking at.
2459 fprintf(f, "set step-mode on\n");
2460 /* tell gdb to delete this file when done handling it... */
2461 fprintf(f, "shell rm -f \"%s\"\n", buf);
2462 fclose(f);
2463 if (flags & FLAG_WITH_XTERM)
2464 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2465 else
2466 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2467 assert(0); /* never reached */
2468 return TRUE;
2471 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags, unsigned port)
2473 int sock;
2474 struct sockaddr_in s_addrs = {0};
2475 socklen_t s_len = sizeof(s_addrs);
2476 struct pollfd pollfd;
2477 IMAGEHLP_MODULE64 imh_mod;
2478 BOOL ret = FALSE;
2480 /* step 1: create socket for gdb connection request */
2481 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2483 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2484 fprintf(stderr, "Can't create socket");
2485 return FALSE;
2488 s_addrs.sin_family = AF_INET;
2489 s_addrs.sin_addr.s_addr = INADDR_ANY;
2490 s_addrs.sin_port = htons(port);
2491 if (bind(sock, (struct sockaddr *)&s_addrs, sizeof(s_addrs)) == -1)
2492 goto cleanup;
2494 if (listen(sock, 1) == -1 || getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2495 goto cleanup;
2497 /* step 2: do the process internal creation */
2498 handle_debug_event(gdbctx, de);
2500 /* step3: get the wine loader name */
2501 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod))
2502 goto cleanup;
2504 /* step 4: fire up gdb (if requested) */
2505 if (flags & FLAG_NO_START)
2506 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2507 else
2508 switch (fork())
2510 case -1: /* error in parent... */
2511 fprintf(stderr, "Cannot create gdb\n");
2512 goto cleanup;
2513 default: /* in parent... success */
2514 signal(SIGINT, SIG_IGN);
2515 break;
2516 case 0: /* in child... and alive */
2517 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2518 /* if we're here, exec failed, so report failure */
2519 goto cleanup;
2522 /* step 5: wait for gdb to connect actually */
2523 pollfd.fd = sock;
2524 pollfd.events = POLLIN;
2525 pollfd.revents = 0;
2527 switch (poll(&pollfd, 1, -1))
2529 case 1:
2530 if (pollfd.revents & POLLIN)
2532 int dummy = 1;
2533 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2534 if (gdbctx->sock == -1)
2535 break;
2536 ret = TRUE;
2537 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2538 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2539 /* don't keep our small packets too long: send them ASAP back to GDB
2540 * without this, GDB really crawls
2542 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2544 break;
2545 case 0:
2546 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2547 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2548 break;
2549 case -1:
2550 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2551 fprintf(stderr, "Poll for cnx failed (error)\n");
2552 break;
2553 default:
2554 assert(0);
2557 cleanup:
2558 close(sock);
2559 return ret;
2562 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigned port)
2564 DEBUG_EVENT de;
2565 int i;
2567 gdbctx->sock = -1;
2568 gdbctx->in_buf = NULL;
2569 gdbctx->in_buf_alloc = 0;
2570 gdbctx->in_len = 0;
2571 gdbctx->out_buf = NULL;
2572 gdbctx->out_buf_alloc = 0;
2573 gdbctx->out_len = 0;
2574 gdbctx->out_curr_packet = -1;
2576 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2577 gdbctx->last_sig = 0;
2578 gdbctx->in_trap = FALSE;
2579 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2580 gdbctx->process = NULL;
2581 for (i = 0; i < NUM_XPOINT; i++)
2582 gdbctx->Xpoints[i].type = -1;
2583 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2584 gdbctx->wine_segs[i] = 0;
2586 /* wait for first trap */
2587 while (WaitForDebugEvent(&de, INFINITE))
2589 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2591 /* this should be the first event we get,
2592 * and the only one of this type */
2593 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2594 /* gdbctx->dwProcessId = pid; */
2595 if (!gdb_startup(gdbctx, &de, flags, port)) return FALSE;
2596 assert(!gdbctx->in_trap);
2598 else
2600 handle_debug_event(gdbctx, &de);
2601 if (gdbctx->in_trap) break;
2603 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2605 return TRUE;
2608 static int gdb_remote(unsigned flags, unsigned port)
2610 struct pollfd pollfd;
2611 struct gdb_context gdbctx;
2612 BOOL doLoop;
2614 for (doLoop = gdb_init_context(&gdbctx, flags, port); doLoop;)
2616 pollfd.fd = gdbctx.sock;
2617 pollfd.events = POLLIN;
2618 pollfd.revents = 0;
2620 switch (poll(&pollfd, 1, -1))
2622 case 1:
2623 /* got something */
2624 if (pollfd.revents & (POLLHUP | POLLERR))
2626 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2627 fprintf(stderr, "Gdb hung up\n");
2628 /* kill also debuggee process - questionnable - */
2629 detach_debuggee(&gdbctx, TRUE);
2630 doLoop = FALSE;
2631 break;
2633 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2635 if (extract_packets(&gdbctx)) doLoop = FALSE;
2637 break;
2638 case 0:
2639 /* timeout, should never happen (infinite timeout) */
2640 break;
2641 case -1:
2642 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2643 fprintf(stderr, "Poll failed\n");
2644 doLoop = FALSE;
2645 break;
2648 wait(NULL);
2649 return 0;
2651 #endif
2653 int gdb_main(int argc, char* argv[])
2655 #ifdef HAVE_POLL
2656 unsigned gdb_flags = 0, port = 0;
2657 char *port_end;
2659 argc--; argv++;
2660 while (argc > 0 && argv[0][0] == '-')
2662 if (strcmp(argv[0], "--no-start") == 0)
2664 gdb_flags |= FLAG_NO_START;
2665 argc--; argv++;
2666 continue;
2668 if (strcmp(argv[0], "--with-xterm") == 0)
2670 gdb_flags |= FLAG_WITH_XTERM;
2671 argc--; argv++;
2672 continue;
2674 if (strcmp(argv[0], "--port") == 0 && argc > 1)
2676 port = strtoul(argv[1], &port_end, 10);
2677 if (*port_end)
2679 fprintf(stderr, "Invalid port: %s\n", argv[1]);
2680 return -1;
2682 argc -= 2; argv += 2;
2683 continue;
2685 return -1;
2687 if (dbg_active_attach(argc, argv) == start_ok ||
2688 dbg_active_launch(argc, argv) == start_ok)
2689 return gdb_remote(gdb_flags, port);
2690 #else
2691 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2692 #endif
2693 return -1;