clock: Convert translations to po files.
[wine.git] / programs / winedbg / gdbproxy.c
blob3c86950d5de0280ab23b63b02e256cf919dacfe1
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/Maintenance-Commands.html
27 #include "config.h"
28 #include "wine/port.h"
30 #include <assert.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #ifdef HAVE_SYS_POLL_H
38 # include <sys/poll.h>
39 #endif
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
42 #endif
43 #ifdef HAVE_SYS_SOCKET_H
44 # include <sys/socket.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49 #ifdef HAVE_NETINET_TCP_H
50 # include <netinet/tcp.h>
51 #endif
52 #ifdef HAVE_UNISTD_H
53 # include <unistd.h>
54 #endif
56 /* if we don't have poll support on this system
57 * we won't provide gdb proxy support here...
59 #ifdef HAVE_POLL
61 #include "debugger.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "tlhelp32.h"
67 #define GDBPXY_TRC_LOWLEVEL 0x01
68 #define GDBPXY_TRC_PACKET 0x02
69 #define GDBPXY_TRC_COMMAND 0x04
70 #define GDBPXY_TRC_COMMAND_ERROR 0x08
71 #define GDBPXY_TRC_WIN32_EVENT 0x10
72 #define GDBPXY_TRC_WIN32_ERROR 0x20
73 #define GDBPXY_TRC_COMMAND_FIXME 0x80
75 struct gdb_ctx_Xpoint
77 enum be_xpoint_type type; /* -1 means free */
78 void* addr;
79 unsigned long val;
82 struct gdb_context
84 /* gdb information */
85 int sock;
86 /* incoming buffer */
87 char* in_buf;
88 int in_buf_alloc;
89 int in_len;
90 /* split into individual packet */
91 char* in_packet;
92 int in_packet_len;
93 /* outgoing buffer */
94 char* out_buf;
95 int out_buf_alloc;
96 int out_len;
97 int out_curr_packet;
98 /* generic GDB thread information */
99 struct dbg_thread* exec_thread; /* thread used in step & continue */
100 struct dbg_thread* other_thread; /* thread to be used in any other operation */
101 unsigned trace;
102 /* current Win32 trap env */
103 unsigned last_sig;
104 BOOL in_trap;
105 CONTEXT context;
106 /* Win32 information */
107 struct dbg_process* process;
108 #define NUM_XPOINT 32
109 struct gdb_ctx_Xpoint Xpoints[NUM_XPOINT];
110 /* Unix environment */
111 unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
114 static BOOL tgt_process_gdbproxy_read(HANDLE hProcess, const void* addr,
115 void* buffer, SIZE_T len, SIZE_T* rlen)
117 return ReadProcessMemory( hProcess, addr, buffer, len, rlen );
120 static BOOL tgt_process_gdbproxy_write(HANDLE hProcess, void* addr,
121 const void* buffer, SIZE_T len, SIZE_T* wlen)
123 return WriteProcessMemory( hProcess, addr, buffer, len, wlen );
126 static struct be_process_io be_process_gdbproxy_io =
128 NULL, /* we shouldn't use close_process() in gdbproxy */
129 tgt_process_gdbproxy_read,
130 tgt_process_gdbproxy_write
133 /* =============================================== *
134 * B A S I C M A N I P U L A T I O N S *
135 * =============================================== *
138 static inline int hex_from0(char ch)
140 if (ch >= '0' && ch <= '9') return ch - '0';
141 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
142 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
144 assert(0);
145 return 0;
148 static inline unsigned char hex_to0(int x)
150 assert(x >= 0 && x < 16);
151 return "0123456789abcdef"[x];
154 static int hex_to_int(const char* src, size_t len)
156 unsigned int returnval = 0;
157 while (len--)
159 returnval <<= 4;
160 returnval |= hex_from0(*src++);
162 return returnval;
165 static void hex_from(void* dst, const char* src, size_t len)
167 unsigned char *p = dst;
168 while (len--)
170 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
171 src += 2;
175 static void hex_to(char* dst, const void* src, size_t len)
177 const unsigned char *p = src;
178 while (len--)
180 *dst++ = hex_to0(*p >> 4);
181 *dst++ = hex_to0(*p & 0x0F);
182 p++;
186 static unsigned char checksum(const char* ptr, int len)
188 unsigned cksum = 0;
190 while (len-- > 0)
191 cksum += (unsigned char)*ptr++;
192 return cksum;
195 /* =============================================== *
196 * C P U H A N D L E R S *
197 * =============================================== *
200 #ifdef __i386__
201 static size_t cpu_register_map[] = {
202 FIELD_OFFSET(CONTEXT, Eax),
203 FIELD_OFFSET(CONTEXT, Ecx),
204 FIELD_OFFSET(CONTEXT, Edx),
205 FIELD_OFFSET(CONTEXT, Ebx),
206 FIELD_OFFSET(CONTEXT, Esp),
207 FIELD_OFFSET(CONTEXT, Ebp),
208 FIELD_OFFSET(CONTEXT, Esi),
209 FIELD_OFFSET(CONTEXT, Edi),
210 FIELD_OFFSET(CONTEXT, Eip),
211 FIELD_OFFSET(CONTEXT, EFlags),
212 FIELD_OFFSET(CONTEXT, SegCs),
213 FIELD_OFFSET(CONTEXT, SegSs),
214 FIELD_OFFSET(CONTEXT, SegDs),
215 FIELD_OFFSET(CONTEXT, SegEs),
216 FIELD_OFFSET(CONTEXT, SegFs),
217 FIELD_OFFSET(CONTEXT, SegGs),
219 #elif defined(__powerpc__)
220 static size_t cpu_register_map[] = {
221 FIELD_OFFSET(CONTEXT, Gpr0),
222 FIELD_OFFSET(CONTEXT, Gpr1),
223 FIELD_OFFSET(CONTEXT, Gpr2),
224 FIELD_OFFSET(CONTEXT, Gpr3),
225 FIELD_OFFSET(CONTEXT, Gpr4),
226 FIELD_OFFSET(CONTEXT, Gpr5),
227 FIELD_OFFSET(CONTEXT, Gpr6),
228 FIELD_OFFSET(CONTEXT, Gpr7),
229 FIELD_OFFSET(CONTEXT, Gpr8),
230 FIELD_OFFSET(CONTEXT, Gpr9),
231 FIELD_OFFSET(CONTEXT, Gpr10),
232 FIELD_OFFSET(CONTEXT, Gpr11),
233 FIELD_OFFSET(CONTEXT, Gpr12),
234 FIELD_OFFSET(CONTEXT, Gpr13),
235 FIELD_OFFSET(CONTEXT, Gpr14),
236 FIELD_OFFSET(CONTEXT, Gpr15),
237 FIELD_OFFSET(CONTEXT, Gpr16),
238 FIELD_OFFSET(CONTEXT, Gpr17),
239 FIELD_OFFSET(CONTEXT, Gpr18),
240 FIELD_OFFSET(CONTEXT, Gpr19),
241 FIELD_OFFSET(CONTEXT, Gpr20),
242 FIELD_OFFSET(CONTEXT, Gpr21),
243 FIELD_OFFSET(CONTEXT, Gpr22),
244 FIELD_OFFSET(CONTEXT, Gpr23),
245 FIELD_OFFSET(CONTEXT, Gpr24),
246 FIELD_OFFSET(CONTEXT, Gpr25),
247 FIELD_OFFSET(CONTEXT, Gpr26),
248 FIELD_OFFSET(CONTEXT, Gpr27),
249 FIELD_OFFSET(CONTEXT, Gpr28),
250 FIELD_OFFSET(CONTEXT, Gpr29),
251 FIELD_OFFSET(CONTEXT, Gpr30),
252 FIELD_OFFSET(CONTEXT, Gpr31),
253 FIELD_OFFSET(CONTEXT, Fpr0),
254 FIELD_OFFSET(CONTEXT, Fpr1),
255 FIELD_OFFSET(CONTEXT, Fpr2),
256 FIELD_OFFSET(CONTEXT, Fpr3),
257 FIELD_OFFSET(CONTEXT, Fpr4),
258 FIELD_OFFSET(CONTEXT, Fpr5),
259 FIELD_OFFSET(CONTEXT, Fpr6),
260 FIELD_OFFSET(CONTEXT, Fpr7),
261 FIELD_OFFSET(CONTEXT, Fpr8),
262 FIELD_OFFSET(CONTEXT, Fpr9),
263 FIELD_OFFSET(CONTEXT, Fpr10),
264 FIELD_OFFSET(CONTEXT, Fpr11),
265 FIELD_OFFSET(CONTEXT, Fpr12),
266 FIELD_OFFSET(CONTEXT, Fpr13),
267 FIELD_OFFSET(CONTEXT, Fpr14),
268 FIELD_OFFSET(CONTEXT, Fpr15),
269 FIELD_OFFSET(CONTEXT, Fpr16),
270 FIELD_OFFSET(CONTEXT, Fpr17),
271 FIELD_OFFSET(CONTEXT, Fpr18),
272 FIELD_OFFSET(CONTEXT, Fpr19),
273 FIELD_OFFSET(CONTEXT, Fpr20),
274 FIELD_OFFSET(CONTEXT, Fpr21),
275 FIELD_OFFSET(CONTEXT, Fpr22),
276 FIELD_OFFSET(CONTEXT, Fpr23),
277 FIELD_OFFSET(CONTEXT, Fpr24),
278 FIELD_OFFSET(CONTEXT, Fpr25),
279 FIELD_OFFSET(CONTEXT, Fpr26),
280 FIELD_OFFSET(CONTEXT, Fpr27),
281 FIELD_OFFSET(CONTEXT, Fpr28),
282 FIELD_OFFSET(CONTEXT, Fpr29),
283 FIELD_OFFSET(CONTEXT, Fpr30),
284 FIELD_OFFSET(CONTEXT, Fpr31),
286 FIELD_OFFSET(CONTEXT, Iar),
287 FIELD_OFFSET(CONTEXT, Msr),
288 FIELD_OFFSET(CONTEXT, Cr),
289 FIELD_OFFSET(CONTEXT, Lr),
290 FIELD_OFFSET(CONTEXT, Ctr),
291 FIELD_OFFSET(CONTEXT, Xer),
292 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
293 /* see gdb/nlm/ppc.c */
295 #elif defined(__ALPHA__)
296 static size_t cpu_register_map[] = {
297 FIELD_OFFSET(CONTEXT, IntV0),
298 FIELD_OFFSET(CONTEXT, IntT0),
299 FIELD_OFFSET(CONTEXT, IntT1),
300 FIELD_OFFSET(CONTEXT, IntT2),
301 FIELD_OFFSET(CONTEXT, IntT3),
302 FIELD_OFFSET(CONTEXT, IntT4),
303 FIELD_OFFSET(CONTEXT, IntT5),
304 FIELD_OFFSET(CONTEXT, IntT6),
305 FIELD_OFFSET(CONTEXT, IntT7),
306 FIELD_OFFSET(CONTEXT, IntS0),
307 FIELD_OFFSET(CONTEXT, IntS1),
308 FIELD_OFFSET(CONTEXT, IntS2),
309 FIELD_OFFSET(CONTEXT, IntS3),
310 FIELD_OFFSET(CONTEXT, IntS4),
311 FIELD_OFFSET(CONTEXT, IntS5),
312 FIELD_OFFSET(CONTEXT, IntFp),
313 FIELD_OFFSET(CONTEXT, IntA0),
314 FIELD_OFFSET(CONTEXT, IntA1),
315 FIELD_OFFSET(CONTEXT, IntA2),
316 FIELD_OFFSET(CONTEXT, IntA3),
317 FIELD_OFFSET(CONTEXT, IntA4),
318 FIELD_OFFSET(CONTEXT, IntA5),
319 FIELD_OFFSET(CONTEXT, IntT8),
320 FIELD_OFFSET(CONTEXT, IntT9),
321 FIELD_OFFSET(CONTEXT, IntT10),
322 FIELD_OFFSET(CONTEXT, IntT11),
323 FIELD_OFFSET(CONTEXT, IntRa),
324 FIELD_OFFSET(CONTEXT, IntT12),
325 FIELD_OFFSET(CONTEXT, IntAt),
326 FIELD_OFFSET(CONTEXT, IntGp),
327 FIELD_OFFSET(CONTEXT, IntSp),
328 FIELD_OFFSET(CONTEXT, IntZero),
329 FIELD_OFFSET(CONTEXT, FltF0),
330 FIELD_OFFSET(CONTEXT, FltF1),
331 FIELD_OFFSET(CONTEXT, FltF2),
332 FIELD_OFFSET(CONTEXT, FltF3),
333 FIELD_OFFSET(CONTEXT, FltF4),
334 FIELD_OFFSET(CONTEXT, FltF5),
335 FIELD_OFFSET(CONTEXT, FltF6),
336 FIELD_OFFSET(CONTEXT, FltF7),
337 FIELD_OFFSET(CONTEXT, FltF8),
338 FIELD_OFFSET(CONTEXT, FltF9),
339 FIELD_OFFSET(CONTEXT, FltF10),
340 FIELD_OFFSET(CONTEXT, FltF11),
341 FIELD_OFFSET(CONTEXT, FltF12),
342 FIELD_OFFSET(CONTEXT, FltF13),
343 FIELD_OFFSET(CONTEXT, FltF14),
344 FIELD_OFFSET(CONTEXT, FltF15),
345 FIELD_OFFSET(CONTEXT, FltF16),
346 FIELD_OFFSET(CONTEXT, FltF17),
347 FIELD_OFFSET(CONTEXT, FltF18),
348 FIELD_OFFSET(CONTEXT, FltF19),
349 FIELD_OFFSET(CONTEXT, FltF20),
350 FIELD_OFFSET(CONTEXT, FltF21),
351 FIELD_OFFSET(CONTEXT, FltF22),
352 FIELD_OFFSET(CONTEXT, FltF23),
353 FIELD_OFFSET(CONTEXT, FltF24),
354 FIELD_OFFSET(CONTEXT, FltF25),
355 FIELD_OFFSET(CONTEXT, FltF26),
356 FIELD_OFFSET(CONTEXT, FltF27),
357 FIELD_OFFSET(CONTEXT, FltF28),
358 FIELD_OFFSET(CONTEXT, FltF29),
359 FIELD_OFFSET(CONTEXT, FltF30),
360 FIELD_OFFSET(CONTEXT, FltF31),
362 /* FIXME: Didn't look for the right order yet */
363 FIELD_OFFSET(CONTEXT, Fir),
364 FIELD_OFFSET(CONTEXT, Fpcr),
365 FIELD_OFFSET(CONTEXT, SoftFpcr),
367 #elif defined(__x86_64__)
368 static size_t cpu_register_map[] = {
369 FIELD_OFFSET(CONTEXT, Rax),
370 FIELD_OFFSET(CONTEXT, Rbx),
371 FIELD_OFFSET(CONTEXT, Rcx),
372 FIELD_OFFSET(CONTEXT, Rdx),
373 FIELD_OFFSET(CONTEXT, Rsi),
374 FIELD_OFFSET(CONTEXT, Rdi),
375 FIELD_OFFSET(CONTEXT, Rbp),
376 FIELD_OFFSET(CONTEXT, Rsp),
377 FIELD_OFFSET(CONTEXT, R8),
378 FIELD_OFFSET(CONTEXT, R9),
379 FIELD_OFFSET(CONTEXT, R10),
380 FIELD_OFFSET(CONTEXT, R11),
381 FIELD_OFFSET(CONTEXT, R12),
382 FIELD_OFFSET(CONTEXT, R13),
383 FIELD_OFFSET(CONTEXT, R14),
384 FIELD_OFFSET(CONTEXT, R15),
385 FIELD_OFFSET(CONTEXT, Rip),
386 FIELD_OFFSET(CONTEXT, EFlags),
387 FIELD_OFFSET(CONTEXT, SegCs),
388 FIELD_OFFSET(CONTEXT, SegSs),
389 FIELD_OFFSET(CONTEXT, SegDs),
390 FIELD_OFFSET(CONTEXT, SegEs),
391 FIELD_OFFSET(CONTEXT, SegFs),
392 FIELD_OFFSET(CONTEXT, SegGs),
394 #elif defined(__sparc__)
395 static size_t cpu_register_map[] = {
396 FIELD_OFFSET(CONTEXT, g0),
397 FIELD_OFFSET(CONTEXT, g1),
398 FIELD_OFFSET(CONTEXT, g2),
399 FIELD_OFFSET(CONTEXT, g3),
400 FIELD_OFFSET(CONTEXT, g4),
401 FIELD_OFFSET(CONTEXT, g5),
402 FIELD_OFFSET(CONTEXT, g6),
403 FIELD_OFFSET(CONTEXT, g7),
404 FIELD_OFFSET(CONTEXT, o0),
405 FIELD_OFFSET(CONTEXT, o1),
406 FIELD_OFFSET(CONTEXT, o2),
407 FIELD_OFFSET(CONTEXT, o3),
408 FIELD_OFFSET(CONTEXT, o4),
409 FIELD_OFFSET(CONTEXT, o5),
410 FIELD_OFFSET(CONTEXT, o6),
411 FIELD_OFFSET(CONTEXT, o7),
412 FIELD_OFFSET(CONTEXT, l0),
413 FIELD_OFFSET(CONTEXT, l1),
414 FIELD_OFFSET(CONTEXT, l2),
415 FIELD_OFFSET(CONTEXT, l3),
416 FIELD_OFFSET(CONTEXT, l4),
417 FIELD_OFFSET(CONTEXT, l5),
418 FIELD_OFFSET(CONTEXT, l6),
419 FIELD_OFFSET(CONTEXT, l7),
420 FIELD_OFFSET(CONTEXT, i0),
421 FIELD_OFFSET(CONTEXT, i1),
422 FIELD_OFFSET(CONTEXT, i2),
423 FIELD_OFFSET(CONTEXT, i3),
424 FIELD_OFFSET(CONTEXT, i4),
425 FIELD_OFFSET(CONTEXT, i5),
426 FIELD_OFFSET(CONTEXT, i6),
427 FIELD_OFFSET(CONTEXT, i7),
429 #elif defined(__arm__)
430 static size_t cpu_register_map[] = {
431 FIELD_OFFSET(CONTEXT, R0),
432 FIELD_OFFSET(CONTEXT, R1),
433 FIELD_OFFSET(CONTEXT, R2),
434 FIELD_OFFSET(CONTEXT, R3),
435 FIELD_OFFSET(CONTEXT, R4),
436 FIELD_OFFSET(CONTEXT, R5),
437 FIELD_OFFSET(CONTEXT, R6),
438 FIELD_OFFSET(CONTEXT, R7),
439 FIELD_OFFSET(CONTEXT, R8),
440 FIELD_OFFSET(CONTEXT, R9),
441 FIELD_OFFSET(CONTEXT, R10),
442 FIELD_OFFSET(CONTEXT, Fp),
443 FIELD_OFFSET(CONTEXT, Ip),
445 #else
446 # error Define the registers map for your CPU
447 #endif
449 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
451 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
453 assert(idx < cpu_num_regs);
454 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
457 /* =============================================== *
458 * W I N 3 2 D E B U G I N T E R F A C E *
459 * =============================================== *
462 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
464 ctx->ContextFlags = CONTEXT_CONTROL
465 | CONTEXT_INTEGER
466 #ifdef CONTEXT_SEGMENTS
467 | CONTEXT_SEGMENTS
468 #endif
469 #ifdef CONTEXT_DEBUG_REGISTERS
470 | CONTEXT_DEBUG_REGISTERS
471 #endif
473 if (!GetThreadContext(h, ctx))
475 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
476 fprintf(stderr, "Can't get thread's context\n");
477 return FALSE;
479 return TRUE;
482 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
484 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
485 BOOL ret = FALSE;
487 switch (rec->ExceptionCode)
489 case EXCEPTION_ACCESS_VIOLATION:
490 case EXCEPTION_PRIV_INSTRUCTION:
491 case EXCEPTION_STACK_OVERFLOW:
492 case EXCEPTION_GUARD_PAGE:
493 gdbctx->last_sig = SIGSEGV;
494 ret = TRUE;
495 break;
496 case EXCEPTION_DATATYPE_MISALIGNMENT:
497 gdbctx->last_sig = SIGBUS;
498 ret = TRUE;
499 break;
500 case EXCEPTION_SINGLE_STEP:
501 /* fall thru */
502 case EXCEPTION_BREAKPOINT:
503 gdbctx->last_sig = SIGTRAP;
504 ret = TRUE;
505 break;
506 case EXCEPTION_FLT_DENORMAL_OPERAND:
507 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
508 case EXCEPTION_FLT_INEXACT_RESULT:
509 case EXCEPTION_FLT_INVALID_OPERATION:
510 case EXCEPTION_FLT_OVERFLOW:
511 case EXCEPTION_FLT_STACK_CHECK:
512 case EXCEPTION_FLT_UNDERFLOW:
513 gdbctx->last_sig = SIGFPE;
514 ret = TRUE;
515 break;
516 case EXCEPTION_INT_DIVIDE_BY_ZERO:
517 case EXCEPTION_INT_OVERFLOW:
518 gdbctx->last_sig = SIGFPE;
519 ret = TRUE;
520 break;
521 case EXCEPTION_ILLEGAL_INSTRUCTION:
522 gdbctx->last_sig = SIGILL;
523 ret = TRUE;
524 break;
525 case CONTROL_C_EXIT:
526 gdbctx->last_sig = SIGINT;
527 ret = TRUE;
528 break;
529 case STATUS_POSSIBLE_DEADLOCK:
530 gdbctx->last_sig = SIGALRM;
531 ret = TRUE;
532 /* FIXME: we could also add here a O packet with additional information */
533 break;
534 default:
535 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
536 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
537 gdbctx->last_sig = SIGABRT;
538 ret = TRUE;
539 break;
541 return ret;
544 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
546 union {
547 char bufferA[256];
548 WCHAR buffer[256];
549 } u;
551 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
553 switch (de->dwDebugEventCode)
555 case CREATE_PROCESS_DEBUG_EVENT:
556 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
557 de->u.CreateProcessInfo.hProcess);
558 if (!gdbctx->process) break;
559 memory_get_string_indirect(gdbctx->process,
560 de->u.CreateProcessInfo.lpImageName,
561 de->u.CreateProcessInfo.fUnicode,
562 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
563 dbg_set_process_name(gdbctx->process, u.buffer);
565 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
566 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
567 de->dwProcessId, de->dwThreadId,
568 dbg_W2A(u.buffer, -1),
569 de->u.CreateProcessInfo.lpImageName,
570 de->u.CreateProcessInfo.lpStartAddress,
571 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
572 de->u.CreateProcessInfo.nDebugInfoSize);
574 /* de->u.CreateProcessInfo.lpStartAddress; */
575 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
576 fprintf(stderr, "Couldn't initiate DbgHelp\n");
578 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
579 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
580 de->dwProcessId, de->dwThreadId,
581 de->u.CreateProcessInfo.lpStartAddress);
583 assert(dbg_curr_thread == NULL); /* shouldn't be there */
584 dbg_add_thread(gdbctx->process, de->dwThreadId,
585 de->u.CreateProcessInfo.hThread,
586 de->u.CreateProcessInfo.lpThreadLocalBase);
587 break;
589 case LOAD_DLL_DEBUG_EVENT:
590 assert(dbg_curr_thread);
591 memory_get_string_indirect(gdbctx->process,
592 de->u.LoadDll.lpImageName,
593 de->u.LoadDll.fUnicode,
594 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
595 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
596 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
597 de->dwProcessId, de->dwThreadId,
598 dbg_W2A(u.buffer, -1),
599 de->u.LoadDll.lpBaseOfDll,
600 de->u.LoadDll.dwDebugInfoFileOffset,
601 de->u.LoadDll.nDebugInfoSize);
602 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
603 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
604 break;
606 case UNLOAD_DLL_DEBUG_EVENT:
607 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
608 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
609 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
610 SymUnloadModule(gdbctx->process->handle,
611 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
612 break;
614 case EXCEPTION_DEBUG_EVENT:
615 assert(dbg_curr_thread);
616 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
617 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
618 de->dwProcessId, de->dwThreadId,
619 de->u.Exception.ExceptionRecord.ExceptionCode);
621 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
623 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
625 break;
627 case CREATE_THREAD_DEBUG_EVENT:
628 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
629 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
630 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
632 dbg_add_thread(gdbctx->process,
633 de->dwThreadId,
634 de->u.CreateThread.hThread,
635 de->u.CreateThread.lpThreadLocalBase);
636 break;
638 case EXIT_THREAD_DEBUG_EVENT:
639 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
640 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
641 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
643 assert(dbg_curr_thread);
644 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
645 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
646 dbg_del_thread(dbg_curr_thread);
647 break;
649 case EXIT_PROCESS_DEBUG_EVENT:
650 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
651 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
652 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
654 dbg_del_process(gdbctx->process);
655 gdbctx->process = NULL;
656 /* now signal gdb that we're done */
657 gdbctx->last_sig = SIGTERM;
658 gdbctx->in_trap = TRUE;
659 break;
661 case OUTPUT_DEBUG_STRING_EVENT:
662 assert(dbg_curr_thread);
663 memory_get_string(gdbctx->process,
664 de->u.DebugString.lpDebugStringData, TRUE,
665 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
666 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
667 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
668 de->dwProcessId, de->dwThreadId, u.bufferA);
669 break;
671 case RIP_EVENT:
672 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
673 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
674 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
675 de->u.RipInfo.dwType);
676 break;
678 default:
679 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
680 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
681 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
685 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
687 if (dbg_curr_thread)
689 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
690 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
691 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
692 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
693 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
694 fprintf(stderr, "Cannot continue on %04x (%x)\n",
695 dbg_curr_thread->tid, cont);
697 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
698 fprintf(stderr, "Cannot find last thread\n");
702 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
705 if (dbg_curr_thread)
707 if(dbg_curr_thread->tid == threadid){
708 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
709 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
710 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
711 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
712 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
713 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
714 fprintf(stderr, "Cannot continue on %04x (%x)\n",
715 dbg_curr_thread->tid, cont);
718 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
719 fprintf(stderr, "Cannot find last thread\n");
722 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
724 struct pollfd pollfd;
725 int ret;
726 char pkt;
728 pollfd.fd = gdbctx->sock;
729 pollfd.events = POLLIN;
730 pollfd.revents = 0;
732 if ((ret = poll(&pollfd, 1, 0)) == 1) {
733 ret = read(gdbctx->sock, &pkt, 1);
734 if (ret != 1) {
735 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
736 fprintf(stderr, "read failed\n");
738 return FALSE;
740 if (pkt != '\003') {
741 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
742 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
744 return FALSE;
746 return TRUE;
747 } else if (ret == -1) {
748 fprintf(stderr, "poll failed\n");
750 return FALSE;
753 static void wait_for_debuggee(struct gdb_context* gdbctx)
755 DEBUG_EVENT de;
757 gdbctx->in_trap = FALSE;
758 for (;;)
760 if (!WaitForDebugEvent(&de, 10))
762 if (GetLastError() == ERROR_SEM_TIMEOUT)
764 if (check_for_interrupt(gdbctx)) {
765 if (!DebugBreakProcess(gdbctx->process->handle)) {
766 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
767 fprintf(stderr, "Failed to break into debugee\n");
769 break;
771 WaitForDebugEvent(&de, INFINITE);
772 } else {
773 continue;
775 } else {
776 break;
779 handle_debug_event(gdbctx, &de);
780 assert(!gdbctx->process ||
781 gdbctx->process->pid == 0 ||
782 de.dwProcessId == gdbctx->process->pid);
783 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
784 if (gdbctx->in_trap) break;
785 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
789 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
791 be_cpu->single_step(&gdbctx->context, FALSE);
792 resume_debuggee(gdbctx, DBG_CONTINUE);
793 if (!kill)
794 DebugActiveProcessStop(gdbctx->process->pid);
795 dbg_del_process(gdbctx->process);
796 gdbctx->process = NULL;
799 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
801 DWORD status;
803 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
805 strcpy(buffer, "Unknown process");
806 return;
808 if (status == STILL_ACTIVE)
810 strcpy(buffer, "Running");
812 else
813 snprintf(buffer, len, "Terminated (%u)", status);
815 switch (GetPriorityClass(gdbctx->process->handle))
817 case 0: break;
818 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
819 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
820 #endif
821 #ifdef BELOW_NORMAL_PRIORITY_CLASS
822 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
823 #endif
824 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
825 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
826 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
827 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
829 strcat(buffer, "\n");
832 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
833 char* buffer, size_t len)
835 struct dbg_thread* thd;
836 DWORD status;
837 int prio;
839 /* FIXME: use the size of buffer */
840 thd = dbg_get_thread(gdbctx->process, tid);
841 if (thd == NULL)
843 strcpy(buffer, "No information");
844 return;
846 if (GetExitCodeThread(thd->handle, &status))
848 if (status == STILL_ACTIVE)
850 /* FIXME: this is a bit brutal... some nicer way shall be found */
851 switch (status = SuspendThread(thd->handle))
853 case -1: break;
854 case 0: strcpy(buffer, "Running"); break;
855 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
857 ResumeThread(thd->handle);
859 else
860 snprintf(buffer, len, "Terminated (exit code = %u)", status);
862 else
864 strcpy(buffer, "Unknown threadID");
866 switch (prio = GetThreadPriority(thd->handle))
868 case THREAD_PRIORITY_ERROR_RETURN: break;
869 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
870 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
871 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
872 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
873 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
874 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
875 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
876 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
878 assert(strlen(buffer) < len);
881 /* =============================================== *
882 * P A C K E T U T I L S *
883 * =============================================== *
886 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
887 packet_last_f = 0x80};
889 static char* packet_realloc(char* buf, int size)
891 if (!buf)
892 return HeapAlloc(GetProcessHeap(), 0, size);
893 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
897 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
899 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
901 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
902 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
906 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
908 packet_reply_grow(gdbctx, len * 2);
909 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
910 gdbctx->out_len += len * 2;
913 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
915 packet_reply_hex_to(gdbctx, src, strlen(src));
918 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
920 int i, shift;
922 shift = (len - 1) * 8;
923 packet_reply_grow(gdbctx, len * 2);
924 for (i = 0; i < len; i++, shift -= 8)
926 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
927 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
931 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
933 packet_reply_grow(gdbctx, len);
934 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
935 gdbctx->out_len += len;
938 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
940 packet_reply_add(gdbctx, str, strlen(str));
943 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
945 packet_reply_add(gdbctx, &ch, 1);
948 static void packet_reply_open(struct gdb_context* gdbctx)
950 assert(gdbctx->out_curr_packet == -1);
951 packet_reply_catc(gdbctx, '$');
952 gdbctx->out_curr_packet = gdbctx->out_len;
955 static void packet_reply_close(struct gdb_context* gdbctx)
957 unsigned char cksum;
958 int plen;
960 plen = gdbctx->out_len - gdbctx->out_curr_packet;
961 packet_reply_catc(gdbctx, '#');
962 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
963 packet_reply_hex_to(gdbctx, &cksum, 1);
964 if (gdbctx->trace & GDBPXY_TRC_PACKET)
965 fprintf(stderr, "Reply : %*.*s\n",
966 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
967 gdbctx->out_curr_packet = -1;
970 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
972 packet_reply_open(gdbctx);
974 if (len == -1) len = strlen(packet);
975 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
977 packet_reply_add(gdbctx, packet, len);
979 packet_reply_close(gdbctx);
981 return packet_done;
984 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
986 packet_reply_open(gdbctx);
988 packet_reply_add(gdbctx, "E", 1);
989 packet_reply_val(gdbctx, error, 1);
991 packet_reply_close(gdbctx);
993 return packet_done;
996 /* =============================================== *
997 * P A C K E T H A N D L E R S *
998 * =============================================== *
1001 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
1003 enum packet_return ret = packet_done;
1005 packet_reply_open(gdbctx);
1007 if (gdbctx->process != NULL)
1009 unsigned char sig;
1010 unsigned i;
1012 packet_reply_catc(gdbctx, 'T');
1013 sig = gdbctx->last_sig;
1014 packet_reply_val(gdbctx, sig, 1);
1015 packet_reply_add(gdbctx, "thread:", 7);
1016 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
1017 packet_reply_catc(gdbctx, ';');
1019 for (i = 0; i < cpu_num_regs; i++)
1021 /* FIXME: this call will also grow the buffer...
1022 * unneeded, but not harmful
1024 packet_reply_val(gdbctx, i, 1);
1025 packet_reply_catc(gdbctx, ':');
1026 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
1027 packet_reply_catc(gdbctx, ';');
1030 else
1032 /* Try to put an exit code
1033 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1034 * just indicate the end of process and exit */
1035 packet_reply_add(gdbctx, "W00", 3);
1036 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1039 packet_reply_close(gdbctx);
1041 return ret;
1044 #if 0
1045 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1047 gdbctx->extended = 1;
1048 return packet_ok;
1050 #endif
1052 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1054 assert(gdbctx->in_packet_len == 0);
1055 return packet_reply_status(gdbctx);
1058 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1060 /* FIXME: add support for address in packet */
1061 assert(gdbctx->in_packet_len == 0);
1062 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1063 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1064 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1065 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1066 resume_debuggee(gdbctx, DBG_CONTINUE);
1067 wait_for_debuggee(gdbctx);
1068 return packet_reply_status(gdbctx);
1071 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1073 int i;
1074 int defaultAction = -1; /* magic non action */
1075 unsigned char sig;
1076 int actions =0;
1077 int actionIndex[20]; /* allow for up to 20 actions */
1078 int threadIndex[20];
1079 int threadCount = 0;
1080 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1081 unsigned int threadID = 0;
1082 struct dbg_thread* thd;
1084 /* basic check */
1085 assert(gdbctx->in_packet_len >= 4);
1087 /* OK we have vCont followed by..
1088 * ? for query
1089 * c for packet_continue
1090 * Csig for packet_continue_signal
1091 * s for step
1092 * Ssig for step signal
1093 * and then an optional thread ID at the end..
1094 * *******************************************/
1096 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1097 fprintf(stderr, "trying to process a verbose packet\n");
1098 /* now check that we've got Cont */
1099 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
1101 /* Query */
1102 if (gdbctx->in_packet[4] == '?')
1105 Reply:
1106 `vCont[;action]...'
1107 The vCont packet is supported. Each action is a supported command in the vCont packet.
1109 The vCont packet is not supported. (this didn't seem to be obeyed!)
1111 packet_reply_open(gdbctx);
1112 packet_reply_add(gdbctx, "vCont", 5);
1113 /* add all the supported actions to the reply (all of them for now) */
1114 packet_reply_add(gdbctx, ";c", 2);
1115 packet_reply_add(gdbctx, ";C", 2);
1116 packet_reply_add(gdbctx, ";s", 2);
1117 packet_reply_add(gdbctx, ";S", 2);
1118 packet_reply_close(gdbctx);
1119 return packet_done;
1122 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1123 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1124 now if only gdb talked XML.... */
1125 #if 0 /* handy for debugging */
1126 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1127 #endif
1129 /* go through the packet and identify where all the actions start at */
1130 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1132 if (gdbctx->in_packet[i] == ';')
1134 threadIndex[actions] = 0;
1135 actionIndex[actions++] = i;
1137 else if (gdbctx->in_packet[i] == ':')
1139 threadIndex[actions - 1] = i;
1143 /* now look up the default action */
1144 for (i = 0 ; i < actions; i++)
1146 if (threadIndex[i] == 0)
1148 if (defaultAction != -1)
1150 fprintf(stderr,"Too many default actions specified\n");
1151 return packet_error;
1153 defaultAction = i;
1157 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1159 /* go through all the threads and stick their ids in the to be done list. */
1160 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1162 threadIDs[threadCount++] = thd->tid;
1163 /* check to see if we have more threads than I counted on, and tell the user what to do
1164 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1165 if (threadCount == 100)
1167 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1168 break;
1172 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1173 * that remains is to apply the actions to the threads and the default action to any threads
1174 * left */
1175 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1176 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1177 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1178 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1180 /* deal with the threaded stuff first */
1181 for (i = 0; i < actions ; i++)
1183 if (threadIndex[i] != 0)
1185 int j, idLength = 0;
1186 if (i < actions - 1)
1188 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1190 else
1192 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1195 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1196 /* process the action */
1197 switch (gdbctx->in_packet[actionIndex[i] + 1])
1199 case 's': /* step */
1200 be_cpu->single_step(&gdbctx->context, TRUE);
1201 /* fall through*/
1202 case 'c': /* continue */
1203 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1204 break;
1205 case 'S': /* step Sig, */
1206 be_cpu->single_step(&gdbctx->context, TRUE);
1207 /* fall through */
1208 case 'C': /* continue sig */
1209 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1210 /* cannot change signals on the fly */
1211 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1212 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1213 if (sig != gdbctx->last_sig)
1214 return packet_error;
1215 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1216 break;
1218 for (j = 0 ; j < threadCount; j++)
1220 if (threadIDs[j] == threadID)
1222 threadIDs[j] = 0;
1223 break;
1227 } /* for i=0 ; i< actions */
1229 /* now we have manage the default action */
1230 if (defaultAction >= 0)
1232 for (i = 0 ; i< threadCount; i++)
1234 /* check to see if we've already done something to the thread*/
1235 if (threadIDs[i] != 0)
1237 /* if not apply the default action*/
1238 threadID = threadIDs[i];
1239 /* process the action (yes this is almost identical to the one above!) */
1240 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1242 case 's': /* step */
1243 be_cpu->single_step(&gdbctx->context, TRUE);
1244 /* fall through */
1245 case 'c': /* continue */
1246 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1247 break;
1248 case 'S':
1249 be_cpu->single_step(&gdbctx->context, TRUE);
1250 /* fall through */
1251 case 'C': /* continue sig */
1252 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1253 /* cannot change signals on the fly */
1254 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1255 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1256 if (sig != gdbctx->last_sig)
1257 return packet_error;
1258 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1259 break;
1263 } /* if(defaultAction >=0) */
1265 wait_for_debuggee(gdbctx);
1266 be_cpu->single_step(&gdbctx->context, FALSE);
1267 return packet_reply_status(gdbctx);
1270 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1272 unsigned char sig;
1274 /* FIXME: add support for address in packet */
1275 assert(gdbctx->in_packet_len == 2);
1276 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1277 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1278 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1279 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1280 hex_from(&sig, gdbctx->in_packet, 1);
1281 /* cannot change signals on the fly */
1282 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1283 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1284 if (sig != gdbctx->last_sig)
1285 return packet_error;
1286 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1287 wait_for_debuggee(gdbctx);
1288 return packet_reply_status(gdbctx);
1291 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1293 detach_debuggee(gdbctx, FALSE);
1294 return packet_ok | packet_last_f;
1297 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1299 int i;
1300 CONTEXT ctx;
1301 CONTEXT* pctx = &gdbctx->context;
1303 assert(gdbctx->in_trap);
1305 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1307 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1308 return packet_error;
1311 packet_reply_open(gdbctx);
1312 for (i = 0; i < cpu_num_regs; i++)
1314 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1316 packet_reply_close(gdbctx);
1317 return packet_done;
1320 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1322 unsigned i;
1323 CONTEXT ctx;
1324 CONTEXT* pctx = &gdbctx->context;
1326 assert(gdbctx->in_trap);
1327 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1329 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1330 return packet_error;
1332 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1334 for (i = 0; i < cpu_num_regs; i++)
1335 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1336 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1338 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1339 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1340 return packet_error;
1342 return packet_ok;
1345 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1347 detach_debuggee(gdbctx, TRUE);
1348 #if 0
1349 if (!gdbctx->extended)
1350 /* dunno whether GDB cares or not */
1351 #endif
1352 wait(NULL);
1353 exit(0);
1354 /* assume we can't really answer something here */
1355 /* return packet_done; */
1358 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1360 char* end;
1361 unsigned thread;
1363 switch (gdbctx->in_packet[0])
1365 case 'c':
1366 case 'g':
1367 if (gdbctx->in_packet[1] == '-')
1368 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1369 else
1370 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1371 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1373 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1374 fprintf(stderr, "Cannot get threadid %*.*s\n",
1375 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1376 gdbctx->in_packet + 1);
1377 return packet_error;
1379 if (gdbctx->in_packet[0] == 'c')
1380 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1381 else
1382 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1383 return packet_ok;
1384 default:
1385 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1386 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1387 return packet_error;
1391 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1393 char *addr;
1394 unsigned int len, blk_len, nread;
1395 char buffer[32];
1396 SIZE_T r = 0;
1398 assert(gdbctx->in_trap);
1399 /* FIXME:check in_packet_len for reading %p,%x */
1400 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1401 if (len <= 0) return packet_error;
1402 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1403 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1404 for (nread = 0; nread < len; nread += r, addr += r)
1406 blk_len = min(sizeof(buffer), len - nread);
1407 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1408 r == 0)
1410 /* fail at first address, return error */
1411 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1412 /* something has already been read, return partial information */
1413 break;
1415 if (nread == 0) packet_reply_open(gdbctx);
1416 packet_reply_hex_to(gdbctx, buffer, r);
1418 packet_reply_close(gdbctx);
1419 return packet_done;
1422 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1424 char* addr;
1425 unsigned int len, blk_len;
1426 char* ptr;
1427 char buffer[32];
1428 SIZE_T w;
1430 assert(gdbctx->in_trap);
1431 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1432 if (ptr == NULL)
1434 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1435 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1436 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1437 return packet_error;
1439 *ptr++ = '\0';
1441 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1443 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1444 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1445 return packet_error;
1447 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1449 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1450 fprintf(stderr, "Wrong sizes %u <> %u\n",
1451 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1452 return packet_error;
1454 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1455 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1456 while (len > 0)
1458 blk_len = min(sizeof(buffer), len);
1459 hex_from(buffer, ptr, blk_len);
1460 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1461 w != blk_len)
1462 break;
1463 addr += blk_len;
1464 len -= blk_len;
1465 ptr += blk_len;
1467 return packet_ok; /* FIXME: error while writing ? */
1470 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1472 unsigned reg;
1473 CONTEXT ctx;
1474 CONTEXT* pctx = &gdbctx->context;
1476 assert(gdbctx->in_trap);
1477 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1478 if (reg >= cpu_num_regs)
1480 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1481 fprintf(stderr, "Register out of bounds %x\n", reg);
1482 return packet_error;
1484 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1486 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1487 return packet_error;
1489 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1490 fprintf(stderr, "Read register %x => %lx\n", reg, *cpu_register(pctx, reg));
1491 packet_reply_open(gdbctx);
1492 packet_reply_hex_to(gdbctx, cpu_register(pctx, reg), 4);
1493 packet_reply_close(gdbctx);
1494 return packet_done;
1497 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1499 unsigned reg;
1500 char* ptr;
1501 char* end;
1502 CONTEXT ctx;
1503 CONTEXT* pctx = &gdbctx->context;
1505 assert(gdbctx->in_trap);
1507 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1508 *ptr++ = '\0';
1509 reg = strtoul(gdbctx->in_packet, &end, 16);
1510 if (end == NULL || reg > cpu_num_regs)
1512 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1513 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1514 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1515 * it wouldn't matter too much, and it fakes our support for all regs
1517 return (end == NULL) ? packet_error : packet_ok;
1519 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1521 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1522 fprintf(stderr, "Wrong sizes %u <> %u\n",
1523 (int)(ptr + 8 - gdbctx->in_packet), gdbctx->in_packet_len);
1524 return packet_error;
1526 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1528 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1529 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr );
1532 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1534 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1535 return packet_error;
1538 hex_from(cpu_register(pctx, reg), ptr, 4);
1539 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1541 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1542 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1543 return packet_error;
1546 return packet_ok;
1549 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1551 char buffer[128];
1552 char clsName[128];
1553 char wndName[128];
1554 HWND child;
1556 do {
1557 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1558 strcpy(clsName, "-- Unknown --");
1559 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1560 strcpy(wndName, "-- Empty --");
1562 packet_reply_open(gdbctx);
1563 packet_reply_catc(gdbctx, 'O');
1564 snprintf(buffer, sizeof(buffer),
1565 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1566 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1567 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1568 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1569 wndName);
1570 packet_reply_hex_to_str(gdbctx, buffer);
1571 packet_reply_close(gdbctx);
1573 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1574 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1575 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1578 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1580 char buffer[128];
1582 /* we do the output in several 'O' packets, with the last one being just OK for
1583 * marking the end of the output */
1584 packet_reply_open(gdbctx);
1585 packet_reply_catc(gdbctx, 'O');
1586 snprintf(buffer, sizeof(buffer),
1587 "%-16.16s %-17.17s %-8.8s %s\n",
1588 "hwnd", "Class Name", " Style", " WndProc Text");
1589 packet_reply_hex_to_str(gdbctx, buffer);
1590 packet_reply_close(gdbctx);
1592 /* FIXME: could also add a pmt to this command in str... */
1593 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1594 packet_reply(gdbctx, "OK", 2);
1597 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1599 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1600 char buffer[128];
1601 char deco;
1602 PROCESSENTRY32 entry;
1603 BOOL ok;
1605 if (snap == INVALID_HANDLE_VALUE)
1606 return;
1608 entry.dwSize = sizeof(entry);
1609 ok = Process32First(snap, &entry);
1611 /* we do the output in several 'O' packets, with the last one being just OK for
1612 * marking the end of the output */
1614 packet_reply_open(gdbctx);
1615 packet_reply_catc(gdbctx, 'O');
1616 snprintf(buffer, sizeof(buffer),
1617 " %-8.8s %-8.8s %-8.8s %s\n",
1618 "pid", "threads", "parent", "executable");
1619 packet_reply_hex_to_str(gdbctx, buffer);
1620 packet_reply_close(gdbctx);
1622 while (ok)
1624 deco = ' ';
1625 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1626 packet_reply_open(gdbctx);
1627 packet_reply_catc(gdbctx, 'O');
1628 snprintf(buffer, sizeof(buffer),
1629 "%c%08x %-8d %08x '%s'\n",
1630 deco, entry.th32ProcessID, entry.cntThreads,
1631 entry.th32ParentProcessID, entry.szExeFile);
1632 packet_reply_hex_to_str(gdbctx, buffer);
1633 packet_reply_close(gdbctx);
1634 ok = Process32Next(snap, &entry);
1636 CloseHandle(snap);
1637 packet_reply(gdbctx, "OK", 2);
1640 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1642 MEMORY_BASIC_INFORMATION mbi;
1643 char* addr = 0;
1644 const char* state;
1645 const char* type;
1646 char prot[3+1];
1647 char buffer[128];
1649 /* we do the output in several 'O' packets, with the last one being just OK for
1650 * marking the end of the output */
1651 packet_reply_open(gdbctx);
1652 packet_reply_catc(gdbctx, 'O');
1653 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1654 packet_reply_close(gdbctx);
1656 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1658 switch (mbi.State)
1660 case MEM_COMMIT: state = "commit "; break;
1661 case MEM_FREE: state = "free "; break;
1662 case MEM_RESERVE: state = "reserve"; break;
1663 default: state = "??? "; break;
1665 if (mbi.State != MEM_FREE)
1667 switch (mbi.Type)
1669 case MEM_IMAGE: type = "image "; break;
1670 case MEM_MAPPED: type = "mapped "; break;
1671 case MEM_PRIVATE: type = "private"; break;
1672 case 0: type = " "; break;
1673 default: type = "??? "; break;
1675 memset(prot, ' ' , sizeof(prot)-1);
1676 prot[sizeof(prot)-1] = '\0';
1677 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1678 prot[0] = 'R';
1679 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1680 prot[1] = 'W';
1681 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1682 prot[1] = 'C';
1683 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1684 prot[2] = 'X';
1686 else
1688 type = "";
1689 prot[0] = '\0';
1691 packet_reply_open(gdbctx);
1692 snprintf(buffer, sizeof(buffer), "%08lx %08lx %s %s %s\n",
1693 (DWORD_PTR)addr, mbi.RegionSize, state, type, prot);
1694 packet_reply_catc(gdbctx, 'O');
1695 packet_reply_hex_to_str(gdbctx, buffer);
1696 packet_reply_close(gdbctx);
1698 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1699 break;
1700 addr += mbi.RegionSize;
1702 packet_reply(gdbctx, "OK", 2);
1705 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1706 int len, const char* str)
1708 char buffer[128];
1710 if (len == 0)
1712 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1714 else if (len >= 2 && str[0] == '=')
1716 unsigned val = atoi(&str[1]);
1717 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1718 gdbctx->trace = val;
1720 else
1722 /* FIXME: ugly but can use error packet here */
1723 packet_reply_cat(gdbctx, "E00");
1724 return;
1726 packet_reply_open(gdbctx);
1727 packet_reply_hex_to_str(gdbctx, buffer);
1728 packet_reply_close(gdbctx);
1731 struct query_detail
1733 int with_arg;
1734 const char* name;
1735 size_t len;
1736 void (*handler)(struct gdb_context*, int, const char*);
1737 } query_details[] =
1739 {0, "wnd", 3, packet_query_monitor_wnd},
1740 {0, "window", 6, packet_query_monitor_wnd},
1741 {0, "proc", 4, packet_query_monitor_process},
1742 {0, "process", 7, packet_query_monitor_process},
1743 {0, "mem", 3, packet_query_monitor_mem},
1744 {1, "trace", 5, packet_query_monitor_trace},
1745 {0, NULL, 0, NULL},
1748 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1749 const char* hxcmd, size_t len)
1751 char buffer[128];
1752 struct query_detail* qd;
1754 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1755 len /= 2;
1756 hex_from(buffer, hxcmd, len);
1758 for (qd = &query_details[0]; qd->name != NULL; qd++)
1760 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1761 if (!qd->with_arg && len != qd->len) continue;
1763 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1764 return packet_done;
1766 return packet_reply_error(gdbctx, EINVAL);
1769 static enum packet_return packet_query(struct gdb_context* gdbctx)
1771 switch (gdbctx->in_packet[0])
1773 case 'f':
1774 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1776 struct dbg_thread* thd;
1778 packet_reply_open(gdbctx);
1779 packet_reply_add(gdbctx, "m", 1);
1780 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1782 packet_reply_val(gdbctx, thd->tid, 4);
1783 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1784 packet_reply_add(gdbctx, ",", 1);
1786 packet_reply_close(gdbctx);
1787 return packet_done;
1789 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1791 char result[128];
1793 packet_reply_open(gdbctx);
1794 packet_reply_catc(gdbctx, 'O');
1795 get_process_info(gdbctx, result, sizeof(result));
1796 packet_reply_hex_to_str(gdbctx, result);
1797 packet_reply_close(gdbctx);
1798 return packet_done;
1800 break;
1801 case 's':
1802 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1804 packet_reply(gdbctx, "l", 1);
1805 return packet_done;
1807 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1809 packet_reply(gdbctx, "l", 1);
1810 return packet_done;
1812 break;
1813 case 'C':
1814 if (gdbctx->in_packet_len == 1)
1816 struct dbg_thread* thd;
1817 /* FIXME: doc says 16 bit val ??? */
1818 /* grab first created thread, aka last in list */
1819 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1820 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1821 packet_reply_open(gdbctx);
1822 packet_reply_add(gdbctx, "QC", 2);
1823 packet_reply_val(gdbctx, thd->tid, 4);
1824 packet_reply_close(gdbctx);
1825 return packet_done;
1827 break;
1828 case 'O':
1829 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1831 char buf[64];
1833 snprintf(buf, sizeof(buf),
1834 "Text=%08lx;Data=%08lx;Bss=%08lx",
1835 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1836 gdbctx->wine_segs[2]);
1837 return packet_reply(gdbctx, buf, -1);
1839 break;
1840 case 'R':
1841 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1843 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1844 gdbctx->in_packet_len - 5);
1846 break;
1847 case 'S':
1848 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1849 return packet_ok;
1850 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1852 /* no features supported */
1853 packet_reply_open(gdbctx);
1854 packet_reply_close(gdbctx);
1855 return packet_done;
1857 break;
1858 case 'T':
1859 if (gdbctx->in_packet_len > 15 &&
1860 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1861 gdbctx->in_packet[15] == ',')
1863 unsigned tid;
1864 char* end;
1865 char result[128];
1867 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1868 if (end == NULL) break;
1869 get_thread_info(gdbctx, tid, result, sizeof(result));
1870 packet_reply_open(gdbctx);
1871 packet_reply_hex_to_str(gdbctx, result);
1872 packet_reply_close(gdbctx);
1873 return packet_done;
1875 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
1877 /* Tracepoints not supported */
1878 packet_reply_open(gdbctx);
1879 packet_reply_close(gdbctx);
1880 return packet_done;
1882 break;
1884 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1885 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1886 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1887 return packet_error;
1890 static enum packet_return packet_step(struct gdb_context* gdbctx)
1892 /* FIXME: add support for address in packet */
1893 assert(gdbctx->in_packet_len == 0);
1894 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1895 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1896 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1897 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1898 be_cpu->single_step(&gdbctx->context, TRUE);
1899 resume_debuggee(gdbctx, DBG_CONTINUE);
1900 wait_for_debuggee(gdbctx);
1901 be_cpu->single_step(&gdbctx->context, FALSE);
1902 return packet_reply_status(gdbctx);
1905 #if 0
1906 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1908 unsigned char sig;
1910 /* FIXME: add support for address in packet */
1911 assert(gdbctx->in_packet_len == 2);
1912 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1913 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1914 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1915 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1916 hex_from(&sig, gdbctx->in_packet, 1);
1917 /* cannot change signals on the fly */
1918 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1919 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1920 if (sig != gdbctx->last_sig)
1921 return packet_error;
1922 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1923 wait_for_debuggee(gdbctx);
1924 return packet_reply_status(gdbctx);
1926 #endif
1928 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1930 char* end;
1931 unsigned tid;
1933 tid = strtol(gdbctx->in_packet, &end, 16);
1934 if (tid == -1 || tid == 0)
1935 return packet_reply_error(gdbctx, EINVAL);
1936 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1937 return packet_ok;
1938 return packet_reply_error(gdbctx, ESRCH);
1941 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1943 void* addr;
1944 unsigned len;
1945 struct gdb_ctx_Xpoint* xpt;
1946 enum be_xpoint_type t;
1948 /* FIXME: check packet_len */
1949 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1950 gdbctx->in_packet[1] != ',' ||
1951 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1952 return packet_error;
1953 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1954 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1955 addr, len, gdbctx->in_packet[0]);
1956 switch (gdbctx->in_packet[0])
1958 case '0': t = be_xpoint_break; len = 0; break;
1959 case '1': t = be_xpoint_watch_exec; break;
1960 case '2': t = be_xpoint_watch_read; break;
1961 case '3': t = be_xpoint_watch_write; break;
1962 default: return packet_error;
1964 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1966 if (xpt->addr == addr && xpt->type == t)
1968 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1969 gdbctx->process->process_io, &gdbctx->context,
1970 t, xpt->addr, xpt->val, len))
1972 xpt->type = -1;
1973 return packet_ok;
1975 break;
1978 return packet_error;
1981 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1983 void* addr;
1984 unsigned len;
1985 struct gdb_ctx_Xpoint* xpt;
1986 enum be_xpoint_type t;
1988 /* FIXME: check packet_len */
1989 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1990 gdbctx->in_packet[1] != ',' ||
1991 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1992 return packet_error;
1993 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1994 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1995 addr, len, gdbctx->in_packet[0]);
1996 switch (gdbctx->in_packet[0])
1998 case '0': t = be_xpoint_break; len = 0; break;
1999 case '1': t = be_xpoint_watch_exec; break;
2000 case '2': t = be_xpoint_watch_read; break;
2001 case '3': t = be_xpoint_watch_write; break;
2002 default: return packet_error;
2004 /* because of packet command handling, this should be made idempotent */
2005 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2007 if (xpt->addr == addr && xpt->type == t)
2008 return packet_ok; /* nothing to do */
2010 /* really set the Xpoint */
2011 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2013 if (xpt->type == -1)
2015 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2016 gdbctx->process->process_io, &gdbctx->context,
2017 t, addr, &xpt->val, len))
2019 xpt->addr = addr;
2020 xpt->type = t;
2021 return packet_ok;
2023 fprintf(stderr, "cannot set xpoint\n");
2024 break;
2027 /* no more entries... eech */
2028 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2029 return packet_error;
2032 /* =============================================== *
2033 * P A C K E T I N F R A S T R U C T U R E *
2034 * =============================================== *
2037 struct packet_entry
2039 char key;
2040 enum packet_return (*handler)(struct gdb_context* gdbctx);
2043 static struct packet_entry packet_entries[] =
2045 /*{'!', packet_extended}, */
2046 {'?', packet_last_signal},
2047 {'c', packet_continue},
2048 {'C', packet_continue_signal},
2049 {'D', packet_detach},
2050 {'g', packet_read_registers},
2051 {'G', packet_write_registers},
2052 {'k', packet_kill},
2053 {'H', packet_thread},
2054 {'m', packet_read_memory},
2055 {'M', packet_write_memory},
2056 {'p', packet_read_register},
2057 {'P', packet_write_register},
2058 {'q', packet_query},
2059 /* {'Q', packet_set}, */
2060 /* {'R', packet,restart}, only in extended mode ! */
2061 {'s', packet_step},
2062 /*{'S', packet_step_signal}, hard(er) to implement */
2063 {'T', packet_thread_alive},
2064 {'v', packet_verbose},
2065 {'z', packet_remove_breakpoint},
2066 {'Z', packet_set_breakpoint},
2069 static BOOL extract_packets(struct gdb_context* gdbctx)
2071 char* end;
2072 int plen;
2073 unsigned char in_cksum, loc_cksum;
2074 char* ptr;
2075 enum packet_return ret = packet_error;
2076 int num_packet = 0;
2078 while ((ret & packet_last_f) == 0)
2080 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2081 fprintf(stderr, "In-buf: %*.*s\n",
2082 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2083 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2084 if (ptr == NULL) return FALSE;
2085 if (ptr != gdbctx->in_buf)
2087 int glen = ptr - gdbctx->in_buf; /* garbage len */
2088 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2089 fprintf(stderr, "Removing garbage: %*.*s\n",
2090 glen, glen, gdbctx->in_buf);
2091 gdbctx->in_len -= glen;
2092 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2094 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2095 if (end == NULL) return FALSE;
2096 /* no checksum yet */
2097 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2098 plen = end - gdbctx->in_buf - 1;
2099 hex_from(&in_cksum, end + 1, 1);
2100 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2101 if (loc_cksum == in_cksum)
2103 if (num_packet == 0) {
2104 int i;
2106 ret = packet_error;
2108 write(gdbctx->sock, "+", 1);
2109 assert(plen);
2111 /* FIXME: should use bsearch if packet_entries was sorted */
2112 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2114 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2116 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2118 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2119 fprintf(stderr, "Unknown packet request %*.*s\n",
2120 plen, plen, &gdbctx->in_buf[1]);
2122 else
2124 gdbctx->in_packet = gdbctx->in_buf + 2;
2125 gdbctx->in_packet_len = plen - 1;
2126 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2127 fprintf(stderr, "Packet: %c%*.*s\n",
2128 gdbctx->in_buf[1],
2129 gdbctx->in_packet_len, gdbctx->in_packet_len,
2130 gdbctx->in_packet);
2131 ret = (packet_entries[i].handler)(gdbctx);
2133 switch (ret & ~packet_last_f)
2135 case packet_error: packet_reply(gdbctx, "", 0); break;
2136 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2137 case packet_done: break;
2139 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2140 fprintf(stderr, "Reply-full: %*.*s\n",
2141 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2142 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2143 assert(i == gdbctx->out_len);
2144 /* if this fails, we'll have to use POLLOUT...
2146 gdbctx->out_len = 0;
2147 num_packet++;
2149 else
2151 /* FIXME: if we have in our input buffer more than one packet,
2152 * it's very likely that we took too long to answer to a given packet
2153 * and gdb is sending us again the same packet
2154 * We simply drop the second packet. This will lower the risk of error,
2155 * but there's still some race conditions here
2156 * A better fix (yet not perfect) would be to have two threads:
2157 * - one managing the packets for gdb
2158 * - the second one managing the commands...
2159 * This would allow us also the reply with the '+' character (Ack of
2160 * the command) way sooner than what we do now
2162 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2163 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2166 else
2168 write(gdbctx->sock, "+", 1);
2169 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2170 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2172 gdbctx->in_len -= plen + 4;
2173 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2175 return TRUE;
2178 static int fetch_data(struct gdb_context* gdbctx)
2180 int len, in_len = gdbctx->in_len;
2182 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2183 for (;;)
2185 #define STEP 128
2186 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2187 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2188 #undef STEP
2189 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2190 fprintf(stderr, "%d %d %*.*s\n",
2191 gdbctx->in_len, gdbctx->in_buf_alloc,
2192 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2193 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2194 if (len <= 0) break;
2195 gdbctx->in_len += len;
2196 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2197 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2199 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2200 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2201 return gdbctx->in_len - in_len;
2204 #define FLAG_NO_START 1
2205 #define FLAG_WITH_XTERM 2
2207 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2209 char buf[MAX_PATH];
2210 int fd;
2211 const char* gdb_path;
2212 FILE* f;
2214 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2215 strcpy(buf,"/tmp/winegdb.XXXXXX");
2216 fd = mkstemps(buf, 0);
2217 if (fd == -1) return FALSE;
2218 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2219 fprintf(f, "file %s\n", wine_path);
2220 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2221 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2222 fprintf(f, "set prompt Wine-gdb>\\ \n");
2223 /* gdb 5.1 seems to require it, won't hurt anyway */
2224 fprintf(f, "sharedlibrary\n");
2225 /* This is needed (but not a decent & final fix)
2226 * Without this, gdb would skip our inter-DLL relay code (because
2227 * we don't have any line number information for the relay code)
2228 * With this, we will stop on first instruction of the stub, and
2229 * reusing step, will get us through the relay stub at the actual
2230 * function we're looking at.
2232 fprintf(f, "set step-mode on\n");
2233 /* tell gdb to delete this file when done handling it... */
2234 fprintf(f, "shell rm -f \"%s\"\n", buf);
2235 fclose(f);
2236 if (flags & FLAG_WITH_XTERM)
2237 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2238 else
2239 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2240 assert(0); /* never reached */
2241 return TRUE;
2244 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2246 int sock;
2247 struct sockaddr_in s_addrs;
2248 unsigned int s_len = sizeof(s_addrs);
2249 struct pollfd pollfd;
2250 IMAGEHLP_MODULE64 imh_mod;
2252 /* step 1: create socket for gdb connection request */
2253 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2255 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2256 fprintf(stderr, "Can't create socket");
2257 return FALSE;
2260 if (listen(sock, 1) == -1 ||
2261 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2262 return FALSE;
2264 /* step 2: do the process internal creation */
2265 handle_debug_event(gdbctx, de);
2267 /* step3: get the wine loader name */
2268 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2270 /* step 4: fire up gdb (if requested) */
2271 if (flags & FLAG_NO_START)
2272 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2273 else
2274 switch (fork())
2276 case -1: /* error in parent... */
2277 fprintf(stderr, "Cannot create gdb\n");
2278 return FALSE;
2279 default: /* in parent... success */
2280 signal(SIGINT, SIG_IGN);
2281 break;
2282 case 0: /* in child... and alive */
2283 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2284 /* if we're here, exec failed, so report failure */
2285 return FALSE;
2288 /* step 5: wait for gdb to connect actually */
2289 pollfd.fd = sock;
2290 pollfd.events = POLLIN;
2291 pollfd.revents = 0;
2293 switch (poll(&pollfd, 1, -1))
2295 case 1:
2296 if (pollfd.revents & POLLIN)
2298 int dummy = 1;
2299 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2300 if (gdbctx->sock == -1)
2301 break;
2302 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2303 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2304 /* don't keep our small packets too long: send them ASAP back to GDB
2305 * without this, GDB really crawls
2307 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2309 break;
2310 case 0:
2311 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2312 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2313 return FALSE;
2314 case -1:
2315 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2316 fprintf(stderr, "Poll for cnx failed (error)\n");
2317 return FALSE;
2318 default:
2319 assert(0);
2322 close(sock);
2323 return TRUE;
2326 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2328 DEBUG_EVENT de;
2329 int i;
2331 gdbctx->sock = -1;
2332 gdbctx->in_buf = NULL;
2333 gdbctx->in_buf_alloc = 0;
2334 gdbctx->in_len = 0;
2335 gdbctx->out_buf = NULL;
2336 gdbctx->out_buf_alloc = 0;
2337 gdbctx->out_len = 0;
2338 gdbctx->out_curr_packet = -1;
2340 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2341 gdbctx->last_sig = 0;
2342 gdbctx->in_trap = FALSE;
2343 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2344 gdbctx->process = NULL;
2345 for (i = 0; i < NUM_XPOINT; i++)
2346 gdbctx->Xpoints[i].type = -1;
2347 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2348 gdbctx->wine_segs[i] = 0;
2350 /* wait for first trap */
2351 while (WaitForDebugEvent(&de, INFINITE))
2353 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2355 /* this should be the first event we get,
2356 * and the only one of this type */
2357 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2358 /* gdbctx->dwProcessId = pid; */
2359 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2360 assert(!gdbctx->in_trap);
2362 else
2364 handle_debug_event(gdbctx, &de);
2365 if (gdbctx->in_trap) break;
2367 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2369 return TRUE;
2372 static int gdb_remote(unsigned flags)
2374 struct pollfd pollfd;
2375 struct gdb_context gdbctx;
2376 BOOL doLoop;
2378 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2380 pollfd.fd = gdbctx.sock;
2381 pollfd.events = POLLIN;
2382 pollfd.revents = 0;
2384 switch (poll(&pollfd, 1, -1))
2386 case 1:
2387 /* got something */
2388 if (pollfd.revents & (POLLHUP | POLLERR))
2390 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2391 fprintf(stderr, "Gdb hung up\n");
2392 /* kill also debuggee process - questionnable - */
2393 detach_debuggee(&gdbctx, TRUE);
2394 doLoop = FALSE;
2395 break;
2397 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2399 if (extract_packets(&gdbctx)) doLoop = FALSE;
2401 break;
2402 case 0:
2403 /* timeout, should never happen (infinite timeout) */
2404 break;
2405 case -1:
2406 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2407 fprintf(stderr, "Poll failed\n");
2408 doLoop = FALSE;
2409 break;
2412 wait(NULL);
2413 return 0;
2415 #endif
2417 int gdb_main(int argc, char* argv[])
2419 #ifdef HAVE_POLL
2420 unsigned gdb_flags = 0;
2422 argc--; argv++;
2423 while (argc > 0 && argv[0][0] == '-')
2425 if (strcmp(argv[0], "--no-start") == 0)
2427 gdb_flags |= FLAG_NO_START;
2428 argc--; argv++;
2429 continue;
2431 if (strcmp(argv[0], "--with-xterm") == 0)
2433 gdb_flags |= FLAG_WITH_XTERM;
2434 argc--; argv++;
2435 continue;
2437 return -1;
2439 if (dbg_active_attach(argc, argv) == start_ok ||
2440 dbg_active_launch(argc, argv) == start_ok)
2441 return gdb_remote(gdb_flags);
2442 #else
2443 fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2444 #endif
2445 return -1;