winedbg: Added x86_64 support.
[wine.git] / programs / winedbg / gdbproxy.c
blob45a452258d21ff45c6377e8df452cdb70559a8fc
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 #include <sys/poll.h>
38 #include <sys/wait.h>
39 #ifdef HAVE_SYS_SOCKET_H
40 # include <sys/socket.h>
41 #endif
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
44 #ifdef HAVE_UNISTD_H
45 # include <unistd.h>
46 #endif
48 #include "debugger.h"
50 #include "windef.h"
51 #include "winbase.h"
52 #include "tlhelp32.h"
54 /* those two are needed only for the SHOWNORMAL flag */
55 #include "wingdi.h"
56 #include "winuser.h"
58 #define GDBPXY_TRC_LOWLEVEL 0x01
59 #define GDBPXY_TRC_PACKET 0x02
60 #define GDBPXY_TRC_COMMAND 0x04
61 #define GDBPXY_TRC_COMMAND_ERROR 0x08
62 #define GDBPXY_TRC_WIN32_EVENT 0x10
63 #define GDBPXY_TRC_WIN32_ERROR 0x20
64 #define GDBPXY_TRC_COMMAND_FIXME 0x80
66 struct gdb_ctx_Xpoint
68 enum be_xpoint_type type; /* -1 means free */
69 void* addr;
70 unsigned long val;
73 struct gdb_context
75 /* gdb information */
76 int sock;
77 /* incoming buffer */
78 char* in_buf;
79 int in_buf_alloc;
80 int in_len;
81 /* split into individual packet */
82 char* in_packet;
83 int in_packet_len;
84 /* outgoing buffer */
85 char* out_buf;
86 int out_buf_alloc;
87 int out_len;
88 int out_curr_packet;
89 /* generic GDB thread information */
90 struct dbg_thread* exec_thread; /* thread used in step & continue */
91 struct dbg_thread* other_thread; /* thread to be used in any other operation */
92 unsigned trace;
93 /* current Win32 trap env */
94 unsigned last_sig;
95 BOOL in_trap;
96 CONTEXT context;
97 /* Win32 information */
98 struct dbg_process* process;
99 #define NUM_XPOINT 32
100 struct gdb_ctx_Xpoint Xpoints[NUM_XPOINT];
101 /* Unix environment */
102 unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
105 static struct be_process_io be_process_gdbproxy_io;
107 /* =============================================== *
108 * B A S I C M A N I P U L A T I O N S *
109 * =============================================== *
112 static inline int hex_from0(char ch)
114 if (ch >= '0' && ch <= '9') return ch - '0';
115 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
116 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
118 assert(0);
119 return 0;
122 static inline unsigned char hex_to0(int x)
124 assert(x >= 0 && x < 16);
125 return "0123456789abcdef"[x];
128 static int hex_to_int(const char* src, size_t len)
130 unsigned int returnval = 0;
131 while (len--)
133 returnval <<= 4;
134 returnval |= hex_from0(*src++);
136 return returnval;
139 static void hex_from(void* dst, const char* src, size_t len)
141 unsigned char *p = dst;
142 while (len--)
144 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
145 src += 2;
149 static void hex_to(char* dst, const void* src, size_t len)
151 const unsigned char *p = src;
152 while (len--)
154 *dst++ = hex_to0(*p >> 4);
155 *dst++ = hex_to0(*p & 0x0F);
156 p++;
160 static unsigned char checksum(const char* ptr, int len)
162 unsigned cksum = 0;
164 while (len-- > 0)
165 cksum += (unsigned char)*ptr++;
166 return cksum;
169 /* =============================================== *
170 * C P U H A N D L E R S *
171 * =============================================== *
174 #ifdef __i386__
175 static size_t cpu_register_map[] = {
176 FIELD_OFFSET(CONTEXT, Eax),
177 FIELD_OFFSET(CONTEXT, Ecx),
178 FIELD_OFFSET(CONTEXT, Edx),
179 FIELD_OFFSET(CONTEXT, Ebx),
180 FIELD_OFFSET(CONTEXT, Esp),
181 FIELD_OFFSET(CONTEXT, Ebp),
182 FIELD_OFFSET(CONTEXT, Esi),
183 FIELD_OFFSET(CONTEXT, Edi),
184 FIELD_OFFSET(CONTEXT, Eip),
185 FIELD_OFFSET(CONTEXT, EFlags),
186 FIELD_OFFSET(CONTEXT, SegCs),
187 FIELD_OFFSET(CONTEXT, SegSs),
188 FIELD_OFFSET(CONTEXT, SegDs),
189 FIELD_OFFSET(CONTEXT, SegEs),
190 FIELD_OFFSET(CONTEXT, SegFs),
191 FIELD_OFFSET(CONTEXT, SegGs),
193 #elif defined(__powerpc__)
194 static size_t cpu_register_map[] = {
195 FIELD_OFFSET(CONTEXT, Gpr0),
196 FIELD_OFFSET(CONTEXT, Gpr1),
197 FIELD_OFFSET(CONTEXT, Gpr2),
198 FIELD_OFFSET(CONTEXT, Gpr3),
199 FIELD_OFFSET(CONTEXT, Gpr4),
200 FIELD_OFFSET(CONTEXT, Gpr5),
201 FIELD_OFFSET(CONTEXT, Gpr6),
202 FIELD_OFFSET(CONTEXT, Gpr7),
203 FIELD_OFFSET(CONTEXT, Gpr8),
204 FIELD_OFFSET(CONTEXT, Gpr9),
205 FIELD_OFFSET(CONTEXT, Gpr10),
206 FIELD_OFFSET(CONTEXT, Gpr11),
207 FIELD_OFFSET(CONTEXT, Gpr12),
208 FIELD_OFFSET(CONTEXT, Gpr13),
209 FIELD_OFFSET(CONTEXT, Gpr14),
210 FIELD_OFFSET(CONTEXT, Gpr15),
211 FIELD_OFFSET(CONTEXT, Gpr16),
212 FIELD_OFFSET(CONTEXT, Gpr17),
213 FIELD_OFFSET(CONTEXT, Gpr18),
214 FIELD_OFFSET(CONTEXT, Gpr19),
215 FIELD_OFFSET(CONTEXT, Gpr20),
216 FIELD_OFFSET(CONTEXT, Gpr21),
217 FIELD_OFFSET(CONTEXT, Gpr22),
218 FIELD_OFFSET(CONTEXT, Gpr23),
219 FIELD_OFFSET(CONTEXT, Gpr24),
220 FIELD_OFFSET(CONTEXT, Gpr25),
221 FIELD_OFFSET(CONTEXT, Gpr26),
222 FIELD_OFFSET(CONTEXT, Gpr27),
223 FIELD_OFFSET(CONTEXT, Gpr28),
224 FIELD_OFFSET(CONTEXT, Gpr29),
225 FIELD_OFFSET(CONTEXT, Gpr30),
226 FIELD_OFFSET(CONTEXT, Gpr31),
227 FIELD_OFFSET(CONTEXT, Fpr0),
228 FIELD_OFFSET(CONTEXT, Fpr1),
229 FIELD_OFFSET(CONTEXT, Fpr2),
230 FIELD_OFFSET(CONTEXT, Fpr3),
231 FIELD_OFFSET(CONTEXT, Fpr4),
232 FIELD_OFFSET(CONTEXT, Fpr5),
233 FIELD_OFFSET(CONTEXT, Fpr6),
234 FIELD_OFFSET(CONTEXT, Fpr7),
235 FIELD_OFFSET(CONTEXT, Fpr8),
236 FIELD_OFFSET(CONTEXT, Fpr9),
237 FIELD_OFFSET(CONTEXT, Fpr10),
238 FIELD_OFFSET(CONTEXT, Fpr11),
239 FIELD_OFFSET(CONTEXT, Fpr12),
240 FIELD_OFFSET(CONTEXT, Fpr13),
241 FIELD_OFFSET(CONTEXT, Fpr14),
242 FIELD_OFFSET(CONTEXT, Fpr15),
243 FIELD_OFFSET(CONTEXT, Fpr16),
244 FIELD_OFFSET(CONTEXT, Fpr17),
245 FIELD_OFFSET(CONTEXT, Fpr18),
246 FIELD_OFFSET(CONTEXT, Fpr19),
247 FIELD_OFFSET(CONTEXT, Fpr20),
248 FIELD_OFFSET(CONTEXT, Fpr21),
249 FIELD_OFFSET(CONTEXT, Fpr22),
250 FIELD_OFFSET(CONTEXT, Fpr23),
251 FIELD_OFFSET(CONTEXT, Fpr24),
252 FIELD_OFFSET(CONTEXT, Fpr25),
253 FIELD_OFFSET(CONTEXT, Fpr26),
254 FIELD_OFFSET(CONTEXT, Fpr27),
255 FIELD_OFFSET(CONTEXT, Fpr28),
256 FIELD_OFFSET(CONTEXT, Fpr29),
257 FIELD_OFFSET(CONTEXT, Fpr30),
258 FIELD_OFFSET(CONTEXT, Fpr31),
260 FIELD_OFFSET(CONTEXT, Iar),
261 FIELD_OFFSET(CONTEXT, Msr),
262 FIELD_OFFSET(CONTEXT, Cr),
263 FIELD_OFFSET(CONTEXT, Lr),
264 FIELD_OFFSET(CONTEXT, Ctr),
265 FIELD_OFFSET(CONTEXT, Xer),
266 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
267 /* see gdb/nlm/ppc.c */
269 #elif defined(__ALPHA__)
270 static size_t cpu_register_map[] = {
271 FIELD_OFFSET(CONTEXT, IntV0),
272 FIELD_OFFSET(CONTEXT, IntT0),
273 FIELD_OFFSET(CONTEXT, IntT1),
274 FIELD_OFFSET(CONTEXT, IntT2),
275 FIELD_OFFSET(CONTEXT, IntT3),
276 FIELD_OFFSET(CONTEXT, IntT4),
277 FIELD_OFFSET(CONTEXT, IntT5),
278 FIELD_OFFSET(CONTEXT, IntT6),
279 FIELD_OFFSET(CONTEXT, IntT7),
280 FIELD_OFFSET(CONTEXT, IntS0),
281 FIELD_OFFSET(CONTEXT, IntS1),
282 FIELD_OFFSET(CONTEXT, IntS2),
283 FIELD_OFFSET(CONTEXT, IntS3),
284 FIELD_OFFSET(CONTEXT, IntS4),
285 FIELD_OFFSET(CONTEXT, IntS5),
286 FIELD_OFFSET(CONTEXT, IntFp),
287 FIELD_OFFSET(CONTEXT, IntA0),
288 FIELD_OFFSET(CONTEXT, IntA1),
289 FIELD_OFFSET(CONTEXT, IntA2),
290 FIELD_OFFSET(CONTEXT, IntA3),
291 FIELD_OFFSET(CONTEXT, IntA4),
292 FIELD_OFFSET(CONTEXT, IntA5),
293 FIELD_OFFSET(CONTEXT, IntT8),
294 FIELD_OFFSET(CONTEXT, IntT9),
295 FIELD_OFFSET(CONTEXT, IntT10),
296 FIELD_OFFSET(CONTEXT, IntT11),
297 FIELD_OFFSET(CONTEXT, IntRa),
298 FIELD_OFFSET(CONTEXT, IntT12),
299 FIELD_OFFSET(CONTEXT, IntAt),
300 FIELD_OFFSET(CONTEXT, IntGp),
301 FIELD_OFFSET(CONTEXT, IntSp),
302 FIELD_OFFSET(CONTEXT, IntZero),
303 FIELD_OFFSET(CONTEXT, FltF0),
304 FIELD_OFFSET(CONTEXT, FltF1),
305 FIELD_OFFSET(CONTEXT, FltF2),
306 FIELD_OFFSET(CONTEXT, FltF3),
307 FIELD_OFFSET(CONTEXT, FltF4),
308 FIELD_OFFSET(CONTEXT, FltF5),
309 FIELD_OFFSET(CONTEXT, FltF6),
310 FIELD_OFFSET(CONTEXT, FltF7),
311 FIELD_OFFSET(CONTEXT, FltF8),
312 FIELD_OFFSET(CONTEXT, FltF9),
313 FIELD_OFFSET(CONTEXT, FltF10),
314 FIELD_OFFSET(CONTEXT, FltF11),
315 FIELD_OFFSET(CONTEXT, FltF12),
316 FIELD_OFFSET(CONTEXT, FltF13),
317 FIELD_OFFSET(CONTEXT, FltF14),
318 FIELD_OFFSET(CONTEXT, FltF15),
319 FIELD_OFFSET(CONTEXT, FltF16),
320 FIELD_OFFSET(CONTEXT, FltF17),
321 FIELD_OFFSET(CONTEXT, FltF18),
322 FIELD_OFFSET(CONTEXT, FltF19),
323 FIELD_OFFSET(CONTEXT, FltF20),
324 FIELD_OFFSET(CONTEXT, FltF21),
325 FIELD_OFFSET(CONTEXT, FltF22),
326 FIELD_OFFSET(CONTEXT, FltF23),
327 FIELD_OFFSET(CONTEXT, FltF24),
328 FIELD_OFFSET(CONTEXT, FltF25),
329 FIELD_OFFSET(CONTEXT, FltF26),
330 FIELD_OFFSET(CONTEXT, FltF27),
331 FIELD_OFFSET(CONTEXT, FltF28),
332 FIELD_OFFSET(CONTEXT, FltF29),
333 FIELD_OFFSET(CONTEXT, FltF30),
334 FIELD_OFFSET(CONTEXT, FltF31),
336 /* FIXME: Didn't look for the right order yet */
337 FIELD_OFFSET(CONTEXT, Fir),
338 FIELD_OFFSET(CONTEXT, Fpcr),
339 FIELD_OFFSET(CONTEXT, SoftFpcr),
341 #elif defined(__x86_64__)
342 static size_t cpu_register_map[] = {
343 FIELD_OFFSET(CONTEXT, Rax),
344 FIELD_OFFSET(CONTEXT, Rbx),
345 FIELD_OFFSET(CONTEXT, Rcx),
346 FIELD_OFFSET(CONTEXT, Rdx),
347 FIELD_OFFSET(CONTEXT, Rsi),
348 FIELD_OFFSET(CONTEXT, Rdi),
349 FIELD_OFFSET(CONTEXT, Rbp),
350 FIELD_OFFSET(CONTEXT, Rsp),
351 FIELD_OFFSET(CONTEXT, R8),
352 FIELD_OFFSET(CONTEXT, R9),
353 FIELD_OFFSET(CONTEXT, R10),
354 FIELD_OFFSET(CONTEXT, R11),
355 FIELD_OFFSET(CONTEXT, R12),
356 FIELD_OFFSET(CONTEXT, R13),
357 FIELD_OFFSET(CONTEXT, R14),
358 FIELD_OFFSET(CONTEXT, R15),
359 FIELD_OFFSET(CONTEXT, Rip),
360 FIELD_OFFSET(CONTEXT, EFlags),
361 FIELD_OFFSET(CONTEXT, SegCs),
362 FIELD_OFFSET(CONTEXT, SegSs),
363 FIELD_OFFSET(CONTEXT, SegDs),
364 FIELD_OFFSET(CONTEXT, SegEs),
365 FIELD_OFFSET(CONTEXT, SegFs),
366 FIELD_OFFSET(CONTEXT, SegGs),
368 #else
369 # error Define the registers map for your CPU
370 #endif
372 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
374 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
376 assert(idx < cpu_num_regs);
377 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
380 /* =============================================== *
381 * W I N 3 2 D E B U G I N T E R F A C E *
382 * =============================================== *
385 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
387 ctx->ContextFlags = CONTEXT_CONTROL
388 | CONTEXT_INTEGER
389 #ifdef CONTEXT_SEGMENTS
390 | CONTEXT_SEGMENTS
391 #endif
392 #ifdef CONTEXT_DEBUG_REGISTERS
393 | CONTEXT_DEBUG_REGISTERS
394 #endif
396 if (!GetThreadContext(h, ctx))
398 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
399 fprintf(stderr, "Can't get thread's context\n");
400 return FALSE;
402 return TRUE;
405 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
407 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
408 BOOL ret = FALSE;
410 switch (rec->ExceptionCode)
412 case EXCEPTION_ACCESS_VIOLATION:
413 case EXCEPTION_PRIV_INSTRUCTION:
414 case EXCEPTION_STACK_OVERFLOW:
415 case EXCEPTION_GUARD_PAGE:
416 gdbctx->last_sig = SIGSEGV;
417 ret = TRUE;
418 break;
419 case EXCEPTION_DATATYPE_MISALIGNMENT:
420 gdbctx->last_sig = SIGBUS;
421 ret = TRUE;
422 break;
423 case EXCEPTION_SINGLE_STEP:
424 /* fall thru */
425 case EXCEPTION_BREAKPOINT:
426 gdbctx->last_sig = SIGTRAP;
427 ret = TRUE;
428 break;
429 case EXCEPTION_FLT_DENORMAL_OPERAND:
430 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
431 case EXCEPTION_FLT_INEXACT_RESULT:
432 case EXCEPTION_FLT_INVALID_OPERATION:
433 case EXCEPTION_FLT_OVERFLOW:
434 case EXCEPTION_FLT_STACK_CHECK:
435 case EXCEPTION_FLT_UNDERFLOW:
436 gdbctx->last_sig = SIGFPE;
437 ret = TRUE;
438 break;
439 case EXCEPTION_INT_DIVIDE_BY_ZERO:
440 case EXCEPTION_INT_OVERFLOW:
441 gdbctx->last_sig = SIGFPE;
442 ret = TRUE;
443 break;
444 case EXCEPTION_ILLEGAL_INSTRUCTION:
445 gdbctx->last_sig = SIGILL;
446 ret = TRUE;
447 break;
448 case CONTROL_C_EXIT:
449 gdbctx->last_sig = SIGINT;
450 ret = TRUE;
451 break;
452 case STATUS_POSSIBLE_DEADLOCK:
453 gdbctx->last_sig = SIGALRM;
454 ret = TRUE;
455 /* FIXME: we could also add here a O packet with additional information */
456 break;
457 default:
458 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
459 fprintf(stderr, "Unhandled exception code 0x%08lx\n", rec->ExceptionCode);
460 gdbctx->last_sig = SIGABRT;
461 ret = TRUE;
462 break;
464 return ret;
467 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
469 char buffer[256];
471 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
473 switch (de->dwDebugEventCode)
475 case CREATE_PROCESS_DEBUG_EVENT:
476 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
477 de->u.CreateProcessInfo.hProcess);
478 if (!gdbctx->process) break;
479 memory_get_string_indirect(gdbctx->process,
480 de->u.CreateProcessInfo.lpImageName,
481 de->u.CreateProcessInfo.fUnicode,
482 buffer, sizeof(buffer));
483 dbg_set_process_name(gdbctx->process, buffer);
485 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
486 fprintf(stderr, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
487 de->dwProcessId, de->dwThreadId,
488 buffer, de->u.CreateProcessInfo.lpImageName,
489 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress,
490 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
491 de->u.CreateProcessInfo.nDebugInfoSize);
493 /* de->u.CreateProcessInfo.lpStartAddress; */
494 if (!SymInitialize(gdbctx->process->handle, NULL, TRUE))
495 fprintf(stderr, "Couldn't initiate DbgHelp\n");
497 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
498 fprintf(stderr, "%08lx:%08lx: create thread I @%08lx\n",
499 de->dwProcessId, de->dwThreadId,
500 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress);
502 assert(dbg_curr_thread == NULL); /* shouldn't be there */
503 dbg_add_thread(gdbctx->process, de->dwThreadId,
504 de->u.CreateProcessInfo.hThread,
505 de->u.CreateProcessInfo.lpThreadLocalBase);
506 break;
508 case LOAD_DLL_DEBUG_EVENT:
509 assert(dbg_curr_thread);
510 memory_get_string_indirect(gdbctx->process,
511 de->u.LoadDll.lpImageName,
512 de->u.LoadDll.fUnicode,
513 buffer, sizeof(buffer));
514 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
515 fprintf(stderr, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
516 de->dwProcessId, de->dwThreadId,
517 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
518 de->u.LoadDll.dwDebugInfoFileOffset,
519 de->u.LoadDll.nDebugInfoSize);
520 SymLoadModule(gdbctx->process->handle, de->u.LoadDll.hFile, buffer, NULL,
521 (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
522 break;
524 case UNLOAD_DLL_DEBUG_EVENT:
525 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
526 fprintf(stderr, "%08lx:%08lx: unload DLL @%08lx\n",
527 de->dwProcessId, de->dwThreadId, (unsigned long)de->u.UnloadDll.lpBaseOfDll);
528 SymUnloadModule(gdbctx->process->handle,
529 (unsigned long)de->u.UnloadDll.lpBaseOfDll);
530 break;
532 case EXCEPTION_DEBUG_EVENT:
533 assert(dbg_curr_thread);
534 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
535 fprintf(stderr, "%08lx:%08lx: exception code=0x%08lx\n",
536 de->dwProcessId, de->dwThreadId,
537 de->u.Exception.ExceptionRecord.ExceptionCode);
539 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
541 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
543 break;
545 case CREATE_THREAD_DEBUG_EVENT:
546 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
547 fprintf(stderr, "%08lx:%08lx: create thread D @%08lx\n",
548 de->dwProcessId, de->dwThreadId, (unsigned long)(void*)de->u.CreateThread.lpStartAddress);
550 dbg_add_thread(gdbctx->process,
551 de->dwThreadId,
552 de->u.CreateThread.hThread,
553 de->u.CreateThread.lpThreadLocalBase);
554 break;
556 case EXIT_THREAD_DEBUG_EVENT:
557 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
558 fprintf(stderr, "%08lx:%08lx: exit thread (%ld)\n",
559 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
561 assert(dbg_curr_thread);
562 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
563 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
564 dbg_del_thread(dbg_curr_thread);
565 break;
567 case EXIT_PROCESS_DEBUG_EVENT:
568 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
569 fprintf(stderr, "%08lx:%08lx: exit process (%ld)\n",
570 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
572 dbg_del_process(gdbctx->process);
573 gdbctx->process = NULL;
574 /* now signal gdb that we're done */
575 gdbctx->last_sig = SIGTERM;
576 gdbctx->in_trap = TRUE;
577 break;
579 case OUTPUT_DEBUG_STRING_EVENT:
580 assert(dbg_curr_thread);
581 memory_get_string(gdbctx->process,
582 de->u.DebugString.lpDebugStringData, TRUE,
583 de->u.DebugString.fUnicode, buffer, sizeof(buffer));
584 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
585 fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n",
586 de->dwProcessId, de->dwThreadId, buffer);
587 break;
589 case RIP_EVENT:
590 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
591 fprintf(stderr, "%08lx:%08lx: rip error=%ld type=%ld\n",
592 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
593 de->u.RipInfo.dwType);
594 break;
596 default:
597 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
598 fprintf(stderr, "%08lx:%08lx: unknown event (%ld)\n",
599 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
603 static void resume_debuggee(struct gdb_context* gdbctx, unsigned long cont)
605 if (dbg_curr_thread)
607 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
608 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
609 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
610 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
611 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
612 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
613 dbg_curr_thread->tid, cont);
615 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
616 fprintf(stderr, "Cannot find last thread\n");
620 static void resume_debuggee_thread(struct gdb_context* gdbctx, unsigned long cont, unsigned int threadid)
623 if (dbg_curr_thread)
625 if(dbg_curr_thread->tid == threadid){
626 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
627 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
628 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
629 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
630 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
631 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
632 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
633 dbg_curr_thread->tid, cont);
636 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
637 fprintf(stderr, "Cannot find last thread\n");
640 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
642 struct pollfd pollfd;
643 int ret;
644 char pkt;
646 pollfd.fd = gdbctx->sock;
647 pollfd.events = POLLIN;
648 pollfd.revents = 0;
650 if ((ret = poll(&pollfd, 1, 0)) == 1) {
651 ret = read(gdbctx->sock, &pkt, 1);
652 if (ret != 1) {
653 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
654 fprintf(stderr, "read failed\n");
656 return FALSE;
658 if (pkt != '\003') {
659 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
660 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
662 return FALSE;
664 return TRUE;
665 } else if (ret == -1) {
666 fprintf(stderr, "poll failed\n");
668 return FALSE;
671 static void wait_for_debuggee(struct gdb_context* gdbctx)
673 DEBUG_EVENT de;
675 gdbctx->in_trap = FALSE;
676 for (;;)
678 if (!WaitForDebugEvent(&de, 10))
680 if (GetLastError() == ERROR_SEM_TIMEOUT)
682 if (check_for_interrupt(gdbctx)) {
683 if (!DebugBreakProcess(gdbctx->process->handle)) {
684 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
685 fprintf(stderr, "Failed to break into debugee\n");
687 break;
689 WaitForDebugEvent(&de, INFINITE);
690 } else {
691 continue;
693 } else {
694 break;
697 handle_debug_event(gdbctx, &de);
698 assert(!gdbctx->process ||
699 gdbctx->process->pid == 0 ||
700 de.dwProcessId == gdbctx->process->pid);
701 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
702 if (gdbctx->in_trap) break;
703 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
707 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
709 be_cpu->single_step(&gdbctx->context, FALSE);
710 resume_debuggee(gdbctx, DBG_CONTINUE);
711 if (!kill)
712 DebugActiveProcessStop(gdbctx->process->pid);
713 dbg_del_process(gdbctx->process);
714 gdbctx->process = NULL;
717 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
719 unsigned long status;
721 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
723 strcpy(buffer, "Unknown process");
724 return;
726 if (status == STILL_ACTIVE)
728 strcpy(buffer, "Running");
730 else
731 snprintf(buffer, len, "Terminated (%lu)", status);
733 switch (GetPriorityClass(gdbctx->process->handle))
735 case 0: break;
736 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
737 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
738 #endif
739 #ifdef BELOW_NORMAL_PRIORITY_CLASS
740 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
741 #endif
742 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
743 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
744 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
745 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
747 strcat(buffer, "\n");
750 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
751 char* buffer, size_t len)
753 struct dbg_thread* thd;
754 unsigned long status;
755 int prio;
757 /* FIXME: use the size of buffer */
758 thd = dbg_get_thread(gdbctx->process, tid);
759 if (thd == NULL)
761 strcpy(buffer, "No information");
762 return;
764 if (GetExitCodeThread(thd->handle, &status))
766 if (status == STILL_ACTIVE)
768 /* FIXME: this is a bit brutal... some nicer way shall be found */
769 switch (status = SuspendThread(thd->handle))
771 case -1: break;
772 case 0: strcpy(buffer, "Running"); break;
773 default: snprintf(buffer, len, "Suspended (%lu)", status - 1);
775 ResumeThread(thd->handle);
777 else
778 snprintf(buffer, len, "Terminated (exit code = %lu)", status);
780 else
782 strcpy(buffer, "Unknown threadID");
784 switch (prio = GetThreadPriority(thd->handle))
786 case THREAD_PRIORITY_ERROR_RETURN: break;
787 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
788 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
789 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
790 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
791 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
792 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
793 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
794 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
796 assert(strlen(buffer) < len);
799 /* =============================================== *
800 * P A C K E T U T I L S *
801 * =============================================== *
804 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
805 packet_last_f = 0x80};
807 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
809 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
811 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
812 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
816 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
818 packet_reply_grow(gdbctx, len * 2);
819 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
820 gdbctx->out_len += len * 2;
823 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
825 packet_reply_hex_to(gdbctx, src, strlen(src));
828 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
830 int i, shift;
832 shift = (len - 1) * 8;
833 packet_reply_grow(gdbctx, len * 2);
834 for (i = 0; i < len; i++, shift -= 8)
836 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
837 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
841 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
843 packet_reply_grow(gdbctx, len);
844 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
845 gdbctx->out_len += len;
848 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
850 packet_reply_add(gdbctx, str, strlen(str));
853 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
855 packet_reply_add(gdbctx, &ch, 1);
858 static void packet_reply_open(struct gdb_context* gdbctx)
860 assert(gdbctx->out_curr_packet == -1);
861 packet_reply_catc(gdbctx, '$');
862 gdbctx->out_curr_packet = gdbctx->out_len;
865 static void packet_reply_close(struct gdb_context* gdbctx)
867 unsigned char cksum;
868 int plen;
870 plen = gdbctx->out_len - gdbctx->out_curr_packet;
871 packet_reply_catc(gdbctx, '#');
872 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
873 packet_reply_hex_to(gdbctx, &cksum, 1);
874 if (gdbctx->trace & GDBPXY_TRC_PACKET)
875 fprintf(stderr, "Reply : %*.*s\n",
876 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
877 gdbctx->out_curr_packet = -1;
880 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
882 packet_reply_open(gdbctx);
884 if (len == -1) len = strlen(packet);
885 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
887 packet_reply_add(gdbctx, packet, len);
889 packet_reply_close(gdbctx);
891 return packet_done;
894 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
896 packet_reply_open(gdbctx);
898 packet_reply_add(gdbctx, "E", 1);
899 packet_reply_val(gdbctx, error, 1);
901 packet_reply_close(gdbctx);
903 return packet_done;
906 /* =============================================== *
907 * P A C K E T H A N D L E R S *
908 * =============================================== *
911 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
913 enum packet_return ret = packet_done;
915 packet_reply_open(gdbctx);
917 if (gdbctx->process != NULL)
919 unsigned char sig;
920 unsigned i;
922 packet_reply_catc(gdbctx, 'T');
923 sig = gdbctx->last_sig;
924 packet_reply_val(gdbctx, sig, 1);
925 packet_reply_add(gdbctx, "thread:", 7);
926 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
927 packet_reply_catc(gdbctx, ';');
929 for (i = 0; i < cpu_num_regs; i++)
931 /* FIXME: this call will also grow the buffer...
932 * unneeded, but not harmful
934 packet_reply_val(gdbctx, i, 1);
935 packet_reply_catc(gdbctx, ':');
936 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
937 packet_reply_catc(gdbctx, ';');
940 else
942 /* Try to put an exit code
943 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
944 * just indicate the end of process and exit */
945 packet_reply_add(gdbctx, "W00", 3);
946 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
949 packet_reply_close(gdbctx);
951 return ret;
954 #if 0
955 static enum packet_return packet_extended(struct gdb_context* gdbctx)
957 gdbctx->extended = 1;
958 return packet_ok;
960 #endif
962 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
964 assert(gdbctx->in_packet_len == 0);
965 return packet_reply_status(gdbctx);
968 static enum packet_return packet_continue(struct gdb_context* gdbctx)
970 /* FIXME: add support for address in packet */
971 assert(gdbctx->in_packet_len == 0);
972 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
973 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
974 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
975 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
976 resume_debuggee(gdbctx, DBG_CONTINUE);
977 wait_for_debuggee(gdbctx);
978 return packet_reply_status(gdbctx);
981 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
983 int i;
984 int defaultAction = -1; /* magic non action */
985 unsigned char sig;
986 int actions =0;
987 int actionIndex[20]; /* allow for up to 20 actions */
988 int threadIndex[20];
989 int threadCount = 0;
990 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
991 unsigned int threadID = 0;
992 struct dbg_thread* thd;
994 /* basic check */
995 assert(gdbctx->in_packet_len >= 4);
997 /* OK we have vCont followed by..
998 * ? for query
999 * c for packet_continue
1000 * Csig for packet_continue_signal
1001 * s for step
1002 * Ssig for step signal
1003 * and then an optional thread ID at the end..
1004 * *******************************************/
1006 fprintf(stderr, "trying to process a verbose packet\n");
1007 /* now check that we've got Cont */
1008 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
1010 /* Query */
1011 if (gdbctx->in_packet[4] == '?')
1014 Reply:
1015 `vCont[;action]...'
1016 The vCont packet is supported. Each action is a supported command in the vCont packet.
1018 The vCont packet is not supported. (this didn't seem to be obeyed!)
1020 packet_reply_open(gdbctx);
1021 packet_reply_add(gdbctx, "vCont", 5);
1022 /* add all the supported actions to the reply (all of them for now) */
1023 packet_reply_add(gdbctx, ";c", 2);
1024 packet_reply_add(gdbctx, ";C", 2);
1025 packet_reply_add(gdbctx, ";s", 2);
1026 packet_reply_add(gdbctx, ";S", 2);
1027 packet_reply_close(gdbctx);
1028 return packet_done;
1031 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1032 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1033 now if only gdb talked XML.... */
1034 #if 0 /* handy for debugging */
1035 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1036 #endif
1038 /* go through the packet and identify where all the actions start at */
1039 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1041 if (gdbctx->in_packet[i] == ';')
1043 threadIndex[actions] = 0;
1044 actionIndex[actions++] = i;
1046 else if (gdbctx->in_packet[i] == ':')
1048 threadIndex[actions - 1] = i;
1052 /* now look up the default action */
1053 for (i = 0 ; i < actions; i++)
1055 if (threadIndex[i] == 0)
1057 if (defaultAction != -1)
1059 fprintf(stderr,"Too many default actions specified\n");
1060 return packet_error;
1062 defaultAction = i;
1066 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1068 /* go through all the threads and stick their ids in the to be done list. */
1069 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1071 threadIDs[threadCount++] = thd->tid;
1072 /* check to see if we have more threads than I counted on, and tell the user what to do
1073 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1074 if (threadCount == 100)
1076 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1077 break;
1081 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1082 * that remains is to apply the actions to the threads and the default action to any threads
1083 * left */
1084 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1085 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1086 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
1087 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1089 /* deal with the threaded stuff first */
1090 for (i = 0; i < actions ; i++)
1092 if (threadIndex[i] != 0)
1094 int j, idLength = 0;
1095 if (i < actions - 1)
1097 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1099 else
1101 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1104 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1105 /* process the action */
1106 switch (gdbctx->in_packet[actionIndex[i] + 1])
1108 case 's': /* step */
1109 be_cpu->single_step(&gdbctx->context, TRUE);
1110 /* fall through*/
1111 case 'c': /* continue */
1112 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1113 break;
1114 case 'S': /* step Sig, */
1115 be_cpu->single_step(&gdbctx->context, TRUE);
1116 /* fall through */
1117 case 'C': /* continue sig */
1118 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1119 /* cannot change signals on the fly */
1120 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1121 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1122 if (sig != gdbctx->last_sig)
1123 return packet_error;
1124 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1125 break;
1127 for (j = 0 ; j < threadCount; j++)
1129 if (threadIDs[j] == threadID)
1131 threadIDs[j] = 0;
1132 break;
1136 } /* for i=0 ; i< actions */
1138 /* now we have manage the default action */
1139 if (defaultAction >= 0)
1141 for (i = 0 ; i< threadCount; i++)
1143 /* check to see if we've already done something to the thread*/
1144 if (threadIDs[i] != 0)
1146 /* if not apply the default action*/
1147 threadID = threadIDs[i];
1148 /* process the action (yes this is almost identical to the one above!) */
1149 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1151 case 's': /* step */
1152 be_cpu->single_step(&gdbctx->context, TRUE);
1153 /* fall through */
1154 case 'c': /* continue */
1155 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1156 break;
1157 case 'S':
1158 be_cpu->single_step(&gdbctx->context, TRUE);
1159 /* fall through */
1160 case 'C': /* continue sig */
1161 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1162 /* cannot change signals on the fly */
1163 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1164 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1165 if (sig != gdbctx->last_sig)
1166 return packet_error;
1167 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1168 break;
1172 } /* if(defaultAction >=0) */
1174 wait_for_debuggee(gdbctx);
1175 be_cpu->single_step(&gdbctx->context, FALSE);
1176 return packet_reply_status(gdbctx);
1179 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1181 unsigned char sig;
1183 /* FIXME: add support for address in packet */
1184 assert(gdbctx->in_packet_len == 2);
1185 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1186 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1187 fprintf(stderr, "NIY: cont/sig on %lu, while last thread is %lu\n",
1188 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1189 hex_from(&sig, gdbctx->in_packet, 1);
1190 /* cannot change signals on the fly */
1191 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1192 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1193 if (sig != gdbctx->last_sig)
1194 return packet_error;
1195 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1196 wait_for_debuggee(gdbctx);
1197 return packet_reply_status(gdbctx);
1200 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1202 detach_debuggee(gdbctx, FALSE);
1203 return packet_ok | packet_last_f;
1206 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1208 int i;
1209 CONTEXT ctx;
1210 CONTEXT* pctx = &gdbctx->context;
1212 assert(gdbctx->in_trap);
1214 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1216 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1217 return packet_error;
1220 packet_reply_open(gdbctx);
1221 for (i = 0; i < cpu_num_regs; i++)
1223 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1225 packet_reply_close(gdbctx);
1226 return packet_done;
1229 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1231 unsigned i;
1232 CONTEXT ctx;
1233 CONTEXT* pctx = &gdbctx->context;
1235 assert(gdbctx->in_trap);
1236 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1238 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1239 return packet_error;
1241 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1243 for (i = 0; i < cpu_num_regs; i++)
1244 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1245 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1247 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1248 fprintf(stderr, "Cannot set context on thread %lu\n", gdbctx->other_thread->tid);
1249 return packet_error;
1251 return packet_ok;
1254 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1256 detach_debuggee(gdbctx, TRUE);
1257 #if 0
1258 if (!gdbctx->extended)
1259 /* dunno whether GDB cares or not */
1260 #endif
1261 wait(NULL);
1262 exit(0);
1263 /* assume we can't really answer something here */
1264 /* return packet_done; */
1267 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1269 char* end;
1270 unsigned thread;
1272 switch (gdbctx->in_packet[0])
1274 case 'c':
1275 case 'g':
1276 if (gdbctx->in_packet[1] == '-')
1277 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1278 else
1279 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1280 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1282 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1283 fprintf(stderr, "Cannot get threadid %*.*s\n",
1284 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1285 gdbctx->in_packet + 1);
1286 return packet_error;
1288 if (gdbctx->in_packet[0] == 'c')
1289 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1290 else
1291 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1292 return packet_ok;
1293 default:
1294 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1295 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1296 return packet_error;
1300 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1302 char *addr;
1303 unsigned int len, blk_len, nread;
1304 char buffer[32];
1305 unsigned long r = 0;
1307 assert(gdbctx->in_trap);
1308 /* FIXME:check in_packet_len for reading %p,%x */
1309 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1310 if (len <= 0) return packet_error;
1311 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1312 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1313 for (nread = 0; nread < len; nread += r, addr += r)
1315 blk_len = min(sizeof(buffer), len - nread);
1316 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1317 r == 0)
1319 /* fail at first address, return error */
1320 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1321 /* something has already been read, return partial information */
1322 break;
1324 if (nread == 0) packet_reply_open(gdbctx);
1325 packet_reply_hex_to(gdbctx, buffer, r);
1327 packet_reply_close(gdbctx);
1328 return packet_done;
1331 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1333 char* addr;
1334 unsigned int len, blk_len;
1335 char* ptr;
1336 char buffer[32];
1337 unsigned long w;
1339 assert(gdbctx->in_trap);
1340 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1341 if (ptr == NULL)
1343 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1344 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1345 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1346 return packet_error;
1348 *ptr++ = '\0';
1350 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1352 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1353 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1354 return packet_error;
1356 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1358 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1359 fprintf(stderr, "Wrong sizes %u <> %u\n",
1360 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1361 return packet_error;
1363 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1364 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1365 while (len > 0)
1367 blk_len = min(sizeof(buffer), len);
1368 hex_from(buffer, ptr, blk_len);
1369 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1370 w != blk_len)
1371 break;
1372 addr += blk_len;
1373 len -= blk_len;
1374 ptr += blk_len;
1376 return packet_ok; /* FIXME: error while writing ? */
1379 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1381 unsigned reg;
1382 char* ptr;
1383 char* end;
1384 CONTEXT ctx;
1385 CONTEXT* pctx = &gdbctx->context;
1387 assert(gdbctx->in_trap);
1389 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1390 *ptr++ = '\0';
1391 reg = strtoul(gdbctx->in_packet, &end, 16);
1392 if (end == NULL || reg > cpu_num_regs)
1394 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1395 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1396 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1397 * it wouldn't matter too much, and it fakes our support for all regs
1399 return (end == NULL) ? packet_error : packet_ok;
1401 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1403 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1404 fprintf(stderr, "Wrong sizes %u <> %u\n",
1405 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1406 return packet_error;
1408 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1409 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1410 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1411 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1413 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1415 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1416 return packet_error;
1419 hex_from(cpu_register(pctx, reg), ptr, 4);
1420 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1422 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1423 fprintf(stderr, "Cannot set context for thread %lu\n", gdbctx->other_thread->tid);
1424 return packet_error;
1427 return packet_ok;
1430 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1432 char buffer[128];
1433 char clsName[128];
1434 char wndName[128];
1435 HWND child;
1437 do {
1438 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1439 strcpy(clsName, "-- Unknown --");
1440 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1441 strcpy(wndName, "-- Empty --");
1443 packet_reply_open(gdbctx);
1444 packet_reply_catc(gdbctx, 'O');
1445 snprintf(buffer, sizeof(buffer),
1446 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1447 indent, "", (UINT)hWnd, 13 - indent, "",
1448 clsName, GetWindowLong(hWnd, GWL_STYLE),
1449 GetWindowLongPtr(hWnd, GWLP_WNDPROC), wndName);
1450 packet_reply_hex_to_str(gdbctx, buffer);
1451 packet_reply_close(gdbctx);
1453 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1454 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1455 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1458 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1460 char buffer[128];
1462 /* we do the output in several 'O' packets, with the last one being just OK for
1463 * marking the end of the output */
1464 packet_reply_open(gdbctx);
1465 packet_reply_catc(gdbctx, 'O');
1466 snprintf(buffer, sizeof(buffer),
1467 "%-16.16s %-17.17s %-8.8s %s\n",
1468 "hwnd", "Class Name", " Style", " WndProc Text");
1469 packet_reply_hex_to_str(gdbctx, buffer);
1470 packet_reply_close(gdbctx);
1472 /* FIXME: could also add a pmt to this command in str... */
1473 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1474 packet_reply(gdbctx, "OK", 2);
1477 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1479 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1480 char buffer[128];
1481 char deco;
1482 PROCESSENTRY32 entry;
1483 BOOL ok;
1485 if (snap == INVALID_HANDLE_VALUE)
1486 return;
1488 entry.dwSize = sizeof(entry);
1489 ok = Process32First(snap, &entry);
1491 /* we do the output in several 'O' packets, with the last one being just OK for
1492 * marking the end of the output */
1494 packet_reply_open(gdbctx);
1495 packet_reply_catc(gdbctx, 'O');
1496 snprintf(buffer, sizeof(buffer),
1497 " %-8.8s %-8.8s %-8.8s %s\n",
1498 "pid", "threads", "parent", "executable");
1499 packet_reply_hex_to_str(gdbctx, buffer);
1500 packet_reply_close(gdbctx);
1502 while (ok)
1504 deco = ' ';
1505 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1506 packet_reply_open(gdbctx);
1507 packet_reply_catc(gdbctx, 'O');
1508 snprintf(buffer, sizeof(buffer),
1509 "%c%08lx %-8ld %08lx '%s'\n",
1510 deco, entry.th32ProcessID, entry.cntThreads,
1511 entry.th32ParentProcessID, entry.szExeFile);
1512 packet_reply_hex_to_str(gdbctx, buffer);
1513 packet_reply_close(gdbctx);
1514 ok = Process32Next(snap, &entry);
1516 CloseHandle(snap);
1517 packet_reply(gdbctx, "OK", 2);
1520 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1522 MEMORY_BASIC_INFORMATION mbi;
1523 char* addr = 0;
1524 const char* state;
1525 const char* type;
1526 char prot[3+1];
1527 char buffer[128];
1529 /* we do the output in several 'O' packets, with the last one being just OK for
1530 * marking the end of the output */
1531 packet_reply_open(gdbctx);
1532 packet_reply_catc(gdbctx, 'O');
1533 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1534 packet_reply_close(gdbctx);
1536 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1538 switch (mbi.State)
1540 case MEM_COMMIT: state = "commit "; break;
1541 case MEM_FREE: state = "free "; break;
1542 case MEM_RESERVE: state = "reserve"; break;
1543 default: state = "??? "; break;
1545 if (mbi.State != MEM_FREE)
1547 switch (mbi.Type)
1549 case MEM_IMAGE: type = "image "; break;
1550 case MEM_MAPPED: type = "mapped "; break;
1551 case MEM_PRIVATE: type = "private"; break;
1552 case 0: type = " "; break;
1553 default: type = "??? "; break;
1555 memset(prot, ' ' , sizeof(prot)-1);
1556 prot[sizeof(prot)-1] = '\0';
1557 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1558 prot[0] = 'R';
1559 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1560 prot[1] = 'W';
1561 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1562 prot[1] = 'C';
1563 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1564 prot[2] = 'X';
1566 else
1568 type = "";
1569 prot[0] = '\0';
1571 packet_reply_open(gdbctx);
1572 snprintf(buffer, sizeof(buffer),
1573 "%08lx %08lx %s %s %s\n",
1574 (DWORD)addr, mbi.RegionSize, state, type, prot);
1575 packet_reply_catc(gdbctx, 'O');
1576 packet_reply_hex_to_str(gdbctx, buffer);
1577 packet_reply_close(gdbctx);
1579 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1580 break;
1581 addr += mbi.RegionSize;
1583 packet_reply(gdbctx, "OK", 2);
1586 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1587 int len, const char* str)
1589 char buffer[128];
1591 if (len == 0)
1593 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1595 else if (len >= 2 && str[0] == '=')
1597 unsigned val = atoi(&str[1]);
1598 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1599 gdbctx->trace = val;
1601 else
1603 /* FIXME: ugly but can use error packet here */
1604 packet_reply_cat(gdbctx, "E00");
1605 return;
1607 packet_reply_open(gdbctx);
1608 packet_reply_hex_to_str(gdbctx, buffer);
1609 packet_reply_close(gdbctx);
1612 struct query_detail
1614 int with_arg;
1615 const char* name;
1616 size_t len;
1617 void (*handler)(struct gdb_context*, int, const char*);
1618 } query_details[] =
1620 {0, "wnd", 3, packet_query_monitor_wnd},
1621 {0, "window", 6, packet_query_monitor_wnd},
1622 {0, "proc", 4, packet_query_monitor_process},
1623 {0, "process", 7, packet_query_monitor_process},
1624 {0, "mem", 3, packet_query_monitor_mem},
1625 {1, "trace", 5, packet_query_monitor_trace},
1626 {0, NULL, 0, NULL},
1629 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1630 const char* hxcmd, size_t len)
1632 char buffer[128];
1633 struct query_detail* qd;
1635 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1636 len /= 2;
1637 hex_from(buffer, hxcmd, len);
1639 for (qd = &query_details[0]; qd->name != NULL; qd++)
1641 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1642 if (!qd->with_arg && len != qd->len) continue;
1644 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1645 return packet_done;
1647 return packet_reply_error(gdbctx, EINVAL);
1650 static enum packet_return packet_query(struct gdb_context* gdbctx)
1652 switch (gdbctx->in_packet[0])
1654 case 'f':
1655 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1657 struct dbg_thread* thd;
1659 packet_reply_open(gdbctx);
1660 packet_reply_add(gdbctx, "m", 1);
1661 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1663 packet_reply_val(gdbctx, thd->tid, 4);
1664 if (thd->next != NULL)
1665 packet_reply_add(gdbctx, ",", 1);
1667 packet_reply_close(gdbctx);
1668 return packet_done;
1670 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1672 char result[128];
1674 packet_reply_open(gdbctx);
1675 packet_reply_catc(gdbctx, 'O');
1676 get_process_info(gdbctx, result, sizeof(result));
1677 packet_reply_hex_to_str(gdbctx, result);
1678 packet_reply_close(gdbctx);
1679 return packet_done;
1681 break;
1682 case 's':
1683 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1685 packet_reply(gdbctx, "l", 1);
1686 return packet_done;
1688 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1690 packet_reply(gdbctx, "l", 1);
1691 return packet_done;
1693 break;
1694 case 'C':
1695 if (gdbctx->in_packet_len == 1)
1697 struct dbg_thread* thd;
1698 /* FIXME: doc says 16 bit val ??? */
1699 /* grab first created thread, aka last in list */
1700 assert(gdbctx->process && gdbctx->process->threads);
1701 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1702 packet_reply_open(gdbctx);
1703 packet_reply_add(gdbctx, "QC", 2);
1704 packet_reply_val(gdbctx, thd->tid, 4);
1705 packet_reply_close(gdbctx);
1706 return packet_done;
1708 break;
1709 case 'O':
1710 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1712 char buf[64];
1714 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1715 gdbctx->wine_segs[2] == 0)
1716 return packet_error;
1717 snprintf(buf, sizeof(buf),
1718 "Text=%08lx;Data=%08lx;Bss=%08lx",
1719 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1720 gdbctx->wine_segs[2]);
1721 return packet_reply(gdbctx, buf, -1);
1723 break;
1724 case 'R':
1725 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1727 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1728 gdbctx->in_packet_len - 5);
1730 break;
1731 case 'S':
1732 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1733 return packet_ok;
1734 break;
1735 case 'T':
1736 if (gdbctx->in_packet_len > 15 &&
1737 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1738 gdbctx->in_packet[15] == ',')
1740 unsigned tid;
1741 char* end;
1742 char result[128];
1744 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1745 if (end == NULL) break;
1746 get_thread_info(gdbctx, tid, result, sizeof(result));
1747 packet_reply_open(gdbctx);
1748 packet_reply_hex_to_str(gdbctx, result);
1749 packet_reply_close(gdbctx);
1750 return packet_done;
1752 break;
1754 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1755 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1756 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1757 return packet_error;
1760 static enum packet_return packet_step(struct gdb_context* gdbctx)
1762 /* FIXME: add support for address in packet */
1763 assert(gdbctx->in_packet_len == 0);
1764 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1765 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1766 fprintf(stderr, "NIY: step on %lu, while last thread is %lu\n",
1767 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1768 be_cpu->single_step(&gdbctx->context, TRUE);
1769 resume_debuggee(gdbctx, DBG_CONTINUE);
1770 wait_for_debuggee(gdbctx);
1771 be_cpu->single_step(&gdbctx->context, FALSE);
1772 return packet_reply_status(gdbctx);
1775 #if 0
1776 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1778 unsigned char sig;
1780 /* FIXME: add support for address in packet */
1781 assert(gdbctx->in_packet_len == 2);
1782 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1783 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1784 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1785 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1786 hex_from(&sig, gdbctx->in_packet, 1);
1787 /* cannot change signals on the fly */
1788 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1789 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1790 if (sig != gdbctx->last_sig)
1791 return packet_error;
1792 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1793 wait_for_debuggee(gdbctx);
1794 return packet_reply_status(gdbctx);
1796 #endif
1798 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1800 char* end;
1801 unsigned tid;
1803 tid = strtol(gdbctx->in_packet, &end, 16);
1804 if (tid == -1 || tid == 0)
1805 return packet_reply_error(gdbctx, EINVAL);
1806 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1807 return packet_ok;
1808 return packet_reply_error(gdbctx, ESRCH);
1811 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1813 void* addr;
1814 unsigned len;
1815 struct gdb_ctx_Xpoint* xpt;
1816 enum be_xpoint_type t;
1818 /* FIXME: check packet_len */
1819 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1820 gdbctx->in_packet[1] != ',' ||
1821 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1822 return packet_error;
1823 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1824 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1825 addr, len, gdbctx->in_packet[0]);
1826 switch (gdbctx->in_packet[0])
1828 case '0': t = be_xpoint_break; len = 0; break;
1829 case '1': t = be_xpoint_watch_exec; break;
1830 case '2': t = be_xpoint_watch_read; break;
1831 case '3': t = be_xpoint_watch_write; break;
1832 default: return packet_error;
1834 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1836 if (xpt->addr == addr && xpt->type == t)
1838 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1839 gdbctx->process->process_io, &gdbctx->context,
1840 t, xpt->addr, xpt->val, len))
1842 xpt->type = -1;
1843 return packet_ok;
1845 break;
1848 return packet_error;
1851 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1853 void* addr;
1854 unsigned len;
1855 struct gdb_ctx_Xpoint* xpt;
1856 enum be_xpoint_type t;
1858 /* FIXME: check packet_len */
1859 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1860 gdbctx->in_packet[1] != ',' ||
1861 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1862 return packet_error;
1863 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1864 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1865 addr, len, gdbctx->in_packet[0]);
1866 switch (gdbctx->in_packet[0])
1868 case '0': t = be_xpoint_break; len = 0; break;
1869 case '1': t = be_xpoint_watch_exec; break;
1870 case '2': t = be_xpoint_watch_read; break;
1871 case '3': t = be_xpoint_watch_write; break;
1872 default: return packet_error;
1874 /* because of packet command handling, this should be made idempotent */
1875 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1877 if (xpt->addr == addr && xpt->type == t)
1878 return packet_ok; /* nothing to do */
1880 /* really set the Xpoint */
1881 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1883 if (xpt->type == -1)
1885 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1886 gdbctx->process->process_io, &gdbctx->context,
1887 t, addr, &xpt->val, len))
1889 xpt->addr = addr;
1890 xpt->type = t;
1891 return packet_ok;
1893 fprintf(stderr, "cannot set xpoint\n");
1894 break;
1897 /* no more entries... eech */
1898 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1899 return packet_error;
1902 /* =============================================== *
1903 * P A C K E T I N F R A S T R U C T U R E *
1904 * =============================================== *
1907 struct packet_entry
1909 char key;
1910 enum packet_return (*handler)(struct gdb_context* gdbctx);
1913 static struct packet_entry packet_entries[] =
1915 /*{'!', packet_extended}, */
1916 {'?', packet_last_signal},
1917 {'c', packet_continue},
1918 {'C', packet_continue_signal},
1919 {'D', packet_detach},
1920 {'g', packet_read_registers},
1921 {'G', packet_write_registers},
1922 {'k', packet_kill},
1923 {'H', packet_thread},
1924 {'m', packet_read_memory},
1925 {'M', packet_write_memory},
1926 /* {'p', packet_read_register}, doesn't seem needed */
1927 {'P', packet_write_register},
1928 {'q', packet_query},
1929 /* {'Q', packet_set}, */
1930 /* {'R', packet,restart}, only in extended mode ! */
1931 {'s', packet_step},
1932 /*{'S', packet_step_signal}, hard(er) to implement */
1933 {'T', packet_thread_alive},
1934 {'v', packet_verbose},
1935 {'z', packet_remove_breakpoint},
1936 {'Z', packet_set_breakpoint},
1939 static BOOL extract_packets(struct gdb_context* gdbctx)
1941 char* end;
1942 int plen;
1943 unsigned char in_cksum, loc_cksum;
1944 char* ptr;
1945 enum packet_return ret = packet_error;
1946 int num_packet = 0;
1948 while ((ret & packet_last_f) == 0)
1950 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1951 fprintf(stderr, "In-buf: %*.*s\n",
1952 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1953 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1954 if (ptr == NULL) return FALSE;
1955 if (ptr != gdbctx->in_buf)
1957 int glen = ptr - gdbctx->in_buf; /* garbage len */
1958 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1959 fprintf(stderr, "Removing garbage: %*.*s\n",
1960 glen, glen, gdbctx->in_buf);
1961 gdbctx->in_len -= glen;
1962 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1964 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1965 if (end == NULL) return FALSE;
1966 /* no checksum yet */
1967 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1968 plen = end - gdbctx->in_buf - 1;
1969 hex_from(&in_cksum, end + 1, 1);
1970 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1971 if (loc_cksum == in_cksum)
1973 if (num_packet == 0) {
1974 int i;
1976 ret = packet_error;
1978 write(gdbctx->sock, "+", 1);
1979 assert(plen);
1981 /* FIXME: should use bsearch if packet_entries was sorted */
1982 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1984 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1986 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1988 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1989 fprintf(stderr, "Unknown packet request %*.*s\n",
1990 plen, plen, &gdbctx->in_buf[1]);
1992 else
1994 gdbctx->in_packet = gdbctx->in_buf + 2;
1995 gdbctx->in_packet_len = plen - 1;
1996 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1997 fprintf(stderr, "Packet: %c%*.*s\n",
1998 gdbctx->in_buf[1],
1999 gdbctx->in_packet_len, gdbctx->in_packet_len,
2000 gdbctx->in_packet);
2001 ret = (packet_entries[i].handler)(gdbctx);
2003 switch (ret & ~packet_last_f)
2005 case packet_error: packet_reply(gdbctx, "", 0); break;
2006 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2007 case packet_done: break;
2009 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2010 fprintf(stderr, "Reply-full: %*.*s\n",
2011 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2012 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2013 assert(i == gdbctx->out_len);
2014 /* if this fails, we'll have to use POLLOUT...
2016 gdbctx->out_len = 0;
2017 num_packet++;
2019 else
2021 /* FIXME: if we have in our input buffer more than one packet,
2022 * it's very likely that we took too long to answer to a given packet
2023 * and gdb is sending us again the same packet
2024 * We simply drop the second packet. This will lower the risk of error,
2025 * but there's still some race conditions here
2026 * A better fix (yet not perfect) would be to have two threads:
2027 * - one managing the packets for gdb
2028 * - the second one managing the commands...
2029 * This would allow us also the reply with the '+' character (Ack of
2030 * the command) way sooner than what we do now
2032 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2033 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2036 else
2038 write(gdbctx->sock, "+", 1);
2039 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2040 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2042 gdbctx->in_len -= plen + 4;
2043 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2045 return TRUE;
2048 static int fetch_data(struct gdb_context* gdbctx)
2050 int len, in_len = gdbctx->in_len;
2052 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2053 for (;;)
2055 #define STEP 128
2056 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2057 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2058 #undef STEP
2059 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2060 fprintf(stderr, "%d %d %*.*s\n",
2061 gdbctx->in_len, gdbctx->in_buf_alloc,
2062 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2063 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2064 if (len <= 0) break;
2065 gdbctx->in_len += len;
2066 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2067 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2069 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2070 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2071 return gdbctx->in_len - in_len;
2074 #define FLAG_NO_START 1
2075 #define FLAG_WITH_XTERM 2
2077 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2079 char buf[MAX_PATH];
2080 int fd;
2081 const char* gdb_path;
2082 FILE* f;
2084 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2085 strcpy(buf,"/tmp/winegdb.XXXXXX");
2086 fd = mkstemps(buf, 0);
2087 if (fd == -1) return FALSE;
2088 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2089 fprintf(f, "file %s\n", wine_path);
2090 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2091 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2092 fprintf(f, "set prompt Wine-gdb>\\ \n");
2093 /* gdb 5.1 seems to require it, won't hurt anyway */
2094 fprintf(f, "sharedlibrary\n");
2095 /* This is needed (but not a decent & final fix)
2096 * Without this, gdb would skip our inter-DLL relay code (because
2097 * we don't have any line number information for the relay code)
2098 * With this, we will stop on first instruction of the stub, and
2099 * reusing step, will get us through the relay stub at the actual
2100 * function we're looking at.
2102 fprintf(f, "set step-mode on\n");
2103 /* tell gdb to delete this file when done handling it... */
2104 fprintf(f, "shell rm -f \"%s\"\n", buf);
2105 fclose(f);
2106 if (flags & FLAG_WITH_XTERM)
2107 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2108 else
2109 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2110 assert(0); /* never reached */
2111 return TRUE;
2114 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2116 int sock;
2117 struct sockaddr_in s_addrs;
2118 unsigned int s_len = sizeof(s_addrs);
2119 struct pollfd pollfd;
2120 IMAGEHLP_MODULE imh_mod;
2122 /* step 1: create socket for gdb connection request */
2123 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2125 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2126 fprintf(stderr, "Can't create socket");
2127 return FALSE;
2130 if (listen(sock, 1) == -1 ||
2131 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2132 return FALSE;
2134 /* step 2: do the process internal creation */
2135 handle_debug_event(gdbctx, de);
2137 /* step3: get the wine loader name */
2138 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2140 /* step 4: fire up gdb (if requested) */
2141 if (flags & FLAG_NO_START)
2142 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2143 else
2144 switch (fork())
2146 case -1: /* error in parent... */
2147 fprintf(stderr, "Cannot create gdb\n");
2148 return FALSE;
2149 break;
2150 default: /* in parent... success */
2151 break;
2152 case 0: /* in child... and alive */
2153 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2154 /* if we're here, exec failed, so report failure */
2155 return FALSE;
2158 /* step 5: wait for gdb to connect actually */
2159 pollfd.fd = sock;
2160 pollfd.events = POLLIN;
2161 pollfd.revents = 0;
2163 switch (poll(&pollfd, 1, -1))
2165 case 1:
2166 if (pollfd.revents & POLLIN)
2168 int dummy = 1;
2169 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2170 if (gdbctx->sock == -1)
2171 break;
2172 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2173 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2174 /* don't keep our small packets too long: send them ASAP back to GDB
2175 * without this, GDB really crawls
2177 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2179 break;
2180 case 0:
2181 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2182 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2183 return FALSE;
2184 case -1:
2185 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2186 fprintf(stderr, "Poll for cnx failed (error)\n");
2187 return FALSE;
2188 default:
2189 assert(0);
2192 close(sock);
2193 return TRUE;
2196 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2198 DEBUG_EVENT de;
2199 int i;
2201 gdbctx->sock = -1;
2202 gdbctx->in_buf = NULL;
2203 gdbctx->in_buf_alloc = 0;
2204 gdbctx->in_len = 0;
2205 gdbctx->out_buf = NULL;
2206 gdbctx->out_buf_alloc = 0;
2207 gdbctx->out_len = 0;
2208 gdbctx->out_curr_packet = -1;
2210 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2211 gdbctx->last_sig = 0;
2212 gdbctx->in_trap = FALSE;
2213 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2214 gdbctx->process = NULL;
2215 for (i = 0; i < NUM_XPOINT; i++)
2216 gdbctx->Xpoints[i].type = -1;
2218 /* wait for first trap */
2219 while (WaitForDebugEvent(&de, INFINITE))
2221 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2223 /* this should be the first event we get,
2224 * and the only one of this type */
2225 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2226 /* gdbctx->dwProcessId = pid; */
2227 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2228 assert(!gdbctx->in_trap);
2230 else
2232 handle_debug_event(gdbctx, &de);
2233 if (gdbctx->in_trap) break;
2235 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2237 return TRUE;
2240 static int gdb_remote(unsigned flags)
2242 struct pollfd pollfd;
2243 struct gdb_context gdbctx;
2244 BOOL doLoop;
2246 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2248 pollfd.fd = gdbctx.sock;
2249 pollfd.events = POLLIN;
2250 pollfd.revents = 0;
2252 switch (poll(&pollfd, 1, -1))
2254 case 1:
2255 /* got something */
2256 if (pollfd.revents & (POLLHUP | POLLERR))
2258 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2259 fprintf(stderr, "Gdb hung up\n");
2260 /* kill also debuggee process - questionnable - */
2261 detach_debuggee(&gdbctx, TRUE);
2262 doLoop = FALSE;
2263 break;
2265 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2267 if (extract_packets(&gdbctx)) doLoop = FALSE;
2269 break;
2270 case 0:
2271 /* timeout, should never happen (infinite timeout) */
2272 break;
2273 case -1:
2274 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2275 fprintf(stderr, "Poll failed\n");
2276 doLoop = FALSE;
2277 break;
2280 wait(NULL);
2281 return 0;
2284 int gdb_main(int argc, char* argv[])
2286 unsigned gdb_flags = 0;
2288 argc--; argv++;
2289 while (argc > 0 && argv[0][0] == '-')
2291 if (strcmp(argv[0], "--no-start") == 0)
2293 gdb_flags |= FLAG_NO_START;
2294 argc--; argv++;
2295 continue;
2297 if (strcmp(argv[0], "--with-xterm") == 0)
2299 gdb_flags |= FLAG_WITH_XTERM;
2300 argc--; argv++;
2301 continue;
2303 return -1;
2305 if (dbg_active_attach(argc, argv) == start_ok ||
2306 dbg_active_launch(argc, argv) == start_ok)
2307 return gdb_remote(gdb_flags);
2308 return -1;
2311 static struct be_process_io be_process_gdbproxy_io =
2313 NULL, /* we shouldn't use close_process() in gdbproxy */
2314 ReadProcessMemory,
2315 WriteProcessMemory