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