ddraw: Use wined3d_get_adapter_display_mode() in ddraw7_GetFourCCCodes().
[wine/multimedia.git] / programs / winedbg / gdbproxy.c
blob58b2202858078614acc5354f25105d5345272c89
1 /*
2 * A Win32 based proxy implementing the GBD remote protocol.
3 * This makes it possible to debug Wine (and any "emulated"
4 * program) under Linux using GDB.
6 * Copyright (c) Eric Pouech 2002-2004
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* Protocol specification can be found here:
24 * http://sources.redhat.com/gdb/onlinedocs/gdb/Maintenance-Commands.html
27 #include "config.h"
28 #include "wine/port.h"
30 #include <assert.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #ifdef HAVE_SYS_POLL_H
38 # include <sys/poll.h>
39 #endif
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
42 #endif
43 #ifdef HAVE_SYS_SOCKET_H
44 # include <sys/socket.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49 #ifdef HAVE_NETINET_TCP_H
50 # include <netinet/tcp.h>
51 #endif
52 #ifdef HAVE_UNISTD_H
53 # include <unistd.h>
54 #endif
56 /* if we don't have poll support on this system
57 * we won't provide gdb proxy support here...
59 #ifdef HAVE_POLL
61 #include "debugger.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "tlhelp32.h"
67 #define GDBPXY_TRC_LOWLEVEL 0x01
68 #define GDBPXY_TRC_PACKET 0x02
69 #define GDBPXY_TRC_COMMAND 0x04
70 #define GDBPXY_TRC_COMMAND_ERROR 0x08
71 #define GDBPXY_TRC_WIN32_EVENT 0x10
72 #define GDBPXY_TRC_WIN32_ERROR 0x20
73 #define GDBPXY_TRC_COMMAND_FIXME 0x80
75 struct gdb_ctx_Xpoint
77 enum be_xpoint_type type; /* -1 means free */
78 void* addr;
79 unsigned long val;
82 struct gdb_context
84 /* gdb information */
85 int sock;
86 /* incoming buffer */
87 char* in_buf;
88 int in_buf_alloc;
89 int in_len;
90 /* split into individual packet */
91 char* in_packet;
92 int in_packet_len;
93 /* outgoing buffer */
94 char* out_buf;
95 int out_buf_alloc;
96 int out_len;
97 int out_curr_packet;
98 /* generic GDB thread information */
99 struct dbg_thread* exec_thread; /* thread used in step & continue */
100 struct dbg_thread* other_thread; /* thread to be used in any other operation */
101 unsigned trace;
102 /* current Win32 trap env */
103 unsigned last_sig;
104 BOOL in_trap;
105 CONTEXT context;
106 /* Win32 information */
107 struct dbg_process* process;
108 #define NUM_XPOINT 32
109 struct gdb_ctx_Xpoint Xpoints[NUM_XPOINT];
110 /* Unix environment */
111 unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
114 static BOOL tgt_process_gdbproxy_read(HANDLE hProcess, const void* addr,
115 void* buffer, SIZE_T len, SIZE_T* rlen)
117 return ReadProcessMemory( hProcess, addr, buffer, len, rlen );
120 static BOOL tgt_process_gdbproxy_write(HANDLE hProcess, void* addr,
121 const void* buffer, SIZE_T len, SIZE_T* wlen)
123 return WriteProcessMemory( hProcess, addr, buffer, len, wlen );
126 static struct be_process_io be_process_gdbproxy_io =
128 NULL, /* we shouldn't use close_process() in gdbproxy */
129 tgt_process_gdbproxy_read,
130 tgt_process_gdbproxy_write
133 /* =============================================== *
134 * B A S I C M A N I P U L A T I O N S *
135 * =============================================== *
138 static inline int hex_from0(char ch)
140 if (ch >= '0' && ch <= '9') return ch - '0';
141 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
142 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
144 assert(0);
145 return 0;
148 static inline unsigned char hex_to0(int x)
150 assert(x >= 0 && x < 16);
151 return "0123456789abcdef"[x];
154 static int hex_to_int(const char* src, size_t len)
156 unsigned int returnval = 0;
157 while (len--)
159 returnval <<= 4;
160 returnval |= hex_from0(*src++);
162 return returnval;
165 static void hex_from(void* dst, const char* src, size_t len)
167 unsigned char *p = dst;
168 while (len--)
170 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
171 src += 2;
175 static void hex_to(char* dst, const void* src, size_t len)
177 const unsigned char *p = src;
178 while (len--)
180 *dst++ = hex_to0(*p >> 4);
181 *dst++ = hex_to0(*p & 0x0F);
182 p++;
186 static unsigned char checksum(const char* ptr, int len)
188 unsigned cksum = 0;
190 while (len-- > 0)
191 cksum += (unsigned char)*ptr++;
192 return cksum;
195 /* =============================================== *
196 * C P U H A N D L E R S *
197 * =============================================== *
200 /* This struct helps us to manage the different representations of a register:
201 * ctx_offset and ctx_length are the location and size in Win32 CONTEXT
202 * gdb_length is the length gdb expects on the wire
203 * As the two sizes could be different, we have to convert between the two
204 * (for example, on x86_64, Seg?s are 4 bytes on the wire and 2 in CONTEXT)
206 struct cpu_register
208 size_t ctx_offset;
209 size_t ctx_length;
210 size_t gdb_length;
213 #define REG(r,gs) {FIELD_OFFSET(CONTEXT, r), sizeof(((CONTEXT*)NULL)->r), gs}
215 #ifdef __i386__
216 static struct cpu_register cpu_register_map[] = {
217 REG(Eax, 4),
218 REG(Ecx, 4),
219 REG(Edx, 4),
220 REG(Ebx, 4),
221 REG(Esp, 4),
222 REG(Ebp, 4),
223 REG(Esi, 4),
224 REG(Edi, 4),
225 REG(Eip, 4),
226 REG(EFlags, 4),
227 REG(SegCs, 4),
228 REG(SegSs, 4),
229 REG(SegDs, 4),
230 REG(SegEs, 4),
231 REG(SegFs, 4),
232 REG(SegGs, 4),
234 #elif defined(__powerpc__)
235 static struct cpu_register cpu_register_map[] = {
236 REG(Gpr0, 4),
237 REG(Gpr1, 4),
238 REG(Gpr2, 4),
239 REG(Gpr3, 4),
240 REG(Gpr4, 4),
241 REG(Gpr5, 4),
242 REG(Gpr6, 4),
243 REG(Gpr7, 4),
244 REG(Gpr8, 4),
245 REG(Gpr9, 4),
246 REG(Gpr10, 4),
247 REG(Gpr11, 4),
248 REG(Gpr12, 4),
249 REG(Gpr13, 4),
250 REG(Gpr14, 4),
251 REG(Gpr15, 4),
252 REG(Gpr16, 4),
253 REG(Gpr17, 4),
254 REG(Gpr18, 4),
255 REG(Gpr19, 4),
256 REG(Gpr20, 4),
257 REG(Gpr21, 4),
258 REG(Gpr22, 4),
259 REG(Gpr23, 4),
260 REG(Gpr24, 4),
261 REG(Gpr25, 4),
262 REG(Gpr26, 4),
263 REG(Gpr27, 4),
264 REG(Gpr28, 4),
265 REG(Gpr29, 4),
266 REG(Gpr30, 4),
267 REG(Gpr31, 4),
268 REG(Fpr0, 4),
269 REG(Fpr1, 4),
270 REG(Fpr2, 4),
271 REG(Fpr3, 4),
272 REG(Fpr4, 4),
273 REG(Fpr5, 4),
274 REG(Fpr6, 4),
275 REG(Fpr7, 4),
276 REG(Fpr8, 4),
277 REG(Fpr9, 4),
278 REG(Fpr10, 4),
279 REG(Fpr11, 4),
280 REG(Fpr12, 4),
281 REG(Fpr13, 4),
282 REG(Fpr14, 4),
283 REG(Fpr15, 4),
284 REG(Fpr16, 4),
285 REG(Fpr17, 4),
286 REG(Fpr18, 4),
287 REG(Fpr19, 4),
288 REG(Fpr20, 4),
289 REG(Fpr21, 4),
290 REG(Fpr22, 4),
291 REG(Fpr23, 4),
292 REG(Fpr24, 4),
293 REG(Fpr25, 4),
294 REG(Fpr26, 4),
295 REG(Fpr27, 4),
296 REG(Fpr28, 4),
297 REG(Fpr29, 4),
298 REG(Fpr30, 4),
299 REG(Fpr31, 4),
301 REG(Iar, 4),
302 REG(Msr, 4),
303 REG(Cr, 4),
304 REG(Lr, 4),
305 REG(Ctr, 4),
306 REG(Xer, 4),
307 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
308 /* see gdb/nlm/ppc.c */
310 #elif defined(__x86_64__)
311 static struct cpu_register cpu_register_map[] = {
312 REG(Rax, 8),
313 REG(Rbx, 8),
314 REG(Rcx, 8),
315 REG(Rdx, 8),
316 REG(Rsi, 8),
317 REG(Rdi, 8),
318 REG(Rbp, 8),
319 REG(Rsp, 8),
320 REG(R8, 8),
321 REG(R9, 8),
322 REG(R10, 8),
323 REG(R11, 8),
324 REG(R12, 8),
325 REG(R13, 8),
326 REG(R14, 8),
327 REG(R15, 8),
328 REG(Rip, 8),
329 REG(EFlags, 4),
330 REG(SegCs, 4),
331 REG(SegSs, 4),
332 REG(SegDs, 4),
333 REG(SegEs, 4),
334 REG(SegFs, 4),
335 REG(SegGs, 4),
337 #elif defined(__sparc__)
338 static struct cpu_register cpu_register_map[] = {
339 REG(g0, 4),
340 REG(g1, 4),
341 REG(g2, 4),
342 REG(g3, 4),
343 REG(g4, 4),
344 REG(g5, 4),
345 REG(g6, 4),
346 REG(g7, 4),
347 REG(o0, 4),
348 REG(o1, 4),
349 REG(o2, 4),
350 REG(o3, 4),
351 REG(o4, 4),
352 REG(o5, 4),
353 REG(o6, 4),
354 REG(o7, 4),
355 REG(l0, 4),
356 REG(l1, 4),
357 REG(l2, 4),
358 REG(l3, 4),
359 REG(l4, 4),
360 REG(l5, 4),
361 REG(l6, 4),
362 REG(l7, 4),
363 REG(i0, 4),
364 REG(i1, 4),
365 REG(i2, 4),
366 REG(i3, 4),
367 REG(i4, 4),
368 REG(i5, 4),
369 REG(i6, 4),
370 REG(i7, 4),
372 #elif defined(__arm__)
373 static struct cpu_register cpu_register_map[] = {
374 REG(R0, 4),
375 REG(R1, 4),
376 REG(R2, 4),
377 REG(R3, 4),
378 REG(R4, 4),
379 REG(R5, 4),
380 REG(R6, 4),
381 REG(R7, 4),
382 REG(R8, 4),
383 REG(R9, 4),
384 REG(R10, 4),
385 REG(Fp, 4),
386 REG(Ip, 4),
387 REG(Sp, 4),
388 REG(Lr, 4),
389 REG(Pc, 4),
391 #else
392 # error Define the registers map for your CPU
393 #endif
394 #undef REG
396 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
398 static inline void* cpu_register_ptr(CONTEXT* ctx, unsigned idx)
400 assert(idx < cpu_num_regs);
401 return (char*)ctx + cpu_register_map[idx].ctx_offset;
404 static inline DWORD64 cpu_register(CONTEXT* ctx, unsigned idx)
406 switch (cpu_register_map[idx].ctx_length)
408 case 2: return *(WORD*)cpu_register_ptr(ctx, idx);
409 case 4: return *(DWORD*)cpu_register_ptr(ctx, idx);
410 case 8: return *(DWORD64*)cpu_register_ptr(ctx, idx);
411 default:
412 fprintf(stderr, "got unexpected size: %u\n", (unsigned)cpu_register_map[idx].ctx_length);
413 assert(0);
417 static inline void cpu_register_hex_from(CONTEXT* ctx, unsigned idx, const char** phex)
419 DWORD64 val = 0;
420 unsigned i;
421 BYTE b;
423 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
425 hex_from(&b, *phex, 1);
426 *phex += 2;
427 val += (DWORD64)b << (8 * i);
429 switch (cpu_register_map[idx].ctx_length)
431 case 2: *(WORD*)cpu_register_ptr(ctx, idx) = (WORD)val; break;
432 case 4: *(DWORD*)cpu_register_ptr(ctx, idx) = (DWORD)val; break;
433 case 8: *(DWORD64*)cpu_register_ptr(ctx, idx) = val; break;
434 default: assert(0);
438 /* =============================================== *
439 * W I N 3 2 D E B U G I N T E R F A C E *
440 * =============================================== *
443 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
445 ctx->ContextFlags = CONTEXT_CONTROL
446 | CONTEXT_INTEGER
447 #ifdef CONTEXT_SEGMENTS
448 | CONTEXT_SEGMENTS
449 #endif
450 #ifdef CONTEXT_DEBUG_REGISTERS
451 | CONTEXT_DEBUG_REGISTERS
452 #endif
454 if (!GetThreadContext(h, ctx))
456 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
457 fprintf(stderr, "Can't get thread's context\n");
458 return FALSE;
460 return TRUE;
463 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
465 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
466 BOOL ret = FALSE;
468 switch (rec->ExceptionCode)
470 case EXCEPTION_ACCESS_VIOLATION:
471 case EXCEPTION_PRIV_INSTRUCTION:
472 case EXCEPTION_STACK_OVERFLOW:
473 case EXCEPTION_GUARD_PAGE:
474 gdbctx->last_sig = SIGSEGV;
475 ret = TRUE;
476 break;
477 case EXCEPTION_DATATYPE_MISALIGNMENT:
478 gdbctx->last_sig = SIGBUS;
479 ret = TRUE;
480 break;
481 case EXCEPTION_SINGLE_STEP:
482 /* fall through */
483 case EXCEPTION_BREAKPOINT:
484 gdbctx->last_sig = SIGTRAP;
485 ret = TRUE;
486 break;
487 case EXCEPTION_FLT_DENORMAL_OPERAND:
488 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
489 case EXCEPTION_FLT_INEXACT_RESULT:
490 case EXCEPTION_FLT_INVALID_OPERATION:
491 case EXCEPTION_FLT_OVERFLOW:
492 case EXCEPTION_FLT_STACK_CHECK:
493 case EXCEPTION_FLT_UNDERFLOW:
494 gdbctx->last_sig = SIGFPE;
495 ret = TRUE;
496 break;
497 case EXCEPTION_INT_DIVIDE_BY_ZERO:
498 case EXCEPTION_INT_OVERFLOW:
499 gdbctx->last_sig = SIGFPE;
500 ret = TRUE;
501 break;
502 case EXCEPTION_ILLEGAL_INSTRUCTION:
503 gdbctx->last_sig = SIGILL;
504 ret = TRUE;
505 break;
506 case CONTROL_C_EXIT:
507 gdbctx->last_sig = SIGINT;
508 ret = TRUE;
509 break;
510 case STATUS_POSSIBLE_DEADLOCK:
511 gdbctx->last_sig = SIGALRM;
512 ret = TRUE;
513 /* FIXME: we could also add here a O packet with additional information */
514 break;
515 default:
516 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
517 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
518 gdbctx->last_sig = SIGABRT;
519 ret = TRUE;
520 break;
522 return ret;
525 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
527 union {
528 char bufferA[256];
529 WCHAR buffer[256];
530 } u;
532 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
534 switch (de->dwDebugEventCode)
536 case CREATE_PROCESS_DEBUG_EVENT:
537 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
538 de->u.CreateProcessInfo.hProcess);
539 if (!gdbctx->process) break;
540 memory_get_string_indirect(gdbctx->process,
541 de->u.CreateProcessInfo.lpImageName,
542 de->u.CreateProcessInfo.fUnicode,
543 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
544 dbg_set_process_name(gdbctx->process, u.buffer);
546 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
547 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
548 de->dwProcessId, de->dwThreadId,
549 dbg_W2A(u.buffer, -1),
550 de->u.CreateProcessInfo.lpImageName,
551 de->u.CreateProcessInfo.lpStartAddress,
552 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
553 de->u.CreateProcessInfo.nDebugInfoSize);
555 /* de->u.CreateProcessInfo.lpStartAddress; */
556 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
557 fprintf(stderr, "Couldn't initiate DbgHelp\n");
559 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
560 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
561 de->dwProcessId, de->dwThreadId,
562 de->u.CreateProcessInfo.lpStartAddress);
564 assert(dbg_curr_thread == NULL); /* shouldn't be there */
565 dbg_add_thread(gdbctx->process, de->dwThreadId,
566 de->u.CreateProcessInfo.hThread,
567 de->u.CreateProcessInfo.lpThreadLocalBase);
568 break;
570 case LOAD_DLL_DEBUG_EVENT:
571 assert(dbg_curr_thread);
572 memory_get_string_indirect(gdbctx->process,
573 de->u.LoadDll.lpImageName,
574 de->u.LoadDll.fUnicode,
575 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
576 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
577 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
578 de->dwProcessId, de->dwThreadId,
579 dbg_W2A(u.buffer, -1),
580 de->u.LoadDll.lpBaseOfDll,
581 de->u.LoadDll.dwDebugInfoFileOffset,
582 de->u.LoadDll.nDebugInfoSize);
583 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
584 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
585 break;
587 case UNLOAD_DLL_DEBUG_EVENT:
588 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
589 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
590 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
591 SymUnloadModule(gdbctx->process->handle,
592 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
593 break;
595 case EXCEPTION_DEBUG_EVENT:
596 assert(dbg_curr_thread);
597 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
598 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
599 de->dwProcessId, de->dwThreadId,
600 de->u.Exception.ExceptionRecord.ExceptionCode);
602 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
604 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
606 break;
608 case CREATE_THREAD_DEBUG_EVENT:
609 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
610 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
611 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
613 dbg_add_thread(gdbctx->process,
614 de->dwThreadId,
615 de->u.CreateThread.hThread,
616 de->u.CreateThread.lpThreadLocalBase);
617 break;
619 case EXIT_THREAD_DEBUG_EVENT:
620 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
621 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
622 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
624 assert(dbg_curr_thread);
625 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
626 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
627 dbg_del_thread(dbg_curr_thread);
628 break;
630 case EXIT_PROCESS_DEBUG_EVENT:
631 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
632 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
633 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
635 dbg_del_process(gdbctx->process);
636 gdbctx->process = NULL;
637 /* now signal gdb that we're done */
638 gdbctx->last_sig = SIGTERM;
639 gdbctx->in_trap = TRUE;
640 break;
642 case OUTPUT_DEBUG_STRING_EVENT:
643 assert(dbg_curr_thread);
644 memory_get_string(gdbctx->process,
645 de->u.DebugString.lpDebugStringData, TRUE,
646 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
647 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
648 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
649 de->dwProcessId, de->dwThreadId, u.bufferA);
650 break;
652 case RIP_EVENT:
653 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
654 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
655 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
656 de->u.RipInfo.dwType);
657 break;
659 default:
660 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
661 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
662 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
666 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
668 if (dbg_curr_thread)
670 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
671 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
672 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
673 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
674 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
675 fprintf(stderr, "Cannot continue on %04x (%x)\n",
676 dbg_curr_thread->tid, cont);
678 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
679 fprintf(stderr, "Cannot find last thread\n");
683 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
686 if (dbg_curr_thread)
688 if(dbg_curr_thread->tid == threadid){
689 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
690 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
691 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
692 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
693 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
694 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
695 fprintf(stderr, "Cannot continue on %04x (%x)\n",
696 dbg_curr_thread->tid, cont);
699 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
700 fprintf(stderr, "Cannot find last thread\n");
703 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
705 struct pollfd pollfd;
706 int ret;
707 char pkt;
709 pollfd.fd = gdbctx->sock;
710 pollfd.events = POLLIN;
711 pollfd.revents = 0;
713 if ((ret = poll(&pollfd, 1, 0)) == 1) {
714 ret = read(gdbctx->sock, &pkt, 1);
715 if (ret != 1) {
716 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
717 fprintf(stderr, "read failed\n");
719 return FALSE;
721 if (pkt != '\003') {
722 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
723 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
725 return FALSE;
727 return TRUE;
728 } else if (ret == -1) {
729 fprintf(stderr, "poll failed\n");
731 return FALSE;
734 static void wait_for_debuggee(struct gdb_context* gdbctx)
736 DEBUG_EVENT de;
738 gdbctx->in_trap = FALSE;
739 for (;;)
741 if (!WaitForDebugEvent(&de, 10))
743 if (GetLastError() == ERROR_SEM_TIMEOUT)
745 if (check_for_interrupt(gdbctx)) {
746 if (!DebugBreakProcess(gdbctx->process->handle)) {
747 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
748 fprintf(stderr, "Failed to break into debugee\n");
750 break;
752 WaitForDebugEvent(&de, INFINITE);
753 } else {
754 continue;
756 } else {
757 break;
760 handle_debug_event(gdbctx, &de);
761 assert(!gdbctx->process ||
762 gdbctx->process->pid == 0 ||
763 de.dwProcessId == gdbctx->process->pid);
764 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
765 if (gdbctx->in_trap) break;
766 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
770 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
772 be_cpu->single_step(&gdbctx->context, FALSE);
773 resume_debuggee(gdbctx, DBG_CONTINUE);
774 if (!kill)
775 DebugActiveProcessStop(gdbctx->process->pid);
776 dbg_del_process(gdbctx->process);
777 gdbctx->process = NULL;
780 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
782 DWORD status;
784 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
786 strcpy(buffer, "Unknown process");
787 return;
789 if (status == STILL_ACTIVE)
791 strcpy(buffer, "Running");
793 else
794 snprintf(buffer, len, "Terminated (%u)", status);
796 switch (GetPriorityClass(gdbctx->process->handle))
798 case 0: break;
799 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
800 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
801 #endif
802 #ifdef BELOW_NORMAL_PRIORITY_CLASS
803 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
804 #endif
805 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
806 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
807 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
808 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
810 strcat(buffer, "\n");
813 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
814 char* buffer, size_t len)
816 struct dbg_thread* thd;
817 DWORD status;
818 int prio;
820 /* FIXME: use the size of buffer */
821 thd = dbg_get_thread(gdbctx->process, tid);
822 if (thd == NULL)
824 strcpy(buffer, "No information");
825 return;
827 if (GetExitCodeThread(thd->handle, &status))
829 if (status == STILL_ACTIVE)
831 /* FIXME: this is a bit brutal... some nicer way shall be found */
832 switch (status = SuspendThread(thd->handle))
834 case -1: break;
835 case 0: strcpy(buffer, "Running"); break;
836 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
838 ResumeThread(thd->handle);
840 else
841 snprintf(buffer, len, "Terminated (exit code = %u)", status);
843 else
845 strcpy(buffer, "Unknown threadID");
847 switch (prio = GetThreadPriority(thd->handle))
849 case THREAD_PRIORITY_ERROR_RETURN: break;
850 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
851 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
852 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
853 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
854 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
855 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
856 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
857 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
859 assert(strlen(buffer) < len);
862 /* =============================================== *
863 * P A C K E T U T I L S *
864 * =============================================== *
867 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
868 packet_last_f = 0x80};
870 static char* packet_realloc(char* buf, int size)
872 if (!buf)
873 return HeapAlloc(GetProcessHeap(), 0, size);
874 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
878 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
880 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
882 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
883 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
887 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
889 packet_reply_grow(gdbctx, len * 2);
890 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
891 gdbctx->out_len += len * 2;
894 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
896 packet_reply_hex_to(gdbctx, src, strlen(src));
899 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
901 int i, shift;
903 shift = (len - 1) * 8;
904 packet_reply_grow(gdbctx, len * 2);
905 for (i = 0; i < len; i++, shift -= 8)
907 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
908 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
912 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
914 packet_reply_grow(gdbctx, len);
915 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
916 gdbctx->out_len += len;
919 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
921 packet_reply_add(gdbctx, str, strlen(str));
924 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
926 packet_reply_add(gdbctx, &ch, 1);
929 static void packet_reply_open(struct gdb_context* gdbctx)
931 assert(gdbctx->out_curr_packet == -1);
932 packet_reply_catc(gdbctx, '$');
933 gdbctx->out_curr_packet = gdbctx->out_len;
936 static void packet_reply_close(struct gdb_context* gdbctx)
938 unsigned char cksum;
939 int plen;
941 plen = gdbctx->out_len - gdbctx->out_curr_packet;
942 packet_reply_catc(gdbctx, '#');
943 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
944 packet_reply_hex_to(gdbctx, &cksum, 1);
945 if (gdbctx->trace & GDBPXY_TRC_PACKET)
946 fprintf(stderr, "Reply : %*.*s\n",
947 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
948 gdbctx->out_curr_packet = -1;
951 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
953 packet_reply_open(gdbctx);
955 if (len == -1) len = strlen(packet);
956 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
958 packet_reply_add(gdbctx, packet, len);
960 packet_reply_close(gdbctx);
962 return packet_done;
965 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
967 packet_reply_open(gdbctx);
969 packet_reply_add(gdbctx, "E", 1);
970 packet_reply_val(gdbctx, error, 1);
972 packet_reply_close(gdbctx);
974 return packet_done;
977 static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, unsigned idx)
979 DWORD64 val = cpu_register(&gdbctx->context, idx);
980 unsigned i;
982 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
984 BYTE b = val;
985 packet_reply_hex_to(gdbctx, &b, 1);
986 val >>= 8;
990 /* =============================================== *
991 * P A C K E T H A N D L E R S *
992 * =============================================== *
995 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
997 enum packet_return ret = packet_done;
999 packet_reply_open(gdbctx);
1001 if (gdbctx->process != NULL)
1003 unsigned char sig;
1004 unsigned i;
1006 packet_reply_catc(gdbctx, 'T');
1007 sig = gdbctx->last_sig;
1008 packet_reply_val(gdbctx, sig, 1);
1009 packet_reply_add(gdbctx, "thread:", 7);
1010 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
1011 packet_reply_catc(gdbctx, ';');
1013 for (i = 0; i < cpu_num_regs; i++)
1015 /* FIXME: this call will also grow the buffer...
1016 * unneeded, but not harmful
1018 packet_reply_val(gdbctx, i, 1);
1019 packet_reply_catc(gdbctx, ':');
1020 packet_reply_register_hex_to(gdbctx, i);
1021 packet_reply_catc(gdbctx, ';');
1024 else
1026 /* Try to put an exit code
1027 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1028 * just indicate the end of process and exit */
1029 packet_reply_add(gdbctx, "W00", 3);
1030 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1033 packet_reply_close(gdbctx);
1035 return ret;
1038 #if 0
1039 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1041 gdbctx->extended = 1;
1042 return packet_ok;
1044 #endif
1046 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1048 assert(gdbctx->in_packet_len == 0);
1049 return packet_reply_status(gdbctx);
1052 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1054 /* FIXME: add support for address in packet */
1055 assert(gdbctx->in_packet_len == 0);
1056 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1057 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1058 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1059 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1060 resume_debuggee(gdbctx, DBG_CONTINUE);
1061 wait_for_debuggee(gdbctx);
1062 return packet_reply_status(gdbctx);
1065 static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
1067 int i;
1068 int defaultAction = -1; /* magic non action */
1069 unsigned char sig;
1070 int actions =0;
1071 int actionIndex[20]; /* allow for up to 20 actions */
1072 int threadIndex[20];
1073 int threadCount = 0;
1074 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1075 unsigned int threadID = 0;
1076 struct dbg_thread* thd;
1078 /* OK we have vCont followed by..
1079 * ? for query
1080 * c for packet_continue
1081 * Csig for packet_continue_signal
1082 * s for step
1083 * Ssig for step signal
1084 * and then an optional thread ID at the end..
1085 * *******************************************/
1087 /* Query */
1088 if (gdbctx->in_packet[4] == '?')
1091 Reply:
1092 `vCont[;action]...'
1093 The vCont packet is supported. Each action is a supported command in the vCont packet.
1095 The vCont packet is not supported. (this didn't seem to be obeyed!)
1097 packet_reply_open(gdbctx);
1098 packet_reply_add(gdbctx, "vCont", 5);
1099 /* add all the supported actions to the reply (all of them for now) */
1100 packet_reply_add(gdbctx, ";c", 2);
1101 packet_reply_add(gdbctx, ";C", 2);
1102 packet_reply_add(gdbctx, ";s", 2);
1103 packet_reply_add(gdbctx, ";S", 2);
1104 packet_reply_close(gdbctx);
1105 return packet_done;
1108 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1109 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1110 now if only gdb talked XML.... */
1111 #if 0 /* handy for debugging */
1112 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1113 #endif
1115 /* go through the packet and identify where all the actions start at */
1116 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1118 if (gdbctx->in_packet[i] == ';')
1120 threadIndex[actions] = 0;
1121 actionIndex[actions++] = i;
1123 else if (gdbctx->in_packet[i] == ':')
1125 threadIndex[actions - 1] = i;
1129 /* now look up the default action */
1130 for (i = 0 ; i < actions; i++)
1132 if (threadIndex[i] == 0)
1134 if (defaultAction != -1)
1136 fprintf(stderr,"Too many default actions specified\n");
1137 return packet_error;
1139 defaultAction = i;
1143 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1145 /* go through all the threads and stick their ids in the to be done list. */
1146 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1148 threadIDs[threadCount++] = thd->tid;
1149 /* check to see if we have more threads than I counted on, and tell the user what to do
1150 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1151 if (threadCount == 100)
1153 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1154 break;
1158 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1159 * that remains is to apply the actions to the threads and the default action to any threads
1160 * left */
1161 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1162 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1163 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1164 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1166 /* deal with the threaded stuff first */
1167 for (i = 0; i < actions ; i++)
1169 if (threadIndex[i] != 0)
1171 int j, idLength = 0;
1172 if (i < actions - 1)
1174 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1176 else
1178 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1181 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1182 /* process the action */
1183 switch (gdbctx->in_packet[actionIndex[i] + 1])
1185 case 's': /* step */
1186 be_cpu->single_step(&gdbctx->context, TRUE);
1187 /* fall through*/
1188 case 'c': /* continue */
1189 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1190 break;
1191 case 'S': /* step Sig, */
1192 be_cpu->single_step(&gdbctx->context, TRUE);
1193 /* fall through */
1194 case 'C': /* continue sig */
1195 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1196 /* cannot change signals on the fly */
1197 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1198 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1199 if (sig != gdbctx->last_sig)
1200 return packet_error;
1201 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1202 break;
1204 for (j = 0 ; j < threadCount; j++)
1206 if (threadIDs[j] == threadID)
1208 threadIDs[j] = 0;
1209 break;
1213 } /* for i=0 ; i< actions */
1215 /* now we have manage the default action */
1216 if (defaultAction >= 0)
1218 for (i = 0 ; i< threadCount; i++)
1220 /* check to see if we've already done something to the thread*/
1221 if (threadIDs[i] != 0)
1223 /* if not apply the default action*/
1224 threadID = threadIDs[i];
1225 /* process the action (yes this is almost identical to the one above!) */
1226 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1228 case 's': /* step */
1229 be_cpu->single_step(&gdbctx->context, TRUE);
1230 /* fall through */
1231 case 'c': /* continue */
1232 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1233 break;
1234 case 'S':
1235 be_cpu->single_step(&gdbctx->context, TRUE);
1236 /* fall through */
1237 case 'C': /* continue sig */
1238 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1239 /* cannot change signals on the fly */
1240 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1241 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1242 if (sig != gdbctx->last_sig)
1243 return packet_error;
1244 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1245 break;
1249 } /* if(defaultAction >=0) */
1251 wait_for_debuggee(gdbctx);
1252 be_cpu->single_step(&gdbctx->context, FALSE);
1253 return packet_reply_status(gdbctx);
1256 struct verbose_defail
1258 const char* name;
1259 unsigned len;
1260 enum packet_return (*handler)(struct gdb_context*);
1261 } verbose_details[] =
1263 /* {"Attach", 6}, */
1264 {"Cont", 4, packet_verbose_cont},
1265 /* {"File", 4},
1266 {"FlashErase", 10},
1267 {"FlashWrite", 10},
1268 {"FlashDone", 9},
1269 {"Kill", 4},
1270 {"Run", 3},
1271 {"Stopped", 7},*/
1274 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1276 unsigned i;
1277 unsigned klen;
1279 for (klen = 0; ; klen++)
1281 if (klen == gdbctx->in_packet_len ||
1282 gdbctx->in_packet[klen] == ';' ||
1283 gdbctx->in_packet[klen] == ':' ||
1284 gdbctx->in_packet[klen] == '?')
1286 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1287 fprintf(stderr, "trying to process a verbose packet %*.*s\n",
1288 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1289 for (i = 0; i < sizeof(verbose_details)/sizeof(verbose_details[0]); i++)
1291 if (klen == verbose_details[i].len &&
1292 !memcmp(gdbctx->in_packet, verbose_details[i].name, verbose_details[i].len))
1294 return verbose_details[i].handler(gdbctx);
1297 /* no matching handler found, abort */
1298 break;
1302 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1303 fprintf(stderr, "No support for verbose packet %*.*s\n",
1304 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1305 return packet_error;
1308 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1310 unsigned char sig;
1312 /* FIXME: add support for address in packet */
1313 assert(gdbctx->in_packet_len == 2);
1314 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1315 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1316 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1317 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1318 hex_from(&sig, gdbctx->in_packet, 1);
1319 /* cannot change signals on the fly */
1320 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1321 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1322 if (sig != gdbctx->last_sig)
1323 return packet_error;
1324 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1325 wait_for_debuggee(gdbctx);
1326 return packet_reply_status(gdbctx);
1329 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1331 detach_debuggee(gdbctx, FALSE);
1332 return packet_ok | packet_last_f;
1335 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1337 int i;
1338 CONTEXT ctx;
1339 CONTEXT* pctx = &gdbctx->context;
1341 assert(gdbctx->in_trap);
1343 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1345 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1346 return packet_error;
1349 packet_reply_open(gdbctx);
1350 for (i = 0; i < cpu_num_regs; i++)
1352 packet_reply_register_hex_to(gdbctx, i);
1354 packet_reply_close(gdbctx);
1355 return packet_done;
1358 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1360 unsigned i;
1361 CONTEXT ctx;
1362 CONTEXT* pctx = &gdbctx->context;
1363 const char* ptr;
1365 assert(gdbctx->in_trap);
1366 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1368 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1369 return packet_error;
1371 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1373 ptr = gdbctx->in_packet;
1374 for (i = 0; i < cpu_num_regs; i++)
1376 cpu_register_hex_from(pctx, i, &ptr);
1378 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1380 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1381 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1382 return packet_error;
1384 return packet_ok;
1387 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1389 detach_debuggee(gdbctx, TRUE);
1390 #if 0
1391 if (!gdbctx->extended)
1392 /* dunno whether GDB cares or not */
1393 #endif
1394 wait(NULL);
1395 exit(0);
1396 /* assume we can't really answer something here */
1397 /* return packet_done; */
1400 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1402 char* end;
1403 unsigned thread;
1405 switch (gdbctx->in_packet[0])
1407 case 'c':
1408 case 'g':
1409 if (gdbctx->in_packet[1] == '-')
1410 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1411 else
1412 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1413 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1415 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1416 fprintf(stderr, "Cannot get threadid %*.*s\n",
1417 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1418 gdbctx->in_packet + 1);
1419 return packet_error;
1421 if (gdbctx->in_packet[0] == 'c')
1422 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1423 else
1424 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1425 return packet_ok;
1426 default:
1427 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1428 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1429 return packet_error;
1433 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1435 char *addr;
1436 unsigned int len, blk_len, nread;
1437 char buffer[32];
1438 SIZE_T r = 0;
1440 assert(gdbctx->in_trap);
1441 /* FIXME:check in_packet_len for reading %p,%x */
1442 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1443 if (len <= 0) return packet_error;
1444 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1445 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1446 for (nread = 0; nread < len; nread += r, addr += r)
1448 blk_len = min(sizeof(buffer), len - nread);
1449 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1450 r == 0)
1452 /* fail at first address, return error */
1453 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1454 /* something has already been read, return partial information */
1455 break;
1457 if (nread == 0) packet_reply_open(gdbctx);
1458 packet_reply_hex_to(gdbctx, buffer, r);
1460 packet_reply_close(gdbctx);
1461 return packet_done;
1464 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1466 char* addr;
1467 unsigned int len, blk_len;
1468 char* ptr;
1469 char buffer[32];
1470 SIZE_T w;
1472 assert(gdbctx->in_trap);
1473 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1474 if (ptr == NULL)
1476 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1477 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1478 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1479 return packet_error;
1481 *ptr++ = '\0';
1483 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1485 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1486 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1487 return packet_error;
1489 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1491 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1492 fprintf(stderr, "Wrong sizes %u <> %u\n",
1493 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1494 return packet_error;
1496 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1497 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1498 while (len > 0)
1500 blk_len = min(sizeof(buffer), len);
1501 hex_from(buffer, ptr, blk_len);
1502 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1503 w != blk_len)
1504 break;
1505 addr += blk_len;
1506 len -= blk_len;
1507 ptr += blk_len;
1509 return packet_ok; /* FIXME: error while writing ? */
1512 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1514 unsigned reg;
1515 CONTEXT ctx;
1516 CONTEXT* pctx = &gdbctx->context;
1518 assert(gdbctx->in_trap);
1519 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1520 if (reg >= cpu_num_regs)
1522 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1523 fprintf(stderr, "Register out of bounds %x\n", reg);
1524 return packet_error;
1526 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1528 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1529 return packet_error;
1531 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1532 fprintf(stderr, "Read register %x => %08x%08x\n", reg,
1533 (unsigned)(cpu_register(pctx, reg) >> 32), (unsigned)cpu_register(pctx, reg));
1534 packet_reply_open(gdbctx);
1535 packet_reply_register_hex_to(gdbctx, reg);
1536 packet_reply_close(gdbctx);
1537 return packet_done;
1540 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1542 unsigned reg;
1543 char* ptr;
1544 CONTEXT ctx;
1545 CONTEXT* pctx = &gdbctx->context;
1547 assert(gdbctx->in_trap);
1549 reg = strtoul(gdbctx->in_packet, &ptr, 16);
1550 if (ptr == NULL || reg > cpu_num_regs || *ptr++ != '=')
1552 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1553 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1554 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1555 * it wouldn't matter too much, and it fakes our support for all regs
1557 return (ptr == NULL) ? packet_error : packet_ok;
1559 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1561 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1562 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
1565 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1567 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1568 return packet_error;
1571 cpu_register_hex_from(pctx, reg, (const char**)&ptr);
1572 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1574 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1575 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1576 return packet_error;
1579 return packet_ok;
1582 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1584 char buffer[128];
1585 char clsName[128];
1586 char wndName[128];
1587 HWND child;
1589 do {
1590 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1591 strcpy(clsName, "-- Unknown --");
1592 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1593 strcpy(wndName, "-- Empty --");
1595 packet_reply_open(gdbctx);
1596 packet_reply_catc(gdbctx, 'O');
1597 snprintf(buffer, sizeof(buffer),
1598 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1599 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1600 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1601 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1602 wndName);
1603 packet_reply_hex_to_str(gdbctx, buffer);
1604 packet_reply_close(gdbctx);
1606 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1607 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1608 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1611 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1613 char buffer[128];
1615 /* we do the output in several 'O' packets, with the last one being just OK for
1616 * marking the end of the output */
1617 packet_reply_open(gdbctx);
1618 packet_reply_catc(gdbctx, 'O');
1619 snprintf(buffer, sizeof(buffer),
1620 "%-16.16s %-17.17s %-8.8s %s\n",
1621 "hwnd", "Class Name", " Style", " WndProc Text");
1622 packet_reply_hex_to_str(gdbctx, buffer);
1623 packet_reply_close(gdbctx);
1625 /* FIXME: could also add a pmt to this command in str... */
1626 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1627 packet_reply(gdbctx, "OK", 2);
1630 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1632 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1633 char buffer[128];
1634 char deco;
1635 PROCESSENTRY32 entry;
1636 BOOL ok;
1638 if (snap == INVALID_HANDLE_VALUE)
1639 return;
1641 entry.dwSize = sizeof(entry);
1642 ok = Process32First(snap, &entry);
1644 /* we do the output in several 'O' packets, with the last one being just OK for
1645 * marking the end of the output */
1647 packet_reply_open(gdbctx);
1648 packet_reply_catc(gdbctx, 'O');
1649 snprintf(buffer, sizeof(buffer),
1650 " %-8.8s %-8.8s %-8.8s %s\n",
1651 "pid", "threads", "parent", "executable");
1652 packet_reply_hex_to_str(gdbctx, buffer);
1653 packet_reply_close(gdbctx);
1655 while (ok)
1657 deco = ' ';
1658 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1659 packet_reply_open(gdbctx);
1660 packet_reply_catc(gdbctx, 'O');
1661 snprintf(buffer, sizeof(buffer),
1662 "%c%08x %-8d %08x '%s'\n",
1663 deco, entry.th32ProcessID, entry.cntThreads,
1664 entry.th32ParentProcessID, entry.szExeFile);
1665 packet_reply_hex_to_str(gdbctx, buffer);
1666 packet_reply_close(gdbctx);
1667 ok = Process32Next(snap, &entry);
1669 CloseHandle(snap);
1670 packet_reply(gdbctx, "OK", 2);
1673 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1675 MEMORY_BASIC_INFORMATION mbi;
1676 char* addr = 0;
1677 const char* state;
1678 const char* type;
1679 char prot[3+1];
1680 char buffer[128];
1682 /* we do the output in several 'O' packets, with the last one being just OK for
1683 * marking the end of the output */
1684 packet_reply_open(gdbctx);
1685 packet_reply_catc(gdbctx, 'O');
1686 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1687 packet_reply_close(gdbctx);
1689 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1691 switch (mbi.State)
1693 case MEM_COMMIT: state = "commit "; break;
1694 case MEM_FREE: state = "free "; break;
1695 case MEM_RESERVE: state = "reserve"; break;
1696 default: state = "??? "; break;
1698 if (mbi.State != MEM_FREE)
1700 switch (mbi.Type)
1702 case MEM_IMAGE: type = "image "; break;
1703 case MEM_MAPPED: type = "mapped "; break;
1704 case MEM_PRIVATE: type = "private"; break;
1705 case 0: type = " "; break;
1706 default: type = "??? "; break;
1708 memset(prot, ' ' , sizeof(prot)-1);
1709 prot[sizeof(prot)-1] = '\0';
1710 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1711 prot[0] = 'R';
1712 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1713 prot[1] = 'W';
1714 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1715 prot[1] = 'C';
1716 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1717 prot[2] = 'X';
1719 else
1721 type = "";
1722 prot[0] = '\0';
1724 packet_reply_open(gdbctx);
1725 snprintf(buffer, sizeof(buffer), "%0*lx %0*lx %s %s %s\n",
1726 (unsigned)sizeof(void*), (DWORD_PTR)addr,
1727 (unsigned)sizeof(void*), mbi.RegionSize, state, type, prot);
1728 packet_reply_catc(gdbctx, 'O');
1729 packet_reply_hex_to_str(gdbctx, buffer);
1730 packet_reply_close(gdbctx);
1732 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1733 break;
1734 addr += mbi.RegionSize;
1736 packet_reply(gdbctx, "OK", 2);
1739 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1740 int len, const char* str)
1742 char buffer[128];
1744 if (len == 0)
1746 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1748 else if (len >= 2 && str[0] == '=')
1750 unsigned val = atoi(&str[1]);
1751 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1752 gdbctx->trace = val;
1754 else
1756 /* FIXME: ugly but can use error packet here */
1757 packet_reply_cat(gdbctx, "E00");
1758 return;
1760 packet_reply_open(gdbctx);
1761 packet_reply_hex_to_str(gdbctx, buffer);
1762 packet_reply_close(gdbctx);
1765 struct query_detail
1767 int with_arg;
1768 const char* name;
1769 size_t len;
1770 void (*handler)(struct gdb_context*, int, const char*);
1771 } query_details[] =
1773 {0, "wnd", 3, packet_query_monitor_wnd},
1774 {0, "window", 6, packet_query_monitor_wnd},
1775 {0, "proc", 4, packet_query_monitor_process},
1776 {0, "process", 7, packet_query_monitor_process},
1777 {0, "mem", 3, packet_query_monitor_mem},
1778 {1, "trace", 5, packet_query_monitor_trace},
1779 {0, NULL, 0, NULL},
1782 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1783 const char* hxcmd, size_t len)
1785 char buffer[128];
1786 struct query_detail* qd;
1788 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1789 len /= 2;
1790 hex_from(buffer, hxcmd, len);
1792 for (qd = &query_details[0]; qd->name != NULL; qd++)
1794 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1795 if (!qd->with_arg && len != qd->len) continue;
1797 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1798 return packet_done;
1800 return packet_reply_error(gdbctx, EINVAL);
1803 static enum packet_return packet_query(struct gdb_context* gdbctx)
1805 switch (gdbctx->in_packet[0])
1807 case 'f':
1808 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1810 struct dbg_thread* thd;
1812 packet_reply_open(gdbctx);
1813 packet_reply_add(gdbctx, "m", 1);
1814 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1816 packet_reply_val(gdbctx, thd->tid, 4);
1817 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1818 packet_reply_add(gdbctx, ",", 1);
1820 packet_reply_close(gdbctx);
1821 return packet_done;
1823 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1825 char result[128];
1827 packet_reply_open(gdbctx);
1828 packet_reply_catc(gdbctx, 'O');
1829 get_process_info(gdbctx, result, sizeof(result));
1830 packet_reply_hex_to_str(gdbctx, result);
1831 packet_reply_close(gdbctx);
1832 return packet_done;
1834 break;
1835 case 's':
1836 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1838 packet_reply(gdbctx, "l", 1);
1839 return packet_done;
1841 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1843 packet_reply(gdbctx, "l", 1);
1844 return packet_done;
1846 break;
1847 case 'A':
1848 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
1850 char buf[2];
1852 buf[0] = '1';
1853 buf[1] = 0;
1854 return packet_reply(gdbctx, buf, -1);
1856 break;
1857 case 'C':
1858 if (gdbctx->in_packet_len == 1)
1860 struct dbg_thread* thd;
1861 /* FIXME: doc says 16 bit val ??? */
1862 /* grab first created thread, aka last in list */
1863 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1864 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1865 packet_reply_open(gdbctx);
1866 packet_reply_add(gdbctx, "QC", 2);
1867 packet_reply_val(gdbctx, thd->tid, 4);
1868 packet_reply_close(gdbctx);
1869 return packet_done;
1871 break;
1872 case 'O':
1873 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1875 char buf[64];
1877 snprintf(buf, sizeof(buf),
1878 "Text=%08lx;Data=%08lx;Bss=%08lx",
1879 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1880 gdbctx->wine_segs[2]);
1881 return packet_reply(gdbctx, buf, -1);
1883 break;
1884 case 'R':
1885 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1887 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1888 gdbctx->in_packet_len - 5);
1890 break;
1891 case 'S':
1892 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1893 return packet_ok;
1894 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1896 /* no features supported */
1897 packet_reply_open(gdbctx);
1898 packet_reply_close(gdbctx);
1899 return packet_done;
1901 break;
1902 case 'T':
1903 if (gdbctx->in_packet_len > 15 &&
1904 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1905 gdbctx->in_packet[15] == ',')
1907 unsigned tid;
1908 char* end;
1909 char result[128];
1911 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1912 if (end == NULL) break;
1913 get_thread_info(gdbctx, tid, result, sizeof(result));
1914 packet_reply_open(gdbctx);
1915 packet_reply_hex_to_str(gdbctx, result);
1916 packet_reply_close(gdbctx);
1917 return packet_done;
1919 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
1921 /* Tracepoints not supported */
1922 packet_reply_open(gdbctx);
1923 packet_reply_close(gdbctx);
1924 return packet_done;
1926 break;
1928 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1929 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1930 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1931 return packet_error;
1934 static enum packet_return packet_step(struct gdb_context* gdbctx)
1936 /* FIXME: add support for address in packet */
1937 assert(gdbctx->in_packet_len == 0);
1938 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1939 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1940 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1941 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1942 be_cpu->single_step(&gdbctx->context, TRUE);
1943 resume_debuggee(gdbctx, DBG_CONTINUE);
1944 wait_for_debuggee(gdbctx);
1945 be_cpu->single_step(&gdbctx->context, FALSE);
1946 return packet_reply_status(gdbctx);
1949 #if 0
1950 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1952 unsigned char sig;
1954 /* FIXME: add support for address in packet */
1955 assert(gdbctx->in_packet_len == 2);
1956 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1957 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1958 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1959 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1960 hex_from(&sig, gdbctx->in_packet, 1);
1961 /* cannot change signals on the fly */
1962 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1963 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1964 if (sig != gdbctx->last_sig)
1965 return packet_error;
1966 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1967 wait_for_debuggee(gdbctx);
1968 return packet_reply_status(gdbctx);
1970 #endif
1972 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1974 char* end;
1975 unsigned tid;
1977 tid = strtol(gdbctx->in_packet, &end, 16);
1978 if (tid == -1 || tid == 0)
1979 return packet_reply_error(gdbctx, EINVAL);
1980 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1981 return packet_ok;
1982 return packet_reply_error(gdbctx, ESRCH);
1985 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1987 void* addr;
1988 unsigned len;
1989 struct gdb_ctx_Xpoint* xpt;
1990 enum be_xpoint_type t;
1992 /* FIXME: check packet_len */
1993 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1994 gdbctx->in_packet[1] != ',' ||
1995 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1996 return packet_error;
1997 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1998 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1999 addr, len, gdbctx->in_packet[0]);
2000 switch (gdbctx->in_packet[0])
2002 case '0': t = be_xpoint_break; len = 0; break;
2003 case '1': t = be_xpoint_watch_exec; break;
2004 case '2': t = be_xpoint_watch_read; break;
2005 case '3': t = be_xpoint_watch_write; break;
2006 default: return packet_error;
2008 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2010 if (xpt->addr == addr && xpt->type == t)
2012 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
2013 gdbctx->process->process_io, &gdbctx->context,
2014 t, xpt->addr, xpt->val, len))
2016 xpt->type = -1;
2017 return packet_ok;
2019 break;
2022 return packet_error;
2025 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
2027 void* addr;
2028 unsigned len;
2029 struct gdb_ctx_Xpoint* xpt;
2030 enum be_xpoint_type t;
2032 /* FIXME: check packet_len */
2033 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2034 gdbctx->in_packet[1] != ',' ||
2035 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2036 return packet_error;
2037 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2038 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
2039 addr, len, gdbctx->in_packet[0]);
2040 switch (gdbctx->in_packet[0])
2042 case '0': t = be_xpoint_break; len = 0; break;
2043 case '1': t = be_xpoint_watch_exec; break;
2044 case '2': t = be_xpoint_watch_read; break;
2045 case '3': t = be_xpoint_watch_write; break;
2046 default: return packet_error;
2048 /* because of packet command handling, this should be made idempotent */
2049 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2051 if (xpt->addr == addr && xpt->type == t)
2052 return packet_ok; /* nothing to do */
2054 /* really set the Xpoint */
2055 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2057 if (xpt->type == -1)
2059 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2060 gdbctx->process->process_io, &gdbctx->context,
2061 t, addr, &xpt->val, len))
2063 xpt->addr = addr;
2064 xpt->type = t;
2065 return packet_ok;
2067 fprintf(stderr, "cannot set xpoint\n");
2068 break;
2071 /* no more entries... eech */
2072 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2073 return packet_error;
2076 /* =============================================== *
2077 * P A C K E T I N F R A S T R U C T U R E *
2078 * =============================================== *
2081 struct packet_entry
2083 char key;
2084 enum packet_return (*handler)(struct gdb_context* gdbctx);
2087 static struct packet_entry packet_entries[] =
2089 /*{'!', packet_extended}, */
2090 {'?', packet_last_signal},
2091 {'c', packet_continue},
2092 {'C', packet_continue_signal},
2093 {'D', packet_detach},
2094 {'g', packet_read_registers},
2095 {'G', packet_write_registers},
2096 {'k', packet_kill},
2097 {'H', packet_thread},
2098 {'m', packet_read_memory},
2099 {'M', packet_write_memory},
2100 {'p', packet_read_register},
2101 {'P', packet_write_register},
2102 {'q', packet_query},
2103 /* {'Q', packet_set}, */
2104 /* {'R', packet,restart}, only in extended mode ! */
2105 {'s', packet_step},
2106 /*{'S', packet_step_signal}, hard(er) to implement */
2107 {'T', packet_thread_alive},
2108 {'v', packet_verbose},
2109 {'z', packet_remove_breakpoint},
2110 {'Z', packet_set_breakpoint},
2113 static BOOL extract_packets(struct gdb_context* gdbctx)
2115 char* end;
2116 int plen;
2117 unsigned char in_cksum, loc_cksum;
2118 char* ptr;
2119 enum packet_return ret = packet_error;
2120 int num_packet = 0;
2122 while ((ret & packet_last_f) == 0)
2124 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2125 fprintf(stderr, "In-buf: %*.*s\n",
2126 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2127 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2128 if (ptr == NULL) return FALSE;
2129 if (ptr != gdbctx->in_buf)
2131 int glen = ptr - gdbctx->in_buf; /* garbage len */
2132 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2133 fprintf(stderr, "Removing garbage: %*.*s\n",
2134 glen, glen, gdbctx->in_buf);
2135 gdbctx->in_len -= glen;
2136 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2138 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2139 if (end == NULL) return FALSE;
2140 /* no checksum yet */
2141 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2142 plen = end - gdbctx->in_buf - 1;
2143 hex_from(&in_cksum, end + 1, 1);
2144 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2145 if (loc_cksum == in_cksum)
2147 if (num_packet == 0) {
2148 int i;
2150 ret = packet_error;
2152 write(gdbctx->sock, "+", 1);
2153 assert(plen);
2155 /* FIXME: should use bsearch if packet_entries was sorted */
2156 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2158 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2160 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2162 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2163 fprintf(stderr, "Unknown packet request %*.*s\n",
2164 plen, plen, &gdbctx->in_buf[1]);
2166 else
2168 gdbctx->in_packet = gdbctx->in_buf + 2;
2169 gdbctx->in_packet_len = plen - 1;
2170 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2171 fprintf(stderr, "Packet: %c%*.*s\n",
2172 gdbctx->in_buf[1],
2173 gdbctx->in_packet_len, gdbctx->in_packet_len,
2174 gdbctx->in_packet);
2175 ret = (packet_entries[i].handler)(gdbctx);
2177 switch (ret & ~packet_last_f)
2179 case packet_error: packet_reply(gdbctx, "", 0); break;
2180 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2181 case packet_done: break;
2183 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2184 fprintf(stderr, "Reply-full: %*.*s\n",
2185 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2186 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2187 assert(i == gdbctx->out_len);
2188 /* if this fails, we'll have to use POLLOUT...
2190 gdbctx->out_len = 0;
2191 num_packet++;
2193 else
2195 /* FIXME: If we have more than one packet in our input buffer,
2196 * it's very likely that we took too long to answer to a given packet
2197 * and gdb is sending us the same packet again.
2198 * So we simply drop the second packet. This will lower the risk of error,
2199 * but there's still some race conditions here.
2200 * A better fix (yet not perfect) would be to have two threads:
2201 * - one managing the packets for gdb
2202 * - the second one managing the commands...
2203 * This would allow us to send the reply with the '+' character (Ack of
2204 * the command) way sooner than we do now.
2206 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2207 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2210 else
2212 write(gdbctx->sock, "+", 1);
2213 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2214 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2216 gdbctx->in_len -= plen + 4;
2217 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2219 return TRUE;
2222 static int fetch_data(struct gdb_context* gdbctx)
2224 int len, in_len = gdbctx->in_len;
2226 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2227 for (;;)
2229 #define STEP 128
2230 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2231 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2232 #undef STEP
2233 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2234 fprintf(stderr, "%d %d %*.*s\n",
2235 gdbctx->in_len, gdbctx->in_buf_alloc,
2236 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2237 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2238 if (len <= 0) break;
2239 gdbctx->in_len += len;
2240 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2241 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2243 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2244 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2245 return gdbctx->in_len - in_len;
2248 #define FLAG_NO_START 1
2249 #define FLAG_WITH_XTERM 2
2251 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2253 char buf[MAX_PATH];
2254 int fd;
2255 const char* gdb_path;
2256 FILE* f;
2258 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2259 strcpy(buf,"/tmp/winegdb.XXXXXX");
2260 fd = mkstemps(buf, 0);
2261 if (fd == -1) return FALSE;
2262 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2263 fprintf(f, "file %s\n", wine_path);
2264 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2265 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2266 fprintf(f, "set prompt Wine-gdb>\\ \n");
2267 /* gdb 5.1 seems to require it, won't hurt anyway */
2268 fprintf(f, "sharedlibrary\n");
2269 /* This is needed (but not a decent & final fix)
2270 * Without this, gdb would skip our inter-DLL relay code (because
2271 * we don't have any line number information for the relay code)
2272 * With this, we will stop on first instruction of the stub, and
2273 * reusing step, will get us through the relay stub at the actual
2274 * function we're looking at.
2276 fprintf(f, "set step-mode on\n");
2277 /* tell gdb to delete this file when done handling it... */
2278 fprintf(f, "shell rm -f \"%s\"\n", buf);
2279 fclose(f);
2280 if (flags & FLAG_WITH_XTERM)
2281 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2282 else
2283 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2284 assert(0); /* never reached */
2285 return TRUE;
2288 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2290 int sock;
2291 struct sockaddr_in s_addrs;
2292 unsigned int s_len = sizeof(s_addrs);
2293 struct pollfd pollfd;
2294 IMAGEHLP_MODULE64 imh_mod;
2296 /* step 1: create socket for gdb connection request */
2297 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2299 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2300 fprintf(stderr, "Can't create socket");
2301 return FALSE;
2304 if (listen(sock, 1) == -1 ||
2305 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2306 return FALSE;
2308 /* step 2: do the process internal creation */
2309 handle_debug_event(gdbctx, de);
2311 /* step3: get the wine loader name */
2312 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2314 /* step 4: fire up gdb (if requested) */
2315 if (flags & FLAG_NO_START)
2316 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2317 else
2318 switch (fork())
2320 case -1: /* error in parent... */
2321 fprintf(stderr, "Cannot create gdb\n");
2322 return FALSE;
2323 default: /* in parent... success */
2324 signal(SIGINT, SIG_IGN);
2325 break;
2326 case 0: /* in child... and alive */
2327 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2328 /* if we're here, exec failed, so report failure */
2329 return FALSE;
2332 /* step 5: wait for gdb to connect actually */
2333 pollfd.fd = sock;
2334 pollfd.events = POLLIN;
2335 pollfd.revents = 0;
2337 switch (poll(&pollfd, 1, -1))
2339 case 1:
2340 if (pollfd.revents & POLLIN)
2342 int dummy = 1;
2343 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2344 if (gdbctx->sock == -1)
2345 break;
2346 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2347 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2348 /* don't keep our small packets too long: send them ASAP back to GDB
2349 * without this, GDB really crawls
2351 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2353 break;
2354 case 0:
2355 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2356 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2357 return FALSE;
2358 case -1:
2359 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2360 fprintf(stderr, "Poll for cnx failed (error)\n");
2361 return FALSE;
2362 default:
2363 assert(0);
2366 close(sock);
2367 return TRUE;
2370 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2372 DEBUG_EVENT de;
2373 int i;
2375 gdbctx->sock = -1;
2376 gdbctx->in_buf = NULL;
2377 gdbctx->in_buf_alloc = 0;
2378 gdbctx->in_len = 0;
2379 gdbctx->out_buf = NULL;
2380 gdbctx->out_buf_alloc = 0;
2381 gdbctx->out_len = 0;
2382 gdbctx->out_curr_packet = -1;
2384 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2385 gdbctx->last_sig = 0;
2386 gdbctx->in_trap = FALSE;
2387 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2388 gdbctx->process = NULL;
2389 for (i = 0; i < NUM_XPOINT; i++)
2390 gdbctx->Xpoints[i].type = -1;
2391 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2392 gdbctx->wine_segs[i] = 0;
2394 /* wait for first trap */
2395 while (WaitForDebugEvent(&de, INFINITE))
2397 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2399 /* this should be the first event we get,
2400 * and the only one of this type */
2401 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2402 /* gdbctx->dwProcessId = pid; */
2403 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2404 assert(!gdbctx->in_trap);
2406 else
2408 handle_debug_event(gdbctx, &de);
2409 if (gdbctx->in_trap) break;
2411 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2413 return TRUE;
2416 static int gdb_remote(unsigned flags)
2418 struct pollfd pollfd;
2419 struct gdb_context gdbctx;
2420 BOOL doLoop;
2422 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2424 pollfd.fd = gdbctx.sock;
2425 pollfd.events = POLLIN;
2426 pollfd.revents = 0;
2428 switch (poll(&pollfd, 1, -1))
2430 case 1:
2431 /* got something */
2432 if (pollfd.revents & (POLLHUP | POLLERR))
2434 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2435 fprintf(stderr, "Gdb hung up\n");
2436 /* kill also debuggee process - questionnable - */
2437 detach_debuggee(&gdbctx, TRUE);
2438 doLoop = FALSE;
2439 break;
2441 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2443 if (extract_packets(&gdbctx)) doLoop = FALSE;
2445 break;
2446 case 0:
2447 /* timeout, should never happen (infinite timeout) */
2448 break;
2449 case -1:
2450 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2451 fprintf(stderr, "Poll failed\n");
2452 doLoop = FALSE;
2453 break;
2456 wait(NULL);
2457 return 0;
2459 #endif
2461 int gdb_main(int argc, char* argv[])
2463 #ifdef HAVE_POLL
2464 unsigned gdb_flags = 0;
2466 argc--; argv++;
2467 while (argc > 0 && argv[0][0] == '-')
2469 if (strcmp(argv[0], "--no-start") == 0)
2471 gdb_flags |= FLAG_NO_START;
2472 argc--; argv++;
2473 continue;
2475 if (strcmp(argv[0], "--with-xterm") == 0)
2477 gdb_flags |= FLAG_WITH_XTERM;
2478 argc--; argv++;
2479 continue;
2481 return -1;
2483 if (dbg_active_attach(argc, argv) == start_ok ||
2484 dbg_active_launch(argc, argv) == start_ok)
2485 return gdb_remote(gdb_flags);
2486 #else
2487 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2488 #endif
2489 return -1;