~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/winedbg/gdbproxy.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.