winedbg: Remove dead variable (Clang).
[wine/multimedia.git] / programs / winedbg / gdbproxy.c
blob7f0a8c9553b80a704b067a2f75ae13192c30cd0a
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 static const char target_xml[] = "";
218 static struct cpu_register cpu_register_map[] = {
219 REG(Eax, 4, CONTEXT_INTEGER),
220 REG(Ecx, 4, CONTEXT_INTEGER),
221 REG(Edx, 4, CONTEXT_INTEGER),
222 REG(Ebx, 4, CONTEXT_INTEGER),
223 REG(Esp, 4, CONTEXT_CONTROL),
224 REG(Ebp, 4, CONTEXT_CONTROL),
225 REG(Esi, 4, CONTEXT_INTEGER),
226 REG(Edi, 4, CONTEXT_INTEGER),
227 REG(Eip, 4, CONTEXT_CONTROL),
228 REG(EFlags, 4, CONTEXT_CONTROL),
229 REG(SegCs, 4, CONTEXT_CONTROL),
230 REG(SegSs, 4, CONTEXT_SEGMENTS),
231 REG(SegDs, 4, CONTEXT_SEGMENTS),
232 REG(SegEs, 4, CONTEXT_SEGMENTS),
233 REG(SegFs, 4, CONTEXT_SEGMENTS),
234 REG(SegGs, 4, CONTEXT_SEGMENTS),
235 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[ 0]), 10, 10, CONTEXT_FLOATING_POINT },
236 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[10]), 10, 10, CONTEXT_FLOATING_POINT },
237 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[20]), 10, 10, CONTEXT_FLOATING_POINT },
238 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[30]), 10, 10, CONTEXT_FLOATING_POINT },
239 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[40]), 10, 10, CONTEXT_FLOATING_POINT },
240 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[50]), 10, 10, CONTEXT_FLOATING_POINT },
241 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[60]), 10, 10, CONTEXT_FLOATING_POINT },
242 { FIELD_OFFSET(CONTEXT, FloatSave.RegisterArea[70]), 10, 10, CONTEXT_FLOATING_POINT },
243 { FIELD_OFFSET(CONTEXT, FloatSave.ControlWord), 2, 4, CONTEXT_FLOATING_POINT },
244 { FIELD_OFFSET(CONTEXT, FloatSave.StatusWord), 2, 4, CONTEXT_FLOATING_POINT },
245 { FIELD_OFFSET(CONTEXT, FloatSave.TagWord), 2, 4, CONTEXT_FLOATING_POINT },
246 { FIELD_OFFSET(CONTEXT, FloatSave.ErrorSelector), 2, 4, CONTEXT_FLOATING_POINT },
247 REG(FloatSave.ErrorOffset, 4, CONTEXT_FLOATING_POINT ),
248 { FIELD_OFFSET(CONTEXT, FloatSave.DataSelector), 2, 4, CONTEXT_FLOATING_POINT },
249 REG(FloatSave.DataOffset, 4, CONTEXT_FLOATING_POINT ),
250 { FIELD_OFFSET(CONTEXT, FloatSave.ErrorSelector)+2, 2, 4, CONTEXT_FLOATING_POINT },
252 #elif defined(__powerpc__)
253 static const char target_xml[] = "";
254 static struct cpu_register cpu_register_map[] = {
255 REG(Gpr0, 4, CONTEXT_INTEGER),
256 REG(Gpr1, 4, CONTEXT_INTEGER),
257 REG(Gpr2, 4, CONTEXT_INTEGER),
258 REG(Gpr3, 4, CONTEXT_INTEGER),
259 REG(Gpr4, 4, CONTEXT_INTEGER),
260 REG(Gpr5, 4, CONTEXT_INTEGER),
261 REG(Gpr6, 4, CONTEXT_INTEGER),
262 REG(Gpr7, 4, CONTEXT_INTEGER),
263 REG(Gpr8, 4, CONTEXT_INTEGER),
264 REG(Gpr9, 4, CONTEXT_INTEGER),
265 REG(Gpr10, 4, CONTEXT_INTEGER),
266 REG(Gpr11, 4, CONTEXT_INTEGER),
267 REG(Gpr12, 4, CONTEXT_INTEGER),
268 REG(Gpr13, 4, CONTEXT_INTEGER),
269 REG(Gpr14, 4, CONTEXT_INTEGER),
270 REG(Gpr15, 4, CONTEXT_INTEGER),
271 REG(Gpr16, 4, CONTEXT_INTEGER),
272 REG(Gpr17, 4, CONTEXT_INTEGER),
273 REG(Gpr18, 4, CONTEXT_INTEGER),
274 REG(Gpr19, 4, CONTEXT_INTEGER),
275 REG(Gpr20, 4, CONTEXT_INTEGER),
276 REG(Gpr21, 4, CONTEXT_INTEGER),
277 REG(Gpr22, 4, CONTEXT_INTEGER),
278 REG(Gpr23, 4, CONTEXT_INTEGER),
279 REG(Gpr24, 4, CONTEXT_INTEGER),
280 REG(Gpr25, 4, CONTEXT_INTEGER),
281 REG(Gpr26, 4, CONTEXT_INTEGER),
282 REG(Gpr27, 4, CONTEXT_INTEGER),
283 REG(Gpr28, 4, CONTEXT_INTEGER),
284 REG(Gpr29, 4, CONTEXT_INTEGER),
285 REG(Gpr30, 4, CONTEXT_INTEGER),
286 REG(Gpr31, 4, CONTEXT_INTEGER),
287 REG(Fpr0, 4, CONTEXT_FLOATING_POINT),
288 REG(Fpr1, 4, CONTEXT_FLOATING_POINT),
289 REG(Fpr2, 4, CONTEXT_FLOATING_POINT),
290 REG(Fpr3, 4, CONTEXT_FLOATING_POINT),
291 REG(Fpr4, 4, CONTEXT_FLOATING_POINT),
292 REG(Fpr5, 4, CONTEXT_FLOATING_POINT),
293 REG(Fpr6, 4, CONTEXT_FLOATING_POINT),
294 REG(Fpr7, 4, CONTEXT_FLOATING_POINT),
295 REG(Fpr8, 4, CONTEXT_FLOATING_POINT),
296 REG(Fpr9, 4, CONTEXT_FLOATING_POINT),
297 REG(Fpr10, 4, CONTEXT_FLOATING_POINT),
298 REG(Fpr11, 4, CONTEXT_FLOATING_POINT),
299 REG(Fpr12, 4, CONTEXT_FLOATING_POINT),
300 REG(Fpr13, 4, CONTEXT_FLOATING_POINT),
301 REG(Fpr14, 4, CONTEXT_FLOATING_POINT),
302 REG(Fpr15, 4, CONTEXT_FLOATING_POINT),
303 REG(Fpr16, 4, CONTEXT_FLOATING_POINT),
304 REG(Fpr17, 4, CONTEXT_FLOATING_POINT),
305 REG(Fpr18, 4, CONTEXT_FLOATING_POINT),
306 REG(Fpr19, 4, CONTEXT_FLOATING_POINT),
307 REG(Fpr20, 4, CONTEXT_FLOATING_POINT),
308 REG(Fpr21, 4, CONTEXT_FLOATING_POINT),
309 REG(Fpr22, 4, CONTEXT_FLOATING_POINT),
310 REG(Fpr23, 4, CONTEXT_FLOATING_POINT),
311 REG(Fpr24, 4, CONTEXT_FLOATING_POINT),
312 REG(Fpr25, 4, CONTEXT_FLOATING_POINT),
313 REG(Fpr26, 4, CONTEXT_FLOATING_POINT),
314 REG(Fpr27, 4, CONTEXT_FLOATING_POINT),
315 REG(Fpr28, 4, CONTEXT_FLOATING_POINT),
316 REG(Fpr29, 4, CONTEXT_FLOATING_POINT),
317 REG(Fpr30, 4, CONTEXT_FLOATING_POINT),
318 REG(Fpr31, 4, CONTEXT_FLOATING_POINT),
320 REG(Iar, 4, CONTEXT_CONTROL),
321 REG(Msr, 4, CONTEXT_CONTROL),
322 REG(Cr, 4, CONTEXT_INTEGER),
323 REG(Lr, 4, CONTEXT_CONTROL),
324 REG(Ctr, 4, CONTEXT_CONTROL),
325 REG(Xer, 4, CONTEXT_INTEGER),
326 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
327 /* see gdb/nlm/ppc.c */
329 #elif defined(__x86_64__)
330 static const char target_xml[] = "";
331 static struct cpu_register cpu_register_map[] = {
332 REG(Rax, 8, CONTEXT_INTEGER),
333 REG(Rbx, 8, CONTEXT_INTEGER),
334 REG(Rcx, 8, CONTEXT_INTEGER),
335 REG(Rdx, 8, CONTEXT_INTEGER),
336 REG(Rsi, 8, CONTEXT_INTEGER),
337 REG(Rdi, 8, CONTEXT_INTEGER),
338 REG(Rbp, 8, CONTEXT_INTEGER),
339 REG(Rsp, 8, CONTEXT_INTEGER),
340 REG(R8, 8, CONTEXT_INTEGER),
341 REG(R9, 8, CONTEXT_INTEGER),
342 REG(R10, 8, CONTEXT_INTEGER),
343 REG(R11, 8, CONTEXT_INTEGER),
344 REG(R12, 8, CONTEXT_INTEGER),
345 REG(R13, 8, CONTEXT_INTEGER),
346 REG(R14, 8, CONTEXT_INTEGER),
347 REG(R15, 8, CONTEXT_INTEGER),
348 REG(Rip, 8, CONTEXT_CONTROL),
349 REG(EFlags, 4, CONTEXT_CONTROL),
350 REG(SegCs, 4, CONTEXT_CONTROL),
351 REG(SegSs, 4, CONTEXT_CONTROL),
352 REG(SegDs, 4, CONTEXT_SEGMENTS),
353 REG(SegEs, 4, CONTEXT_SEGMENTS),
354 REG(SegFs, 4, CONTEXT_SEGMENTS),
355 REG(SegGs, 4, CONTEXT_SEGMENTS),
357 #elif defined(__arm__)
358 static const char target_xml[] =
359 "l <target><architecture>arm</architecture>\n"
360 "<feature name=\"org.gnu.gdb.arm.core\">\n"
361 " <reg name=\"r0\" bitsize=\"32\" type=\"uint32\"/>\n"
362 " <reg name=\"r1\" bitsize=\"32\" type=\"uint32\"/>\n"
363 " <reg name=\"r2\" bitsize=\"32\" type=\"uint32\"/>\n"
364 " <reg name=\"r3\" bitsize=\"32\" type=\"uint32\"/>\n"
365 " <reg name=\"r4\" bitsize=\"32\" type=\"uint32\"/>\n"
366 " <reg name=\"r5\" bitsize=\"32\" type=\"uint32\"/>\n"
367 " <reg name=\"r6\" bitsize=\"32\" type=\"uint32\"/>\n"
368 " <reg name=\"r7\" bitsize=\"32\" type=\"uint32\"/>\n"
369 " <reg name=\"r8\" bitsize=\"32\" type=\"uint32\"/>\n"
370 " <reg name=\"r9\" bitsize=\"32\" type=\"uint32\"/>\n"
371 " <reg name=\"r10\" bitsize=\"32\" type=\"uint32\"/>\n"
372 " <reg name=\"r11\" bitsize=\"32\" type=\"uint32\"/>\n"
373 " <reg name=\"r12\" bitsize=\"32\" type=\"uint32\"/>\n"
374 " <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n"
375 " <reg name=\"lr\" bitsize=\"32\"/>\n"
376 " <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n"
377 " <reg name=\"cpsr\" bitsize=\"32\"/>\n"
378 "</feature></target>\n";
380 static struct cpu_register cpu_register_map[] = {
381 REG(R0, 4, CONTEXT_INTEGER),
382 REG(R1, 4, CONTEXT_INTEGER),
383 REG(R2, 4, CONTEXT_INTEGER),
384 REG(R3, 4, CONTEXT_INTEGER),
385 REG(R4, 4, CONTEXT_INTEGER),
386 REG(R5, 4, CONTEXT_INTEGER),
387 REG(R6, 4, CONTEXT_INTEGER),
388 REG(R7, 4, CONTEXT_INTEGER),
389 REG(R8, 4, CONTEXT_INTEGER),
390 REG(R9, 4, CONTEXT_INTEGER),
391 REG(R10, 4, CONTEXT_INTEGER),
392 REG(Fp, 4, CONTEXT_INTEGER),
393 REG(Ip, 4, CONTEXT_INTEGER),
394 REG(Sp, 4, CONTEXT_CONTROL),
395 REG(Lr, 4, CONTEXT_CONTROL),
396 REG(Pc, 4, CONTEXT_CONTROL),
397 REG(Cpsr, 4, CONTEXT_CONTROL),
399 #elif defined(__aarch64__)
400 static const char target_xml[] = "";
401 static struct cpu_register cpu_register_map[] = {
402 REG(Cpsr, 4, CONTEXT_CONTROL),
403 REG(X0, 8, CONTEXT_INTEGER),
404 REG(X1, 8, CONTEXT_INTEGER),
405 REG(X2, 8, CONTEXT_INTEGER),
406 REG(X3, 8, CONTEXT_INTEGER),
407 REG(X4, 8, CONTEXT_INTEGER),
408 REG(X5, 8, CONTEXT_INTEGER),
409 REG(X6, 8, CONTEXT_INTEGER),
410 REG(X7, 8, CONTEXT_INTEGER),
411 REG(X8, 8, CONTEXT_INTEGER),
412 REG(X9, 8, CONTEXT_INTEGER),
413 REG(X10, 8, CONTEXT_INTEGER),
414 REG(X11, 8, CONTEXT_INTEGER),
415 REG(X12, 8, CONTEXT_INTEGER),
416 REG(X13, 8, CONTEXT_INTEGER),
417 REG(X14, 8, CONTEXT_INTEGER),
418 REG(X15, 8, CONTEXT_INTEGER),
419 REG(X16, 8, CONTEXT_INTEGER),
420 REG(X17, 8, CONTEXT_INTEGER),
421 REG(X18, 8, CONTEXT_INTEGER),
422 REG(X19, 8, CONTEXT_INTEGER),
423 REG(X20, 8, CONTEXT_INTEGER),
424 REG(X21, 8, CONTEXT_INTEGER),
425 REG(X22, 8, CONTEXT_INTEGER),
426 REG(X23, 8, CONTEXT_INTEGER),
427 REG(X24, 8, CONTEXT_INTEGER),
428 REG(X25, 8, CONTEXT_INTEGER),
429 REG(X26, 8, CONTEXT_INTEGER),
430 REG(X27, 8, CONTEXT_INTEGER),
431 REG(X28, 8, CONTEXT_INTEGER),
432 REG(Fp, 8, CONTEXT_INTEGER),
433 REG(Lr, 8, CONTEXT_INTEGER),
434 REG(Sp, 8, CONTEXT_CONTROL),
435 REG(Pc, 8, CONTEXT_CONTROL),
437 #else
438 # error Define the registers map for your CPU
439 #endif
440 #undef REG
442 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
444 static inline void* cpu_register_ptr(CONTEXT* ctx, unsigned idx)
446 assert(idx < cpu_num_regs);
447 return (char*)ctx + cpu_register_map[idx].ctx_offset;
450 static inline DWORD64 cpu_register(CONTEXT* ctx, unsigned idx)
452 switch (cpu_register_map[idx].ctx_length)
454 case 2: return *(WORD*)cpu_register_ptr(ctx, idx);
455 case 4: return *(DWORD*)cpu_register_ptr(ctx, idx);
456 case 8: return *(DWORD64*)cpu_register_ptr(ctx, idx);
457 default:
458 fprintf(stderr, "got unexpected size: %u\n", (unsigned)cpu_register_map[idx].ctx_length);
459 assert(0);
460 return 0;
464 static inline void cpu_register_hex_from(CONTEXT* ctx, unsigned idx, const char** phex)
466 if (cpu_register_map[idx].gdb_length == cpu_register_map[idx].ctx_length)
467 hex_from(cpu_register_ptr(ctx, idx), *phex, cpu_register_map[idx].gdb_length);
468 else
470 DWORD64 val = 0;
471 unsigned i;
472 BYTE b;
474 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
476 hex_from(&b, *phex, 1);
477 *phex += 2;
478 val += (DWORD64)b << (8 * i);
480 switch (cpu_register_map[idx].ctx_length)
482 case 2: *(WORD*)cpu_register_ptr(ctx, idx) = (WORD)val; break;
483 case 4: *(DWORD*)cpu_register_ptr(ctx, idx) = (DWORD)val; break;
484 case 8: *(DWORD64*)cpu_register_ptr(ctx, idx) = val; break;
485 default: assert(0);
490 /* =============================================== *
491 * W I N 3 2 D E B U G I N T E R F A C E *
492 * =============================================== *
495 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
497 ctx->ContextFlags = CONTEXT_CONTROL
498 | CONTEXT_INTEGER
499 #if defined(__powerpc__) || defined(__i386__)
500 | CONTEXT_FLOATING_POINT
501 #endif
502 #ifdef CONTEXT_SEGMENTS
503 | CONTEXT_SEGMENTS
504 #endif
505 #ifdef CONTEXT_DEBUG_REGISTERS
506 | CONTEXT_DEBUG_REGISTERS
507 #endif
509 if (!GetThreadContext(h, ctx))
511 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
512 fprintf(stderr, "Can't get thread's context\n");
513 return FALSE;
515 return TRUE;
518 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
520 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
521 BOOL ret = FALSE;
523 switch (rec->ExceptionCode)
525 case EXCEPTION_ACCESS_VIOLATION:
526 case EXCEPTION_PRIV_INSTRUCTION:
527 case EXCEPTION_STACK_OVERFLOW:
528 case EXCEPTION_GUARD_PAGE:
529 gdbctx->last_sig = SIGSEGV;
530 ret = TRUE;
531 break;
532 case EXCEPTION_DATATYPE_MISALIGNMENT:
533 gdbctx->last_sig = SIGBUS;
534 ret = TRUE;
535 break;
536 case EXCEPTION_SINGLE_STEP:
537 /* fall through */
538 case EXCEPTION_BREAKPOINT:
539 gdbctx->last_sig = SIGTRAP;
540 ret = TRUE;
541 break;
542 case EXCEPTION_FLT_DENORMAL_OPERAND:
543 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
544 case EXCEPTION_FLT_INEXACT_RESULT:
545 case EXCEPTION_FLT_INVALID_OPERATION:
546 case EXCEPTION_FLT_OVERFLOW:
547 case EXCEPTION_FLT_STACK_CHECK:
548 case EXCEPTION_FLT_UNDERFLOW:
549 gdbctx->last_sig = SIGFPE;
550 ret = TRUE;
551 break;
552 case EXCEPTION_INT_DIVIDE_BY_ZERO:
553 case EXCEPTION_INT_OVERFLOW:
554 gdbctx->last_sig = SIGFPE;
555 ret = TRUE;
556 break;
557 case EXCEPTION_ILLEGAL_INSTRUCTION:
558 gdbctx->last_sig = SIGILL;
559 ret = TRUE;
560 break;
561 case CONTROL_C_EXIT:
562 gdbctx->last_sig = SIGINT;
563 ret = TRUE;
564 break;
565 case STATUS_POSSIBLE_DEADLOCK:
566 gdbctx->last_sig = SIGALRM;
567 ret = TRUE;
568 /* FIXME: we could also add here a O packet with additional information */
569 break;
570 default:
571 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
572 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
573 gdbctx->last_sig = SIGABRT;
574 ret = TRUE;
575 break;
577 return ret;
580 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
582 union {
583 char bufferA[256];
584 WCHAR buffer[256];
585 } u;
587 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
589 switch (de->dwDebugEventCode)
591 case CREATE_PROCESS_DEBUG_EVENT:
592 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
593 de->u.CreateProcessInfo.hProcess);
594 if (!gdbctx->process) break;
595 memory_get_string_indirect(gdbctx->process,
596 de->u.CreateProcessInfo.lpImageName,
597 de->u.CreateProcessInfo.fUnicode,
598 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
599 dbg_set_process_name(gdbctx->process, u.buffer);
601 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
602 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
603 de->dwProcessId, de->dwThreadId,
604 dbg_W2A(u.buffer, -1),
605 de->u.CreateProcessInfo.lpImageName,
606 de->u.CreateProcessInfo.lpStartAddress,
607 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
608 de->u.CreateProcessInfo.nDebugInfoSize);
610 /* de->u.CreateProcessInfo.lpStartAddress; */
611 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
612 fprintf(stderr, "Couldn't initiate DbgHelp\n");
614 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
615 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
616 de->dwProcessId, de->dwThreadId,
617 de->u.CreateProcessInfo.lpStartAddress);
619 assert(dbg_curr_thread == NULL); /* shouldn't be there */
620 dbg_add_thread(gdbctx->process, de->dwThreadId,
621 de->u.CreateProcessInfo.hThread,
622 de->u.CreateProcessInfo.lpThreadLocalBase);
623 break;
625 case LOAD_DLL_DEBUG_EVENT:
626 assert(dbg_curr_thread);
627 memory_get_string_indirect(gdbctx->process,
628 de->u.LoadDll.lpImageName,
629 de->u.LoadDll.fUnicode,
630 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
631 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
632 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
633 de->dwProcessId, de->dwThreadId,
634 dbg_W2A(u.buffer, -1),
635 de->u.LoadDll.lpBaseOfDll,
636 de->u.LoadDll.dwDebugInfoFileOffset,
637 de->u.LoadDll.nDebugInfoSize);
638 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
639 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
640 break;
642 case UNLOAD_DLL_DEBUG_EVENT:
643 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
644 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
645 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
646 SymUnloadModule(gdbctx->process->handle,
647 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
648 break;
650 case EXCEPTION_DEBUG_EVENT:
651 assert(dbg_curr_thread);
652 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
653 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
654 de->dwProcessId, de->dwThreadId,
655 de->u.Exception.ExceptionRecord.ExceptionCode);
657 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
659 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
661 break;
663 case CREATE_THREAD_DEBUG_EVENT:
664 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
665 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
666 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
668 dbg_add_thread(gdbctx->process,
669 de->dwThreadId,
670 de->u.CreateThread.hThread,
671 de->u.CreateThread.lpThreadLocalBase);
672 break;
674 case EXIT_THREAD_DEBUG_EVENT:
675 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
676 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
677 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
679 assert(dbg_curr_thread);
680 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
681 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
682 dbg_del_thread(dbg_curr_thread);
683 break;
685 case EXIT_PROCESS_DEBUG_EVENT:
686 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
687 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
688 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
690 dbg_del_process(gdbctx->process);
691 gdbctx->process = NULL;
692 /* now signal gdb that we're done */
693 gdbctx->last_sig = SIGTERM;
694 gdbctx->in_trap = TRUE;
695 break;
697 case OUTPUT_DEBUG_STRING_EVENT:
698 assert(dbg_curr_thread);
699 memory_get_string(gdbctx->process,
700 de->u.DebugString.lpDebugStringData, TRUE,
701 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
702 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
703 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
704 de->dwProcessId, de->dwThreadId, u.bufferA);
705 break;
707 case RIP_EVENT:
708 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
709 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
710 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
711 de->u.RipInfo.dwType);
712 break;
714 default:
715 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
716 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
717 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
721 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
723 if (dbg_curr_thread)
725 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
726 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
727 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
728 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
729 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
730 fprintf(stderr, "Cannot continue on %04x (%x)\n",
731 dbg_curr_thread->tid, cont);
733 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
734 fprintf(stderr, "Cannot find last thread\n");
738 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
741 if (dbg_curr_thread)
743 if(dbg_curr_thread->tid == threadid){
744 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
745 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
746 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
747 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
748 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
749 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
750 fprintf(stderr, "Cannot continue on %04x (%x)\n",
751 dbg_curr_thread->tid, cont);
754 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
755 fprintf(stderr, "Cannot find last thread\n");
758 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
760 struct pollfd pollfd;
761 int ret;
762 char pkt;
764 pollfd.fd = gdbctx->sock;
765 pollfd.events = POLLIN;
766 pollfd.revents = 0;
768 if ((ret = poll(&pollfd, 1, 0)) == 1) {
769 ret = read(gdbctx->sock, &pkt, 1);
770 if (ret != 1) {
771 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
772 fprintf(stderr, "read failed\n");
774 return FALSE;
776 if (pkt != '\003') {
777 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
778 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
780 return FALSE;
782 return TRUE;
783 } else if (ret == -1) {
784 fprintf(stderr, "poll failed\n");
786 return FALSE;
789 static void wait_for_debuggee(struct gdb_context* gdbctx)
791 DEBUG_EVENT de;
793 gdbctx->in_trap = FALSE;
794 for (;;)
796 if (!WaitForDebugEvent(&de, 10))
798 if (GetLastError() == ERROR_SEM_TIMEOUT)
800 if (check_for_interrupt(gdbctx)) {
801 if (!DebugBreakProcess(gdbctx->process->handle)) {
802 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
803 fprintf(stderr, "Failed to break into debugee\n");
805 break;
807 WaitForDebugEvent(&de, INFINITE);
808 } else {
809 continue;
811 } else {
812 break;
815 handle_debug_event(gdbctx, &de);
816 assert(!gdbctx->process ||
817 gdbctx->process->pid == 0 ||
818 de.dwProcessId == gdbctx->process->pid);
819 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
820 if (gdbctx->in_trap) break;
821 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
825 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
827 be_cpu->single_step(&gdbctx->context, FALSE);
828 resume_debuggee(gdbctx, DBG_CONTINUE);
829 if (!kill)
830 DebugActiveProcessStop(gdbctx->process->pid);
831 dbg_del_process(gdbctx->process);
832 gdbctx->process = NULL;
835 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
837 DWORD status;
839 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
841 strcpy(buffer, "Unknown process");
842 return;
844 if (status == STILL_ACTIVE)
846 strcpy(buffer, "Running");
848 else
849 snprintf(buffer, len, "Terminated (%u)", status);
851 switch (GetPriorityClass(gdbctx->process->handle))
853 case 0: break;
854 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
855 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
856 #endif
857 #ifdef BELOW_NORMAL_PRIORITY_CLASS
858 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
859 #endif
860 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
861 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
862 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
863 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
865 strcat(buffer, "\n");
868 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
869 char* buffer, size_t len)
871 struct dbg_thread* thd;
872 DWORD status;
873 int prio;
875 /* FIXME: use the size of buffer */
876 thd = dbg_get_thread(gdbctx->process, tid);
877 if (thd == NULL)
879 strcpy(buffer, "No information");
880 return;
882 if (GetExitCodeThread(thd->handle, &status))
884 if (status == STILL_ACTIVE)
886 /* FIXME: this is a bit brutal... some nicer way shall be found */
887 switch (status = SuspendThread(thd->handle))
889 case -1: break;
890 case 0: strcpy(buffer, "Running"); break;
891 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
893 ResumeThread(thd->handle);
895 else
896 snprintf(buffer, len, "Terminated (exit code = %u)", status);
898 else
900 strcpy(buffer, "Unknown threadID");
902 switch (prio = GetThreadPriority(thd->handle))
904 case THREAD_PRIORITY_ERROR_RETURN: break;
905 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
906 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
907 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
908 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
909 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
910 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
911 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
912 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
914 assert(strlen(buffer) < len);
917 /* =============================================== *
918 * P A C K E T U T I L S *
919 * =============================================== *
922 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
923 packet_last_f = 0x80};
925 static char* packet_realloc(char* buf, int size)
927 if (!buf)
928 return HeapAlloc(GetProcessHeap(), 0, size);
929 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
933 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
935 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
937 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
938 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
942 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
944 packet_reply_grow(gdbctx, len * 2);
945 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
946 gdbctx->out_len += len * 2;
949 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
951 packet_reply_hex_to(gdbctx, src, strlen(src));
954 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
956 int i, shift;
958 shift = (len - 1) * 8;
959 packet_reply_grow(gdbctx, len * 2);
960 for (i = 0; i < len; i++, shift -= 8)
962 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
963 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
967 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
969 packet_reply_grow(gdbctx, len);
970 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
971 gdbctx->out_len += len;
974 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
976 packet_reply_add(gdbctx, str, strlen(str));
979 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
981 packet_reply_add(gdbctx, &ch, 1);
984 static void packet_reply_open(struct gdb_context* gdbctx)
986 assert(gdbctx->out_curr_packet == -1);
987 packet_reply_catc(gdbctx, '$');
988 gdbctx->out_curr_packet = gdbctx->out_len;
991 static void packet_reply_close(struct gdb_context* gdbctx)
993 unsigned char cksum;
994 int plen;
996 plen = gdbctx->out_len - gdbctx->out_curr_packet;
997 packet_reply_catc(gdbctx, '#');
998 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
999 packet_reply_hex_to(gdbctx, &cksum, 1);
1000 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1001 fprintf(stderr, "Reply : %*.*s\n",
1002 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
1003 gdbctx->out_curr_packet = -1;
1006 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
1008 packet_reply_open(gdbctx);
1010 if (len == -1) len = strlen(packet);
1011 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
1013 packet_reply_add(gdbctx, packet, len);
1015 packet_reply_close(gdbctx);
1017 return packet_done;
1020 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
1022 packet_reply_open(gdbctx);
1024 packet_reply_add(gdbctx, "E", 1);
1025 packet_reply_val(gdbctx, error, 1);
1027 packet_reply_close(gdbctx);
1029 return packet_done;
1032 static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, unsigned idx)
1034 if (cpu_register_map[idx].gdb_length == cpu_register_map[idx].ctx_length)
1035 packet_reply_hex_to(gdbctx, cpu_register_ptr(&gdbctx->context, idx), cpu_register_map[idx].gdb_length);
1036 else
1038 DWORD64 val = cpu_register(&gdbctx->context, idx);
1039 unsigned i;
1041 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
1043 BYTE b = val;
1044 packet_reply_hex_to(gdbctx, &b, 1);
1045 val >>= 8;
1050 /* =============================================== *
1051 * P A C K E T H A N D L E R S *
1052 * =============================================== *
1055 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
1057 enum packet_return ret = packet_done;
1059 packet_reply_open(gdbctx);
1061 if (gdbctx->process != NULL)
1063 unsigned char sig;
1064 unsigned i;
1066 packet_reply_catc(gdbctx, 'T');
1067 sig = gdbctx->last_sig;
1068 packet_reply_val(gdbctx, sig, 1);
1069 packet_reply_add(gdbctx, "thread:", 7);
1070 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
1071 packet_reply_catc(gdbctx, ';');
1073 for (i = 0; i < cpu_num_regs; i++)
1075 ULONG flags = cpu_register_map[i].ctx_flags;
1076 if ((gdbctx->context.ContextFlags & flags) != flags)
1077 break;
1079 /* FIXME: this call will also grow the buffer...
1080 * unneeded, but not harmful
1082 packet_reply_val(gdbctx, i, 1);
1083 packet_reply_catc(gdbctx, ':');
1084 packet_reply_register_hex_to(gdbctx, i);
1085 packet_reply_catc(gdbctx, ';');
1088 else
1090 /* Try to put an exit code
1091 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1092 * just indicate the end of process and exit */
1093 packet_reply_add(gdbctx, "W00", 3);
1094 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1097 packet_reply_close(gdbctx);
1099 return ret;
1102 #if 0
1103 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1105 gdbctx->extended = 1;
1106 return packet_ok;
1108 #endif
1110 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1112 assert(gdbctx->in_packet_len == 0);
1113 return packet_reply_status(gdbctx);
1116 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1118 /* FIXME: add support for address in packet */
1119 assert(gdbctx->in_packet_len == 0);
1120 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1121 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1122 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1123 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1124 resume_debuggee(gdbctx, DBG_CONTINUE);
1125 wait_for_debuggee(gdbctx);
1126 return packet_reply_status(gdbctx);
1129 static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
1131 int i;
1132 int defaultAction = -1; /* magic non action */
1133 unsigned char sig;
1134 int actions =0;
1135 int actionIndex[20]; /* allow for up to 20 actions */
1136 int threadIndex[20];
1137 int threadCount = 0;
1138 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1139 unsigned int threadID = 0;
1140 struct dbg_thread* thd;
1142 /* OK we have vCont followed by..
1143 * ? for query
1144 * c for packet_continue
1145 * Csig for packet_continue_signal
1146 * s for step
1147 * Ssig for step signal
1148 * and then an optional thread ID at the end..
1149 * *******************************************/
1151 /* Query */
1152 if (gdbctx->in_packet[4] == '?')
1155 Reply:
1156 `vCont[;action]...'
1157 The vCont packet is supported. Each action is a supported command in the vCont packet.
1159 The vCont packet is not supported. (this didn't seem to be obeyed!)
1161 packet_reply_open(gdbctx);
1162 packet_reply_add(gdbctx, "vCont", 5);
1163 /* add all the supported actions to the reply (all of them for now) */
1164 packet_reply_add(gdbctx, ";c", 2);
1165 packet_reply_add(gdbctx, ";C", 2);
1166 packet_reply_add(gdbctx, ";s", 2);
1167 packet_reply_add(gdbctx, ";S", 2);
1168 packet_reply_close(gdbctx);
1169 return packet_done;
1172 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1173 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1174 now if only gdb talked XML.... */
1175 #if 0 /* handy for debugging */
1176 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1177 #endif
1179 /* go through the packet and identify where all the actions start at */
1180 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1182 if (gdbctx->in_packet[i] == ';')
1184 threadIndex[actions] = 0;
1185 actionIndex[actions++] = i;
1187 else if (gdbctx->in_packet[i] == ':')
1189 threadIndex[actions - 1] = i;
1193 /* now look up the default action */
1194 for (i = 0 ; i < actions; i++)
1196 if (threadIndex[i] == 0)
1198 if (defaultAction != -1)
1200 fprintf(stderr,"Too many default actions specified\n");
1201 return packet_error;
1203 defaultAction = i;
1207 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1209 /* go through all the threads and stick their ids in the to be done list. */
1210 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1212 threadIDs[threadCount++] = thd->tid;
1213 /* check to see if we have more threads than I counted on, and tell the user what to do
1214 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1215 if (threadCount == 100)
1217 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1218 break;
1222 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1223 * that remains is to apply the actions to the threads and the default action to any threads
1224 * left */
1225 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1226 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1227 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1228 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1230 /* deal with the threaded stuff first */
1231 for (i = 0; i < actions ; i++)
1233 if (threadIndex[i] != 0)
1235 int j, idLength = 0;
1236 if (i < actions - 1)
1238 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1240 else
1242 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1245 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1246 /* process the action */
1247 switch (gdbctx->in_packet[actionIndex[i] + 1])
1249 case 's': /* step */
1250 be_cpu->single_step(&gdbctx->context, TRUE);
1251 /* fall through*/
1252 case 'c': /* continue */
1253 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1254 break;
1255 case 'S': /* step Sig, */
1256 be_cpu->single_step(&gdbctx->context, TRUE);
1257 /* fall through */
1258 case 'C': /* continue sig */
1259 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1260 /* cannot change signals on the fly */
1261 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1262 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1263 if (sig != gdbctx->last_sig)
1264 return packet_error;
1265 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1266 break;
1268 for (j = 0 ; j < threadCount; j++)
1270 if (threadIDs[j] == threadID)
1272 threadIDs[j] = 0;
1273 break;
1277 } /* for i=0 ; i< actions */
1279 /* now we have manage the default action */
1280 if (defaultAction >= 0)
1282 for (i = 0 ; i< threadCount; i++)
1284 /* check to see if we've already done something to the thread*/
1285 if (threadIDs[i] != 0)
1287 /* if not apply the default action*/
1288 threadID = threadIDs[i];
1289 /* process the action (yes this is almost identical to the one above!) */
1290 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1292 case 's': /* step */
1293 be_cpu->single_step(&gdbctx->context, TRUE);
1294 /* fall through */
1295 case 'c': /* continue */
1296 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1297 break;
1298 case 'S':
1299 be_cpu->single_step(&gdbctx->context, TRUE);
1300 /* fall through */
1301 case 'C': /* continue sig */
1302 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1303 /* cannot change signals on the fly */
1304 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1305 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1306 if (sig != gdbctx->last_sig)
1307 return packet_error;
1308 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1309 break;
1313 } /* if(defaultAction >=0) */
1315 wait_for_debuggee(gdbctx);
1316 be_cpu->single_step(&gdbctx->context, FALSE);
1317 return packet_reply_status(gdbctx);
1320 struct verbose_defail
1322 const char* name;
1323 unsigned len;
1324 enum packet_return (*handler)(struct gdb_context*);
1325 } verbose_details[] =
1327 /* {"Attach", 6}, */
1328 {"Cont", 4, packet_verbose_cont},
1329 /* {"File", 4},
1330 {"FlashErase", 10},
1331 {"FlashWrite", 10},
1332 {"FlashDone", 9},
1333 {"Kill", 4},
1334 {"Run", 3},
1335 {"Stopped", 7},*/
1338 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1340 unsigned i;
1341 unsigned klen;
1343 for (klen = 0; ; klen++)
1345 if (klen == gdbctx->in_packet_len ||
1346 gdbctx->in_packet[klen] == ';' ||
1347 gdbctx->in_packet[klen] == ':' ||
1348 gdbctx->in_packet[klen] == '?')
1350 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1351 fprintf(stderr, "trying to process a verbose packet %*.*s\n",
1352 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1353 for (i = 0; i < sizeof(verbose_details)/sizeof(verbose_details[0]); i++)
1355 if (klen == verbose_details[i].len &&
1356 !memcmp(gdbctx->in_packet, verbose_details[i].name, verbose_details[i].len))
1358 return verbose_details[i].handler(gdbctx);
1361 /* no matching handler found, abort */
1362 break;
1366 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1367 fprintf(stderr, "No support for verbose packet %*.*s\n",
1368 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1369 return packet_error;
1372 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1374 unsigned char sig;
1376 /* FIXME: add support for address in packet */
1377 assert(gdbctx->in_packet_len == 2);
1378 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1379 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1380 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1381 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1382 hex_from(&sig, gdbctx->in_packet, 1);
1383 /* cannot change signals on the fly */
1384 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1385 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1386 if (sig != gdbctx->last_sig)
1387 return packet_error;
1388 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1389 wait_for_debuggee(gdbctx);
1390 return packet_reply_status(gdbctx);
1393 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1395 detach_debuggee(gdbctx, FALSE);
1396 return packet_ok | packet_last_f;
1399 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1401 int i;
1402 CONTEXT ctx;
1404 assert(gdbctx->in_trap);
1406 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1408 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, &ctx))
1409 return packet_error;
1412 packet_reply_open(gdbctx);
1413 for (i = 0; i < cpu_num_regs; i++)
1415 ULONG flags = cpu_register_map[i].ctx_flags;
1416 if ((gdbctx->context.ContextFlags & flags) != flags)
1417 break;
1418 packet_reply_register_hex_to(gdbctx, i);
1420 packet_reply_close(gdbctx);
1421 return packet_done;
1424 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1426 unsigned i;
1427 CONTEXT ctx;
1428 CONTEXT* pctx = &gdbctx->context;
1429 const char* ptr;
1431 assert(gdbctx->in_trap);
1432 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1434 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1435 return packet_error;
1437 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1439 ptr = gdbctx->in_packet;
1440 for (i = 0; i < cpu_num_regs; i++)
1442 ULONG flags = cpu_register_map[i].ctx_flags;
1443 if ((pctx->ContextFlags & flags) != flags)
1444 break;
1445 cpu_register_hex_from(pctx, i, &ptr);
1447 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1449 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1450 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1451 return packet_error;
1453 return packet_ok;
1456 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1458 detach_debuggee(gdbctx, TRUE);
1459 #if 0
1460 if (!gdbctx->extended)
1461 /* dunno whether GDB cares or not */
1462 #endif
1463 wait(NULL);
1464 exit(0);
1465 /* assume we can't really answer something here */
1466 /* return packet_done; */
1469 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1471 char* end;
1472 unsigned thread;
1474 switch (gdbctx->in_packet[0])
1476 case 'c':
1477 case 'g':
1478 if (gdbctx->in_packet[1] == '-')
1479 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1480 else
1481 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1482 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1484 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1485 fprintf(stderr, "Cannot get threadid %*.*s\n",
1486 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1487 gdbctx->in_packet + 1);
1488 return packet_error;
1490 if (gdbctx->in_packet[0] == 'c')
1491 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1492 else
1493 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1494 return packet_ok;
1495 default:
1496 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1497 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1498 return packet_error;
1502 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1504 char *addr;
1505 unsigned int len, blk_len, nread;
1506 char buffer[32];
1507 SIZE_T r = 0;
1509 assert(gdbctx->in_trap);
1510 /* FIXME:check in_packet_len for reading %p,%x */
1511 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1512 if (len <= 0) return packet_error;
1513 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1514 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1515 for (nread = 0; nread < len; nread += r, addr += r)
1517 blk_len = min(sizeof(buffer), len - nread);
1518 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1519 r == 0)
1521 /* fail at first address, return error */
1522 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1523 /* something has already been read, return partial information */
1524 break;
1526 if (nread == 0) packet_reply_open(gdbctx);
1527 packet_reply_hex_to(gdbctx, buffer, r);
1529 packet_reply_close(gdbctx);
1530 return packet_done;
1533 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1535 char* addr;
1536 unsigned int len, blk_len;
1537 char* ptr;
1538 char buffer[32];
1539 SIZE_T w;
1541 assert(gdbctx->in_trap);
1542 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1543 if (ptr == NULL)
1545 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1546 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1547 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1548 return packet_error;
1550 *ptr++ = '\0';
1552 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1554 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1555 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1556 return packet_error;
1558 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1560 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1561 fprintf(stderr, "Wrong sizes %u <> %u\n",
1562 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1563 return packet_error;
1565 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1566 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1567 while (len > 0)
1569 blk_len = min(sizeof(buffer), len);
1570 hex_from(buffer, ptr, blk_len);
1571 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1572 w != blk_len)
1573 break;
1574 addr += blk_len;
1575 len -= blk_len;
1576 ptr += blk_len;
1578 return packet_ok; /* FIXME: error while writing ? */
1581 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1583 unsigned reg;
1584 CONTEXT ctx;
1585 CONTEXT* pctx = &gdbctx->context;
1587 assert(gdbctx->in_trap);
1588 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1589 if (reg >= cpu_num_regs)
1591 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1592 fprintf(stderr, "Register out of bounds %x\n", reg);
1593 return packet_error;
1595 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1597 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1598 return packet_error;
1600 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1602 if (cpu_register_map[reg].ctx_length <= sizeof(DWORD64))
1603 fprintf(stderr, "Read register %x => %08x%08x\n", reg,
1604 (unsigned)(cpu_register(pctx, reg) >> 32), (unsigned)cpu_register(pctx, reg));
1605 else
1606 fprintf(stderr, "Read register %x\n", reg);
1608 packet_reply_open(gdbctx);
1609 packet_reply_register_hex_to(gdbctx, reg);
1610 packet_reply_close(gdbctx);
1611 return packet_done;
1614 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1616 unsigned reg;
1617 char* ptr;
1618 CONTEXT ctx;
1619 CONTEXT* pctx = &gdbctx->context;
1621 assert(gdbctx->in_trap);
1623 reg = strtoul(gdbctx->in_packet, &ptr, 16);
1624 if (ptr == NULL || reg >= cpu_num_regs || *ptr++ != '=')
1626 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1627 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1628 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1629 * it wouldn't matter too much, and it fakes our support for all regs
1631 return (ptr == NULL) ? packet_error : packet_ok;
1633 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1635 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1636 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
1639 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1641 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1642 return packet_error;
1644 if ((pctx->ContextFlags & cpu_register_map[reg].ctx_flags) != cpu_register_map[reg].ctx_flags)
1646 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1647 fprintf(stderr, "Writing reg %u is not supported on this host\n", reg);
1648 return packet_error;
1651 cpu_register_hex_from(pctx, reg, (const char**)&ptr);
1652 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1654 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1655 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1656 return packet_error;
1659 return packet_ok;
1662 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1664 char buffer[128];
1665 char clsName[128];
1666 char wndName[128];
1667 HWND child;
1669 do {
1670 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1671 strcpy(clsName, "-- Unknown --");
1672 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1673 strcpy(wndName, "-- Empty --");
1675 packet_reply_open(gdbctx);
1676 packet_reply_catc(gdbctx, 'O');
1677 snprintf(buffer, sizeof(buffer),
1678 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1679 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1680 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1681 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1682 wndName);
1683 packet_reply_hex_to_str(gdbctx, buffer);
1684 packet_reply_close(gdbctx);
1686 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1687 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1688 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1691 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1693 char buffer[128];
1695 /* we do the output in several 'O' packets, with the last one being just OK for
1696 * marking the end of the output */
1697 packet_reply_open(gdbctx);
1698 packet_reply_catc(gdbctx, 'O');
1699 snprintf(buffer, sizeof(buffer),
1700 "%-16.16s %-17.17s %-8.8s %s\n",
1701 "hwnd", "Class Name", " Style", " WndProc Text");
1702 packet_reply_hex_to_str(gdbctx, buffer);
1703 packet_reply_close(gdbctx);
1705 /* FIXME: could also add a pmt to this command in str... */
1706 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1707 packet_reply(gdbctx, "OK", 2);
1710 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1712 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1713 char buffer[128];
1714 char deco;
1715 PROCESSENTRY32 entry;
1716 BOOL ok;
1718 if (snap == INVALID_HANDLE_VALUE)
1719 return;
1721 entry.dwSize = sizeof(entry);
1722 ok = Process32First(snap, &entry);
1724 /* we do the output in several 'O' packets, with the last one being just OK for
1725 * marking the end of the output */
1727 packet_reply_open(gdbctx);
1728 packet_reply_catc(gdbctx, 'O');
1729 snprintf(buffer, sizeof(buffer),
1730 " %-8.8s %-8.8s %-8.8s %s\n",
1731 "pid", "threads", "parent", "executable");
1732 packet_reply_hex_to_str(gdbctx, buffer);
1733 packet_reply_close(gdbctx);
1735 while (ok)
1737 deco = ' ';
1738 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1739 packet_reply_open(gdbctx);
1740 packet_reply_catc(gdbctx, 'O');
1741 snprintf(buffer, sizeof(buffer),
1742 "%c%08x %-8d %08x '%s'\n",
1743 deco, entry.th32ProcessID, entry.cntThreads,
1744 entry.th32ParentProcessID, entry.szExeFile);
1745 packet_reply_hex_to_str(gdbctx, buffer);
1746 packet_reply_close(gdbctx);
1747 ok = Process32Next(snap, &entry);
1749 CloseHandle(snap);
1750 packet_reply(gdbctx, "OK", 2);
1753 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1755 MEMORY_BASIC_INFORMATION mbi;
1756 char* addr = 0;
1757 const char* state;
1758 const char* type;
1759 char prot[3+1];
1760 char buffer[128];
1762 /* we do the output in several 'O' packets, with the last one being just OK for
1763 * marking the end of the output */
1764 packet_reply_open(gdbctx);
1765 packet_reply_catc(gdbctx, 'O');
1766 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1767 packet_reply_close(gdbctx);
1769 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1771 switch (mbi.State)
1773 case MEM_COMMIT: state = "commit "; break;
1774 case MEM_FREE: state = "free "; break;
1775 case MEM_RESERVE: state = "reserve"; break;
1776 default: state = "??? "; break;
1778 if (mbi.State != MEM_FREE)
1780 switch (mbi.Type)
1782 case MEM_IMAGE: type = "image "; break;
1783 case MEM_MAPPED: type = "mapped "; break;
1784 case MEM_PRIVATE: type = "private"; break;
1785 case 0: type = " "; break;
1786 default: type = "??? "; break;
1788 memset(prot, ' ' , sizeof(prot)-1);
1789 prot[sizeof(prot)-1] = '\0';
1790 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1791 prot[0] = 'R';
1792 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1793 prot[1] = 'W';
1794 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1795 prot[1] = 'C';
1796 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1797 prot[2] = 'X';
1799 else
1801 type = "";
1802 prot[0] = '\0';
1804 packet_reply_open(gdbctx);
1805 snprintf(buffer, sizeof(buffer), "%0*lx %0*lx %s %s %s\n",
1806 (unsigned)sizeof(void*), (DWORD_PTR)addr,
1807 (unsigned)sizeof(void*), mbi.RegionSize, state, type, prot);
1808 packet_reply_catc(gdbctx, 'O');
1809 packet_reply_hex_to_str(gdbctx, buffer);
1810 packet_reply_close(gdbctx);
1812 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1813 break;
1814 addr += mbi.RegionSize;
1816 packet_reply(gdbctx, "OK", 2);
1819 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1820 int len, const char* str)
1822 char buffer[128];
1824 if (len == 0)
1826 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1828 else if (len >= 2 && str[0] == '=')
1830 unsigned val = atoi(&str[1]);
1831 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1832 gdbctx->trace = val;
1834 else
1836 /* FIXME: ugly but can use error packet here */
1837 packet_reply_cat(gdbctx, "E00");
1838 return;
1840 packet_reply_open(gdbctx);
1841 packet_reply_hex_to_str(gdbctx, buffer);
1842 packet_reply_close(gdbctx);
1845 struct query_detail
1847 int with_arg;
1848 const char* name;
1849 size_t len;
1850 void (*handler)(struct gdb_context*, int, const char*);
1851 } query_details[] =
1853 {0, "wnd", 3, packet_query_monitor_wnd},
1854 {0, "window", 6, packet_query_monitor_wnd},
1855 {0, "proc", 4, packet_query_monitor_process},
1856 {0, "process", 7, packet_query_monitor_process},
1857 {0, "mem", 3, packet_query_monitor_mem},
1858 {1, "trace", 5, packet_query_monitor_trace},
1859 {0, NULL, 0, NULL},
1862 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1863 const char* hxcmd, size_t len)
1865 char buffer[128];
1866 struct query_detail* qd;
1868 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1869 len /= 2;
1870 hex_from(buffer, hxcmd, len);
1872 for (qd = query_details; qd->name != NULL; qd++)
1874 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1875 if (!qd->with_arg && len != qd->len) continue;
1877 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1878 return packet_done;
1880 return packet_reply_error(gdbctx, EINVAL);
1883 static enum packet_return packet_query(struct gdb_context* gdbctx)
1885 switch (gdbctx->in_packet[0])
1887 case 'f':
1888 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1890 struct dbg_thread* thd;
1892 packet_reply_open(gdbctx);
1893 packet_reply_add(gdbctx, "m", 1);
1894 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1896 packet_reply_val(gdbctx, thd->tid, 4);
1897 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1898 packet_reply_add(gdbctx, ",", 1);
1900 packet_reply_close(gdbctx);
1901 return packet_done;
1903 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1905 char result[128];
1907 packet_reply_open(gdbctx);
1908 packet_reply_catc(gdbctx, 'O');
1909 get_process_info(gdbctx, result, sizeof(result));
1910 packet_reply_hex_to_str(gdbctx, result);
1911 packet_reply_close(gdbctx);
1912 return packet_done;
1914 break;
1915 case 's':
1916 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1918 packet_reply(gdbctx, "l", 1);
1919 return packet_done;
1921 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1923 packet_reply(gdbctx, "l", 1);
1924 return packet_done;
1926 break;
1927 case 'A':
1928 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
1930 char buf[2];
1932 buf[0] = '1';
1933 buf[1] = 0;
1934 return packet_reply(gdbctx, buf, -1);
1936 break;
1937 case 'C':
1938 if (gdbctx->in_packet_len == 1)
1940 struct dbg_thread* thd;
1941 /* FIXME: doc says 16 bit val ??? */
1942 /* grab first created thread, aka last in list */
1943 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1944 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1945 packet_reply_open(gdbctx);
1946 packet_reply_add(gdbctx, "QC", 2);
1947 packet_reply_val(gdbctx, thd->tid, 4);
1948 packet_reply_close(gdbctx);
1949 return packet_done;
1951 break;
1952 case 'O':
1953 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1955 char buf[64];
1957 snprintf(buf, sizeof(buf),
1958 "Text=%08lx;Data=%08lx;Bss=%08lx",
1959 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1960 gdbctx->wine_segs[2]);
1961 return packet_reply(gdbctx, buf, -1);
1963 break;
1964 case 'R':
1965 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1967 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1968 gdbctx->in_packet_len - 5);
1970 break;
1971 case 'S':
1972 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1973 return packet_ok;
1974 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1976 if (strlen(target_xml))
1977 return packet_reply(gdbctx, "PacketSize=400;qXfer:features:read+", -1);
1978 else
1980 /* no features supported */
1981 packet_reply_open(gdbctx);
1982 packet_reply_close(gdbctx);
1983 return packet_done;
1986 break;
1987 case 'T':
1988 if (gdbctx->in_packet_len > 15 &&
1989 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1990 gdbctx->in_packet[15] == ',')
1992 unsigned tid;
1993 char* end;
1994 char result[128];
1996 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1997 if (end == NULL) break;
1998 get_thread_info(gdbctx, tid, result, sizeof(result));
1999 packet_reply_open(gdbctx);
2000 packet_reply_hex_to_str(gdbctx, result);
2001 packet_reply_close(gdbctx);
2002 return packet_done;
2004 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
2006 /* Tracepoints not supported */
2007 packet_reply_open(gdbctx);
2008 packet_reply_close(gdbctx);
2009 return packet_done;
2011 break;
2012 case 'X':
2013 if (strlen(target_xml) && strncmp(gdbctx->in_packet, "Xfer:features:read:target.xml", 29) == 0)
2014 return packet_reply(gdbctx, target_xml, -1);
2015 break;
2017 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2018 fprintf(stderr, "Unknown or malformed query %*.*s\n",
2019 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
2020 return packet_error;
2023 static enum packet_return packet_step(struct gdb_context* gdbctx)
2025 /* FIXME: add support for address in packet */
2026 assert(gdbctx->in_packet_len == 0);
2027 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
2028 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
2029 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
2030 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
2031 be_cpu->single_step(&gdbctx->context, TRUE);
2032 resume_debuggee(gdbctx, DBG_CONTINUE);
2033 wait_for_debuggee(gdbctx);
2034 be_cpu->single_step(&gdbctx->context, FALSE);
2035 return packet_reply_status(gdbctx);
2038 #if 0
2039 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
2041 unsigned char sig;
2043 /* FIXME: add support for address in packet */
2044 assert(gdbctx->in_packet_len == 2);
2045 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
2046 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2047 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
2048 gdbctx->exec_thread, DEBUG_CurrThread->tid);
2049 hex_from(&sig, gdbctx->in_packet, 1);
2050 /* cannot change signals on the fly */
2051 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2052 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
2053 if (sig != gdbctx->last_sig)
2054 return packet_error;
2055 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
2056 wait_for_debuggee(gdbctx);
2057 return packet_reply_status(gdbctx);
2059 #endif
2061 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
2063 char* end;
2064 unsigned tid;
2066 tid = strtol(gdbctx->in_packet, &end, 16);
2067 if (tid == -1 || tid == 0)
2068 return packet_reply_error(gdbctx, EINVAL);
2069 if (dbg_get_thread(gdbctx->process, tid) != NULL)
2070 return packet_ok;
2071 return packet_reply_error(gdbctx, ESRCH);
2074 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
2076 void* addr;
2077 unsigned len;
2078 struct gdb_ctx_Xpoint* xpt;
2079 enum be_xpoint_type t;
2081 /* FIXME: check packet_len */
2082 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2083 gdbctx->in_packet[1] != ',' ||
2084 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2085 return packet_error;
2086 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2087 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
2088 addr, len, gdbctx->in_packet[0]);
2089 switch (gdbctx->in_packet[0])
2091 case '0': t = be_xpoint_break; len = 0; break;
2092 case '1': t = be_xpoint_watch_exec; break;
2093 case '2': t = be_xpoint_watch_read; break;
2094 case '3': t = be_xpoint_watch_write; break;
2095 default: return packet_error;
2097 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2099 if (xpt->addr == addr && xpt->type == t)
2101 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
2102 gdbctx->process->process_io, &gdbctx->context,
2103 t, xpt->addr, xpt->val, len))
2105 xpt->type = -1;
2106 return packet_ok;
2108 break;
2111 return packet_error;
2114 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
2116 void* addr;
2117 unsigned len;
2118 struct gdb_ctx_Xpoint* xpt;
2119 enum be_xpoint_type t;
2121 /* FIXME: check packet_len */
2122 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2123 gdbctx->in_packet[1] != ',' ||
2124 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2125 return packet_error;
2126 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2127 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
2128 addr, len, gdbctx->in_packet[0]);
2129 switch (gdbctx->in_packet[0])
2131 case '0': t = be_xpoint_break; len = 0; break;
2132 case '1': t = be_xpoint_watch_exec; break;
2133 case '2': t = be_xpoint_watch_read; break;
2134 case '3': t = be_xpoint_watch_write; break;
2135 default: return packet_error;
2137 /* because of packet command handling, this should be made idempotent */
2138 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2140 if (xpt->addr == addr && xpt->type == t)
2141 return packet_ok; /* nothing to do */
2143 /* really set the Xpoint */
2144 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2146 if (xpt->type == -1)
2148 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2149 gdbctx->process->process_io, &gdbctx->context,
2150 t, addr, &xpt->val, len))
2152 xpt->addr = addr;
2153 xpt->type = t;
2154 return packet_ok;
2156 fprintf(stderr, "cannot set xpoint\n");
2157 break;
2160 /* no more entries... eech */
2161 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2162 return packet_error;
2165 /* =============================================== *
2166 * P A C K E T I N F R A S T R U C T U R E *
2167 * =============================================== *
2170 struct packet_entry
2172 char key;
2173 enum packet_return (*handler)(struct gdb_context* gdbctx);
2176 static struct packet_entry packet_entries[] =
2178 /*{'!', packet_extended}, */
2179 {'?', packet_last_signal},
2180 {'c', packet_continue},
2181 {'C', packet_continue_signal},
2182 {'D', packet_detach},
2183 {'g', packet_read_registers},
2184 {'G', packet_write_registers},
2185 {'k', packet_kill},
2186 {'H', packet_thread},
2187 {'m', packet_read_memory},
2188 {'M', packet_write_memory},
2189 {'p', packet_read_register},
2190 {'P', packet_write_register},
2191 {'q', packet_query},
2192 /* {'Q', packet_set}, */
2193 /* {'R', packet,restart}, only in extended mode ! */
2194 {'s', packet_step},
2195 /*{'S', packet_step_signal}, hard(er) to implement */
2196 {'T', packet_thread_alive},
2197 {'v', packet_verbose},
2198 {'z', packet_remove_breakpoint},
2199 {'Z', packet_set_breakpoint},
2202 static BOOL extract_packets(struct gdb_context* gdbctx)
2204 char* end;
2205 int plen;
2206 unsigned char in_cksum, loc_cksum;
2207 char* ptr;
2208 enum packet_return ret = packet_error;
2209 int num_packet = 0;
2211 while ((ret & packet_last_f) == 0)
2213 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2214 fprintf(stderr, "In-buf: %*.*s\n",
2215 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2216 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2217 if (ptr == NULL) return FALSE;
2218 if (ptr != gdbctx->in_buf)
2220 int glen = ptr - gdbctx->in_buf; /* garbage len */
2221 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2222 fprintf(stderr, "Removing garbage: %*.*s\n",
2223 glen, glen, gdbctx->in_buf);
2224 gdbctx->in_len -= glen;
2225 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2227 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2228 if (end == NULL) return FALSE;
2229 /* no checksum yet */
2230 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2231 plen = end - gdbctx->in_buf - 1;
2232 hex_from(&in_cksum, end + 1, 1);
2233 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2234 if (loc_cksum == in_cksum)
2236 if (num_packet == 0) {
2237 int i;
2239 ret = packet_error;
2241 write(gdbctx->sock, "+", 1);
2242 assert(plen);
2244 /* FIXME: should use bsearch if packet_entries was sorted */
2245 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2247 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2249 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2251 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2252 fprintf(stderr, "Unknown packet request %*.*s\n",
2253 plen, plen, &gdbctx->in_buf[1]);
2255 else
2257 gdbctx->in_packet = gdbctx->in_buf + 2;
2258 gdbctx->in_packet_len = plen - 1;
2259 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2260 fprintf(stderr, "Packet: %c%*.*s\n",
2261 gdbctx->in_buf[1],
2262 gdbctx->in_packet_len, gdbctx->in_packet_len,
2263 gdbctx->in_packet);
2264 ret = (packet_entries[i].handler)(gdbctx);
2266 switch (ret & ~packet_last_f)
2268 case packet_error: packet_reply(gdbctx, "", 0); break;
2269 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2270 case packet_done: break;
2272 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2273 fprintf(stderr, "Reply-full: %*.*s\n",
2274 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2275 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2276 assert(i == gdbctx->out_len);
2277 /* if this fails, we'll have to use POLLOUT...
2279 gdbctx->out_len = 0;
2280 num_packet++;
2282 else
2284 /* FIXME: If we have more than one packet in our input buffer,
2285 * it's very likely that we took too long to answer to a given packet
2286 * and gdb is sending us the same packet again.
2287 * So we simply drop the second packet. This will lower the risk of error,
2288 * but there are still some race conditions here.
2289 * A better fix (yet not perfect) would be to have two threads:
2290 * - one managing the packets for gdb
2291 * - the second one managing the commands...
2292 * This would allow us to send the reply with the '+' character (Ack of
2293 * the command) way sooner than we do now.
2295 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2296 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2299 else
2301 write(gdbctx->sock, "+", 1);
2302 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2303 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2305 gdbctx->in_len -= plen + 4;
2306 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2308 return TRUE;
2311 static int fetch_data(struct gdb_context* gdbctx)
2313 int len, in_len = gdbctx->in_len;
2315 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2316 for (;;)
2318 #define STEP 128
2319 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2320 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2321 #undef STEP
2322 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2323 fprintf(stderr, "%d %d %*.*s\n",
2324 gdbctx->in_len, gdbctx->in_buf_alloc,
2325 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2326 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2327 if (len <= 0) break;
2328 gdbctx->in_len += len;
2329 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2330 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2332 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2333 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2334 return gdbctx->in_len - in_len;
2337 #define FLAG_NO_START 1
2338 #define FLAG_WITH_XTERM 2
2340 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2342 char buf[MAX_PATH];
2343 int fd;
2344 const char *gdb_path, *tmp_path;
2345 FILE* f;
2347 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2348 if (!(tmp_path = getenv("TMPDIR"))) tmp_path = "/tmp";
2349 strcpy(buf, tmp_path);
2350 strcat(buf, "/winegdb.XXXXXX");
2351 fd = mkstemps(buf, 0);
2352 if (fd == -1) return FALSE;
2353 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2354 fprintf(f, "file %s\n", wine_path);
2355 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2356 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2357 fprintf(f, "set prompt Wine-gdb>\\ \n");
2358 /* gdb 5.1 seems to require it, won't hurt anyway */
2359 fprintf(f, "sharedlibrary\n");
2360 /* This is needed (but not a decent & final fix)
2361 * Without this, gdb would skip our inter-DLL relay code (because
2362 * we don't have any line number information for the relay code)
2363 * With this, we will stop on first instruction of the stub, and
2364 * reusing step, will get us through the relay stub at the actual
2365 * function we're looking at.
2367 fprintf(f, "set step-mode on\n");
2368 /* tell gdb to delete this file when done handling it... */
2369 fprintf(f, "shell rm -f \"%s\"\n", buf);
2370 fclose(f);
2371 if (flags & FLAG_WITH_XTERM)
2372 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2373 else
2374 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2375 assert(0); /* never reached */
2376 return TRUE;
2379 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2381 int sock;
2382 struct sockaddr_in s_addrs;
2383 socklen_t s_len = sizeof(s_addrs);
2384 struct pollfd pollfd;
2385 IMAGEHLP_MODULE64 imh_mod;
2386 BOOL ret = FALSE;
2388 /* step 1: create socket for gdb connection request */
2389 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2391 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2392 fprintf(stderr, "Can't create socket");
2393 return FALSE;
2396 if (listen(sock, 1) == -1 || getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2397 goto cleanup;
2399 /* step 2: do the process internal creation */
2400 handle_debug_event(gdbctx, de);
2402 /* step3: get the wine loader name */
2403 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod))
2404 goto cleanup;
2406 /* step 4: fire up gdb (if requested) */
2407 if (flags & FLAG_NO_START)
2408 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2409 else
2410 switch (fork())
2412 case -1: /* error in parent... */
2413 fprintf(stderr, "Cannot create gdb\n");
2414 goto cleanup;
2415 default: /* in parent... success */
2416 signal(SIGINT, SIG_IGN);
2417 break;
2418 case 0: /* in child... and alive */
2419 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2420 /* if we're here, exec failed, so report failure */
2421 goto cleanup;
2424 /* step 5: wait for gdb to connect actually */
2425 pollfd.fd = sock;
2426 pollfd.events = POLLIN;
2427 pollfd.revents = 0;
2429 switch (poll(&pollfd, 1, -1))
2431 case 1:
2432 if (pollfd.revents & POLLIN)
2434 int dummy = 1;
2435 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2436 if (gdbctx->sock == -1)
2437 break;
2438 ret = TRUE;
2439 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2440 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2441 /* don't keep our small packets too long: send them ASAP back to GDB
2442 * without this, GDB really crawls
2444 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2446 break;
2447 case 0:
2448 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2449 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2450 break;
2451 case -1:
2452 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2453 fprintf(stderr, "Poll for cnx failed (error)\n");
2454 break;
2455 default:
2456 assert(0);
2459 cleanup:
2460 close(sock);
2461 return ret;
2464 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2466 DEBUG_EVENT de;
2467 int i;
2469 gdbctx->sock = -1;
2470 gdbctx->in_buf = NULL;
2471 gdbctx->in_buf_alloc = 0;
2472 gdbctx->in_len = 0;
2473 gdbctx->out_buf = NULL;
2474 gdbctx->out_buf_alloc = 0;
2475 gdbctx->out_len = 0;
2476 gdbctx->out_curr_packet = -1;
2478 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2479 gdbctx->last_sig = 0;
2480 gdbctx->in_trap = FALSE;
2481 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2482 gdbctx->process = NULL;
2483 for (i = 0; i < NUM_XPOINT; i++)
2484 gdbctx->Xpoints[i].type = -1;
2485 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2486 gdbctx->wine_segs[i] = 0;
2488 /* wait for first trap */
2489 while (WaitForDebugEvent(&de, INFINITE))
2491 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2493 /* this should be the first event we get,
2494 * and the only one of this type */
2495 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2496 /* gdbctx->dwProcessId = pid; */
2497 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2498 assert(!gdbctx->in_trap);
2500 else
2502 handle_debug_event(gdbctx, &de);
2503 if (gdbctx->in_trap) break;
2505 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2507 return TRUE;
2510 static int gdb_remote(unsigned flags)
2512 struct pollfd pollfd;
2513 struct gdb_context gdbctx;
2514 BOOL doLoop;
2516 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2518 pollfd.fd = gdbctx.sock;
2519 pollfd.events = POLLIN;
2520 pollfd.revents = 0;
2522 switch (poll(&pollfd, 1, -1))
2524 case 1:
2525 /* got something */
2526 if (pollfd.revents & (POLLHUP | POLLERR))
2528 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2529 fprintf(stderr, "Gdb hung up\n");
2530 /* kill also debuggee process - questionnable - */
2531 detach_debuggee(&gdbctx, TRUE);
2532 doLoop = FALSE;
2533 break;
2535 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2537 if (extract_packets(&gdbctx)) doLoop = FALSE;
2539 break;
2540 case 0:
2541 /* timeout, should never happen (infinite timeout) */
2542 break;
2543 case -1:
2544 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2545 fprintf(stderr, "Poll failed\n");
2546 doLoop = FALSE;
2547 break;
2550 wait(NULL);
2551 return 0;
2553 #endif
2555 int gdb_main(int argc, char* argv[])
2557 #ifdef HAVE_POLL
2558 unsigned gdb_flags = 0;
2560 argc--; argv++;
2561 while (argc > 0 && argv[0][0] == '-')
2563 if (strcmp(argv[0], "--no-start") == 0)
2565 gdb_flags |= FLAG_NO_START;
2566 argc--; argv++;
2567 continue;
2569 if (strcmp(argv[0], "--with-xterm") == 0)
2571 gdb_flags |= FLAG_WITH_XTERM;
2572 argc--; argv++;
2573 continue;
2575 return -1;
2577 if (dbg_active_attach(argc, argv) == start_ok ||
2578 dbg_active_launch(argc, argv) == start_ok)
2579 return gdb_remote(gdb_flags);
2580 #else
2581 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2582 #endif
2583 return -1;