shell32: Merge menu implementations together.
[wine/multimedia.git] / programs / winedbg / gdbproxy.c
blob9205badef115a1968cf327d030ddd9802653a86c
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/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 #ifdef __i386__
201 static size_t cpu_register_map[] = {
202 FIELD_OFFSET(CONTEXT, Eax),
203 FIELD_OFFSET(CONTEXT, Ecx),
204 FIELD_OFFSET(CONTEXT, Edx),
205 FIELD_OFFSET(CONTEXT, Ebx),
206 FIELD_OFFSET(CONTEXT, Esp),
207 FIELD_OFFSET(CONTEXT, Ebp),
208 FIELD_OFFSET(CONTEXT, Esi),
209 FIELD_OFFSET(CONTEXT, Edi),
210 FIELD_OFFSET(CONTEXT, Eip),
211 FIELD_OFFSET(CONTEXT, EFlags),
212 FIELD_OFFSET(CONTEXT, SegCs),
213 FIELD_OFFSET(CONTEXT, SegSs),
214 FIELD_OFFSET(CONTEXT, SegDs),
215 FIELD_OFFSET(CONTEXT, SegEs),
216 FIELD_OFFSET(CONTEXT, SegFs),
217 FIELD_OFFSET(CONTEXT, SegGs),
219 #elif defined(__powerpc__)
220 static size_t cpu_register_map[] = {
221 FIELD_OFFSET(CONTEXT, Gpr0),
222 FIELD_OFFSET(CONTEXT, Gpr1),
223 FIELD_OFFSET(CONTEXT, Gpr2),
224 FIELD_OFFSET(CONTEXT, Gpr3),
225 FIELD_OFFSET(CONTEXT, Gpr4),
226 FIELD_OFFSET(CONTEXT, Gpr5),
227 FIELD_OFFSET(CONTEXT, Gpr6),
228 FIELD_OFFSET(CONTEXT, Gpr7),
229 FIELD_OFFSET(CONTEXT, Gpr8),
230 FIELD_OFFSET(CONTEXT, Gpr9),
231 FIELD_OFFSET(CONTEXT, Gpr10),
232 FIELD_OFFSET(CONTEXT, Gpr11),
233 FIELD_OFFSET(CONTEXT, Gpr12),
234 FIELD_OFFSET(CONTEXT, Gpr13),
235 FIELD_OFFSET(CONTEXT, Gpr14),
236 FIELD_OFFSET(CONTEXT, Gpr15),
237 FIELD_OFFSET(CONTEXT, Gpr16),
238 FIELD_OFFSET(CONTEXT, Gpr17),
239 FIELD_OFFSET(CONTEXT, Gpr18),
240 FIELD_OFFSET(CONTEXT, Gpr19),
241 FIELD_OFFSET(CONTEXT, Gpr20),
242 FIELD_OFFSET(CONTEXT, Gpr21),
243 FIELD_OFFSET(CONTEXT, Gpr22),
244 FIELD_OFFSET(CONTEXT, Gpr23),
245 FIELD_OFFSET(CONTEXT, Gpr24),
246 FIELD_OFFSET(CONTEXT, Gpr25),
247 FIELD_OFFSET(CONTEXT, Gpr26),
248 FIELD_OFFSET(CONTEXT, Gpr27),
249 FIELD_OFFSET(CONTEXT, Gpr28),
250 FIELD_OFFSET(CONTEXT, Gpr29),
251 FIELD_OFFSET(CONTEXT, Gpr30),
252 FIELD_OFFSET(CONTEXT, Gpr31),
253 FIELD_OFFSET(CONTEXT, Fpr0),
254 FIELD_OFFSET(CONTEXT, Fpr1),
255 FIELD_OFFSET(CONTEXT, Fpr2),
256 FIELD_OFFSET(CONTEXT, Fpr3),
257 FIELD_OFFSET(CONTEXT, Fpr4),
258 FIELD_OFFSET(CONTEXT, Fpr5),
259 FIELD_OFFSET(CONTEXT, Fpr6),
260 FIELD_OFFSET(CONTEXT, Fpr7),
261 FIELD_OFFSET(CONTEXT, Fpr8),
262 FIELD_OFFSET(CONTEXT, Fpr9),
263 FIELD_OFFSET(CONTEXT, Fpr10),
264 FIELD_OFFSET(CONTEXT, Fpr11),
265 FIELD_OFFSET(CONTEXT, Fpr12),
266 FIELD_OFFSET(CONTEXT, Fpr13),
267 FIELD_OFFSET(CONTEXT, Fpr14),
268 FIELD_OFFSET(CONTEXT, Fpr15),
269 FIELD_OFFSET(CONTEXT, Fpr16),
270 FIELD_OFFSET(CONTEXT, Fpr17),
271 FIELD_OFFSET(CONTEXT, Fpr18),
272 FIELD_OFFSET(CONTEXT, Fpr19),
273 FIELD_OFFSET(CONTEXT, Fpr20),
274 FIELD_OFFSET(CONTEXT, Fpr21),
275 FIELD_OFFSET(CONTEXT, Fpr22),
276 FIELD_OFFSET(CONTEXT, Fpr23),
277 FIELD_OFFSET(CONTEXT, Fpr24),
278 FIELD_OFFSET(CONTEXT, Fpr25),
279 FIELD_OFFSET(CONTEXT, Fpr26),
280 FIELD_OFFSET(CONTEXT, Fpr27),
281 FIELD_OFFSET(CONTEXT, Fpr28),
282 FIELD_OFFSET(CONTEXT, Fpr29),
283 FIELD_OFFSET(CONTEXT, Fpr30),
284 FIELD_OFFSET(CONTEXT, Fpr31),
286 FIELD_OFFSET(CONTEXT, Iar),
287 FIELD_OFFSET(CONTEXT, Msr),
288 FIELD_OFFSET(CONTEXT, Cr),
289 FIELD_OFFSET(CONTEXT, Lr),
290 FIELD_OFFSET(CONTEXT, Ctr),
291 FIELD_OFFSET(CONTEXT, Xer),
292 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
293 /* see gdb/nlm/ppc.c */
295 #elif defined(__x86_64__)
296 static size_t cpu_register_map[] = {
297 FIELD_OFFSET(CONTEXT, Rax),
298 FIELD_OFFSET(CONTEXT, Rbx),
299 FIELD_OFFSET(CONTEXT, Rcx),
300 FIELD_OFFSET(CONTEXT, Rdx),
301 FIELD_OFFSET(CONTEXT, Rsi),
302 FIELD_OFFSET(CONTEXT, Rdi),
303 FIELD_OFFSET(CONTEXT, Rbp),
304 FIELD_OFFSET(CONTEXT, Rsp),
305 FIELD_OFFSET(CONTEXT, R8),
306 FIELD_OFFSET(CONTEXT, R9),
307 FIELD_OFFSET(CONTEXT, R10),
308 FIELD_OFFSET(CONTEXT, R11),
309 FIELD_OFFSET(CONTEXT, R12),
310 FIELD_OFFSET(CONTEXT, R13),
311 FIELD_OFFSET(CONTEXT, R14),
312 FIELD_OFFSET(CONTEXT, R15),
313 FIELD_OFFSET(CONTEXT, Rip),
314 FIELD_OFFSET(CONTEXT, EFlags),
315 FIELD_OFFSET(CONTEXT, SegCs),
316 FIELD_OFFSET(CONTEXT, SegSs),
317 FIELD_OFFSET(CONTEXT, SegDs),
318 FIELD_OFFSET(CONTEXT, SegEs),
319 FIELD_OFFSET(CONTEXT, SegFs),
320 FIELD_OFFSET(CONTEXT, SegGs),
322 #elif defined(__sparc__)
323 static size_t cpu_register_map[] = {
324 FIELD_OFFSET(CONTEXT, g0),
325 FIELD_OFFSET(CONTEXT, g1),
326 FIELD_OFFSET(CONTEXT, g2),
327 FIELD_OFFSET(CONTEXT, g3),
328 FIELD_OFFSET(CONTEXT, g4),
329 FIELD_OFFSET(CONTEXT, g5),
330 FIELD_OFFSET(CONTEXT, g6),
331 FIELD_OFFSET(CONTEXT, g7),
332 FIELD_OFFSET(CONTEXT, o0),
333 FIELD_OFFSET(CONTEXT, o1),
334 FIELD_OFFSET(CONTEXT, o2),
335 FIELD_OFFSET(CONTEXT, o3),
336 FIELD_OFFSET(CONTEXT, o4),
337 FIELD_OFFSET(CONTEXT, o5),
338 FIELD_OFFSET(CONTEXT, o6),
339 FIELD_OFFSET(CONTEXT, o7),
340 FIELD_OFFSET(CONTEXT, l0),
341 FIELD_OFFSET(CONTEXT, l1),
342 FIELD_OFFSET(CONTEXT, l2),
343 FIELD_OFFSET(CONTEXT, l3),
344 FIELD_OFFSET(CONTEXT, l4),
345 FIELD_OFFSET(CONTEXT, l5),
346 FIELD_OFFSET(CONTEXT, l6),
347 FIELD_OFFSET(CONTEXT, l7),
348 FIELD_OFFSET(CONTEXT, i0),
349 FIELD_OFFSET(CONTEXT, i1),
350 FIELD_OFFSET(CONTEXT, i2),
351 FIELD_OFFSET(CONTEXT, i3),
352 FIELD_OFFSET(CONTEXT, i4),
353 FIELD_OFFSET(CONTEXT, i5),
354 FIELD_OFFSET(CONTEXT, i6),
355 FIELD_OFFSET(CONTEXT, i7),
357 #elif defined(__arm__)
358 static size_t cpu_register_map[] = {
359 FIELD_OFFSET(CONTEXT, R0),
360 FIELD_OFFSET(CONTEXT, R1),
361 FIELD_OFFSET(CONTEXT, R2),
362 FIELD_OFFSET(CONTEXT, R3),
363 FIELD_OFFSET(CONTEXT, R4),
364 FIELD_OFFSET(CONTEXT, R5),
365 FIELD_OFFSET(CONTEXT, R6),
366 FIELD_OFFSET(CONTEXT, R7),
367 FIELD_OFFSET(CONTEXT, R8),
368 FIELD_OFFSET(CONTEXT, R9),
369 FIELD_OFFSET(CONTEXT, R10),
370 FIELD_OFFSET(CONTEXT, Fp),
371 FIELD_OFFSET(CONTEXT, Ip),
372 FIELD_OFFSET(CONTEXT, Sp),
373 FIELD_OFFSET(CONTEXT, Lr),
374 FIELD_OFFSET(CONTEXT, Pc),
376 #else
377 # error Define the registers map for your CPU
378 #endif
380 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
382 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
384 assert(idx < cpu_num_regs);
385 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
388 /* =============================================== *
389 * W I N 3 2 D E B U G I N T E R F A C E *
390 * =============================================== *
393 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
395 ctx->ContextFlags = CONTEXT_CONTROL
396 | CONTEXT_INTEGER
397 #ifdef CONTEXT_SEGMENTS
398 | CONTEXT_SEGMENTS
399 #endif
400 #ifdef CONTEXT_DEBUG_REGISTERS
401 | CONTEXT_DEBUG_REGISTERS
402 #endif
404 if (!GetThreadContext(h, ctx))
406 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
407 fprintf(stderr, "Can't get thread's context\n");
408 return FALSE;
410 return TRUE;
413 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
415 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
416 BOOL ret = FALSE;
418 switch (rec->ExceptionCode)
420 case EXCEPTION_ACCESS_VIOLATION:
421 case EXCEPTION_PRIV_INSTRUCTION:
422 case EXCEPTION_STACK_OVERFLOW:
423 case EXCEPTION_GUARD_PAGE:
424 gdbctx->last_sig = SIGSEGV;
425 ret = TRUE;
426 break;
427 case EXCEPTION_DATATYPE_MISALIGNMENT:
428 gdbctx->last_sig = SIGBUS;
429 ret = TRUE;
430 break;
431 case EXCEPTION_SINGLE_STEP:
432 /* fall thru */
433 case EXCEPTION_BREAKPOINT:
434 gdbctx->last_sig = SIGTRAP;
435 ret = TRUE;
436 break;
437 case EXCEPTION_FLT_DENORMAL_OPERAND:
438 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
439 case EXCEPTION_FLT_INEXACT_RESULT:
440 case EXCEPTION_FLT_INVALID_OPERATION:
441 case EXCEPTION_FLT_OVERFLOW:
442 case EXCEPTION_FLT_STACK_CHECK:
443 case EXCEPTION_FLT_UNDERFLOW:
444 gdbctx->last_sig = SIGFPE;
445 ret = TRUE;
446 break;
447 case EXCEPTION_INT_DIVIDE_BY_ZERO:
448 case EXCEPTION_INT_OVERFLOW:
449 gdbctx->last_sig = SIGFPE;
450 ret = TRUE;
451 break;
452 case EXCEPTION_ILLEGAL_INSTRUCTION:
453 gdbctx->last_sig = SIGILL;
454 ret = TRUE;
455 break;
456 case CONTROL_C_EXIT:
457 gdbctx->last_sig = SIGINT;
458 ret = TRUE;
459 break;
460 case STATUS_POSSIBLE_DEADLOCK:
461 gdbctx->last_sig = SIGALRM;
462 ret = TRUE;
463 /* FIXME: we could also add here a O packet with additional information */
464 break;
465 default:
466 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
467 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
468 gdbctx->last_sig = SIGABRT;
469 ret = TRUE;
470 break;
472 return ret;
475 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
477 union {
478 char bufferA[256];
479 WCHAR buffer[256];
480 } u;
482 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
484 switch (de->dwDebugEventCode)
486 case CREATE_PROCESS_DEBUG_EVENT:
487 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
488 de->u.CreateProcessInfo.hProcess);
489 if (!gdbctx->process) break;
490 memory_get_string_indirect(gdbctx->process,
491 de->u.CreateProcessInfo.lpImageName,
492 de->u.CreateProcessInfo.fUnicode,
493 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
494 dbg_set_process_name(gdbctx->process, u.buffer);
496 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
497 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
498 de->dwProcessId, de->dwThreadId,
499 dbg_W2A(u.buffer, -1),
500 de->u.CreateProcessInfo.lpImageName,
501 de->u.CreateProcessInfo.lpStartAddress,
502 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
503 de->u.CreateProcessInfo.nDebugInfoSize);
505 /* de->u.CreateProcessInfo.lpStartAddress; */
506 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
507 fprintf(stderr, "Couldn't initiate DbgHelp\n");
509 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
510 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
511 de->dwProcessId, de->dwThreadId,
512 de->u.CreateProcessInfo.lpStartAddress);
514 assert(dbg_curr_thread == NULL); /* shouldn't be there */
515 dbg_add_thread(gdbctx->process, de->dwThreadId,
516 de->u.CreateProcessInfo.hThread,
517 de->u.CreateProcessInfo.lpThreadLocalBase);
518 break;
520 case LOAD_DLL_DEBUG_EVENT:
521 assert(dbg_curr_thread);
522 memory_get_string_indirect(gdbctx->process,
523 de->u.LoadDll.lpImageName,
524 de->u.LoadDll.fUnicode,
525 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
526 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
527 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
528 de->dwProcessId, de->dwThreadId,
529 dbg_W2A(u.buffer, -1),
530 de->u.LoadDll.lpBaseOfDll,
531 de->u.LoadDll.dwDebugInfoFileOffset,
532 de->u.LoadDll.nDebugInfoSize);
533 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
534 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
535 break;
537 case UNLOAD_DLL_DEBUG_EVENT:
538 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
539 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
540 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
541 SymUnloadModule(gdbctx->process->handle,
542 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
543 break;
545 case EXCEPTION_DEBUG_EVENT:
546 assert(dbg_curr_thread);
547 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
548 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
549 de->dwProcessId, de->dwThreadId,
550 de->u.Exception.ExceptionRecord.ExceptionCode);
552 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
554 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
556 break;
558 case CREATE_THREAD_DEBUG_EVENT:
559 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
560 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
561 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
563 dbg_add_thread(gdbctx->process,
564 de->dwThreadId,
565 de->u.CreateThread.hThread,
566 de->u.CreateThread.lpThreadLocalBase);
567 break;
569 case EXIT_THREAD_DEBUG_EVENT:
570 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
571 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
572 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
574 assert(dbg_curr_thread);
575 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
576 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
577 dbg_del_thread(dbg_curr_thread);
578 break;
580 case EXIT_PROCESS_DEBUG_EVENT:
581 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
582 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
583 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
585 dbg_del_process(gdbctx->process);
586 gdbctx->process = NULL;
587 /* now signal gdb that we're done */
588 gdbctx->last_sig = SIGTERM;
589 gdbctx->in_trap = TRUE;
590 break;
592 case OUTPUT_DEBUG_STRING_EVENT:
593 assert(dbg_curr_thread);
594 memory_get_string(gdbctx->process,
595 de->u.DebugString.lpDebugStringData, TRUE,
596 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
597 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
598 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
599 de->dwProcessId, de->dwThreadId, u.bufferA);
600 break;
602 case RIP_EVENT:
603 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
604 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
605 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
606 de->u.RipInfo.dwType);
607 break;
609 default:
610 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
611 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
612 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
616 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
618 if (dbg_curr_thread)
620 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
621 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
622 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
623 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
624 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
625 fprintf(stderr, "Cannot continue on %04x (%x)\n",
626 dbg_curr_thread->tid, cont);
628 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
629 fprintf(stderr, "Cannot find last thread\n");
633 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
636 if (dbg_curr_thread)
638 if(dbg_curr_thread->tid == threadid){
639 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
640 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
641 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
642 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
643 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
644 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
645 fprintf(stderr, "Cannot continue on %04x (%x)\n",
646 dbg_curr_thread->tid, cont);
649 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
650 fprintf(stderr, "Cannot find last thread\n");
653 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
655 struct pollfd pollfd;
656 int ret;
657 char pkt;
659 pollfd.fd = gdbctx->sock;
660 pollfd.events = POLLIN;
661 pollfd.revents = 0;
663 if ((ret = poll(&pollfd, 1, 0)) == 1) {
664 ret = read(gdbctx->sock, &pkt, 1);
665 if (ret != 1) {
666 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
667 fprintf(stderr, "read failed\n");
669 return FALSE;
671 if (pkt != '\003') {
672 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
673 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
675 return FALSE;
677 return TRUE;
678 } else if (ret == -1) {
679 fprintf(stderr, "poll failed\n");
681 return FALSE;
684 static void wait_for_debuggee(struct gdb_context* gdbctx)
686 DEBUG_EVENT de;
688 gdbctx->in_trap = FALSE;
689 for (;;)
691 if (!WaitForDebugEvent(&de, 10))
693 if (GetLastError() == ERROR_SEM_TIMEOUT)
695 if (check_for_interrupt(gdbctx)) {
696 if (!DebugBreakProcess(gdbctx->process->handle)) {
697 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
698 fprintf(stderr, "Failed to break into debugee\n");
700 break;
702 WaitForDebugEvent(&de, INFINITE);
703 } else {
704 continue;
706 } else {
707 break;
710 handle_debug_event(gdbctx, &de);
711 assert(!gdbctx->process ||
712 gdbctx->process->pid == 0 ||
713 de.dwProcessId == gdbctx->process->pid);
714 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
715 if (gdbctx->in_trap) break;
716 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
720 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
722 be_cpu->single_step(&gdbctx->context, FALSE);
723 resume_debuggee(gdbctx, DBG_CONTINUE);
724 if (!kill)
725 DebugActiveProcessStop(gdbctx->process->pid);
726 dbg_del_process(gdbctx->process);
727 gdbctx->process = NULL;
730 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
732 DWORD status;
734 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
736 strcpy(buffer, "Unknown process");
737 return;
739 if (status == STILL_ACTIVE)
741 strcpy(buffer, "Running");
743 else
744 snprintf(buffer, len, "Terminated (%u)", status);
746 switch (GetPriorityClass(gdbctx->process->handle))
748 case 0: break;
749 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
750 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
751 #endif
752 #ifdef BELOW_NORMAL_PRIORITY_CLASS
753 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
754 #endif
755 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
756 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
757 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
758 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
760 strcat(buffer, "\n");
763 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
764 char* buffer, size_t len)
766 struct dbg_thread* thd;
767 DWORD status;
768 int prio;
770 /* FIXME: use the size of buffer */
771 thd = dbg_get_thread(gdbctx->process, tid);
772 if (thd == NULL)
774 strcpy(buffer, "No information");
775 return;
777 if (GetExitCodeThread(thd->handle, &status))
779 if (status == STILL_ACTIVE)
781 /* FIXME: this is a bit brutal... some nicer way shall be found */
782 switch (status = SuspendThread(thd->handle))
784 case -1: break;
785 case 0: strcpy(buffer, "Running"); break;
786 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
788 ResumeThread(thd->handle);
790 else
791 snprintf(buffer, len, "Terminated (exit code = %u)", status);
793 else
795 strcpy(buffer, "Unknown threadID");
797 switch (prio = GetThreadPriority(thd->handle))
799 case THREAD_PRIORITY_ERROR_RETURN: break;
800 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
801 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
802 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
803 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
804 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
805 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
806 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
807 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
809 assert(strlen(buffer) < len);
812 /* =============================================== *
813 * P A C K E T U T I L S *
814 * =============================================== *
817 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
818 packet_last_f = 0x80};
820 static char* packet_realloc(char* buf, int size)
822 if (!buf)
823 return HeapAlloc(GetProcessHeap(), 0, size);
824 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
828 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
830 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
832 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
833 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
837 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
839 packet_reply_grow(gdbctx, len * 2);
840 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
841 gdbctx->out_len += len * 2;
844 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
846 packet_reply_hex_to(gdbctx, src, strlen(src));
849 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
851 int i, shift;
853 shift = (len - 1) * 8;
854 packet_reply_grow(gdbctx, len * 2);
855 for (i = 0; i < len; i++, shift -= 8)
857 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
858 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
862 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
864 packet_reply_grow(gdbctx, len);
865 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
866 gdbctx->out_len += len;
869 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
871 packet_reply_add(gdbctx, str, strlen(str));
874 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
876 packet_reply_add(gdbctx, &ch, 1);
879 static void packet_reply_open(struct gdb_context* gdbctx)
881 assert(gdbctx->out_curr_packet == -1);
882 packet_reply_catc(gdbctx, '$');
883 gdbctx->out_curr_packet = gdbctx->out_len;
886 static void packet_reply_close(struct gdb_context* gdbctx)
888 unsigned char cksum;
889 int plen;
891 plen = gdbctx->out_len - gdbctx->out_curr_packet;
892 packet_reply_catc(gdbctx, '#');
893 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
894 packet_reply_hex_to(gdbctx, &cksum, 1);
895 if (gdbctx->trace & GDBPXY_TRC_PACKET)
896 fprintf(stderr, "Reply : %*.*s\n",
897 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
898 gdbctx->out_curr_packet = -1;
901 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
903 packet_reply_open(gdbctx);
905 if (len == -1) len = strlen(packet);
906 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
908 packet_reply_add(gdbctx, packet, len);
910 packet_reply_close(gdbctx);
912 return packet_done;
915 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
917 packet_reply_open(gdbctx);
919 packet_reply_add(gdbctx, "E", 1);
920 packet_reply_val(gdbctx, error, 1);
922 packet_reply_close(gdbctx);
924 return packet_done;
927 /* =============================================== *
928 * P A C K E T H A N D L E R S *
929 * =============================================== *
932 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
934 enum packet_return ret = packet_done;
936 packet_reply_open(gdbctx);
938 if (gdbctx->process != NULL)
940 unsigned char sig;
941 unsigned i;
943 packet_reply_catc(gdbctx, 'T');
944 sig = gdbctx->last_sig;
945 packet_reply_val(gdbctx, sig, 1);
946 packet_reply_add(gdbctx, "thread:", 7);
947 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
948 packet_reply_catc(gdbctx, ';');
950 for (i = 0; i < cpu_num_regs; i++)
952 /* FIXME: this call will also grow the buffer...
953 * unneeded, but not harmful
955 packet_reply_val(gdbctx, i, 1);
956 packet_reply_catc(gdbctx, ':');
957 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
958 packet_reply_catc(gdbctx, ';');
961 else
963 /* Try to put an exit code
964 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
965 * just indicate the end of process and exit */
966 packet_reply_add(gdbctx, "W00", 3);
967 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
970 packet_reply_close(gdbctx);
972 return ret;
975 #if 0
976 static enum packet_return packet_extended(struct gdb_context* gdbctx)
978 gdbctx->extended = 1;
979 return packet_ok;
981 #endif
983 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
985 assert(gdbctx->in_packet_len == 0);
986 return packet_reply_status(gdbctx);
989 static enum packet_return packet_continue(struct gdb_context* gdbctx)
991 /* FIXME: add support for address in packet */
992 assert(gdbctx->in_packet_len == 0);
993 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
994 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
995 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
996 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
997 resume_debuggee(gdbctx, DBG_CONTINUE);
998 wait_for_debuggee(gdbctx);
999 return packet_reply_status(gdbctx);
1002 static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
1004 int i;
1005 int defaultAction = -1; /* magic non action */
1006 unsigned char sig;
1007 int actions =0;
1008 int actionIndex[20]; /* allow for up to 20 actions */
1009 int threadIndex[20];
1010 int threadCount = 0;
1011 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1012 unsigned int threadID = 0;
1013 struct dbg_thread* thd;
1015 /* OK we have vCont followed by..
1016 * ? for query
1017 * c for packet_continue
1018 * Csig for packet_continue_signal
1019 * s for step
1020 * Ssig for step signal
1021 * and then an optional thread ID at the end..
1022 * *******************************************/
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 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
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/winedbg/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 struct verbose_defail
1195 const char* name;
1196 unsigned len;
1197 enum packet_return (*handler)(struct gdb_context*);
1198 } verbose_details[] =
1200 /* {"Attach", 6}, */
1201 {"Cont", 4, packet_verbose_cont},
1202 /* {"File", 4},
1203 {"FlashErase", 10},
1204 {"FlashWrite", 10},
1205 {"FlashDone", 9},
1206 {"Kill", 4},
1207 {"Run", 3},
1208 {"Stopped", 7},*/
1211 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1213 unsigned i;
1214 unsigned klen;
1216 for (klen = 0; ; klen++)
1218 if (klen == gdbctx->in_packet_len ||
1219 gdbctx->in_packet[klen] == ';' ||
1220 gdbctx->in_packet[klen] == ':' ||
1221 gdbctx->in_packet[klen] == '?')
1223 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1224 fprintf(stderr, "trying to process a verbose packet %*.*s\n",
1225 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1226 for (i = 0; i < sizeof(verbose_details)/sizeof(verbose_details[0]); i++)
1228 if (klen == verbose_details[i].len &&
1229 !memcmp(gdbctx->in_packet, verbose_details[i].name, verbose_details[i].len))
1231 return verbose_details[i].handler(gdbctx);
1234 /* no matching handler found, abort */
1235 break;
1239 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1240 fprintf(stderr, "No support for verbose packet %*.*s\n",
1241 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1242 return packet_error;
1245 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1247 unsigned char sig;
1249 /* FIXME: add support for address in packet */
1250 assert(gdbctx->in_packet_len == 2);
1251 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1252 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1253 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1254 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1255 hex_from(&sig, gdbctx->in_packet, 1);
1256 /* cannot change signals on the fly */
1257 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1258 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1259 if (sig != gdbctx->last_sig)
1260 return packet_error;
1261 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1262 wait_for_debuggee(gdbctx);
1263 return packet_reply_status(gdbctx);
1266 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1268 detach_debuggee(gdbctx, FALSE);
1269 return packet_ok | packet_last_f;
1272 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1274 int i;
1275 CONTEXT ctx;
1276 CONTEXT* pctx = &gdbctx->context;
1278 assert(gdbctx->in_trap);
1280 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1282 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1283 return packet_error;
1286 packet_reply_open(gdbctx);
1287 for (i = 0; i < cpu_num_regs; i++)
1289 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1291 packet_reply_close(gdbctx);
1292 return packet_done;
1295 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1297 unsigned i;
1298 CONTEXT ctx;
1299 CONTEXT* pctx = &gdbctx->context;
1301 assert(gdbctx->in_trap);
1302 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1304 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1305 return packet_error;
1307 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1309 for (i = 0; i < cpu_num_regs; i++)
1310 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1311 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1313 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1314 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1315 return packet_error;
1317 return packet_ok;
1320 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1322 detach_debuggee(gdbctx, TRUE);
1323 #if 0
1324 if (!gdbctx->extended)
1325 /* dunno whether GDB cares or not */
1326 #endif
1327 wait(NULL);
1328 exit(0);
1329 /* assume we can't really answer something here */
1330 /* return packet_done; */
1333 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1335 char* end;
1336 unsigned thread;
1338 switch (gdbctx->in_packet[0])
1340 case 'c':
1341 case 'g':
1342 if (gdbctx->in_packet[1] == '-')
1343 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1344 else
1345 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1346 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1348 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1349 fprintf(stderr, "Cannot get threadid %*.*s\n",
1350 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1351 gdbctx->in_packet + 1);
1352 return packet_error;
1354 if (gdbctx->in_packet[0] == 'c')
1355 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1356 else
1357 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1358 return packet_ok;
1359 default:
1360 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1361 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1362 return packet_error;
1366 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1368 char *addr;
1369 unsigned int len, blk_len, nread;
1370 char buffer[32];
1371 SIZE_T r = 0;
1373 assert(gdbctx->in_trap);
1374 /* FIXME:check in_packet_len for reading %p,%x */
1375 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1376 if (len <= 0) return packet_error;
1377 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1378 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1379 for (nread = 0; nread < len; nread += r, addr += r)
1381 blk_len = min(sizeof(buffer), len - nread);
1382 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1383 r == 0)
1385 /* fail at first address, return error */
1386 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1387 /* something has already been read, return partial information */
1388 break;
1390 if (nread == 0) packet_reply_open(gdbctx);
1391 packet_reply_hex_to(gdbctx, buffer, r);
1393 packet_reply_close(gdbctx);
1394 return packet_done;
1397 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1399 char* addr;
1400 unsigned int len, blk_len;
1401 char* ptr;
1402 char buffer[32];
1403 SIZE_T w;
1405 assert(gdbctx->in_trap);
1406 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1407 if (ptr == NULL)
1409 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1410 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1411 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1412 return packet_error;
1414 *ptr++ = '\0';
1416 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1418 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1419 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1420 return packet_error;
1422 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1424 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1425 fprintf(stderr, "Wrong sizes %u <> %u\n",
1426 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1427 return packet_error;
1429 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1430 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1431 while (len > 0)
1433 blk_len = min(sizeof(buffer), len);
1434 hex_from(buffer, ptr, blk_len);
1435 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1436 w != blk_len)
1437 break;
1438 addr += blk_len;
1439 len -= blk_len;
1440 ptr += blk_len;
1442 return packet_ok; /* FIXME: error while writing ? */
1445 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1447 unsigned reg;
1448 CONTEXT ctx;
1449 CONTEXT* pctx = &gdbctx->context;
1451 assert(gdbctx->in_trap);
1452 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1453 if (reg >= cpu_num_regs)
1455 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1456 fprintf(stderr, "Register out of bounds %x\n", reg);
1457 return packet_error;
1459 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1461 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1462 return packet_error;
1464 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1465 fprintf(stderr, "Read register %x => %lx\n", reg, *cpu_register(pctx, reg));
1466 packet_reply_open(gdbctx);
1467 packet_reply_hex_to(gdbctx, cpu_register(pctx, reg), 4);
1468 packet_reply_close(gdbctx);
1469 return packet_done;
1472 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1474 unsigned reg;
1475 char* ptr;
1476 char* end;
1477 CONTEXT ctx;
1478 CONTEXT* pctx = &gdbctx->context;
1480 assert(gdbctx->in_trap);
1482 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1483 *ptr++ = '\0';
1484 reg = strtoul(gdbctx->in_packet, &end, 16);
1485 if (end == NULL || reg > cpu_num_regs)
1487 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1488 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1489 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1490 * it wouldn't matter too much, and it fakes our support for all regs
1492 return (end == NULL) ? packet_error : packet_ok;
1494 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1496 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1497 fprintf(stderr, "Wrong sizes %u <> %u\n",
1498 (int)(ptr + 8 - gdbctx->in_packet), gdbctx->in_packet_len);
1499 return packet_error;
1501 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1503 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1504 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr );
1507 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1509 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1510 return packet_error;
1513 hex_from(cpu_register(pctx, reg), ptr, 4);
1514 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1516 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1517 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1518 return packet_error;
1521 return packet_ok;
1524 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1526 char buffer[128];
1527 char clsName[128];
1528 char wndName[128];
1529 HWND child;
1531 do {
1532 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1533 strcpy(clsName, "-- Unknown --");
1534 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1535 strcpy(wndName, "-- Empty --");
1537 packet_reply_open(gdbctx);
1538 packet_reply_catc(gdbctx, 'O');
1539 snprintf(buffer, sizeof(buffer),
1540 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1541 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1542 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1543 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1544 wndName);
1545 packet_reply_hex_to_str(gdbctx, buffer);
1546 packet_reply_close(gdbctx);
1548 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1549 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1550 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1553 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1555 char buffer[128];
1557 /* we do the output in several 'O' packets, with the last one being just OK for
1558 * marking the end of the output */
1559 packet_reply_open(gdbctx);
1560 packet_reply_catc(gdbctx, 'O');
1561 snprintf(buffer, sizeof(buffer),
1562 "%-16.16s %-17.17s %-8.8s %s\n",
1563 "hwnd", "Class Name", " Style", " WndProc Text");
1564 packet_reply_hex_to_str(gdbctx, buffer);
1565 packet_reply_close(gdbctx);
1567 /* FIXME: could also add a pmt to this command in str... */
1568 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1569 packet_reply(gdbctx, "OK", 2);
1572 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1574 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1575 char buffer[128];
1576 char deco;
1577 PROCESSENTRY32 entry;
1578 BOOL ok;
1580 if (snap == INVALID_HANDLE_VALUE)
1581 return;
1583 entry.dwSize = sizeof(entry);
1584 ok = Process32First(snap, &entry);
1586 /* we do the output in several 'O' packets, with the last one being just OK for
1587 * marking the end of the output */
1589 packet_reply_open(gdbctx);
1590 packet_reply_catc(gdbctx, 'O');
1591 snprintf(buffer, sizeof(buffer),
1592 " %-8.8s %-8.8s %-8.8s %s\n",
1593 "pid", "threads", "parent", "executable");
1594 packet_reply_hex_to_str(gdbctx, buffer);
1595 packet_reply_close(gdbctx);
1597 while (ok)
1599 deco = ' ';
1600 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1601 packet_reply_open(gdbctx);
1602 packet_reply_catc(gdbctx, 'O');
1603 snprintf(buffer, sizeof(buffer),
1604 "%c%08x %-8d %08x '%s'\n",
1605 deco, entry.th32ProcessID, entry.cntThreads,
1606 entry.th32ParentProcessID, entry.szExeFile);
1607 packet_reply_hex_to_str(gdbctx, buffer);
1608 packet_reply_close(gdbctx);
1609 ok = Process32Next(snap, &entry);
1611 CloseHandle(snap);
1612 packet_reply(gdbctx, "OK", 2);
1615 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1617 MEMORY_BASIC_INFORMATION mbi;
1618 char* addr = 0;
1619 const char* state;
1620 const char* type;
1621 char prot[3+1];
1622 char buffer[128];
1624 /* we do the output in several 'O' packets, with the last one being just OK for
1625 * marking the end of the output */
1626 packet_reply_open(gdbctx);
1627 packet_reply_catc(gdbctx, 'O');
1628 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1629 packet_reply_close(gdbctx);
1631 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1633 switch (mbi.State)
1635 case MEM_COMMIT: state = "commit "; break;
1636 case MEM_FREE: state = "free "; break;
1637 case MEM_RESERVE: state = "reserve"; break;
1638 default: state = "??? "; break;
1640 if (mbi.State != MEM_FREE)
1642 switch (mbi.Type)
1644 case MEM_IMAGE: type = "image "; break;
1645 case MEM_MAPPED: type = "mapped "; break;
1646 case MEM_PRIVATE: type = "private"; break;
1647 case 0: type = " "; break;
1648 default: type = "??? "; break;
1650 memset(prot, ' ' , sizeof(prot)-1);
1651 prot[sizeof(prot)-1] = '\0';
1652 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1653 prot[0] = 'R';
1654 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1655 prot[1] = 'W';
1656 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1657 prot[1] = 'C';
1658 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1659 prot[2] = 'X';
1661 else
1663 type = "";
1664 prot[0] = '\0';
1666 packet_reply_open(gdbctx);
1667 snprintf(buffer, sizeof(buffer), "%08lx %08lx %s %s %s\n",
1668 (DWORD_PTR)addr, mbi.RegionSize, state, type, prot);
1669 packet_reply_catc(gdbctx, 'O');
1670 packet_reply_hex_to_str(gdbctx, buffer);
1671 packet_reply_close(gdbctx);
1673 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1674 break;
1675 addr += mbi.RegionSize;
1677 packet_reply(gdbctx, "OK", 2);
1680 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1681 int len, const char* str)
1683 char buffer[128];
1685 if (len == 0)
1687 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1689 else if (len >= 2 && str[0] == '=')
1691 unsigned val = atoi(&str[1]);
1692 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1693 gdbctx->trace = val;
1695 else
1697 /* FIXME: ugly but can use error packet here */
1698 packet_reply_cat(gdbctx, "E00");
1699 return;
1701 packet_reply_open(gdbctx);
1702 packet_reply_hex_to_str(gdbctx, buffer);
1703 packet_reply_close(gdbctx);
1706 struct query_detail
1708 int with_arg;
1709 const char* name;
1710 size_t len;
1711 void (*handler)(struct gdb_context*, int, const char*);
1712 } query_details[] =
1714 {0, "wnd", 3, packet_query_monitor_wnd},
1715 {0, "window", 6, packet_query_monitor_wnd},
1716 {0, "proc", 4, packet_query_monitor_process},
1717 {0, "process", 7, packet_query_monitor_process},
1718 {0, "mem", 3, packet_query_monitor_mem},
1719 {1, "trace", 5, packet_query_monitor_trace},
1720 {0, NULL, 0, NULL},
1723 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1724 const char* hxcmd, size_t len)
1726 char buffer[128];
1727 struct query_detail* qd;
1729 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1730 len /= 2;
1731 hex_from(buffer, hxcmd, len);
1733 for (qd = &query_details[0]; qd->name != NULL; qd++)
1735 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1736 if (!qd->with_arg && len != qd->len) continue;
1738 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1739 return packet_done;
1741 return packet_reply_error(gdbctx, EINVAL);
1744 static enum packet_return packet_query(struct gdb_context* gdbctx)
1746 switch (gdbctx->in_packet[0])
1748 case 'f':
1749 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1751 struct dbg_thread* thd;
1753 packet_reply_open(gdbctx);
1754 packet_reply_add(gdbctx, "m", 1);
1755 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1757 packet_reply_val(gdbctx, thd->tid, 4);
1758 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1759 packet_reply_add(gdbctx, ",", 1);
1761 packet_reply_close(gdbctx);
1762 return packet_done;
1764 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1766 char result[128];
1768 packet_reply_open(gdbctx);
1769 packet_reply_catc(gdbctx, 'O');
1770 get_process_info(gdbctx, result, sizeof(result));
1771 packet_reply_hex_to_str(gdbctx, result);
1772 packet_reply_close(gdbctx);
1773 return packet_done;
1775 break;
1776 case 's':
1777 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1779 packet_reply(gdbctx, "l", 1);
1780 return packet_done;
1782 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1784 packet_reply(gdbctx, "l", 1);
1785 return packet_done;
1787 break;
1788 case 'A':
1789 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
1791 char buf[2];
1793 buf[0] = '1';
1794 buf[1] = 0;
1795 return packet_reply(gdbctx, buf, -1);
1797 break;
1798 case 'C':
1799 if (gdbctx->in_packet_len == 1)
1801 struct dbg_thread* thd;
1802 /* FIXME: doc says 16 bit val ??? */
1803 /* grab first created thread, aka last in list */
1804 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1805 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1806 packet_reply_open(gdbctx);
1807 packet_reply_add(gdbctx, "QC", 2);
1808 packet_reply_val(gdbctx, thd->tid, 4);
1809 packet_reply_close(gdbctx);
1810 return packet_done;
1812 break;
1813 case 'O':
1814 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1816 char buf[64];
1818 snprintf(buf, sizeof(buf),
1819 "Text=%08lx;Data=%08lx;Bss=%08lx",
1820 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1821 gdbctx->wine_segs[2]);
1822 return packet_reply(gdbctx, buf, -1);
1824 break;
1825 case 'R':
1826 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1828 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1829 gdbctx->in_packet_len - 5);
1831 break;
1832 case 'S':
1833 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1834 return packet_ok;
1835 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1837 /* no features supported */
1838 packet_reply_open(gdbctx);
1839 packet_reply_close(gdbctx);
1840 return packet_done;
1842 break;
1843 case 'T':
1844 if (gdbctx->in_packet_len > 15 &&
1845 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1846 gdbctx->in_packet[15] == ',')
1848 unsigned tid;
1849 char* end;
1850 char result[128];
1852 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1853 if (end == NULL) break;
1854 get_thread_info(gdbctx, tid, result, sizeof(result));
1855 packet_reply_open(gdbctx);
1856 packet_reply_hex_to_str(gdbctx, result);
1857 packet_reply_close(gdbctx);
1858 return packet_done;
1860 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
1862 /* Tracepoints not supported */
1863 packet_reply_open(gdbctx);
1864 packet_reply_close(gdbctx);
1865 return packet_done;
1867 break;
1869 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1870 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1871 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1872 return packet_error;
1875 static enum packet_return packet_step(struct gdb_context* gdbctx)
1877 /* FIXME: add support for address in packet */
1878 assert(gdbctx->in_packet_len == 0);
1879 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1880 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1881 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1882 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1883 be_cpu->single_step(&gdbctx->context, TRUE);
1884 resume_debuggee(gdbctx, DBG_CONTINUE);
1885 wait_for_debuggee(gdbctx);
1886 be_cpu->single_step(&gdbctx->context, FALSE);
1887 return packet_reply_status(gdbctx);
1890 #if 0
1891 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1893 unsigned char sig;
1895 /* FIXME: add support for address in packet */
1896 assert(gdbctx->in_packet_len == 2);
1897 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1898 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1899 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1900 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1901 hex_from(&sig, gdbctx->in_packet, 1);
1902 /* cannot change signals on the fly */
1903 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1904 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1905 if (sig != gdbctx->last_sig)
1906 return packet_error;
1907 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1908 wait_for_debuggee(gdbctx);
1909 return packet_reply_status(gdbctx);
1911 #endif
1913 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1915 char* end;
1916 unsigned tid;
1918 tid = strtol(gdbctx->in_packet, &end, 16);
1919 if (tid == -1 || tid == 0)
1920 return packet_reply_error(gdbctx, EINVAL);
1921 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1922 return packet_ok;
1923 return packet_reply_error(gdbctx, ESRCH);
1926 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1928 void* addr;
1929 unsigned len;
1930 struct gdb_ctx_Xpoint* xpt;
1931 enum be_xpoint_type t;
1933 /* FIXME: check packet_len */
1934 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1935 gdbctx->in_packet[1] != ',' ||
1936 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1937 return packet_error;
1938 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1939 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1940 addr, len, gdbctx->in_packet[0]);
1941 switch (gdbctx->in_packet[0])
1943 case '0': t = be_xpoint_break; len = 0; break;
1944 case '1': t = be_xpoint_watch_exec; break;
1945 case '2': t = be_xpoint_watch_read; break;
1946 case '3': t = be_xpoint_watch_write; break;
1947 default: return packet_error;
1949 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1951 if (xpt->addr == addr && xpt->type == t)
1953 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1954 gdbctx->process->process_io, &gdbctx->context,
1955 t, xpt->addr, xpt->val, len))
1957 xpt->type = -1;
1958 return packet_ok;
1960 break;
1963 return packet_error;
1966 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1968 void* addr;
1969 unsigned len;
1970 struct gdb_ctx_Xpoint* xpt;
1971 enum be_xpoint_type t;
1973 /* FIXME: check packet_len */
1974 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1975 gdbctx->in_packet[1] != ',' ||
1976 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1977 return packet_error;
1978 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1979 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1980 addr, len, gdbctx->in_packet[0]);
1981 switch (gdbctx->in_packet[0])
1983 case '0': t = be_xpoint_break; len = 0; break;
1984 case '1': t = be_xpoint_watch_exec; break;
1985 case '2': t = be_xpoint_watch_read; break;
1986 case '3': t = be_xpoint_watch_write; break;
1987 default: return packet_error;
1989 /* because of packet command handling, this should be made idempotent */
1990 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1992 if (xpt->addr == addr && xpt->type == t)
1993 return packet_ok; /* nothing to do */
1995 /* really set the Xpoint */
1996 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1998 if (xpt->type == -1)
2000 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2001 gdbctx->process->process_io, &gdbctx->context,
2002 t, addr, &xpt->val, len))
2004 xpt->addr = addr;
2005 xpt->type = t;
2006 return packet_ok;
2008 fprintf(stderr, "cannot set xpoint\n");
2009 break;
2012 /* no more entries... eech */
2013 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2014 return packet_error;
2017 /* =============================================== *
2018 * P A C K E T I N F R A S T R U C T U R E *
2019 * =============================================== *
2022 struct packet_entry
2024 char key;
2025 enum packet_return (*handler)(struct gdb_context* gdbctx);
2028 static struct packet_entry packet_entries[] =
2030 /*{'!', packet_extended}, */
2031 {'?', packet_last_signal},
2032 {'c', packet_continue},
2033 {'C', packet_continue_signal},
2034 {'D', packet_detach},
2035 {'g', packet_read_registers},
2036 {'G', packet_write_registers},
2037 {'k', packet_kill},
2038 {'H', packet_thread},
2039 {'m', packet_read_memory},
2040 {'M', packet_write_memory},
2041 {'p', packet_read_register},
2042 {'P', packet_write_register},
2043 {'q', packet_query},
2044 /* {'Q', packet_set}, */
2045 /* {'R', packet,restart}, only in extended mode ! */
2046 {'s', packet_step},
2047 /*{'S', packet_step_signal}, hard(er) to implement */
2048 {'T', packet_thread_alive},
2049 {'v', packet_verbose},
2050 {'z', packet_remove_breakpoint},
2051 {'Z', packet_set_breakpoint},
2054 static BOOL extract_packets(struct gdb_context* gdbctx)
2056 char* end;
2057 int plen;
2058 unsigned char in_cksum, loc_cksum;
2059 char* ptr;
2060 enum packet_return ret = packet_error;
2061 int num_packet = 0;
2063 while ((ret & packet_last_f) == 0)
2065 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2066 fprintf(stderr, "In-buf: %*.*s\n",
2067 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2068 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2069 if (ptr == NULL) return FALSE;
2070 if (ptr != gdbctx->in_buf)
2072 int glen = ptr - gdbctx->in_buf; /* garbage len */
2073 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2074 fprintf(stderr, "Removing garbage: %*.*s\n",
2075 glen, glen, gdbctx->in_buf);
2076 gdbctx->in_len -= glen;
2077 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2079 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2080 if (end == NULL) return FALSE;
2081 /* no checksum yet */
2082 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2083 plen = end - gdbctx->in_buf - 1;
2084 hex_from(&in_cksum, end + 1, 1);
2085 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2086 if (loc_cksum == in_cksum)
2088 if (num_packet == 0) {
2089 int i;
2091 ret = packet_error;
2093 write(gdbctx->sock, "+", 1);
2094 assert(plen);
2096 /* FIXME: should use bsearch if packet_entries was sorted */
2097 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2099 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2101 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2103 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2104 fprintf(stderr, "Unknown packet request %*.*s\n",
2105 plen, plen, &gdbctx->in_buf[1]);
2107 else
2109 gdbctx->in_packet = gdbctx->in_buf + 2;
2110 gdbctx->in_packet_len = plen - 1;
2111 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2112 fprintf(stderr, "Packet: %c%*.*s\n",
2113 gdbctx->in_buf[1],
2114 gdbctx->in_packet_len, gdbctx->in_packet_len,
2115 gdbctx->in_packet);
2116 ret = (packet_entries[i].handler)(gdbctx);
2118 switch (ret & ~packet_last_f)
2120 case packet_error: packet_reply(gdbctx, "", 0); break;
2121 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2122 case packet_done: break;
2124 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2125 fprintf(stderr, "Reply-full: %*.*s\n",
2126 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2127 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2128 assert(i == gdbctx->out_len);
2129 /* if this fails, we'll have to use POLLOUT...
2131 gdbctx->out_len = 0;
2132 num_packet++;
2134 else
2136 /* FIXME: if we have in our input buffer more than one packet,
2137 * it's very likely that we took too long to answer to a given packet
2138 * and gdb is sending us again the same packet
2139 * We simply drop the second packet. This will lower the risk of error,
2140 * but there's still some race conditions here
2141 * A better fix (yet not perfect) would be to have two threads:
2142 * - one managing the packets for gdb
2143 * - the second one managing the commands...
2144 * This would allow us also the reply with the '+' character (Ack of
2145 * the command) way sooner than what we do now
2147 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2148 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2151 else
2153 write(gdbctx->sock, "+", 1);
2154 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2155 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2157 gdbctx->in_len -= plen + 4;
2158 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2160 return TRUE;
2163 static int fetch_data(struct gdb_context* gdbctx)
2165 int len, in_len = gdbctx->in_len;
2167 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2168 for (;;)
2170 #define STEP 128
2171 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2172 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2173 #undef STEP
2174 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2175 fprintf(stderr, "%d %d %*.*s\n",
2176 gdbctx->in_len, gdbctx->in_buf_alloc,
2177 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2178 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2179 if (len <= 0) break;
2180 gdbctx->in_len += len;
2181 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2182 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2184 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2185 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2186 return gdbctx->in_len - in_len;
2189 #define FLAG_NO_START 1
2190 #define FLAG_WITH_XTERM 2
2192 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2194 char buf[MAX_PATH];
2195 int fd;
2196 const char* gdb_path;
2197 FILE* f;
2199 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2200 strcpy(buf,"/tmp/winegdb.XXXXXX");
2201 fd = mkstemps(buf, 0);
2202 if (fd == -1) return FALSE;
2203 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2204 fprintf(f, "file %s\n", wine_path);
2205 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2206 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2207 fprintf(f, "set prompt Wine-gdb>\\ \n");
2208 /* gdb 5.1 seems to require it, won't hurt anyway */
2209 fprintf(f, "sharedlibrary\n");
2210 /* This is needed (but not a decent & final fix)
2211 * Without this, gdb would skip our inter-DLL relay code (because
2212 * we don't have any line number information for the relay code)
2213 * With this, we will stop on first instruction of the stub, and
2214 * reusing step, will get us through the relay stub at the actual
2215 * function we're looking at.
2217 fprintf(f, "set step-mode on\n");
2218 /* tell gdb to delete this file when done handling it... */
2219 fprintf(f, "shell rm -f \"%s\"\n", buf);
2220 fclose(f);
2221 if (flags & FLAG_WITH_XTERM)
2222 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2223 else
2224 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2225 assert(0); /* never reached */
2226 return TRUE;
2229 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2231 int sock;
2232 struct sockaddr_in s_addrs;
2233 unsigned int s_len = sizeof(s_addrs);
2234 struct pollfd pollfd;
2235 IMAGEHLP_MODULE64 imh_mod;
2237 /* step 1: create socket for gdb connection request */
2238 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2240 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2241 fprintf(stderr, "Can't create socket");
2242 return FALSE;
2245 if (listen(sock, 1) == -1 ||
2246 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2247 return FALSE;
2249 /* step 2: do the process internal creation */
2250 handle_debug_event(gdbctx, de);
2252 /* step3: get the wine loader name */
2253 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2255 /* step 4: fire up gdb (if requested) */
2256 if (flags & FLAG_NO_START)
2257 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2258 else
2259 switch (fork())
2261 case -1: /* error in parent... */
2262 fprintf(stderr, "Cannot create gdb\n");
2263 return FALSE;
2264 default: /* in parent... success */
2265 signal(SIGINT, SIG_IGN);
2266 break;
2267 case 0: /* in child... and alive */
2268 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2269 /* if we're here, exec failed, so report failure */
2270 return FALSE;
2273 /* step 5: wait for gdb to connect actually */
2274 pollfd.fd = sock;
2275 pollfd.events = POLLIN;
2276 pollfd.revents = 0;
2278 switch (poll(&pollfd, 1, -1))
2280 case 1:
2281 if (pollfd.revents & POLLIN)
2283 int dummy = 1;
2284 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2285 if (gdbctx->sock == -1)
2286 break;
2287 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2288 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2289 /* don't keep our small packets too long: send them ASAP back to GDB
2290 * without this, GDB really crawls
2292 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2294 break;
2295 case 0:
2296 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2297 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2298 return FALSE;
2299 case -1:
2300 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2301 fprintf(stderr, "Poll for cnx failed (error)\n");
2302 return FALSE;
2303 default:
2304 assert(0);
2307 close(sock);
2308 return TRUE;
2311 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2313 DEBUG_EVENT de;
2314 int i;
2316 gdbctx->sock = -1;
2317 gdbctx->in_buf = NULL;
2318 gdbctx->in_buf_alloc = 0;
2319 gdbctx->in_len = 0;
2320 gdbctx->out_buf = NULL;
2321 gdbctx->out_buf_alloc = 0;
2322 gdbctx->out_len = 0;
2323 gdbctx->out_curr_packet = -1;
2325 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2326 gdbctx->last_sig = 0;
2327 gdbctx->in_trap = FALSE;
2328 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2329 gdbctx->process = NULL;
2330 for (i = 0; i < NUM_XPOINT; i++)
2331 gdbctx->Xpoints[i].type = -1;
2332 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2333 gdbctx->wine_segs[i] = 0;
2335 /* wait for first trap */
2336 while (WaitForDebugEvent(&de, INFINITE))
2338 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2340 /* this should be the first event we get,
2341 * and the only one of this type */
2342 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2343 /* gdbctx->dwProcessId = pid; */
2344 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2345 assert(!gdbctx->in_trap);
2347 else
2349 handle_debug_event(gdbctx, &de);
2350 if (gdbctx->in_trap) break;
2352 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2354 return TRUE;
2357 static int gdb_remote(unsigned flags)
2359 struct pollfd pollfd;
2360 struct gdb_context gdbctx;
2361 BOOL doLoop;
2363 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2365 pollfd.fd = gdbctx.sock;
2366 pollfd.events = POLLIN;
2367 pollfd.revents = 0;
2369 switch (poll(&pollfd, 1, -1))
2371 case 1:
2372 /* got something */
2373 if (pollfd.revents & (POLLHUP | POLLERR))
2375 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2376 fprintf(stderr, "Gdb hung up\n");
2377 /* kill also debuggee process - questionnable - */
2378 detach_debuggee(&gdbctx, TRUE);
2379 doLoop = FALSE;
2380 break;
2382 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2384 if (extract_packets(&gdbctx)) doLoop = FALSE;
2386 break;
2387 case 0:
2388 /* timeout, should never happen (infinite timeout) */
2389 break;
2390 case -1:
2391 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2392 fprintf(stderr, "Poll failed\n");
2393 doLoop = FALSE;
2394 break;
2397 wait(NULL);
2398 return 0;
2400 #endif
2402 int gdb_main(int argc, char* argv[])
2404 #ifdef HAVE_POLL
2405 unsigned gdb_flags = 0;
2407 argc--; argv++;
2408 while (argc > 0 && argv[0][0] == '-')
2410 if (strcmp(argv[0], "--no-start") == 0)
2412 gdb_flags |= FLAG_NO_START;
2413 argc--; argv++;
2414 continue;
2416 if (strcmp(argv[0], "--with-xterm") == 0)
2418 gdb_flags |= FLAG_WITH_XTERM;
2419 argc--; argv++;
2420 continue;
2422 return -1;
2424 if (dbg_active_attach(argc, argv) == start_ok ||
2425 dbg_active_launch(argc, argv) == start_ok)
2426 return gdb_remote(gdb_flags);
2427 #else
2428 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2429 #endif
2430 return -1;