dpnet: COM cleanup for the IDirectPlay8LobbiedApplication iface.
[wine/multimedia.git] / programs / winedbg / gdbproxy.c
blobe81f72c3bb09d9ff367c4943d7444c196d3d8bfb
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(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 /* basic check */
1016 assert(gdbctx->in_packet_len >= 4);
1018 /* OK we have vCont followed by..
1019 * ? for query
1020 * c for packet_continue
1021 * Csig for packet_continue_signal
1022 * s for step
1023 * Ssig for step signal
1024 * and then an optional thread ID at the end..
1025 * *******************************************/
1027 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1028 fprintf(stderr, "trying to process a verbose packet\n");
1029 /* now check that we've got Cont */
1030 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
1032 /* Query */
1033 if (gdbctx->in_packet[4] == '?')
1036 Reply:
1037 `vCont[;action]...'
1038 The vCont packet is supported. Each action is a supported command in the vCont packet.
1040 The vCont packet is not supported. (this didn't seem to be obeyed!)
1042 packet_reply_open(gdbctx);
1043 packet_reply_add(gdbctx, "vCont", 5);
1044 /* add all the supported actions to the reply (all of them for now) */
1045 packet_reply_add(gdbctx, ";c", 2);
1046 packet_reply_add(gdbctx, ";C", 2);
1047 packet_reply_add(gdbctx, ";s", 2);
1048 packet_reply_add(gdbctx, ";S", 2);
1049 packet_reply_close(gdbctx);
1050 return packet_done;
1053 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1054 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1055 now if only gdb talked XML.... */
1056 #if 0 /* handy for debugging */
1057 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1058 #endif
1060 /* go through the packet and identify where all the actions start at */
1061 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1063 if (gdbctx->in_packet[i] == ';')
1065 threadIndex[actions] = 0;
1066 actionIndex[actions++] = i;
1068 else if (gdbctx->in_packet[i] == ':')
1070 threadIndex[actions - 1] = i;
1074 /* now look up the default action */
1075 for (i = 0 ; i < actions; i++)
1077 if (threadIndex[i] == 0)
1079 if (defaultAction != -1)
1081 fprintf(stderr,"Too many default actions specified\n");
1082 return packet_error;
1084 defaultAction = i;
1088 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1090 /* go through all the threads and stick their ids in the to be done list. */
1091 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1093 threadIDs[threadCount++] = thd->tid;
1094 /* check to see if we have more threads than I counted on, and tell the user what to do
1095 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1096 if (threadCount == 100)
1098 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1099 break;
1103 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1104 * that remains is to apply the actions to the threads and the default action to any threads
1105 * left */
1106 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1107 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1108 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1109 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1111 /* deal with the threaded stuff first */
1112 for (i = 0; i < actions ; i++)
1114 if (threadIndex[i] != 0)
1116 int j, idLength = 0;
1117 if (i < actions - 1)
1119 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1121 else
1123 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1126 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1127 /* process the action */
1128 switch (gdbctx->in_packet[actionIndex[i] + 1])
1130 case 's': /* step */
1131 be_cpu->single_step(&gdbctx->context, TRUE);
1132 /* fall through*/
1133 case 'c': /* continue */
1134 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1135 break;
1136 case 'S': /* step Sig, */
1137 be_cpu->single_step(&gdbctx->context, TRUE);
1138 /* fall through */
1139 case 'C': /* continue sig */
1140 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1141 /* cannot change signals on the fly */
1142 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1143 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1144 if (sig != gdbctx->last_sig)
1145 return packet_error;
1146 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1147 break;
1149 for (j = 0 ; j < threadCount; j++)
1151 if (threadIDs[j] == threadID)
1153 threadIDs[j] = 0;
1154 break;
1158 } /* for i=0 ; i< actions */
1160 /* now we have manage the default action */
1161 if (defaultAction >= 0)
1163 for (i = 0 ; i< threadCount; i++)
1165 /* check to see if we've already done something to the thread*/
1166 if (threadIDs[i] != 0)
1168 /* if not apply the default action*/
1169 threadID = threadIDs[i];
1170 /* process the action (yes this is almost identical to the one above!) */
1171 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1173 case 's': /* step */
1174 be_cpu->single_step(&gdbctx->context, TRUE);
1175 /* fall through */
1176 case 'c': /* continue */
1177 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1178 break;
1179 case 'S':
1180 be_cpu->single_step(&gdbctx->context, TRUE);
1181 /* fall through */
1182 case 'C': /* continue sig */
1183 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1184 /* cannot change signals on the fly */
1185 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1186 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1187 if (sig != gdbctx->last_sig)
1188 return packet_error;
1189 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1190 break;
1194 } /* if(defaultAction >=0) */
1196 wait_for_debuggee(gdbctx);
1197 be_cpu->single_step(&gdbctx->context, FALSE);
1198 return packet_reply_status(gdbctx);
1201 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1203 unsigned char sig;
1205 /* FIXME: add support for address in packet */
1206 assert(gdbctx->in_packet_len == 2);
1207 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1208 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1209 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1210 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1211 hex_from(&sig, gdbctx->in_packet, 1);
1212 /* cannot change signals on the fly */
1213 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1214 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1215 if (sig != gdbctx->last_sig)
1216 return packet_error;
1217 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1218 wait_for_debuggee(gdbctx);
1219 return packet_reply_status(gdbctx);
1222 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1224 detach_debuggee(gdbctx, FALSE);
1225 return packet_ok | packet_last_f;
1228 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1230 int i;
1231 CONTEXT ctx;
1232 CONTEXT* pctx = &gdbctx->context;
1234 assert(gdbctx->in_trap);
1236 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1238 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1239 return packet_error;
1242 packet_reply_open(gdbctx);
1243 for (i = 0; i < cpu_num_regs; i++)
1245 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1247 packet_reply_close(gdbctx);
1248 return packet_done;
1251 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1253 unsigned i;
1254 CONTEXT ctx;
1255 CONTEXT* pctx = &gdbctx->context;
1257 assert(gdbctx->in_trap);
1258 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1260 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1261 return packet_error;
1263 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1265 for (i = 0; i < cpu_num_regs; i++)
1266 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1267 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1269 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1270 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1271 return packet_error;
1273 return packet_ok;
1276 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1278 detach_debuggee(gdbctx, TRUE);
1279 #if 0
1280 if (!gdbctx->extended)
1281 /* dunno whether GDB cares or not */
1282 #endif
1283 wait(NULL);
1284 exit(0);
1285 /* assume we can't really answer something here */
1286 /* return packet_done; */
1289 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1291 char* end;
1292 unsigned thread;
1294 switch (gdbctx->in_packet[0])
1296 case 'c':
1297 case 'g':
1298 if (gdbctx->in_packet[1] == '-')
1299 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1300 else
1301 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1302 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1304 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1305 fprintf(stderr, "Cannot get threadid %*.*s\n",
1306 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1307 gdbctx->in_packet + 1);
1308 return packet_error;
1310 if (gdbctx->in_packet[0] == 'c')
1311 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1312 else
1313 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1314 return packet_ok;
1315 default:
1316 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1317 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1318 return packet_error;
1322 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1324 char *addr;
1325 unsigned int len, blk_len, nread;
1326 char buffer[32];
1327 SIZE_T r = 0;
1329 assert(gdbctx->in_trap);
1330 /* FIXME:check in_packet_len for reading %p,%x */
1331 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1332 if (len <= 0) return packet_error;
1333 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1334 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1335 for (nread = 0; nread < len; nread += r, addr += r)
1337 blk_len = min(sizeof(buffer), len - nread);
1338 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1339 r == 0)
1341 /* fail at first address, return error */
1342 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1343 /* something has already been read, return partial information */
1344 break;
1346 if (nread == 0) packet_reply_open(gdbctx);
1347 packet_reply_hex_to(gdbctx, buffer, r);
1349 packet_reply_close(gdbctx);
1350 return packet_done;
1353 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1355 char* addr;
1356 unsigned int len, blk_len;
1357 char* ptr;
1358 char buffer[32];
1359 SIZE_T w;
1361 assert(gdbctx->in_trap);
1362 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1363 if (ptr == NULL)
1365 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1366 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1367 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1368 return packet_error;
1370 *ptr++ = '\0';
1372 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1374 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1375 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1376 return packet_error;
1378 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1380 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1381 fprintf(stderr, "Wrong sizes %u <> %u\n",
1382 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1383 return packet_error;
1385 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1386 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1387 while (len > 0)
1389 blk_len = min(sizeof(buffer), len);
1390 hex_from(buffer, ptr, blk_len);
1391 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1392 w != blk_len)
1393 break;
1394 addr += blk_len;
1395 len -= blk_len;
1396 ptr += blk_len;
1398 return packet_ok; /* FIXME: error while writing ? */
1401 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1403 unsigned reg;
1404 CONTEXT ctx;
1405 CONTEXT* pctx = &gdbctx->context;
1407 assert(gdbctx->in_trap);
1408 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1409 if (reg >= cpu_num_regs)
1411 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1412 fprintf(stderr, "Register out of bounds %x\n", reg);
1413 return packet_error;
1415 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1417 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1418 return packet_error;
1420 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1421 fprintf(stderr, "Read register %x => %lx\n", reg, *cpu_register(pctx, reg));
1422 packet_reply_open(gdbctx);
1423 packet_reply_hex_to(gdbctx, cpu_register(pctx, reg), 4);
1424 packet_reply_close(gdbctx);
1425 return packet_done;
1428 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1430 unsigned reg;
1431 char* ptr;
1432 char* end;
1433 CONTEXT ctx;
1434 CONTEXT* pctx = &gdbctx->context;
1436 assert(gdbctx->in_trap);
1438 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1439 *ptr++ = '\0';
1440 reg = strtoul(gdbctx->in_packet, &end, 16);
1441 if (end == NULL || reg > cpu_num_regs)
1443 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1444 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1445 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1446 * it wouldn't matter too much, and it fakes our support for all regs
1448 return (end == NULL) ? packet_error : packet_ok;
1450 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1452 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1453 fprintf(stderr, "Wrong sizes %u <> %u\n",
1454 (int)(ptr + 8 - gdbctx->in_packet), gdbctx->in_packet_len);
1455 return packet_error;
1457 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1459 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1460 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr );
1463 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1465 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1466 return packet_error;
1469 hex_from(cpu_register(pctx, reg), ptr, 4);
1470 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1472 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1473 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1474 return packet_error;
1477 return packet_ok;
1480 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1482 char buffer[128];
1483 char clsName[128];
1484 char wndName[128];
1485 HWND child;
1487 do {
1488 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1489 strcpy(clsName, "-- Unknown --");
1490 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1491 strcpy(wndName, "-- Empty --");
1493 packet_reply_open(gdbctx);
1494 packet_reply_catc(gdbctx, 'O');
1495 snprintf(buffer, sizeof(buffer),
1496 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1497 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1498 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1499 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1500 wndName);
1501 packet_reply_hex_to_str(gdbctx, buffer);
1502 packet_reply_close(gdbctx);
1504 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1505 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1506 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1509 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1511 char buffer[128];
1513 /* we do the output in several 'O' packets, with the last one being just OK for
1514 * marking the end of the output */
1515 packet_reply_open(gdbctx);
1516 packet_reply_catc(gdbctx, 'O');
1517 snprintf(buffer, sizeof(buffer),
1518 "%-16.16s %-17.17s %-8.8s %s\n",
1519 "hwnd", "Class Name", " Style", " WndProc Text");
1520 packet_reply_hex_to_str(gdbctx, buffer);
1521 packet_reply_close(gdbctx);
1523 /* FIXME: could also add a pmt to this command in str... */
1524 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1525 packet_reply(gdbctx, "OK", 2);
1528 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1530 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1531 char buffer[128];
1532 char deco;
1533 PROCESSENTRY32 entry;
1534 BOOL ok;
1536 if (snap == INVALID_HANDLE_VALUE)
1537 return;
1539 entry.dwSize = sizeof(entry);
1540 ok = Process32First(snap, &entry);
1542 /* we do the output in several 'O' packets, with the last one being just OK for
1543 * marking the end of the output */
1545 packet_reply_open(gdbctx);
1546 packet_reply_catc(gdbctx, 'O');
1547 snprintf(buffer, sizeof(buffer),
1548 " %-8.8s %-8.8s %-8.8s %s\n",
1549 "pid", "threads", "parent", "executable");
1550 packet_reply_hex_to_str(gdbctx, buffer);
1551 packet_reply_close(gdbctx);
1553 while (ok)
1555 deco = ' ';
1556 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1557 packet_reply_open(gdbctx);
1558 packet_reply_catc(gdbctx, 'O');
1559 snprintf(buffer, sizeof(buffer),
1560 "%c%08x %-8d %08x '%s'\n",
1561 deco, entry.th32ProcessID, entry.cntThreads,
1562 entry.th32ParentProcessID, entry.szExeFile);
1563 packet_reply_hex_to_str(gdbctx, buffer);
1564 packet_reply_close(gdbctx);
1565 ok = Process32Next(snap, &entry);
1567 CloseHandle(snap);
1568 packet_reply(gdbctx, "OK", 2);
1571 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1573 MEMORY_BASIC_INFORMATION mbi;
1574 char* addr = 0;
1575 const char* state;
1576 const char* type;
1577 char prot[3+1];
1578 char buffer[128];
1580 /* we do the output in several 'O' packets, with the last one being just OK for
1581 * marking the end of the output */
1582 packet_reply_open(gdbctx);
1583 packet_reply_catc(gdbctx, 'O');
1584 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1585 packet_reply_close(gdbctx);
1587 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1589 switch (mbi.State)
1591 case MEM_COMMIT: state = "commit "; break;
1592 case MEM_FREE: state = "free "; break;
1593 case MEM_RESERVE: state = "reserve"; break;
1594 default: state = "??? "; break;
1596 if (mbi.State != MEM_FREE)
1598 switch (mbi.Type)
1600 case MEM_IMAGE: type = "image "; break;
1601 case MEM_MAPPED: type = "mapped "; break;
1602 case MEM_PRIVATE: type = "private"; break;
1603 case 0: type = " "; break;
1604 default: type = "??? "; break;
1606 memset(prot, ' ' , sizeof(prot)-1);
1607 prot[sizeof(prot)-1] = '\0';
1608 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1609 prot[0] = 'R';
1610 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1611 prot[1] = 'W';
1612 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1613 prot[1] = 'C';
1614 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1615 prot[2] = 'X';
1617 else
1619 type = "";
1620 prot[0] = '\0';
1622 packet_reply_open(gdbctx);
1623 snprintf(buffer, sizeof(buffer), "%08lx %08lx %s %s %s\n",
1624 (DWORD_PTR)addr, mbi.RegionSize, state, type, prot);
1625 packet_reply_catc(gdbctx, 'O');
1626 packet_reply_hex_to_str(gdbctx, buffer);
1627 packet_reply_close(gdbctx);
1629 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1630 break;
1631 addr += mbi.RegionSize;
1633 packet_reply(gdbctx, "OK", 2);
1636 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1637 int len, const char* str)
1639 char buffer[128];
1641 if (len == 0)
1643 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1645 else if (len >= 2 && str[0] == '=')
1647 unsigned val = atoi(&str[1]);
1648 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1649 gdbctx->trace = val;
1651 else
1653 /* FIXME: ugly but can use error packet here */
1654 packet_reply_cat(gdbctx, "E00");
1655 return;
1657 packet_reply_open(gdbctx);
1658 packet_reply_hex_to_str(gdbctx, buffer);
1659 packet_reply_close(gdbctx);
1662 struct query_detail
1664 int with_arg;
1665 const char* name;
1666 size_t len;
1667 void (*handler)(struct gdb_context*, int, const char*);
1668 } query_details[] =
1670 {0, "wnd", 3, packet_query_monitor_wnd},
1671 {0, "window", 6, packet_query_monitor_wnd},
1672 {0, "proc", 4, packet_query_monitor_process},
1673 {0, "process", 7, packet_query_monitor_process},
1674 {0, "mem", 3, packet_query_monitor_mem},
1675 {1, "trace", 5, packet_query_monitor_trace},
1676 {0, NULL, 0, NULL},
1679 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1680 const char* hxcmd, size_t len)
1682 char buffer[128];
1683 struct query_detail* qd;
1685 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1686 len /= 2;
1687 hex_from(buffer, hxcmd, len);
1689 for (qd = &query_details[0]; qd->name != NULL; qd++)
1691 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1692 if (!qd->with_arg && len != qd->len) continue;
1694 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1695 return packet_done;
1697 return packet_reply_error(gdbctx, EINVAL);
1700 static enum packet_return packet_query(struct gdb_context* gdbctx)
1702 switch (gdbctx->in_packet[0])
1704 case 'f':
1705 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1707 struct dbg_thread* thd;
1709 packet_reply_open(gdbctx);
1710 packet_reply_add(gdbctx, "m", 1);
1711 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1713 packet_reply_val(gdbctx, thd->tid, 4);
1714 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1715 packet_reply_add(gdbctx, ",", 1);
1717 packet_reply_close(gdbctx);
1718 return packet_done;
1720 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1722 char result[128];
1724 packet_reply_open(gdbctx);
1725 packet_reply_catc(gdbctx, 'O');
1726 get_process_info(gdbctx, result, sizeof(result));
1727 packet_reply_hex_to_str(gdbctx, result);
1728 packet_reply_close(gdbctx);
1729 return packet_done;
1731 break;
1732 case 's':
1733 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1735 packet_reply(gdbctx, "l", 1);
1736 return packet_done;
1738 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1740 packet_reply(gdbctx, "l", 1);
1741 return packet_done;
1743 break;
1744 case 'C':
1745 if (gdbctx->in_packet_len == 1)
1747 struct dbg_thread* thd;
1748 /* FIXME: doc says 16 bit val ??? */
1749 /* grab first created thread, aka last in list */
1750 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1751 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1752 packet_reply_open(gdbctx);
1753 packet_reply_add(gdbctx, "QC", 2);
1754 packet_reply_val(gdbctx, thd->tid, 4);
1755 packet_reply_close(gdbctx);
1756 return packet_done;
1758 break;
1759 case 'O':
1760 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1762 char buf[64];
1764 snprintf(buf, sizeof(buf),
1765 "Text=%08lx;Data=%08lx;Bss=%08lx",
1766 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1767 gdbctx->wine_segs[2]);
1768 return packet_reply(gdbctx, buf, -1);
1770 break;
1771 case 'R':
1772 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1774 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1775 gdbctx->in_packet_len - 5);
1777 break;
1778 case 'S':
1779 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1780 return packet_ok;
1781 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1783 /* no features supported */
1784 packet_reply_open(gdbctx);
1785 packet_reply_close(gdbctx);
1786 return packet_done;
1788 break;
1789 case 'T':
1790 if (gdbctx->in_packet_len > 15 &&
1791 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1792 gdbctx->in_packet[15] == ',')
1794 unsigned tid;
1795 char* end;
1796 char result[128];
1798 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1799 if (end == NULL) break;
1800 get_thread_info(gdbctx, tid, result, sizeof(result));
1801 packet_reply_open(gdbctx);
1802 packet_reply_hex_to_str(gdbctx, result);
1803 packet_reply_close(gdbctx);
1804 return packet_done;
1806 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
1808 /* Tracepoints not supported */
1809 packet_reply_open(gdbctx);
1810 packet_reply_close(gdbctx);
1811 return packet_done;
1813 break;
1815 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1816 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1817 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1818 return packet_error;
1821 static enum packet_return packet_step(struct gdb_context* gdbctx)
1823 /* FIXME: add support for address in packet */
1824 assert(gdbctx->in_packet_len == 0);
1825 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1826 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1827 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1828 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1829 be_cpu->single_step(&gdbctx->context, TRUE);
1830 resume_debuggee(gdbctx, DBG_CONTINUE);
1831 wait_for_debuggee(gdbctx);
1832 be_cpu->single_step(&gdbctx->context, FALSE);
1833 return packet_reply_status(gdbctx);
1836 #if 0
1837 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1839 unsigned char sig;
1841 /* FIXME: add support for address in packet */
1842 assert(gdbctx->in_packet_len == 2);
1843 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1844 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1845 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1846 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1847 hex_from(&sig, gdbctx->in_packet, 1);
1848 /* cannot change signals on the fly */
1849 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1850 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1851 if (sig != gdbctx->last_sig)
1852 return packet_error;
1853 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1854 wait_for_debuggee(gdbctx);
1855 return packet_reply_status(gdbctx);
1857 #endif
1859 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1861 char* end;
1862 unsigned tid;
1864 tid = strtol(gdbctx->in_packet, &end, 16);
1865 if (tid == -1 || tid == 0)
1866 return packet_reply_error(gdbctx, EINVAL);
1867 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1868 return packet_ok;
1869 return packet_reply_error(gdbctx, ESRCH);
1872 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1874 void* addr;
1875 unsigned len;
1876 struct gdb_ctx_Xpoint* xpt;
1877 enum be_xpoint_type t;
1879 /* FIXME: check packet_len */
1880 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1881 gdbctx->in_packet[1] != ',' ||
1882 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1883 return packet_error;
1884 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1885 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1886 addr, len, gdbctx->in_packet[0]);
1887 switch (gdbctx->in_packet[0])
1889 case '0': t = be_xpoint_break; len = 0; break;
1890 case '1': t = be_xpoint_watch_exec; break;
1891 case '2': t = be_xpoint_watch_read; break;
1892 case '3': t = be_xpoint_watch_write; break;
1893 default: return packet_error;
1895 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1897 if (xpt->addr == addr && xpt->type == t)
1899 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1900 gdbctx->process->process_io, &gdbctx->context,
1901 t, xpt->addr, xpt->val, len))
1903 xpt->type = -1;
1904 return packet_ok;
1906 break;
1909 return packet_error;
1912 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1914 void* addr;
1915 unsigned len;
1916 struct gdb_ctx_Xpoint* xpt;
1917 enum be_xpoint_type t;
1919 /* FIXME: check packet_len */
1920 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1921 gdbctx->in_packet[1] != ',' ||
1922 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1923 return packet_error;
1924 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1925 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1926 addr, len, gdbctx->in_packet[0]);
1927 switch (gdbctx->in_packet[0])
1929 case '0': t = be_xpoint_break; len = 0; break;
1930 case '1': t = be_xpoint_watch_exec; break;
1931 case '2': t = be_xpoint_watch_read; break;
1932 case '3': t = be_xpoint_watch_write; break;
1933 default: return packet_error;
1935 /* because of packet command handling, this should be made idempotent */
1936 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1938 if (xpt->addr == addr && xpt->type == t)
1939 return packet_ok; /* nothing to do */
1941 /* really set the Xpoint */
1942 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1944 if (xpt->type == -1)
1946 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1947 gdbctx->process->process_io, &gdbctx->context,
1948 t, addr, &xpt->val, len))
1950 xpt->addr = addr;
1951 xpt->type = t;
1952 return packet_ok;
1954 fprintf(stderr, "cannot set xpoint\n");
1955 break;
1958 /* no more entries... eech */
1959 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1960 return packet_error;
1963 /* =============================================== *
1964 * P A C K E T I N F R A S T R U C T U R E *
1965 * =============================================== *
1968 struct packet_entry
1970 char key;
1971 enum packet_return (*handler)(struct gdb_context* gdbctx);
1974 static struct packet_entry packet_entries[] =
1976 /*{'!', packet_extended}, */
1977 {'?', packet_last_signal},
1978 {'c', packet_continue},
1979 {'C', packet_continue_signal},
1980 {'D', packet_detach},
1981 {'g', packet_read_registers},
1982 {'G', packet_write_registers},
1983 {'k', packet_kill},
1984 {'H', packet_thread},
1985 {'m', packet_read_memory},
1986 {'M', packet_write_memory},
1987 {'p', packet_read_register},
1988 {'P', packet_write_register},
1989 {'q', packet_query},
1990 /* {'Q', packet_set}, */
1991 /* {'R', packet,restart}, only in extended mode ! */
1992 {'s', packet_step},
1993 /*{'S', packet_step_signal}, hard(er) to implement */
1994 {'T', packet_thread_alive},
1995 {'v', packet_verbose},
1996 {'z', packet_remove_breakpoint},
1997 {'Z', packet_set_breakpoint},
2000 static BOOL extract_packets(struct gdb_context* gdbctx)
2002 char* end;
2003 int plen;
2004 unsigned char in_cksum, loc_cksum;
2005 char* ptr;
2006 enum packet_return ret = packet_error;
2007 int num_packet = 0;
2009 while ((ret & packet_last_f) == 0)
2011 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2012 fprintf(stderr, "In-buf: %*.*s\n",
2013 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2014 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2015 if (ptr == NULL) return FALSE;
2016 if (ptr != gdbctx->in_buf)
2018 int glen = ptr - gdbctx->in_buf; /* garbage len */
2019 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2020 fprintf(stderr, "Removing garbage: %*.*s\n",
2021 glen, glen, gdbctx->in_buf);
2022 gdbctx->in_len -= glen;
2023 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2025 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2026 if (end == NULL) return FALSE;
2027 /* no checksum yet */
2028 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2029 plen = end - gdbctx->in_buf - 1;
2030 hex_from(&in_cksum, end + 1, 1);
2031 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2032 if (loc_cksum == in_cksum)
2034 if (num_packet == 0) {
2035 int i;
2037 ret = packet_error;
2039 write(gdbctx->sock, "+", 1);
2040 assert(plen);
2042 /* FIXME: should use bsearch if packet_entries was sorted */
2043 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2045 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2047 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2049 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2050 fprintf(stderr, "Unknown packet request %*.*s\n",
2051 plen, plen, &gdbctx->in_buf[1]);
2053 else
2055 gdbctx->in_packet = gdbctx->in_buf + 2;
2056 gdbctx->in_packet_len = plen - 1;
2057 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2058 fprintf(stderr, "Packet: %c%*.*s\n",
2059 gdbctx->in_buf[1],
2060 gdbctx->in_packet_len, gdbctx->in_packet_len,
2061 gdbctx->in_packet);
2062 ret = (packet_entries[i].handler)(gdbctx);
2064 switch (ret & ~packet_last_f)
2066 case packet_error: packet_reply(gdbctx, "", 0); break;
2067 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2068 case packet_done: break;
2070 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2071 fprintf(stderr, "Reply-full: %*.*s\n",
2072 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2073 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2074 assert(i == gdbctx->out_len);
2075 /* if this fails, we'll have to use POLLOUT...
2077 gdbctx->out_len = 0;
2078 num_packet++;
2080 else
2082 /* FIXME: if we have in our input buffer more than one packet,
2083 * it's very likely that we took too long to answer to a given packet
2084 * and gdb is sending us again the same packet
2085 * We simply drop the second packet. This will lower the risk of error,
2086 * but there's still some race conditions here
2087 * A better fix (yet not perfect) would be to have two threads:
2088 * - one managing the packets for gdb
2089 * - the second one managing the commands...
2090 * This would allow us also the reply with the '+' character (Ack of
2091 * the command) way sooner than what we do now
2093 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2094 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2097 else
2099 write(gdbctx->sock, "+", 1);
2100 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2101 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2103 gdbctx->in_len -= plen + 4;
2104 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2106 return TRUE;
2109 static int fetch_data(struct gdb_context* gdbctx)
2111 int len, in_len = gdbctx->in_len;
2113 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2114 for (;;)
2116 #define STEP 128
2117 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2118 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2119 #undef STEP
2120 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2121 fprintf(stderr, "%d %d %*.*s\n",
2122 gdbctx->in_len, gdbctx->in_buf_alloc,
2123 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2124 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2125 if (len <= 0) break;
2126 gdbctx->in_len += len;
2127 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2128 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2130 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2131 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2132 return gdbctx->in_len - in_len;
2135 #define FLAG_NO_START 1
2136 #define FLAG_WITH_XTERM 2
2138 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2140 char buf[MAX_PATH];
2141 int fd;
2142 const char* gdb_path;
2143 FILE* f;
2145 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2146 strcpy(buf,"/tmp/winegdb.XXXXXX");
2147 fd = mkstemps(buf, 0);
2148 if (fd == -1) return FALSE;
2149 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2150 fprintf(f, "file %s\n", wine_path);
2151 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2152 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2153 fprintf(f, "set prompt Wine-gdb>\\ \n");
2154 /* gdb 5.1 seems to require it, won't hurt anyway */
2155 fprintf(f, "sharedlibrary\n");
2156 /* This is needed (but not a decent & final fix)
2157 * Without this, gdb would skip our inter-DLL relay code (because
2158 * we don't have any line number information for the relay code)
2159 * With this, we will stop on first instruction of the stub, and
2160 * reusing step, will get us through the relay stub at the actual
2161 * function we're looking at.
2163 fprintf(f, "set step-mode on\n");
2164 /* tell gdb to delete this file when done handling it... */
2165 fprintf(f, "shell rm -f \"%s\"\n", buf);
2166 fclose(f);
2167 if (flags & FLAG_WITH_XTERM)
2168 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2169 else
2170 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2171 assert(0); /* never reached */
2172 return TRUE;
2175 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2177 int sock;
2178 struct sockaddr_in s_addrs;
2179 unsigned int s_len = sizeof(s_addrs);
2180 struct pollfd pollfd;
2181 IMAGEHLP_MODULE64 imh_mod;
2183 /* step 1: create socket for gdb connection request */
2184 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2186 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2187 fprintf(stderr, "Can't create socket");
2188 return FALSE;
2191 if (listen(sock, 1) == -1 ||
2192 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2193 return FALSE;
2195 /* step 2: do the process internal creation */
2196 handle_debug_event(gdbctx, de);
2198 /* step3: get the wine loader name */
2199 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2201 /* step 4: fire up gdb (if requested) */
2202 if (flags & FLAG_NO_START)
2203 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2204 else
2205 switch (fork())
2207 case -1: /* error in parent... */
2208 fprintf(stderr, "Cannot create gdb\n");
2209 return FALSE;
2210 default: /* in parent... success */
2211 signal(SIGINT, SIG_IGN);
2212 break;
2213 case 0: /* in child... and alive */
2214 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2215 /* if we're here, exec failed, so report failure */
2216 return FALSE;
2219 /* step 5: wait for gdb to connect actually */
2220 pollfd.fd = sock;
2221 pollfd.events = POLLIN;
2222 pollfd.revents = 0;
2224 switch (poll(&pollfd, 1, -1))
2226 case 1:
2227 if (pollfd.revents & POLLIN)
2229 int dummy = 1;
2230 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2231 if (gdbctx->sock == -1)
2232 break;
2233 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2234 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2235 /* don't keep our small packets too long: send them ASAP back to GDB
2236 * without this, GDB really crawls
2238 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2240 break;
2241 case 0:
2242 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2243 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2244 return FALSE;
2245 case -1:
2246 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2247 fprintf(stderr, "Poll for cnx failed (error)\n");
2248 return FALSE;
2249 default:
2250 assert(0);
2253 close(sock);
2254 return TRUE;
2257 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2259 DEBUG_EVENT de;
2260 int i;
2262 gdbctx->sock = -1;
2263 gdbctx->in_buf = NULL;
2264 gdbctx->in_buf_alloc = 0;
2265 gdbctx->in_len = 0;
2266 gdbctx->out_buf = NULL;
2267 gdbctx->out_buf_alloc = 0;
2268 gdbctx->out_len = 0;
2269 gdbctx->out_curr_packet = -1;
2271 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2272 gdbctx->last_sig = 0;
2273 gdbctx->in_trap = FALSE;
2274 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2275 gdbctx->process = NULL;
2276 for (i = 0; i < NUM_XPOINT; i++)
2277 gdbctx->Xpoints[i].type = -1;
2278 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2279 gdbctx->wine_segs[i] = 0;
2281 /* wait for first trap */
2282 while (WaitForDebugEvent(&de, INFINITE))
2284 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2286 /* this should be the first event we get,
2287 * and the only one of this type */
2288 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2289 /* gdbctx->dwProcessId = pid; */
2290 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2291 assert(!gdbctx->in_trap);
2293 else
2295 handle_debug_event(gdbctx, &de);
2296 if (gdbctx->in_trap) break;
2298 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2300 return TRUE;
2303 static int gdb_remote(unsigned flags)
2305 struct pollfd pollfd;
2306 struct gdb_context gdbctx;
2307 BOOL doLoop;
2309 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2311 pollfd.fd = gdbctx.sock;
2312 pollfd.events = POLLIN;
2313 pollfd.revents = 0;
2315 switch (poll(&pollfd, 1, -1))
2317 case 1:
2318 /* got something */
2319 if (pollfd.revents & (POLLHUP | POLLERR))
2321 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2322 fprintf(stderr, "Gdb hung up\n");
2323 /* kill also debuggee process - questionnable - */
2324 detach_debuggee(&gdbctx, TRUE);
2325 doLoop = FALSE;
2326 break;
2328 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2330 if (extract_packets(&gdbctx)) doLoop = FALSE;
2332 break;
2333 case 0:
2334 /* timeout, should never happen (infinite timeout) */
2335 break;
2336 case -1:
2337 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2338 fprintf(stderr, "Poll failed\n");
2339 doLoop = FALSE;
2340 break;
2343 wait(NULL);
2344 return 0;
2346 #endif
2348 int gdb_main(int argc, char* argv[])
2350 #ifdef HAVE_POLL
2351 unsigned gdb_flags = 0;
2353 argc--; argv++;
2354 while (argc > 0 && argv[0][0] == '-')
2356 if (strcmp(argv[0], "--no-start") == 0)
2358 gdb_flags |= FLAG_NO_START;
2359 argc--; argv++;
2360 continue;
2362 if (strcmp(argv[0], "--with-xterm") == 0)
2364 gdb_flags |= FLAG_WITH_XTERM;
2365 argc--; argv++;
2366 continue;
2368 return -1;
2370 if (dbg_active_attach(argc, argv) == start_ok ||
2371 dbg_active_launch(argc, argv) == start_ok)
2372 return gdb_remote(gdb_flags);
2373 #else
2374 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2375 #endif
2376 return -1;