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