quartz: Make the memory allocator emit more warnings and fix race condition.
[wine/wine64.git] / programs / winedbg / gdbproxy.c
blob2fbec0461478d472a524d0eea8cbccf417c92711
1 /*
2 * A Win32 based proxy implementing the GBD remote protocol
3 * This allows to debug Wine (and any "emulated" program) under
4 * 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_32.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 struct be_process_io be_process_gdbproxy_io =
116 NULL, /* we shouldn't use close_process() in gdbproxy */
117 ReadProcessMemory,
118 WriteProcessMemory
121 /* =============================================== *
122 * B A S I C M A N I P U L A T I O N S *
123 * =============================================== *
126 static inline int hex_from0(char ch)
128 if (ch >= '0' && ch <= '9') return ch - '0';
129 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
130 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
132 assert(0);
133 return 0;
136 static inline unsigned char hex_to0(int x)
138 assert(x >= 0 && x < 16);
139 return "0123456789abcdef"[x];
142 static int hex_to_int(const char* src, size_t len)
144 unsigned int returnval = 0;
145 while (len--)
147 returnval <<= 4;
148 returnval |= hex_from0(*src++);
150 return returnval;
153 static void hex_from(void* dst, const char* src, size_t len)
155 unsigned char *p = dst;
156 while (len--)
158 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
159 src += 2;
163 static void hex_to(char* dst, const void* src, size_t len)
165 const unsigned char *p = src;
166 while (len--)
168 *dst++ = hex_to0(*p >> 4);
169 *dst++ = hex_to0(*p & 0x0F);
170 p++;
174 static unsigned char checksum(const char* ptr, int len)
176 unsigned cksum = 0;
178 while (len-- > 0)
179 cksum += (unsigned char)*ptr++;
180 return cksum;
183 /* =============================================== *
184 * C P U H A N D L E R S *
185 * =============================================== *
188 #ifdef __i386__
189 static size_t cpu_register_map[] = {
190 FIELD_OFFSET(CONTEXT, Eax),
191 FIELD_OFFSET(CONTEXT, Ecx),
192 FIELD_OFFSET(CONTEXT, Edx),
193 FIELD_OFFSET(CONTEXT, Ebx),
194 FIELD_OFFSET(CONTEXT, Esp),
195 FIELD_OFFSET(CONTEXT, Ebp),
196 FIELD_OFFSET(CONTEXT, Esi),
197 FIELD_OFFSET(CONTEXT, Edi),
198 FIELD_OFFSET(CONTEXT, Eip),
199 FIELD_OFFSET(CONTEXT, EFlags),
200 FIELD_OFFSET(CONTEXT, SegCs),
201 FIELD_OFFSET(CONTEXT, SegSs),
202 FIELD_OFFSET(CONTEXT, SegDs),
203 FIELD_OFFSET(CONTEXT, SegEs),
204 FIELD_OFFSET(CONTEXT, SegFs),
205 FIELD_OFFSET(CONTEXT, SegGs),
207 #elif defined(__powerpc__)
208 static size_t cpu_register_map[] = {
209 FIELD_OFFSET(CONTEXT, Gpr0),
210 FIELD_OFFSET(CONTEXT, Gpr1),
211 FIELD_OFFSET(CONTEXT, Gpr2),
212 FIELD_OFFSET(CONTEXT, Gpr3),
213 FIELD_OFFSET(CONTEXT, Gpr4),
214 FIELD_OFFSET(CONTEXT, Gpr5),
215 FIELD_OFFSET(CONTEXT, Gpr6),
216 FIELD_OFFSET(CONTEXT, Gpr7),
217 FIELD_OFFSET(CONTEXT, Gpr8),
218 FIELD_OFFSET(CONTEXT, Gpr9),
219 FIELD_OFFSET(CONTEXT, Gpr10),
220 FIELD_OFFSET(CONTEXT, Gpr11),
221 FIELD_OFFSET(CONTEXT, Gpr12),
222 FIELD_OFFSET(CONTEXT, Gpr13),
223 FIELD_OFFSET(CONTEXT, Gpr14),
224 FIELD_OFFSET(CONTEXT, Gpr15),
225 FIELD_OFFSET(CONTEXT, Gpr16),
226 FIELD_OFFSET(CONTEXT, Gpr17),
227 FIELD_OFFSET(CONTEXT, Gpr18),
228 FIELD_OFFSET(CONTEXT, Gpr19),
229 FIELD_OFFSET(CONTEXT, Gpr20),
230 FIELD_OFFSET(CONTEXT, Gpr21),
231 FIELD_OFFSET(CONTEXT, Gpr22),
232 FIELD_OFFSET(CONTEXT, Gpr23),
233 FIELD_OFFSET(CONTEXT, Gpr24),
234 FIELD_OFFSET(CONTEXT, Gpr25),
235 FIELD_OFFSET(CONTEXT, Gpr26),
236 FIELD_OFFSET(CONTEXT, Gpr27),
237 FIELD_OFFSET(CONTEXT, Gpr28),
238 FIELD_OFFSET(CONTEXT, Gpr29),
239 FIELD_OFFSET(CONTEXT, Gpr30),
240 FIELD_OFFSET(CONTEXT, Gpr31),
241 FIELD_OFFSET(CONTEXT, Fpr0),
242 FIELD_OFFSET(CONTEXT, Fpr1),
243 FIELD_OFFSET(CONTEXT, Fpr2),
244 FIELD_OFFSET(CONTEXT, Fpr3),
245 FIELD_OFFSET(CONTEXT, Fpr4),
246 FIELD_OFFSET(CONTEXT, Fpr5),
247 FIELD_OFFSET(CONTEXT, Fpr6),
248 FIELD_OFFSET(CONTEXT, Fpr7),
249 FIELD_OFFSET(CONTEXT, Fpr8),
250 FIELD_OFFSET(CONTEXT, Fpr9),
251 FIELD_OFFSET(CONTEXT, Fpr10),
252 FIELD_OFFSET(CONTEXT, Fpr11),
253 FIELD_OFFSET(CONTEXT, Fpr12),
254 FIELD_OFFSET(CONTEXT, Fpr13),
255 FIELD_OFFSET(CONTEXT, Fpr14),
256 FIELD_OFFSET(CONTEXT, Fpr15),
257 FIELD_OFFSET(CONTEXT, Fpr16),
258 FIELD_OFFSET(CONTEXT, Fpr17),
259 FIELD_OFFSET(CONTEXT, Fpr18),
260 FIELD_OFFSET(CONTEXT, Fpr19),
261 FIELD_OFFSET(CONTEXT, Fpr20),
262 FIELD_OFFSET(CONTEXT, Fpr21),
263 FIELD_OFFSET(CONTEXT, Fpr22),
264 FIELD_OFFSET(CONTEXT, Fpr23),
265 FIELD_OFFSET(CONTEXT, Fpr24),
266 FIELD_OFFSET(CONTEXT, Fpr25),
267 FIELD_OFFSET(CONTEXT, Fpr26),
268 FIELD_OFFSET(CONTEXT, Fpr27),
269 FIELD_OFFSET(CONTEXT, Fpr28),
270 FIELD_OFFSET(CONTEXT, Fpr29),
271 FIELD_OFFSET(CONTEXT, Fpr30),
272 FIELD_OFFSET(CONTEXT, Fpr31),
274 FIELD_OFFSET(CONTEXT, Iar),
275 FIELD_OFFSET(CONTEXT, Msr),
276 FIELD_OFFSET(CONTEXT, Cr),
277 FIELD_OFFSET(CONTEXT, Lr),
278 FIELD_OFFSET(CONTEXT, Ctr),
279 FIELD_OFFSET(CONTEXT, Xer),
280 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
281 /* see gdb/nlm/ppc.c */
283 #elif defined(__ALPHA__)
284 static size_t cpu_register_map[] = {
285 FIELD_OFFSET(CONTEXT, IntV0),
286 FIELD_OFFSET(CONTEXT, IntT0),
287 FIELD_OFFSET(CONTEXT, IntT1),
288 FIELD_OFFSET(CONTEXT, IntT2),
289 FIELD_OFFSET(CONTEXT, IntT3),
290 FIELD_OFFSET(CONTEXT, IntT4),
291 FIELD_OFFSET(CONTEXT, IntT5),
292 FIELD_OFFSET(CONTEXT, IntT6),
293 FIELD_OFFSET(CONTEXT, IntT7),
294 FIELD_OFFSET(CONTEXT, IntS0),
295 FIELD_OFFSET(CONTEXT, IntS1),
296 FIELD_OFFSET(CONTEXT, IntS2),
297 FIELD_OFFSET(CONTEXT, IntS3),
298 FIELD_OFFSET(CONTEXT, IntS4),
299 FIELD_OFFSET(CONTEXT, IntS5),
300 FIELD_OFFSET(CONTEXT, IntFp),
301 FIELD_OFFSET(CONTEXT, IntA0),
302 FIELD_OFFSET(CONTEXT, IntA1),
303 FIELD_OFFSET(CONTEXT, IntA2),
304 FIELD_OFFSET(CONTEXT, IntA3),
305 FIELD_OFFSET(CONTEXT, IntA4),
306 FIELD_OFFSET(CONTEXT, IntA5),
307 FIELD_OFFSET(CONTEXT, IntT8),
308 FIELD_OFFSET(CONTEXT, IntT9),
309 FIELD_OFFSET(CONTEXT, IntT10),
310 FIELD_OFFSET(CONTEXT, IntT11),
311 FIELD_OFFSET(CONTEXT, IntRa),
312 FIELD_OFFSET(CONTEXT, IntT12),
313 FIELD_OFFSET(CONTEXT, IntAt),
314 FIELD_OFFSET(CONTEXT, IntGp),
315 FIELD_OFFSET(CONTEXT, IntSp),
316 FIELD_OFFSET(CONTEXT, IntZero),
317 FIELD_OFFSET(CONTEXT, FltF0),
318 FIELD_OFFSET(CONTEXT, FltF1),
319 FIELD_OFFSET(CONTEXT, FltF2),
320 FIELD_OFFSET(CONTEXT, FltF3),
321 FIELD_OFFSET(CONTEXT, FltF4),
322 FIELD_OFFSET(CONTEXT, FltF5),
323 FIELD_OFFSET(CONTEXT, FltF6),
324 FIELD_OFFSET(CONTEXT, FltF7),
325 FIELD_OFFSET(CONTEXT, FltF8),
326 FIELD_OFFSET(CONTEXT, FltF9),
327 FIELD_OFFSET(CONTEXT, FltF10),
328 FIELD_OFFSET(CONTEXT, FltF11),
329 FIELD_OFFSET(CONTEXT, FltF12),
330 FIELD_OFFSET(CONTEXT, FltF13),
331 FIELD_OFFSET(CONTEXT, FltF14),
332 FIELD_OFFSET(CONTEXT, FltF15),
333 FIELD_OFFSET(CONTEXT, FltF16),
334 FIELD_OFFSET(CONTEXT, FltF17),
335 FIELD_OFFSET(CONTEXT, FltF18),
336 FIELD_OFFSET(CONTEXT, FltF19),
337 FIELD_OFFSET(CONTEXT, FltF20),
338 FIELD_OFFSET(CONTEXT, FltF21),
339 FIELD_OFFSET(CONTEXT, FltF22),
340 FIELD_OFFSET(CONTEXT, FltF23),
341 FIELD_OFFSET(CONTEXT, FltF24),
342 FIELD_OFFSET(CONTEXT, FltF25),
343 FIELD_OFFSET(CONTEXT, FltF26),
344 FIELD_OFFSET(CONTEXT, FltF27),
345 FIELD_OFFSET(CONTEXT, FltF28),
346 FIELD_OFFSET(CONTEXT, FltF29),
347 FIELD_OFFSET(CONTEXT, FltF30),
348 FIELD_OFFSET(CONTEXT, FltF31),
350 /* FIXME: Didn't look for the right order yet */
351 FIELD_OFFSET(CONTEXT, Fir),
352 FIELD_OFFSET(CONTEXT, Fpcr),
353 FIELD_OFFSET(CONTEXT, SoftFpcr),
355 #elif defined(__x86_64__)
356 static size_t cpu_register_map[] = {
357 FIELD_OFFSET(CONTEXT, Rax),
358 FIELD_OFFSET(CONTEXT, Rbx),
359 FIELD_OFFSET(CONTEXT, Rcx),
360 FIELD_OFFSET(CONTEXT, Rdx),
361 FIELD_OFFSET(CONTEXT, Rsi),
362 FIELD_OFFSET(CONTEXT, Rdi),
363 FIELD_OFFSET(CONTEXT, Rbp),
364 FIELD_OFFSET(CONTEXT, Rsp),
365 FIELD_OFFSET(CONTEXT, R8),
366 FIELD_OFFSET(CONTEXT, R9),
367 FIELD_OFFSET(CONTEXT, R10),
368 FIELD_OFFSET(CONTEXT, R11),
369 FIELD_OFFSET(CONTEXT, R12),
370 FIELD_OFFSET(CONTEXT, R13),
371 FIELD_OFFSET(CONTEXT, R14),
372 FIELD_OFFSET(CONTEXT, R15),
373 FIELD_OFFSET(CONTEXT, Rip),
374 FIELD_OFFSET(CONTEXT, EFlags),
375 FIELD_OFFSET(CONTEXT, SegCs),
376 FIELD_OFFSET(CONTEXT, SegSs),
377 FIELD_OFFSET(CONTEXT, SegDs),
378 FIELD_OFFSET(CONTEXT, SegEs),
379 FIELD_OFFSET(CONTEXT, SegFs),
380 FIELD_OFFSET(CONTEXT, SegGs),
382 #else
383 # error Define the registers map for your CPU
384 #endif
386 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
388 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
390 assert(idx < cpu_num_regs);
391 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
394 /* =============================================== *
395 * W I N 3 2 D E B U G I N T E R F A C E *
396 * =============================================== *
399 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
401 ctx->ContextFlags = CONTEXT_CONTROL
402 | CONTEXT_INTEGER
403 #ifdef CONTEXT_SEGMENTS
404 | CONTEXT_SEGMENTS
405 #endif
406 #ifdef CONTEXT_DEBUG_REGISTERS
407 | CONTEXT_DEBUG_REGISTERS
408 #endif
410 if (!GetThreadContext(h, ctx))
412 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
413 fprintf(stderr, "Can't get thread's context\n");
414 return FALSE;
416 return TRUE;
419 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
421 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
422 BOOL ret = FALSE;
424 switch (rec->ExceptionCode)
426 case EXCEPTION_ACCESS_VIOLATION:
427 case EXCEPTION_PRIV_INSTRUCTION:
428 case EXCEPTION_STACK_OVERFLOW:
429 case EXCEPTION_GUARD_PAGE:
430 gdbctx->last_sig = SIGSEGV;
431 ret = TRUE;
432 break;
433 case EXCEPTION_DATATYPE_MISALIGNMENT:
434 gdbctx->last_sig = SIGBUS;
435 ret = TRUE;
436 break;
437 case EXCEPTION_SINGLE_STEP:
438 /* fall thru */
439 case EXCEPTION_BREAKPOINT:
440 gdbctx->last_sig = SIGTRAP;
441 ret = TRUE;
442 break;
443 case EXCEPTION_FLT_DENORMAL_OPERAND:
444 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
445 case EXCEPTION_FLT_INEXACT_RESULT:
446 case EXCEPTION_FLT_INVALID_OPERATION:
447 case EXCEPTION_FLT_OVERFLOW:
448 case EXCEPTION_FLT_STACK_CHECK:
449 case EXCEPTION_FLT_UNDERFLOW:
450 gdbctx->last_sig = SIGFPE;
451 ret = TRUE;
452 break;
453 case EXCEPTION_INT_DIVIDE_BY_ZERO:
454 case EXCEPTION_INT_OVERFLOW:
455 gdbctx->last_sig = SIGFPE;
456 ret = TRUE;
457 break;
458 case EXCEPTION_ILLEGAL_INSTRUCTION:
459 gdbctx->last_sig = SIGILL;
460 ret = TRUE;
461 break;
462 case CONTROL_C_EXIT:
463 gdbctx->last_sig = SIGINT;
464 ret = TRUE;
465 break;
466 case STATUS_POSSIBLE_DEADLOCK:
467 gdbctx->last_sig = SIGALRM;
468 ret = TRUE;
469 /* FIXME: we could also add here a O packet with additional information */
470 break;
471 default:
472 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
473 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
474 gdbctx->last_sig = SIGABRT;
475 ret = TRUE;
476 break;
478 return ret;
481 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
483 char buffer[256];
485 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
487 switch (de->dwDebugEventCode)
489 case CREATE_PROCESS_DEBUG_EVENT:
490 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
491 de->u.CreateProcessInfo.hProcess);
492 if (!gdbctx->process) break;
493 memory_get_string_indirect(gdbctx->process,
494 de->u.CreateProcessInfo.lpImageName,
495 de->u.CreateProcessInfo.fUnicode,
496 buffer, sizeof(buffer));
497 dbg_set_process_name(gdbctx->process, buffer);
499 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
500 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
501 de->dwProcessId, de->dwThreadId,
502 buffer, de->u.CreateProcessInfo.lpImageName,
503 de->u.CreateProcessInfo.lpStartAddress,
504 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
505 de->u.CreateProcessInfo.nDebugInfoSize);
507 /* de->u.CreateProcessInfo.lpStartAddress; */
508 if (!SymInitialize(gdbctx->process->handle, NULL, TRUE))
509 fprintf(stderr, "Couldn't initiate DbgHelp\n");
511 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
512 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
513 de->dwProcessId, de->dwThreadId,
514 de->u.CreateProcessInfo.lpStartAddress);
516 assert(dbg_curr_thread == NULL); /* shouldn't be there */
517 dbg_add_thread(gdbctx->process, de->dwThreadId,
518 de->u.CreateProcessInfo.hThread,
519 de->u.CreateProcessInfo.lpThreadLocalBase);
520 break;
522 case LOAD_DLL_DEBUG_EVENT:
523 assert(dbg_curr_thread);
524 memory_get_string_indirect(gdbctx->process,
525 de->u.LoadDll.lpImageName,
526 de->u.LoadDll.fUnicode,
527 buffer, sizeof(buffer));
528 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
529 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
530 de->dwProcessId, de->dwThreadId,
531 buffer, de->u.LoadDll.lpBaseOfDll,
532 de->u.LoadDll.dwDebugInfoFileOffset,
533 de->u.LoadDll.nDebugInfoSize);
534 SymLoadModule(gdbctx->process->handle, de->u.LoadDll.hFile, buffer, NULL,
535 (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
536 break;
538 case UNLOAD_DLL_DEBUG_EVENT:
539 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
540 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
541 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
542 SymUnloadModule(gdbctx->process->handle,
543 (unsigned long)de->u.UnloadDll.lpBaseOfDll);
544 break;
546 case EXCEPTION_DEBUG_EVENT:
547 assert(dbg_curr_thread);
548 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
549 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
550 de->dwProcessId, de->dwThreadId,
551 de->u.Exception.ExceptionRecord.ExceptionCode);
553 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
555 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
557 break;
559 case CREATE_THREAD_DEBUG_EVENT:
560 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
561 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
562 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
564 dbg_add_thread(gdbctx->process,
565 de->dwThreadId,
566 de->u.CreateThread.hThread,
567 de->u.CreateThread.lpThreadLocalBase);
568 break;
570 case EXIT_THREAD_DEBUG_EVENT:
571 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
572 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
573 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
575 assert(dbg_curr_thread);
576 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
577 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
578 dbg_del_thread(dbg_curr_thread);
579 break;
581 case EXIT_PROCESS_DEBUG_EVENT:
582 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
583 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
584 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
586 dbg_del_process(gdbctx->process);
587 gdbctx->process = NULL;
588 /* now signal gdb that we're done */
589 gdbctx->last_sig = SIGTERM;
590 gdbctx->in_trap = TRUE;
591 break;
593 case OUTPUT_DEBUG_STRING_EVENT:
594 assert(dbg_curr_thread);
595 memory_get_string(gdbctx->process,
596 de->u.DebugString.lpDebugStringData, TRUE,
597 de->u.DebugString.fUnicode, buffer, sizeof(buffer));
598 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
599 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
600 de->dwProcessId, de->dwThreadId, buffer);
601 break;
603 case RIP_EVENT:
604 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
605 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
606 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
607 de->u.RipInfo.dwType);
608 break;
610 default:
611 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
612 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
613 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
617 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
619 if (dbg_curr_thread)
621 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
622 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
623 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
624 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
625 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
626 fprintf(stderr, "Cannot continue on %04x (%x)\n",
627 dbg_curr_thread->tid, cont);
629 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
630 fprintf(stderr, "Cannot find last thread\n");
634 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
637 if (dbg_curr_thread)
639 if(dbg_curr_thread->tid == threadid){
640 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
641 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
642 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
643 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
644 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
645 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
646 fprintf(stderr, "Cannot continue on %04x (%x)\n",
647 dbg_curr_thread->tid, cont);
650 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
651 fprintf(stderr, "Cannot find last thread\n");
654 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
656 struct pollfd pollfd;
657 int ret;
658 char pkt;
660 pollfd.fd = gdbctx->sock;
661 pollfd.events = POLLIN;
662 pollfd.revents = 0;
664 if ((ret = poll(&pollfd, 1, 0)) == 1) {
665 ret = read(gdbctx->sock, &pkt, 1);
666 if (ret != 1) {
667 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
668 fprintf(stderr, "read failed\n");
670 return FALSE;
672 if (pkt != '\003') {
673 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
674 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
676 return FALSE;
678 return TRUE;
679 } else if (ret == -1) {
680 fprintf(stderr, "poll failed\n");
682 return FALSE;
685 static void wait_for_debuggee(struct gdb_context* gdbctx)
687 DEBUG_EVENT de;
689 gdbctx->in_trap = FALSE;
690 for (;;)
692 if (!WaitForDebugEvent(&de, 10))
694 if (GetLastError() == ERROR_SEM_TIMEOUT)
696 if (check_for_interrupt(gdbctx)) {
697 if (!DebugBreakProcess(gdbctx->process->handle)) {
698 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
699 fprintf(stderr, "Failed to break into debugee\n");
701 break;
703 WaitForDebugEvent(&de, INFINITE);
704 } else {
705 continue;
707 } else {
708 break;
711 handle_debug_event(gdbctx, &de);
712 assert(!gdbctx->process ||
713 gdbctx->process->pid == 0 ||
714 de.dwProcessId == gdbctx->process->pid);
715 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
716 if (gdbctx->in_trap) break;
717 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
721 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
723 be_cpu->single_step(&gdbctx->context, FALSE);
724 resume_debuggee(gdbctx, DBG_CONTINUE);
725 if (!kill)
726 DebugActiveProcessStop(gdbctx->process->pid);
727 dbg_del_process(gdbctx->process);
728 gdbctx->process = NULL;
731 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
733 DWORD status;
735 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
737 strcpy(buffer, "Unknown process");
738 return;
740 if (status == STILL_ACTIVE)
742 strcpy(buffer, "Running");
744 else
745 snprintf(buffer, len, "Terminated (%u)", status);
747 switch (GetPriorityClass(gdbctx->process->handle))
749 case 0: break;
750 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
751 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
752 #endif
753 #ifdef BELOW_NORMAL_PRIORITY_CLASS
754 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
755 #endif
756 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
757 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
758 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
759 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
761 strcat(buffer, "\n");
764 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
765 char* buffer, size_t len)
767 struct dbg_thread* thd;
768 DWORD status;
769 int prio;
771 /* FIXME: use the size of buffer */
772 thd = dbg_get_thread(gdbctx->process, tid);
773 if (thd == NULL)
775 strcpy(buffer, "No information");
776 return;
778 if (GetExitCodeThread(thd->handle, &status))
780 if (status == STILL_ACTIVE)
782 /* FIXME: this is a bit brutal... some nicer way shall be found */
783 switch (status = SuspendThread(thd->handle))
785 case -1: break;
786 case 0: strcpy(buffer, "Running"); break;
787 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
789 ResumeThread(thd->handle);
791 else
792 snprintf(buffer, len, "Terminated (exit code = %u)", status);
794 else
796 strcpy(buffer, "Unknown threadID");
798 switch (prio = GetThreadPriority(thd->handle))
800 case THREAD_PRIORITY_ERROR_RETURN: break;
801 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
802 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
803 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
804 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
805 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
806 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
807 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
808 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
810 assert(strlen(buffer) < len);
813 /* =============================================== *
814 * P A C K E T U T I L S *
815 * =============================================== *
818 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
819 packet_last_f = 0x80};
821 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
823 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
825 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
826 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
830 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
832 packet_reply_grow(gdbctx, len * 2);
833 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
834 gdbctx->out_len += len * 2;
837 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
839 packet_reply_hex_to(gdbctx, src, strlen(src));
842 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
844 int i, shift;
846 shift = (len - 1) * 8;
847 packet_reply_grow(gdbctx, len * 2);
848 for (i = 0; i < len; i++, shift -= 8)
850 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
851 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
855 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
857 packet_reply_grow(gdbctx, len);
858 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
859 gdbctx->out_len += len;
862 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
864 packet_reply_add(gdbctx, str, strlen(str));
867 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
869 packet_reply_add(gdbctx, &ch, 1);
872 static void packet_reply_open(struct gdb_context* gdbctx)
874 assert(gdbctx->out_curr_packet == -1);
875 packet_reply_catc(gdbctx, '$');
876 gdbctx->out_curr_packet = gdbctx->out_len;
879 static void packet_reply_close(struct gdb_context* gdbctx)
881 unsigned char cksum;
882 int plen;
884 plen = gdbctx->out_len - gdbctx->out_curr_packet;
885 packet_reply_catc(gdbctx, '#');
886 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
887 packet_reply_hex_to(gdbctx, &cksum, 1);
888 if (gdbctx->trace & GDBPXY_TRC_PACKET)
889 fprintf(stderr, "Reply : %*.*s\n",
890 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
891 gdbctx->out_curr_packet = -1;
894 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
896 packet_reply_open(gdbctx);
898 if (len == -1) len = strlen(packet);
899 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
901 packet_reply_add(gdbctx, packet, len);
903 packet_reply_close(gdbctx);
905 return packet_done;
908 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
910 packet_reply_open(gdbctx);
912 packet_reply_add(gdbctx, "E", 1);
913 packet_reply_val(gdbctx, error, 1);
915 packet_reply_close(gdbctx);
917 return packet_done;
920 /* =============================================== *
921 * P A C K E T H A N D L E R S *
922 * =============================================== *
925 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
927 enum packet_return ret = packet_done;
929 packet_reply_open(gdbctx);
931 if (gdbctx->process != NULL)
933 unsigned char sig;
934 unsigned i;
936 packet_reply_catc(gdbctx, 'T');
937 sig = gdbctx->last_sig;
938 packet_reply_val(gdbctx, sig, 1);
939 packet_reply_add(gdbctx, "thread:", 7);
940 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
941 packet_reply_catc(gdbctx, ';');
943 for (i = 0; i < cpu_num_regs; i++)
945 /* FIXME: this call will also grow the buffer...
946 * unneeded, but not harmful
948 packet_reply_val(gdbctx, i, 1);
949 packet_reply_catc(gdbctx, ':');
950 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
951 packet_reply_catc(gdbctx, ';');
954 else
956 /* Try to put an exit code
957 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
958 * just indicate the end of process and exit */
959 packet_reply_add(gdbctx, "W00", 3);
960 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
963 packet_reply_close(gdbctx);
965 return ret;
968 #if 0
969 static enum packet_return packet_extended(struct gdb_context* gdbctx)
971 gdbctx->extended = 1;
972 return packet_ok;
974 #endif
976 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
978 assert(gdbctx->in_packet_len == 0);
979 return packet_reply_status(gdbctx);
982 static enum packet_return packet_continue(struct gdb_context* gdbctx)
984 /* FIXME: add support for address in packet */
985 assert(gdbctx->in_packet_len == 0);
986 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
987 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
988 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
989 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
990 resume_debuggee(gdbctx, DBG_CONTINUE);
991 wait_for_debuggee(gdbctx);
992 return packet_reply_status(gdbctx);
995 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
997 int i;
998 int defaultAction = -1; /* magic non action */
999 unsigned char sig;
1000 int actions =0;
1001 int actionIndex[20]; /* allow for up to 20 actions */
1002 int threadIndex[20];
1003 int threadCount = 0;
1004 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1005 unsigned int threadID = 0;
1006 struct dbg_thread* thd;
1008 /* basic check */
1009 assert(gdbctx->in_packet_len >= 4);
1011 /* OK we have vCont followed by..
1012 * ? for query
1013 * c for packet_continue
1014 * Csig for packet_continue_signal
1015 * s for step
1016 * Ssig for step signal
1017 * and then an optional thread ID at the end..
1018 * *******************************************/
1020 fprintf(stderr, "trying to process a verbose packet\n");
1021 /* now check that we've got Cont */
1022 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
1024 /* Query */
1025 if (gdbctx->in_packet[4] == '?')
1028 Reply:
1029 `vCont[;action]...'
1030 The vCont packet is supported. Each action is a supported command in the vCont packet.
1032 The vCont packet is not supported. (this didn't seem to be obeyed!)
1034 packet_reply_open(gdbctx);
1035 packet_reply_add(gdbctx, "vCont", 5);
1036 /* add all the supported actions to the reply (all of them for now) */
1037 packet_reply_add(gdbctx, ";c", 2);
1038 packet_reply_add(gdbctx, ";C", 2);
1039 packet_reply_add(gdbctx, ";s", 2);
1040 packet_reply_add(gdbctx, ";S", 2);
1041 packet_reply_close(gdbctx);
1042 return packet_done;
1045 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1046 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1047 now if only gdb talked XML.... */
1048 #if 0 /* handy for debugging */
1049 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1050 #endif
1052 /* go through the packet and identify where all the actions start at */
1053 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1055 if (gdbctx->in_packet[i] == ';')
1057 threadIndex[actions] = 0;
1058 actionIndex[actions++] = i;
1060 else if (gdbctx->in_packet[i] == ':')
1062 threadIndex[actions - 1] = i;
1066 /* now look up the default action */
1067 for (i = 0 ; i < actions; i++)
1069 if (threadIndex[i] == 0)
1071 if (defaultAction != -1)
1073 fprintf(stderr,"Too many default actions specified\n");
1074 return packet_error;
1076 defaultAction = i;
1080 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1082 /* go through all the threads and stick their ids in the to be done list. */
1083 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1085 threadIDs[threadCount++] = thd->tid;
1086 /* check to see if we have more threads than I counted on, and tell the user what to do
1087 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1088 if (threadCount == 100)
1090 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1091 break;
1095 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1096 * that remains is to apply the actions to the threads and the default action to any threads
1097 * left */
1098 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1099 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1100 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1101 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1103 /* deal with the threaded stuff first */
1104 for (i = 0; i < actions ; i++)
1106 if (threadIndex[i] != 0)
1108 int j, idLength = 0;
1109 if (i < actions - 1)
1111 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1113 else
1115 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1118 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1119 /* process the action */
1120 switch (gdbctx->in_packet[actionIndex[i] + 1])
1122 case 's': /* step */
1123 be_cpu->single_step(&gdbctx->context, TRUE);
1124 /* fall through*/
1125 case 'c': /* continue */
1126 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1127 break;
1128 case 'S': /* step Sig, */
1129 be_cpu->single_step(&gdbctx->context, TRUE);
1130 /* fall through */
1131 case 'C': /* continue sig */
1132 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1133 /* cannot change signals on the fly */
1134 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1135 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1136 if (sig != gdbctx->last_sig)
1137 return packet_error;
1138 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1139 break;
1141 for (j = 0 ; j < threadCount; j++)
1143 if (threadIDs[j] == threadID)
1145 threadIDs[j] = 0;
1146 break;
1150 } /* for i=0 ; i< actions */
1152 /* now we have manage the default action */
1153 if (defaultAction >= 0)
1155 for (i = 0 ; i< threadCount; i++)
1157 /* check to see if we've already done something to the thread*/
1158 if (threadIDs[i] != 0)
1160 /* if not apply the default action*/
1161 threadID = threadIDs[i];
1162 /* process the action (yes this is almost identical to the one above!) */
1163 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1165 case 's': /* step */
1166 be_cpu->single_step(&gdbctx->context, TRUE);
1167 /* fall through */
1168 case 'c': /* continue */
1169 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1170 break;
1171 case 'S':
1172 be_cpu->single_step(&gdbctx->context, TRUE);
1173 /* fall through */
1174 case 'C': /* continue sig */
1175 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1176 /* cannot change signals on the fly */
1177 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1178 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1179 if (sig != gdbctx->last_sig)
1180 return packet_error;
1181 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1182 break;
1186 } /* if(defaultAction >=0) */
1188 wait_for_debuggee(gdbctx);
1189 be_cpu->single_step(&gdbctx->context, FALSE);
1190 return packet_reply_status(gdbctx);
1193 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1195 unsigned char sig;
1197 /* FIXME: add support for address in packet */
1198 assert(gdbctx->in_packet_len == 2);
1199 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1200 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1201 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1202 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1203 hex_from(&sig, gdbctx->in_packet, 1);
1204 /* cannot change signals on the fly */
1205 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1206 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1207 if (sig != gdbctx->last_sig)
1208 return packet_error;
1209 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1210 wait_for_debuggee(gdbctx);
1211 return packet_reply_status(gdbctx);
1214 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1216 detach_debuggee(gdbctx, FALSE);
1217 return packet_ok | packet_last_f;
1220 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1222 int i;
1223 CONTEXT ctx;
1224 CONTEXT* pctx = &gdbctx->context;
1226 assert(gdbctx->in_trap);
1228 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1230 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1231 return packet_error;
1234 packet_reply_open(gdbctx);
1235 for (i = 0; i < cpu_num_regs; i++)
1237 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1239 packet_reply_close(gdbctx);
1240 return packet_done;
1243 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1245 unsigned i;
1246 CONTEXT ctx;
1247 CONTEXT* pctx = &gdbctx->context;
1249 assert(gdbctx->in_trap);
1250 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1252 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1253 return packet_error;
1255 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1257 for (i = 0; i < cpu_num_regs; i++)
1258 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1259 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1261 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1262 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1263 return packet_error;
1265 return packet_ok;
1268 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1270 detach_debuggee(gdbctx, TRUE);
1271 #if 0
1272 if (!gdbctx->extended)
1273 /* dunno whether GDB cares or not */
1274 #endif
1275 wait(NULL);
1276 exit(0);
1277 /* assume we can't really answer something here */
1278 /* return packet_done; */
1281 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1283 char* end;
1284 unsigned thread;
1286 switch (gdbctx->in_packet[0])
1288 case 'c':
1289 case 'g':
1290 if (gdbctx->in_packet[1] == '-')
1291 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1292 else
1293 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1294 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1296 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1297 fprintf(stderr, "Cannot get threadid %*.*s\n",
1298 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1299 gdbctx->in_packet + 1);
1300 return packet_error;
1302 if (gdbctx->in_packet[0] == 'c')
1303 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1304 else
1305 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1306 return packet_ok;
1307 default:
1308 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1309 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1310 return packet_error;
1314 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1316 char *addr;
1317 unsigned int len, blk_len, nread;
1318 char buffer[32];
1319 SIZE_T r = 0;
1321 assert(gdbctx->in_trap);
1322 /* FIXME:check in_packet_len for reading %p,%x */
1323 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1324 if (len <= 0) return packet_error;
1325 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1326 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1327 for (nread = 0; nread < len; nread += r, addr += r)
1329 blk_len = min(sizeof(buffer), len - nread);
1330 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1331 r == 0)
1333 /* fail at first address, return error */
1334 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1335 /* something has already been read, return partial information */
1336 break;
1338 if (nread == 0) packet_reply_open(gdbctx);
1339 packet_reply_hex_to(gdbctx, buffer, r);
1341 packet_reply_close(gdbctx);
1342 return packet_done;
1345 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1347 char* addr;
1348 unsigned int len, blk_len;
1349 char* ptr;
1350 char buffer[32];
1351 SIZE_T w;
1353 assert(gdbctx->in_trap);
1354 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1355 if (ptr == NULL)
1357 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1358 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1359 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1360 return packet_error;
1362 *ptr++ = '\0';
1364 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1366 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1367 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1368 return packet_error;
1370 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1372 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1373 fprintf(stderr, "Wrong sizes %u <> %u\n",
1374 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1375 return packet_error;
1377 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1378 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1379 while (len > 0)
1381 blk_len = min(sizeof(buffer), len);
1382 hex_from(buffer, ptr, blk_len);
1383 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1384 w != blk_len)
1385 break;
1386 addr += blk_len;
1387 len -= blk_len;
1388 ptr += blk_len;
1390 return packet_ok; /* FIXME: error while writing ? */
1393 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1395 unsigned reg;
1396 CONTEXT ctx;
1397 CONTEXT* pctx = &gdbctx->context;
1399 assert(gdbctx->in_trap);
1400 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1401 if (reg >= cpu_num_regs)
1403 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1404 fprintf(stderr, "Register out of bounds %x\n", reg);
1405 return packet_error;
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;
1412 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1413 fprintf(stderr, "Read register %x => %lx\n", reg, *cpu_register(pctx, reg));
1414 packet_reply_open(gdbctx);
1415 packet_reply_hex_to(gdbctx, cpu_register(pctx, reg), 4);
1416 packet_reply_close(gdbctx);
1417 return packet_done;
1420 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1422 unsigned reg;
1423 char* ptr;
1424 char* end;
1425 CONTEXT ctx;
1426 CONTEXT* pctx = &gdbctx->context;
1428 assert(gdbctx->in_trap);
1430 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1431 *ptr++ = '\0';
1432 reg = strtoul(gdbctx->in_packet, &end, 16);
1433 if (end == NULL || reg > cpu_num_regs)
1435 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1436 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1437 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1438 * it wouldn't matter too much, and it fakes our support for all regs
1440 return (end == NULL) ? packet_error : packet_ok;
1442 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1444 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1445 fprintf(stderr, "Wrong sizes %u <> %u\n",
1446 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1447 return packet_error;
1449 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1450 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1451 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1452 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1454 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1456 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1457 return packet_error;
1460 hex_from(cpu_register(pctx, reg), ptr, 4);
1461 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1463 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1464 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1465 return packet_error;
1468 return packet_ok;
1471 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1473 char buffer[128];
1474 char clsName[128];
1475 char wndName[128];
1476 HWND child;
1478 do {
1479 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1480 strcpy(clsName, "-- Unknown --");
1481 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1482 strcpy(wndName, "-- Empty --");
1484 packet_reply_open(gdbctx);
1485 packet_reply_catc(gdbctx, 'O');
1486 snprintf(buffer, sizeof(buffer),
1487 "%*s%04lx%*s%-17.17s %08x %08x %.14s\n",
1488 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1489 clsName, GetWindowLong(hWnd, GWL_STYLE),
1490 GetWindowLongPtr(hWnd, GWLP_WNDPROC), wndName);
1491 packet_reply_hex_to_str(gdbctx, buffer);
1492 packet_reply_close(gdbctx);
1494 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1495 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1496 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1499 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1501 char buffer[128];
1503 /* we do the output in several 'O' packets, with the last one being just OK for
1504 * marking the end of the output */
1505 packet_reply_open(gdbctx);
1506 packet_reply_catc(gdbctx, 'O');
1507 snprintf(buffer, sizeof(buffer),
1508 "%-16.16s %-17.17s %-8.8s %s\n",
1509 "hwnd", "Class Name", " Style", " WndProc Text");
1510 packet_reply_hex_to_str(gdbctx, buffer);
1511 packet_reply_close(gdbctx);
1513 /* FIXME: could also add a pmt to this command in str... */
1514 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1515 packet_reply(gdbctx, "OK", 2);
1518 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1520 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1521 char buffer[128];
1522 char deco;
1523 PROCESSENTRY32 entry;
1524 BOOL ok;
1526 if (snap == INVALID_HANDLE_VALUE)
1527 return;
1529 entry.dwSize = sizeof(entry);
1530 ok = Process32First(snap, &entry);
1532 /* we do the output in several 'O' packets, with the last one being just OK for
1533 * marking the end of the output */
1535 packet_reply_open(gdbctx);
1536 packet_reply_catc(gdbctx, 'O');
1537 snprintf(buffer, sizeof(buffer),
1538 " %-8.8s %-8.8s %-8.8s %s\n",
1539 "pid", "threads", "parent", "executable");
1540 packet_reply_hex_to_str(gdbctx, buffer);
1541 packet_reply_close(gdbctx);
1543 while (ok)
1545 deco = ' ';
1546 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1547 packet_reply_open(gdbctx);
1548 packet_reply_catc(gdbctx, 'O');
1549 snprintf(buffer, sizeof(buffer),
1550 "%c%08x %-8d %08x '%s'\n",
1551 deco, entry.th32ProcessID, entry.cntThreads,
1552 entry.th32ParentProcessID, entry.szExeFile);
1553 packet_reply_hex_to_str(gdbctx, buffer);
1554 packet_reply_close(gdbctx);
1555 ok = Process32Next(snap, &entry);
1557 CloseHandle(snap);
1558 packet_reply(gdbctx, "OK", 2);
1561 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1563 MEMORY_BASIC_INFORMATION mbi;
1564 char* addr = 0;
1565 const char* state;
1566 const char* type;
1567 char prot[3+1];
1568 char buffer[128];
1570 /* we do the output in several 'O' packets, with the last one being just OK for
1571 * marking the end of the output */
1572 packet_reply_open(gdbctx);
1573 packet_reply_catc(gdbctx, 'O');
1574 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1575 packet_reply_close(gdbctx);
1577 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1579 switch (mbi.State)
1581 case MEM_COMMIT: state = "commit "; break;
1582 case MEM_FREE: state = "free "; break;
1583 case MEM_RESERVE: state = "reserve"; break;
1584 default: state = "??? "; break;
1586 if (mbi.State != MEM_FREE)
1588 switch (mbi.Type)
1590 case MEM_IMAGE: type = "image "; break;
1591 case MEM_MAPPED: type = "mapped "; break;
1592 case MEM_PRIVATE: type = "private"; break;
1593 case 0: type = " "; break;
1594 default: type = "??? "; break;
1596 memset(prot, ' ' , sizeof(prot)-1);
1597 prot[sizeof(prot)-1] = '\0';
1598 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1599 prot[0] = 'R';
1600 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1601 prot[1] = 'W';
1602 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1603 prot[1] = 'C';
1604 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1605 prot[2] = 'X';
1607 else
1609 type = "";
1610 prot[0] = '\0';
1612 packet_reply_open(gdbctx);
1613 snprintf(buffer, sizeof(buffer), "%08lx %08lx %s %s %s\n",
1614 (DWORD_PTR)addr, mbi.RegionSize, state, type, prot);
1615 packet_reply_catc(gdbctx, 'O');
1616 packet_reply_hex_to_str(gdbctx, buffer);
1617 packet_reply_close(gdbctx);
1619 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1620 break;
1621 addr += mbi.RegionSize;
1623 packet_reply(gdbctx, "OK", 2);
1626 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1627 int len, const char* str)
1629 char buffer[128];
1631 if (len == 0)
1633 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1635 else if (len >= 2 && str[0] == '=')
1637 unsigned val = atoi(&str[1]);
1638 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1639 gdbctx->trace = val;
1641 else
1643 /* FIXME: ugly but can use error packet here */
1644 packet_reply_cat(gdbctx, "E00");
1645 return;
1647 packet_reply_open(gdbctx);
1648 packet_reply_hex_to_str(gdbctx, buffer);
1649 packet_reply_close(gdbctx);
1652 struct query_detail
1654 int with_arg;
1655 const char* name;
1656 size_t len;
1657 void (*handler)(struct gdb_context*, int, const char*);
1658 } query_details[] =
1660 {0, "wnd", 3, packet_query_monitor_wnd},
1661 {0, "window", 6, packet_query_monitor_wnd},
1662 {0, "proc", 4, packet_query_monitor_process},
1663 {0, "process", 7, packet_query_monitor_process},
1664 {0, "mem", 3, packet_query_monitor_mem},
1665 {1, "trace", 5, packet_query_monitor_trace},
1666 {0, NULL, 0, NULL},
1669 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1670 const char* hxcmd, size_t len)
1672 char buffer[128];
1673 struct query_detail* qd;
1675 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1676 len /= 2;
1677 hex_from(buffer, hxcmd, len);
1679 for (qd = &query_details[0]; qd->name != NULL; qd++)
1681 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1682 if (!qd->with_arg && len != qd->len) continue;
1684 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1685 return packet_done;
1687 return packet_reply_error(gdbctx, EINVAL);
1690 static enum packet_return packet_query(struct gdb_context* gdbctx)
1692 switch (gdbctx->in_packet[0])
1694 case 'f':
1695 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1697 struct dbg_thread* thd;
1699 packet_reply_open(gdbctx);
1700 packet_reply_add(gdbctx, "m", 1);
1701 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1703 packet_reply_val(gdbctx, thd->tid, 4);
1704 if (thd->next != NULL)
1705 packet_reply_add(gdbctx, ",", 1);
1707 packet_reply_close(gdbctx);
1708 return packet_done;
1710 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1712 char result[128];
1714 packet_reply_open(gdbctx);
1715 packet_reply_catc(gdbctx, 'O');
1716 get_process_info(gdbctx, result, sizeof(result));
1717 packet_reply_hex_to_str(gdbctx, result);
1718 packet_reply_close(gdbctx);
1719 return packet_done;
1721 break;
1722 case 's':
1723 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1725 packet_reply(gdbctx, "l", 1);
1726 return packet_done;
1728 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1730 packet_reply(gdbctx, "l", 1);
1731 return packet_done;
1733 break;
1734 case 'C':
1735 if (gdbctx->in_packet_len == 1)
1737 struct dbg_thread* thd;
1738 /* FIXME: doc says 16 bit val ??? */
1739 /* grab first created thread, aka last in list */
1740 assert(gdbctx->process && gdbctx->process->threads);
1741 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1742 packet_reply_open(gdbctx);
1743 packet_reply_add(gdbctx, "QC", 2);
1744 packet_reply_val(gdbctx, thd->tid, 4);
1745 packet_reply_close(gdbctx);
1746 return packet_done;
1748 break;
1749 case 'O':
1750 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1752 char buf[64];
1754 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1755 gdbctx->wine_segs[2] == 0)
1756 return packet_error;
1757 snprintf(buf, sizeof(buf),
1758 "Text=%08lx;Data=%08lx;Bss=%08lx",
1759 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1760 gdbctx->wine_segs[2]);
1761 return packet_reply(gdbctx, buf, -1);
1763 break;
1764 case 'R':
1765 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1767 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1768 gdbctx->in_packet_len - 5);
1770 break;
1771 case 'S':
1772 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1773 return packet_ok;
1774 if (strncmp(gdbctx->in_packet, "Supported", gdbctx->in_packet_len) == 0)
1776 packet_reply_open(gdbctx);
1777 packet_reply_close(gdbctx);
1778 return packet_done;
1780 break;
1781 case 'T':
1782 if (gdbctx->in_packet_len > 15 &&
1783 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1784 gdbctx->in_packet[15] == ',')
1786 unsigned tid;
1787 char* end;
1788 char result[128];
1790 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1791 if (end == NULL) break;
1792 get_thread_info(gdbctx, tid, result, sizeof(result));
1793 packet_reply_open(gdbctx);
1794 packet_reply_hex_to_str(gdbctx, result);
1795 packet_reply_close(gdbctx);
1796 return packet_done;
1798 break;
1800 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1801 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1802 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1803 return packet_error;
1806 static enum packet_return packet_step(struct gdb_context* gdbctx)
1808 /* FIXME: add support for address in packet */
1809 assert(gdbctx->in_packet_len == 0);
1810 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1811 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1812 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1813 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1814 be_cpu->single_step(&gdbctx->context, TRUE);
1815 resume_debuggee(gdbctx, DBG_CONTINUE);
1816 wait_for_debuggee(gdbctx);
1817 be_cpu->single_step(&gdbctx->context, FALSE);
1818 return packet_reply_status(gdbctx);
1821 #if 0
1822 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1824 unsigned char sig;
1826 /* FIXME: add support for address in packet */
1827 assert(gdbctx->in_packet_len == 2);
1828 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1829 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1830 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1831 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1832 hex_from(&sig, gdbctx->in_packet, 1);
1833 /* cannot change signals on the fly */
1834 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1835 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1836 if (sig != gdbctx->last_sig)
1837 return packet_error;
1838 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1839 wait_for_debuggee(gdbctx);
1840 return packet_reply_status(gdbctx);
1842 #endif
1844 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1846 char* end;
1847 unsigned tid;
1849 tid = strtol(gdbctx->in_packet, &end, 16);
1850 if (tid == -1 || tid == 0)
1851 return packet_reply_error(gdbctx, EINVAL);
1852 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1853 return packet_ok;
1854 return packet_reply_error(gdbctx, ESRCH);
1857 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1859 void* addr;
1860 unsigned len;
1861 struct gdb_ctx_Xpoint* xpt;
1862 enum be_xpoint_type t;
1864 /* FIXME: check packet_len */
1865 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1866 gdbctx->in_packet[1] != ',' ||
1867 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1868 return packet_error;
1869 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1870 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1871 addr, len, gdbctx->in_packet[0]);
1872 switch (gdbctx->in_packet[0])
1874 case '0': t = be_xpoint_break; len = 0; break;
1875 case '1': t = be_xpoint_watch_exec; break;
1876 case '2': t = be_xpoint_watch_read; break;
1877 case '3': t = be_xpoint_watch_write; break;
1878 default: return packet_error;
1880 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1882 if (xpt->addr == addr && xpt->type == t)
1884 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1885 gdbctx->process->process_io, &gdbctx->context,
1886 t, xpt->addr, xpt->val, len))
1888 xpt->type = -1;
1889 return packet_ok;
1891 break;
1894 return packet_error;
1897 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1899 void* addr;
1900 unsigned len;
1901 struct gdb_ctx_Xpoint* xpt;
1902 enum be_xpoint_type t;
1904 /* FIXME: check packet_len */
1905 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1906 gdbctx->in_packet[1] != ',' ||
1907 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1908 return packet_error;
1909 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1910 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1911 addr, len, gdbctx->in_packet[0]);
1912 switch (gdbctx->in_packet[0])
1914 case '0': t = be_xpoint_break; len = 0; break;
1915 case '1': t = be_xpoint_watch_exec; break;
1916 case '2': t = be_xpoint_watch_read; break;
1917 case '3': t = be_xpoint_watch_write; break;
1918 default: return packet_error;
1920 /* because of packet command handling, this should be made idempotent */
1921 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1923 if (xpt->addr == addr && xpt->type == t)
1924 return packet_ok; /* nothing to do */
1926 /* really set the Xpoint */
1927 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1929 if (xpt->type == -1)
1931 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1932 gdbctx->process->process_io, &gdbctx->context,
1933 t, addr, &xpt->val, len))
1935 xpt->addr = addr;
1936 xpt->type = t;
1937 return packet_ok;
1939 fprintf(stderr, "cannot set xpoint\n");
1940 break;
1943 /* no more entries... eech */
1944 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1945 return packet_error;
1948 /* =============================================== *
1949 * P A C K E T I N F R A S T R U C T U R E *
1950 * =============================================== *
1953 struct packet_entry
1955 char key;
1956 enum packet_return (*handler)(struct gdb_context* gdbctx);
1959 static struct packet_entry packet_entries[] =
1961 /*{'!', packet_extended}, */
1962 {'?', packet_last_signal},
1963 {'c', packet_continue},
1964 {'C', packet_continue_signal},
1965 {'D', packet_detach},
1966 {'g', packet_read_registers},
1967 {'G', packet_write_registers},
1968 {'k', packet_kill},
1969 {'H', packet_thread},
1970 {'m', packet_read_memory},
1971 {'M', packet_write_memory},
1972 {'p', packet_read_register},
1973 {'P', packet_write_register},
1974 {'q', packet_query},
1975 /* {'Q', packet_set}, */
1976 /* {'R', packet,restart}, only in extended mode ! */
1977 {'s', packet_step},
1978 /*{'S', packet_step_signal}, hard(er) to implement */
1979 {'T', packet_thread_alive},
1980 {'v', packet_verbose},
1981 {'z', packet_remove_breakpoint},
1982 {'Z', packet_set_breakpoint},
1985 static BOOL extract_packets(struct gdb_context* gdbctx)
1987 char* end;
1988 int plen;
1989 unsigned char in_cksum, loc_cksum;
1990 char* ptr;
1991 enum packet_return ret = packet_error;
1992 int num_packet = 0;
1994 while ((ret & packet_last_f) == 0)
1996 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1997 fprintf(stderr, "In-buf: %*.*s\n",
1998 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1999 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2000 if (ptr == NULL) return FALSE;
2001 if (ptr != gdbctx->in_buf)
2003 int glen = ptr - gdbctx->in_buf; /* garbage len */
2004 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2005 fprintf(stderr, "Removing garbage: %*.*s\n",
2006 glen, glen, gdbctx->in_buf);
2007 gdbctx->in_len -= glen;
2008 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2010 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2011 if (end == NULL) return FALSE;
2012 /* no checksum yet */
2013 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2014 plen = end - gdbctx->in_buf - 1;
2015 hex_from(&in_cksum, end + 1, 1);
2016 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2017 if (loc_cksum == in_cksum)
2019 if (num_packet == 0) {
2020 int i;
2022 ret = packet_error;
2024 write(gdbctx->sock, "+", 1);
2025 assert(plen);
2027 /* FIXME: should use bsearch if packet_entries was sorted */
2028 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2030 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2032 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2034 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2035 fprintf(stderr, "Unknown packet request %*.*s\n",
2036 plen, plen, &gdbctx->in_buf[1]);
2038 else
2040 gdbctx->in_packet = gdbctx->in_buf + 2;
2041 gdbctx->in_packet_len = plen - 1;
2042 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2043 fprintf(stderr, "Packet: %c%*.*s\n",
2044 gdbctx->in_buf[1],
2045 gdbctx->in_packet_len, gdbctx->in_packet_len,
2046 gdbctx->in_packet);
2047 ret = (packet_entries[i].handler)(gdbctx);
2049 switch (ret & ~packet_last_f)
2051 case packet_error: packet_reply(gdbctx, "", 0); break;
2052 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2053 case packet_done: break;
2055 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2056 fprintf(stderr, "Reply-full: %*.*s\n",
2057 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2058 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2059 assert(i == gdbctx->out_len);
2060 /* if this fails, we'll have to use POLLOUT...
2062 gdbctx->out_len = 0;
2063 num_packet++;
2065 else
2067 /* FIXME: if we have in our input buffer more than one packet,
2068 * it's very likely that we took too long to answer to a given packet
2069 * and gdb is sending us again the same packet
2070 * We simply drop the second packet. This will lower the risk of error,
2071 * but there's still some race conditions here
2072 * A better fix (yet not perfect) would be to have two threads:
2073 * - one managing the packets for gdb
2074 * - the second one managing the commands...
2075 * This would allow us also the reply with the '+' character (Ack of
2076 * the command) way sooner than what we do now
2078 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2079 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2082 else
2084 write(gdbctx->sock, "+", 1);
2085 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2086 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2088 gdbctx->in_len -= plen + 4;
2089 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2091 return TRUE;
2094 static int fetch_data(struct gdb_context* gdbctx)
2096 int len, in_len = gdbctx->in_len;
2098 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2099 for (;;)
2101 #define STEP 128
2102 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2103 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2104 #undef STEP
2105 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2106 fprintf(stderr, "%d %d %*.*s\n",
2107 gdbctx->in_len, gdbctx->in_buf_alloc,
2108 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2109 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2110 if (len <= 0) break;
2111 gdbctx->in_len += len;
2112 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2113 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2115 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2116 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2117 return gdbctx->in_len - in_len;
2120 #define FLAG_NO_START 1
2121 #define FLAG_WITH_XTERM 2
2123 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2125 char buf[MAX_PATH];
2126 int fd;
2127 const char* gdb_path;
2128 FILE* f;
2130 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2131 strcpy(buf,"/tmp/winegdb.XXXXXX");
2132 fd = mkstemps(buf, 0);
2133 if (fd == -1) return FALSE;
2134 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2135 fprintf(f, "file %s\n", wine_path);
2136 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2137 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2138 fprintf(f, "set prompt Wine-gdb>\\ \n");
2139 /* gdb 5.1 seems to require it, won't hurt anyway */
2140 fprintf(f, "sharedlibrary\n");
2141 /* This is needed (but not a decent & final fix)
2142 * Without this, gdb would skip our inter-DLL relay code (because
2143 * we don't have any line number information for the relay code)
2144 * With this, we will stop on first instruction of the stub, and
2145 * reusing step, will get us through the relay stub at the actual
2146 * function we're looking at.
2148 fprintf(f, "set step-mode on\n");
2149 /* tell gdb to delete this file when done handling it... */
2150 fprintf(f, "shell rm -f \"%s\"\n", buf);
2151 fclose(f);
2152 if (flags & FLAG_WITH_XTERM)
2153 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2154 else
2155 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2156 assert(0); /* never reached */
2157 return TRUE;
2160 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2162 int sock;
2163 struct sockaddr_in s_addrs;
2164 unsigned int s_len = sizeof(s_addrs);
2165 struct pollfd pollfd;
2166 IMAGEHLP_MODULE imh_mod;
2168 /* step 1: create socket for gdb connection request */
2169 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2171 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2172 fprintf(stderr, "Can't create socket");
2173 return FALSE;
2176 if (listen(sock, 1) == -1 ||
2177 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2178 return FALSE;
2180 /* step 2: do the process internal creation */
2181 handle_debug_event(gdbctx, de);
2183 /* step3: get the wine loader name */
2184 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2186 /* step 4: fire up gdb (if requested) */
2187 if (flags & FLAG_NO_START)
2188 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2189 else
2190 switch (fork())
2192 case -1: /* error in parent... */
2193 fprintf(stderr, "Cannot create gdb\n");
2194 return FALSE;
2195 default: /* in parent... success */
2196 break;
2197 case 0: /* in child... and alive */
2198 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2199 /* if we're here, exec failed, so report failure */
2200 return FALSE;
2203 /* step 5: wait for gdb to connect actually */
2204 pollfd.fd = sock;
2205 pollfd.events = POLLIN;
2206 pollfd.revents = 0;
2208 switch (poll(&pollfd, 1, -1))
2210 case 1:
2211 if (pollfd.revents & POLLIN)
2213 int dummy = 1;
2214 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2215 if (gdbctx->sock == -1)
2216 break;
2217 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2218 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2219 /* don't keep our small packets too long: send them ASAP back to GDB
2220 * without this, GDB really crawls
2222 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2224 break;
2225 case 0:
2226 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2227 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2228 return FALSE;
2229 case -1:
2230 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2231 fprintf(stderr, "Poll for cnx failed (error)\n");
2232 return FALSE;
2233 default:
2234 assert(0);
2237 close(sock);
2238 return TRUE;
2241 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2243 DEBUG_EVENT de;
2244 int i;
2246 gdbctx->sock = -1;
2247 gdbctx->in_buf = NULL;
2248 gdbctx->in_buf_alloc = 0;
2249 gdbctx->in_len = 0;
2250 gdbctx->out_buf = NULL;
2251 gdbctx->out_buf_alloc = 0;
2252 gdbctx->out_len = 0;
2253 gdbctx->out_curr_packet = -1;
2255 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2256 gdbctx->last_sig = 0;
2257 gdbctx->in_trap = FALSE;
2258 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2259 gdbctx->process = NULL;
2260 for (i = 0; i < NUM_XPOINT; i++)
2261 gdbctx->Xpoints[i].type = -1;
2263 /* wait for first trap */
2264 while (WaitForDebugEvent(&de, INFINITE))
2266 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2268 /* this should be the first event we get,
2269 * and the only one of this type */
2270 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2271 /* gdbctx->dwProcessId = pid; */
2272 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2273 assert(!gdbctx->in_trap);
2275 else
2277 handle_debug_event(gdbctx, &de);
2278 if (gdbctx->in_trap) break;
2280 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2282 return TRUE;
2285 static int gdb_remote(unsigned flags)
2287 struct pollfd pollfd;
2288 struct gdb_context gdbctx;
2289 BOOL doLoop;
2291 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2293 pollfd.fd = gdbctx.sock;
2294 pollfd.events = POLLIN;
2295 pollfd.revents = 0;
2297 switch (poll(&pollfd, 1, -1))
2299 case 1:
2300 /* got something */
2301 if (pollfd.revents & (POLLHUP | POLLERR))
2303 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2304 fprintf(stderr, "Gdb hung up\n");
2305 /* kill also debuggee process - questionnable - */
2306 detach_debuggee(&gdbctx, TRUE);
2307 doLoop = FALSE;
2308 break;
2310 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2312 if (extract_packets(&gdbctx)) doLoop = FALSE;
2314 break;
2315 case 0:
2316 /* timeout, should never happen (infinite timeout) */
2317 break;
2318 case -1:
2319 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2320 fprintf(stderr, "Poll failed\n");
2321 doLoop = FALSE;
2322 break;
2325 wait(NULL);
2326 return 0;
2328 #endif
2330 int gdb_main(int argc, char* argv[])
2332 #ifdef HAVE_POLL
2333 unsigned gdb_flags = 0;
2335 argc--; argv++;
2336 while (argc > 0 && argv[0][0] == '-')
2338 if (strcmp(argv[0], "--no-start") == 0)
2340 gdb_flags |= FLAG_NO_START;
2341 argc--; argv++;
2342 continue;
2344 if (strcmp(argv[0], "--with-xterm") == 0)
2346 gdb_flags |= FLAG_WITH_XTERM;
2347 argc--; argv++;
2348 continue;
2350 return -1;
2352 if (dbg_active_attach(argc, argv) == start_ok ||
2353 dbg_active_launch(argc, argv) == start_ok)
2354 return gdb_remote(gdb_flags);
2355 #else
2356 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2357 #endif
2358 return -1;