msvcp100: Don't bother to clean up at process exit.
[wine.git] / programs / winedbg / gdbproxy.c
blob04d36f7267295f7d41bba3fb385e282ad8eb6d24
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(X0, 8, CONTEXT_INTEGER),
403 REG(X1, 8, CONTEXT_INTEGER),
404 REG(X2, 8, CONTEXT_INTEGER),
405 REG(X3, 8, CONTEXT_INTEGER),
406 REG(X4, 8, CONTEXT_INTEGER),
407 REG(X5, 8, CONTEXT_INTEGER),
408 REG(X6, 8, CONTEXT_INTEGER),
409 REG(X7, 8, CONTEXT_INTEGER),
410 REG(X8, 8, CONTEXT_INTEGER),
411 REG(X9, 8, CONTEXT_INTEGER),
412 REG(X10, 8, CONTEXT_INTEGER),
413 REG(X11, 8, CONTEXT_INTEGER),
414 REG(X12, 8, CONTEXT_INTEGER),
415 REG(X13, 8, CONTEXT_INTEGER),
416 REG(X14, 8, CONTEXT_INTEGER),
417 REG(X15, 8, CONTEXT_INTEGER),
418 REG(X16, 8, CONTEXT_INTEGER),
419 REG(X17, 8, CONTEXT_INTEGER),
420 REG(X18, 8, CONTEXT_INTEGER),
421 REG(X19, 8, CONTEXT_INTEGER),
422 REG(X20, 8, CONTEXT_INTEGER),
423 REG(X21, 8, CONTEXT_INTEGER),
424 REG(X22, 8, CONTEXT_INTEGER),
425 REG(X23, 8, CONTEXT_INTEGER),
426 REG(X24, 8, CONTEXT_INTEGER),
427 REG(X25, 8, CONTEXT_INTEGER),
428 REG(X26, 8, CONTEXT_INTEGER),
429 REG(X27, 8, CONTEXT_INTEGER),
430 REG(X28, 8, CONTEXT_INTEGER),
431 REG(X29, 8, CONTEXT_INTEGER),
432 REG(X30, 8, CONTEXT_INTEGER),
433 REG(Sp, 8, CONTEXT_CONTROL),
434 REG(Pc, 8, CONTEXT_CONTROL),
435 REG(PState, 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;
1403 CONTEXT* pctx = &gdbctx->context;
1405 assert(gdbctx->in_trap);
1407 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1409 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1410 return packet_error;
1413 packet_reply_open(gdbctx);
1414 for (i = 0; i < cpu_num_regs; i++)
1416 ULONG flags = cpu_register_map[i].ctx_flags;
1417 if ((gdbctx->context.ContextFlags & flags) != flags)
1418 break;
1419 packet_reply_register_hex_to(gdbctx, i);
1421 packet_reply_close(gdbctx);
1422 return packet_done;
1425 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1427 unsigned i;
1428 CONTEXT ctx;
1429 CONTEXT* pctx = &gdbctx->context;
1430 const char* ptr;
1432 assert(gdbctx->in_trap);
1433 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1435 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1436 return packet_error;
1438 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1440 ptr = gdbctx->in_packet;
1441 for (i = 0; i < cpu_num_regs; i++)
1443 ULONG flags = cpu_register_map[i].ctx_flags;
1444 if ((pctx->ContextFlags & flags) != flags)
1445 break;
1446 cpu_register_hex_from(pctx, i, &ptr);
1448 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1450 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1451 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1452 return packet_error;
1454 return packet_ok;
1457 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1459 detach_debuggee(gdbctx, TRUE);
1460 #if 0
1461 if (!gdbctx->extended)
1462 /* dunno whether GDB cares or not */
1463 #endif
1464 wait(NULL);
1465 exit(0);
1466 /* assume we can't really answer something here */
1467 /* return packet_done; */
1470 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1472 char* end;
1473 unsigned thread;
1475 switch (gdbctx->in_packet[0])
1477 case 'c':
1478 case 'g':
1479 if (gdbctx->in_packet[1] == '-')
1480 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1481 else
1482 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1483 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1485 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1486 fprintf(stderr, "Cannot get threadid %*.*s\n",
1487 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1488 gdbctx->in_packet + 1);
1489 return packet_error;
1491 if (gdbctx->in_packet[0] == 'c')
1492 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1493 else
1494 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1495 return packet_ok;
1496 default:
1497 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1498 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1499 return packet_error;
1503 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1505 char *addr;
1506 unsigned int len, blk_len, nread;
1507 char buffer[32];
1508 SIZE_T r = 0;
1510 assert(gdbctx->in_trap);
1511 /* FIXME:check in_packet_len for reading %p,%x */
1512 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1513 if (len <= 0) return packet_error;
1514 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1515 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1516 for (nread = 0; nread < len; nread += r, addr += r)
1518 blk_len = min(sizeof(buffer), len - nread);
1519 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1520 r == 0)
1522 /* fail at first address, return error */
1523 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1524 /* something has already been read, return partial information */
1525 break;
1527 if (nread == 0) packet_reply_open(gdbctx);
1528 packet_reply_hex_to(gdbctx, buffer, r);
1530 packet_reply_close(gdbctx);
1531 return packet_done;
1534 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1536 char* addr;
1537 unsigned int len, blk_len;
1538 char* ptr;
1539 char buffer[32];
1540 SIZE_T w;
1542 assert(gdbctx->in_trap);
1543 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1544 if (ptr == NULL)
1546 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1547 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1548 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1549 return packet_error;
1551 *ptr++ = '\0';
1553 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1555 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1556 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1557 return packet_error;
1559 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1561 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1562 fprintf(stderr, "Wrong sizes %u <> %u\n",
1563 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1564 return packet_error;
1566 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1567 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1568 while (len > 0)
1570 blk_len = min(sizeof(buffer), len);
1571 hex_from(buffer, ptr, blk_len);
1572 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1573 w != blk_len)
1574 break;
1575 addr += blk_len;
1576 len -= blk_len;
1577 ptr += blk_len;
1579 return packet_ok; /* FIXME: error while writing ? */
1582 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1584 unsigned reg;
1585 CONTEXT ctx;
1586 CONTEXT* pctx = &gdbctx->context;
1588 assert(gdbctx->in_trap);
1589 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1590 if (reg >= cpu_num_regs)
1592 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1593 fprintf(stderr, "Register out of bounds %x\n", reg);
1594 return packet_error;
1596 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1598 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1599 return packet_error;
1601 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1603 if (cpu_register_map[reg].ctx_length <= sizeof(DWORD64))
1604 fprintf(stderr, "Read register %x => %08x%08x\n", reg,
1605 (unsigned)(cpu_register(pctx, reg) >> 32), (unsigned)cpu_register(pctx, reg));
1606 else
1607 fprintf(stderr, "Read register %x\n", reg);
1609 packet_reply_open(gdbctx);
1610 packet_reply_register_hex_to(gdbctx, reg);
1611 packet_reply_close(gdbctx);
1612 return packet_done;
1615 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1617 unsigned reg;
1618 char* ptr;
1619 CONTEXT ctx;
1620 CONTEXT* pctx = &gdbctx->context;
1622 assert(gdbctx->in_trap);
1624 reg = strtoul(gdbctx->in_packet, &ptr, 16);
1625 if (ptr == NULL || reg >= cpu_num_regs || *ptr++ != '=')
1627 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1628 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1629 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1630 * it wouldn't matter too much, and it fakes our support for all regs
1632 return (ptr == NULL) ? packet_error : packet_ok;
1634 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1636 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1637 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
1640 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1642 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1643 return packet_error;
1645 if ((pctx->ContextFlags & cpu_register_map[reg].ctx_flags) != cpu_register_map[reg].ctx_flags)
1647 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1648 fprintf(stderr, "Writing reg %u is not supported on this host\n", reg);
1649 return packet_error;
1652 cpu_register_hex_from(pctx, reg, (const char**)&ptr);
1653 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1655 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1656 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1657 return packet_error;
1660 return packet_ok;
1663 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1665 char buffer[128];
1666 char clsName[128];
1667 char wndName[128];
1668 HWND child;
1670 do {
1671 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1672 strcpy(clsName, "-- Unknown --");
1673 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1674 strcpy(wndName, "-- Empty --");
1676 packet_reply_open(gdbctx);
1677 packet_reply_catc(gdbctx, 'O');
1678 snprintf(buffer, sizeof(buffer),
1679 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1680 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1681 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1682 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1683 wndName);
1684 packet_reply_hex_to_str(gdbctx, buffer);
1685 packet_reply_close(gdbctx);
1687 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1688 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1689 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1692 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1694 char buffer[128];
1696 /* we do the output in several 'O' packets, with the last one being just OK for
1697 * marking the end of the output */
1698 packet_reply_open(gdbctx);
1699 packet_reply_catc(gdbctx, 'O');
1700 snprintf(buffer, sizeof(buffer),
1701 "%-16.16s %-17.17s %-8.8s %s\n",
1702 "hwnd", "Class Name", " Style", " WndProc Text");
1703 packet_reply_hex_to_str(gdbctx, buffer);
1704 packet_reply_close(gdbctx);
1706 /* FIXME: could also add a pmt to this command in str... */
1707 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1708 packet_reply(gdbctx, "OK", 2);
1711 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1713 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1714 char buffer[128];
1715 char deco;
1716 PROCESSENTRY32 entry;
1717 BOOL ok;
1719 if (snap == INVALID_HANDLE_VALUE)
1720 return;
1722 entry.dwSize = sizeof(entry);
1723 ok = Process32First(snap, &entry);
1725 /* we do the output in several 'O' packets, with the last one being just OK for
1726 * marking the end of the output */
1728 packet_reply_open(gdbctx);
1729 packet_reply_catc(gdbctx, 'O');
1730 snprintf(buffer, sizeof(buffer),
1731 " %-8.8s %-8.8s %-8.8s %s\n",
1732 "pid", "threads", "parent", "executable");
1733 packet_reply_hex_to_str(gdbctx, buffer);
1734 packet_reply_close(gdbctx);
1736 while (ok)
1738 deco = ' ';
1739 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1740 packet_reply_open(gdbctx);
1741 packet_reply_catc(gdbctx, 'O');
1742 snprintf(buffer, sizeof(buffer),
1743 "%c%08x %-8d %08x '%s'\n",
1744 deco, entry.th32ProcessID, entry.cntThreads,
1745 entry.th32ParentProcessID, entry.szExeFile);
1746 packet_reply_hex_to_str(gdbctx, buffer);
1747 packet_reply_close(gdbctx);
1748 ok = Process32Next(snap, &entry);
1750 CloseHandle(snap);
1751 packet_reply(gdbctx, "OK", 2);
1754 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1756 MEMORY_BASIC_INFORMATION mbi;
1757 char* addr = 0;
1758 const char* state;
1759 const char* type;
1760 char prot[3+1];
1761 char buffer[128];
1763 /* we do the output in several 'O' packets, with the last one being just OK for
1764 * marking the end of the output */
1765 packet_reply_open(gdbctx);
1766 packet_reply_catc(gdbctx, 'O');
1767 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1768 packet_reply_close(gdbctx);
1770 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1772 switch (mbi.State)
1774 case MEM_COMMIT: state = "commit "; break;
1775 case MEM_FREE: state = "free "; break;
1776 case MEM_RESERVE: state = "reserve"; break;
1777 default: state = "??? "; break;
1779 if (mbi.State != MEM_FREE)
1781 switch (mbi.Type)
1783 case MEM_IMAGE: type = "image "; break;
1784 case MEM_MAPPED: type = "mapped "; break;
1785 case MEM_PRIVATE: type = "private"; break;
1786 case 0: type = " "; break;
1787 default: type = "??? "; break;
1789 memset(prot, ' ' , sizeof(prot)-1);
1790 prot[sizeof(prot)-1] = '\0';
1791 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1792 prot[0] = 'R';
1793 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1794 prot[1] = 'W';
1795 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1796 prot[1] = 'C';
1797 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1798 prot[2] = 'X';
1800 else
1802 type = "";
1803 prot[0] = '\0';
1805 packet_reply_open(gdbctx);
1806 snprintf(buffer, sizeof(buffer), "%0*lx %0*lx %s %s %s\n",
1807 (unsigned)sizeof(void*), (DWORD_PTR)addr,
1808 (unsigned)sizeof(void*), mbi.RegionSize, state, type, prot);
1809 packet_reply_catc(gdbctx, 'O');
1810 packet_reply_hex_to_str(gdbctx, buffer);
1811 packet_reply_close(gdbctx);
1813 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1814 break;
1815 addr += mbi.RegionSize;
1817 packet_reply(gdbctx, "OK", 2);
1820 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1821 int len, const char* str)
1823 char buffer[128];
1825 if (len == 0)
1827 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1829 else if (len >= 2 && str[0] == '=')
1831 unsigned val = atoi(&str[1]);
1832 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1833 gdbctx->trace = val;
1835 else
1837 /* FIXME: ugly but can use error packet here */
1838 packet_reply_cat(gdbctx, "E00");
1839 return;
1841 packet_reply_open(gdbctx);
1842 packet_reply_hex_to_str(gdbctx, buffer);
1843 packet_reply_close(gdbctx);
1846 struct query_detail
1848 int with_arg;
1849 const char* name;
1850 size_t len;
1851 void (*handler)(struct gdb_context*, int, const char*);
1852 } query_details[] =
1854 {0, "wnd", 3, packet_query_monitor_wnd},
1855 {0, "window", 6, packet_query_monitor_wnd},
1856 {0, "proc", 4, packet_query_monitor_process},
1857 {0, "process", 7, packet_query_monitor_process},
1858 {0, "mem", 3, packet_query_monitor_mem},
1859 {1, "trace", 5, packet_query_monitor_trace},
1860 {0, NULL, 0, NULL},
1863 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1864 const char* hxcmd, size_t len)
1866 char buffer[128];
1867 struct query_detail* qd;
1869 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1870 len /= 2;
1871 hex_from(buffer, hxcmd, len);
1873 for (qd = query_details; qd->name != NULL; qd++)
1875 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1876 if (!qd->with_arg && len != qd->len) continue;
1878 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1879 return packet_done;
1881 return packet_reply_error(gdbctx, EINVAL);
1884 static enum packet_return packet_query(struct gdb_context* gdbctx)
1886 switch (gdbctx->in_packet[0])
1888 case 'f':
1889 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1891 struct dbg_thread* thd;
1893 packet_reply_open(gdbctx);
1894 packet_reply_add(gdbctx, "m", 1);
1895 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1897 packet_reply_val(gdbctx, thd->tid, 4);
1898 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1899 packet_reply_add(gdbctx, ",", 1);
1901 packet_reply_close(gdbctx);
1902 return packet_done;
1904 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1906 char result[128];
1908 packet_reply_open(gdbctx);
1909 packet_reply_catc(gdbctx, 'O');
1910 get_process_info(gdbctx, result, sizeof(result));
1911 packet_reply_hex_to_str(gdbctx, result);
1912 packet_reply_close(gdbctx);
1913 return packet_done;
1915 break;
1916 case 's':
1917 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1919 packet_reply(gdbctx, "l", 1);
1920 return packet_done;
1922 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1924 packet_reply(gdbctx, "l", 1);
1925 return packet_done;
1927 break;
1928 case 'A':
1929 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
1931 char buf[2];
1933 buf[0] = '1';
1934 buf[1] = 0;
1935 return packet_reply(gdbctx, buf, -1);
1937 break;
1938 case 'C':
1939 if (gdbctx->in_packet_len == 1)
1941 struct dbg_thread* thd;
1942 /* FIXME: doc says 16 bit val ??? */
1943 /* grab first created thread, aka last in list */
1944 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1945 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1946 packet_reply_open(gdbctx);
1947 packet_reply_add(gdbctx, "QC", 2);
1948 packet_reply_val(gdbctx, thd->tid, 4);
1949 packet_reply_close(gdbctx);
1950 return packet_done;
1952 break;
1953 case 'O':
1954 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1956 char buf[64];
1958 snprintf(buf, sizeof(buf),
1959 "Text=%08lx;Data=%08lx;Bss=%08lx",
1960 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1961 gdbctx->wine_segs[2]);
1962 return packet_reply(gdbctx, buf, -1);
1964 break;
1965 case 'R':
1966 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1968 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1969 gdbctx->in_packet_len - 5);
1971 break;
1972 case 'S':
1973 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1974 return packet_ok;
1975 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1977 if (strlen(target_xml))
1978 return packet_reply(gdbctx, "PacketSize=400;qXfer:features:read+", -1);
1979 else
1981 /* no features supported */
1982 packet_reply_open(gdbctx);
1983 packet_reply_close(gdbctx);
1984 return packet_done;
1987 break;
1988 case 'T':
1989 if (gdbctx->in_packet_len > 15 &&
1990 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1991 gdbctx->in_packet[15] == ',')
1993 unsigned tid;
1994 char* end;
1995 char result[128];
1997 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1998 if (end == NULL) break;
1999 get_thread_info(gdbctx, tid, result, sizeof(result));
2000 packet_reply_open(gdbctx);
2001 packet_reply_hex_to_str(gdbctx, result);
2002 packet_reply_close(gdbctx);
2003 return packet_done;
2005 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
2007 /* Tracepoints not supported */
2008 packet_reply_open(gdbctx);
2009 packet_reply_close(gdbctx);
2010 return packet_done;
2012 break;
2013 case 'X':
2014 if (strlen(target_xml) && strncmp(gdbctx->in_packet, "Xfer:features:read:target.xml", 29) == 0)
2015 return packet_reply(gdbctx, target_xml, -1);
2016 break;
2018 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2019 fprintf(stderr, "Unknown or malformed query %*.*s\n",
2020 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
2021 return packet_error;
2024 static enum packet_return packet_step(struct gdb_context* gdbctx)
2026 /* FIXME: add support for address in packet */
2027 assert(gdbctx->in_packet_len == 0);
2028 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
2029 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
2030 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
2031 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
2032 be_cpu->single_step(&gdbctx->context, TRUE);
2033 resume_debuggee(gdbctx, DBG_CONTINUE);
2034 wait_for_debuggee(gdbctx);
2035 be_cpu->single_step(&gdbctx->context, FALSE);
2036 return packet_reply_status(gdbctx);
2039 #if 0
2040 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
2042 unsigned char sig;
2044 /* FIXME: add support for address in packet */
2045 assert(gdbctx->in_packet_len == 2);
2046 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
2047 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2048 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
2049 gdbctx->exec_thread, DEBUG_CurrThread->tid);
2050 hex_from(&sig, gdbctx->in_packet, 1);
2051 /* cannot change signals on the fly */
2052 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2053 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
2054 if (sig != gdbctx->last_sig)
2055 return packet_error;
2056 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
2057 wait_for_debuggee(gdbctx);
2058 return packet_reply_status(gdbctx);
2060 #endif
2062 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
2064 char* end;
2065 unsigned tid;
2067 tid = strtol(gdbctx->in_packet, &end, 16);
2068 if (tid == -1 || tid == 0)
2069 return packet_reply_error(gdbctx, EINVAL);
2070 if (dbg_get_thread(gdbctx->process, tid) != NULL)
2071 return packet_ok;
2072 return packet_reply_error(gdbctx, ESRCH);
2075 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
2077 void* addr;
2078 unsigned len;
2079 struct gdb_ctx_Xpoint* xpt;
2080 enum be_xpoint_type t;
2082 /* FIXME: check packet_len */
2083 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2084 gdbctx->in_packet[1] != ',' ||
2085 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2086 return packet_error;
2087 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2088 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
2089 addr, len, gdbctx->in_packet[0]);
2090 switch (gdbctx->in_packet[0])
2092 case '0': t = be_xpoint_break; len = 0; break;
2093 case '1': t = be_xpoint_watch_exec; break;
2094 case '2': t = be_xpoint_watch_read; break;
2095 case '3': t = be_xpoint_watch_write; break;
2096 default: return packet_error;
2098 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2100 if (xpt->addr == addr && xpt->type == t)
2102 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
2103 gdbctx->process->process_io, &gdbctx->context,
2104 t, xpt->addr, xpt->val, len))
2106 xpt->type = -1;
2107 return packet_ok;
2109 break;
2112 return packet_error;
2115 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
2117 void* addr;
2118 unsigned len;
2119 struct gdb_ctx_Xpoint* xpt;
2120 enum be_xpoint_type t;
2122 /* FIXME: check packet_len */
2123 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2124 gdbctx->in_packet[1] != ',' ||
2125 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2126 return packet_error;
2127 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2128 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
2129 addr, len, gdbctx->in_packet[0]);
2130 switch (gdbctx->in_packet[0])
2132 case '0': t = be_xpoint_break; len = 0; break;
2133 case '1': t = be_xpoint_watch_exec; break;
2134 case '2': t = be_xpoint_watch_read; break;
2135 case '3': t = be_xpoint_watch_write; break;
2136 default: return packet_error;
2138 /* because of packet command handling, this should be made idempotent */
2139 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2141 if (xpt->addr == addr && xpt->type == t)
2142 return packet_ok; /* nothing to do */
2144 /* really set the Xpoint */
2145 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2147 if (xpt->type == -1)
2149 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2150 gdbctx->process->process_io, &gdbctx->context,
2151 t, addr, &xpt->val, len))
2153 xpt->addr = addr;
2154 xpt->type = t;
2155 return packet_ok;
2157 fprintf(stderr, "cannot set xpoint\n");
2158 break;
2161 /* no more entries... eech */
2162 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2163 return packet_error;
2166 /* =============================================== *
2167 * P A C K E T I N F R A S T R U C T U R E *
2168 * =============================================== *
2171 struct packet_entry
2173 char key;
2174 enum packet_return (*handler)(struct gdb_context* gdbctx);
2177 static struct packet_entry packet_entries[] =
2179 /*{'!', packet_extended}, */
2180 {'?', packet_last_signal},
2181 {'c', packet_continue},
2182 {'C', packet_continue_signal},
2183 {'D', packet_detach},
2184 {'g', packet_read_registers},
2185 {'G', packet_write_registers},
2186 {'k', packet_kill},
2187 {'H', packet_thread},
2188 {'m', packet_read_memory},
2189 {'M', packet_write_memory},
2190 {'p', packet_read_register},
2191 {'P', packet_write_register},
2192 {'q', packet_query},
2193 /* {'Q', packet_set}, */
2194 /* {'R', packet,restart}, only in extended mode ! */
2195 {'s', packet_step},
2196 /*{'S', packet_step_signal}, hard(er) to implement */
2197 {'T', packet_thread_alive},
2198 {'v', packet_verbose},
2199 {'z', packet_remove_breakpoint},
2200 {'Z', packet_set_breakpoint},
2203 static BOOL extract_packets(struct gdb_context* gdbctx)
2205 char* end;
2206 int plen;
2207 unsigned char in_cksum, loc_cksum;
2208 char* ptr;
2209 enum packet_return ret = packet_error;
2210 int num_packet = 0;
2212 while ((ret & packet_last_f) == 0)
2214 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2215 fprintf(stderr, "In-buf: %*.*s\n",
2216 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2217 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2218 if (ptr == NULL) return FALSE;
2219 if (ptr != gdbctx->in_buf)
2221 int glen = ptr - gdbctx->in_buf; /* garbage len */
2222 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2223 fprintf(stderr, "Removing garbage: %*.*s\n",
2224 glen, glen, gdbctx->in_buf);
2225 gdbctx->in_len -= glen;
2226 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2228 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2229 if (end == NULL) return FALSE;
2230 /* no checksum yet */
2231 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2232 plen = end - gdbctx->in_buf - 1;
2233 hex_from(&in_cksum, end + 1, 1);
2234 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2235 if (loc_cksum == in_cksum)
2237 if (num_packet == 0) {
2238 int i;
2240 ret = packet_error;
2242 write(gdbctx->sock, "+", 1);
2243 assert(plen);
2245 /* FIXME: should use bsearch if packet_entries was sorted */
2246 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2248 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2250 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2252 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2253 fprintf(stderr, "Unknown packet request %*.*s\n",
2254 plen, plen, &gdbctx->in_buf[1]);
2256 else
2258 gdbctx->in_packet = gdbctx->in_buf + 2;
2259 gdbctx->in_packet_len = plen - 1;
2260 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2261 fprintf(stderr, "Packet: %c%*.*s\n",
2262 gdbctx->in_buf[1],
2263 gdbctx->in_packet_len, gdbctx->in_packet_len,
2264 gdbctx->in_packet);
2265 ret = (packet_entries[i].handler)(gdbctx);
2267 switch (ret & ~packet_last_f)
2269 case packet_error: packet_reply(gdbctx, "", 0); break;
2270 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2271 case packet_done: break;
2273 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2274 fprintf(stderr, "Reply-full: %*.*s\n",
2275 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2276 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2277 assert(i == gdbctx->out_len);
2278 /* if this fails, we'll have to use POLLOUT...
2280 gdbctx->out_len = 0;
2281 num_packet++;
2283 else
2285 /* FIXME: If we have more than one packet in our input buffer,
2286 * it's very likely that we took too long to answer to a given packet
2287 * and gdb is sending us the same packet again.
2288 * So we simply drop the second packet. This will lower the risk of error,
2289 * but there's still some race conditions here.
2290 * A better fix (yet not perfect) would be to have two threads:
2291 * - one managing the packets for gdb
2292 * - the second one managing the commands...
2293 * This would allow us to send the reply with the '+' character (Ack of
2294 * the command) way sooner than we do now.
2296 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2297 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2300 else
2302 write(gdbctx->sock, "+", 1);
2303 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2304 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2306 gdbctx->in_len -= plen + 4;
2307 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2309 return TRUE;
2312 static int fetch_data(struct gdb_context* gdbctx)
2314 int len, in_len = gdbctx->in_len;
2316 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2317 for (;;)
2319 #define STEP 128
2320 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2321 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2322 #undef STEP
2323 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2324 fprintf(stderr, "%d %d %*.*s\n",
2325 gdbctx->in_len, gdbctx->in_buf_alloc,
2326 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2327 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2328 if (len <= 0) break;
2329 gdbctx->in_len += len;
2330 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2331 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2333 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2334 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2335 return gdbctx->in_len - in_len;
2338 #define FLAG_NO_START 1
2339 #define FLAG_WITH_XTERM 2
2341 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2343 char buf[MAX_PATH];
2344 int fd;
2345 const char* gdb_path;
2346 FILE* f;
2348 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2349 strcpy(buf,"/tmp/winegdb.XXXXXX");
2350 fd = mkstemps(buf, 0);
2351 if (fd == -1) return FALSE;
2352 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2353 fprintf(f, "file %s\n", wine_path);
2354 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2355 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2356 fprintf(f, "set prompt Wine-gdb>\\ \n");
2357 /* gdb 5.1 seems to require it, won't hurt anyway */
2358 fprintf(f, "sharedlibrary\n");
2359 /* This is needed (but not a decent & final fix)
2360 * Without this, gdb would skip our inter-DLL relay code (because
2361 * we don't have any line number information for the relay code)
2362 * With this, we will stop on first instruction of the stub, and
2363 * reusing step, will get us through the relay stub at the actual
2364 * function we're looking at.
2366 fprintf(f, "set step-mode on\n");
2367 /* tell gdb to delete this file when done handling it... */
2368 fprintf(f, "shell rm -f \"%s\"\n", buf);
2369 fclose(f);
2370 if (flags & FLAG_WITH_XTERM)
2371 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2372 else
2373 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2374 assert(0); /* never reached */
2375 return TRUE;
2378 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2380 int sock;
2381 struct sockaddr_in s_addrs;
2382 socklen_t s_len = sizeof(s_addrs);
2383 struct pollfd pollfd;
2384 IMAGEHLP_MODULE64 imh_mod;
2385 BOOL ret = FALSE;
2387 /* step 1: create socket for gdb connection request */
2388 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2390 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2391 fprintf(stderr, "Can't create socket");
2392 return FALSE;
2395 if (listen(sock, 1) == -1 || getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2396 goto cleanup;
2398 /* step 2: do the process internal creation */
2399 handle_debug_event(gdbctx, de);
2401 /* step3: get the wine loader name */
2402 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod))
2403 goto cleanup;
2405 /* step 4: fire up gdb (if requested) */
2406 if (flags & FLAG_NO_START)
2407 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2408 else
2409 switch (fork())
2411 case -1: /* error in parent... */
2412 fprintf(stderr, "Cannot create gdb\n");
2413 goto cleanup;
2414 default: /* in parent... success */
2415 signal(SIGINT, SIG_IGN);
2416 break;
2417 case 0: /* in child... and alive */
2418 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2419 /* if we're here, exec failed, so report failure */
2420 goto cleanup;
2423 /* step 5: wait for gdb to connect actually */
2424 pollfd.fd = sock;
2425 pollfd.events = POLLIN;
2426 pollfd.revents = 0;
2428 switch (poll(&pollfd, 1, -1))
2430 case 1:
2431 if (pollfd.revents & POLLIN)
2433 int dummy = 1;
2434 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2435 if (gdbctx->sock == -1)
2436 break;
2437 ret = TRUE;
2438 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2439 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2440 /* don't keep our small packets too long: send them ASAP back to GDB
2441 * without this, GDB really crawls
2443 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2445 break;
2446 case 0:
2447 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2448 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2449 break;
2450 case -1:
2451 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2452 fprintf(stderr, "Poll for cnx failed (error)\n");
2453 break;
2454 default:
2455 assert(0);
2458 cleanup:
2459 close(sock);
2460 return ret;
2463 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2465 DEBUG_EVENT de;
2466 int i;
2468 gdbctx->sock = -1;
2469 gdbctx->in_buf = NULL;
2470 gdbctx->in_buf_alloc = 0;
2471 gdbctx->in_len = 0;
2472 gdbctx->out_buf = NULL;
2473 gdbctx->out_buf_alloc = 0;
2474 gdbctx->out_len = 0;
2475 gdbctx->out_curr_packet = -1;
2477 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2478 gdbctx->last_sig = 0;
2479 gdbctx->in_trap = FALSE;
2480 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2481 gdbctx->process = NULL;
2482 for (i = 0; i < NUM_XPOINT; i++)
2483 gdbctx->Xpoints[i].type = -1;
2484 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2485 gdbctx->wine_segs[i] = 0;
2487 /* wait for first trap */
2488 while (WaitForDebugEvent(&de, INFINITE))
2490 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2492 /* this should be the first event we get,
2493 * and the only one of this type */
2494 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2495 /* gdbctx->dwProcessId = pid; */
2496 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2497 assert(!gdbctx->in_trap);
2499 else
2501 handle_debug_event(gdbctx, &de);
2502 if (gdbctx->in_trap) break;
2504 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2506 return TRUE;
2509 static int gdb_remote(unsigned flags)
2511 struct pollfd pollfd;
2512 struct gdb_context gdbctx;
2513 BOOL doLoop;
2515 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2517 pollfd.fd = gdbctx.sock;
2518 pollfd.events = POLLIN;
2519 pollfd.revents = 0;
2521 switch (poll(&pollfd, 1, -1))
2523 case 1:
2524 /* got something */
2525 if (pollfd.revents & (POLLHUP | POLLERR))
2527 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2528 fprintf(stderr, "Gdb hung up\n");
2529 /* kill also debuggee process - questionnable - */
2530 detach_debuggee(&gdbctx, TRUE);
2531 doLoop = FALSE;
2532 break;
2534 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2536 if (extract_packets(&gdbctx)) doLoop = FALSE;
2538 break;
2539 case 0:
2540 /* timeout, should never happen (infinite timeout) */
2541 break;
2542 case -1:
2543 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2544 fprintf(stderr, "Poll failed\n");
2545 doLoop = FALSE;
2546 break;
2549 wait(NULL);
2550 return 0;
2552 #endif
2554 int gdb_main(int argc, char* argv[])
2556 #ifdef HAVE_POLL
2557 unsigned gdb_flags = 0;
2559 argc--; argv++;
2560 while (argc > 0 && argv[0][0] == '-')
2562 if (strcmp(argv[0], "--no-start") == 0)
2564 gdb_flags |= FLAG_NO_START;
2565 argc--; argv++;
2566 continue;
2568 if (strcmp(argv[0], "--with-xterm") == 0)
2570 gdb_flags |= FLAG_WITH_XTERM;
2571 argc--; argv++;
2572 continue;
2574 return -1;
2576 if (dbg_active_attach(argc, argv) == start_ok ||
2577 dbg_active_launch(argc, argv) == start_ok)
2578 return gdb_remote(gdb_flags);
2579 #else
2580 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2581 #endif
2582 return -1;