dinput: Fix the compile for missing EV_SYN define.
[wine/multimedia.git] / programs / winedbg / gdbproxy.c
blob6a448d378bb7efdd031b542926a2d468af8bc82a
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 /* =============================================== *
106 * B A S I C M A N I P U L A T I O N S *
107 * =============================================== *
110 static inline int hex_from0(char ch)
112 if (ch >= '0' && ch <= '9') return ch - '0';
113 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
114 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
116 assert(0);
117 return 0;
120 static inline unsigned char hex_to0(int x)
122 assert(x >= 0 && x < 16);
123 return "0123456789abcdef"[x];
126 static int hex_to_int(const char* src, size_t len)
128 unsigned int returnval = 0;
129 while (len--)
131 returnval <<= 4;
132 returnval |= hex_from0(*src++);
134 return returnval;
137 static void hex_from(void* dst, const char* src, size_t len)
139 unsigned char *p = dst;
140 while (len--)
142 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
143 src += 2;
147 static void hex_to(char* dst, const void* src, size_t len)
149 const unsigned char *p = src;
150 while (len--)
152 *dst++ = hex_to0(*p >> 4);
153 *dst++ = hex_to0(*p & 0x0F);
154 p++;
158 static unsigned char checksum(const char* ptr, int len)
160 unsigned cksum = 0;
162 while (len-- > 0)
163 cksum += (unsigned char)*ptr++;
164 return cksum;
167 /* =============================================== *
168 * C P U H A N D L E R S *
169 * =============================================== *
172 #ifdef __i386__
173 static size_t cpu_register_map[] = {
174 FIELD_OFFSET(CONTEXT, Eax),
175 FIELD_OFFSET(CONTEXT, Ecx),
176 FIELD_OFFSET(CONTEXT, Edx),
177 FIELD_OFFSET(CONTEXT, Ebx),
178 FIELD_OFFSET(CONTEXT, Esp),
179 FIELD_OFFSET(CONTEXT, Ebp),
180 FIELD_OFFSET(CONTEXT, Esi),
181 FIELD_OFFSET(CONTEXT, Edi),
182 FIELD_OFFSET(CONTEXT, Eip),
183 FIELD_OFFSET(CONTEXT, EFlags),
184 FIELD_OFFSET(CONTEXT, SegCs),
185 FIELD_OFFSET(CONTEXT, SegSs),
186 FIELD_OFFSET(CONTEXT, SegDs),
187 FIELD_OFFSET(CONTEXT, SegEs),
188 FIELD_OFFSET(CONTEXT, SegFs),
189 FIELD_OFFSET(CONTEXT, SegGs),
191 #elif defined(__powerpc__)
192 static size_t cpu_register_map[] = {
193 FIELD_OFFSET(CONTEXT, Gpr0),
194 FIELD_OFFSET(CONTEXT, Gpr1),
195 FIELD_OFFSET(CONTEXT, Gpr2),
196 FIELD_OFFSET(CONTEXT, Gpr3),
197 FIELD_OFFSET(CONTEXT, Gpr4),
198 FIELD_OFFSET(CONTEXT, Gpr5),
199 FIELD_OFFSET(CONTEXT, Gpr6),
200 FIELD_OFFSET(CONTEXT, Gpr7),
201 FIELD_OFFSET(CONTEXT, Gpr8),
202 FIELD_OFFSET(CONTEXT, Gpr9),
203 FIELD_OFFSET(CONTEXT, Gpr10),
204 FIELD_OFFSET(CONTEXT, Gpr11),
205 FIELD_OFFSET(CONTEXT, Gpr12),
206 FIELD_OFFSET(CONTEXT, Gpr13),
207 FIELD_OFFSET(CONTEXT, Gpr14),
208 FIELD_OFFSET(CONTEXT, Gpr15),
209 FIELD_OFFSET(CONTEXT, Gpr16),
210 FIELD_OFFSET(CONTEXT, Gpr17),
211 FIELD_OFFSET(CONTEXT, Gpr18),
212 FIELD_OFFSET(CONTEXT, Gpr19),
213 FIELD_OFFSET(CONTEXT, Gpr20),
214 FIELD_OFFSET(CONTEXT, Gpr21),
215 FIELD_OFFSET(CONTEXT, Gpr22),
216 FIELD_OFFSET(CONTEXT, Gpr23),
217 FIELD_OFFSET(CONTEXT, Gpr24),
218 FIELD_OFFSET(CONTEXT, Gpr25),
219 FIELD_OFFSET(CONTEXT, Gpr26),
220 FIELD_OFFSET(CONTEXT, Gpr27),
221 FIELD_OFFSET(CONTEXT, Gpr28),
222 FIELD_OFFSET(CONTEXT, Gpr29),
223 FIELD_OFFSET(CONTEXT, Gpr30),
224 FIELD_OFFSET(CONTEXT, Gpr31),
225 FIELD_OFFSET(CONTEXT, Fpr0),
226 FIELD_OFFSET(CONTEXT, Fpr1),
227 FIELD_OFFSET(CONTEXT, Fpr2),
228 FIELD_OFFSET(CONTEXT, Fpr3),
229 FIELD_OFFSET(CONTEXT, Fpr4),
230 FIELD_OFFSET(CONTEXT, Fpr5),
231 FIELD_OFFSET(CONTEXT, Fpr6),
232 FIELD_OFFSET(CONTEXT, Fpr7),
233 FIELD_OFFSET(CONTEXT, Fpr8),
234 FIELD_OFFSET(CONTEXT, Fpr9),
235 FIELD_OFFSET(CONTEXT, Fpr10),
236 FIELD_OFFSET(CONTEXT, Fpr11),
237 FIELD_OFFSET(CONTEXT, Fpr12),
238 FIELD_OFFSET(CONTEXT, Fpr13),
239 FIELD_OFFSET(CONTEXT, Fpr14),
240 FIELD_OFFSET(CONTEXT, Fpr15),
241 FIELD_OFFSET(CONTEXT, Fpr16),
242 FIELD_OFFSET(CONTEXT, Fpr17),
243 FIELD_OFFSET(CONTEXT, Fpr18),
244 FIELD_OFFSET(CONTEXT, Fpr19),
245 FIELD_OFFSET(CONTEXT, Fpr20),
246 FIELD_OFFSET(CONTEXT, Fpr21),
247 FIELD_OFFSET(CONTEXT, Fpr22),
248 FIELD_OFFSET(CONTEXT, Fpr23),
249 FIELD_OFFSET(CONTEXT, Fpr24),
250 FIELD_OFFSET(CONTEXT, Fpr25),
251 FIELD_OFFSET(CONTEXT, Fpr26),
252 FIELD_OFFSET(CONTEXT, Fpr27),
253 FIELD_OFFSET(CONTEXT, Fpr28),
254 FIELD_OFFSET(CONTEXT, Fpr29),
255 FIELD_OFFSET(CONTEXT, Fpr30),
256 FIELD_OFFSET(CONTEXT, Fpr31),
258 FIELD_OFFSET(CONTEXT, Iar),
259 FIELD_OFFSET(CONTEXT, Msr),
260 FIELD_OFFSET(CONTEXT, Cr),
261 FIELD_OFFSET(CONTEXT, Lr),
262 FIELD_OFFSET(CONTEXT, Ctr),
263 FIELD_OFFSET(CONTEXT, Xer),
264 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
265 /* see gdb/nlm/ppc.c */
267 #elif defined(__ALPHA__)
268 static size_t cpu_register_map[] = {
269 FIELD_OFFSET(CONTEXT, IntV0),
270 FIELD_OFFSET(CONTEXT, IntT0),
271 FIELD_OFFSET(CONTEXT, IntT1),
272 FIELD_OFFSET(CONTEXT, IntT2),
273 FIELD_OFFSET(CONTEXT, IntT3),
274 FIELD_OFFSET(CONTEXT, IntT4),
275 FIELD_OFFSET(CONTEXT, IntT5),
276 FIELD_OFFSET(CONTEXT, IntT6),
277 FIELD_OFFSET(CONTEXT, IntT7),
278 FIELD_OFFSET(CONTEXT, IntS0),
279 FIELD_OFFSET(CONTEXT, IntS1),
280 FIELD_OFFSET(CONTEXT, IntS2),
281 FIELD_OFFSET(CONTEXT, IntS3),
282 FIELD_OFFSET(CONTEXT, IntS4),
283 FIELD_OFFSET(CONTEXT, IntS5),
284 FIELD_OFFSET(CONTEXT, IntFp),
285 FIELD_OFFSET(CONTEXT, IntA0),
286 FIELD_OFFSET(CONTEXT, IntA1),
287 FIELD_OFFSET(CONTEXT, IntA2),
288 FIELD_OFFSET(CONTEXT, IntA3),
289 FIELD_OFFSET(CONTEXT, IntA4),
290 FIELD_OFFSET(CONTEXT, IntA5),
291 FIELD_OFFSET(CONTEXT, IntT8),
292 FIELD_OFFSET(CONTEXT, IntT9),
293 FIELD_OFFSET(CONTEXT, IntT10),
294 FIELD_OFFSET(CONTEXT, IntT11),
295 FIELD_OFFSET(CONTEXT, IntRa),
296 FIELD_OFFSET(CONTEXT, IntT12),
297 FIELD_OFFSET(CONTEXT, IntAt),
298 FIELD_OFFSET(CONTEXT, IntGp),
299 FIELD_OFFSET(CONTEXT, IntSp),
300 FIELD_OFFSET(CONTEXT, IntZero),
301 FIELD_OFFSET(CONTEXT, FltF0),
302 FIELD_OFFSET(CONTEXT, FltF1),
303 FIELD_OFFSET(CONTEXT, FltF2),
304 FIELD_OFFSET(CONTEXT, FltF3),
305 FIELD_OFFSET(CONTEXT, FltF4),
306 FIELD_OFFSET(CONTEXT, FltF5),
307 FIELD_OFFSET(CONTEXT, FltF6),
308 FIELD_OFFSET(CONTEXT, FltF7),
309 FIELD_OFFSET(CONTEXT, FltF8),
310 FIELD_OFFSET(CONTEXT, FltF9),
311 FIELD_OFFSET(CONTEXT, FltF10),
312 FIELD_OFFSET(CONTEXT, FltF11),
313 FIELD_OFFSET(CONTEXT, FltF12),
314 FIELD_OFFSET(CONTEXT, FltF13),
315 FIELD_OFFSET(CONTEXT, FltF14),
316 FIELD_OFFSET(CONTEXT, FltF15),
317 FIELD_OFFSET(CONTEXT, FltF16),
318 FIELD_OFFSET(CONTEXT, FltF17),
319 FIELD_OFFSET(CONTEXT, FltF18),
320 FIELD_OFFSET(CONTEXT, FltF19),
321 FIELD_OFFSET(CONTEXT, FltF20),
322 FIELD_OFFSET(CONTEXT, FltF21),
323 FIELD_OFFSET(CONTEXT, FltF22),
324 FIELD_OFFSET(CONTEXT, FltF23),
325 FIELD_OFFSET(CONTEXT, FltF24),
326 FIELD_OFFSET(CONTEXT, FltF25),
327 FIELD_OFFSET(CONTEXT, FltF26),
328 FIELD_OFFSET(CONTEXT, FltF27),
329 FIELD_OFFSET(CONTEXT, FltF28),
330 FIELD_OFFSET(CONTEXT, FltF29),
331 FIELD_OFFSET(CONTEXT, FltF30),
332 FIELD_OFFSET(CONTEXT, FltF31),
334 /* FIXME: Didn't look for the right order yet */
335 FIELD_OFFSET(CONTEXT, Fir),
336 FIELD_OFFSET(CONTEXT, Fpcr),
337 FIELD_OFFSET(CONTEXT, SoftFpcr),
339 #else
340 # error Define the registers map for your CPU
341 #endif
343 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
345 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
347 assert(idx < cpu_num_regs);
348 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
351 /* =============================================== *
352 * W I N 3 2 D E B U G I N T E R F A C E *
353 * =============================================== *
356 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
358 ctx->ContextFlags = CONTEXT_CONTROL
359 | CONTEXT_INTEGER
360 #ifdef CONTEXT_SEGMENTS
361 | CONTEXT_SEGMENTS
362 #endif
363 #ifdef CONTEXT_DEBUG_REGISTERS
364 | CONTEXT_DEBUG_REGISTERS
365 #endif
367 if (!GetThreadContext(h, ctx))
369 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
370 fprintf(stderr, "Can't get thread's context\n");
371 return FALSE;
373 return TRUE;
376 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
378 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
379 BOOL ret = FALSE;
381 switch (rec->ExceptionCode)
383 case EXCEPTION_ACCESS_VIOLATION:
384 case EXCEPTION_PRIV_INSTRUCTION:
385 case EXCEPTION_STACK_OVERFLOW:
386 case EXCEPTION_GUARD_PAGE:
387 gdbctx->last_sig = SIGSEGV;
388 ret = TRUE;
389 break;
390 case EXCEPTION_DATATYPE_MISALIGNMENT:
391 gdbctx->last_sig = SIGBUS;
392 ret = TRUE;
393 break;
394 case EXCEPTION_SINGLE_STEP:
395 /* fall thru */
396 case EXCEPTION_BREAKPOINT:
397 gdbctx->last_sig = SIGTRAP;
398 ret = TRUE;
399 break;
400 case EXCEPTION_FLT_DENORMAL_OPERAND:
401 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
402 case EXCEPTION_FLT_INEXACT_RESULT:
403 case EXCEPTION_FLT_INVALID_OPERATION:
404 case EXCEPTION_FLT_OVERFLOW:
405 case EXCEPTION_FLT_STACK_CHECK:
406 case EXCEPTION_FLT_UNDERFLOW:
407 gdbctx->last_sig = SIGFPE;
408 ret = TRUE;
409 break;
410 case EXCEPTION_INT_DIVIDE_BY_ZERO:
411 case EXCEPTION_INT_OVERFLOW:
412 gdbctx->last_sig = SIGFPE;
413 ret = TRUE;
414 break;
415 case EXCEPTION_ILLEGAL_INSTRUCTION:
416 gdbctx->last_sig = SIGILL;
417 ret = TRUE;
418 break;
419 case CONTROL_C_EXIT:
420 gdbctx->last_sig = SIGINT;
421 ret = TRUE;
422 break;
423 case STATUS_POSSIBLE_DEADLOCK:
424 gdbctx->last_sig = SIGALRM;
425 ret = TRUE;
426 /* FIXME: we could also add here a O packet with additional information */
427 break;
428 default:
429 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
430 fprintf(stderr, "Unhandled exception code 0x%08lx\n", rec->ExceptionCode);
431 gdbctx->last_sig = SIGABRT;
432 ret = TRUE;
433 break;
435 return ret;
438 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
440 char buffer[256];
442 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
444 switch (de->dwDebugEventCode)
446 case CREATE_PROCESS_DEBUG_EVENT:
447 gdbctx->process = dbg_add_process(de->dwProcessId,
448 de->u.CreateProcessInfo.hProcess);
449 if (!gdbctx->process) break;
450 memory_get_string_indirect(gdbctx->process,
451 de->u.CreateProcessInfo.lpImageName,
452 de->u.CreateProcessInfo.fUnicode,
453 buffer, sizeof(buffer));
454 dbg_set_process_name(gdbctx->process, buffer);
456 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
457 fprintf(stderr, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
458 de->dwProcessId, de->dwThreadId,
459 buffer, de->u.CreateProcessInfo.lpImageName,
460 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress,
461 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
462 de->u.CreateProcessInfo.nDebugInfoSize);
464 /* de->u.CreateProcessInfo.lpStartAddress; */
465 if (!SymInitialize(gdbctx->process->handle, NULL, TRUE))
466 fprintf(stderr, "Couldn't initiate DbgHelp\n");
468 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
469 fprintf(stderr, "%08lx:%08lx: create thread I @%08lx\n",
470 de->dwProcessId, de->dwThreadId,
471 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress);
473 assert(dbg_curr_thread == NULL); /* shouldn't be there */
474 dbg_add_thread(gdbctx->process, de->dwThreadId,
475 de->u.CreateProcessInfo.hThread,
476 de->u.CreateProcessInfo.lpThreadLocalBase);
477 break;
479 case LOAD_DLL_DEBUG_EVENT:
480 assert(dbg_curr_thread);
481 memory_get_string_indirect(gdbctx->process,
482 de->u.LoadDll.lpImageName,
483 de->u.LoadDll.fUnicode,
484 buffer, sizeof(buffer));
485 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
486 fprintf(stderr, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
487 de->dwProcessId, de->dwThreadId,
488 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
489 de->u.LoadDll.dwDebugInfoFileOffset,
490 de->u.LoadDll.nDebugInfoSize);
491 SymLoadModule(gdbctx->process->handle, de->u.LoadDll.hFile, buffer, NULL,
492 (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
493 break;
495 case UNLOAD_DLL_DEBUG_EVENT:
496 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
497 fprintf(stderr, "%08lx:%08lx: unload DLL @%08lx\n",
498 de->dwProcessId, de->dwThreadId, (unsigned long)de->u.UnloadDll.lpBaseOfDll);
499 SymUnloadModule(gdbctx->process->handle,
500 (unsigned long)de->u.UnloadDll.lpBaseOfDll);
501 break;
503 case EXCEPTION_DEBUG_EVENT:
504 assert(dbg_curr_thread);
505 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
506 fprintf(stderr, "%08lx:%08lx: exception code=0x%08lx\n",
507 de->dwProcessId, de->dwThreadId,
508 de->u.Exception.ExceptionRecord.ExceptionCode);
510 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
512 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
514 break;
516 case CREATE_THREAD_DEBUG_EVENT:
517 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
518 fprintf(stderr, "%08lx:%08lx: create thread D @%08lx\n",
519 de->dwProcessId, de->dwThreadId, (unsigned long)(void*)de->u.CreateThread.lpStartAddress);
521 dbg_add_thread(gdbctx->process,
522 de->dwThreadId,
523 de->u.CreateThread.hThread,
524 de->u.CreateThread.lpThreadLocalBase);
525 break;
527 case EXIT_THREAD_DEBUG_EVENT:
528 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
529 fprintf(stderr, "%08lx:%08lx: exit thread (%ld)\n",
530 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
532 assert(dbg_curr_thread);
533 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
534 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
535 dbg_del_thread(dbg_curr_thread);
536 break;
538 case EXIT_PROCESS_DEBUG_EVENT:
539 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
540 fprintf(stderr, "%08lx:%08lx: exit process (%ld)\n",
541 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
543 dbg_del_process(gdbctx->process);
544 gdbctx->process = NULL;
545 /* now signal gdb that we're done */
546 gdbctx->last_sig = SIGTERM;
547 gdbctx->in_trap = TRUE;
548 break;
550 case OUTPUT_DEBUG_STRING_EVENT:
551 assert(dbg_curr_thread);
552 memory_get_string(gdbctx->process,
553 de->u.DebugString.lpDebugStringData, TRUE,
554 de->u.DebugString.fUnicode, buffer, sizeof(buffer));
555 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
556 fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n",
557 de->dwProcessId, de->dwThreadId, buffer);
558 break;
560 case RIP_EVENT:
561 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
562 fprintf(stderr, "%08lx:%08lx: rip error=%ld type=%ld\n",
563 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
564 de->u.RipInfo.dwType);
565 break;
567 default:
568 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
569 fprintf(stderr, "%08lx:%08lx: unknown event (%ld)\n",
570 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
574 static void resume_debuggee(struct gdb_context* gdbctx, unsigned long cont)
576 if (dbg_curr_thread)
578 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
579 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
580 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
581 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
582 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
583 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
584 dbg_curr_thread->tid, cont);
586 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
587 fprintf(stderr, "Cannot find last thread\n");
591 static void resume_debuggee_thread(struct gdb_context* gdbctx, unsigned long cont, unsigned int threadid)
594 if (dbg_curr_thread)
596 if(dbg_curr_thread->tid == threadid){
597 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
598 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
599 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
600 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
601 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
602 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
603 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
604 dbg_curr_thread->tid, cont);
607 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
608 fprintf(stderr, "Cannot find last thread\n");
611 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
613 struct pollfd pollfd;
614 int ret;
615 char pkt;
617 pollfd.fd = gdbctx->sock;
618 pollfd.events = POLLIN;
619 pollfd.revents = 0;
621 if ((ret = poll(&pollfd, 1, 0)) == 1) {
622 ret = read(gdbctx->sock, &pkt, 1);
623 if (ret != 1) {
624 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
625 fprintf(stderr, "read failed\n");
627 return FALSE;
629 if (pkt != '\003') {
630 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
631 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
633 return FALSE;
635 return TRUE;
636 } else if (ret == -1) {
637 fprintf(stderr, "poll failed\n");
639 return FALSE;
642 static void wait_for_debuggee(struct gdb_context* gdbctx)
644 DEBUG_EVENT de;
646 gdbctx->in_trap = FALSE;
647 for (;;)
649 if (!WaitForDebugEvent(&de, 10))
651 if (GetLastError() == ERROR_SEM_TIMEOUT)
653 if (check_for_interrupt(gdbctx)) {
654 if (!DebugBreakProcess(gdbctx->process->handle)) {
655 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
656 fprintf(stderr, "Failed to break into debugee\n");
658 break;
660 WaitForDebugEvent(&de, INFINITE);
661 } else {
662 continue;
664 } else {
665 break;
668 handle_debug_event(gdbctx, &de);
669 assert(!gdbctx->process ||
670 gdbctx->process->pid == 0 ||
671 de.dwProcessId == gdbctx->process->pid);
672 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
673 if (gdbctx->in_trap) break;
674 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
678 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
680 be_cpu->single_step(&gdbctx->context, FALSE);
681 resume_debuggee(gdbctx, DBG_CONTINUE);
682 if (!kill)
683 DebugActiveProcessStop(gdbctx->process->pid);
684 dbg_del_process(gdbctx->process);
685 gdbctx->process = NULL;
688 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
690 unsigned long status;
692 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
694 strcpy(buffer, "Unknown process");
695 return;
697 if (status == STILL_ACTIVE)
699 strcpy(buffer, "Running");
701 else
702 snprintf(buffer, len, "Terminated (%lu)", status);
704 switch (GetPriorityClass(gdbctx->process->handle))
706 case 0: break;
707 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
708 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
709 #endif
710 #ifdef BELOW_NORMAL_PRIORITY_CLASS
711 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
712 #endif
713 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
714 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
715 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
716 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
718 strcat(buffer, "\n");
721 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
722 char* buffer, size_t len)
724 struct dbg_thread* thd;
725 unsigned long status;
726 int prio;
728 /* FIXME: use the size of buffer */
729 thd = dbg_get_thread(gdbctx->process, tid);
730 if (thd == NULL)
732 strcpy(buffer, "No information");
733 return;
735 if (GetExitCodeThread(thd->handle, &status))
737 if (status == STILL_ACTIVE)
739 /* FIXME: this is a bit brutal... some nicer way shall be found */
740 switch (status = SuspendThread(thd->handle))
742 case -1: break;
743 case 0: strcpy(buffer, "Running"); break;
744 default: snprintf(buffer, len, "Suspended (%lu)", status - 1);
746 ResumeThread(thd->handle);
748 else
749 snprintf(buffer, len, "Terminated (exit code = %lu)", status);
751 else
753 strcpy(buffer, "Unknown threadID");
755 switch (prio = GetThreadPriority(thd->handle))
757 case THREAD_PRIORITY_ERROR_RETURN: break;
758 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
759 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
760 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
761 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
762 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
763 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
764 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
765 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
767 assert(strlen(buffer) < len);
770 /* =============================================== *
771 * P A C K E T U T I L S *
772 * =============================================== *
775 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
776 packet_last_f = 0x80};
778 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
780 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
782 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
783 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
787 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
789 packet_reply_grow(gdbctx, len * 2);
790 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
791 gdbctx->out_len += len * 2;
794 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
796 packet_reply_hex_to(gdbctx, src, strlen(src));
799 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
801 int i, shift;
803 shift = (len - 1) * 8;
804 packet_reply_grow(gdbctx, len * 2);
805 for (i = 0; i < len; i++, shift -= 8)
807 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
808 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
812 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
814 packet_reply_grow(gdbctx, len);
815 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
816 gdbctx->out_len += len;
819 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
821 packet_reply_add(gdbctx, str, strlen(str));
824 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
826 packet_reply_add(gdbctx, &ch, 1);
829 static void packet_reply_open(struct gdb_context* gdbctx)
831 assert(gdbctx->out_curr_packet == -1);
832 packet_reply_catc(gdbctx, '$');
833 gdbctx->out_curr_packet = gdbctx->out_len;
836 static void packet_reply_close(struct gdb_context* gdbctx)
838 unsigned char cksum;
839 int plen;
841 plen = gdbctx->out_len - gdbctx->out_curr_packet;
842 packet_reply_catc(gdbctx, '#');
843 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
844 packet_reply_hex_to(gdbctx, &cksum, 1);
845 if (gdbctx->trace & GDBPXY_TRC_PACKET)
846 fprintf(stderr, "Reply : %*.*s\n",
847 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
848 gdbctx->out_curr_packet = -1;
851 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
853 packet_reply_open(gdbctx);
855 if (len == -1) len = strlen(packet);
856 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
858 packet_reply_add(gdbctx, packet, len);
860 packet_reply_close(gdbctx);
862 return packet_done;
865 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
867 packet_reply_open(gdbctx);
869 packet_reply_add(gdbctx, "E", 1);
870 packet_reply_val(gdbctx, error, 1);
872 packet_reply_close(gdbctx);
874 return packet_done;
877 /* =============================================== *
878 * P A C K E T H A N D L E R S *
879 * =============================================== *
882 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
884 enum packet_return ret = packet_done;
886 packet_reply_open(gdbctx);
888 if (gdbctx->process != NULL)
890 unsigned char sig;
891 unsigned i;
893 packet_reply_catc(gdbctx, 'T');
894 sig = gdbctx->last_sig;
895 packet_reply_val(gdbctx, sig, 1);
896 packet_reply_add(gdbctx, "thread:", 7);
897 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
898 packet_reply_catc(gdbctx, ';');
900 for (i = 0; i < cpu_num_regs; i++)
902 /* FIXME: this call will also grow the buffer...
903 * unneeded, but not harmful
905 packet_reply_val(gdbctx, i, 1);
906 packet_reply_catc(gdbctx, ':');
907 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
908 packet_reply_catc(gdbctx, ';');
911 else
913 /* Try to put an exit code
914 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
915 * just indicate the end of process and exit */
916 packet_reply_add(gdbctx, "W00", 3);
917 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
920 packet_reply_close(gdbctx);
922 return ret;
925 #if 0
926 static enum packet_return packet_extended(struct gdb_context* gdbctx)
928 gdbctx->extended = 1;
929 return packet_ok;
931 #endif
933 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
935 assert(gdbctx->in_packet_len == 0);
936 return packet_reply_status(gdbctx);
939 static enum packet_return packet_continue(struct gdb_context* gdbctx)
941 /* FIXME: add support for address in packet */
942 assert(gdbctx->in_packet_len == 0);
943 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
944 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
945 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
946 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
947 resume_debuggee(gdbctx, DBG_CONTINUE);
948 wait_for_debuggee(gdbctx);
949 return packet_reply_status(gdbctx);
952 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
954 int i;
955 int defaultAction = -1; /* magic non action */
956 unsigned char sig;
957 int actions =0;
958 int actionIndex[20]; /* allow for up to 20 actions */
959 int threadIndex[20];
960 int threadCount = 0;
961 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
962 unsigned int threadID = 0;
963 struct dbg_thread* thd;
965 /* basic check */
966 assert(gdbctx->in_packet_len >= 4);
968 /* OK we have vCont followed by..
969 * ? for query
970 * c for packet_continue
971 * Csig for packet_continue_signal
972 * s for step
973 * Ssig for step signal
974 * and then an optional thread ID at the end..
975 * *******************************************/
977 fprintf(stderr, "trying to process a verbose packet\n");
978 /* now check that we've got Cont */
979 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
981 /* Query */
982 if (gdbctx->in_packet[4] == '?')
985 Reply:
986 `vCont[;action]...'
987 The vCont packet is supported. Each action is a supported command in the vCont packet.
989 The vCont packet is not supported. (this didn't seem to be obeyed!)
991 packet_reply_open(gdbctx);
992 packet_reply_add(gdbctx, "vCont", 5);
993 /* add all the supported actions to the reply (all of them for now) */
994 packet_reply_add(gdbctx, ";c", 2);
995 packet_reply_add(gdbctx, ";C", 2);
996 packet_reply_add(gdbctx, ";s", 2);
997 packet_reply_add(gdbctx, ";S", 2);
998 packet_reply_close(gdbctx);
999 return packet_done;
1002 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1003 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1004 now if only gdb talked XML.... */
1005 #if 0 /* handy for debugging */
1006 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1007 #endif
1009 /* go through the packet and identify where all the actions start at */
1010 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1012 if (gdbctx->in_packet[i] == ';')
1014 threadIndex[actions] = 0;
1015 actionIndex[actions++] = i;
1017 else if (gdbctx->in_packet[i] == ':')
1019 threadIndex[actions - 1] = i;
1023 /* now look up the default action */
1024 for (i = 0 ; i < actions; i++)
1026 if (threadIndex[i] == 0)
1028 if (defaultAction != -1)
1030 fprintf(stderr,"Too many default actions specified\n");
1031 return packet_error;
1033 defaultAction = i;
1037 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1039 /* go through all the threads and stick their ids in the to be done list. */
1040 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1042 threadIDs[threadCount++] = thd->tid;
1043 /* check to see if we have more threads than I counted on, and tell the user what to do
1044 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1045 if (threadCount == 100)
1047 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1048 break;
1052 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1053 * that remains is to apply the actions to the threads and the default action to any threads
1054 * left */
1055 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1056 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1057 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
1058 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1060 /* deal with the threaded stuff first */
1061 for (i = 0; i < actions ; i++)
1063 if (threadIndex[i] != 0)
1065 int j, idLength = 0;
1066 if (i < actions - 1)
1068 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1070 else
1072 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1075 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1076 /* process the action */
1077 switch (gdbctx->in_packet[actionIndex[i] + 1])
1079 case 's': /* step */
1080 be_cpu->single_step(&gdbctx->context, TRUE);
1081 /* fall through*/
1082 case 'c': /* continue */
1083 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1084 break;
1085 case 'S': /* step Sig, */
1086 be_cpu->single_step(&gdbctx->context, TRUE);
1087 /* fall through */
1088 case 'C': /* continue sig */
1089 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1090 /* cannot change signals on the fly */
1091 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1092 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1093 if (sig != gdbctx->last_sig)
1094 return packet_error;
1095 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1096 break;
1098 for (j = 0 ; j < threadCount; j++)
1100 if (threadIDs[j] == threadID)
1102 threadIDs[j] = 0;
1103 break;
1107 } /* for i=0 ; i< actions */
1109 /* now we have manage the default action */
1110 if (defaultAction >= 0)
1112 for (i = 0 ; i< threadCount; i++)
1114 /* check to see if we've already done something to the thread*/
1115 if (threadIDs[i] != 0)
1117 /* if not apply the default action*/
1118 threadID = threadIDs[i];
1119 /* process the action (yes this is almost identical to the one above!) */
1120 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1122 case 's': /* step */
1123 be_cpu->single_step(&gdbctx->context, TRUE);
1124 /* fall through */
1125 case 'c': /* continue */
1126 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1127 break;
1128 case 'S':
1129 be_cpu->single_step(&gdbctx->context, TRUE);
1130 /* fall through */
1131 case 'C': /* continue sig */
1132 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1133 /* cannot change signals on the fly */
1134 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1135 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1136 if (sig != gdbctx->last_sig)
1137 return packet_error;
1138 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1139 break;
1143 } /* if(defaultAction >=0) */
1145 wait_for_debuggee(gdbctx);
1146 be_cpu->single_step(&gdbctx->context, FALSE);
1147 return packet_reply_status(gdbctx);
1150 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1152 unsigned char sig;
1154 /* FIXME: add support for address in packet */
1155 assert(gdbctx->in_packet_len == 2);
1156 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1157 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1158 fprintf(stderr, "NIY: cont/sig on %lu, while last thread is %lu\n",
1159 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1160 hex_from(&sig, gdbctx->in_packet, 1);
1161 /* cannot change signals on the fly */
1162 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1163 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1164 if (sig != gdbctx->last_sig)
1165 return packet_error;
1166 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1167 wait_for_debuggee(gdbctx);
1168 return packet_reply_status(gdbctx);
1171 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1173 detach_debuggee(gdbctx, FALSE);
1174 return packet_ok | packet_last_f;
1177 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1179 int i;
1180 CONTEXT ctx;
1181 CONTEXT* pctx = &gdbctx->context;
1183 assert(gdbctx->in_trap);
1185 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1187 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1188 return packet_error;
1191 packet_reply_open(gdbctx);
1192 for (i = 0; i < cpu_num_regs; i++)
1194 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1196 packet_reply_close(gdbctx);
1197 return packet_done;
1200 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1202 unsigned i;
1203 CONTEXT ctx;
1204 CONTEXT* pctx = &gdbctx->context;
1206 assert(gdbctx->in_trap);
1207 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1209 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1210 return packet_error;
1212 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1214 for (i = 0; i < cpu_num_regs; i++)
1215 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1216 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1218 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1219 fprintf(stderr, "Cannot set context on thread %lu\n", gdbctx->other_thread->tid);
1220 return packet_error;
1222 return packet_ok;
1225 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1227 detach_debuggee(gdbctx, TRUE);
1228 #if 0
1229 if (!gdbctx->extended)
1230 /* dunno whether GDB cares or not */
1231 #endif
1232 wait(NULL);
1233 exit(0);
1234 /* assume we can't really answer something here */
1235 /* return packet_done; */
1238 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1240 char* end;
1241 unsigned thread;
1243 switch (gdbctx->in_packet[0])
1245 case 'c':
1246 case 'g':
1247 if (gdbctx->in_packet[1] == '-')
1248 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1249 else
1250 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1251 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1253 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1254 fprintf(stderr, "Cannot get threadid %*.*s\n",
1255 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1256 gdbctx->in_packet + 1);
1257 return packet_error;
1259 if (gdbctx->in_packet[0] == 'c')
1260 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1261 else
1262 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1263 return packet_ok;
1264 default:
1265 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1266 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1267 return packet_error;
1271 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1273 char *addr;
1274 size_t len, blk_len, nread;
1275 char buffer[32];
1276 unsigned long r = 0;
1278 assert(gdbctx->in_trap);
1279 /* FIXME:check in_packet_len for reading %p,%x */
1280 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1281 if (len <= 0) return packet_error;
1282 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1283 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1284 for (nread = 0; nread < len; nread += r, addr += r)
1286 blk_len = min(sizeof(buffer), len - nread);
1287 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1288 r == 0)
1290 /* fail at first address, return error */
1291 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1292 /* something has already been read, return partial information */
1293 break;
1295 if (nread == 0) packet_reply_open(gdbctx);
1296 packet_reply_hex_to(gdbctx, buffer, r);
1298 packet_reply_close(gdbctx);
1299 return packet_done;
1302 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1304 char* addr;
1305 size_t len, blk_len;
1306 char* ptr;
1307 char buffer[32];
1308 unsigned long w;
1310 assert(gdbctx->in_trap);
1311 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1312 if (ptr == NULL)
1314 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1315 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1316 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1317 return packet_error;
1319 *ptr++ = '\0';
1321 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1323 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1324 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1325 return packet_error;
1327 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1329 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1330 fprintf(stderr, "Wrong sizes %u <> %u\n",
1331 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1332 return packet_error;
1334 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1335 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1336 while (len > 0)
1338 blk_len = min(sizeof(buffer), len);
1339 hex_from(buffer, ptr, blk_len);
1340 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1341 w != blk_len)
1342 break;
1343 addr += blk_len;
1344 len -= blk_len;
1345 ptr += blk_len;
1347 return packet_ok; /* FIXME: error while writing ? */
1350 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1352 unsigned reg;
1353 char* ptr;
1354 char* end;
1355 CONTEXT ctx;
1356 CONTEXT* pctx = &gdbctx->context;
1358 assert(gdbctx->in_trap);
1360 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1361 *ptr++ = '\0';
1362 reg = strtoul(gdbctx->in_packet, &end, 16);
1363 if (end == NULL || reg > cpu_num_regs)
1365 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1366 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1367 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1368 * it wouldn't matter too much, and it fakes our support for all regs
1370 return (end == NULL) ? packet_error : packet_ok;
1372 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1374 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1375 fprintf(stderr, "Wrong sizes %u <> %u\n",
1376 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1377 return packet_error;
1379 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1380 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1381 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1382 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1384 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1386 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1387 return packet_error;
1390 hex_from(cpu_register(pctx, reg), ptr, 4);
1391 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1393 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1394 fprintf(stderr, "Cannot set context for thread %lu\n", gdbctx->other_thread->tid);
1395 return packet_error;
1398 return packet_ok;
1401 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1403 char buffer[128];
1404 char clsName[128];
1405 char wndName[128];
1406 HWND child;
1408 do {
1409 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1410 strcpy(clsName, "-- Unknown --");
1411 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1412 strcpy(wndName, "-- Empty --");
1414 packet_reply_open(gdbctx);
1415 packet_reply_catc(gdbctx, 'O');
1416 snprintf(buffer, sizeof(buffer),
1417 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1418 indent, "", (UINT)hWnd, 13 - indent, "",
1419 clsName, GetWindowLong(hWnd, GWL_STYLE),
1420 GetWindowLongPtr(hWnd, GWLP_WNDPROC), wndName);
1421 packet_reply_hex_to_str(gdbctx, buffer);
1422 packet_reply_close(gdbctx);
1424 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1425 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1426 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1429 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1431 char buffer[128];
1433 /* we do the output in several 'O' packets, with the last one being just OK for
1434 * marking the end of the output */
1435 packet_reply_open(gdbctx);
1436 packet_reply_catc(gdbctx, 'O');
1437 snprintf(buffer, sizeof(buffer),
1438 "%-16.16s %-17.17s %-8.8s %s\n",
1439 "hwnd", "Class Name", " Style", " WndProc Text");
1440 packet_reply_hex_to_str(gdbctx, buffer);
1441 packet_reply_close(gdbctx);
1443 /* FIXME: could also add a pmt to this command in str... */
1444 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1445 packet_reply(gdbctx, "OK", 2);
1448 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1450 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1451 char buffer[128];
1452 char deco;
1453 PROCESSENTRY32 entry;
1454 BOOL ok;
1456 if (snap == INVALID_HANDLE_VALUE)
1457 return;
1459 entry.dwSize = sizeof(entry);
1460 ok = Process32First(snap, &entry);
1462 /* we do the output in several 'O' packets, with the last one being just OK for
1463 * marking the end of the output */
1465 packet_reply_open(gdbctx);
1466 packet_reply_catc(gdbctx, 'O');
1467 snprintf(buffer, sizeof(buffer),
1468 " %-8.8s %-8.8s %-8.8s %s\n",
1469 "pid", "threads", "parent", "executable");
1470 packet_reply_hex_to_str(gdbctx, buffer);
1471 packet_reply_close(gdbctx);
1473 while (ok)
1475 deco = ' ';
1476 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1477 packet_reply_open(gdbctx);
1478 packet_reply_catc(gdbctx, 'O');
1479 snprintf(buffer, sizeof(buffer),
1480 "%c%08lx %-8ld %08lx '%s'\n",
1481 deco, entry.th32ProcessID, entry.cntThreads,
1482 entry.th32ParentProcessID, entry.szExeFile);
1483 packet_reply_hex_to_str(gdbctx, buffer);
1484 packet_reply_close(gdbctx);
1485 ok = Process32Next(snap, &entry);
1487 CloseHandle(snap);
1488 packet_reply(gdbctx, "OK", 2);
1491 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1493 MEMORY_BASIC_INFORMATION mbi;
1494 char* addr = 0;
1495 const char* state;
1496 const char* type;
1497 char prot[3+1];
1498 char buffer[128];
1500 /* we do the output in several 'O' packets, with the last one being just OK for
1501 * marking the end of the output */
1502 packet_reply_open(gdbctx);
1503 packet_reply_catc(gdbctx, 'O');
1504 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1505 packet_reply_close(gdbctx);
1507 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1509 switch (mbi.State)
1511 case MEM_COMMIT: state = "commit "; break;
1512 case MEM_FREE: state = "free "; break;
1513 case MEM_RESERVE: state = "reserve"; break;
1514 default: state = "??? "; break;
1516 if (mbi.State != MEM_FREE)
1518 switch (mbi.Type)
1520 case MEM_IMAGE: type = "image "; break;
1521 case MEM_MAPPED: type = "mapped "; break;
1522 case MEM_PRIVATE: type = "private"; break;
1523 case 0: type = " "; break;
1524 default: type = "??? "; break;
1526 memset(prot, ' ' , sizeof(prot)-1);
1527 prot[sizeof(prot)-1] = '\0';
1528 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1529 prot[0] = 'R';
1530 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1531 prot[1] = 'W';
1532 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1533 prot[1] = 'C';
1534 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1535 prot[2] = 'X';
1537 else
1539 type = "";
1540 prot[0] = '\0';
1542 packet_reply_open(gdbctx);
1543 snprintf(buffer, sizeof(buffer),
1544 "%08lx %08lx %s %s %s\n",
1545 (DWORD)addr, mbi.RegionSize, state, type, prot);
1546 packet_reply_catc(gdbctx, 'O');
1547 packet_reply_hex_to_str(gdbctx, buffer);
1548 packet_reply_close(gdbctx);
1550 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1551 break;
1552 addr += mbi.RegionSize;
1554 packet_reply(gdbctx, "OK", 2);
1557 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1558 int len, const char* str)
1560 char buffer[128];
1562 if (len == 0)
1564 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1566 else if (len >= 2 && str[0] == '=')
1568 unsigned val = atoi(&str[1]);
1569 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1570 gdbctx->trace = val;
1572 else
1574 /* FIXME: ugly but can use error packet here */
1575 packet_reply_cat(gdbctx, "E00");
1576 return;
1578 packet_reply_open(gdbctx);
1579 packet_reply_hex_to_str(gdbctx, buffer);
1580 packet_reply_close(gdbctx);
1583 struct query_detail
1585 int with_arg;
1586 const char* name;
1587 size_t len;
1588 void (*handler)(struct gdb_context*, int, const char*);
1589 } query_details[] =
1591 {0, "wnd", 3, packet_query_monitor_wnd},
1592 {0, "window", 6, packet_query_monitor_wnd},
1593 {0, "proc", 4, packet_query_monitor_process},
1594 {0, "process", 7, packet_query_monitor_process},
1595 {0, "mem", 3, packet_query_monitor_mem},
1596 {1, "trace", 5, packet_query_monitor_trace},
1597 {0, NULL, 0, NULL},
1600 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1601 const char* hxcmd, size_t len)
1603 char buffer[128];
1604 struct query_detail* qd;
1606 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1607 len /= 2;
1608 hex_from(buffer, hxcmd, len);
1610 for (qd = &query_details[0]; qd->name != NULL; qd++)
1612 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1613 if (!qd->with_arg && len != qd->len) continue;
1615 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1616 return packet_done;
1618 return packet_reply_error(gdbctx, EINVAL);
1621 static enum packet_return packet_query(struct gdb_context* gdbctx)
1623 switch (gdbctx->in_packet[0])
1625 case 'f':
1626 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1628 struct dbg_thread* thd;
1630 packet_reply_open(gdbctx);
1631 packet_reply_add(gdbctx, "m", 1);
1632 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1634 packet_reply_val(gdbctx, thd->tid, 4);
1635 if (thd->next != NULL)
1636 packet_reply_add(gdbctx, ",", 1);
1638 packet_reply_close(gdbctx);
1639 return packet_done;
1641 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1643 char result[128];
1645 packet_reply_open(gdbctx);
1646 packet_reply_catc(gdbctx, 'O');
1647 get_process_info(gdbctx, result, sizeof(result));
1648 packet_reply_hex_to_str(gdbctx, result);
1649 packet_reply_close(gdbctx);
1650 return packet_done;
1652 break;
1653 case 's':
1654 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1656 packet_reply(gdbctx, "l", 1);
1657 return packet_done;
1659 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1661 packet_reply(gdbctx, "l", 1);
1662 return packet_done;
1664 break;
1665 case 'C':
1666 if (gdbctx->in_packet_len == 1)
1668 struct dbg_thread* thd;
1669 /* FIXME: doc says 16 bit val ??? */
1670 /* grab first created thread, aka last in list */
1671 assert(gdbctx->process && gdbctx->process->threads);
1672 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1673 packet_reply_open(gdbctx);
1674 packet_reply_add(gdbctx, "QC", 2);
1675 packet_reply_val(gdbctx, thd->tid, 4);
1676 packet_reply_close(gdbctx);
1677 return packet_done;
1679 break;
1680 case 'O':
1681 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1683 char buf[64];
1685 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1686 gdbctx->wine_segs[2] == 0)
1687 return packet_error;
1688 snprintf(buf, sizeof(buf),
1689 "Text=%08lx;Data=%08lx;Bss=%08lx",
1690 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1691 gdbctx->wine_segs[2]);
1692 return packet_reply(gdbctx, buf, -1);
1694 break;
1695 case 'R':
1696 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1698 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1699 gdbctx->in_packet_len - 5);
1701 break;
1702 case 'S':
1703 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1704 return packet_ok;
1705 break;
1706 case 'T':
1707 if (gdbctx->in_packet_len > 15 &&
1708 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1709 gdbctx->in_packet[15] == ',')
1711 unsigned tid;
1712 char* end;
1713 char result[128];
1715 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1716 if (end == NULL) break;
1717 get_thread_info(gdbctx, tid, result, sizeof(result));
1718 packet_reply_open(gdbctx);
1719 packet_reply_hex_to_str(gdbctx, result);
1720 packet_reply_close(gdbctx);
1721 return packet_done;
1723 break;
1725 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1726 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1727 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1728 return packet_error;
1731 static enum packet_return packet_step(struct gdb_context* gdbctx)
1733 /* FIXME: add support for address in packet */
1734 assert(gdbctx->in_packet_len == 0);
1735 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1736 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1737 fprintf(stderr, "NIY: step on %lu, while last thread is %lu\n",
1738 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1739 be_cpu->single_step(&gdbctx->context, TRUE);
1740 resume_debuggee(gdbctx, DBG_CONTINUE);
1741 wait_for_debuggee(gdbctx);
1742 be_cpu->single_step(&gdbctx->context, FALSE);
1743 return packet_reply_status(gdbctx);
1746 #if 0
1747 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1749 unsigned char sig;
1751 /* FIXME: add support for address in packet */
1752 assert(gdbctx->in_packet_len == 2);
1753 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1754 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1755 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1756 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1757 hex_from(&sig, gdbctx->in_packet, 1);
1758 /* cannot change signals on the fly */
1759 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1760 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1761 if (sig != gdbctx->last_sig)
1762 return packet_error;
1763 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1764 wait_for_debuggee(gdbctx);
1765 return packet_reply_status(gdbctx);
1767 #endif
1769 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1771 char* end;
1772 unsigned tid;
1774 tid = strtol(gdbctx->in_packet, &end, 16);
1775 if (tid == -1 || tid == 0)
1776 return packet_reply_error(gdbctx, EINVAL);
1777 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1778 return packet_ok;
1779 return packet_reply_error(gdbctx, ESRCH);
1782 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1784 void* addr;
1785 unsigned len;
1786 struct gdb_ctx_Xpoint* xpt;
1787 enum be_xpoint_type t;
1789 /* FIXME: check packet_len */
1790 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1791 gdbctx->in_packet[1] != ',' ||
1792 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1793 return packet_error;
1794 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1795 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1796 addr, len, gdbctx->in_packet[0]);
1797 switch (gdbctx->in_packet[0])
1799 case '0': t = be_xpoint_break; len = 0; break;
1800 case '1': t = be_xpoint_watch_exec; break;
1801 case '2': t = be_xpoint_watch_read; break;
1802 case '3': t = be_xpoint_watch_write; break;
1803 default: return packet_error;
1805 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1807 if (xpt->addr == addr && xpt->type == t)
1809 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1810 gdbctx->process->process_io, &gdbctx->context,
1811 t, xpt->addr, xpt->val, len))
1813 xpt->type = -1;
1814 return packet_ok;
1816 break;
1819 return packet_error;
1822 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1824 void* addr;
1825 unsigned len;
1826 struct gdb_ctx_Xpoint* xpt;
1827 enum be_xpoint_type t;
1829 /* FIXME: check packet_len */
1830 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1831 gdbctx->in_packet[1] != ',' ||
1832 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1833 return packet_error;
1834 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1835 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1836 addr, len, gdbctx->in_packet[0]);
1837 switch (gdbctx->in_packet[0])
1839 case '0': t = be_xpoint_break; len = 0; break;
1840 case '1': t = be_xpoint_watch_exec; break;
1841 case '2': t = be_xpoint_watch_read; break;
1842 case '3': t = be_xpoint_watch_write; break;
1843 default: return packet_error;
1845 /* because of packet command handling, this should be made idempotent */
1846 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1848 if (xpt->addr == addr && xpt->type == t)
1849 return packet_ok; /* nothing to do */
1851 /* really set the Xpoint */
1852 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1854 if (xpt->type == -1)
1856 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1857 gdbctx->process->process_io, &gdbctx->context,
1858 t, addr, &xpt->val, len))
1860 xpt->addr = addr;
1861 xpt->type = t;
1862 return packet_ok;
1864 fprintf(stderr, "cannot set xpoint\n");
1865 break;
1868 /* no more entries... eech */
1869 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1870 return packet_error;
1873 /* =============================================== *
1874 * P A C K E T I N F R A S T R U C T U R E *
1875 * =============================================== *
1878 struct packet_entry
1880 char key;
1881 enum packet_return (*handler)(struct gdb_context* gdbctx);
1884 static struct packet_entry packet_entries[] =
1886 /*{'!', packet_extended}, */
1887 {'?', packet_last_signal},
1888 {'c', packet_continue},
1889 {'C', packet_continue_signal},
1890 {'D', packet_detach},
1891 {'g', packet_read_registers},
1892 {'G', packet_write_registers},
1893 {'k', packet_kill},
1894 {'H', packet_thread},
1895 {'m', packet_read_memory},
1896 {'M', packet_write_memory},
1897 /* {'p', packet_read_register}, doesn't seem needed */
1898 {'P', packet_write_register},
1899 {'q', packet_query},
1900 /* {'Q', packet_set}, */
1901 /* {'R', packet,restart}, only in extended mode ! */
1902 {'s', packet_step},
1903 /*{'S', packet_step_signal}, hard(er) to implement */
1904 {'T', packet_thread_alive},
1905 {'v', packet_verbose},
1906 {'z', packet_remove_breakpoint},
1907 {'Z', packet_set_breakpoint},
1910 static BOOL extract_packets(struct gdb_context* gdbctx)
1912 char* end;
1913 int plen;
1914 unsigned char in_cksum, loc_cksum;
1915 char* ptr;
1916 enum packet_return ret = packet_error;
1917 int num_packet = 0;
1919 while ((ret & packet_last_f) == 0)
1921 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1922 fprintf(stderr, "In-buf: %*.*s\n",
1923 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1924 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1925 if (ptr == NULL) return FALSE;
1926 if (ptr != gdbctx->in_buf)
1928 int glen = ptr - gdbctx->in_buf; /* garbage len */
1929 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1930 fprintf(stderr, "Removing garbage: %*.*s\n",
1931 glen, glen, gdbctx->in_buf);
1932 gdbctx->in_len -= glen;
1933 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1935 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1936 if (end == NULL) return FALSE;
1937 /* no checksum yet */
1938 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1939 plen = end - gdbctx->in_buf - 1;
1940 hex_from(&in_cksum, end + 1, 1);
1941 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1942 if (loc_cksum == in_cksum)
1944 if (num_packet == 0) {
1945 int i;
1947 ret = packet_error;
1949 write(gdbctx->sock, "+", 1);
1950 assert(plen);
1952 /* FIXME: should use bsearch if packet_entries was sorted */
1953 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1955 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1957 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1959 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1960 fprintf(stderr, "Unknown packet request %*.*s\n",
1961 plen, plen, &gdbctx->in_buf[1]);
1963 else
1965 gdbctx->in_packet = gdbctx->in_buf + 2;
1966 gdbctx->in_packet_len = plen - 1;
1967 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1968 fprintf(stderr, "Packet: %c%*.*s\n",
1969 gdbctx->in_buf[1],
1970 gdbctx->in_packet_len, gdbctx->in_packet_len,
1971 gdbctx->in_packet);
1972 ret = (packet_entries[i].handler)(gdbctx);
1974 switch (ret & ~packet_last_f)
1976 case packet_error: packet_reply(gdbctx, "", 0); break;
1977 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
1978 case packet_done: break;
1980 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1981 fprintf(stderr, "Reply-full: %*.*s\n",
1982 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
1983 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
1984 assert(i == gdbctx->out_len);
1985 /* if this fails, we'll have to use POLLOUT...
1987 gdbctx->out_len = 0;
1988 num_packet++;
1990 else
1992 /* FIXME: if we have in our input buffer more than one packet,
1993 * it's very likely that we took too long to answer to a given packet
1994 * and gdb is sending us again the same packet
1995 * We simply drop the second packet. This will lower the risk of error,
1996 * but there's still some race conditions here
1997 * A better fix (yet not perfect) would be to have two threads:
1998 * - one managing the packets for gdb
1999 * - the second one managing the commands...
2000 * This would allow us also the reply with the '+' character (Ack of
2001 * the command) way sooner than what we do now
2003 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2004 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2007 else
2009 write(gdbctx->sock, "+", 1);
2010 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2011 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2013 gdbctx->in_len -= plen + 4;
2014 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2016 return TRUE;
2019 static int fetch_data(struct gdb_context* gdbctx)
2021 int len, in_len = gdbctx->in_len;
2023 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2024 for (;;)
2026 #define STEP 128
2027 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2028 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2029 #undef STEP
2030 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2031 fprintf(stderr, "%d %d %*.*s\n",
2032 gdbctx->in_len, gdbctx->in_buf_alloc,
2033 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2034 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2035 if (len <= 0) break;
2036 gdbctx->in_len += len;
2037 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2038 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2040 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2041 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2042 return gdbctx->in_len - in_len;
2045 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2047 char buf[MAX_PATH];
2048 int fd;
2049 const char* gdb_path;
2050 FILE* f;
2052 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2053 strcpy(buf,"/tmp/winegdb.XXXXXX");
2054 fd = mkstemps(buf, 0);
2055 if (fd == -1) return FALSE;
2056 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2057 fprintf(f, "file %s\n", wine_path);
2058 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2059 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2060 fprintf(f, "set prompt Wine-gdb>\\ \n");
2061 /* gdb 5.1 seems to require it, won't hurt anyway */
2062 fprintf(f, "sharedlibrary\n");
2063 /* This is needed (but not a decent & final fix)
2064 * Without this, gdb would skip our inter-DLL relay code (because
2065 * we don't have any line number information for the relay code)
2066 * With this, we will stop on first instruction of the stub, and
2067 * reusing step, will get us through the relay stub at the actual
2068 * function we're looking at.
2070 fprintf(f, "set step-mode on\n");
2071 /* tell gdb to delete this file when done handling it... */
2072 fprintf(f, "shell rm -f \"%s\"\n", buf);
2073 fclose(f);
2074 if (flags & 2)
2075 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2076 else
2077 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2078 assert(0); /* never reached */
2079 return TRUE;
2082 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2084 int sock;
2085 struct sockaddr_in s_addrs;
2086 unsigned int s_len = sizeof(s_addrs);
2087 struct pollfd pollfd;
2088 IMAGEHLP_MODULE imh_mod;
2090 /* step 1: create socket for gdb connection request */
2091 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2093 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2094 fprintf(stderr, "Can't create socket");
2095 return FALSE;
2098 if (listen(sock, 1) == -1 ||
2099 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2100 return FALSE;
2102 /* step 2: do the process internal creation */
2103 handle_debug_event(gdbctx, de);
2105 /* step3: get the wine loader name */
2106 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2108 /* step 4: fire up gdb (if requested) */
2109 if (flags & 1)
2110 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2111 else
2112 switch (fork())
2114 case -1: /* error in parent... */
2115 fprintf(stderr, "Cannot create gdb\n");
2116 return FALSE;
2117 break;
2118 default: /* in parent... success */
2119 break;
2120 case 0: /* in child... and alive */
2121 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2122 /* if we're here, exec failed, so report failure */
2123 return FALSE;
2126 /* step 5: wait for gdb to connect actually */
2127 pollfd.fd = sock;
2128 pollfd.events = POLLIN;
2129 pollfd.revents = 0;
2131 switch (poll(&pollfd, 1, -1))
2133 case 1:
2134 if (pollfd.revents & POLLIN)
2136 int dummy = 1;
2137 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2138 if (gdbctx->sock == -1)
2139 break;
2140 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2141 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2142 /* don't keep our small packets too long: send them ASAP back to GDB
2143 * without this, GDB really crawls
2145 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2147 break;
2148 case 0:
2149 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2150 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2151 return FALSE;
2152 case -1:
2153 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2154 fprintf(stderr, "Poll for cnx failed (error)\n");
2155 return FALSE;
2156 default:
2157 assert(0);
2160 close(sock);
2161 return TRUE;
2164 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2166 DEBUG_EVENT de;
2167 int i;
2169 gdbctx->sock = -1;
2170 gdbctx->in_buf = NULL;
2171 gdbctx->in_buf_alloc = 0;
2172 gdbctx->in_len = 0;
2173 gdbctx->out_buf = NULL;
2174 gdbctx->out_buf_alloc = 0;
2175 gdbctx->out_len = 0;
2176 gdbctx->out_curr_packet = -1;
2178 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2179 gdbctx->last_sig = 0;
2180 gdbctx->in_trap = FALSE;
2181 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2182 gdbctx->process = NULL;
2183 for (i = 0; i < NUM_XPOINT; i++)
2184 gdbctx->Xpoints[i].type = -1;
2186 /* wait for first trap */
2187 while (WaitForDebugEvent(&de, INFINITE))
2189 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2191 /* this should be the first event we get,
2192 * and the only one of this type */
2193 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2194 /* gdbctx->dwProcessId = pid; */
2195 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2196 assert(!gdbctx->in_trap);
2198 else
2200 handle_debug_event(gdbctx, &de);
2201 if (gdbctx->in_trap) break;
2203 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2205 return TRUE;
2208 BOOL gdb_remote(unsigned flags)
2210 struct pollfd pollfd;
2211 struct gdb_context gdbctx;
2212 BOOL doLoop;
2214 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2216 pollfd.fd = gdbctx.sock;
2217 pollfd.events = POLLIN;
2218 pollfd.revents = 0;
2220 switch (poll(&pollfd, 1, -1))
2222 case 1:
2223 /* got something */
2224 if (pollfd.revents & (POLLHUP | POLLERR))
2226 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2227 fprintf(stderr, "Gdb hung up\n");
2228 /* kill also debuggee process - questionnable - */
2229 detach_debuggee(&gdbctx, TRUE);
2230 doLoop = FALSE;
2231 break;
2233 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2235 if (extract_packets(&gdbctx)) doLoop = FALSE;
2237 break;
2238 case 0:
2239 /* timeout, should never happen (infinite timeout) */
2240 break;
2241 case -1:
2242 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2243 fprintf(stderr, "Poll failed\n");
2244 doLoop = FALSE;
2245 break;
2248 wait(NULL);
2249 return 0;