new 818051de2c8769029049ce3d36c6b856f47496c9
[wine/hacks.git] / programs / winedbg / gdbproxy.c
blob4f83c72941f27f222247cb79dee93561d0b26236
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 /* =============================================== *
117 * B A S I C M A N I P U L A T I O N S *
118 * =============================================== *
121 static inline int hex_from0(char ch)
123 if (ch >= '0' && ch <= '9') return ch - '0';
124 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
125 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
127 assert(0);
128 return 0;
131 static inline unsigned char hex_to0(int x)
133 assert(x >= 0 && x < 16);
134 return "0123456789abcdef"[x];
137 static int hex_to_int(const char* src, size_t len)
139 unsigned int returnval = 0;
140 while (len--)
142 returnval <<= 4;
143 returnval |= hex_from0(*src++);
145 return returnval;
148 static void hex_from(void* dst, const char* src, size_t len)
150 unsigned char *p = dst;
151 while (len--)
153 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
154 src += 2;
158 static void hex_to(char* dst, const void* src, size_t len)
160 const unsigned char *p = src;
161 while (len--)
163 *dst++ = hex_to0(*p >> 4);
164 *dst++ = hex_to0(*p & 0x0F);
165 p++;
169 static unsigned char checksum(const char* ptr, int len)
171 unsigned cksum = 0;
173 while (len-- > 0)
174 cksum += (unsigned char)*ptr++;
175 return cksum;
178 /* =============================================== *
179 * C P U H A N D L E R S *
180 * =============================================== *
183 #ifdef __i386__
184 static size_t cpu_register_map[] = {
185 FIELD_OFFSET(CONTEXT, Eax),
186 FIELD_OFFSET(CONTEXT, Ecx),
187 FIELD_OFFSET(CONTEXT, Edx),
188 FIELD_OFFSET(CONTEXT, Ebx),
189 FIELD_OFFSET(CONTEXT, Esp),
190 FIELD_OFFSET(CONTEXT, Ebp),
191 FIELD_OFFSET(CONTEXT, Esi),
192 FIELD_OFFSET(CONTEXT, Edi),
193 FIELD_OFFSET(CONTEXT, Eip),
194 FIELD_OFFSET(CONTEXT, EFlags),
195 FIELD_OFFSET(CONTEXT, SegCs),
196 FIELD_OFFSET(CONTEXT, SegSs),
197 FIELD_OFFSET(CONTEXT, SegDs),
198 FIELD_OFFSET(CONTEXT, SegEs),
199 FIELD_OFFSET(CONTEXT, SegFs),
200 FIELD_OFFSET(CONTEXT, SegGs),
202 #elif defined(__powerpc__)
203 static size_t cpu_register_map[] = {
204 FIELD_OFFSET(CONTEXT, Gpr0),
205 FIELD_OFFSET(CONTEXT, Gpr1),
206 FIELD_OFFSET(CONTEXT, Gpr2),
207 FIELD_OFFSET(CONTEXT, Gpr3),
208 FIELD_OFFSET(CONTEXT, Gpr4),
209 FIELD_OFFSET(CONTEXT, Gpr5),
210 FIELD_OFFSET(CONTEXT, Gpr6),
211 FIELD_OFFSET(CONTEXT, Gpr7),
212 FIELD_OFFSET(CONTEXT, Gpr8),
213 FIELD_OFFSET(CONTEXT, Gpr9),
214 FIELD_OFFSET(CONTEXT, Gpr10),
215 FIELD_OFFSET(CONTEXT, Gpr11),
216 FIELD_OFFSET(CONTEXT, Gpr12),
217 FIELD_OFFSET(CONTEXT, Gpr13),
218 FIELD_OFFSET(CONTEXT, Gpr14),
219 FIELD_OFFSET(CONTEXT, Gpr15),
220 FIELD_OFFSET(CONTEXT, Gpr16),
221 FIELD_OFFSET(CONTEXT, Gpr17),
222 FIELD_OFFSET(CONTEXT, Gpr18),
223 FIELD_OFFSET(CONTEXT, Gpr19),
224 FIELD_OFFSET(CONTEXT, Gpr20),
225 FIELD_OFFSET(CONTEXT, Gpr21),
226 FIELD_OFFSET(CONTEXT, Gpr22),
227 FIELD_OFFSET(CONTEXT, Gpr23),
228 FIELD_OFFSET(CONTEXT, Gpr24),
229 FIELD_OFFSET(CONTEXT, Gpr25),
230 FIELD_OFFSET(CONTEXT, Gpr26),
231 FIELD_OFFSET(CONTEXT, Gpr27),
232 FIELD_OFFSET(CONTEXT, Gpr28),
233 FIELD_OFFSET(CONTEXT, Gpr29),
234 FIELD_OFFSET(CONTEXT, Gpr30),
235 FIELD_OFFSET(CONTEXT, Gpr31),
236 FIELD_OFFSET(CONTEXT, Fpr0),
237 FIELD_OFFSET(CONTEXT, Fpr1),
238 FIELD_OFFSET(CONTEXT, Fpr2),
239 FIELD_OFFSET(CONTEXT, Fpr3),
240 FIELD_OFFSET(CONTEXT, Fpr4),
241 FIELD_OFFSET(CONTEXT, Fpr5),
242 FIELD_OFFSET(CONTEXT, Fpr6),
243 FIELD_OFFSET(CONTEXT, Fpr7),
244 FIELD_OFFSET(CONTEXT, Fpr8),
245 FIELD_OFFSET(CONTEXT, Fpr9),
246 FIELD_OFFSET(CONTEXT, Fpr10),
247 FIELD_OFFSET(CONTEXT, Fpr11),
248 FIELD_OFFSET(CONTEXT, Fpr12),
249 FIELD_OFFSET(CONTEXT, Fpr13),
250 FIELD_OFFSET(CONTEXT, Fpr14),
251 FIELD_OFFSET(CONTEXT, Fpr15),
252 FIELD_OFFSET(CONTEXT, Fpr16),
253 FIELD_OFFSET(CONTEXT, Fpr17),
254 FIELD_OFFSET(CONTEXT, Fpr18),
255 FIELD_OFFSET(CONTEXT, Fpr19),
256 FIELD_OFFSET(CONTEXT, Fpr20),
257 FIELD_OFFSET(CONTEXT, Fpr21),
258 FIELD_OFFSET(CONTEXT, Fpr22),
259 FIELD_OFFSET(CONTEXT, Fpr23),
260 FIELD_OFFSET(CONTEXT, Fpr24),
261 FIELD_OFFSET(CONTEXT, Fpr25),
262 FIELD_OFFSET(CONTEXT, Fpr26),
263 FIELD_OFFSET(CONTEXT, Fpr27),
264 FIELD_OFFSET(CONTEXT, Fpr28),
265 FIELD_OFFSET(CONTEXT, Fpr29),
266 FIELD_OFFSET(CONTEXT, Fpr30),
267 FIELD_OFFSET(CONTEXT, Fpr31),
269 FIELD_OFFSET(CONTEXT, Iar),
270 FIELD_OFFSET(CONTEXT, Msr),
271 FIELD_OFFSET(CONTEXT, Cr),
272 FIELD_OFFSET(CONTEXT, Lr),
273 FIELD_OFFSET(CONTEXT, Ctr),
274 FIELD_OFFSET(CONTEXT, Xer),
275 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
276 /* see gdb/nlm/ppc.c */
278 #elif defined(__ALPHA__)
279 static size_t cpu_register_map[] = {
280 FIELD_OFFSET(CONTEXT, IntV0),
281 FIELD_OFFSET(CONTEXT, IntT0),
282 FIELD_OFFSET(CONTEXT, IntT1),
283 FIELD_OFFSET(CONTEXT, IntT2),
284 FIELD_OFFSET(CONTEXT, IntT3),
285 FIELD_OFFSET(CONTEXT, IntT4),
286 FIELD_OFFSET(CONTEXT, IntT5),
287 FIELD_OFFSET(CONTEXT, IntT6),
288 FIELD_OFFSET(CONTEXT, IntT7),
289 FIELD_OFFSET(CONTEXT, IntS0),
290 FIELD_OFFSET(CONTEXT, IntS1),
291 FIELD_OFFSET(CONTEXT, IntS2),
292 FIELD_OFFSET(CONTEXT, IntS3),
293 FIELD_OFFSET(CONTEXT, IntS4),
294 FIELD_OFFSET(CONTEXT, IntS5),
295 FIELD_OFFSET(CONTEXT, IntFp),
296 FIELD_OFFSET(CONTEXT, IntA0),
297 FIELD_OFFSET(CONTEXT, IntA1),
298 FIELD_OFFSET(CONTEXT, IntA2),
299 FIELD_OFFSET(CONTEXT, IntA3),
300 FIELD_OFFSET(CONTEXT, IntA4),
301 FIELD_OFFSET(CONTEXT, IntA5),
302 FIELD_OFFSET(CONTEXT, IntT8),
303 FIELD_OFFSET(CONTEXT, IntT9),
304 FIELD_OFFSET(CONTEXT, IntT10),
305 FIELD_OFFSET(CONTEXT, IntT11),
306 FIELD_OFFSET(CONTEXT, IntRa),
307 FIELD_OFFSET(CONTEXT, IntT12),
308 FIELD_OFFSET(CONTEXT, IntAt),
309 FIELD_OFFSET(CONTEXT, IntGp),
310 FIELD_OFFSET(CONTEXT, IntSp),
311 FIELD_OFFSET(CONTEXT, IntZero),
312 FIELD_OFFSET(CONTEXT, FltF0),
313 FIELD_OFFSET(CONTEXT, FltF1),
314 FIELD_OFFSET(CONTEXT, FltF2),
315 FIELD_OFFSET(CONTEXT, FltF3),
316 FIELD_OFFSET(CONTEXT, FltF4),
317 FIELD_OFFSET(CONTEXT, FltF5),
318 FIELD_OFFSET(CONTEXT, FltF6),
319 FIELD_OFFSET(CONTEXT, FltF7),
320 FIELD_OFFSET(CONTEXT, FltF8),
321 FIELD_OFFSET(CONTEXT, FltF9),
322 FIELD_OFFSET(CONTEXT, FltF10),
323 FIELD_OFFSET(CONTEXT, FltF11),
324 FIELD_OFFSET(CONTEXT, FltF12),
325 FIELD_OFFSET(CONTEXT, FltF13),
326 FIELD_OFFSET(CONTEXT, FltF14),
327 FIELD_OFFSET(CONTEXT, FltF15),
328 FIELD_OFFSET(CONTEXT, FltF16),
329 FIELD_OFFSET(CONTEXT, FltF17),
330 FIELD_OFFSET(CONTEXT, FltF18),
331 FIELD_OFFSET(CONTEXT, FltF19),
332 FIELD_OFFSET(CONTEXT, FltF20),
333 FIELD_OFFSET(CONTEXT, FltF21),
334 FIELD_OFFSET(CONTEXT, FltF22),
335 FIELD_OFFSET(CONTEXT, FltF23),
336 FIELD_OFFSET(CONTEXT, FltF24),
337 FIELD_OFFSET(CONTEXT, FltF25),
338 FIELD_OFFSET(CONTEXT, FltF26),
339 FIELD_OFFSET(CONTEXT, FltF27),
340 FIELD_OFFSET(CONTEXT, FltF28),
341 FIELD_OFFSET(CONTEXT, FltF29),
342 FIELD_OFFSET(CONTEXT, FltF30),
343 FIELD_OFFSET(CONTEXT, FltF31),
345 /* FIXME: Didn't look for the right order yet */
346 FIELD_OFFSET(CONTEXT, Fir),
347 FIELD_OFFSET(CONTEXT, Fpcr),
348 FIELD_OFFSET(CONTEXT, SoftFpcr),
350 #elif defined(__x86_64__)
351 static size_t cpu_register_map[] = {
352 FIELD_OFFSET(CONTEXT, Rax),
353 FIELD_OFFSET(CONTEXT, Rbx),
354 FIELD_OFFSET(CONTEXT, Rcx),
355 FIELD_OFFSET(CONTEXT, Rdx),
356 FIELD_OFFSET(CONTEXT, Rsi),
357 FIELD_OFFSET(CONTEXT, Rdi),
358 FIELD_OFFSET(CONTEXT, Rbp),
359 FIELD_OFFSET(CONTEXT, Rsp),
360 FIELD_OFFSET(CONTEXT, R8),
361 FIELD_OFFSET(CONTEXT, R9),
362 FIELD_OFFSET(CONTEXT, R10),
363 FIELD_OFFSET(CONTEXT, R11),
364 FIELD_OFFSET(CONTEXT, R12),
365 FIELD_OFFSET(CONTEXT, R13),
366 FIELD_OFFSET(CONTEXT, R14),
367 FIELD_OFFSET(CONTEXT, R15),
368 FIELD_OFFSET(CONTEXT, Rip),
369 FIELD_OFFSET(CONTEXT, EFlags),
370 FIELD_OFFSET(CONTEXT, SegCs),
371 FIELD_OFFSET(CONTEXT, SegSs),
372 FIELD_OFFSET(CONTEXT, SegDs),
373 FIELD_OFFSET(CONTEXT, SegEs),
374 FIELD_OFFSET(CONTEXT, SegFs),
375 FIELD_OFFSET(CONTEXT, SegGs),
377 #else
378 # error Define the registers map for your CPU
379 #endif
381 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
383 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
385 assert(idx < cpu_num_regs);
386 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
389 /* =============================================== *
390 * W I N 3 2 D E B U G I N T E R F A C E *
391 * =============================================== *
394 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
396 ctx->ContextFlags = CONTEXT_CONTROL
397 | CONTEXT_INTEGER
398 #ifdef CONTEXT_SEGMENTS
399 | CONTEXT_SEGMENTS
400 #endif
401 #ifdef CONTEXT_DEBUG_REGISTERS
402 | CONTEXT_DEBUG_REGISTERS
403 #endif
405 if (!GetThreadContext(h, ctx))
407 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
408 fprintf(stderr, "Can't get thread's context\n");
409 return FALSE;
411 return TRUE;
414 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
416 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
417 BOOL ret = FALSE;
419 switch (rec->ExceptionCode)
421 case EXCEPTION_ACCESS_VIOLATION:
422 case EXCEPTION_PRIV_INSTRUCTION:
423 case EXCEPTION_STACK_OVERFLOW:
424 case EXCEPTION_GUARD_PAGE:
425 gdbctx->last_sig = SIGSEGV;
426 ret = TRUE;
427 break;
428 case EXCEPTION_DATATYPE_MISALIGNMENT:
429 gdbctx->last_sig = SIGBUS;
430 ret = TRUE;
431 break;
432 case EXCEPTION_SINGLE_STEP:
433 /* fall thru */
434 case EXCEPTION_BREAKPOINT:
435 gdbctx->last_sig = SIGTRAP;
436 ret = TRUE;
437 break;
438 case EXCEPTION_FLT_DENORMAL_OPERAND:
439 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
440 case EXCEPTION_FLT_INEXACT_RESULT:
441 case EXCEPTION_FLT_INVALID_OPERATION:
442 case EXCEPTION_FLT_OVERFLOW:
443 case EXCEPTION_FLT_STACK_CHECK:
444 case EXCEPTION_FLT_UNDERFLOW:
445 gdbctx->last_sig = SIGFPE;
446 ret = TRUE;
447 break;
448 case EXCEPTION_INT_DIVIDE_BY_ZERO:
449 case EXCEPTION_INT_OVERFLOW:
450 gdbctx->last_sig = SIGFPE;
451 ret = TRUE;
452 break;
453 case EXCEPTION_ILLEGAL_INSTRUCTION:
454 gdbctx->last_sig = SIGILL;
455 ret = TRUE;
456 break;
457 case CONTROL_C_EXIT:
458 gdbctx->last_sig = SIGINT;
459 ret = TRUE;
460 break;
461 case STATUS_POSSIBLE_DEADLOCK:
462 gdbctx->last_sig = SIGALRM;
463 ret = TRUE;
464 /* FIXME: we could also add here a O packet with additional information */
465 break;
466 default:
467 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
468 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
469 gdbctx->last_sig = SIGABRT;
470 ret = TRUE;
471 break;
473 return ret;
476 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
478 char buffer[256];
480 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
482 switch (de->dwDebugEventCode)
484 case CREATE_PROCESS_DEBUG_EVENT:
485 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
486 de->u.CreateProcessInfo.hProcess);
487 if (!gdbctx->process) break;
488 memory_get_string_indirect(gdbctx->process,
489 de->u.CreateProcessInfo.lpImageName,
490 de->u.CreateProcessInfo.fUnicode,
491 buffer, sizeof(buffer));
492 dbg_set_process_name(gdbctx->process, buffer);
494 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
495 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
496 de->dwProcessId, de->dwThreadId,
497 buffer, de->u.CreateProcessInfo.lpImageName,
498 de->u.CreateProcessInfo.lpStartAddress,
499 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
500 de->u.CreateProcessInfo.nDebugInfoSize);
502 /* de->u.CreateProcessInfo.lpStartAddress; */
503 if (!SymInitialize(gdbctx->process->handle, NULL, TRUE))
504 fprintf(stderr, "Couldn't initiate DbgHelp\n");
506 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
507 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
508 de->dwProcessId, de->dwThreadId,
509 de->u.CreateProcessInfo.lpStartAddress);
511 assert(dbg_curr_thread == NULL); /* shouldn't be there */
512 dbg_add_thread(gdbctx->process, de->dwThreadId,
513 de->u.CreateProcessInfo.hThread,
514 de->u.CreateProcessInfo.lpThreadLocalBase);
515 break;
517 case LOAD_DLL_DEBUG_EVENT:
518 assert(dbg_curr_thread);
519 memory_get_string_indirect(gdbctx->process,
520 de->u.LoadDll.lpImageName,
521 de->u.LoadDll.fUnicode,
522 buffer, sizeof(buffer));
523 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
524 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
525 de->dwProcessId, de->dwThreadId,
526 buffer, de->u.LoadDll.lpBaseOfDll,
527 de->u.LoadDll.dwDebugInfoFileOffset,
528 de->u.LoadDll.nDebugInfoSize);
529 SymLoadModule(gdbctx->process->handle, de->u.LoadDll.hFile, buffer, NULL,
530 (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
531 break;
533 case UNLOAD_DLL_DEBUG_EVENT:
534 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
535 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
536 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
537 SymUnloadModule(gdbctx->process->handle,
538 (unsigned long)de->u.UnloadDll.lpBaseOfDll);
539 break;
541 case EXCEPTION_DEBUG_EVENT:
542 assert(dbg_curr_thread);
543 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
544 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
545 de->dwProcessId, de->dwThreadId,
546 de->u.Exception.ExceptionRecord.ExceptionCode);
548 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
550 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
552 break;
554 case CREATE_THREAD_DEBUG_EVENT:
555 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
556 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
557 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
559 dbg_add_thread(gdbctx->process,
560 de->dwThreadId,
561 de->u.CreateThread.hThread,
562 de->u.CreateThread.lpThreadLocalBase);
563 break;
565 case EXIT_THREAD_DEBUG_EVENT:
566 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
567 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
568 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
570 assert(dbg_curr_thread);
571 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
572 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
573 dbg_del_thread(dbg_curr_thread);
574 break;
576 case EXIT_PROCESS_DEBUG_EVENT:
577 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
578 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
579 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
581 dbg_del_process(gdbctx->process);
582 gdbctx->process = NULL;
583 /* now signal gdb that we're done */
584 gdbctx->last_sig = SIGTERM;
585 gdbctx->in_trap = TRUE;
586 break;
588 case OUTPUT_DEBUG_STRING_EVENT:
589 assert(dbg_curr_thread);
590 memory_get_string(gdbctx->process,
591 de->u.DebugString.lpDebugStringData, TRUE,
592 de->u.DebugString.fUnicode, buffer, sizeof(buffer));
593 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
594 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
595 de->dwProcessId, de->dwThreadId, buffer);
596 break;
598 case RIP_EVENT:
599 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
600 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
601 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
602 de->u.RipInfo.dwType);
603 break;
605 default:
606 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
607 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
608 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
612 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
614 if (dbg_curr_thread)
616 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
617 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
618 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
619 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
620 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
621 fprintf(stderr, "Cannot continue on %04x (%x)\n",
622 dbg_curr_thread->tid, cont);
624 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
625 fprintf(stderr, "Cannot find last thread\n");
629 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
632 if (dbg_curr_thread)
634 if(dbg_curr_thread->tid == threadid){
635 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
636 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
637 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
638 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
639 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
640 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
641 fprintf(stderr, "Cannot continue on %04x (%x)\n",
642 dbg_curr_thread->tid, cont);
645 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
646 fprintf(stderr, "Cannot find last thread\n");
649 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
651 struct pollfd pollfd;
652 int ret;
653 char pkt;
655 pollfd.fd = gdbctx->sock;
656 pollfd.events = POLLIN;
657 pollfd.revents = 0;
659 if ((ret = poll(&pollfd, 1, 0)) == 1) {
660 ret = read(gdbctx->sock, &pkt, 1);
661 if (ret != 1) {
662 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
663 fprintf(stderr, "read failed\n");
665 return FALSE;
667 if (pkt != '\003') {
668 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
669 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
671 return FALSE;
673 return TRUE;
674 } else if (ret == -1) {
675 fprintf(stderr, "poll failed\n");
677 return FALSE;
680 static void wait_for_debuggee(struct gdb_context* gdbctx)
682 DEBUG_EVENT de;
684 gdbctx->in_trap = FALSE;
685 for (;;)
687 if (!WaitForDebugEvent(&de, 10))
689 if (GetLastError() == ERROR_SEM_TIMEOUT)
691 if (check_for_interrupt(gdbctx)) {
692 if (!DebugBreakProcess(gdbctx->process->handle)) {
693 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
694 fprintf(stderr, "Failed to break into debugee\n");
696 break;
698 WaitForDebugEvent(&de, INFINITE);
699 } else {
700 continue;
702 } else {
703 break;
706 handle_debug_event(gdbctx, &de);
707 assert(!gdbctx->process ||
708 gdbctx->process->pid == 0 ||
709 de.dwProcessId == gdbctx->process->pid);
710 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
711 if (gdbctx->in_trap) break;
712 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
716 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
718 be_cpu->single_step(&gdbctx->context, FALSE);
719 resume_debuggee(gdbctx, DBG_CONTINUE);
720 if (!kill)
721 DebugActiveProcessStop(gdbctx->process->pid);
722 dbg_del_process(gdbctx->process);
723 gdbctx->process = NULL;
726 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
728 DWORD status;
730 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
732 strcpy(buffer, "Unknown process");
733 return;
735 if (status == STILL_ACTIVE)
737 strcpy(buffer, "Running");
739 else
740 snprintf(buffer, len, "Terminated (%u)", status);
742 switch (GetPriorityClass(gdbctx->process->handle))
744 case 0: break;
745 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
746 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
747 #endif
748 #ifdef BELOW_NORMAL_PRIORITY_CLASS
749 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
750 #endif
751 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
752 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
753 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
754 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
756 strcat(buffer, "\n");
759 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
760 char* buffer, size_t len)
762 struct dbg_thread* thd;
763 DWORD status;
764 int prio;
766 /* FIXME: use the size of buffer */
767 thd = dbg_get_thread(gdbctx->process, tid);
768 if (thd == NULL)
770 strcpy(buffer, "No information");
771 return;
773 if (GetExitCodeThread(thd->handle, &status))
775 if (status == STILL_ACTIVE)
777 /* FIXME: this is a bit brutal... some nicer way shall be found */
778 switch (status = SuspendThread(thd->handle))
780 case -1: break;
781 case 0: strcpy(buffer, "Running"); break;
782 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
784 ResumeThread(thd->handle);
786 else
787 snprintf(buffer, len, "Terminated (exit code = %u)", status);
789 else
791 strcpy(buffer, "Unknown threadID");
793 switch (prio = GetThreadPriority(thd->handle))
795 case THREAD_PRIORITY_ERROR_RETURN: break;
796 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
797 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
798 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
799 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
800 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
801 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
802 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
803 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
805 assert(strlen(buffer) < len);
808 /* =============================================== *
809 * P A C K E T U T I L S *
810 * =============================================== *
813 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
814 packet_last_f = 0x80};
816 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
818 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
820 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
821 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
825 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
827 packet_reply_grow(gdbctx, len * 2);
828 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
829 gdbctx->out_len += len * 2;
832 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
834 packet_reply_hex_to(gdbctx, src, strlen(src));
837 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
839 int i, shift;
841 shift = (len - 1) * 8;
842 packet_reply_grow(gdbctx, len * 2);
843 for (i = 0; i < len; i++, shift -= 8)
845 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
846 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
850 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
852 packet_reply_grow(gdbctx, len);
853 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
854 gdbctx->out_len += len;
857 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
859 packet_reply_add(gdbctx, str, strlen(str));
862 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
864 packet_reply_add(gdbctx, &ch, 1);
867 static void packet_reply_open(struct gdb_context* gdbctx)
869 assert(gdbctx->out_curr_packet == -1);
870 packet_reply_catc(gdbctx, '$');
871 gdbctx->out_curr_packet = gdbctx->out_len;
874 static void packet_reply_close(struct gdb_context* gdbctx)
876 unsigned char cksum;
877 int plen;
879 plen = gdbctx->out_len - gdbctx->out_curr_packet;
880 packet_reply_catc(gdbctx, '#');
881 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
882 packet_reply_hex_to(gdbctx, &cksum, 1);
883 if (gdbctx->trace & GDBPXY_TRC_PACKET)
884 fprintf(stderr, "Reply : %*.*s\n",
885 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
886 gdbctx->out_curr_packet = -1;
889 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
891 packet_reply_open(gdbctx);
893 if (len == -1) len = strlen(packet);
894 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
896 packet_reply_add(gdbctx, packet, len);
898 packet_reply_close(gdbctx);
900 return packet_done;
903 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
905 packet_reply_open(gdbctx);
907 packet_reply_add(gdbctx, "E", 1);
908 packet_reply_val(gdbctx, error, 1);
910 packet_reply_close(gdbctx);
912 return packet_done;
915 /* =============================================== *
916 * P A C K E T H A N D L E R S *
917 * =============================================== *
920 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
922 enum packet_return ret = packet_done;
924 packet_reply_open(gdbctx);
926 if (gdbctx->process != NULL)
928 unsigned char sig;
929 unsigned i;
931 packet_reply_catc(gdbctx, 'T');
932 sig = gdbctx->last_sig;
933 packet_reply_val(gdbctx, sig, 1);
934 packet_reply_add(gdbctx, "thread:", 7);
935 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
936 packet_reply_catc(gdbctx, ';');
938 for (i = 0; i < cpu_num_regs; i++)
940 /* FIXME: this call will also grow the buffer...
941 * unneeded, but not harmful
943 packet_reply_val(gdbctx, i, 1);
944 packet_reply_catc(gdbctx, ':');
945 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
946 packet_reply_catc(gdbctx, ';');
949 else
951 /* Try to put an exit code
952 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
953 * just indicate the end of process and exit */
954 packet_reply_add(gdbctx, "W00", 3);
955 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
958 packet_reply_close(gdbctx);
960 return ret;
963 #if 0
964 static enum packet_return packet_extended(struct gdb_context* gdbctx)
966 gdbctx->extended = 1;
967 return packet_ok;
969 #endif
971 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
973 assert(gdbctx->in_packet_len == 0);
974 return packet_reply_status(gdbctx);
977 static enum packet_return packet_continue(struct gdb_context* gdbctx)
979 /* FIXME: add support for address in packet */
980 assert(gdbctx->in_packet_len == 0);
981 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
982 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
983 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
984 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
985 resume_debuggee(gdbctx, DBG_CONTINUE);
986 wait_for_debuggee(gdbctx);
987 return packet_reply_status(gdbctx);
990 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
992 int i;
993 int defaultAction = -1; /* magic non action */
994 unsigned char sig;
995 int actions =0;
996 int actionIndex[20]; /* allow for up to 20 actions */
997 int threadIndex[20];
998 int threadCount = 0;
999 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1000 unsigned int threadID = 0;
1001 struct dbg_thread* thd;
1003 /* basic check */
1004 assert(gdbctx->in_packet_len >= 4);
1006 /* OK we have vCont followed by..
1007 * ? for query
1008 * c for packet_continue
1009 * Csig for packet_continue_signal
1010 * s for step
1011 * Ssig for step signal
1012 * and then an optional thread ID at the end..
1013 * *******************************************/
1015 fprintf(stderr, "trying to process a verbose packet\n");
1016 /* now check that we've got Cont */
1017 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
1019 /* Query */
1020 if (gdbctx->in_packet[4] == '?')
1023 Reply:
1024 `vCont[;action]...'
1025 The vCont packet is supported. Each action is a supported command in the vCont packet.
1027 The vCont packet is not supported. (this didn't seem to be obeyed!)
1029 packet_reply_open(gdbctx);
1030 packet_reply_add(gdbctx, "vCont", 5);
1031 /* add all the supported actions to the reply (all of them for now) */
1032 packet_reply_add(gdbctx, ";c", 2);
1033 packet_reply_add(gdbctx, ";C", 2);
1034 packet_reply_add(gdbctx, ";s", 2);
1035 packet_reply_add(gdbctx, ";S", 2);
1036 packet_reply_close(gdbctx);
1037 return packet_done;
1040 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1041 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1042 now if only gdb talked XML.... */
1043 #if 0 /* handy for debugging */
1044 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1045 #endif
1047 /* go through the packet and identify where all the actions start at */
1048 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1050 if (gdbctx->in_packet[i] == ';')
1052 threadIndex[actions] = 0;
1053 actionIndex[actions++] = i;
1055 else if (gdbctx->in_packet[i] == ':')
1057 threadIndex[actions - 1] = i;
1061 /* now look up the default action */
1062 for (i = 0 ; i < actions; i++)
1064 if (threadIndex[i] == 0)
1066 if (defaultAction != -1)
1068 fprintf(stderr,"Too many default actions specified\n");
1069 return packet_error;
1071 defaultAction = i;
1075 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1077 /* go through all the threads and stick their ids in the to be done list. */
1078 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1080 threadIDs[threadCount++] = thd->tid;
1081 /* check to see if we have more threads than I counted on, and tell the user what to do
1082 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1083 if (threadCount == 100)
1085 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1086 break;
1090 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1091 * that remains is to apply the actions to the threads and the default action to any threads
1092 * left */
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);
1098 /* deal with the threaded stuff first */
1099 for (i = 0; i < actions ; i++)
1101 if (threadIndex[i] != 0)
1103 int j, idLength = 0;
1104 if (i < actions - 1)
1106 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1108 else
1110 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1113 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1114 /* process the action */
1115 switch (gdbctx->in_packet[actionIndex[i] + 1])
1117 case 's': /* step */
1118 be_cpu->single_step(&gdbctx->context, TRUE);
1119 /* fall through*/
1120 case 'c': /* continue */
1121 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1122 break;
1123 case 'S': /* step Sig, */
1124 be_cpu->single_step(&gdbctx->context, TRUE);
1125 /* fall through */
1126 case 'C': /* continue sig */
1127 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1128 /* cannot change signals on the fly */
1129 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1130 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1131 if (sig != gdbctx->last_sig)
1132 return packet_error;
1133 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1134 break;
1136 for (j = 0 ; j < threadCount; j++)
1138 if (threadIDs[j] == threadID)
1140 threadIDs[j] = 0;
1141 break;
1145 } /* for i=0 ; i< actions */
1147 /* now we have manage the default action */
1148 if (defaultAction >= 0)
1150 for (i = 0 ; i< threadCount; i++)
1152 /* check to see if we've already done something to the thread*/
1153 if (threadIDs[i] != 0)
1155 /* if not apply the default action*/
1156 threadID = threadIDs[i];
1157 /* process the action (yes this is almost identical to the one above!) */
1158 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1160 case 's': /* step */
1161 be_cpu->single_step(&gdbctx->context, TRUE);
1162 /* fall through */
1163 case 'c': /* continue */
1164 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1165 break;
1166 case 'S':
1167 be_cpu->single_step(&gdbctx->context, TRUE);
1168 /* fall through */
1169 case 'C': /* continue sig */
1170 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1171 /* cannot change signals on the fly */
1172 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1173 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1174 if (sig != gdbctx->last_sig)
1175 return packet_error;
1176 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1177 break;
1181 } /* if(defaultAction >=0) */
1183 wait_for_debuggee(gdbctx);
1184 be_cpu->single_step(&gdbctx->context, FALSE);
1185 return packet_reply_status(gdbctx);
1188 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1190 unsigned char sig;
1192 /* FIXME: add support for address in packet */
1193 assert(gdbctx->in_packet_len == 2);
1194 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1195 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1196 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1197 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1198 hex_from(&sig, gdbctx->in_packet, 1);
1199 /* cannot change signals on the fly */
1200 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1201 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1202 if (sig != gdbctx->last_sig)
1203 return packet_error;
1204 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1205 wait_for_debuggee(gdbctx);
1206 return packet_reply_status(gdbctx);
1209 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1211 detach_debuggee(gdbctx, FALSE);
1212 return packet_ok | packet_last_f;
1215 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1217 int i;
1218 CONTEXT ctx;
1219 CONTEXT* pctx = &gdbctx->context;
1221 assert(gdbctx->in_trap);
1223 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1225 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1226 return packet_error;
1229 packet_reply_open(gdbctx);
1230 for (i = 0; i < cpu_num_regs; i++)
1232 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1234 packet_reply_close(gdbctx);
1235 return packet_done;
1238 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1240 unsigned i;
1241 CONTEXT ctx;
1242 CONTEXT* pctx = &gdbctx->context;
1244 assert(gdbctx->in_trap);
1245 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1247 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1248 return packet_error;
1250 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1252 for (i = 0; i < cpu_num_regs; i++)
1253 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1254 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1256 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1257 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1258 return packet_error;
1260 return packet_ok;
1263 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1265 detach_debuggee(gdbctx, TRUE);
1266 #if 0
1267 if (!gdbctx->extended)
1268 /* dunno whether GDB cares or not */
1269 #endif
1270 wait(NULL);
1271 exit(0);
1272 /* assume we can't really answer something here */
1273 /* return packet_done; */
1276 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1278 char* end;
1279 unsigned thread;
1281 switch (gdbctx->in_packet[0])
1283 case 'c':
1284 case 'g':
1285 if (gdbctx->in_packet[1] == '-')
1286 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1287 else
1288 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1289 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1291 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1292 fprintf(stderr, "Cannot get threadid %*.*s\n",
1293 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1294 gdbctx->in_packet + 1);
1295 return packet_error;
1297 if (gdbctx->in_packet[0] == 'c')
1298 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1299 else
1300 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1301 return packet_ok;
1302 default:
1303 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1304 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1305 return packet_error;
1309 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1311 char *addr;
1312 unsigned int len, blk_len, nread;
1313 char buffer[32];
1314 SIZE_T r = 0;
1316 assert(gdbctx->in_trap);
1317 /* FIXME:check in_packet_len for reading %p,%x */
1318 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1319 if (len <= 0) return packet_error;
1320 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1321 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1322 for (nread = 0; nread < len; nread += r, addr += r)
1324 blk_len = min(sizeof(buffer), len - nread);
1325 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1326 r == 0)
1328 /* fail at first address, return error */
1329 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1330 /* something has already been read, return partial information */
1331 break;
1333 if (nread == 0) packet_reply_open(gdbctx);
1334 packet_reply_hex_to(gdbctx, buffer, r);
1336 packet_reply_close(gdbctx);
1337 return packet_done;
1340 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1342 char* addr;
1343 unsigned int len, blk_len;
1344 char* ptr;
1345 char buffer[32];
1346 SIZE_T w;
1348 assert(gdbctx->in_trap);
1349 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1350 if (ptr == NULL)
1352 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1353 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1354 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1355 return packet_error;
1357 *ptr++ = '\0';
1359 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1361 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1362 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1363 return packet_error;
1365 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1367 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1368 fprintf(stderr, "Wrong sizes %u <> %u\n",
1369 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1370 return packet_error;
1372 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1373 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1374 while (len > 0)
1376 blk_len = min(sizeof(buffer), len);
1377 hex_from(buffer, ptr, blk_len);
1378 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1379 w != blk_len)
1380 break;
1381 addr += blk_len;
1382 len -= blk_len;
1383 ptr += blk_len;
1385 return packet_ok; /* FIXME: error while writing ? */
1388 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1390 unsigned reg;
1391 char* ptr;
1392 char* end;
1393 CONTEXT ctx;
1394 CONTEXT* pctx = &gdbctx->context;
1396 assert(gdbctx->in_trap);
1398 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1399 *ptr++ = '\0';
1400 reg = strtoul(gdbctx->in_packet, &end, 16);
1401 if (end == NULL || reg > cpu_num_regs)
1403 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1404 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1405 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1406 * it wouldn't matter too much, and it fakes our support for all regs
1408 return (end == NULL) ? packet_error : packet_ok;
1410 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1412 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1413 fprintf(stderr, "Wrong sizes %u <> %u\n",
1414 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1415 return packet_error;
1417 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1418 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1419 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1420 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1422 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1424 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1425 return packet_error;
1428 hex_from(cpu_register(pctx, reg), ptr, 4);
1429 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1431 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1432 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1433 return packet_error;
1436 return packet_ok;
1439 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1441 char buffer[128];
1442 char clsName[128];
1443 char wndName[128];
1444 HWND child;
1446 do {
1447 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1448 strcpy(clsName, "-- Unknown --");
1449 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1450 strcpy(wndName, "-- Empty --");
1452 packet_reply_open(gdbctx);
1453 packet_reply_catc(gdbctx, 'O');
1454 snprintf(buffer, sizeof(buffer),
1455 "%*s%04lx%*s%-17.17s %08x %08x %.14s\n",
1456 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1457 clsName, GetWindowLong(hWnd, GWL_STYLE),
1458 GetWindowLongPtr(hWnd, GWLP_WNDPROC), wndName);
1459 packet_reply_hex_to_str(gdbctx, buffer);
1460 packet_reply_close(gdbctx);
1462 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1463 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1464 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1467 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1469 char buffer[128];
1471 /* we do the output in several 'O' packets, with the last one being just OK for
1472 * marking the end of the output */
1473 packet_reply_open(gdbctx);
1474 packet_reply_catc(gdbctx, 'O');
1475 snprintf(buffer, sizeof(buffer),
1476 "%-16.16s %-17.17s %-8.8s %s\n",
1477 "hwnd", "Class Name", " Style", " WndProc Text");
1478 packet_reply_hex_to_str(gdbctx, buffer);
1479 packet_reply_close(gdbctx);
1481 /* FIXME: could also add a pmt to this command in str... */
1482 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1483 packet_reply(gdbctx, "OK", 2);
1486 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1488 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1489 char buffer[128];
1490 char deco;
1491 PROCESSENTRY32 entry;
1492 BOOL ok;
1494 if (snap == INVALID_HANDLE_VALUE)
1495 return;
1497 entry.dwSize = sizeof(entry);
1498 ok = Process32First(snap, &entry);
1500 /* we do the output in several 'O' packets, with the last one being just OK for
1501 * marking the end of the output */
1503 packet_reply_open(gdbctx);
1504 packet_reply_catc(gdbctx, 'O');
1505 snprintf(buffer, sizeof(buffer),
1506 " %-8.8s %-8.8s %-8.8s %s\n",
1507 "pid", "threads", "parent", "executable");
1508 packet_reply_hex_to_str(gdbctx, buffer);
1509 packet_reply_close(gdbctx);
1511 while (ok)
1513 deco = ' ';
1514 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1515 packet_reply_open(gdbctx);
1516 packet_reply_catc(gdbctx, 'O');
1517 snprintf(buffer, sizeof(buffer),
1518 "%c%08x %-8d %08x '%s'\n",
1519 deco, entry.th32ProcessID, entry.cntThreads,
1520 entry.th32ParentProcessID, entry.szExeFile);
1521 packet_reply_hex_to_str(gdbctx, buffer);
1522 packet_reply_close(gdbctx);
1523 ok = Process32Next(snap, &entry);
1525 CloseHandle(snap);
1526 packet_reply(gdbctx, "OK", 2);
1529 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1531 MEMORY_BASIC_INFORMATION mbi;
1532 char* addr = 0;
1533 const char* state;
1534 const char* type;
1535 char prot[3+1];
1536 char buffer[128];
1538 /* we do the output in several 'O' packets, with the last one being just OK for
1539 * marking the end of the output */
1540 packet_reply_open(gdbctx);
1541 packet_reply_catc(gdbctx, 'O');
1542 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1543 packet_reply_close(gdbctx);
1545 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1547 switch (mbi.State)
1549 case MEM_COMMIT: state = "commit "; break;
1550 case MEM_FREE: state = "free "; break;
1551 case MEM_RESERVE: state = "reserve"; break;
1552 default: state = "??? "; break;
1554 if (mbi.State != MEM_FREE)
1556 switch (mbi.Type)
1558 case MEM_IMAGE: type = "image "; break;
1559 case MEM_MAPPED: type = "mapped "; break;
1560 case MEM_PRIVATE: type = "private"; break;
1561 case 0: type = " "; break;
1562 default: type = "??? "; break;
1564 memset(prot, ' ' , sizeof(prot)-1);
1565 prot[sizeof(prot)-1] = '\0';
1566 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1567 prot[0] = 'R';
1568 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1569 prot[1] = 'W';
1570 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1571 prot[1] = 'C';
1572 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1573 prot[2] = 'X';
1575 else
1577 type = "";
1578 prot[0] = '\0';
1580 packet_reply_open(gdbctx);
1581 snprintf(buffer, sizeof(buffer), "%08lx %08lx %s %s %s\n",
1582 (DWORD_PTR)addr, mbi.RegionSize, state, type, prot);
1583 packet_reply_catc(gdbctx, 'O');
1584 packet_reply_hex_to_str(gdbctx, buffer);
1585 packet_reply_close(gdbctx);
1587 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1588 break;
1589 addr += mbi.RegionSize;
1591 packet_reply(gdbctx, "OK", 2);
1594 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1595 int len, const char* str)
1597 char buffer[128];
1599 if (len == 0)
1601 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1603 else if (len >= 2 && str[0] == '=')
1605 unsigned val = atoi(&str[1]);
1606 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1607 gdbctx->trace = val;
1609 else
1611 /* FIXME: ugly but can use error packet here */
1612 packet_reply_cat(gdbctx, "E00");
1613 return;
1615 packet_reply_open(gdbctx);
1616 packet_reply_hex_to_str(gdbctx, buffer);
1617 packet_reply_close(gdbctx);
1620 struct query_detail
1622 int with_arg;
1623 const char* name;
1624 size_t len;
1625 void (*handler)(struct gdb_context*, int, const char*);
1626 } query_details[] =
1628 {0, "wnd", 3, packet_query_monitor_wnd},
1629 {0, "window", 6, packet_query_monitor_wnd},
1630 {0, "proc", 4, packet_query_monitor_process},
1631 {0, "process", 7, packet_query_monitor_process},
1632 {0, "mem", 3, packet_query_monitor_mem},
1633 {1, "trace", 5, packet_query_monitor_trace},
1634 {0, NULL, 0, NULL},
1637 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1638 const char* hxcmd, size_t len)
1640 char buffer[128];
1641 struct query_detail* qd;
1643 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1644 len /= 2;
1645 hex_from(buffer, hxcmd, len);
1647 for (qd = &query_details[0]; qd->name != NULL; qd++)
1649 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1650 if (!qd->with_arg && len != qd->len) continue;
1652 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1653 return packet_done;
1655 return packet_reply_error(gdbctx, EINVAL);
1658 static enum packet_return packet_query(struct gdb_context* gdbctx)
1660 switch (gdbctx->in_packet[0])
1662 case 'f':
1663 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1665 struct dbg_thread* thd;
1667 packet_reply_open(gdbctx);
1668 packet_reply_add(gdbctx, "m", 1);
1669 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1671 packet_reply_val(gdbctx, thd->tid, 4);
1672 if (thd->next != NULL)
1673 packet_reply_add(gdbctx, ",", 1);
1675 packet_reply_close(gdbctx);
1676 return packet_done;
1678 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1680 char result[128];
1682 packet_reply_open(gdbctx);
1683 packet_reply_catc(gdbctx, 'O');
1684 get_process_info(gdbctx, result, sizeof(result));
1685 packet_reply_hex_to_str(gdbctx, result);
1686 packet_reply_close(gdbctx);
1687 return packet_done;
1689 break;
1690 case 's':
1691 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1693 packet_reply(gdbctx, "l", 1);
1694 return packet_done;
1696 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1698 packet_reply(gdbctx, "l", 1);
1699 return packet_done;
1701 break;
1702 case 'C':
1703 if (gdbctx->in_packet_len == 1)
1705 struct dbg_thread* thd;
1706 /* FIXME: doc says 16 bit val ??? */
1707 /* grab first created thread, aka last in list */
1708 assert(gdbctx->process && gdbctx->process->threads);
1709 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1710 packet_reply_open(gdbctx);
1711 packet_reply_add(gdbctx, "QC", 2);
1712 packet_reply_val(gdbctx, thd->tid, 4);
1713 packet_reply_close(gdbctx);
1714 return packet_done;
1716 break;
1717 case 'O':
1718 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1720 char buf[64];
1722 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1723 gdbctx->wine_segs[2] == 0)
1724 return packet_error;
1725 snprintf(buf, sizeof(buf),
1726 "Text=%08lx;Data=%08lx;Bss=%08lx",
1727 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1728 gdbctx->wine_segs[2]);
1729 return packet_reply(gdbctx, buf, -1);
1731 break;
1732 case 'R':
1733 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1735 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1736 gdbctx->in_packet_len - 5);
1738 break;
1739 case 'S':
1740 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1741 return packet_ok;
1742 break;
1743 case 'T':
1744 if (gdbctx->in_packet_len > 15 &&
1745 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1746 gdbctx->in_packet[15] == ',')
1748 unsigned tid;
1749 char* end;
1750 char result[128];
1752 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1753 if (end == NULL) break;
1754 get_thread_info(gdbctx, tid, result, sizeof(result));
1755 packet_reply_open(gdbctx);
1756 packet_reply_hex_to_str(gdbctx, result);
1757 packet_reply_close(gdbctx);
1758 return packet_done;
1760 break;
1762 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1763 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1764 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1765 return packet_error;
1768 static enum packet_return packet_step(struct gdb_context* gdbctx)
1770 /* FIXME: add support for address in packet */
1771 assert(gdbctx->in_packet_len == 0);
1772 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1773 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1774 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1775 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1776 be_cpu->single_step(&gdbctx->context, TRUE);
1777 resume_debuggee(gdbctx, DBG_CONTINUE);
1778 wait_for_debuggee(gdbctx);
1779 be_cpu->single_step(&gdbctx->context, FALSE);
1780 return packet_reply_status(gdbctx);
1783 #if 0
1784 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1786 unsigned char sig;
1788 /* FIXME: add support for address in packet */
1789 assert(gdbctx->in_packet_len == 2);
1790 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1791 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1792 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1793 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1794 hex_from(&sig, gdbctx->in_packet, 1);
1795 /* cannot change signals on the fly */
1796 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1797 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1798 if (sig != gdbctx->last_sig)
1799 return packet_error;
1800 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1801 wait_for_debuggee(gdbctx);
1802 return packet_reply_status(gdbctx);
1804 #endif
1806 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1808 char* end;
1809 unsigned tid;
1811 tid = strtol(gdbctx->in_packet, &end, 16);
1812 if (tid == -1 || tid == 0)
1813 return packet_reply_error(gdbctx, EINVAL);
1814 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1815 return packet_ok;
1816 return packet_reply_error(gdbctx, ESRCH);
1819 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1821 void* addr;
1822 unsigned len;
1823 struct gdb_ctx_Xpoint* xpt;
1824 enum be_xpoint_type t;
1826 /* FIXME: check packet_len */
1827 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1828 gdbctx->in_packet[1] != ',' ||
1829 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1830 return packet_error;
1831 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1832 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1833 addr, len, gdbctx->in_packet[0]);
1834 switch (gdbctx->in_packet[0])
1836 case '0': t = be_xpoint_break; len = 0; break;
1837 case '1': t = be_xpoint_watch_exec; break;
1838 case '2': t = be_xpoint_watch_read; break;
1839 case '3': t = be_xpoint_watch_write; break;
1840 default: return packet_error;
1842 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1844 if (xpt->addr == addr && xpt->type == t)
1846 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1847 gdbctx->process->process_io, &gdbctx->context,
1848 t, xpt->addr, xpt->val, len))
1850 xpt->type = -1;
1851 return packet_ok;
1853 break;
1856 return packet_error;
1859 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1861 void* addr;
1862 unsigned len;
1863 struct gdb_ctx_Xpoint* xpt;
1864 enum be_xpoint_type t;
1866 /* FIXME: check packet_len */
1867 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1868 gdbctx->in_packet[1] != ',' ||
1869 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1870 return packet_error;
1871 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1872 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1873 addr, len, gdbctx->in_packet[0]);
1874 switch (gdbctx->in_packet[0])
1876 case '0': t = be_xpoint_break; len = 0; break;
1877 case '1': t = be_xpoint_watch_exec; break;
1878 case '2': t = be_xpoint_watch_read; break;
1879 case '3': t = be_xpoint_watch_write; break;
1880 default: return packet_error;
1882 /* because of packet command handling, this should be made idempotent */
1883 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1885 if (xpt->addr == addr && xpt->type == t)
1886 return packet_ok; /* nothing to do */
1888 /* really set the Xpoint */
1889 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1891 if (xpt->type == -1)
1893 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1894 gdbctx->process->process_io, &gdbctx->context,
1895 t, addr, &xpt->val, len))
1897 xpt->addr = addr;
1898 xpt->type = t;
1899 return packet_ok;
1901 fprintf(stderr, "cannot set xpoint\n");
1902 break;
1905 /* no more entries... eech */
1906 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1907 return packet_error;
1910 /* =============================================== *
1911 * P A C K E T I N F R A S T R U C T U R E *
1912 * =============================================== *
1915 struct packet_entry
1917 char key;
1918 enum packet_return (*handler)(struct gdb_context* gdbctx);
1921 static struct packet_entry packet_entries[] =
1923 /*{'!', packet_extended}, */
1924 {'?', packet_last_signal},
1925 {'c', packet_continue},
1926 {'C', packet_continue_signal},
1927 {'D', packet_detach},
1928 {'g', packet_read_registers},
1929 {'G', packet_write_registers},
1930 {'k', packet_kill},
1931 {'H', packet_thread},
1932 {'m', packet_read_memory},
1933 {'M', packet_write_memory},
1934 /* {'p', packet_read_register}, doesn't seem needed */
1935 {'P', packet_write_register},
1936 {'q', packet_query},
1937 /* {'Q', packet_set}, */
1938 /* {'R', packet,restart}, only in extended mode ! */
1939 {'s', packet_step},
1940 /*{'S', packet_step_signal}, hard(er) to implement */
1941 {'T', packet_thread_alive},
1942 {'v', packet_verbose},
1943 {'z', packet_remove_breakpoint},
1944 {'Z', packet_set_breakpoint},
1947 static BOOL extract_packets(struct gdb_context* gdbctx)
1949 char* end;
1950 int plen;
1951 unsigned char in_cksum, loc_cksum;
1952 char* ptr;
1953 enum packet_return ret = packet_error;
1954 int num_packet = 0;
1956 while ((ret & packet_last_f) == 0)
1958 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1959 fprintf(stderr, "In-buf: %*.*s\n",
1960 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1961 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1962 if (ptr == NULL) return FALSE;
1963 if (ptr != gdbctx->in_buf)
1965 int glen = ptr - gdbctx->in_buf; /* garbage len */
1966 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1967 fprintf(stderr, "Removing garbage: %*.*s\n",
1968 glen, glen, gdbctx->in_buf);
1969 gdbctx->in_len -= glen;
1970 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1972 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1973 if (end == NULL) return FALSE;
1974 /* no checksum yet */
1975 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1976 plen = end - gdbctx->in_buf - 1;
1977 hex_from(&in_cksum, end + 1, 1);
1978 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1979 if (loc_cksum == in_cksum)
1981 if (num_packet == 0) {
1982 int i;
1984 ret = packet_error;
1986 write(gdbctx->sock, "+", 1);
1987 assert(plen);
1989 /* FIXME: should use bsearch if packet_entries was sorted */
1990 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1992 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1994 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1996 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1997 fprintf(stderr, "Unknown packet request %*.*s\n",
1998 plen, plen, &gdbctx->in_buf[1]);
2000 else
2002 gdbctx->in_packet = gdbctx->in_buf + 2;
2003 gdbctx->in_packet_len = plen - 1;
2004 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2005 fprintf(stderr, "Packet: %c%*.*s\n",
2006 gdbctx->in_buf[1],
2007 gdbctx->in_packet_len, gdbctx->in_packet_len,
2008 gdbctx->in_packet);
2009 ret = (packet_entries[i].handler)(gdbctx);
2011 switch (ret & ~packet_last_f)
2013 case packet_error: packet_reply(gdbctx, "", 0); break;
2014 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2015 case packet_done: break;
2017 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2018 fprintf(stderr, "Reply-full: %*.*s\n",
2019 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2020 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2021 assert(i == gdbctx->out_len);
2022 /* if this fails, we'll have to use POLLOUT...
2024 gdbctx->out_len = 0;
2025 num_packet++;
2027 else
2029 /* FIXME: if we have in our input buffer more than one packet,
2030 * it's very likely that we took too long to answer to a given packet
2031 * and gdb is sending us again the same packet
2032 * We simply drop the second packet. This will lower the risk of error,
2033 * but there's still some race conditions here
2034 * A better fix (yet not perfect) would be to have two threads:
2035 * - one managing the packets for gdb
2036 * - the second one managing the commands...
2037 * This would allow us also the reply with the '+' character (Ack of
2038 * the command) way sooner than what we do now
2040 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2041 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2044 else
2046 write(gdbctx->sock, "+", 1);
2047 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2048 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2050 gdbctx->in_len -= plen + 4;
2051 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2053 return TRUE;
2056 static int fetch_data(struct gdb_context* gdbctx)
2058 int len, in_len = gdbctx->in_len;
2060 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2061 for (;;)
2063 #define STEP 128
2064 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2065 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2066 #undef STEP
2067 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2068 fprintf(stderr, "%d %d %*.*s\n",
2069 gdbctx->in_len, gdbctx->in_buf_alloc,
2070 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2071 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2072 if (len <= 0) break;
2073 gdbctx->in_len += len;
2074 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2075 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2077 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2078 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2079 return gdbctx->in_len - in_len;
2082 #define FLAG_NO_START 1
2083 #define FLAG_WITH_XTERM 2
2085 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2087 char buf[MAX_PATH];
2088 int fd;
2089 const char* gdb_path;
2090 FILE* f;
2092 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2093 strcpy(buf,"/tmp/winegdb.XXXXXX");
2094 fd = mkstemps(buf, 0);
2095 if (fd == -1) return FALSE;
2096 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2097 fprintf(f, "file %s\n", wine_path);
2098 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2099 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2100 fprintf(f, "set prompt Wine-gdb>\\ \n");
2101 /* gdb 5.1 seems to require it, won't hurt anyway */
2102 fprintf(f, "sharedlibrary\n");
2103 /* This is needed (but not a decent & final fix)
2104 * Without this, gdb would skip our inter-DLL relay code (because
2105 * we don't have any line number information for the relay code)
2106 * With this, we will stop on first instruction of the stub, and
2107 * reusing step, will get us through the relay stub at the actual
2108 * function we're looking at.
2110 fprintf(f, "set step-mode on\n");
2111 /* tell gdb to delete this file when done handling it... */
2112 fprintf(f, "shell rm -f \"%s\"\n", buf);
2113 fclose(f);
2114 if (flags & FLAG_WITH_XTERM)
2115 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2116 else
2117 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2118 assert(0); /* never reached */
2119 return TRUE;
2122 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2124 int sock;
2125 struct sockaddr_in s_addrs;
2126 unsigned int s_len = sizeof(s_addrs);
2127 struct pollfd pollfd;
2128 IMAGEHLP_MODULE imh_mod;
2130 /* step 1: create socket for gdb connection request */
2131 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2133 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2134 fprintf(stderr, "Can't create socket");
2135 return FALSE;
2138 if (listen(sock, 1) == -1 ||
2139 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2140 return FALSE;
2142 /* step 2: do the process internal creation */
2143 handle_debug_event(gdbctx, de);
2145 /* step3: get the wine loader name */
2146 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2148 /* step 4: fire up gdb (if requested) */
2149 if (flags & FLAG_NO_START)
2150 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2151 else
2152 switch (fork())
2154 case -1: /* error in parent... */
2155 fprintf(stderr, "Cannot create gdb\n");
2156 return FALSE;
2157 default: /* in parent... success */
2158 break;
2159 case 0: /* in child... and alive */
2160 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2161 /* if we're here, exec failed, so report failure */
2162 return FALSE;
2165 /* step 5: wait for gdb to connect actually */
2166 pollfd.fd = sock;
2167 pollfd.events = POLLIN;
2168 pollfd.revents = 0;
2170 switch (poll(&pollfd, 1, -1))
2172 case 1:
2173 if (pollfd.revents & POLLIN)
2175 int dummy = 1;
2176 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2177 if (gdbctx->sock == -1)
2178 break;
2179 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2180 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2181 /* don't keep our small packets too long: send them ASAP back to GDB
2182 * without this, GDB really crawls
2184 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2186 break;
2187 case 0:
2188 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2189 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2190 return FALSE;
2191 case -1:
2192 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2193 fprintf(stderr, "Poll for cnx failed (error)\n");
2194 return FALSE;
2195 default:
2196 assert(0);
2199 close(sock);
2200 return TRUE;
2203 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2205 DEBUG_EVENT de;
2206 int i;
2208 gdbctx->sock = -1;
2209 gdbctx->in_buf = NULL;
2210 gdbctx->in_buf_alloc = 0;
2211 gdbctx->in_len = 0;
2212 gdbctx->out_buf = NULL;
2213 gdbctx->out_buf_alloc = 0;
2214 gdbctx->out_len = 0;
2215 gdbctx->out_curr_packet = -1;
2217 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2218 gdbctx->last_sig = 0;
2219 gdbctx->in_trap = FALSE;
2220 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2221 gdbctx->process = NULL;
2222 for (i = 0; i < NUM_XPOINT; i++)
2223 gdbctx->Xpoints[i].type = -1;
2225 /* wait for first trap */
2226 while (WaitForDebugEvent(&de, INFINITE))
2228 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2230 /* this should be the first event we get,
2231 * and the only one of this type */
2232 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2233 /* gdbctx->dwProcessId = pid; */
2234 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2235 assert(!gdbctx->in_trap);
2237 else
2239 handle_debug_event(gdbctx, &de);
2240 if (gdbctx->in_trap) break;
2242 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2244 return TRUE;
2247 static int gdb_remote(unsigned flags)
2249 struct pollfd pollfd;
2250 struct gdb_context gdbctx;
2251 BOOL doLoop;
2253 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2255 pollfd.fd = gdbctx.sock;
2256 pollfd.events = POLLIN;
2257 pollfd.revents = 0;
2259 switch (poll(&pollfd, 1, -1))
2261 case 1:
2262 /* got something */
2263 if (pollfd.revents & (POLLHUP | POLLERR))
2265 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2266 fprintf(stderr, "Gdb hung up\n");
2267 /* kill also debuggee process - questionnable - */
2268 detach_debuggee(&gdbctx, TRUE);
2269 doLoop = FALSE;
2270 break;
2272 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2274 if (extract_packets(&gdbctx)) doLoop = FALSE;
2276 break;
2277 case 0:
2278 /* timeout, should never happen (infinite timeout) */
2279 break;
2280 case -1:
2281 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2282 fprintf(stderr, "Poll failed\n");
2283 doLoop = FALSE;
2284 break;
2287 wait(NULL);
2288 return 0;
2290 #endif
2292 int gdb_main(int argc, char* argv[])
2294 #ifdef HAVE_POLL
2295 unsigned gdb_flags = 0;
2297 argc--; argv++;
2298 while (argc > 0 && argv[0][0] == '-')
2300 if (strcmp(argv[0], "--no-start") == 0)
2302 gdb_flags |= FLAG_NO_START;
2303 argc--; argv++;
2304 continue;
2306 if (strcmp(argv[0], "--with-xterm") == 0)
2308 gdb_flags |= FLAG_WITH_XTERM;
2309 argc--; argv++;
2310 continue;
2312 return -1;
2314 if (dbg_active_attach(argc, argv) == start_ok ||
2315 dbg_active_launch(argc, argv) == start_ok)
2316 return gdb_remote(gdb_flags);
2317 #else
2318 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2319 #endif
2320 return -1;
2323 static struct be_process_io be_process_gdbproxy_io =
2325 NULL, /* we shouldn't use close_process() in gdbproxy */
2326 ReadProcessMemory,
2327 WriteProcessMemory