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