comctl32: Use the listview's background colour when drawing with imagelist.
[wine/multimedia.git] / programs / winedbg / gdbproxy.c
blob5e4cf29d0e6cb0125ac6273387913ca2ea614c7a
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 #else
342 # error Define the registers map for your CPU
343 #endif
345 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
347 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
349 assert(idx < cpu_num_regs);
350 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
353 /* =============================================== *
354 * W I N 3 2 D E B U G I N T E R F A C E *
355 * =============================================== *
358 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
360 ctx->ContextFlags = CONTEXT_CONTROL
361 | CONTEXT_INTEGER
362 #ifdef CONTEXT_SEGMENTS
363 | CONTEXT_SEGMENTS
364 #endif
365 #ifdef CONTEXT_DEBUG_REGISTERS
366 | CONTEXT_DEBUG_REGISTERS
367 #endif
369 if (!GetThreadContext(h, ctx))
371 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
372 fprintf(stderr, "Can't get thread's context\n");
373 return FALSE;
375 return TRUE;
378 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
380 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
381 BOOL ret = FALSE;
383 switch (rec->ExceptionCode)
385 case EXCEPTION_ACCESS_VIOLATION:
386 case EXCEPTION_PRIV_INSTRUCTION:
387 case EXCEPTION_STACK_OVERFLOW:
388 case EXCEPTION_GUARD_PAGE:
389 gdbctx->last_sig = SIGSEGV;
390 ret = TRUE;
391 break;
392 case EXCEPTION_DATATYPE_MISALIGNMENT:
393 gdbctx->last_sig = SIGBUS;
394 ret = TRUE;
395 break;
396 case EXCEPTION_SINGLE_STEP:
397 /* fall thru */
398 case EXCEPTION_BREAKPOINT:
399 gdbctx->last_sig = SIGTRAP;
400 ret = TRUE;
401 break;
402 case EXCEPTION_FLT_DENORMAL_OPERAND:
403 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
404 case EXCEPTION_FLT_INEXACT_RESULT:
405 case EXCEPTION_FLT_INVALID_OPERATION:
406 case EXCEPTION_FLT_OVERFLOW:
407 case EXCEPTION_FLT_STACK_CHECK:
408 case EXCEPTION_FLT_UNDERFLOW:
409 gdbctx->last_sig = SIGFPE;
410 ret = TRUE;
411 break;
412 case EXCEPTION_INT_DIVIDE_BY_ZERO:
413 case EXCEPTION_INT_OVERFLOW:
414 gdbctx->last_sig = SIGFPE;
415 ret = TRUE;
416 break;
417 case EXCEPTION_ILLEGAL_INSTRUCTION:
418 gdbctx->last_sig = SIGILL;
419 ret = TRUE;
420 break;
421 case CONTROL_C_EXIT:
422 gdbctx->last_sig = SIGINT;
423 ret = TRUE;
424 break;
425 case STATUS_POSSIBLE_DEADLOCK:
426 gdbctx->last_sig = SIGALRM;
427 ret = TRUE;
428 /* FIXME: we could also add here a O packet with additional information */
429 break;
430 default:
431 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
432 fprintf(stderr, "Unhandled exception code 0x%08lx\n", rec->ExceptionCode);
433 gdbctx->last_sig = SIGABRT;
434 ret = TRUE;
435 break;
437 return ret;
440 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
442 char buffer[256];
444 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
446 switch (de->dwDebugEventCode)
448 case CREATE_PROCESS_DEBUG_EVENT:
449 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
450 de->u.CreateProcessInfo.hProcess);
451 if (!gdbctx->process) break;
452 memory_get_string_indirect(gdbctx->process,
453 de->u.CreateProcessInfo.lpImageName,
454 de->u.CreateProcessInfo.fUnicode,
455 buffer, sizeof(buffer));
456 dbg_set_process_name(gdbctx->process, buffer);
458 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
459 fprintf(stderr, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
460 de->dwProcessId, de->dwThreadId,
461 buffer, de->u.CreateProcessInfo.lpImageName,
462 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress,
463 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
464 de->u.CreateProcessInfo.nDebugInfoSize);
466 /* de->u.CreateProcessInfo.lpStartAddress; */
467 if (!SymInitialize(gdbctx->process->handle, NULL, TRUE))
468 fprintf(stderr, "Couldn't initiate DbgHelp\n");
470 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
471 fprintf(stderr, "%08lx:%08lx: create thread I @%08lx\n",
472 de->dwProcessId, de->dwThreadId,
473 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress);
475 assert(dbg_curr_thread == NULL); /* shouldn't be there */
476 dbg_add_thread(gdbctx->process, de->dwThreadId,
477 de->u.CreateProcessInfo.hThread,
478 de->u.CreateProcessInfo.lpThreadLocalBase);
479 break;
481 case LOAD_DLL_DEBUG_EVENT:
482 assert(dbg_curr_thread);
483 memory_get_string_indirect(gdbctx->process,
484 de->u.LoadDll.lpImageName,
485 de->u.LoadDll.fUnicode,
486 buffer, sizeof(buffer));
487 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
488 fprintf(stderr, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
489 de->dwProcessId, de->dwThreadId,
490 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
491 de->u.LoadDll.dwDebugInfoFileOffset,
492 de->u.LoadDll.nDebugInfoSize);
493 SymLoadModule(gdbctx->process->handle, de->u.LoadDll.hFile, buffer, NULL,
494 (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
495 break;
497 case UNLOAD_DLL_DEBUG_EVENT:
498 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
499 fprintf(stderr, "%08lx:%08lx: unload DLL @%08lx\n",
500 de->dwProcessId, de->dwThreadId, (unsigned long)de->u.UnloadDll.lpBaseOfDll);
501 SymUnloadModule(gdbctx->process->handle,
502 (unsigned long)de->u.UnloadDll.lpBaseOfDll);
503 break;
505 case EXCEPTION_DEBUG_EVENT:
506 assert(dbg_curr_thread);
507 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
508 fprintf(stderr, "%08lx:%08lx: exception code=0x%08lx\n",
509 de->dwProcessId, de->dwThreadId,
510 de->u.Exception.ExceptionRecord.ExceptionCode);
512 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
514 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
516 break;
518 case CREATE_THREAD_DEBUG_EVENT:
519 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
520 fprintf(stderr, "%08lx:%08lx: create thread D @%08lx\n",
521 de->dwProcessId, de->dwThreadId, (unsigned long)(void*)de->u.CreateThread.lpStartAddress);
523 dbg_add_thread(gdbctx->process,
524 de->dwThreadId,
525 de->u.CreateThread.hThread,
526 de->u.CreateThread.lpThreadLocalBase);
527 break;
529 case EXIT_THREAD_DEBUG_EVENT:
530 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
531 fprintf(stderr, "%08lx:%08lx: exit thread (%ld)\n",
532 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
534 assert(dbg_curr_thread);
535 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
536 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
537 dbg_del_thread(dbg_curr_thread);
538 break;
540 case EXIT_PROCESS_DEBUG_EVENT:
541 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
542 fprintf(stderr, "%08lx:%08lx: exit process (%ld)\n",
543 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
545 dbg_del_process(gdbctx->process);
546 gdbctx->process = NULL;
547 /* now signal gdb that we're done */
548 gdbctx->last_sig = SIGTERM;
549 gdbctx->in_trap = TRUE;
550 break;
552 case OUTPUT_DEBUG_STRING_EVENT:
553 assert(dbg_curr_thread);
554 memory_get_string(gdbctx->process,
555 de->u.DebugString.lpDebugStringData, TRUE,
556 de->u.DebugString.fUnicode, buffer, sizeof(buffer));
557 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
558 fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n",
559 de->dwProcessId, de->dwThreadId, buffer);
560 break;
562 case RIP_EVENT:
563 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
564 fprintf(stderr, "%08lx:%08lx: rip error=%ld type=%ld\n",
565 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
566 de->u.RipInfo.dwType);
567 break;
569 default:
570 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
571 fprintf(stderr, "%08lx:%08lx: unknown event (%ld)\n",
572 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
576 static void resume_debuggee(struct gdb_context* gdbctx, unsigned long cont)
578 if (dbg_curr_thread)
580 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
581 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
582 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
583 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
584 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
585 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
586 dbg_curr_thread->tid, cont);
588 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
589 fprintf(stderr, "Cannot find last thread\n");
593 static void resume_debuggee_thread(struct gdb_context* gdbctx, unsigned long cont, unsigned int threadid)
596 if (dbg_curr_thread)
598 if(dbg_curr_thread->tid == threadid){
599 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
600 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
601 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
602 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
603 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
604 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
605 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
606 dbg_curr_thread->tid, cont);
609 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
610 fprintf(stderr, "Cannot find last thread\n");
613 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
615 struct pollfd pollfd;
616 int ret;
617 char pkt;
619 pollfd.fd = gdbctx->sock;
620 pollfd.events = POLLIN;
621 pollfd.revents = 0;
623 if ((ret = poll(&pollfd, 1, 0)) == 1) {
624 ret = read(gdbctx->sock, &pkt, 1);
625 if (ret != 1) {
626 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
627 fprintf(stderr, "read failed\n");
629 return FALSE;
631 if (pkt != '\003') {
632 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
633 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
635 return FALSE;
637 return TRUE;
638 } else if (ret == -1) {
639 fprintf(stderr, "poll failed\n");
641 return FALSE;
644 static void wait_for_debuggee(struct gdb_context* gdbctx)
646 DEBUG_EVENT de;
648 gdbctx->in_trap = FALSE;
649 for (;;)
651 if (!WaitForDebugEvent(&de, 10))
653 if (GetLastError() == ERROR_SEM_TIMEOUT)
655 if (check_for_interrupt(gdbctx)) {
656 if (!DebugBreakProcess(gdbctx->process->handle)) {
657 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
658 fprintf(stderr, "Failed to break into debugee\n");
660 break;
662 WaitForDebugEvent(&de, INFINITE);
663 } else {
664 continue;
666 } else {
667 break;
670 handle_debug_event(gdbctx, &de);
671 assert(!gdbctx->process ||
672 gdbctx->process->pid == 0 ||
673 de.dwProcessId == gdbctx->process->pid);
674 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
675 if (gdbctx->in_trap) break;
676 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
680 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
682 be_cpu->single_step(&gdbctx->context, FALSE);
683 resume_debuggee(gdbctx, DBG_CONTINUE);
684 if (!kill)
685 DebugActiveProcessStop(gdbctx->process->pid);
686 dbg_del_process(gdbctx->process);
687 gdbctx->process = NULL;
690 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
692 unsigned long status;
694 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
696 strcpy(buffer, "Unknown process");
697 return;
699 if (status == STILL_ACTIVE)
701 strcpy(buffer, "Running");
703 else
704 snprintf(buffer, len, "Terminated (%lu)", status);
706 switch (GetPriorityClass(gdbctx->process->handle))
708 case 0: break;
709 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
710 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
711 #endif
712 #ifdef BELOW_NORMAL_PRIORITY_CLASS
713 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
714 #endif
715 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
716 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
717 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
718 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
720 strcat(buffer, "\n");
723 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
724 char* buffer, size_t len)
726 struct dbg_thread* thd;
727 unsigned long status;
728 int prio;
730 /* FIXME: use the size of buffer */
731 thd = dbg_get_thread(gdbctx->process, tid);
732 if (thd == NULL)
734 strcpy(buffer, "No information");
735 return;
737 if (GetExitCodeThread(thd->handle, &status))
739 if (status == STILL_ACTIVE)
741 /* FIXME: this is a bit brutal... some nicer way shall be found */
742 switch (status = SuspendThread(thd->handle))
744 case -1: break;
745 case 0: strcpy(buffer, "Running"); break;
746 default: snprintf(buffer, len, "Suspended (%lu)", status - 1);
748 ResumeThread(thd->handle);
750 else
751 snprintf(buffer, len, "Terminated (exit code = %lu)", status);
753 else
755 strcpy(buffer, "Unknown threadID");
757 switch (prio = GetThreadPriority(thd->handle))
759 case THREAD_PRIORITY_ERROR_RETURN: break;
760 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
761 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
762 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
763 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
764 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
765 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
766 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
767 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
769 assert(strlen(buffer) < len);
772 /* =============================================== *
773 * P A C K E T U T I L S *
774 * =============================================== *
777 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
778 packet_last_f = 0x80};
780 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
782 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
784 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
785 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
789 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
791 packet_reply_grow(gdbctx, len * 2);
792 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
793 gdbctx->out_len += len * 2;
796 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
798 packet_reply_hex_to(gdbctx, src, strlen(src));
801 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
803 int i, shift;
805 shift = (len - 1) * 8;
806 packet_reply_grow(gdbctx, len * 2);
807 for (i = 0; i < len; i++, shift -= 8)
809 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
810 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
814 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
816 packet_reply_grow(gdbctx, len);
817 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
818 gdbctx->out_len += len;
821 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
823 packet_reply_add(gdbctx, str, strlen(str));
826 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
828 packet_reply_add(gdbctx, &ch, 1);
831 static void packet_reply_open(struct gdb_context* gdbctx)
833 assert(gdbctx->out_curr_packet == -1);
834 packet_reply_catc(gdbctx, '$');
835 gdbctx->out_curr_packet = gdbctx->out_len;
838 static void packet_reply_close(struct gdb_context* gdbctx)
840 unsigned char cksum;
841 int plen;
843 plen = gdbctx->out_len - gdbctx->out_curr_packet;
844 packet_reply_catc(gdbctx, '#');
845 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
846 packet_reply_hex_to(gdbctx, &cksum, 1);
847 if (gdbctx->trace & GDBPXY_TRC_PACKET)
848 fprintf(stderr, "Reply : %*.*s\n",
849 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
850 gdbctx->out_curr_packet = -1;
853 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
855 packet_reply_open(gdbctx);
857 if (len == -1) len = strlen(packet);
858 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
860 packet_reply_add(gdbctx, packet, len);
862 packet_reply_close(gdbctx);
864 return packet_done;
867 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
869 packet_reply_open(gdbctx);
871 packet_reply_add(gdbctx, "E", 1);
872 packet_reply_val(gdbctx, error, 1);
874 packet_reply_close(gdbctx);
876 return packet_done;
879 /* =============================================== *
880 * P A C K E T H A N D L E R S *
881 * =============================================== *
884 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
886 enum packet_return ret = packet_done;
888 packet_reply_open(gdbctx);
890 if (gdbctx->process != NULL)
892 unsigned char sig;
893 unsigned i;
895 packet_reply_catc(gdbctx, 'T');
896 sig = gdbctx->last_sig;
897 packet_reply_val(gdbctx, sig, 1);
898 packet_reply_add(gdbctx, "thread:", 7);
899 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
900 packet_reply_catc(gdbctx, ';');
902 for (i = 0; i < cpu_num_regs; i++)
904 /* FIXME: this call will also grow the buffer...
905 * unneeded, but not harmful
907 packet_reply_val(gdbctx, i, 1);
908 packet_reply_catc(gdbctx, ':');
909 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
910 packet_reply_catc(gdbctx, ';');
913 else
915 /* Try to put an exit code
916 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
917 * just indicate the end of process and exit */
918 packet_reply_add(gdbctx, "W00", 3);
919 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
922 packet_reply_close(gdbctx);
924 return ret;
927 #if 0
928 static enum packet_return packet_extended(struct gdb_context* gdbctx)
930 gdbctx->extended = 1;
931 return packet_ok;
933 #endif
935 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
937 assert(gdbctx->in_packet_len == 0);
938 return packet_reply_status(gdbctx);
941 static enum packet_return packet_continue(struct gdb_context* gdbctx)
943 /* FIXME: add support for address in packet */
944 assert(gdbctx->in_packet_len == 0);
945 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
946 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
947 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
948 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
949 resume_debuggee(gdbctx, DBG_CONTINUE);
950 wait_for_debuggee(gdbctx);
951 return packet_reply_status(gdbctx);
954 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
956 int i;
957 int defaultAction = -1; /* magic non action */
958 unsigned char sig;
959 int actions =0;
960 int actionIndex[20]; /* allow for up to 20 actions */
961 int threadIndex[20];
962 int threadCount = 0;
963 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
964 unsigned int threadID = 0;
965 struct dbg_thread* thd;
967 /* basic check */
968 assert(gdbctx->in_packet_len >= 4);
970 /* OK we have vCont followed by..
971 * ? for query
972 * c for packet_continue
973 * Csig for packet_continue_signal
974 * s for step
975 * Ssig for step signal
976 * and then an optional thread ID at the end..
977 * *******************************************/
979 fprintf(stderr, "trying to process a verbose packet\n");
980 /* now check that we've got Cont */
981 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
983 /* Query */
984 if (gdbctx->in_packet[4] == '?')
987 Reply:
988 `vCont[;action]...'
989 The vCont packet is supported. Each action is a supported command in the vCont packet.
991 The vCont packet is not supported. (this didn't seem to be obeyed!)
993 packet_reply_open(gdbctx);
994 packet_reply_add(gdbctx, "vCont", 5);
995 /* add all the supported actions to the reply (all of them for now) */
996 packet_reply_add(gdbctx, ";c", 2);
997 packet_reply_add(gdbctx, ";C", 2);
998 packet_reply_add(gdbctx, ";s", 2);
999 packet_reply_add(gdbctx, ";S", 2);
1000 packet_reply_close(gdbctx);
1001 return packet_done;
1004 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1005 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1006 now if only gdb talked XML.... */
1007 #if 0 /* handy for debugging */
1008 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1009 #endif
1011 /* go through the packet and identify where all the actions start at */
1012 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1014 if (gdbctx->in_packet[i] == ';')
1016 threadIndex[actions] = 0;
1017 actionIndex[actions++] = i;
1019 else if (gdbctx->in_packet[i] == ':')
1021 threadIndex[actions - 1] = i;
1025 /* now look up the default action */
1026 for (i = 0 ; i < actions; i++)
1028 if (threadIndex[i] == 0)
1030 if (defaultAction != -1)
1032 fprintf(stderr,"Too many default actions specified\n");
1033 return packet_error;
1035 defaultAction = i;
1039 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1041 /* go through all the threads and stick their ids in the to be done list. */
1042 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1044 threadIDs[threadCount++] = thd->tid;
1045 /* check to see if we have more threads than I counted on, and tell the user what to do
1046 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1047 if (threadCount == 100)
1049 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1050 break;
1054 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1055 * that remains is to apply the actions to the threads and the default action to any threads
1056 * left */
1057 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1058 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1059 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
1060 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1062 /* deal with the threaded stuff first */
1063 for (i = 0; i < actions ; i++)
1065 if (threadIndex[i] != 0)
1067 int j, idLength = 0;
1068 if (i < actions - 1)
1070 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1072 else
1074 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1077 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1078 /* process the action */
1079 switch (gdbctx->in_packet[actionIndex[i] + 1])
1081 case 's': /* step */
1082 be_cpu->single_step(&gdbctx->context, TRUE);
1083 /* fall through*/
1084 case 'c': /* continue */
1085 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1086 break;
1087 case 'S': /* step Sig, */
1088 be_cpu->single_step(&gdbctx->context, TRUE);
1089 /* fall through */
1090 case 'C': /* continue sig */
1091 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1092 /* cannot change signals on the fly */
1093 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1094 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1095 if (sig != gdbctx->last_sig)
1096 return packet_error;
1097 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1098 break;
1100 for (j = 0 ; j < threadCount; j++)
1102 if (threadIDs[j] == threadID)
1104 threadIDs[j] = 0;
1105 break;
1109 } /* for i=0 ; i< actions */
1111 /* now we have manage the default action */
1112 if (defaultAction >= 0)
1114 for (i = 0 ; i< threadCount; i++)
1116 /* check to see if we've already done something to the thread*/
1117 if (threadIDs[i] != 0)
1119 /* if not apply the default action*/
1120 threadID = threadIDs[i];
1121 /* process the action (yes this is almost identical to the one above!) */
1122 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1124 case 's': /* step */
1125 be_cpu->single_step(&gdbctx->context, TRUE);
1126 /* fall through */
1127 case 'c': /* continue */
1128 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1129 break;
1130 case 'S':
1131 be_cpu->single_step(&gdbctx->context, TRUE);
1132 /* fall through */
1133 case 'C': /* continue sig */
1134 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1135 /* cannot change signals on the fly */
1136 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1137 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1138 if (sig != gdbctx->last_sig)
1139 return packet_error;
1140 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1141 break;
1145 } /* if(defaultAction >=0) */
1147 wait_for_debuggee(gdbctx);
1148 be_cpu->single_step(&gdbctx->context, FALSE);
1149 return packet_reply_status(gdbctx);
1152 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1154 unsigned char sig;
1156 /* FIXME: add support for address in packet */
1157 assert(gdbctx->in_packet_len == 2);
1158 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1159 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1160 fprintf(stderr, "NIY: cont/sig on %lu, while last thread is %lu\n",
1161 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1162 hex_from(&sig, gdbctx->in_packet, 1);
1163 /* cannot change signals on the fly */
1164 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1165 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1166 if (sig != gdbctx->last_sig)
1167 return packet_error;
1168 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1169 wait_for_debuggee(gdbctx);
1170 return packet_reply_status(gdbctx);
1173 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1175 detach_debuggee(gdbctx, FALSE);
1176 return packet_ok | packet_last_f;
1179 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1181 int i;
1182 CONTEXT ctx;
1183 CONTEXT* pctx = &gdbctx->context;
1185 assert(gdbctx->in_trap);
1187 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1189 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1190 return packet_error;
1193 packet_reply_open(gdbctx);
1194 for (i = 0; i < cpu_num_regs; i++)
1196 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1198 packet_reply_close(gdbctx);
1199 return packet_done;
1202 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1204 unsigned i;
1205 CONTEXT ctx;
1206 CONTEXT* pctx = &gdbctx->context;
1208 assert(gdbctx->in_trap);
1209 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1211 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1212 return packet_error;
1214 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1216 for (i = 0; i < cpu_num_regs; i++)
1217 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1218 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1220 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1221 fprintf(stderr, "Cannot set context on thread %lu\n", gdbctx->other_thread->tid);
1222 return packet_error;
1224 return packet_ok;
1227 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1229 detach_debuggee(gdbctx, TRUE);
1230 #if 0
1231 if (!gdbctx->extended)
1232 /* dunno whether GDB cares or not */
1233 #endif
1234 wait(NULL);
1235 exit(0);
1236 /* assume we can't really answer something here */
1237 /* return packet_done; */
1240 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1242 char* end;
1243 unsigned thread;
1245 switch (gdbctx->in_packet[0])
1247 case 'c':
1248 case 'g':
1249 if (gdbctx->in_packet[1] == '-')
1250 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1251 else
1252 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1253 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1255 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1256 fprintf(stderr, "Cannot get threadid %*.*s\n",
1257 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1258 gdbctx->in_packet + 1);
1259 return packet_error;
1261 if (gdbctx->in_packet[0] == 'c')
1262 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1263 else
1264 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1265 return packet_ok;
1266 default:
1267 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1268 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1269 return packet_error;
1273 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1275 char *addr;
1276 unsigned int len, blk_len, nread;
1277 char buffer[32];
1278 unsigned long r = 0;
1280 assert(gdbctx->in_trap);
1281 /* FIXME:check in_packet_len for reading %p,%x */
1282 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1283 if (len <= 0) return packet_error;
1284 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1285 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1286 for (nread = 0; nread < len; nread += r, addr += r)
1288 blk_len = min(sizeof(buffer), len - nread);
1289 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1290 r == 0)
1292 /* fail at first address, return error */
1293 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1294 /* something has already been read, return partial information */
1295 break;
1297 if (nread == 0) packet_reply_open(gdbctx);
1298 packet_reply_hex_to(gdbctx, buffer, r);
1300 packet_reply_close(gdbctx);
1301 return packet_done;
1304 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1306 char* addr;
1307 unsigned int len, blk_len;
1308 char* ptr;
1309 char buffer[32];
1310 unsigned long w;
1312 assert(gdbctx->in_trap);
1313 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1314 if (ptr == NULL)
1316 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1317 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1318 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1319 return packet_error;
1321 *ptr++ = '\0';
1323 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1325 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1326 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1327 return packet_error;
1329 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1331 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1332 fprintf(stderr, "Wrong sizes %u <> %u\n",
1333 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1334 return packet_error;
1336 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1337 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1338 while (len > 0)
1340 blk_len = min(sizeof(buffer), len);
1341 hex_from(buffer, ptr, blk_len);
1342 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1343 w != blk_len)
1344 break;
1345 addr += blk_len;
1346 len -= blk_len;
1347 ptr += blk_len;
1349 return packet_ok; /* FIXME: error while writing ? */
1352 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1354 unsigned reg;
1355 char* ptr;
1356 char* end;
1357 CONTEXT ctx;
1358 CONTEXT* pctx = &gdbctx->context;
1360 assert(gdbctx->in_trap);
1362 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1363 *ptr++ = '\0';
1364 reg = strtoul(gdbctx->in_packet, &end, 16);
1365 if (end == NULL || reg > cpu_num_regs)
1367 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1368 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1369 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1370 * it wouldn't matter too much, and it fakes our support for all regs
1372 return (end == NULL) ? packet_error : packet_ok;
1374 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1376 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1377 fprintf(stderr, "Wrong sizes %u <> %u\n",
1378 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1379 return packet_error;
1381 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1382 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1383 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1384 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1386 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1388 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1389 return packet_error;
1392 hex_from(cpu_register(pctx, reg), ptr, 4);
1393 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1395 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1396 fprintf(stderr, "Cannot set context for thread %lu\n", gdbctx->other_thread->tid);
1397 return packet_error;
1400 return packet_ok;
1403 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1405 char buffer[128];
1406 char clsName[128];
1407 char wndName[128];
1408 HWND child;
1410 do {
1411 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1412 strcpy(clsName, "-- Unknown --");
1413 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1414 strcpy(wndName, "-- Empty --");
1416 packet_reply_open(gdbctx);
1417 packet_reply_catc(gdbctx, 'O');
1418 snprintf(buffer, sizeof(buffer),
1419 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1420 indent, "", (UINT)hWnd, 13 - indent, "",
1421 clsName, GetWindowLong(hWnd, GWL_STYLE),
1422 GetWindowLongPtr(hWnd, GWLP_WNDPROC), wndName);
1423 packet_reply_hex_to_str(gdbctx, buffer);
1424 packet_reply_close(gdbctx);
1426 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1427 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1428 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1431 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1433 char buffer[128];
1435 /* we do the output in several 'O' packets, with the last one being just OK for
1436 * marking the end of the output */
1437 packet_reply_open(gdbctx);
1438 packet_reply_catc(gdbctx, 'O');
1439 snprintf(buffer, sizeof(buffer),
1440 "%-16.16s %-17.17s %-8.8s %s\n",
1441 "hwnd", "Class Name", " Style", " WndProc Text");
1442 packet_reply_hex_to_str(gdbctx, buffer);
1443 packet_reply_close(gdbctx);
1445 /* FIXME: could also add a pmt to this command in str... */
1446 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1447 packet_reply(gdbctx, "OK", 2);
1450 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1452 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1453 char buffer[128];
1454 char deco;
1455 PROCESSENTRY32 entry;
1456 BOOL ok;
1458 if (snap == INVALID_HANDLE_VALUE)
1459 return;
1461 entry.dwSize = sizeof(entry);
1462 ok = Process32First(snap, &entry);
1464 /* we do the output in several 'O' packets, with the last one being just OK for
1465 * marking the end of the output */
1467 packet_reply_open(gdbctx);
1468 packet_reply_catc(gdbctx, 'O');
1469 snprintf(buffer, sizeof(buffer),
1470 " %-8.8s %-8.8s %-8.8s %s\n",
1471 "pid", "threads", "parent", "executable");
1472 packet_reply_hex_to_str(gdbctx, buffer);
1473 packet_reply_close(gdbctx);
1475 while (ok)
1477 deco = ' ';
1478 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1479 packet_reply_open(gdbctx);
1480 packet_reply_catc(gdbctx, 'O');
1481 snprintf(buffer, sizeof(buffer),
1482 "%c%08lx %-8ld %08lx '%s'\n",
1483 deco, entry.th32ProcessID, entry.cntThreads,
1484 entry.th32ParentProcessID, entry.szExeFile);
1485 packet_reply_hex_to_str(gdbctx, buffer);
1486 packet_reply_close(gdbctx);
1487 ok = Process32Next(snap, &entry);
1489 CloseHandle(snap);
1490 packet_reply(gdbctx, "OK", 2);
1493 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1495 MEMORY_BASIC_INFORMATION mbi;
1496 char* addr = 0;
1497 const char* state;
1498 const char* type;
1499 char prot[3+1];
1500 char buffer[128];
1502 /* we do the output in several 'O' packets, with the last one being just OK for
1503 * marking the end of the output */
1504 packet_reply_open(gdbctx);
1505 packet_reply_catc(gdbctx, 'O');
1506 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1507 packet_reply_close(gdbctx);
1509 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1511 switch (mbi.State)
1513 case MEM_COMMIT: state = "commit "; break;
1514 case MEM_FREE: state = "free "; break;
1515 case MEM_RESERVE: state = "reserve"; break;
1516 default: state = "??? "; break;
1518 if (mbi.State != MEM_FREE)
1520 switch (mbi.Type)
1522 case MEM_IMAGE: type = "image "; break;
1523 case MEM_MAPPED: type = "mapped "; break;
1524 case MEM_PRIVATE: type = "private"; break;
1525 case 0: type = " "; break;
1526 default: type = "??? "; break;
1528 memset(prot, ' ' , sizeof(prot)-1);
1529 prot[sizeof(prot)-1] = '\0';
1530 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1531 prot[0] = 'R';
1532 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1533 prot[1] = 'W';
1534 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1535 prot[1] = 'C';
1536 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1537 prot[2] = 'X';
1539 else
1541 type = "";
1542 prot[0] = '\0';
1544 packet_reply_open(gdbctx);
1545 snprintf(buffer, sizeof(buffer),
1546 "%08lx %08lx %s %s %s\n",
1547 (DWORD)addr, mbi.RegionSize, state, type, prot);
1548 packet_reply_catc(gdbctx, 'O');
1549 packet_reply_hex_to_str(gdbctx, buffer);
1550 packet_reply_close(gdbctx);
1552 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1553 break;
1554 addr += mbi.RegionSize;
1556 packet_reply(gdbctx, "OK", 2);
1559 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1560 int len, const char* str)
1562 char buffer[128];
1564 if (len == 0)
1566 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1568 else if (len >= 2 && str[0] == '=')
1570 unsigned val = atoi(&str[1]);
1571 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1572 gdbctx->trace = val;
1574 else
1576 /* FIXME: ugly but can use error packet here */
1577 packet_reply_cat(gdbctx, "E00");
1578 return;
1580 packet_reply_open(gdbctx);
1581 packet_reply_hex_to_str(gdbctx, buffer);
1582 packet_reply_close(gdbctx);
1585 struct query_detail
1587 int with_arg;
1588 const char* name;
1589 size_t len;
1590 void (*handler)(struct gdb_context*, int, const char*);
1591 } query_details[] =
1593 {0, "wnd", 3, packet_query_monitor_wnd},
1594 {0, "window", 6, packet_query_monitor_wnd},
1595 {0, "proc", 4, packet_query_monitor_process},
1596 {0, "process", 7, packet_query_monitor_process},
1597 {0, "mem", 3, packet_query_monitor_mem},
1598 {1, "trace", 5, packet_query_monitor_trace},
1599 {0, NULL, 0, NULL},
1602 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1603 const char* hxcmd, size_t len)
1605 char buffer[128];
1606 struct query_detail* qd;
1608 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1609 len /= 2;
1610 hex_from(buffer, hxcmd, len);
1612 for (qd = &query_details[0]; qd->name != NULL; qd++)
1614 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1615 if (!qd->with_arg && len != qd->len) continue;
1617 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1618 return packet_done;
1620 return packet_reply_error(gdbctx, EINVAL);
1623 static enum packet_return packet_query(struct gdb_context* gdbctx)
1625 switch (gdbctx->in_packet[0])
1627 case 'f':
1628 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1630 struct dbg_thread* thd;
1632 packet_reply_open(gdbctx);
1633 packet_reply_add(gdbctx, "m", 1);
1634 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1636 packet_reply_val(gdbctx, thd->tid, 4);
1637 if (thd->next != NULL)
1638 packet_reply_add(gdbctx, ",", 1);
1640 packet_reply_close(gdbctx);
1641 return packet_done;
1643 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1645 char result[128];
1647 packet_reply_open(gdbctx);
1648 packet_reply_catc(gdbctx, 'O');
1649 get_process_info(gdbctx, result, sizeof(result));
1650 packet_reply_hex_to_str(gdbctx, result);
1651 packet_reply_close(gdbctx);
1652 return packet_done;
1654 break;
1655 case 's':
1656 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1658 packet_reply(gdbctx, "l", 1);
1659 return packet_done;
1661 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1663 packet_reply(gdbctx, "l", 1);
1664 return packet_done;
1666 break;
1667 case 'C':
1668 if (gdbctx->in_packet_len == 1)
1670 struct dbg_thread* thd;
1671 /* FIXME: doc says 16 bit val ??? */
1672 /* grab first created thread, aka last in list */
1673 assert(gdbctx->process && gdbctx->process->threads);
1674 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1675 packet_reply_open(gdbctx);
1676 packet_reply_add(gdbctx, "QC", 2);
1677 packet_reply_val(gdbctx, thd->tid, 4);
1678 packet_reply_close(gdbctx);
1679 return packet_done;
1681 break;
1682 case 'O':
1683 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1685 char buf[64];
1687 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1688 gdbctx->wine_segs[2] == 0)
1689 return packet_error;
1690 snprintf(buf, sizeof(buf),
1691 "Text=%08lx;Data=%08lx;Bss=%08lx",
1692 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1693 gdbctx->wine_segs[2]);
1694 return packet_reply(gdbctx, buf, -1);
1696 break;
1697 case 'R':
1698 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1700 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1701 gdbctx->in_packet_len - 5);
1703 break;
1704 case 'S':
1705 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1706 return packet_ok;
1707 break;
1708 case 'T':
1709 if (gdbctx->in_packet_len > 15 &&
1710 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1711 gdbctx->in_packet[15] == ',')
1713 unsigned tid;
1714 char* end;
1715 char result[128];
1717 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1718 if (end == NULL) break;
1719 get_thread_info(gdbctx, tid, result, sizeof(result));
1720 packet_reply_open(gdbctx);
1721 packet_reply_hex_to_str(gdbctx, result);
1722 packet_reply_close(gdbctx);
1723 return packet_done;
1725 break;
1727 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1728 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1729 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1730 return packet_error;
1733 static enum packet_return packet_step(struct gdb_context* gdbctx)
1735 /* FIXME: add support for address in packet */
1736 assert(gdbctx->in_packet_len == 0);
1737 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1738 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1739 fprintf(stderr, "NIY: step on %lu, while last thread is %lu\n",
1740 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1741 be_cpu->single_step(&gdbctx->context, TRUE);
1742 resume_debuggee(gdbctx, DBG_CONTINUE);
1743 wait_for_debuggee(gdbctx);
1744 be_cpu->single_step(&gdbctx->context, FALSE);
1745 return packet_reply_status(gdbctx);
1748 #if 0
1749 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1751 unsigned char sig;
1753 /* FIXME: add support for address in packet */
1754 assert(gdbctx->in_packet_len == 2);
1755 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1756 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1757 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1758 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1759 hex_from(&sig, gdbctx->in_packet, 1);
1760 /* cannot change signals on the fly */
1761 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1762 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1763 if (sig != gdbctx->last_sig)
1764 return packet_error;
1765 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1766 wait_for_debuggee(gdbctx);
1767 return packet_reply_status(gdbctx);
1769 #endif
1771 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1773 char* end;
1774 unsigned tid;
1776 tid = strtol(gdbctx->in_packet, &end, 16);
1777 if (tid == -1 || tid == 0)
1778 return packet_reply_error(gdbctx, EINVAL);
1779 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1780 return packet_ok;
1781 return packet_reply_error(gdbctx, ESRCH);
1784 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1786 void* addr;
1787 unsigned len;
1788 struct gdb_ctx_Xpoint* xpt;
1789 enum be_xpoint_type t;
1791 /* FIXME: check packet_len */
1792 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1793 gdbctx->in_packet[1] != ',' ||
1794 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1795 return packet_error;
1796 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1797 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1798 addr, len, gdbctx->in_packet[0]);
1799 switch (gdbctx->in_packet[0])
1801 case '0': t = be_xpoint_break; len = 0; break;
1802 case '1': t = be_xpoint_watch_exec; break;
1803 case '2': t = be_xpoint_watch_read; break;
1804 case '3': t = be_xpoint_watch_write; break;
1805 default: return packet_error;
1807 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1809 if (xpt->addr == addr && xpt->type == t)
1811 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1812 gdbctx->process->process_io, &gdbctx->context,
1813 t, xpt->addr, xpt->val, len))
1815 xpt->type = -1;
1816 return packet_ok;
1818 break;
1821 return packet_error;
1824 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1826 void* addr;
1827 unsigned len;
1828 struct gdb_ctx_Xpoint* xpt;
1829 enum be_xpoint_type t;
1831 /* FIXME: check packet_len */
1832 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1833 gdbctx->in_packet[1] != ',' ||
1834 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1835 return packet_error;
1836 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1837 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1838 addr, len, gdbctx->in_packet[0]);
1839 switch (gdbctx->in_packet[0])
1841 case '0': t = be_xpoint_break; len = 0; break;
1842 case '1': t = be_xpoint_watch_exec; break;
1843 case '2': t = be_xpoint_watch_read; break;
1844 case '3': t = be_xpoint_watch_write; break;
1845 default: return packet_error;
1847 /* because of packet command handling, this should be made idempotent */
1848 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1850 if (xpt->addr == addr && xpt->type == t)
1851 return packet_ok; /* nothing to do */
1853 /* really set the Xpoint */
1854 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1856 if (xpt->type == -1)
1858 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1859 gdbctx->process->process_io, &gdbctx->context,
1860 t, addr, &xpt->val, len))
1862 xpt->addr = addr;
1863 xpt->type = t;
1864 return packet_ok;
1866 fprintf(stderr, "cannot set xpoint\n");
1867 break;
1870 /* no more entries... eech */
1871 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1872 return packet_error;
1875 /* =============================================== *
1876 * P A C K E T I N F R A S T R U C T U R E *
1877 * =============================================== *
1880 struct packet_entry
1882 char key;
1883 enum packet_return (*handler)(struct gdb_context* gdbctx);
1886 static struct packet_entry packet_entries[] =
1888 /*{'!', packet_extended}, */
1889 {'?', packet_last_signal},
1890 {'c', packet_continue},
1891 {'C', packet_continue_signal},
1892 {'D', packet_detach},
1893 {'g', packet_read_registers},
1894 {'G', packet_write_registers},
1895 {'k', packet_kill},
1896 {'H', packet_thread},
1897 {'m', packet_read_memory},
1898 {'M', packet_write_memory},
1899 /* {'p', packet_read_register}, doesn't seem needed */
1900 {'P', packet_write_register},
1901 {'q', packet_query},
1902 /* {'Q', packet_set}, */
1903 /* {'R', packet,restart}, only in extended mode ! */
1904 {'s', packet_step},
1905 /*{'S', packet_step_signal}, hard(er) to implement */
1906 {'T', packet_thread_alive},
1907 {'v', packet_verbose},
1908 {'z', packet_remove_breakpoint},
1909 {'Z', packet_set_breakpoint},
1912 static BOOL extract_packets(struct gdb_context* gdbctx)
1914 char* end;
1915 int plen;
1916 unsigned char in_cksum, loc_cksum;
1917 char* ptr;
1918 enum packet_return ret = packet_error;
1919 int num_packet = 0;
1921 while ((ret & packet_last_f) == 0)
1923 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1924 fprintf(stderr, "In-buf: %*.*s\n",
1925 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1926 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1927 if (ptr == NULL) return FALSE;
1928 if (ptr != gdbctx->in_buf)
1930 int glen = ptr - gdbctx->in_buf; /* garbage len */
1931 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1932 fprintf(stderr, "Removing garbage: %*.*s\n",
1933 glen, glen, gdbctx->in_buf);
1934 gdbctx->in_len -= glen;
1935 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1937 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1938 if (end == NULL) return FALSE;
1939 /* no checksum yet */
1940 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1941 plen = end - gdbctx->in_buf - 1;
1942 hex_from(&in_cksum, end + 1, 1);
1943 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1944 if (loc_cksum == in_cksum)
1946 if (num_packet == 0) {
1947 int i;
1949 ret = packet_error;
1951 write(gdbctx->sock, "+", 1);
1952 assert(plen);
1954 /* FIXME: should use bsearch if packet_entries was sorted */
1955 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1957 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1959 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1961 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1962 fprintf(stderr, "Unknown packet request %*.*s\n",
1963 plen, plen, &gdbctx->in_buf[1]);
1965 else
1967 gdbctx->in_packet = gdbctx->in_buf + 2;
1968 gdbctx->in_packet_len = plen - 1;
1969 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1970 fprintf(stderr, "Packet: %c%*.*s\n",
1971 gdbctx->in_buf[1],
1972 gdbctx->in_packet_len, gdbctx->in_packet_len,
1973 gdbctx->in_packet);
1974 ret = (packet_entries[i].handler)(gdbctx);
1976 switch (ret & ~packet_last_f)
1978 case packet_error: packet_reply(gdbctx, "", 0); break;
1979 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
1980 case packet_done: break;
1982 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1983 fprintf(stderr, "Reply-full: %*.*s\n",
1984 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
1985 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
1986 assert(i == gdbctx->out_len);
1987 /* if this fails, we'll have to use POLLOUT...
1989 gdbctx->out_len = 0;
1990 num_packet++;
1992 else
1994 /* FIXME: if we have in our input buffer more than one packet,
1995 * it's very likely that we took too long to answer to a given packet
1996 * and gdb is sending us again the same packet
1997 * We simply drop the second packet. This will lower the risk of error,
1998 * but there's still some race conditions here
1999 * A better fix (yet not perfect) would be to have two threads:
2000 * - one managing the packets for gdb
2001 * - the second one managing the commands...
2002 * This would allow us also the reply with the '+' character (Ack of
2003 * the command) way sooner than what we do now
2005 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2006 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2009 else
2011 write(gdbctx->sock, "+", 1);
2012 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2013 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2015 gdbctx->in_len -= plen + 4;
2016 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2018 return TRUE;
2021 static int fetch_data(struct gdb_context* gdbctx)
2023 int len, in_len = gdbctx->in_len;
2025 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2026 for (;;)
2028 #define STEP 128
2029 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2030 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2031 #undef STEP
2032 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2033 fprintf(stderr, "%d %d %*.*s\n",
2034 gdbctx->in_len, gdbctx->in_buf_alloc,
2035 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2036 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2037 if (len <= 0) break;
2038 gdbctx->in_len += len;
2039 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2040 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2042 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2043 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2044 return gdbctx->in_len - in_len;
2047 #define FLAG_NO_START 1
2048 #define FLAG_WITH_XTERM 2
2050 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2052 char buf[MAX_PATH];
2053 int fd;
2054 const char* gdb_path;
2055 FILE* f;
2057 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2058 strcpy(buf,"/tmp/winegdb.XXXXXX");
2059 fd = mkstemps(buf, 0);
2060 if (fd == -1) return FALSE;
2061 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2062 fprintf(f, "file %s\n", wine_path);
2063 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2064 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2065 fprintf(f, "set prompt Wine-gdb>\\ \n");
2066 /* gdb 5.1 seems to require it, won't hurt anyway */
2067 fprintf(f, "sharedlibrary\n");
2068 /* This is needed (but not a decent & final fix)
2069 * Without this, gdb would skip our inter-DLL relay code (because
2070 * we don't have any line number information for the relay code)
2071 * With this, we will stop on first instruction of the stub, and
2072 * reusing step, will get us through the relay stub at the actual
2073 * function we're looking at.
2075 fprintf(f, "set step-mode on\n");
2076 /* tell gdb to delete this file when done handling it... */
2077 fprintf(f, "shell rm -f \"%s\"\n", buf);
2078 fclose(f);
2079 if (flags & FLAG_WITH_XTERM)
2080 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2081 else
2082 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2083 assert(0); /* never reached */
2084 return TRUE;
2087 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2089 int sock;
2090 struct sockaddr_in s_addrs;
2091 unsigned int s_len = sizeof(s_addrs);
2092 struct pollfd pollfd;
2093 IMAGEHLP_MODULE imh_mod;
2095 /* step 1: create socket for gdb connection request */
2096 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2098 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2099 fprintf(stderr, "Can't create socket");
2100 return FALSE;
2103 if (listen(sock, 1) == -1 ||
2104 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2105 return FALSE;
2107 /* step 2: do the process internal creation */
2108 handle_debug_event(gdbctx, de);
2110 /* step3: get the wine loader name */
2111 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2113 /* step 4: fire up gdb (if requested) */
2114 if (flags & FLAG_NO_START)
2115 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2116 else
2117 switch (fork())
2119 case -1: /* error in parent... */
2120 fprintf(stderr, "Cannot create gdb\n");
2121 return FALSE;
2122 break;
2123 default: /* in parent... success */
2124 break;
2125 case 0: /* in child... and alive */
2126 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2127 /* if we're here, exec failed, so report failure */
2128 return FALSE;
2131 /* step 5: wait for gdb to connect actually */
2132 pollfd.fd = sock;
2133 pollfd.events = POLLIN;
2134 pollfd.revents = 0;
2136 switch (poll(&pollfd, 1, -1))
2138 case 1:
2139 if (pollfd.revents & POLLIN)
2141 int dummy = 1;
2142 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2143 if (gdbctx->sock == -1)
2144 break;
2145 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2146 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2147 /* don't keep our small packets too long: send them ASAP back to GDB
2148 * without this, GDB really crawls
2150 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2152 break;
2153 case 0:
2154 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2155 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2156 return FALSE;
2157 case -1:
2158 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2159 fprintf(stderr, "Poll for cnx failed (error)\n");
2160 return FALSE;
2161 default:
2162 assert(0);
2165 close(sock);
2166 return TRUE;
2169 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2171 DEBUG_EVENT de;
2172 int i;
2174 gdbctx->sock = -1;
2175 gdbctx->in_buf = NULL;
2176 gdbctx->in_buf_alloc = 0;
2177 gdbctx->in_len = 0;
2178 gdbctx->out_buf = NULL;
2179 gdbctx->out_buf_alloc = 0;
2180 gdbctx->out_len = 0;
2181 gdbctx->out_curr_packet = -1;
2183 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2184 gdbctx->last_sig = 0;
2185 gdbctx->in_trap = FALSE;
2186 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2187 gdbctx->process = NULL;
2188 for (i = 0; i < NUM_XPOINT; i++)
2189 gdbctx->Xpoints[i].type = -1;
2191 /* wait for first trap */
2192 while (WaitForDebugEvent(&de, INFINITE))
2194 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2196 /* this should be the first event we get,
2197 * and the only one of this type */
2198 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2199 /* gdbctx->dwProcessId = pid; */
2200 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2201 assert(!gdbctx->in_trap);
2203 else
2205 handle_debug_event(gdbctx, &de);
2206 if (gdbctx->in_trap) break;
2208 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2210 return TRUE;
2213 static int gdb_remote(unsigned flags)
2215 struct pollfd pollfd;
2216 struct gdb_context gdbctx;
2217 BOOL doLoop;
2219 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2221 pollfd.fd = gdbctx.sock;
2222 pollfd.events = POLLIN;
2223 pollfd.revents = 0;
2225 switch (poll(&pollfd, 1, -1))
2227 case 1:
2228 /* got something */
2229 if (pollfd.revents & (POLLHUP | POLLERR))
2231 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2232 fprintf(stderr, "Gdb hung up\n");
2233 /* kill also debuggee process - questionnable - */
2234 detach_debuggee(&gdbctx, TRUE);
2235 doLoop = FALSE;
2236 break;
2238 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2240 if (extract_packets(&gdbctx)) doLoop = FALSE;
2242 break;
2243 case 0:
2244 /* timeout, should never happen (infinite timeout) */
2245 break;
2246 case -1:
2247 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2248 fprintf(stderr, "Poll failed\n");
2249 doLoop = FALSE;
2250 break;
2253 wait(NULL);
2254 return 0;
2257 int gdb_main(int argc, char* argv[])
2259 unsigned gdb_flags = 0;
2261 argc--; argv++;
2262 while (argc > 0 && argv[0][0] == '-')
2264 if (strcmp(argv[0], "--no-start") == 0)
2266 gdb_flags |= FLAG_NO_START;
2267 argc--; argv++;
2268 continue;
2270 if (strcmp(argv[0], "--with-xterm") == 0)
2272 gdb_flags |= FLAG_WITH_XTERM;
2273 argc--; argv++;
2274 continue;
2276 return -1;
2278 if (dbg_active_attach(argc, argv) == start_ok ||
2279 dbg_active_launch(argc, argv) == start_ok)
2280 return gdb_remote(gdb_flags);
2281 return -1;
2284 static struct be_process_io be_process_gdbproxy_io =
2286 NULL, /* we shouldn't use close_process() in gdbproxy */
2287 ReadProcessMemory,
2288 WriteProcessMemory