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