winex11: Free visual info stored with the context.
[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%08x\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, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
496                     de->dwProcessId, de->dwThreadId,
497                     buffer, de->u.CreateProcessInfo.lpImageName,
498                     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, "%04x:%04x: create thread I @%p\n",
508                     de->dwProcessId, de->dwThreadId,
509                     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, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
525                     de->dwProcessId, de->dwThreadId,
526                     buffer, 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, "%08x:%08x: unload DLL @%p\n",
536                     de->dwProcessId, de->dwThreadId, 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, "%08x:%08x: exception code=0x%08x\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, "%08x:%08x: create thread D @%p\n",
557                     de->dwProcessId, de->dwThreadId, 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, "%08x:%08x: exit thread (%u)\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, "%08x:%08x: exit process (%u)\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, "%08x:%08x: 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, "%08x:%08x: rip error=%u type=%u\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, "%08x:%08x: unknown event (%u)\n",
608                     de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
609     }
610 }
611
612 static void resume_debuggee(struct gdb_context* gdbctx, DWORD 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 %04x\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 %04x (%x)\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, DWORD 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 %04x\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 %04x (%x)\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     DWORD 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 (%u)", 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     DWORD               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 (%u)", status - 1);
783             }
784             ResumeThread(thd->handle);
785         }
786         else
787             snprintf(buffer, len, "Terminated (exit code = %u)", 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 %04x, while last thread is %04x\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 %04x, while last thread is %04x\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 %04x, while last thread is %04x\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 %04x\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 %04x\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%04lx%*s%-17.17s %08x %08x %.14s\n",
1456                 indent, "", (ULONG_PTR)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%08x %-8d %08x '%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), "%08lx %08lx %s %s %s\n",
1582                  (DWORD_PTR)addr, mbi.RegionSize, state, type, prot);
1583         packet_reply_catc(gdbctx, 'O');
1584         packet_reply_hex_to_str(gdbctx, buffer);
1585         packet_reply_close(gdbctx);
1586
1587         if (addr + mbi.RegionSize < addr) /* wrap around ? */
1588             break;
1589         addr += mbi.RegionSize;
1590     }
1591     packet_reply(gdbctx, "OK", 2);
1592 }
1593
1594 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1595                                        int len, const char* str)
1596 {
1597     char        buffer[128];
1598
1599     if (len == 0)
1600     {
1601         snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1602     }
1603     else if (len >= 2 && str[0] == '=')
1604     {
1605         unsigned val = atoi(&str[1]);
1606         snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1607         gdbctx->trace = val;
1608     }
1609     else
1610     {
1611         /* FIXME: ugly but can use error packet here */
1612         packet_reply_cat(gdbctx, "E00");
1613         return;
1614     }
1615     packet_reply_open(gdbctx);
1616     packet_reply_hex_to_str(gdbctx, buffer);
1617     packet_reply_close(gdbctx);
1618 }
1619
1620 struct query_detail
1621 {
1622     int         with_arg;
1623     const char* name;
1624     size_t      len;
1625     void        (*handler)(struct gdb_context*, int, const char*);
1626 } query_details[] =
1627 {
1628     {0, "wnd",     3, packet_query_monitor_wnd},
1629     {0, "window",  6, packet_query_monitor_wnd},
1630     {0, "proc",    4, packet_query_monitor_process},
1631     {0, "process", 7, packet_query_monitor_process},
1632     {0, "mem",     3, packet_query_monitor_mem},
1633     {1, "trace",   5, packet_query_monitor_trace},
1634     {0, NULL,      0, NULL},
1635 };
1636
1637 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1638                                                       const char* hxcmd, size_t len)
1639 {
1640     char                        buffer[128];
1641     struct query_detail*        qd;
1642
1643     assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1644     len /= 2;
1645     hex_from(buffer, hxcmd, len);
1646
1647     for (qd = &query_details[0]; qd->name != NULL; qd++)
1648     {
1649         if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1650         if (!qd->with_arg && len != qd->len) continue;
1651
1652         (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1653         return packet_done;
1654     }
1655     return packet_reply_error(gdbctx, EINVAL);
1656 }
1657
1658 static enum packet_return packet_query(struct gdb_context* gdbctx)
1659 {
1660     switch (gdbctx->in_packet[0])
1661     {
1662     case 'f':
1663         if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1664         {
1665             struct dbg_thread*  thd;
1666
1667             packet_reply_open(gdbctx);
1668             packet_reply_add(gdbctx, "m", 1);
1669             for (thd = gdbctx->process->threads; thd; thd = thd->next)
1670             {
1671                 packet_reply_val(gdbctx, thd->tid, 4);
1672                 if (thd->next != NULL)
1673                     packet_reply_add(gdbctx, ",", 1);
1674             }
1675             packet_reply_close(gdbctx);
1676             return packet_done;
1677         }
1678         else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1679         {
1680             char        result[128];
1681
1682             packet_reply_open(gdbctx);
1683             packet_reply_catc(gdbctx, 'O');
1684             get_process_info(gdbctx, result, sizeof(result));
1685             packet_reply_hex_to_str(gdbctx, result);
1686             packet_reply_close(gdbctx);
1687             return packet_done;
1688         }
1689         break;
1690     case 's':
1691         if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1692         {
1693             packet_reply(gdbctx, "l", 1);
1694             return packet_done;
1695         }
1696         else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1697         {
1698             packet_reply(gdbctx, "l", 1);
1699             return packet_done;
1700         }
1701         break;
1702     case 'C':
1703         if (gdbctx->in_packet_len == 1)
1704         {
1705             struct dbg_thread*  thd;
1706             /* FIXME: doc says 16 bit val ??? */
1707             /* grab first created thread, aka last in list */
1708             assert(gdbctx->process && gdbctx->process->threads);
1709             for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1710             packet_reply_open(gdbctx);
1711             packet_reply_add(gdbctx, "QC", 2);
1712             packet_reply_val(gdbctx, thd->tid, 4);
1713             packet_reply_close(gdbctx);
1714             return packet_done;
1715         }
1716         break;
1717     case 'O':
1718         if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1719         {
1720             char    buf[64];
1721
1722             if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1723                 gdbctx->wine_segs[2] == 0)
1724                 return packet_error;
1725             snprintf(buf, sizeof(buf), 
1726                      "Text=%08lx;Data=%08lx;Bss=%08lx",
1727                      gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1728                      gdbctx->wine_segs[2]);
1729             return packet_reply(gdbctx, buf, -1);
1730         }
1731         break;
1732     case 'R':
1733         if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1734         {
1735             return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1736                                                gdbctx->in_packet_len - 5);
1737         }
1738         break;
1739     case 'S':
1740         if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1741             return packet_ok;
1742         break;
1743     case 'T':
1744         if (gdbctx->in_packet_len > 15 &&
1745             strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1746             gdbctx->in_packet[15] == ',')
1747         {
1748             unsigned    tid;
1749             char*       end;
1750             char        result[128];
1751
1752             tid = strtol(gdbctx->in_packet + 16, &end, 16);
1753             if (end == NULL) break;
1754             get_thread_info(gdbctx, tid, result, sizeof(result));
1755             packet_reply_open(gdbctx);
1756             packet_reply_hex_to_str(gdbctx, result);
1757             packet_reply_close(gdbctx);
1758             return packet_done;
1759         }
1760         break;
1761     }
1762     if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1763         fprintf(stderr, "Unknown or malformed query %*.*s\n",
1764                 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1765     return packet_error;
1766 }
1767
1768 static enum packet_return packet_step(struct gdb_context* gdbctx)
1769 {
1770     /* FIXME: add support for address in packet */
1771     assert(gdbctx->in_packet_len == 0);
1772     if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1773         if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1774             fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1775                     gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1776     be_cpu->single_step(&gdbctx->context, TRUE);
1777     resume_debuggee(gdbctx, DBG_CONTINUE);
1778     wait_for_debuggee(gdbctx);
1779     be_cpu->single_step(&gdbctx->context, FALSE);
1780     return packet_reply_status(gdbctx);
1781 }
1782
1783 #if 0
1784 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1785 {
1786     unsigned char sig;
1787
1788     /* FIXME: add support for address in packet */
1789     assert(gdbctx->in_packet_len == 2);
1790     if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1791         if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1792             fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1793                     gdbctx->exec_thread, DEBUG_CurrThread->tid);
1794     hex_from(&sig, gdbctx->in_packet, 1);
1795     /* cannot change signals on the fly */
1796     if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1797         fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1798     if (sig != gdbctx->last_sig)
1799         return packet_error;
1800     resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1801     wait_for_debuggee(gdbctx);
1802     return packet_reply_status(gdbctx);
1803 }
1804 #endif
1805
1806 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1807 {
1808     char*       end;
1809     unsigned    tid;
1810
1811     tid = strtol(gdbctx->in_packet, &end, 16);
1812     if (tid == -1 || tid == 0)
1813         return packet_reply_error(gdbctx, EINVAL);
1814     if (dbg_get_thread(gdbctx->process, tid) != NULL)
1815         return packet_ok;
1816     return packet_reply_error(gdbctx, ESRCH);
1817 }
1818
1819 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1820 {
1821     void*                       addr;
1822     unsigned                    len;
1823     struct gdb_ctx_Xpoint*      xpt;
1824     enum be_xpoint_type         t;
1825
1826     /* FIXME: check packet_len */
1827     if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1828         gdbctx->in_packet[1] != ',' ||
1829         sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1830         return packet_error;
1831     if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1832         fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1833                 addr, len, gdbctx->in_packet[0]);
1834     switch (gdbctx->in_packet[0])
1835     {
1836     case '0': t = be_xpoint_break; len = 0; break;
1837     case '1': t = be_xpoint_watch_exec; break;
1838     case '2': t = be_xpoint_watch_read; break;
1839     case '3': t = be_xpoint_watch_write; break;
1840     default: return packet_error;
1841     }
1842     for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1843     {
1844         if (xpt->addr == addr && xpt->type == t)
1845         {
1846             if (be_cpu->remove_Xpoint(gdbctx->process->handle,
1847                                       gdbctx->process->process_io, &gdbctx->context,
1848                                       t, xpt->addr, xpt->val, len))
1849             {
1850                 xpt->type = -1;
1851                 return packet_ok;
1852             }
1853             break;
1854         }
1855     }
1856     return packet_error;
1857 }
1858
1859 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1860 {
1861     void*                       addr;
1862     unsigned                    len;
1863     struct gdb_ctx_Xpoint*      xpt;
1864     enum be_xpoint_type         t;
1865
1866     /* FIXME: check packet_len */
1867     if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1868         gdbctx->in_packet[1] != ',' ||
1869         sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1870         return packet_error;
1871     if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1872         fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1873                 addr, len, gdbctx->in_packet[0]);
1874     switch (gdbctx->in_packet[0])
1875     {
1876     case '0': t = be_xpoint_break; len = 0; break;
1877     case '1': t = be_xpoint_watch_exec; break;
1878     case '2': t = be_xpoint_watch_read; break;
1879     case '3': t = be_xpoint_watch_write; break;
1880     default: return packet_error;
1881     }
1882     /* because of packet command handling, this should be made idempotent */
1883     for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1884     {
1885         if (xpt->addr == addr && xpt->type == t)
1886             return packet_ok; /* nothing to do */
1887     }
1888     /* really set the Xpoint */
1889     for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1890     {
1891         if (xpt->type == -1)
1892         {
1893             if (be_cpu->insert_Xpoint(gdbctx->process->handle,
1894                                       gdbctx->process->process_io, &gdbctx->context, 
1895                                       t, addr, &xpt->val, len))
1896             {
1897                 xpt->addr = addr;
1898                 xpt->type = t;
1899                 return packet_ok;
1900             }
1901             fprintf(stderr, "cannot set xpoint\n");
1902             break;
1903         }
1904     }
1905     /* no more entries... eech */
1906     fprintf(stderr, "Running out of spots for {break|watch}points\n");
1907     return packet_error;
1908 }
1909
1910 /* =============================================== *
1911  *    P A C K E T  I N F R A S T R U C T U R E     *
1912  * =============================================== *
1913  */
1914
1915 struct packet_entry
1916 {
1917     char                key;
1918     enum packet_return  (*handler)(struct gdb_context* gdbctx);
1919 };
1920
1921 static struct packet_entry packet_entries[] =
1922 {
1923         /*{'!', packet_extended}, */
1924         {'?', packet_last_signal},
1925         {'c', packet_continue},
1926         {'C', packet_continue_signal},
1927         {'D', packet_detach},
1928         {'g', packet_read_registers},
1929         {'G', packet_write_registers},
1930         {'k', packet_kill},
1931         {'H', packet_thread},
1932         {'m', packet_read_memory},
1933         {'M', packet_write_memory},
1934         /* {'p', packet_read_register}, doesn't seem needed */
1935         {'P', packet_write_register},
1936         {'q', packet_query},
1937         /* {'Q', packet_set}, */
1938         /* {'R', packet,restart}, only in extended mode ! */
1939         {'s', packet_step},        
1940         /*{'S', packet_step_signal}, hard(er) to implement */
1941         {'T', packet_thread_alive},
1942         {'v', packet_verbose},
1943         {'z', packet_remove_breakpoint},
1944         {'Z', packet_set_breakpoint},
1945 };
1946
1947 static BOOL extract_packets(struct gdb_context* gdbctx)
1948 {
1949     char*               end;
1950     int                 plen;
1951     unsigned char       in_cksum, loc_cksum;
1952     char*               ptr;
1953     enum packet_return  ret = packet_error;
1954     int                 num_packet = 0;
1955
1956     while ((ret & packet_last_f) == 0)
1957     {
1958         if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1959             fprintf(stderr, "In-buf: %*.*s\n",
1960                     gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1961         ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1962         if (ptr == NULL) return FALSE;
1963         if (ptr != gdbctx->in_buf)
1964         {
1965             int glen = ptr - gdbctx->in_buf; /* garbage len */
1966             if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1967                 fprintf(stderr, "Removing garbage: %*.*s\n",
1968                         glen, glen, gdbctx->in_buf);
1969             gdbctx->in_len -= glen;
1970             memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1971         }
1972         end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1973         if (end == NULL) return FALSE;
1974         /* no checksum yet */
1975         if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1976         plen = end - gdbctx->in_buf - 1;
1977         hex_from(&in_cksum, end + 1, 1);
1978         loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1979         if (loc_cksum == in_cksum)
1980         {
1981             if (num_packet == 0) {
1982                 int                 i;
1983                 
1984                 ret = packet_error;
1985                 
1986                 write(gdbctx->sock, "+", 1);
1987                 assert(plen);
1988                 
1989                 /* FIXME: should use bsearch if packet_entries was sorted */
1990                 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1991                 {
1992                     if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1993                 }
1994                 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1995                 {
1996                     if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1997                         fprintf(stderr, "Unknown packet request %*.*s\n",
1998                                 plen, plen, &gdbctx->in_buf[1]);
1999                 }
2000                 else
2001                 {
2002                     gdbctx->in_packet = gdbctx->in_buf + 2;
2003                     gdbctx->in_packet_len = plen - 1;
2004                     if (gdbctx->trace & GDBPXY_TRC_PACKET)
2005                         fprintf(stderr, "Packet: %c%*.*s\n",
2006                                 gdbctx->in_buf[1],
2007                                 gdbctx->in_packet_len, gdbctx->in_packet_len,
2008                                 gdbctx->in_packet);
2009                     ret = (packet_entries[i].handler)(gdbctx);
2010                 }
2011                 switch (ret & ~packet_last_f)
2012                 {
2013                 case packet_error:  packet_reply(gdbctx, "", 0); break;
2014                 case packet_ok:     packet_reply(gdbctx, "OK", 2); break;
2015                 case packet_done:   break;
2016                 }
2017                 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2018                     fprintf(stderr, "Reply-full: %*.*s\n",
2019                             gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2020                 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2021                 assert(i == gdbctx->out_len);
2022                 /* if this fails, we'll have to use POLLOUT...
2023                  */
2024                 gdbctx->out_len = 0;
2025                 num_packet++;
2026             }
2027             else 
2028             {
2029                 /* FIXME: if we have in our input buffer more than one packet, 
2030                  * it's very likely that we took too long to answer to a given packet
2031                  * and gdb is sending us again the same packet
2032                  * We simply drop the second packet. This will lower the risk of error, 
2033                  * but there's still some race conditions here
2034                  * A better fix (yet not perfect) would be to have two threads:
2035                  * - one managing the packets for gdb
2036                  * - the second one managing the commands...
2037                  * This would allow us also the reply with the '+' character (Ack of
2038                  * the command) way sooner than what we do now
2039                  */
2040                 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2041                     fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2042             }
2043         }
2044         else
2045         {
2046             write(gdbctx->sock, "+", 1);
2047             if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2048                 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2049         }
2050         gdbctx->in_len -= plen + 4;
2051         memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2052     }
2053     return TRUE;
2054 }
2055
2056 static int fetch_data(struct gdb_context* gdbctx)
2057 {
2058     int len, in_len = gdbctx->in_len;
2059
2060     assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2061     for (;;)
2062     {
2063 #define STEP 128
2064         if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2065             gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2066 #undef STEP
2067         if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2068             fprintf(stderr, "%d %d %*.*s\n",
2069                     gdbctx->in_len, gdbctx->in_buf_alloc,
2070                     gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2071         len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2072         if (len <= 0) break;
2073         gdbctx->in_len += len;
2074         assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2075         if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2076     }
2077     if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2078         fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2079     return gdbctx->in_len - in_len;
2080 }
2081
2082 #define FLAG_NO_START   1
2083 #define FLAG_WITH_XTERM 2
2084
2085 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2086 {
2087     char            buf[MAX_PATH];
2088     int             fd;
2089     const char*     gdb_path;
2090     FILE*           f;
2091
2092     if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2093     strcpy(buf,"/tmp/winegdb.XXXXXX");
2094     fd = mkstemps(buf, 0);
2095     if (fd == -1) return FALSE;
2096     if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2097     fprintf(f, "file %s\n", wine_path);
2098     fprintf(f, "target remote localhost:%d\n", ntohs(port));
2099     fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2100     fprintf(f, "set prompt Wine-gdb>\\ \n");
2101     /* gdb 5.1 seems to require it, won't hurt anyway */
2102     fprintf(f, "sharedlibrary\n");
2103     /* This is needed (but not a decent & final fix)
2104      * Without this, gdb would skip our inter-DLL relay code (because
2105      * we don't have any line number information for the relay code)
2106      * With this, we will stop on first instruction of the stub, and
2107      * reusing step, will get us through the relay stub at the actual
2108      * function we're looking at.
2109      */
2110     fprintf(f, "set step-mode on\n");
2111     /* tell gdb to delete this file when done handling it... */
2112     fprintf(f, "shell rm -f \"%s\"\n", buf);
2113     fclose(f);
2114     if (flags & FLAG_WITH_XTERM)
2115         execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2116     else
2117         execlp(gdb_path, gdb_path, "-x", buf, NULL);
2118     assert(0); /* never reached */
2119     return TRUE;
2120 }
2121
2122 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2123 {
2124     int                 sock;
2125     struct sockaddr_in  s_addrs;
2126     unsigned int        s_len = sizeof(s_addrs);
2127     struct pollfd       pollfd;
2128     IMAGEHLP_MODULE     imh_mod;
2129
2130     /* step 1: create socket for gdb connection request */
2131     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2132     {
2133         if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2134             fprintf(stderr, "Can't create socket");
2135         return FALSE;
2136     }
2137
2138     if (listen(sock, 1) == -1 ||
2139         getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2140         return FALSE;
2141
2142     /* step 2: do the process internal creation */
2143     handle_debug_event(gdbctx, de);
2144
2145     /* step3: get the wine loader name */
2146     if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2147
2148     /* step 4: fire up gdb (if requested) */
2149     if (flags & FLAG_NO_START)
2150         fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2151     else
2152         switch (fork())
2153         {
2154         case -1: /* error in parent... */
2155             fprintf(stderr, "Cannot create gdb\n");
2156             return FALSE;
2157         default: /* in parent... success */
2158             break;
2159         case 0: /* in child... and alive */
2160             gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2161             /* if we're here, exec failed, so report failure */
2162             return FALSE;
2163         }
2164
2165     /* step 5: wait for gdb to connect actually */
2166     pollfd.fd = sock;
2167     pollfd.events = POLLIN;
2168     pollfd.revents = 0;
2169
2170     switch (poll(&pollfd, 1, -1))
2171     {
2172     case 1:
2173         if (pollfd.revents & POLLIN)
2174         {
2175             int dummy = 1;
2176             gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2177             if (gdbctx->sock == -1)
2178                 break;
2179             if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2180                 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2181             /* don't keep our small packets too long: send them ASAP back to GDB
2182              * without this, GDB really crawls
2183              */
2184             setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2185         }
2186         break;
2187     case 0:
2188         if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2189             fprintf(stderr, "Poll for cnx failed (timeout)\n");
2190         return FALSE;
2191     case -1:
2192         if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2193             fprintf(stderr, "Poll for cnx failed (error)\n");
2194         return FALSE;
2195     default:
2196         assert(0);
2197     }
2198
2199     close(sock);
2200     return TRUE;
2201 }
2202
2203 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2204 {
2205     DEBUG_EVENT         de;
2206     int                 i;
2207
2208     gdbctx->sock = -1;
2209     gdbctx->in_buf = NULL;
2210     gdbctx->in_buf_alloc = 0;
2211     gdbctx->in_len = 0;
2212     gdbctx->out_buf = NULL;
2213     gdbctx->out_buf_alloc = 0;
2214     gdbctx->out_len = 0;
2215     gdbctx->out_curr_packet = -1;
2216
2217     gdbctx->exec_thread = gdbctx->other_thread = NULL;
2218     gdbctx->last_sig = 0;
2219     gdbctx->in_trap = FALSE;
2220     gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2221     gdbctx->process = NULL;
2222     for (i = 0; i < NUM_XPOINT; i++)
2223         gdbctx->Xpoints[i].type = -1;
2224
2225     /* wait for first trap */
2226     while (WaitForDebugEvent(&de, INFINITE))
2227     {
2228         if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2229         {
2230             /* this should be the first event we get,
2231              * and the only one of this type  */
2232             assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2233             /* gdbctx->dwProcessId = pid; */
2234             if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2235             assert(!gdbctx->in_trap);
2236         }
2237         else
2238         {
2239             handle_debug_event(gdbctx, &de);
2240             if (gdbctx->in_trap) break;
2241         }
2242         ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2243     }
2244     return TRUE;
2245 }
2246
2247 static int gdb_remote(unsigned flags)
2248 {
2249     struct pollfd       pollfd;
2250     struct gdb_context  gdbctx;
2251     BOOL                doLoop;
2252
2253     for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2254     {
2255         pollfd.fd = gdbctx.sock;
2256         pollfd.events = POLLIN;
2257         pollfd.revents = 0;
2258
2259         switch (poll(&pollfd, 1, -1))
2260         {
2261         case 1:
2262             /* got something */
2263             if (pollfd.revents & (POLLHUP | POLLERR))
2264             {
2265                 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2266                     fprintf(stderr, "Gdb hung up\n");
2267                 /* kill also debuggee process - questionnable - */
2268                 detach_debuggee(&gdbctx, TRUE);
2269                 doLoop = FALSE;
2270                 break;
2271             }
2272             if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2273             {
2274                 if (extract_packets(&gdbctx)) doLoop = FALSE;
2275             }
2276             break;
2277         case 0:
2278             /* timeout, should never happen (infinite timeout) */
2279             break;
2280         case -1:
2281             if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2282                 fprintf(stderr, "Poll failed\n");
2283             doLoop = FALSE;
2284             break;
2285         }
2286     }
2287     wait(NULL);
2288     return 0;
2289 }
2290 #endif
2291
2292 int gdb_main(int argc, char* argv[])
2293 {
2294 #ifdef HAVE_POLL
2295     unsigned gdb_flags = 0;
2296
2297     argc--; argv++;
2298     while (argc > 0 && argv[0][0] == '-')
2299     {
2300         if (strcmp(argv[0], "--no-start") == 0)
2301         {
2302             gdb_flags |= FLAG_NO_START;
2303             argc--; argv++;
2304             continue;
2305         }
2306         if (strcmp(argv[0], "--with-xterm") == 0)
2307         {
2308             gdb_flags |= FLAG_WITH_XTERM;
2309             argc--; argv++;
2310             continue;
2311         }
2312         return -1;
2313     }
2314     if (dbg_active_attach(argc, argv) == start_ok ||
2315         dbg_active_launch(argc, argv) == start_ok)
2316         return gdb_remote(gdb_flags);
2317 #else
2318     fprintf(stderr, "GdbProxy mode not supported on this platform\n");
2319 #endif
2320     return -1;
2321 }
2322
2323 static struct be_process_io be_process_gdbproxy_io =
2324 {
2325     NULL, /* we shouldn't use close_process() in gdbproxy */
2326     ReadProcessMemory,
2327     WriteProcessMemory
2328 };