push 9bfdf186dc6a237cd7f58f0ee2ef677e81617b1d
[wine/hacks.git] / programs / winedbg / gdbproxy.c
blob9026b3726937dd66ef026e13409c5d2de61283a7
1 /*
2 * A Win32 based proxy implementing the GBD remote protocol
3 * This allows to debug Wine (and any "emulated" program) under
4 * Linux using GDB
6 * Copyright (c) Eric Pouech 2002-2004
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* Protocol specification can be found here:
24 * http://sources.redhat.com/gdb/onlinedocs/gdb_32.html
27 #include "config.h"
28 #include "wine/port.h"
30 #include <assert.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #ifdef HAVE_SYS_POLL_H
38 # include <sys/poll.h>
39 #endif
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
42 #endif
43 #ifdef HAVE_SYS_SOCKET_H
44 # include <sys/socket.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49 #ifdef HAVE_NETINET_TCP_H
50 # include <netinet/tcp.h>
51 #endif
52 #ifdef HAVE_UNISTD_H
53 # include <unistd.h>
54 #endif
56 /* if we don't have poll support on this system
57 * we won't provide gdb proxy support here...
59 #ifdef HAVE_POLL
61 #include "debugger.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "tlhelp32.h"
67 #define GDBPXY_TRC_LOWLEVEL 0x01
68 #define GDBPXY_TRC_PACKET 0x02
69 #define GDBPXY_TRC_COMMAND 0x04
70 #define GDBPXY_TRC_COMMAND_ERROR 0x08
71 #define GDBPXY_TRC_WIN32_EVENT 0x10
72 #define GDBPXY_TRC_WIN32_ERROR 0x20
73 #define GDBPXY_TRC_COMMAND_FIXME 0x80
75 struct gdb_ctx_Xpoint
77 enum be_xpoint_type type; /* -1 means free */
78 void* addr;
79 unsigned long val;
82 struct gdb_context
84 /* gdb information */
85 int sock;
86 /* incoming buffer */
87 char* in_buf;
88 int in_buf_alloc;
89 int in_len;
90 /* split into individual packet */
91 char* in_packet;
92 int in_packet_len;
93 /* outgoing buffer */
94 char* out_buf;
95 int out_buf_alloc;
96 int out_len;
97 int out_curr_packet;
98 /* generic GDB thread information */
99 struct dbg_thread* exec_thread; /* thread used in step & continue */
100 struct dbg_thread* other_thread; /* thread to be used in any other operation */
101 unsigned trace;
102 /* current Win32 trap env */
103 unsigned last_sig;
104 BOOL in_trap;
105 CONTEXT context;
106 /* Win32 information */
107 struct dbg_process* process;
108 #define NUM_XPOINT 32
109 struct gdb_ctx_Xpoint Xpoints[NUM_XPOINT];
110 /* Unix environment */
111 unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
114 static struct be_process_io be_process_gdbproxy_io =
116 NULL, /* we shouldn't use close_process() in gdbproxy */
117 ReadProcessMemory,
118 WriteProcessMemory
121 /* =============================================== *
122 * B A S I C M A N I P U L A T I O N S *
123 * =============================================== *
126 static inline int hex_from0(char ch)
128 if (ch >= '0' && ch <= '9') return ch - '0';
129 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
130 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
132 assert(0);
133 return 0;
136 static inline unsigned char hex_to0(int x)
138 assert(x >= 0 && x < 16);
139 return "0123456789abcdef"[x];
142 static int hex_to_int(const char* src, size_t len)
144 unsigned int returnval = 0;
145 while (len--)
147 returnval <<= 4;
148 returnval |= hex_from0(*src++);
150 return returnval;
153 static void hex_from(void* dst, const char* src, size_t len)
155 unsigned char *p = dst;
156 while (len--)
158 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
159 src += 2;
163 static void hex_to(char* dst, const void* src, size_t len)
165 const unsigned char *p = src;
166 while (len--)
168 *dst++ = hex_to0(*p >> 4);
169 *dst++ = hex_to0(*p & 0x0F);
170 p++;
174 static unsigned char checksum(const char* ptr, int len)
176 unsigned cksum = 0;
178 while (len-- > 0)
179 cksum += (unsigned char)*ptr++;
180 return cksum;
183 /* =============================================== *
184 * C P U H A N D L E R S *
185 * =============================================== *
188 #ifdef __i386__
189 static size_t cpu_register_map[] = {
190 FIELD_OFFSET(CONTEXT, Eax),
191 FIELD_OFFSET(CONTEXT, Ecx),
192 FIELD_OFFSET(CONTEXT, Edx),
193 FIELD_OFFSET(CONTEXT, Ebx),
194 FIELD_OFFSET(CONTEXT, Esp),
195 FIELD_OFFSET(CONTEXT, Ebp),
196 FIELD_OFFSET(CONTEXT, Esi),
197 FIELD_OFFSET(CONTEXT, Edi),
198 FIELD_OFFSET(CONTEXT, Eip),
199 FIELD_OFFSET(CONTEXT, EFlags),
200 FIELD_OFFSET(CONTEXT, SegCs),
201 FIELD_OFFSET(CONTEXT, SegSs),
202 FIELD_OFFSET(CONTEXT, SegDs),
203 FIELD_OFFSET(CONTEXT, SegEs),
204 FIELD_OFFSET(CONTEXT, SegFs),
205 FIELD_OFFSET(CONTEXT, SegGs),
207 #elif defined(__powerpc__)
208 static size_t cpu_register_map[] = {
209 FIELD_OFFSET(CONTEXT, Gpr0),
210 FIELD_OFFSET(CONTEXT, Gpr1),
211 FIELD_OFFSET(CONTEXT, Gpr2),
212 FIELD_OFFSET(CONTEXT, Gpr3),
213 FIELD_OFFSET(CONTEXT, Gpr4),
214 FIELD_OFFSET(CONTEXT, Gpr5),
215 FIELD_OFFSET(CONTEXT, Gpr6),
216 FIELD_OFFSET(CONTEXT, Gpr7),
217 FIELD_OFFSET(CONTEXT, Gpr8),
218 FIELD_OFFSET(CONTEXT, Gpr9),
219 FIELD_OFFSET(CONTEXT, Gpr10),
220 FIELD_OFFSET(CONTEXT, Gpr11),
221 FIELD_OFFSET(CONTEXT, Gpr12),
222 FIELD_OFFSET(CONTEXT, Gpr13),
223 FIELD_OFFSET(CONTEXT, Gpr14),
224 FIELD_OFFSET(CONTEXT, Gpr15),
225 FIELD_OFFSET(CONTEXT, Gpr16),
226 FIELD_OFFSET(CONTEXT, Gpr17),
227 FIELD_OFFSET(CONTEXT, Gpr18),
228 FIELD_OFFSET(CONTEXT, Gpr19),
229 FIELD_OFFSET(CONTEXT, Gpr20),
230 FIELD_OFFSET(CONTEXT, Gpr21),
231 FIELD_OFFSET(CONTEXT, Gpr22),
232 FIELD_OFFSET(CONTEXT, Gpr23),
233 FIELD_OFFSET(CONTEXT, Gpr24),
234 FIELD_OFFSET(CONTEXT, Gpr25),
235 FIELD_OFFSET(CONTEXT, Gpr26),
236 FIELD_OFFSET(CONTEXT, Gpr27),
237 FIELD_OFFSET(CONTEXT, Gpr28),
238 FIELD_OFFSET(CONTEXT, Gpr29),
239 FIELD_OFFSET(CONTEXT, Gpr30),
240 FIELD_OFFSET(CONTEXT, Gpr31),
241 FIELD_OFFSET(CONTEXT, Fpr0),
242 FIELD_OFFSET(CONTEXT, Fpr1),
243 FIELD_OFFSET(CONTEXT, Fpr2),
244 FIELD_OFFSET(CONTEXT, Fpr3),
245 FIELD_OFFSET(CONTEXT, Fpr4),
246 FIELD_OFFSET(CONTEXT, Fpr5),
247 FIELD_OFFSET(CONTEXT, Fpr6),
248 FIELD_OFFSET(CONTEXT, Fpr7),
249 FIELD_OFFSET(CONTEXT, Fpr8),
250 FIELD_OFFSET(CONTEXT, Fpr9),
251 FIELD_OFFSET(CONTEXT, Fpr10),
252 FIELD_OFFSET(CONTEXT, Fpr11),
253 FIELD_OFFSET(CONTEXT, Fpr12),
254 FIELD_OFFSET(CONTEXT, Fpr13),
255 FIELD_OFFSET(CONTEXT, Fpr14),
256 FIELD_OFFSET(CONTEXT, Fpr15),
257 FIELD_OFFSET(CONTEXT, Fpr16),
258 FIELD_OFFSET(CONTEXT, Fpr17),
259 FIELD_OFFSET(CONTEXT, Fpr18),
260 FIELD_OFFSET(CONTEXT, Fpr19),
261 FIELD_OFFSET(CONTEXT, Fpr20),
262 FIELD_OFFSET(CONTEXT, Fpr21),
263 FIELD_OFFSET(CONTEXT, Fpr22),
264 FIELD_OFFSET(CONTEXT, Fpr23),
265 FIELD_OFFSET(CONTEXT, Fpr24),
266 FIELD_OFFSET(CONTEXT, Fpr25),
267 FIELD_OFFSET(CONTEXT, Fpr26),
268 FIELD_OFFSET(CONTEXT, Fpr27),
269 FIELD_OFFSET(CONTEXT, Fpr28),
270 FIELD_OFFSET(CONTEXT, Fpr29),
271 FIELD_OFFSET(CONTEXT, Fpr30),
272 FIELD_OFFSET(CONTEXT, Fpr31),
274 FIELD_OFFSET(CONTEXT, Iar),
275 FIELD_OFFSET(CONTEXT, Msr),
276 FIELD_OFFSET(CONTEXT, Cr),
277 FIELD_OFFSET(CONTEXT, Lr),
278 FIELD_OFFSET(CONTEXT, Ctr),
279 FIELD_OFFSET(CONTEXT, Xer),
280 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
281 /* see gdb/nlm/ppc.c */
283 #elif defined(__ALPHA__)
284 static size_t cpu_register_map[] = {
285 FIELD_OFFSET(CONTEXT, IntV0),
286 FIELD_OFFSET(CONTEXT, IntT0),
287 FIELD_OFFSET(CONTEXT, IntT1),
288 FIELD_OFFSET(CONTEXT, IntT2),
289 FIELD_OFFSET(CONTEXT, IntT3),
290 FIELD_OFFSET(CONTEXT, IntT4),
291 FIELD_OFFSET(CONTEXT, IntT5),
292 FIELD_OFFSET(CONTEXT, IntT6),
293 FIELD_OFFSET(CONTEXT, IntT7),
294 FIELD_OFFSET(CONTEXT, IntS0),
295 FIELD_OFFSET(CONTEXT, IntS1),
296 FIELD_OFFSET(CONTEXT, IntS2),
297 FIELD_OFFSET(CONTEXT, IntS3),
298 FIELD_OFFSET(CONTEXT, IntS4),
299 FIELD_OFFSET(CONTEXT, IntS5),
300 FIELD_OFFSET(CONTEXT, IntFp),
301 FIELD_OFFSET(CONTEXT, IntA0),
302 FIELD_OFFSET(CONTEXT, IntA1),
303 FIELD_OFFSET(CONTEXT, IntA2),
304 FIELD_OFFSET(CONTEXT, IntA3),
305 FIELD_OFFSET(CONTEXT, IntA4),
306 FIELD_OFFSET(CONTEXT, IntA5),
307 FIELD_OFFSET(CONTEXT, IntT8),
308 FIELD_OFFSET(CONTEXT, IntT9),
309 FIELD_OFFSET(CONTEXT, IntT10),
310 FIELD_OFFSET(CONTEXT, IntT11),
311 FIELD_OFFSET(CONTEXT, IntRa),
312 FIELD_OFFSET(CONTEXT, IntT12),
313 FIELD_OFFSET(CONTEXT, IntAt),
314 FIELD_OFFSET(CONTEXT, IntGp),
315 FIELD_OFFSET(CONTEXT, IntSp),
316 FIELD_OFFSET(CONTEXT, IntZero),
317 FIELD_OFFSET(CONTEXT, FltF0),
318 FIELD_OFFSET(CONTEXT, FltF1),
319 FIELD_OFFSET(CONTEXT, FltF2),
320 FIELD_OFFSET(CONTEXT, FltF3),
321 FIELD_OFFSET(CONTEXT, FltF4),
322 FIELD_OFFSET(CONTEXT, FltF5),
323 FIELD_OFFSET(CONTEXT, FltF6),
324 FIELD_OFFSET(CONTEXT, FltF7),
325 FIELD_OFFSET(CONTEXT, FltF8),
326 FIELD_OFFSET(CONTEXT, FltF9),
327 FIELD_OFFSET(CONTEXT, FltF10),
328 FIELD_OFFSET(CONTEXT, FltF11),
329 FIELD_OFFSET(CONTEXT, FltF12),
330 FIELD_OFFSET(CONTEXT, FltF13),
331 FIELD_OFFSET(CONTEXT, FltF14),
332 FIELD_OFFSET(CONTEXT, FltF15),
333 FIELD_OFFSET(CONTEXT, FltF16),
334 FIELD_OFFSET(CONTEXT, FltF17),
335 FIELD_OFFSET(CONTEXT, FltF18),
336 FIELD_OFFSET(CONTEXT, FltF19),
337 FIELD_OFFSET(CONTEXT, FltF20),
338 FIELD_OFFSET(CONTEXT, FltF21),
339 FIELD_OFFSET(CONTEXT, FltF22),
340 FIELD_OFFSET(CONTEXT, FltF23),
341 FIELD_OFFSET(CONTEXT, FltF24),
342 FIELD_OFFSET(CONTEXT, FltF25),
343 FIELD_OFFSET(CONTEXT, FltF26),
344 FIELD_OFFSET(CONTEXT, FltF27),
345 FIELD_OFFSET(CONTEXT, FltF28),
346 FIELD_OFFSET(CONTEXT, FltF29),
347 FIELD_OFFSET(CONTEXT, FltF30),
348 FIELD_OFFSET(CONTEXT, FltF31),
350 /* FIXME: Didn't look for the right order yet */
351 FIELD_OFFSET(CONTEXT, Fir),
352 FIELD_OFFSET(CONTEXT, Fpcr),
353 FIELD_OFFSET(CONTEXT, SoftFpcr),
355 #elif defined(__x86_64__)
356 static size_t cpu_register_map[] = {
357 FIELD_OFFSET(CONTEXT, Rax),
358 FIELD_OFFSET(CONTEXT, Rbx),
359 FIELD_OFFSET(CONTEXT, Rcx),
360 FIELD_OFFSET(CONTEXT, Rdx),
361 FIELD_OFFSET(CONTEXT, Rsi),
362 FIELD_OFFSET(CONTEXT, Rdi),
363 FIELD_OFFSET(CONTEXT, Rbp),
364 FIELD_OFFSET(CONTEXT, Rsp),
365 FIELD_OFFSET(CONTEXT, R8),
366 FIELD_OFFSET(CONTEXT, R9),
367 FIELD_OFFSET(CONTEXT, R10),
368 FIELD_OFFSET(CONTEXT, R11),
369 FIELD_OFFSET(CONTEXT, R12),
370 FIELD_OFFSET(CONTEXT, R13),
371 FIELD_OFFSET(CONTEXT, R14),
372 FIELD_OFFSET(CONTEXT, R15),
373 FIELD_OFFSET(CONTEXT, Rip),
374 FIELD_OFFSET(CONTEXT, EFlags),
375 FIELD_OFFSET(CONTEXT, SegCs),
376 FIELD_OFFSET(CONTEXT, SegSs),
377 FIELD_OFFSET(CONTEXT, SegDs),
378 FIELD_OFFSET(CONTEXT, SegEs),
379 FIELD_OFFSET(CONTEXT, SegFs),
380 FIELD_OFFSET(CONTEXT, SegGs),
382 #else
383 # error Define the registers map for your CPU
384 #endif
386 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
388 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
390 assert(idx < cpu_num_regs);
391 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
394 /* =============================================== *
395 * W I N 3 2 D E B U G I N T E R F A C E *
396 * =============================================== *
399 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
401 ctx->ContextFlags = CONTEXT_CONTROL
402 | CONTEXT_INTEGER
403 #ifdef CONTEXT_SEGMENTS
404 | CONTEXT_SEGMENTS
405 #endif
406 #ifdef CONTEXT_DEBUG_REGISTERS
407 | CONTEXT_DEBUG_REGISTERS
408 #endif
410 if (!GetThreadContext(h, ctx))
412 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
413 fprintf(stderr, "Can't get thread's context\n");
414 return FALSE;
416 return TRUE;
419 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
421 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
422 BOOL ret = FALSE;
424 switch (rec->ExceptionCode)
426 case EXCEPTION_ACCESS_VIOLATION:
427 case EXCEPTION_PRIV_INSTRUCTION:
428 case EXCEPTION_STACK_OVERFLOW:
429 case EXCEPTION_GUARD_PAGE:
430 gdbctx->last_sig = SIGSEGV;
431 ret = TRUE;
432 break;
433 case EXCEPTION_DATATYPE_MISALIGNMENT:
434 gdbctx->last_sig = SIGBUS;
435 ret = TRUE;
436 break;
437 case EXCEPTION_SINGLE_STEP:
438 /* fall thru */
439 case EXCEPTION_BREAKPOINT:
440 gdbctx->last_sig = SIGTRAP;
441 ret = TRUE;
442 break;
443 case EXCEPTION_FLT_DENORMAL_OPERAND:
444 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
445 case EXCEPTION_FLT_INEXACT_RESULT:
446 case EXCEPTION_FLT_INVALID_OPERATION:
447 case EXCEPTION_FLT_OVERFLOW:
448 case EXCEPTION_FLT_STACK_CHECK:
449 case EXCEPTION_FLT_UNDERFLOW:
450 gdbctx->last_sig = SIGFPE;
451 ret = TRUE;
452 break;
453 case EXCEPTION_INT_DIVIDE_BY_ZERO:
454 case EXCEPTION_INT_OVERFLOW:
455 gdbctx->last_sig = SIGFPE;
456 ret = TRUE;
457 break;
458 case EXCEPTION_ILLEGAL_INSTRUCTION:
459 gdbctx->last_sig = SIGILL;
460 ret = TRUE;
461 break;
462 case CONTROL_C_EXIT:
463 gdbctx->last_sig = SIGINT;
464 ret = TRUE;
465 break;
466 case STATUS_POSSIBLE_DEADLOCK:
467 gdbctx->last_sig = SIGALRM;
468 ret = TRUE;
469 /* FIXME: we could also add here a O packet with additional information */
470 break;
471 default:
472 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
473 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
474 gdbctx->last_sig = SIGABRT;
475 ret = TRUE;
476 break;
478 return ret;
481 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
483 union {
484 char bufferA[256];
485 WCHAR buffer[256];
486 } u;
488 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
490 switch (de->dwDebugEventCode)
492 case CREATE_PROCESS_DEBUG_EVENT:
493 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
494 de->u.CreateProcessInfo.hProcess);
495 if (!gdbctx->process) break;
496 memory_get_string_indirect(gdbctx->process,
497 de->u.CreateProcessInfo.lpImageName,
498 de->u.CreateProcessInfo.fUnicode,
499 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
500 dbg_set_process_name(gdbctx->process, u.buffer);
502 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
503 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
504 de->dwProcessId, de->dwThreadId,
505 dbg_W2A(u.buffer, -1),
506 de->u.CreateProcessInfo.lpImageName,
507 de->u.CreateProcessInfo.lpStartAddress,
508 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
509 de->u.CreateProcessInfo.nDebugInfoSize);
511 /* de->u.CreateProcessInfo.lpStartAddress; */
512 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
513 fprintf(stderr, "Couldn't initiate DbgHelp\n");
515 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
516 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
517 de->dwProcessId, de->dwThreadId,
518 de->u.CreateProcessInfo.lpStartAddress);
520 assert(dbg_curr_thread == NULL); /* shouldn't be there */
521 dbg_add_thread(gdbctx->process, de->dwThreadId,
522 de->u.CreateProcessInfo.hThread,
523 de->u.CreateProcessInfo.lpThreadLocalBase);
524 break;
526 case LOAD_DLL_DEBUG_EVENT:
527 assert(dbg_curr_thread);
528 memory_get_string_indirect(gdbctx->process,
529 de->u.LoadDll.lpImageName,
530 de->u.LoadDll.fUnicode,
531 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
532 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
533 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
534 de->dwProcessId, de->dwThreadId,
535 dbg_W2A(u.buffer, -1),
536 de->u.LoadDll.lpBaseOfDll,
537 de->u.LoadDll.dwDebugInfoFileOffset,
538 de->u.LoadDll.nDebugInfoSize);
539 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
540 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
541 break;
543 case UNLOAD_DLL_DEBUG_EVENT:
544 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
545 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
546 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
547 SymUnloadModule(gdbctx->process->handle,
548 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
549 break;
551 case EXCEPTION_DEBUG_EVENT:
552 assert(dbg_curr_thread);
553 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
554 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
555 de->dwProcessId, de->dwThreadId,
556 de->u.Exception.ExceptionRecord.ExceptionCode);
558 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
560 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
562 break;
564 case CREATE_THREAD_DEBUG_EVENT:
565 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
566 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
567 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
569 dbg_add_thread(gdbctx->process,
570 de->dwThreadId,
571 de->u.CreateThread.hThread,
572 de->u.CreateThread.lpThreadLocalBase);
573 break;
575 case EXIT_THREAD_DEBUG_EVENT:
576 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
577 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
578 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
580 assert(dbg_curr_thread);
581 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
582 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
583 dbg_del_thread(dbg_curr_thread);
584 break;
586 case EXIT_PROCESS_DEBUG_EVENT:
587 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
588 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
589 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
591 dbg_del_process(gdbctx->process);
592 gdbctx->process = NULL;
593 /* now signal gdb that we're done */
594 gdbctx->last_sig = SIGTERM;
595 gdbctx->in_trap = TRUE;
596 break;
598 case OUTPUT_DEBUG_STRING_EVENT:
599 assert(dbg_curr_thread);
600 memory_get_string(gdbctx->process,
601 de->u.DebugString.lpDebugStringData, TRUE,
602 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
603 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
604 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
605 de->dwProcessId, de->dwThreadId, u.bufferA);
606 break;
608 case RIP_EVENT:
609 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
610 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
611 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
612 de->u.RipInfo.dwType);
613 break;
615 default:
616 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
617 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
618 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
622 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
624 if (dbg_curr_thread)
626 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
627 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
628 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
629 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
630 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
631 fprintf(stderr, "Cannot continue on %04x (%x)\n",
632 dbg_curr_thread->tid, cont);
634 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
635 fprintf(stderr, "Cannot find last thread\n");
639 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
642 if (dbg_curr_thread)
644 if(dbg_curr_thread->tid == threadid){
645 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
646 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
647 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
648 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
649 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
650 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
651 fprintf(stderr, "Cannot continue on %04x (%x)\n",
652 dbg_curr_thread->tid, cont);
655 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
656 fprintf(stderr, "Cannot find last thread\n");
659 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
661 struct pollfd pollfd;
662 int ret;
663 char pkt;
665 pollfd.fd = gdbctx->sock;
666 pollfd.events = POLLIN;
667 pollfd.revents = 0;
669 if ((ret = poll(&pollfd, 1, 0)) == 1) {
670 ret = read(gdbctx->sock, &pkt, 1);
671 if (ret != 1) {
672 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
673 fprintf(stderr, "read failed\n");
675 return FALSE;
677 if (pkt != '\003') {
678 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
679 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
681 return FALSE;
683 return TRUE;
684 } else if (ret == -1) {
685 fprintf(stderr, "poll failed\n");
687 return FALSE;
690 static void wait_for_debuggee(struct gdb_context* gdbctx)
692 DEBUG_EVENT de;
694 gdbctx->in_trap = FALSE;
695 for (;;)
697 if (!WaitForDebugEvent(&de, 10))
699 if (GetLastError() == ERROR_SEM_TIMEOUT)
701 if (check_for_interrupt(gdbctx)) {
702 if (!DebugBreakProcess(gdbctx->process->handle)) {
703 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
704 fprintf(stderr, "Failed to break into debugee\n");
706 break;
708 WaitForDebugEvent(&de, INFINITE);
709 } else {
710 continue;
712 } else {
713 break;
716 handle_debug_event(gdbctx, &de);
717 assert(!gdbctx->process ||
718 gdbctx->process->pid == 0 ||
719 de.dwProcessId == gdbctx->process->pid);
720 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
721 if (gdbctx->in_trap) break;
722 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
726 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
728 be_cpu->single_step(&gdbctx->context, FALSE);
729 resume_debuggee(gdbctx, DBG_CONTINUE);
730 if (!kill)
731 DebugActiveProcessStop(gdbctx->process->pid);
732 dbg_del_process(gdbctx->process);
733 gdbctx->process = NULL;
736 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
738 DWORD status;
740 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
742 strcpy(buffer, "Unknown process");
743 return;
745 if (status == STILL_ACTIVE)
747 strcpy(buffer, "Running");
749 else
750 snprintf(buffer, len, "Terminated (%u)", status);
752 switch (GetPriorityClass(gdbctx->process->handle))
754 case 0: break;
755 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
756 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
757 #endif
758 #ifdef BELOW_NORMAL_PRIORITY_CLASS
759 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
760 #endif
761 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
762 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
763 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
764 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
766 strcat(buffer, "\n");
769 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
770 char* buffer, size_t len)
772 struct dbg_thread* thd;
773 DWORD status;
774 int prio;
776 /* FIXME: use the size of buffer */
777 thd = dbg_get_thread(gdbctx->process, tid);
778 if (thd == NULL)
780 strcpy(buffer, "No information");
781 return;
783 if (GetExitCodeThread(thd->handle, &status))
785 if (status == STILL_ACTIVE)
787 /* FIXME: this is a bit brutal... some nicer way shall be found */
788 switch (status = SuspendThread(thd->handle))
790 case -1: break;
791 case 0: strcpy(buffer, "Running"); break;
792 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
794 ResumeThread(thd->handle);
796 else
797 snprintf(buffer, len, "Terminated (exit code = %u)", status);
799 else
801 strcpy(buffer, "Unknown threadID");
803 switch (prio = GetThreadPriority(thd->handle))
805 case THREAD_PRIORITY_ERROR_RETURN: break;
806 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
807 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
808 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
809 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
810 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
811 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
812 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
813 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
815 assert(strlen(buffer) < len);
818 /* =============================================== *
819 * P A C K E T U T I L S *
820 * =============================================== *
823 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
824 packet_last_f = 0x80};
826 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
828 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
830 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
831 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
835 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
837 packet_reply_grow(gdbctx, len * 2);
838 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
839 gdbctx->out_len += len * 2;
842 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
844 packet_reply_hex_to(gdbctx, src, strlen(src));
847 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
849 int i, shift;
851 shift = (len - 1) * 8;
852 packet_reply_grow(gdbctx, len * 2);
853 for (i = 0; i < len; i++, shift -= 8)
855 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
856 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
860 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
862 packet_reply_grow(gdbctx, len);
863 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
864 gdbctx->out_len += len;
867 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
869 packet_reply_add(gdbctx, str, strlen(str));
872 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
874 packet_reply_add(gdbctx, &ch, 1);
877 static void packet_reply_open(struct gdb_context* gdbctx)
879 assert(gdbctx->out_curr_packet == -1);
880 packet_reply_catc(gdbctx, '$');
881 gdbctx->out_curr_packet = gdbctx->out_len;
884 static void packet_reply_close(struct gdb_context* gdbctx)
886 unsigned char cksum;
887 int plen;
889 plen = gdbctx->out_len - gdbctx->out_curr_packet;
890 packet_reply_catc(gdbctx, '#');
891 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
892 packet_reply_hex_to(gdbctx, &cksum, 1);
893 if (gdbctx->trace & GDBPXY_TRC_PACKET)
894 fprintf(stderr, "Reply : %*.*s\n",
895 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
896 gdbctx->out_curr_packet = -1;
899 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
901 packet_reply_open(gdbctx);
903 if (len == -1) len = strlen(packet);
904 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
906 packet_reply_add(gdbctx, packet, len);
908 packet_reply_close(gdbctx);
910 return packet_done;
913 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
915 packet_reply_open(gdbctx);
917 packet_reply_add(gdbctx, "E", 1);
918 packet_reply_val(gdbctx, error, 1);
920 packet_reply_close(gdbctx);
922 return packet_done;
925 /* =============================================== *
926 * P A C K E T H A N D L E R S *
927 * =============================================== *
930 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
932 enum packet_return ret = packet_done;
934 packet_reply_open(gdbctx);
936 if (gdbctx->process != NULL)
938 unsigned char sig;
939 unsigned i;
941 packet_reply_catc(gdbctx, 'T');
942 sig = gdbctx->last_sig;
943 packet_reply_val(gdbctx, sig, 1);
944 packet_reply_add(gdbctx, "thread:", 7);
945 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
946 packet_reply_catc(gdbctx, ';');
948 for (i = 0; i < cpu_num_regs; i++)
950 /* FIXME: this call will also grow the buffer...
951 * unneeded, but not harmful
953 packet_reply_val(gdbctx, i, 1);
954 packet_reply_catc(gdbctx, ':');
955 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
956 packet_reply_catc(gdbctx, ';');
959 else
961 /* Try to put an exit code
962 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
963 * just indicate the end of process and exit */
964 packet_reply_add(gdbctx, "W00", 3);
965 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
968 packet_reply_close(gdbctx);
970 return ret;
973 #if 0
974 static enum packet_return packet_extended(struct gdb_context* gdbctx)
976 gdbctx->extended = 1;
977 return packet_ok;
979 #endif
981 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
983 assert(gdbctx->in_packet_len == 0);
984 return packet_reply_status(gdbctx);
987 static enum packet_return packet_continue(struct gdb_context* gdbctx)
989 /* FIXME: add support for address in packet */
990 assert(gdbctx->in_packet_len == 0);
991 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
992 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
993 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
994 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
995 resume_debuggee(gdbctx, DBG_CONTINUE);
996 wait_for_debuggee(gdbctx);
997 return packet_reply_status(gdbctx);
1000 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1002 int i;
1003 int defaultAction = -1; /* magic non action */
1004 unsigned char sig;
1005 int actions =0;
1006 int actionIndex[20]; /* allow for up to 20 actions */
1007 int threadIndex[20];
1008 int threadCount = 0;
1009 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1010 unsigned int threadID = 0;
1011 struct dbg_thread* thd;
1013 /* basic check */
1014 assert(gdbctx->in_packet_len >= 4);
1016 /* OK we have vCont followed by..
1017 * ? for query
1018 * c for packet_continue
1019 * Csig for packet_continue_signal
1020 * s for step
1021 * Ssig for step signal
1022 * and then an optional thread ID at the end..
1023 * *******************************************/
1025 fprintf(stderr, "trying to process a verbose packet\n");
1026 /* now check that we've got Cont */
1027 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
1029 /* Query */
1030 if (gdbctx->in_packet[4] == '?')
1033 Reply:
1034 `vCont[;action]...'
1035 The vCont packet is supported. Each action is a supported command in the vCont packet.
1037 The vCont packet is not supported. (this didn't seem to be obeyed!)
1039 packet_reply_open(gdbctx);
1040 packet_reply_add(gdbctx, "vCont", 5);
1041 /* add all the supported actions to the reply (all of them for now) */
1042 packet_reply_add(gdbctx, ";c", 2);
1043 packet_reply_add(gdbctx, ";C", 2);
1044 packet_reply_add(gdbctx, ";s", 2);
1045 packet_reply_add(gdbctx, ";S", 2);
1046 packet_reply_close(gdbctx);
1047 return packet_done;
1050 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1051 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1052 now if only gdb talked XML.... */
1053 #if 0 /* handy for debugging */
1054 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1055 #endif
1057 /* go through the packet and identify where all the actions start at */
1058 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1060 if (gdbctx->in_packet[i] == ';')
1062 threadIndex[actions] = 0;
1063 actionIndex[actions++] = i;
1065 else if (gdbctx->in_packet[i] == ':')
1067 threadIndex[actions - 1] = i;
1071 /* now look up the default action */
1072 for (i = 0 ; i < actions; i++)
1074 if (threadIndex[i] == 0)
1076 if (defaultAction != -1)
1078 fprintf(stderr,"Too many default actions specified\n");
1079 return packet_error;
1081 defaultAction = i;
1085 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1087 /* go through all the threads and stick their ids in the to be done list. */
1088 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1090 threadIDs[threadCount++] = thd->tid;
1091 /* check to see if we have more threads than I counted on, and tell the user what to do
1092 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1093 if (threadCount == 100)
1095 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1096 break;
1100 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1101 * that remains is to apply the actions to the threads and the default action to any threads
1102 * left */
1103 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1104 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1105 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1106 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1108 /* deal with the threaded stuff first */
1109 for (i = 0; i < actions ; i++)
1111 if (threadIndex[i] != 0)
1113 int j, idLength = 0;
1114 if (i < actions - 1)
1116 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1118 else
1120 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1123 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1124 /* process the action */
1125 switch (gdbctx->in_packet[actionIndex[i] + 1])
1127 case 's': /* step */
1128 be_cpu->single_step(&gdbctx->context, TRUE);
1129 /* fall through*/
1130 case 'c': /* continue */
1131 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1132 break;
1133 case 'S': /* step Sig, */
1134 be_cpu->single_step(&gdbctx->context, TRUE);
1135 /* fall through */
1136 case 'C': /* continue sig */
1137 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1138 /* cannot change signals on the fly */
1139 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1140 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1141 if (sig != gdbctx->last_sig)
1142 return packet_error;
1143 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1144 break;
1146 for (j = 0 ; j < threadCount; j++)
1148 if (threadIDs[j] == threadID)
1150 threadIDs[j] = 0;
1151 break;
1155 } /* for i=0 ; i< actions */
1157 /* now we have manage the default action */
1158 if (defaultAction >= 0)
1160 for (i = 0 ; i< threadCount; i++)
1162 /* check to see if we've already done something to the thread*/
1163 if (threadIDs[i] != 0)
1165 /* if not apply the default action*/
1166 threadID = threadIDs[i];
1167 /* process the action (yes this is almost identical to the one above!) */
1168 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1170 case 's': /* step */
1171 be_cpu->single_step(&gdbctx->context, TRUE);
1172 /* fall through */
1173 case 'c': /* continue */
1174 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1175 break;
1176 case 'S':
1177 be_cpu->single_step(&gdbctx->context, TRUE);
1178 /* fall through */
1179 case 'C': /* continue sig */
1180 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1181 /* cannot change signals on the fly */
1182 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1183 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1184 if (sig != gdbctx->last_sig)
1185 return packet_error;
1186 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1187 break;
1191 } /* if(defaultAction >=0) */
1193 wait_for_debuggee(gdbctx);
1194 be_cpu->single_step(&gdbctx->context, FALSE);
1195 return packet_reply_status(gdbctx);
1198 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1200 unsigned char sig;
1202 /* FIXME: add support for address in packet */
1203 assert(gdbctx->in_packet_len == 2);
1204 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1205 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1206 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1207 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1208 hex_from(&sig, gdbctx->in_packet, 1);
1209 /* cannot change signals on the fly */
1210 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1211 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1212 if (sig != gdbctx->last_sig)
1213 return packet_error;
1214 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1215 wait_for_debuggee(gdbctx);
1216 return packet_reply_status(gdbctx);
1219 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1221 detach_debuggee(gdbctx, FALSE);
1222 return packet_ok | packet_last_f;
1225 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1227 int i;
1228 CONTEXT ctx;
1229 CONTEXT* pctx = &gdbctx->context;
1231 assert(gdbctx->in_trap);
1233 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1235 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1236 return packet_error;
1239 packet_reply_open(gdbctx);
1240 for (i = 0; i < cpu_num_regs; i++)
1242 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1244 packet_reply_close(gdbctx);
1245 return packet_done;
1248 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1250 unsigned i;
1251 CONTEXT ctx;
1252 CONTEXT* pctx = &gdbctx->context;
1254 assert(gdbctx->in_trap);
1255 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1257 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1258 return packet_error;
1260 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1262 for (i = 0; i < cpu_num_regs; i++)
1263 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1264 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1266 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1267 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1268 return packet_error;
1270 return packet_ok;
1273 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1275 detach_debuggee(gdbctx, TRUE);
1276 #if 0
1277 if (!gdbctx->extended)
1278 /* dunno whether GDB cares or not */
1279 #endif
1280 wait(NULL);
1281 exit(0);
1282 /* assume we can't really answer something here */
1283 /* return packet_done; */
1286 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1288 char* end;
1289 unsigned thread;
1291 switch (gdbctx->in_packet[0])
1293 case 'c':
1294 case 'g':
1295 if (gdbctx->in_packet[1] == '-')
1296 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1297 else
1298 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1299 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1301 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1302 fprintf(stderr, "Cannot get threadid %*.*s\n",
1303 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1304 gdbctx->in_packet + 1);
1305 return packet_error;
1307 if (gdbctx->in_packet[0] == 'c')
1308 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1309 else
1310 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1311 return packet_ok;
1312 default:
1313 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1314 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1315 return packet_error;
1319 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1321 char *addr;
1322 unsigned int len, blk_len, nread;
1323 char buffer[32];
1324 SIZE_T r = 0;
1326 assert(gdbctx->in_trap);
1327 /* FIXME:check in_packet_len for reading %p,%x */
1328 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1329 if (len <= 0) return packet_error;
1330 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1331 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1332 for (nread = 0; nread < len; nread += r, addr += r)
1334 blk_len = min(sizeof(buffer), len - nread);
1335 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1336 r == 0)
1338 /* fail at first address, return error */
1339 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1340 /* something has already been read, return partial information */
1341 break;
1343 if (nread == 0) packet_reply_open(gdbctx);
1344 packet_reply_hex_to(gdbctx, buffer, r);
1346 packet_reply_close(gdbctx);
1347 return packet_done;
1350 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1352 char* addr;
1353 unsigned int len, blk_len;
1354 char* ptr;
1355 char buffer[32];
1356 SIZE_T w;
1358 assert(gdbctx->in_trap);
1359 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1360 if (ptr == NULL)
1362 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1363 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1364 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1365 return packet_error;
1367 *ptr++ = '\0';
1369 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1371 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1372 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1373 return packet_error;
1375 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1377 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1378 fprintf(stderr, "Wrong sizes %u <> %u\n",
1379 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1380 return packet_error;
1382 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1383 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1384 while (len > 0)
1386 blk_len = min(sizeof(buffer), len);
1387 hex_from(buffer, ptr, blk_len);
1388 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1389 w != blk_len)
1390 break;
1391 addr += blk_len;
1392 len -= blk_len;
1393 ptr += blk_len;
1395 return packet_ok; /* FIXME: error while writing ? */
1398 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1400 unsigned reg;
1401 CONTEXT ctx;
1402 CONTEXT* pctx = &gdbctx->context;
1404 assert(gdbctx->in_trap);
1405 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1406 if (reg >= cpu_num_regs)
1408 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1409 fprintf(stderr, "Register out of bounds %x\n", reg);
1410 return packet_error;
1412 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1414 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1415 return packet_error;
1417 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1418 fprintf(stderr, "Read register %x => %lx\n", reg, *cpu_register(pctx, reg));
1419 packet_reply_open(gdbctx);
1420 packet_reply_hex_to(gdbctx, cpu_register(pctx, reg), 4);
1421 packet_reply_close(gdbctx);
1422 return packet_done;
1425 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1427 unsigned reg;
1428 char* ptr;
1429 char* end;
1430 CONTEXT ctx;
1431 CONTEXT* pctx = &gdbctx->context;
1433 assert(gdbctx->in_trap);
1435 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1436 *ptr++ = '\0';
1437 reg = strtoul(gdbctx->in_packet, &end, 16);
1438 if (end == NULL || reg > cpu_num_regs)
1440 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1441 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1442 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1443 * it wouldn't matter too much, and it fakes our support for all regs
1445 return (end == NULL) ? packet_error : packet_ok;
1447 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1449 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1450 fprintf(stderr, "Wrong sizes %u <> %u\n",
1451 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1452 return packet_error;
1454 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1455 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1456 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1457 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1459 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1461 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1462 return packet_error;
1465 hex_from(cpu_register(pctx, reg), ptr, 4);
1466 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1468 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1469 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1470 return packet_error;
1473 return packet_ok;
1476 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1478 char buffer[128];
1479 char clsName[128];
1480 char wndName[128];
1481 HWND child;
1483 do {
1484 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1485 strcpy(clsName, "-- Unknown --");
1486 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1487 strcpy(wndName, "-- Empty --");
1489 packet_reply_open(gdbctx);
1490 packet_reply_catc(gdbctx, 'O');
1491 snprintf(buffer, sizeof(buffer),
1492 "%*s%04lx%*s%-17.17s %08x %08x %.14s\n",
1493 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1494 clsName, GetWindowLong(hWnd, GWL_STYLE),
1495 GetWindowLongPtr(hWnd, GWLP_WNDPROC), wndName);
1496 packet_reply_hex_to_str(gdbctx, buffer);
1497 packet_reply_close(gdbctx);
1499 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1500 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1501 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1504 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1506 char buffer[128];
1508 /* we do the output in several 'O' packets, with the last one being just OK for
1509 * marking the end of the output */
1510 packet_reply_open(gdbctx);
1511 packet_reply_catc(gdbctx, 'O');
1512 snprintf(buffer, sizeof(buffer),
1513 "%-16.16s %-17.17s %-8.8s %s\n",
1514 "hwnd", "Class Name", " Style", " WndProc Text");
1515 packet_reply_hex_to_str(gdbctx, buffer);
1516 packet_reply_close(gdbctx);
1518 /* FIXME: could also add a pmt to this command in str... */
1519 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1520 packet_reply(gdbctx, "OK", 2);
1523 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1525 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1526 char buffer[128];
1527 char deco;
1528 PROCESSENTRY32 entry;
1529 BOOL ok;
1531 if (snap == INVALID_HANDLE_VALUE)
1532 return;
1534 entry.dwSize = sizeof(entry);
1535 ok = Process32First(snap, &entry);
1537 /* we do the output in several 'O' packets, with the last one being just OK for
1538 * marking the end of the output */
1540 packet_reply_open(gdbctx);
1541 packet_reply_catc(gdbctx, 'O');
1542 snprintf(buffer, sizeof(buffer),
1543 " %-8.8s %-8.8s %-8.8s %s\n",
1544 "pid", "threads", "parent", "executable");
1545 packet_reply_hex_to_str(gdbctx, buffer);
1546 packet_reply_close(gdbctx);
1548 while (ok)
1550 deco = ' ';
1551 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1552 packet_reply_open(gdbctx);
1553 packet_reply_catc(gdbctx, 'O');
1554 snprintf(buffer, sizeof(buffer),
1555 "%c%08x %-8d %08x '%s'\n",
1556 deco, entry.th32ProcessID, entry.cntThreads,
1557 entry.th32ParentProcessID, entry.szExeFile);
1558 packet_reply_hex_to_str(gdbctx, buffer);
1559 packet_reply_close(gdbctx);
1560 ok = Process32Next(snap, &entry);
1562 CloseHandle(snap);
1563 packet_reply(gdbctx, "OK", 2);
1566 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1568 MEMORY_BASIC_INFORMATION mbi;
1569 char* addr = 0;
1570 const char* state;
1571 const char* type;
1572 char prot[3+1];
1573 char buffer[128];
1575 /* we do the output in several 'O' packets, with the last one being just OK for
1576 * marking the end of the output */
1577 packet_reply_open(gdbctx);
1578 packet_reply_catc(gdbctx, 'O');
1579 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1580 packet_reply_close(gdbctx);
1582 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1584 switch (mbi.State)
1586 case MEM_COMMIT: state = "commit "; break;
1587 case MEM_FREE: state = "free "; break;
1588 case MEM_RESERVE: state = "reserve"; break;
1589 default: state = "??? "; break;
1591 if (mbi.State != MEM_FREE)
1593 switch (mbi.Type)
1595 case MEM_IMAGE: type = "image "; break;
1596 case MEM_MAPPED: type = "mapped "; break;
1597 case MEM_PRIVATE: type = "private"; break;
1598 case 0: type = " "; break;
1599 default: type = "??? "; break;
1601 memset(prot, ' ' , sizeof(prot)-1);
1602 prot[sizeof(prot)-1] = '\0';
1603 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1604 prot[0] = 'R';
1605 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1606 prot[1] = 'W';
1607 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1608 prot[1] = 'C';
1609 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1610 prot[2] = 'X';
1612 else
1614 type = "";
1615 prot[0] = '\0';
1617 packet_reply_open(gdbctx);
1618 snprintf(buffer, sizeof(buffer), "%08lx %08lx %s %s %s\n",
1619 (DWORD_PTR)addr, mbi.RegionSize, state, type, prot);
1620 packet_reply_catc(gdbctx, 'O');
1621 packet_reply_hex_to_str(gdbctx, buffer);
1622 packet_reply_close(gdbctx);
1624 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1625 break;
1626 addr += mbi.RegionSize;
1628 packet_reply(gdbctx, "OK", 2);
1631 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1632 int len, const char* str)
1634 char buffer[128];
1636 if (len == 0)
1638 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1640 else if (len >= 2 && str[0] == '=')
1642 unsigned val = atoi(&str[1]);
1643 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1644 gdbctx->trace = val;
1646 else
1648 /* FIXME: ugly but can use error packet here */
1649 packet_reply_cat(gdbctx, "E00");
1650 return;
1652 packet_reply_open(gdbctx);
1653 packet_reply_hex_to_str(gdbctx, buffer);
1654 packet_reply_close(gdbctx);
1657 struct query_detail
1659 int with_arg;
1660 const char* name;
1661 size_t len;
1662 void (*handler)(struct gdb_context*, int, const char*);
1663 } query_details[] =
1665 {0, "wnd", 3, packet_query_monitor_wnd},
1666 {0, "window", 6, packet_query_monitor_wnd},
1667 {0, "proc", 4, packet_query_monitor_process},
1668 {0, "process", 7, packet_query_monitor_process},
1669 {0, "mem", 3, packet_query_monitor_mem},
1670 {1, "trace", 5, packet_query_monitor_trace},
1671 {0, NULL, 0, NULL},
1674 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1675 const char* hxcmd, size_t len)
1677 char buffer[128];
1678 struct query_detail* qd;
1680 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1681 len /= 2;
1682 hex_from(buffer, hxcmd, len);
1684 for (qd = &query_details[0]; qd->name != NULL; qd++)
1686 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1687 if (!qd->with_arg && len != qd->len) continue;
1689 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1690 return packet_done;
1692 return packet_reply_error(gdbctx, EINVAL);
1695 static enum packet_return packet_query(struct gdb_context* gdbctx)
1697 switch (gdbctx->in_packet[0])
1699 case 'f':
1700 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1702 struct dbg_thread* thd;
1704 packet_reply_open(gdbctx);
1705 packet_reply_add(gdbctx, "m", 1);
1706 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1708 packet_reply_val(gdbctx, thd->tid, 4);
1709 if (thd->next != NULL)
1710 packet_reply_add(gdbctx, ",", 1);
1712 packet_reply_close(gdbctx);
1713 return packet_done;
1715 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1717 char result[128];
1719 packet_reply_open(gdbctx);
1720 packet_reply_catc(gdbctx, 'O');
1721 get_process_info(gdbctx, result, sizeof(result));
1722 packet_reply_hex_to_str(gdbctx, result);
1723 packet_reply_close(gdbctx);
1724 return packet_done;
1726 break;
1727 case 's':
1728 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1730 packet_reply(gdbctx, "l", 1);
1731 return packet_done;
1733 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1735 packet_reply(gdbctx, "l", 1);
1736 return packet_done;
1738 break;
1739 case 'C':
1740 if (gdbctx->in_packet_len == 1)
1742 struct dbg_thread* thd;
1743 /* FIXME: doc says 16 bit val ??? */
1744 /* grab first created thread, aka last in list */
1745 assert(gdbctx->process && gdbctx->process->threads);
1746 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1747 packet_reply_open(gdbctx);
1748 packet_reply_add(gdbctx, "QC", 2);
1749 packet_reply_val(gdbctx, thd->tid, 4);
1750 packet_reply_close(gdbctx);
1751 return packet_done;
1753 break;
1754 case 'O':
1755 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1757 char buf[64];
1759 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1760 gdbctx->wine_segs[2] == 0)
1761 return packet_error;
1762 snprintf(buf, sizeof(buf),
1763 "Text=%08lx;Data=%08lx;Bss=%08lx",
1764 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1765 gdbctx->wine_segs[2]);
1766 return packet_reply(gdbctx, buf, -1);
1768 break;
1769 case 'R':
1770 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1772 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1773 gdbctx->in_packet_len - 5);
1775 break;
1776 case 'S':
1777 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1778 return packet_ok;
1779 if (strncmp(gdbctx->in_packet, "Supported", gdbctx->in_packet_len) == 0)
1781 packet_reply_open(gdbctx);
1782 packet_reply_close(gdbctx);
1783 return packet_done;
1785 break;
1786 case 'T':
1787 if (gdbctx->in_packet_len > 15 &&
1788 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1789 gdbctx->in_packet[15] == ',')
1791 unsigned tid;
1792 char* end;
1793 char result[128];
1795 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1796 if (end == NULL) break;
1797 get_thread_info(gdbctx, tid, result, sizeof(result));
1798 packet_reply_open(gdbctx);
1799 packet_reply_hex_to_str(gdbctx, result);
1800 packet_reply_close(gdbctx);
1801 return packet_done;
1803 break;
1805 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1806 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1807 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1808 return packet_error;
1811 static enum packet_return packet_step(struct gdb_context* gdbctx)
1813 /* FIXME: add support for address in packet */
1814 assert(gdbctx->in_packet_len == 0);
1815 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1816 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1817 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1818 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1819 be_cpu->single_step(&gdbctx->context, TRUE);
1820 resume_debuggee(gdbctx, DBG_CONTINUE);
1821 wait_for_debuggee(gdbctx);
1822 be_cpu->single_step(&gdbctx->context, FALSE);
1823 return packet_reply_status(gdbctx);
1826 #if 0
1827 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1829 unsigned char sig;
1831 /* FIXME: add support for address in packet */
1832 assert(gdbctx->in_packet_len == 2);
1833 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1834 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1835 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1836 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1837 hex_from(&sig, gdbctx->in_packet, 1);
1838 /* cannot change signals on the fly */
1839 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1840 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1841 if (sig != gdbctx->last_sig)
1842 return packet_error;
1843 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1844 wait_for_debuggee(gdbctx);
1845 return packet_reply_status(gdbctx);
1847 #endif
1849 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1851 char* end;
1852 unsigned tid;
1854 tid = strtol(gdbctx->in_packet, &end, 16);
1855 if (tid == -1 || tid == 0)
1856 return packet_reply_error(gdbctx, EINVAL);
1857 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1858 return packet_ok;
1859 return packet_reply_error(gdbctx, ESRCH);
1862 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1864 void* addr;
1865 unsigned len;
1866 struct gdb_ctx_Xpoint* xpt;
1867 enum be_xpoint_type t;
1869 /* FIXME: check packet_len */
1870 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1871 gdbctx->in_packet[1] != ',' ||
1872 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1873 return packet_error;
1874 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1875 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1876 addr, len, gdbctx->in_packet[0]);
1877 switch (gdbctx->in_packet[0])
1879 case '0': t = be_xpoint_break; len = 0; break;
1880 case '1': t = be_xpoint_watch_exec; break;
1881 case '2': t = be_xpoint_watch_read; break;
1882 case '3': t = be_xpoint_watch_write; break;
1883 default: return packet_error;
1885 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1887 if (xpt->addr == addr && xpt->type == t)
1889 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1890 gdbctx->process->process_io, &gdbctx->context,
1891 t, xpt->addr, xpt->val, len))
1893 xpt->type = -1;
1894 return packet_ok;
1896 break;
1899 return packet_error;
1902 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1904 void* addr;
1905 unsigned len;
1906 struct gdb_ctx_Xpoint* xpt;
1907 enum be_xpoint_type t;
1909 /* FIXME: check packet_len */
1910 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1911 gdbctx->in_packet[1] != ',' ||
1912 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1913 return packet_error;
1914 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1915 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1916 addr, len, gdbctx->in_packet[0]);
1917 switch (gdbctx->in_packet[0])
1919 case '0': t = be_xpoint_break; len = 0; break;
1920 case '1': t = be_xpoint_watch_exec; break;
1921 case '2': t = be_xpoint_watch_read; break;
1922 case '3': t = be_xpoint_watch_write; break;
1923 default: return packet_error;
1925 /* because of packet command handling, this should be made idempotent */
1926 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1928 if (xpt->addr == addr && xpt->type == t)
1929 return packet_ok; /* nothing to do */
1931 /* really set the Xpoint */
1932 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1934 if (xpt->type == -1)
1936 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1937 gdbctx->process->process_io, &gdbctx->context,
1938 t, addr, &xpt->val, len))
1940 xpt->addr = addr;
1941 xpt->type = t;
1942 return packet_ok;
1944 fprintf(stderr, "cannot set xpoint\n");
1945 break;
1948 /* no more entries... eech */
1949 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1950 return packet_error;
1953 /* =============================================== *
1954 * P A C K E T I N F R A S T R U C T U R E *
1955 * =============================================== *
1958 struct packet_entry
1960 char key;
1961 enum packet_return (*handler)(struct gdb_context* gdbctx);
1964 static struct packet_entry packet_entries[] =
1966 /*{'!', packet_extended}, */
1967 {'?', packet_last_signal},
1968 {'c', packet_continue},
1969 {'C', packet_continue_signal},
1970 {'D', packet_detach},
1971 {'g', packet_read_registers},
1972 {'G', packet_write_registers},
1973 {'k', packet_kill},
1974 {'H', packet_thread},
1975 {'m', packet_read_memory},
1976 {'M', packet_write_memory},
1977 {'p', packet_read_register},
1978 {'P', packet_write_register},
1979 {'q', packet_query},
1980 /* {'Q', packet_set}, */
1981 /* {'R', packet,restart}, only in extended mode ! */
1982 {'s', packet_step},
1983 /*{'S', packet_step_signal}, hard(er) to implement */
1984 {'T', packet_thread_alive},
1985 {'v', packet_verbose},
1986 {'z', packet_remove_breakpoint},
1987 {'Z', packet_set_breakpoint},
1990 static BOOL extract_packets(struct gdb_context* gdbctx)
1992 char* end;
1993 int plen;
1994 unsigned char in_cksum, loc_cksum;
1995 char* ptr;
1996 enum packet_return ret = packet_error;
1997 int num_packet = 0;
1999 while ((ret & packet_last_f) == 0)
2001 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2002 fprintf(stderr, "In-buf: %*.*s\n",
2003 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2004 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2005 if (ptr == NULL) return FALSE;
2006 if (ptr != gdbctx->in_buf)
2008 int glen = ptr - gdbctx->in_buf; /* garbage len */
2009 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2010 fprintf(stderr, "Removing garbage: %*.*s\n",
2011 glen, glen, gdbctx->in_buf);
2012 gdbctx->in_len -= glen;
2013 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2015 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2016 if (end == NULL) return FALSE;
2017 /* no checksum yet */
2018 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2019 plen = end - gdbctx->in_buf - 1;
2020 hex_from(&in_cksum, end + 1, 1);
2021 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2022 if (loc_cksum == in_cksum)
2024 if (num_packet == 0) {
2025 int i;
2027 ret = packet_error;
2029 write(gdbctx->sock, "+", 1);
2030 assert(plen);
2032 /* FIXME: should use bsearch if packet_entries was sorted */
2033 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2035 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2037 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2039 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2040 fprintf(stderr, "Unknown packet request %*.*s\n",
2041 plen, plen, &gdbctx->in_buf[1]);
2043 else
2045 gdbctx->in_packet = gdbctx->in_buf + 2;
2046 gdbctx->in_packet_len = plen - 1;
2047 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2048 fprintf(stderr, "Packet: %c%*.*s\n",
2049 gdbctx->in_buf[1],
2050 gdbctx->in_packet_len, gdbctx->in_packet_len,
2051 gdbctx->in_packet);
2052 ret = (packet_entries[i].handler)(gdbctx);
2054 switch (ret & ~packet_last_f)
2056 case packet_error: packet_reply(gdbctx, "", 0); break;
2057 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2058 case packet_done: break;
2060 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2061 fprintf(stderr, "Reply-full: %*.*s\n",
2062 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2063 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2064 assert(i == gdbctx->out_len);
2065 /* if this fails, we'll have to use POLLOUT...
2067 gdbctx->out_len = 0;
2068 num_packet++;
2070 else
2072 /* FIXME: if we have in our input buffer more than one packet,
2073 * it's very likely that we took too long to answer to a given packet
2074 * and gdb is sending us again the same packet
2075 * We simply drop the second packet. This will lower the risk of error,
2076 * but there's still some race conditions here
2077 * A better fix (yet not perfect) would be to have two threads:
2078 * - one managing the packets for gdb
2079 * - the second one managing the commands...
2080 * This would allow us also the reply with the '+' character (Ack of
2081 * the command) way sooner than what we do now
2083 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2084 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2087 else
2089 write(gdbctx->sock, "+", 1);
2090 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2091 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2093 gdbctx->in_len -= plen + 4;
2094 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2096 return TRUE;
2099 static int fetch_data(struct gdb_context* gdbctx)
2101 int len, in_len = gdbctx->in_len;
2103 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2104 for (;;)
2106 #define STEP 128
2107 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2108 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2109 #undef STEP
2110 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2111 fprintf(stderr, "%d %d %*.*s\n",
2112 gdbctx->in_len, gdbctx->in_buf_alloc,
2113 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2114 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2115 if (len <= 0) break;
2116 gdbctx->in_len += len;
2117 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2118 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2120 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2121 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2122 return gdbctx->in_len - in_len;
2125 #define FLAG_NO_START 1
2126 #define FLAG_WITH_XTERM 2
2128 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2130 char buf[MAX_PATH];
2131 int fd;
2132 const char* gdb_path;
2133 FILE* f;
2135 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2136 strcpy(buf,"/tmp/winegdb.XXXXXX");
2137 fd = mkstemps(buf, 0);
2138 if (fd == -1) return FALSE;
2139 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2140 fprintf(f, "file %s\n", wine_path);
2141 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2142 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2143 fprintf(f, "set prompt Wine-gdb>\\ \n");
2144 /* gdb 5.1 seems to require it, won't hurt anyway */
2145 fprintf(f, "sharedlibrary\n");
2146 /* This is needed (but not a decent & final fix)
2147 * Without this, gdb would skip our inter-DLL relay code (because
2148 * we don't have any line number information for the relay code)
2149 * With this, we will stop on first instruction of the stub, and
2150 * reusing step, will get us through the relay stub at the actual
2151 * function we're looking at.
2153 fprintf(f, "set step-mode on\n");
2154 /* tell gdb to delete this file when done handling it... */
2155 fprintf(f, "shell rm -f \"%s\"\n", buf);
2156 fclose(f);
2157 if (flags & FLAG_WITH_XTERM)
2158 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2159 else
2160 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2161 assert(0); /* never reached */
2162 return TRUE;
2165 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2167 int sock;
2168 struct sockaddr_in s_addrs;
2169 unsigned int s_len = sizeof(s_addrs);
2170 struct pollfd pollfd;
2171 IMAGEHLP_MODULE imh_mod;
2173 /* step 1: create socket for gdb connection request */
2174 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2176 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2177 fprintf(stderr, "Can't create socket");
2178 return FALSE;
2181 if (listen(sock, 1) == -1 ||
2182 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2183 return FALSE;
2185 /* step 2: do the process internal creation */
2186 handle_debug_event(gdbctx, de);
2188 /* step3: get the wine loader name */
2189 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2191 /* step 4: fire up gdb (if requested) */
2192 if (flags & FLAG_NO_START)
2193 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2194 else
2195 switch (fork())
2197 case -1: /* error in parent... */
2198 fprintf(stderr, "Cannot create gdb\n");
2199 return FALSE;
2200 default: /* in parent... success */
2201 break;
2202 case 0: /* in child... and alive */
2203 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2204 /* if we're here, exec failed, so report failure */
2205 return FALSE;
2208 /* step 5: wait for gdb to connect actually */
2209 pollfd.fd = sock;
2210 pollfd.events = POLLIN;
2211 pollfd.revents = 0;
2213 switch (poll(&pollfd, 1, -1))
2215 case 1:
2216 if (pollfd.revents & POLLIN)
2218 int dummy = 1;
2219 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2220 if (gdbctx->sock == -1)
2221 break;
2222 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2223 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2224 /* don't keep our small packets too long: send them ASAP back to GDB
2225 * without this, GDB really crawls
2227 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2229 break;
2230 case 0:
2231 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2232 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2233 return FALSE;
2234 case -1:
2235 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2236 fprintf(stderr, "Poll for cnx failed (error)\n");
2237 return FALSE;
2238 default:
2239 assert(0);
2242 close(sock);
2243 return TRUE;
2246 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2248 DEBUG_EVENT de;
2249 int i;
2251 gdbctx->sock = -1;
2252 gdbctx->in_buf = NULL;
2253 gdbctx->in_buf_alloc = 0;
2254 gdbctx->in_len = 0;
2255 gdbctx->out_buf = NULL;
2256 gdbctx->out_buf_alloc = 0;
2257 gdbctx->out_len = 0;
2258 gdbctx->out_curr_packet = -1;
2260 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2261 gdbctx->last_sig = 0;
2262 gdbctx->in_trap = FALSE;
2263 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2264 gdbctx->process = NULL;
2265 for (i = 0; i < NUM_XPOINT; i++)
2266 gdbctx->Xpoints[i].type = -1;
2268 /* wait for first trap */
2269 while (WaitForDebugEvent(&de, INFINITE))
2271 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2273 /* this should be the first event we get,
2274 * and the only one of this type */
2275 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2276 /* gdbctx->dwProcessId = pid; */
2277 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2278 assert(!gdbctx->in_trap);
2280 else
2282 handle_debug_event(gdbctx, &de);
2283 if (gdbctx->in_trap) break;
2285 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2287 return TRUE;
2290 static int gdb_remote(unsigned flags)
2292 struct pollfd pollfd;
2293 struct gdb_context gdbctx;
2294 BOOL doLoop;
2296 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2298 pollfd.fd = gdbctx.sock;
2299 pollfd.events = POLLIN;
2300 pollfd.revents = 0;
2302 switch (poll(&pollfd, 1, -1))
2304 case 1:
2305 /* got something */
2306 if (pollfd.revents & (POLLHUP | POLLERR))
2308 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2309 fprintf(stderr, "Gdb hung up\n");
2310 /* kill also debuggee process - questionnable - */
2311 detach_debuggee(&gdbctx, TRUE);
2312 doLoop = FALSE;
2313 break;
2315 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2317 if (extract_packets(&gdbctx)) doLoop = FALSE;
2319 break;
2320 case 0:
2321 /* timeout, should never happen (infinite timeout) */
2322 break;
2323 case -1:
2324 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2325 fprintf(stderr, "Poll failed\n");
2326 doLoop = FALSE;
2327 break;
2330 wait(NULL);
2331 return 0;
2333 #endif
2335 int gdb_main(int argc, char* argv[])
2337 #ifdef HAVE_POLL
2338 unsigned gdb_flags = 0;
2340 argc--; argv++;
2341 while (argc > 0 && argv[0][0] == '-')
2343 if (strcmp(argv[0], "--no-start") == 0)
2345 gdb_flags |= FLAG_NO_START;
2346 argc--; argv++;
2347 continue;
2349 if (strcmp(argv[0], "--with-xterm") == 0)
2351 gdb_flags |= FLAG_WITH_XTERM;
2352 argc--; argv++;
2353 continue;
2355 return -1;
2357 if (dbg_active_attach(argc, argv) == start_ok ||
2358 dbg_active_launch(argc, argv) == start_ok)
2359 return gdb_remote(gdb_flags);
2360 #else
2361 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2362 #endif
2363 return -1;