winedbg: Add PState to cpu_register_map for ARM64.
[wine.git] / programs / winedbg / gdbproxy.c
blobbbd3898ae534b3125f75f56d6f9e368f294b3e23
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 #elif defined(__aarch64__)
392 static struct cpu_register cpu_register_map[] = {
393 REG(X0, 8),
394 REG(X1, 8),
395 REG(X2, 8),
396 REG(X3, 8),
397 REG(X4, 8),
398 REG(X5, 8),
399 REG(X6, 8),
400 REG(X7, 8),
401 REG(X8, 8),
402 REG(X9, 8),
403 REG(X10, 8),
404 REG(X11, 8),
405 REG(X12, 8),
406 REG(X13, 8),
407 REG(X14, 8),
408 REG(X15, 8),
409 REG(X16, 8),
410 REG(X17, 8),
411 REG(X18, 8),
412 REG(X19, 8),
413 REG(X20, 8),
414 REG(X21, 8),
415 REG(X22, 8),
416 REG(X23, 8),
417 REG(X24, 8),
418 REG(X25, 8),
419 REG(X26, 8),
420 REG(X27, 8),
421 REG(X28, 8),
422 REG(X29, 8),
423 REG(X30, 8),
424 REG(Sp, 8),
425 REG(Pc, 8),
426 REG(PState, 8),
428 #else
429 # error Define the registers map for your CPU
430 #endif
431 #undef REG
433 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
435 static inline void* cpu_register_ptr(CONTEXT* ctx, unsigned idx)
437 assert(idx < cpu_num_regs);
438 return (char*)ctx + cpu_register_map[idx].ctx_offset;
441 static inline DWORD64 cpu_register(CONTEXT* ctx, unsigned idx)
443 switch (cpu_register_map[idx].ctx_length)
445 case 2: return *(WORD*)cpu_register_ptr(ctx, idx);
446 case 4: return *(DWORD*)cpu_register_ptr(ctx, idx);
447 case 8: return *(DWORD64*)cpu_register_ptr(ctx, idx);
448 default:
449 fprintf(stderr, "got unexpected size: %u\n", (unsigned)cpu_register_map[idx].ctx_length);
450 assert(0);
454 static inline void cpu_register_hex_from(CONTEXT* ctx, unsigned idx, const char** phex)
456 DWORD64 val = 0;
457 unsigned i;
458 BYTE b;
460 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
462 hex_from(&b, *phex, 1);
463 *phex += 2;
464 val += (DWORD64)b << (8 * i);
466 switch (cpu_register_map[idx].ctx_length)
468 case 2: *(WORD*)cpu_register_ptr(ctx, idx) = (WORD)val; break;
469 case 4: *(DWORD*)cpu_register_ptr(ctx, idx) = (DWORD)val; break;
470 case 8: *(DWORD64*)cpu_register_ptr(ctx, idx) = val; break;
471 default: assert(0);
475 /* =============================================== *
476 * W I N 3 2 D E B U G I N T E R F A C E *
477 * =============================================== *
480 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
482 ctx->ContextFlags = CONTEXT_CONTROL
483 | CONTEXT_INTEGER
484 #ifdef CONTEXT_SEGMENTS
485 | CONTEXT_SEGMENTS
486 #endif
487 #ifdef CONTEXT_DEBUG_REGISTERS
488 | CONTEXT_DEBUG_REGISTERS
489 #endif
491 if (!GetThreadContext(h, ctx))
493 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
494 fprintf(stderr, "Can't get thread's context\n");
495 return FALSE;
497 return TRUE;
500 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
502 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
503 BOOL ret = FALSE;
505 switch (rec->ExceptionCode)
507 case EXCEPTION_ACCESS_VIOLATION:
508 case EXCEPTION_PRIV_INSTRUCTION:
509 case EXCEPTION_STACK_OVERFLOW:
510 case EXCEPTION_GUARD_PAGE:
511 gdbctx->last_sig = SIGSEGV;
512 ret = TRUE;
513 break;
514 case EXCEPTION_DATATYPE_MISALIGNMENT:
515 gdbctx->last_sig = SIGBUS;
516 ret = TRUE;
517 break;
518 case EXCEPTION_SINGLE_STEP:
519 /* fall through */
520 case EXCEPTION_BREAKPOINT:
521 gdbctx->last_sig = SIGTRAP;
522 ret = TRUE;
523 break;
524 case EXCEPTION_FLT_DENORMAL_OPERAND:
525 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
526 case EXCEPTION_FLT_INEXACT_RESULT:
527 case EXCEPTION_FLT_INVALID_OPERATION:
528 case EXCEPTION_FLT_OVERFLOW:
529 case EXCEPTION_FLT_STACK_CHECK:
530 case EXCEPTION_FLT_UNDERFLOW:
531 gdbctx->last_sig = SIGFPE;
532 ret = TRUE;
533 break;
534 case EXCEPTION_INT_DIVIDE_BY_ZERO:
535 case EXCEPTION_INT_OVERFLOW:
536 gdbctx->last_sig = SIGFPE;
537 ret = TRUE;
538 break;
539 case EXCEPTION_ILLEGAL_INSTRUCTION:
540 gdbctx->last_sig = SIGILL;
541 ret = TRUE;
542 break;
543 case CONTROL_C_EXIT:
544 gdbctx->last_sig = SIGINT;
545 ret = TRUE;
546 break;
547 case STATUS_POSSIBLE_DEADLOCK:
548 gdbctx->last_sig = SIGALRM;
549 ret = TRUE;
550 /* FIXME: we could also add here a O packet with additional information */
551 break;
552 default:
553 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
554 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
555 gdbctx->last_sig = SIGABRT;
556 ret = TRUE;
557 break;
559 return ret;
562 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
564 union {
565 char bufferA[256];
566 WCHAR buffer[256];
567 } u;
569 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
571 switch (de->dwDebugEventCode)
573 case CREATE_PROCESS_DEBUG_EVENT:
574 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
575 de->u.CreateProcessInfo.hProcess);
576 if (!gdbctx->process) break;
577 memory_get_string_indirect(gdbctx->process,
578 de->u.CreateProcessInfo.lpImageName,
579 de->u.CreateProcessInfo.fUnicode,
580 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
581 dbg_set_process_name(gdbctx->process, u.buffer);
583 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
584 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
585 de->dwProcessId, de->dwThreadId,
586 dbg_W2A(u.buffer, -1),
587 de->u.CreateProcessInfo.lpImageName,
588 de->u.CreateProcessInfo.lpStartAddress,
589 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
590 de->u.CreateProcessInfo.nDebugInfoSize);
592 /* de->u.CreateProcessInfo.lpStartAddress; */
593 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
594 fprintf(stderr, "Couldn't initiate DbgHelp\n");
596 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
597 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
598 de->dwProcessId, de->dwThreadId,
599 de->u.CreateProcessInfo.lpStartAddress);
601 assert(dbg_curr_thread == NULL); /* shouldn't be there */
602 dbg_add_thread(gdbctx->process, de->dwThreadId,
603 de->u.CreateProcessInfo.hThread,
604 de->u.CreateProcessInfo.lpThreadLocalBase);
605 break;
607 case LOAD_DLL_DEBUG_EVENT:
608 assert(dbg_curr_thread);
609 memory_get_string_indirect(gdbctx->process,
610 de->u.LoadDll.lpImageName,
611 de->u.LoadDll.fUnicode,
612 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
613 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
614 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
615 de->dwProcessId, de->dwThreadId,
616 dbg_W2A(u.buffer, -1),
617 de->u.LoadDll.lpBaseOfDll,
618 de->u.LoadDll.dwDebugInfoFileOffset,
619 de->u.LoadDll.nDebugInfoSize);
620 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
621 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
622 break;
624 case UNLOAD_DLL_DEBUG_EVENT:
625 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
626 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
627 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
628 SymUnloadModule(gdbctx->process->handle,
629 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
630 break;
632 case EXCEPTION_DEBUG_EVENT:
633 assert(dbg_curr_thread);
634 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
635 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
636 de->dwProcessId, de->dwThreadId,
637 de->u.Exception.ExceptionRecord.ExceptionCode);
639 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
641 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
643 break;
645 case CREATE_THREAD_DEBUG_EVENT:
646 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
647 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
648 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
650 dbg_add_thread(gdbctx->process,
651 de->dwThreadId,
652 de->u.CreateThread.hThread,
653 de->u.CreateThread.lpThreadLocalBase);
654 break;
656 case EXIT_THREAD_DEBUG_EVENT:
657 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
658 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
659 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
661 assert(dbg_curr_thread);
662 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
663 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
664 dbg_del_thread(dbg_curr_thread);
665 break;
667 case EXIT_PROCESS_DEBUG_EVENT:
668 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
669 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
670 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
672 dbg_del_process(gdbctx->process);
673 gdbctx->process = NULL;
674 /* now signal gdb that we're done */
675 gdbctx->last_sig = SIGTERM;
676 gdbctx->in_trap = TRUE;
677 break;
679 case OUTPUT_DEBUG_STRING_EVENT:
680 assert(dbg_curr_thread);
681 memory_get_string(gdbctx->process,
682 de->u.DebugString.lpDebugStringData, TRUE,
683 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
684 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
685 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
686 de->dwProcessId, de->dwThreadId, u.bufferA);
687 break;
689 case RIP_EVENT:
690 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
691 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
692 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
693 de->u.RipInfo.dwType);
694 break;
696 default:
697 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
698 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
699 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
703 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
705 if (dbg_curr_thread)
707 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
708 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
709 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
710 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
711 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
712 fprintf(stderr, "Cannot continue on %04x (%x)\n",
713 dbg_curr_thread->tid, cont);
715 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
716 fprintf(stderr, "Cannot find last thread\n");
720 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
723 if (dbg_curr_thread)
725 if(dbg_curr_thread->tid == threadid){
726 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
727 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
728 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
729 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
730 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
731 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
732 fprintf(stderr, "Cannot continue on %04x (%x)\n",
733 dbg_curr_thread->tid, cont);
736 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
737 fprintf(stderr, "Cannot find last thread\n");
740 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
742 struct pollfd pollfd;
743 int ret;
744 char pkt;
746 pollfd.fd = gdbctx->sock;
747 pollfd.events = POLLIN;
748 pollfd.revents = 0;
750 if ((ret = poll(&pollfd, 1, 0)) == 1) {
751 ret = read(gdbctx->sock, &pkt, 1);
752 if (ret != 1) {
753 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
754 fprintf(stderr, "read failed\n");
756 return FALSE;
758 if (pkt != '\003') {
759 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
760 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
762 return FALSE;
764 return TRUE;
765 } else if (ret == -1) {
766 fprintf(stderr, "poll failed\n");
768 return FALSE;
771 static void wait_for_debuggee(struct gdb_context* gdbctx)
773 DEBUG_EVENT de;
775 gdbctx->in_trap = FALSE;
776 for (;;)
778 if (!WaitForDebugEvent(&de, 10))
780 if (GetLastError() == ERROR_SEM_TIMEOUT)
782 if (check_for_interrupt(gdbctx)) {
783 if (!DebugBreakProcess(gdbctx->process->handle)) {
784 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
785 fprintf(stderr, "Failed to break into debugee\n");
787 break;
789 WaitForDebugEvent(&de, INFINITE);
790 } else {
791 continue;
793 } else {
794 break;
797 handle_debug_event(gdbctx, &de);
798 assert(!gdbctx->process ||
799 gdbctx->process->pid == 0 ||
800 de.dwProcessId == gdbctx->process->pid);
801 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
802 if (gdbctx->in_trap) break;
803 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
807 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
809 be_cpu->single_step(&gdbctx->context, FALSE);
810 resume_debuggee(gdbctx, DBG_CONTINUE);
811 if (!kill)
812 DebugActiveProcessStop(gdbctx->process->pid);
813 dbg_del_process(gdbctx->process);
814 gdbctx->process = NULL;
817 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
819 DWORD status;
821 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
823 strcpy(buffer, "Unknown process");
824 return;
826 if (status == STILL_ACTIVE)
828 strcpy(buffer, "Running");
830 else
831 snprintf(buffer, len, "Terminated (%u)", status);
833 switch (GetPriorityClass(gdbctx->process->handle))
835 case 0: break;
836 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
837 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
838 #endif
839 #ifdef BELOW_NORMAL_PRIORITY_CLASS
840 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
841 #endif
842 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
843 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
844 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
845 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
847 strcat(buffer, "\n");
850 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
851 char* buffer, size_t len)
853 struct dbg_thread* thd;
854 DWORD status;
855 int prio;
857 /* FIXME: use the size of buffer */
858 thd = dbg_get_thread(gdbctx->process, tid);
859 if (thd == NULL)
861 strcpy(buffer, "No information");
862 return;
864 if (GetExitCodeThread(thd->handle, &status))
866 if (status == STILL_ACTIVE)
868 /* FIXME: this is a bit brutal... some nicer way shall be found */
869 switch (status = SuspendThread(thd->handle))
871 case -1: break;
872 case 0: strcpy(buffer, "Running"); break;
873 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
875 ResumeThread(thd->handle);
877 else
878 snprintf(buffer, len, "Terminated (exit code = %u)", status);
880 else
882 strcpy(buffer, "Unknown threadID");
884 switch (prio = GetThreadPriority(thd->handle))
886 case THREAD_PRIORITY_ERROR_RETURN: break;
887 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
888 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
889 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
890 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
891 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
892 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
893 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
894 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
896 assert(strlen(buffer) < len);
899 /* =============================================== *
900 * P A C K E T U T I L S *
901 * =============================================== *
904 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
905 packet_last_f = 0x80};
907 static char* packet_realloc(char* buf, int size)
909 if (!buf)
910 return HeapAlloc(GetProcessHeap(), 0, size);
911 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
915 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
917 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
919 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
920 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
924 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
926 packet_reply_grow(gdbctx, len * 2);
927 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
928 gdbctx->out_len += len * 2;
931 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
933 packet_reply_hex_to(gdbctx, src, strlen(src));
936 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
938 int i, shift;
940 shift = (len - 1) * 8;
941 packet_reply_grow(gdbctx, len * 2);
942 for (i = 0; i < len; i++, shift -= 8)
944 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
945 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
949 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
951 packet_reply_grow(gdbctx, len);
952 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
953 gdbctx->out_len += len;
956 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
958 packet_reply_add(gdbctx, str, strlen(str));
961 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
963 packet_reply_add(gdbctx, &ch, 1);
966 static void packet_reply_open(struct gdb_context* gdbctx)
968 assert(gdbctx->out_curr_packet == -1);
969 packet_reply_catc(gdbctx, '$');
970 gdbctx->out_curr_packet = gdbctx->out_len;
973 static void packet_reply_close(struct gdb_context* gdbctx)
975 unsigned char cksum;
976 int plen;
978 plen = gdbctx->out_len - gdbctx->out_curr_packet;
979 packet_reply_catc(gdbctx, '#');
980 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
981 packet_reply_hex_to(gdbctx, &cksum, 1);
982 if (gdbctx->trace & GDBPXY_TRC_PACKET)
983 fprintf(stderr, "Reply : %*.*s\n",
984 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
985 gdbctx->out_curr_packet = -1;
988 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
990 packet_reply_open(gdbctx);
992 if (len == -1) len = strlen(packet);
993 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
995 packet_reply_add(gdbctx, packet, len);
997 packet_reply_close(gdbctx);
999 return packet_done;
1002 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
1004 packet_reply_open(gdbctx);
1006 packet_reply_add(gdbctx, "E", 1);
1007 packet_reply_val(gdbctx, error, 1);
1009 packet_reply_close(gdbctx);
1011 return packet_done;
1014 static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, unsigned idx)
1016 DWORD64 val = cpu_register(&gdbctx->context, idx);
1017 unsigned i;
1019 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
1021 BYTE b = val;
1022 packet_reply_hex_to(gdbctx, &b, 1);
1023 val >>= 8;
1027 /* =============================================== *
1028 * P A C K E T H A N D L E R S *
1029 * =============================================== *
1032 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
1034 enum packet_return ret = packet_done;
1036 packet_reply_open(gdbctx);
1038 if (gdbctx->process != NULL)
1040 unsigned char sig;
1041 unsigned i;
1043 packet_reply_catc(gdbctx, 'T');
1044 sig = gdbctx->last_sig;
1045 packet_reply_val(gdbctx, sig, 1);
1046 packet_reply_add(gdbctx, "thread:", 7);
1047 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
1048 packet_reply_catc(gdbctx, ';');
1050 for (i = 0; i < cpu_num_regs; i++)
1052 /* FIXME: this call will also grow the buffer...
1053 * unneeded, but not harmful
1055 packet_reply_val(gdbctx, i, 1);
1056 packet_reply_catc(gdbctx, ':');
1057 packet_reply_register_hex_to(gdbctx, i);
1058 packet_reply_catc(gdbctx, ';');
1061 else
1063 /* Try to put an exit code
1064 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1065 * just indicate the end of process and exit */
1066 packet_reply_add(gdbctx, "W00", 3);
1067 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1070 packet_reply_close(gdbctx);
1072 return ret;
1075 #if 0
1076 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1078 gdbctx->extended = 1;
1079 return packet_ok;
1081 #endif
1083 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1085 assert(gdbctx->in_packet_len == 0);
1086 return packet_reply_status(gdbctx);
1089 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1091 /* FIXME: add support for address in packet */
1092 assert(gdbctx->in_packet_len == 0);
1093 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1094 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1095 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1096 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1097 resume_debuggee(gdbctx, DBG_CONTINUE);
1098 wait_for_debuggee(gdbctx);
1099 return packet_reply_status(gdbctx);
1102 static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
1104 int i;
1105 int defaultAction = -1; /* magic non action */
1106 unsigned char sig;
1107 int actions =0;
1108 int actionIndex[20]; /* allow for up to 20 actions */
1109 int threadIndex[20];
1110 int threadCount = 0;
1111 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1112 unsigned int threadID = 0;
1113 struct dbg_thread* thd;
1115 /* OK we have vCont followed by..
1116 * ? for query
1117 * c for packet_continue
1118 * Csig for packet_continue_signal
1119 * s for step
1120 * Ssig for step signal
1121 * and then an optional thread ID at the end..
1122 * *******************************************/
1124 /* Query */
1125 if (gdbctx->in_packet[4] == '?')
1128 Reply:
1129 `vCont[;action]...'
1130 The vCont packet is supported. Each action is a supported command in the vCont packet.
1132 The vCont packet is not supported. (this didn't seem to be obeyed!)
1134 packet_reply_open(gdbctx);
1135 packet_reply_add(gdbctx, "vCont", 5);
1136 /* add all the supported actions to the reply (all of them for now) */
1137 packet_reply_add(gdbctx, ";c", 2);
1138 packet_reply_add(gdbctx, ";C", 2);
1139 packet_reply_add(gdbctx, ";s", 2);
1140 packet_reply_add(gdbctx, ";S", 2);
1141 packet_reply_close(gdbctx);
1142 return packet_done;
1145 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1146 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1147 now if only gdb talked XML.... */
1148 #if 0 /* handy for debugging */
1149 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1150 #endif
1152 /* go through the packet and identify where all the actions start at */
1153 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1155 if (gdbctx->in_packet[i] == ';')
1157 threadIndex[actions] = 0;
1158 actionIndex[actions++] = i;
1160 else if (gdbctx->in_packet[i] == ':')
1162 threadIndex[actions - 1] = i;
1166 /* now look up the default action */
1167 for (i = 0 ; i < actions; i++)
1169 if (threadIndex[i] == 0)
1171 if (defaultAction != -1)
1173 fprintf(stderr,"Too many default actions specified\n");
1174 return packet_error;
1176 defaultAction = i;
1180 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1182 /* go through all the threads and stick their ids in the to be done list. */
1183 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1185 threadIDs[threadCount++] = thd->tid;
1186 /* check to see if we have more threads than I counted on, and tell the user what to do
1187 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1188 if (threadCount == 100)
1190 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1191 break;
1195 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1196 * that remains is to apply the actions to the threads and the default action to any threads
1197 * left */
1198 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1199 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1200 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1201 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1203 /* deal with the threaded stuff first */
1204 for (i = 0; i < actions ; i++)
1206 if (threadIndex[i] != 0)
1208 int j, idLength = 0;
1209 if (i < actions - 1)
1211 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1213 else
1215 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1218 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1219 /* process the action */
1220 switch (gdbctx->in_packet[actionIndex[i] + 1])
1222 case 's': /* step */
1223 be_cpu->single_step(&gdbctx->context, TRUE);
1224 /* fall through*/
1225 case 'c': /* continue */
1226 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1227 break;
1228 case 'S': /* step Sig, */
1229 be_cpu->single_step(&gdbctx->context, TRUE);
1230 /* fall through */
1231 case 'C': /* continue sig */
1232 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1233 /* cannot change signals on the fly */
1234 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1235 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1236 if (sig != gdbctx->last_sig)
1237 return packet_error;
1238 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1239 break;
1241 for (j = 0 ; j < threadCount; j++)
1243 if (threadIDs[j] == threadID)
1245 threadIDs[j] = 0;
1246 break;
1250 } /* for i=0 ; i< actions */
1252 /* now we have manage the default action */
1253 if (defaultAction >= 0)
1255 for (i = 0 ; i< threadCount; i++)
1257 /* check to see if we've already done something to the thread*/
1258 if (threadIDs[i] != 0)
1260 /* if not apply the default action*/
1261 threadID = threadIDs[i];
1262 /* process the action (yes this is almost identical to the one above!) */
1263 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1265 case 's': /* step */
1266 be_cpu->single_step(&gdbctx->context, TRUE);
1267 /* fall through */
1268 case 'c': /* continue */
1269 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1270 break;
1271 case 'S':
1272 be_cpu->single_step(&gdbctx->context, TRUE);
1273 /* fall through */
1274 case 'C': /* continue sig */
1275 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1276 /* cannot change signals on the fly */
1277 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1278 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1279 if (sig != gdbctx->last_sig)
1280 return packet_error;
1281 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1282 break;
1286 } /* if(defaultAction >=0) */
1288 wait_for_debuggee(gdbctx);
1289 be_cpu->single_step(&gdbctx->context, FALSE);
1290 return packet_reply_status(gdbctx);
1293 struct verbose_defail
1295 const char* name;
1296 unsigned len;
1297 enum packet_return (*handler)(struct gdb_context*);
1298 } verbose_details[] =
1300 /* {"Attach", 6}, */
1301 {"Cont", 4, packet_verbose_cont},
1302 /* {"File", 4},
1303 {"FlashErase", 10},
1304 {"FlashWrite", 10},
1305 {"FlashDone", 9},
1306 {"Kill", 4},
1307 {"Run", 3},
1308 {"Stopped", 7},*/
1311 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1313 unsigned i;
1314 unsigned klen;
1316 for (klen = 0; ; klen++)
1318 if (klen == gdbctx->in_packet_len ||
1319 gdbctx->in_packet[klen] == ';' ||
1320 gdbctx->in_packet[klen] == ':' ||
1321 gdbctx->in_packet[klen] == '?')
1323 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1324 fprintf(stderr, "trying to process a verbose packet %*.*s\n",
1325 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1326 for (i = 0; i < sizeof(verbose_details)/sizeof(verbose_details[0]); i++)
1328 if (klen == verbose_details[i].len &&
1329 !memcmp(gdbctx->in_packet, verbose_details[i].name, verbose_details[i].len))
1331 return verbose_details[i].handler(gdbctx);
1334 /* no matching handler found, abort */
1335 break;
1339 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1340 fprintf(stderr, "No support for verbose packet %*.*s\n",
1341 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1342 return packet_error;
1345 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1347 unsigned char sig;
1349 /* FIXME: add support for address in packet */
1350 assert(gdbctx->in_packet_len == 2);
1351 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1352 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1353 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1354 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1355 hex_from(&sig, gdbctx->in_packet, 1);
1356 /* cannot change signals on the fly */
1357 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1358 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1359 if (sig != gdbctx->last_sig)
1360 return packet_error;
1361 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1362 wait_for_debuggee(gdbctx);
1363 return packet_reply_status(gdbctx);
1366 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1368 detach_debuggee(gdbctx, FALSE);
1369 return packet_ok | packet_last_f;
1372 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1374 int i;
1375 CONTEXT ctx;
1376 CONTEXT* pctx = &gdbctx->context;
1378 assert(gdbctx->in_trap);
1380 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1382 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1383 return packet_error;
1386 packet_reply_open(gdbctx);
1387 for (i = 0; i < cpu_num_regs; i++)
1389 packet_reply_register_hex_to(gdbctx, i);
1391 packet_reply_close(gdbctx);
1392 return packet_done;
1395 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1397 unsigned i;
1398 CONTEXT ctx;
1399 CONTEXT* pctx = &gdbctx->context;
1400 const char* ptr;
1402 assert(gdbctx->in_trap);
1403 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1405 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1406 return packet_error;
1408 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1410 ptr = gdbctx->in_packet;
1411 for (i = 0; i < cpu_num_regs; i++)
1413 cpu_register_hex_from(pctx, i, &ptr);
1415 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1417 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1418 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1419 return packet_error;
1421 return packet_ok;
1424 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1426 detach_debuggee(gdbctx, TRUE);
1427 #if 0
1428 if (!gdbctx->extended)
1429 /* dunno whether GDB cares or not */
1430 #endif
1431 wait(NULL);
1432 exit(0);
1433 /* assume we can't really answer something here */
1434 /* return packet_done; */
1437 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1439 char* end;
1440 unsigned thread;
1442 switch (gdbctx->in_packet[0])
1444 case 'c':
1445 case 'g':
1446 if (gdbctx->in_packet[1] == '-')
1447 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1448 else
1449 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1450 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1452 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1453 fprintf(stderr, "Cannot get threadid %*.*s\n",
1454 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1455 gdbctx->in_packet + 1);
1456 return packet_error;
1458 if (gdbctx->in_packet[0] == 'c')
1459 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1460 else
1461 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1462 return packet_ok;
1463 default:
1464 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1465 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1466 return packet_error;
1470 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1472 char *addr;
1473 unsigned int len, blk_len, nread;
1474 char buffer[32];
1475 SIZE_T r = 0;
1477 assert(gdbctx->in_trap);
1478 /* FIXME:check in_packet_len for reading %p,%x */
1479 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1480 if (len <= 0) return packet_error;
1481 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1482 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1483 for (nread = 0; nread < len; nread += r, addr += r)
1485 blk_len = min(sizeof(buffer), len - nread);
1486 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1487 r == 0)
1489 /* fail at first address, return error */
1490 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1491 /* something has already been read, return partial information */
1492 break;
1494 if (nread == 0) packet_reply_open(gdbctx);
1495 packet_reply_hex_to(gdbctx, buffer, r);
1497 packet_reply_close(gdbctx);
1498 return packet_done;
1501 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1503 char* addr;
1504 unsigned int len, blk_len;
1505 char* ptr;
1506 char buffer[32];
1507 SIZE_T w;
1509 assert(gdbctx->in_trap);
1510 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1511 if (ptr == NULL)
1513 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1514 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1515 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1516 return packet_error;
1518 *ptr++ = '\0';
1520 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1522 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1523 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1524 return packet_error;
1526 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1528 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1529 fprintf(stderr, "Wrong sizes %u <> %u\n",
1530 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1531 return packet_error;
1533 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1534 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1535 while (len > 0)
1537 blk_len = min(sizeof(buffer), len);
1538 hex_from(buffer, ptr, blk_len);
1539 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1540 w != blk_len)
1541 break;
1542 addr += blk_len;
1543 len -= blk_len;
1544 ptr += blk_len;
1546 return packet_ok; /* FIXME: error while writing ? */
1549 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1551 unsigned reg;
1552 CONTEXT ctx;
1553 CONTEXT* pctx = &gdbctx->context;
1555 assert(gdbctx->in_trap);
1556 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1557 if (reg >= cpu_num_regs)
1559 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1560 fprintf(stderr, "Register out of bounds %x\n", reg);
1561 return packet_error;
1563 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1565 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1566 return packet_error;
1568 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1569 fprintf(stderr, "Read register %x => %08x%08x\n", reg,
1570 (unsigned)(cpu_register(pctx, reg) >> 32), (unsigned)cpu_register(pctx, reg));
1571 packet_reply_open(gdbctx);
1572 packet_reply_register_hex_to(gdbctx, reg);
1573 packet_reply_close(gdbctx);
1574 return packet_done;
1577 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1579 unsigned reg;
1580 char* ptr;
1581 CONTEXT ctx;
1582 CONTEXT* pctx = &gdbctx->context;
1584 assert(gdbctx->in_trap);
1586 reg = strtoul(gdbctx->in_packet, &ptr, 16);
1587 if (ptr == NULL || reg >= cpu_num_regs || *ptr++ != '=')
1589 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1590 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1591 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1592 * it wouldn't matter too much, and it fakes our support for all regs
1594 return (ptr == NULL) ? packet_error : packet_ok;
1596 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1598 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1599 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
1602 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1604 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1605 return packet_error;
1608 cpu_register_hex_from(pctx, reg, (const char**)&ptr);
1609 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1611 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1612 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1613 return packet_error;
1616 return packet_ok;
1619 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1621 char buffer[128];
1622 char clsName[128];
1623 char wndName[128];
1624 HWND child;
1626 do {
1627 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1628 strcpy(clsName, "-- Unknown --");
1629 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1630 strcpy(wndName, "-- Empty --");
1632 packet_reply_open(gdbctx);
1633 packet_reply_catc(gdbctx, 'O');
1634 snprintf(buffer, sizeof(buffer),
1635 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1636 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1637 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1638 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1639 wndName);
1640 packet_reply_hex_to_str(gdbctx, buffer);
1641 packet_reply_close(gdbctx);
1643 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1644 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1645 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1648 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1650 char buffer[128];
1652 /* we do the output in several 'O' packets, with the last one being just OK for
1653 * marking the end of the output */
1654 packet_reply_open(gdbctx);
1655 packet_reply_catc(gdbctx, 'O');
1656 snprintf(buffer, sizeof(buffer),
1657 "%-16.16s %-17.17s %-8.8s %s\n",
1658 "hwnd", "Class Name", " Style", " WndProc Text");
1659 packet_reply_hex_to_str(gdbctx, buffer);
1660 packet_reply_close(gdbctx);
1662 /* FIXME: could also add a pmt to this command in str... */
1663 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1664 packet_reply(gdbctx, "OK", 2);
1667 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1669 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1670 char buffer[128];
1671 char deco;
1672 PROCESSENTRY32 entry;
1673 BOOL ok;
1675 if (snap == INVALID_HANDLE_VALUE)
1676 return;
1678 entry.dwSize = sizeof(entry);
1679 ok = Process32First(snap, &entry);
1681 /* we do the output in several 'O' packets, with the last one being just OK for
1682 * marking the end of the output */
1684 packet_reply_open(gdbctx);
1685 packet_reply_catc(gdbctx, 'O');
1686 snprintf(buffer, sizeof(buffer),
1687 " %-8.8s %-8.8s %-8.8s %s\n",
1688 "pid", "threads", "parent", "executable");
1689 packet_reply_hex_to_str(gdbctx, buffer);
1690 packet_reply_close(gdbctx);
1692 while (ok)
1694 deco = ' ';
1695 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1696 packet_reply_open(gdbctx);
1697 packet_reply_catc(gdbctx, 'O');
1698 snprintf(buffer, sizeof(buffer),
1699 "%c%08x %-8d %08x '%s'\n",
1700 deco, entry.th32ProcessID, entry.cntThreads,
1701 entry.th32ParentProcessID, entry.szExeFile);
1702 packet_reply_hex_to_str(gdbctx, buffer);
1703 packet_reply_close(gdbctx);
1704 ok = Process32Next(snap, &entry);
1706 CloseHandle(snap);
1707 packet_reply(gdbctx, "OK", 2);
1710 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1712 MEMORY_BASIC_INFORMATION mbi;
1713 char* addr = 0;
1714 const char* state;
1715 const char* type;
1716 char prot[3+1];
1717 char buffer[128];
1719 /* we do the output in several 'O' packets, with the last one being just OK for
1720 * marking the end of the output */
1721 packet_reply_open(gdbctx);
1722 packet_reply_catc(gdbctx, 'O');
1723 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1724 packet_reply_close(gdbctx);
1726 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1728 switch (mbi.State)
1730 case MEM_COMMIT: state = "commit "; break;
1731 case MEM_FREE: state = "free "; break;
1732 case MEM_RESERVE: state = "reserve"; break;
1733 default: state = "??? "; break;
1735 if (mbi.State != MEM_FREE)
1737 switch (mbi.Type)
1739 case MEM_IMAGE: type = "image "; break;
1740 case MEM_MAPPED: type = "mapped "; break;
1741 case MEM_PRIVATE: type = "private"; break;
1742 case 0: type = " "; break;
1743 default: type = "??? "; break;
1745 memset(prot, ' ' , sizeof(prot)-1);
1746 prot[sizeof(prot)-1] = '\0';
1747 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1748 prot[0] = 'R';
1749 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1750 prot[1] = 'W';
1751 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1752 prot[1] = 'C';
1753 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1754 prot[2] = 'X';
1756 else
1758 type = "";
1759 prot[0] = '\0';
1761 packet_reply_open(gdbctx);
1762 snprintf(buffer, sizeof(buffer), "%0*lx %0*lx %s %s %s\n",
1763 (unsigned)sizeof(void*), (DWORD_PTR)addr,
1764 (unsigned)sizeof(void*), mbi.RegionSize, state, type, prot);
1765 packet_reply_catc(gdbctx, 'O');
1766 packet_reply_hex_to_str(gdbctx, buffer);
1767 packet_reply_close(gdbctx);
1769 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1770 break;
1771 addr += mbi.RegionSize;
1773 packet_reply(gdbctx, "OK", 2);
1776 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1777 int len, const char* str)
1779 char buffer[128];
1781 if (len == 0)
1783 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1785 else if (len >= 2 && str[0] == '=')
1787 unsigned val = atoi(&str[1]);
1788 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1789 gdbctx->trace = val;
1791 else
1793 /* FIXME: ugly but can use error packet here */
1794 packet_reply_cat(gdbctx, "E00");
1795 return;
1797 packet_reply_open(gdbctx);
1798 packet_reply_hex_to_str(gdbctx, buffer);
1799 packet_reply_close(gdbctx);
1802 struct query_detail
1804 int with_arg;
1805 const char* name;
1806 size_t len;
1807 void (*handler)(struct gdb_context*, int, const char*);
1808 } query_details[] =
1810 {0, "wnd", 3, packet_query_monitor_wnd},
1811 {0, "window", 6, packet_query_monitor_wnd},
1812 {0, "proc", 4, packet_query_monitor_process},
1813 {0, "process", 7, packet_query_monitor_process},
1814 {0, "mem", 3, packet_query_monitor_mem},
1815 {1, "trace", 5, packet_query_monitor_trace},
1816 {0, NULL, 0, NULL},
1819 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1820 const char* hxcmd, size_t len)
1822 char buffer[128];
1823 struct query_detail* qd;
1825 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1826 len /= 2;
1827 hex_from(buffer, hxcmd, len);
1829 for (qd = query_details; qd->name != NULL; qd++)
1831 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1832 if (!qd->with_arg && len != qd->len) continue;
1834 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1835 return packet_done;
1837 return packet_reply_error(gdbctx, EINVAL);
1840 static enum packet_return packet_query(struct gdb_context* gdbctx)
1842 switch (gdbctx->in_packet[0])
1844 case 'f':
1845 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1847 struct dbg_thread* thd;
1849 packet_reply_open(gdbctx);
1850 packet_reply_add(gdbctx, "m", 1);
1851 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1853 packet_reply_val(gdbctx, thd->tid, 4);
1854 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1855 packet_reply_add(gdbctx, ",", 1);
1857 packet_reply_close(gdbctx);
1858 return packet_done;
1860 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1862 char result[128];
1864 packet_reply_open(gdbctx);
1865 packet_reply_catc(gdbctx, 'O');
1866 get_process_info(gdbctx, result, sizeof(result));
1867 packet_reply_hex_to_str(gdbctx, result);
1868 packet_reply_close(gdbctx);
1869 return packet_done;
1871 break;
1872 case 's':
1873 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1875 packet_reply(gdbctx, "l", 1);
1876 return packet_done;
1878 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1880 packet_reply(gdbctx, "l", 1);
1881 return packet_done;
1883 break;
1884 case 'A':
1885 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
1887 char buf[2];
1889 buf[0] = '1';
1890 buf[1] = 0;
1891 return packet_reply(gdbctx, buf, -1);
1893 break;
1894 case 'C':
1895 if (gdbctx->in_packet_len == 1)
1897 struct dbg_thread* thd;
1898 /* FIXME: doc says 16 bit val ??? */
1899 /* grab first created thread, aka last in list */
1900 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1901 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1902 packet_reply_open(gdbctx);
1903 packet_reply_add(gdbctx, "QC", 2);
1904 packet_reply_val(gdbctx, thd->tid, 4);
1905 packet_reply_close(gdbctx);
1906 return packet_done;
1908 break;
1909 case 'O':
1910 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1912 char buf[64];
1914 snprintf(buf, sizeof(buf),
1915 "Text=%08lx;Data=%08lx;Bss=%08lx",
1916 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1917 gdbctx->wine_segs[2]);
1918 return packet_reply(gdbctx, buf, -1);
1920 break;
1921 case 'R':
1922 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1924 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1925 gdbctx->in_packet_len - 5);
1927 break;
1928 case 'S':
1929 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1930 return packet_ok;
1931 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1933 /* no features supported */
1934 packet_reply_open(gdbctx);
1935 packet_reply_close(gdbctx);
1936 return packet_done;
1938 break;
1939 case 'T':
1940 if (gdbctx->in_packet_len > 15 &&
1941 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1942 gdbctx->in_packet[15] == ',')
1944 unsigned tid;
1945 char* end;
1946 char result[128];
1948 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1949 if (end == NULL) break;
1950 get_thread_info(gdbctx, tid, result, sizeof(result));
1951 packet_reply_open(gdbctx);
1952 packet_reply_hex_to_str(gdbctx, result);
1953 packet_reply_close(gdbctx);
1954 return packet_done;
1956 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
1958 /* Tracepoints not supported */
1959 packet_reply_open(gdbctx);
1960 packet_reply_close(gdbctx);
1961 return packet_done;
1963 break;
1965 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1966 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1967 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1968 return packet_error;
1971 static enum packet_return packet_step(struct gdb_context* gdbctx)
1973 /* FIXME: add support for address in packet */
1974 assert(gdbctx->in_packet_len == 0);
1975 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1976 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1977 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1978 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1979 be_cpu->single_step(&gdbctx->context, TRUE);
1980 resume_debuggee(gdbctx, DBG_CONTINUE);
1981 wait_for_debuggee(gdbctx);
1982 be_cpu->single_step(&gdbctx->context, FALSE);
1983 return packet_reply_status(gdbctx);
1986 #if 0
1987 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1989 unsigned char sig;
1991 /* FIXME: add support for address in packet */
1992 assert(gdbctx->in_packet_len == 2);
1993 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1994 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1995 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1996 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1997 hex_from(&sig, gdbctx->in_packet, 1);
1998 /* cannot change signals on the fly */
1999 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2000 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
2001 if (sig != gdbctx->last_sig)
2002 return packet_error;
2003 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
2004 wait_for_debuggee(gdbctx);
2005 return packet_reply_status(gdbctx);
2007 #endif
2009 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
2011 char* end;
2012 unsigned tid;
2014 tid = strtol(gdbctx->in_packet, &end, 16);
2015 if (tid == -1 || tid == 0)
2016 return packet_reply_error(gdbctx, EINVAL);
2017 if (dbg_get_thread(gdbctx->process, tid) != NULL)
2018 return packet_ok;
2019 return packet_reply_error(gdbctx, ESRCH);
2022 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
2024 void* addr;
2025 unsigned len;
2026 struct gdb_ctx_Xpoint* xpt;
2027 enum be_xpoint_type t;
2029 /* FIXME: check packet_len */
2030 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2031 gdbctx->in_packet[1] != ',' ||
2032 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2033 return packet_error;
2034 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2035 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
2036 addr, len, gdbctx->in_packet[0]);
2037 switch (gdbctx->in_packet[0])
2039 case '0': t = be_xpoint_break; len = 0; break;
2040 case '1': t = be_xpoint_watch_exec; break;
2041 case '2': t = be_xpoint_watch_read; break;
2042 case '3': t = be_xpoint_watch_write; break;
2043 default: return packet_error;
2045 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2047 if (xpt->addr == addr && xpt->type == t)
2049 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
2050 gdbctx->process->process_io, &gdbctx->context,
2051 t, xpt->addr, xpt->val, len))
2053 xpt->type = -1;
2054 return packet_ok;
2056 break;
2059 return packet_error;
2062 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
2064 void* addr;
2065 unsigned len;
2066 struct gdb_ctx_Xpoint* xpt;
2067 enum be_xpoint_type t;
2069 /* FIXME: check packet_len */
2070 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2071 gdbctx->in_packet[1] != ',' ||
2072 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2073 return packet_error;
2074 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2075 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
2076 addr, len, gdbctx->in_packet[0]);
2077 switch (gdbctx->in_packet[0])
2079 case '0': t = be_xpoint_break; len = 0; break;
2080 case '1': t = be_xpoint_watch_exec; break;
2081 case '2': t = be_xpoint_watch_read; break;
2082 case '3': t = be_xpoint_watch_write; break;
2083 default: return packet_error;
2085 /* because of packet command handling, this should be made idempotent */
2086 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2088 if (xpt->addr == addr && xpt->type == t)
2089 return packet_ok; /* nothing to do */
2091 /* really set the Xpoint */
2092 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2094 if (xpt->type == -1)
2096 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2097 gdbctx->process->process_io, &gdbctx->context,
2098 t, addr, &xpt->val, len))
2100 xpt->addr = addr;
2101 xpt->type = t;
2102 return packet_ok;
2104 fprintf(stderr, "cannot set xpoint\n");
2105 break;
2108 /* no more entries... eech */
2109 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2110 return packet_error;
2113 /* =============================================== *
2114 * P A C K E T I N F R A S T R U C T U R E *
2115 * =============================================== *
2118 struct packet_entry
2120 char key;
2121 enum packet_return (*handler)(struct gdb_context* gdbctx);
2124 static struct packet_entry packet_entries[] =
2126 /*{'!', packet_extended}, */
2127 {'?', packet_last_signal},
2128 {'c', packet_continue},
2129 {'C', packet_continue_signal},
2130 {'D', packet_detach},
2131 {'g', packet_read_registers},
2132 {'G', packet_write_registers},
2133 {'k', packet_kill},
2134 {'H', packet_thread},
2135 {'m', packet_read_memory},
2136 {'M', packet_write_memory},
2137 {'p', packet_read_register},
2138 {'P', packet_write_register},
2139 {'q', packet_query},
2140 /* {'Q', packet_set}, */
2141 /* {'R', packet,restart}, only in extended mode ! */
2142 {'s', packet_step},
2143 /*{'S', packet_step_signal}, hard(er) to implement */
2144 {'T', packet_thread_alive},
2145 {'v', packet_verbose},
2146 {'z', packet_remove_breakpoint},
2147 {'Z', packet_set_breakpoint},
2150 static BOOL extract_packets(struct gdb_context* gdbctx)
2152 char* end;
2153 int plen;
2154 unsigned char in_cksum, loc_cksum;
2155 char* ptr;
2156 enum packet_return ret = packet_error;
2157 int num_packet = 0;
2159 while ((ret & packet_last_f) == 0)
2161 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2162 fprintf(stderr, "In-buf: %*.*s\n",
2163 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2164 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2165 if (ptr == NULL) return FALSE;
2166 if (ptr != gdbctx->in_buf)
2168 int glen = ptr - gdbctx->in_buf; /* garbage len */
2169 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2170 fprintf(stderr, "Removing garbage: %*.*s\n",
2171 glen, glen, gdbctx->in_buf);
2172 gdbctx->in_len -= glen;
2173 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2175 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2176 if (end == NULL) return FALSE;
2177 /* no checksum yet */
2178 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2179 plen = end - gdbctx->in_buf - 1;
2180 hex_from(&in_cksum, end + 1, 1);
2181 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2182 if (loc_cksum == in_cksum)
2184 if (num_packet == 0) {
2185 int i;
2187 ret = packet_error;
2189 write(gdbctx->sock, "+", 1);
2190 assert(plen);
2192 /* FIXME: should use bsearch if packet_entries was sorted */
2193 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2195 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2197 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2199 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2200 fprintf(stderr, "Unknown packet request %*.*s\n",
2201 plen, plen, &gdbctx->in_buf[1]);
2203 else
2205 gdbctx->in_packet = gdbctx->in_buf + 2;
2206 gdbctx->in_packet_len = plen - 1;
2207 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2208 fprintf(stderr, "Packet: %c%*.*s\n",
2209 gdbctx->in_buf[1],
2210 gdbctx->in_packet_len, gdbctx->in_packet_len,
2211 gdbctx->in_packet);
2212 ret = (packet_entries[i].handler)(gdbctx);
2214 switch (ret & ~packet_last_f)
2216 case packet_error: packet_reply(gdbctx, "", 0); break;
2217 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2218 case packet_done: break;
2220 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2221 fprintf(stderr, "Reply-full: %*.*s\n",
2222 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2223 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2224 assert(i == gdbctx->out_len);
2225 /* if this fails, we'll have to use POLLOUT...
2227 gdbctx->out_len = 0;
2228 num_packet++;
2230 else
2232 /* FIXME: If we have more than one packet in our input buffer,
2233 * it's very likely that we took too long to answer to a given packet
2234 * and gdb is sending us the same packet again.
2235 * So we simply drop the second packet. This will lower the risk of error,
2236 * but there's still some race conditions here.
2237 * A better fix (yet not perfect) would be to have two threads:
2238 * - one managing the packets for gdb
2239 * - the second one managing the commands...
2240 * This would allow us to send the reply with the '+' character (Ack of
2241 * the command) way sooner than we do now.
2243 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2244 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2247 else
2249 write(gdbctx->sock, "+", 1);
2250 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2251 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2253 gdbctx->in_len -= plen + 4;
2254 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2256 return TRUE;
2259 static int fetch_data(struct gdb_context* gdbctx)
2261 int len, in_len = gdbctx->in_len;
2263 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2264 for (;;)
2266 #define STEP 128
2267 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2268 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2269 #undef STEP
2270 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2271 fprintf(stderr, "%d %d %*.*s\n",
2272 gdbctx->in_len, gdbctx->in_buf_alloc,
2273 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2274 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2275 if (len <= 0) break;
2276 gdbctx->in_len += len;
2277 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2278 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2280 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2281 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2282 return gdbctx->in_len - in_len;
2285 #define FLAG_NO_START 1
2286 #define FLAG_WITH_XTERM 2
2288 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2290 char buf[MAX_PATH];
2291 int fd;
2292 const char* gdb_path;
2293 FILE* f;
2295 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2296 strcpy(buf,"/tmp/winegdb.XXXXXX");
2297 fd = mkstemps(buf, 0);
2298 if (fd == -1) return FALSE;
2299 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2300 fprintf(f, "file %s\n", wine_path);
2301 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2302 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2303 fprintf(f, "set prompt Wine-gdb>\\ \n");
2304 /* gdb 5.1 seems to require it, won't hurt anyway */
2305 fprintf(f, "sharedlibrary\n");
2306 /* This is needed (but not a decent & final fix)
2307 * Without this, gdb would skip our inter-DLL relay code (because
2308 * we don't have any line number information for the relay code)
2309 * With this, we will stop on first instruction of the stub, and
2310 * reusing step, will get us through the relay stub at the actual
2311 * function we're looking at.
2313 fprintf(f, "set step-mode on\n");
2314 /* tell gdb to delete this file when done handling it... */
2315 fprintf(f, "shell rm -f \"%s\"\n", buf);
2316 fclose(f);
2317 if (flags & FLAG_WITH_XTERM)
2318 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2319 else
2320 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2321 assert(0); /* never reached */
2322 return TRUE;
2325 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2327 int sock;
2328 struct sockaddr_in s_addrs;
2329 unsigned int s_len = sizeof(s_addrs);
2330 struct pollfd pollfd;
2331 IMAGEHLP_MODULE64 imh_mod;
2332 BOOL ret = FALSE;
2334 /* step 1: create socket for gdb connection request */
2335 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2337 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2338 fprintf(stderr, "Can't create socket");
2339 return FALSE;
2342 if (listen(sock, 1) == -1 || getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2343 goto cleanup;
2345 /* step 2: do the process internal creation */
2346 handle_debug_event(gdbctx, de);
2348 /* step3: get the wine loader name */
2349 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod))
2350 goto cleanup;
2352 /* step 4: fire up gdb (if requested) */
2353 if (flags & FLAG_NO_START)
2354 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2355 else
2356 switch (fork())
2358 case -1: /* error in parent... */
2359 fprintf(stderr, "Cannot create gdb\n");
2360 goto cleanup;
2361 default: /* in parent... success */
2362 signal(SIGINT, SIG_IGN);
2363 break;
2364 case 0: /* in child... and alive */
2365 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2366 /* if we're here, exec failed, so report failure */
2367 goto cleanup;
2370 /* step 5: wait for gdb to connect actually */
2371 pollfd.fd = sock;
2372 pollfd.events = POLLIN;
2373 pollfd.revents = 0;
2375 switch (poll(&pollfd, 1, -1))
2377 case 1:
2378 if (pollfd.revents & POLLIN)
2380 int dummy = 1;
2381 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2382 if (gdbctx->sock == -1)
2383 break;
2384 ret = TRUE;
2385 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2386 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2387 /* don't keep our small packets too long: send them ASAP back to GDB
2388 * without this, GDB really crawls
2390 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2392 break;
2393 case 0:
2394 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2395 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2396 break;
2397 case -1:
2398 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2399 fprintf(stderr, "Poll for cnx failed (error)\n");
2400 break;
2401 default:
2402 assert(0);
2405 cleanup:
2406 close(sock);
2407 return ret;
2410 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2412 DEBUG_EVENT de;
2413 int i;
2415 gdbctx->sock = -1;
2416 gdbctx->in_buf = NULL;
2417 gdbctx->in_buf_alloc = 0;
2418 gdbctx->in_len = 0;
2419 gdbctx->out_buf = NULL;
2420 gdbctx->out_buf_alloc = 0;
2421 gdbctx->out_len = 0;
2422 gdbctx->out_curr_packet = -1;
2424 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2425 gdbctx->last_sig = 0;
2426 gdbctx->in_trap = FALSE;
2427 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2428 gdbctx->process = NULL;
2429 for (i = 0; i < NUM_XPOINT; i++)
2430 gdbctx->Xpoints[i].type = -1;
2431 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2432 gdbctx->wine_segs[i] = 0;
2434 /* wait for first trap */
2435 while (WaitForDebugEvent(&de, INFINITE))
2437 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2439 /* this should be the first event we get,
2440 * and the only one of this type */
2441 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2442 /* gdbctx->dwProcessId = pid; */
2443 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2444 assert(!gdbctx->in_trap);
2446 else
2448 handle_debug_event(gdbctx, &de);
2449 if (gdbctx->in_trap) break;
2451 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2453 return TRUE;
2456 static int gdb_remote(unsigned flags)
2458 struct pollfd pollfd;
2459 struct gdb_context gdbctx;
2460 BOOL doLoop;
2462 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2464 pollfd.fd = gdbctx.sock;
2465 pollfd.events = POLLIN;
2466 pollfd.revents = 0;
2468 switch (poll(&pollfd, 1, -1))
2470 case 1:
2471 /* got something */
2472 if (pollfd.revents & (POLLHUP | POLLERR))
2474 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2475 fprintf(stderr, "Gdb hung up\n");
2476 /* kill also debuggee process - questionnable - */
2477 detach_debuggee(&gdbctx, TRUE);
2478 doLoop = FALSE;
2479 break;
2481 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2483 if (extract_packets(&gdbctx)) doLoop = FALSE;
2485 break;
2486 case 0:
2487 /* timeout, should never happen (infinite timeout) */
2488 break;
2489 case -1:
2490 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2491 fprintf(stderr, "Poll failed\n");
2492 doLoop = FALSE;
2493 break;
2496 wait(NULL);
2497 return 0;
2499 #endif
2501 int gdb_main(int argc, char* argv[])
2503 #ifdef HAVE_POLL
2504 unsigned gdb_flags = 0;
2506 argc--; argv++;
2507 while (argc > 0 && argv[0][0] == '-')
2509 if (strcmp(argv[0], "--no-start") == 0)
2511 gdb_flags |= FLAG_NO_START;
2512 argc--; argv++;
2513 continue;
2515 if (strcmp(argv[0], "--with-xterm") == 0)
2517 gdb_flags |= FLAG_WITH_XTERM;
2518 argc--; argv++;
2519 continue;
2521 return -1;
2523 if (dbg_active_attach(argc, argv) == start_ok ||
2524 dbg_active_launch(argc, argv) == start_ok)
2525 return gdb_remote(gdb_flags);
2526 #else
2527 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2528 #endif
2529 return -1;