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