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

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

Version: ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * A Win32 based proxy implementing the GBD remote protocol
  3  * This allows to debug Wine (and any "emulated" program) under
  4  * Linux using GDB
  5  *
  6  * Copyright (c) Eric Pouech 2002-2004
  7  *
  8  * This library is free software; you can redistribute it and/or
  9  * modify it under the terms of the GNU Lesser General Public
 10  * License as published by the Free Software Foundation; either
 11  * version 2.1 of the License, or (at your option) any later version.
 12  *
 13  * This library is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * Lesser General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU Lesser General Public
 19  * License along with this library; if not, write to the Free Software
 20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 21  */
 22 
 23 /* Protocol specification can be found here:
 24  * http://sources.redhat.com/gdb/onlinedocs/gdb_32.html
 25  */
 26 
 27 #include "config.h"
 28 #include "wine/port.h"
 29 
 30 #include <assert.h>
 31 #include <errno.h>
 32 #include <fcntl.h>
 33 #include <signal.h>
 34 #include <stdarg.h>
 35 #include <stdio.h>
 36 #include <stdlib.h>
 37 #ifdef HAVE_SYS_POLL_H
 38 # include <sys/poll.h>
 39 #endif
 40 #ifdef HAVE_SYS_WAIT_H
 41 # include <sys/wait.h>
 42 #endif
 43 #ifdef HAVE_SYS_SOCKET_H
 44 # include <sys/socket.h>
 45 #endif
 46 #ifdef HAVE_NETINET_IN_H
 47 # include <netinet/in.h>
 48 #endif
 49 #ifdef HAVE_NETINET_TCP_H
 50 # include <netinet/tcp.h>
 51 #endif
 52 #ifdef HAVE_UNISTD_H
 53 # include <unistd.h>
 54 #endif
 55 
 56 /* if we don't have poll support on this system
 57  * we won't provide gdb proxy support here...
 58  */
 59 #ifdef HAVE_POLL
 60 
 61 #include "debugger.h"
 62 
 63 #include "windef.h"
 64 #include "winbase.h"
 65 #include "tlhelp32.h"
 66 
 67 #define GDBPXY_TRC_LOWLEVEL             0x01
 68 #define GDBPXY_TRC_PACKET               0x02
 69 #define GDBPXY_TRC_COMMAND              0x04
 70 #define GDBPXY_TRC_COMMAND_ERROR        0x08
 71 #define GDBPXY_TRC_WIN32_EVENT          0x10
 72 #define GDBPXY_TRC_WIN32_ERROR          0x20
 73 #define GDBPXY_TRC_COMMAND_FIXME        0x80
 74 
 75 struct gdb_ctx_Xpoint
 76 {
 77     enum be_xpoint_type         type;   /* -1 means free */
 78     void*                       addr;
 79     unsigned long               val;
 80 };
 81 
 82 struct gdb_context
 83 {
 84     /* gdb information */
 85     int                         sock;
 86     /* incoming buffer */
 87     char*                       in_buf;
 88     int                         in_buf_alloc;
 89     int                         in_len;
 90     /* split into individual packet */
 91     char*                       in_packet;
 92     int                         in_packet_len;
 93     /* outgoing buffer */
 94     char*                       out_buf;
 95     int                         out_buf_alloc;
 96     int                         out_len;
 97     int                         out_curr_packet;
 98     /* generic GDB thread information */
 99     struct dbg_thread*          exec_thread;    /* thread used in step & continue */
100     struct dbg_thread*          other_thread;   /* thread to be used in any other operation */
101     unsigned                    trace;
102     /* current Win32 trap env */
103     unsigned                    last_sig;
104     BOOL                        in_trap;
105     CONTEXT                     context;
106     /* Win32 information */
107     struct dbg_process*         process;
108 #define NUM_XPOINT      32
109     struct gdb_ctx_Xpoint       Xpoints[NUM_XPOINT];
110     /* Unix environment */
111     unsigned long               wine_segs[3];   /* load addresses of the ELF wine exec segments (text, bss and data) */
112 };
113 
114 static struct be_process_io be_process_gdbproxy_io =
115 {
116     NULL, /* we shouldn't use close_process() in gdbproxy */
117     ReadProcessMemory,
118     WriteProcessMemory
119 };
120 
121 /* =============================================== *
122  *       B A S I C   M A N I P U L A T I O N S     *
123  * =============================================== *
124  */
125 
126 static inline int hex_from0(char ch)
127 {
128     if (ch >= '' && ch <= '9') return ch - '';
129     if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
130     if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
131 
132     assert(0);
133     return 0;
134 }
135 
136 static inline unsigned char hex_to0(int x)
137 {
138     assert(x >= 0 && x < 16);
139     return "0123456789abcdef"[x];
140 }
141 
142 static int hex_to_int(const char* src, size_t len)
143 {
144     unsigned int returnval = 0;
145     while (len--)
146     {
147         returnval <<= 4;
148         returnval |= hex_from0(*src++);
149     }
150     return returnval;
151 }
152 
153 static void hex_from(void* dst, const char* src, size_t len)
154 {
155     unsigned char *p = dst;
156     while (len--)
157     {
158         *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
159         src += 2;
160     }
161 }
162 
163 static void hex_to(char* dst, const void* src, size_t len)
164 {
165     const unsigned char *p = src;
166     while (len--)
167     {
168         *dst++ = hex_to0(*p >> 4);
169         *dst++ = hex_to0(*p & 0x0F);
170         p++;
171     }
172 }
173 
174 static unsigned char checksum(const char* ptr, int len)
175 {
176     unsigned cksum = 0;
177 
178     while (len-- > 0)
179         cksum += (unsigned char)*ptr++;
180     return cksum;
181 }
182 
183 /* =============================================== *
184  *              C P U   H A N D L E R S            *
185  * =============================================== *
186  */
187 
188 #ifdef __i386__
189 static size_t cpu_register_map[] = {
190     FIELD_OFFSET(CONTEXT, Eax),
191     FIELD_OFFSET(CONTEXT, Ecx),
192     FIELD_OFFSET(CONTEXT, Edx),
193     FIELD_OFFSET(CONTEXT, Ebx),
194     FIELD_OFFSET(CONTEXT, Esp),
195     FIELD_OFFSET(CONTEXT, Ebp),
196     FIELD_OFFSET(CONTEXT, Esi),
197     FIELD_OFFSET(CONTEXT, Edi),
198     FIELD_OFFSET(CONTEXT, Eip),
199     FIELD_OFFSET(CONTEXT, EFlags),
200     FIELD_OFFSET(CONTEXT, SegCs),
201     FIELD_OFFSET(CONTEXT, SegSs),
202     FIELD_OFFSET(CONTEXT, SegDs),
203     FIELD_OFFSET(CONTEXT, SegEs),
204     FIELD_OFFSET(CONTEXT, SegFs),
205     FIELD_OFFSET(CONTEXT, SegGs),
206 };
207 #elif defined(__powerpc__)
208 static size_t cpu_register_map[] = {
209     FIELD_OFFSET(CONTEXT, Gpr0),
210     FIELD_OFFSET(CONTEXT, Gpr1),
211     FIELD_OFFSET(CONTEXT, Gpr2),
212     FIELD_OFFSET(CONTEXT, Gpr3),
213     FIELD_OFFSET(CONTEXT, Gpr4),
214     FIELD_OFFSET(CONTEXT, Gpr5),
215     FIELD_OFFSET(CONTEXT, Gpr6),
216     FIELD_OFFSET(CONTEXT, Gpr7),
217     FIELD_OFFSET(CONTEXT, Gpr8),
218     FIELD_OFFSET(CONTEXT, Gpr9),
219     FIELD_OFFSET(CONTEXT, Gpr10),
220     FIELD_OFFSET(CONTEXT, Gpr11),
221     FIELD_OFFSET(CONTEXT, Gpr12),
222     FIELD_OFFSET(CONTEXT, Gpr13),
223     FIELD_OFFSET(CONTEXT, Gpr14),
224     FIELD_OFFSET(CONTEXT, Gpr15),
225     FIELD_OFFSET(CONTEXT, Gpr16),
226     FIELD_OFFSET(CONTEXT, Gpr17),
227     FIELD_OFFSET(CONTEXT, Gpr18),
228     FIELD_OFFSET(CONTEXT, Gpr19),
229     FIELD_OFFSET(CONTEXT, Gpr20),
230     FIELD_OFFSET(CONTEXT, Gpr21),
231     FIELD_OFFSET(CONTEXT, Gpr22),
232     FIELD_OFFSET(CONTEXT, Gpr23),
233     FIELD_OFFSET(CONTEXT, Gpr24),
234     FIELD_OFFSET(CONTEXT, Gpr25),
235     FIELD_OFFSET(CONTEXT, Gpr26),
236     FIELD_OFFSET(CONTEXT, Gpr27),
237     FIELD_OFFSET(CONTEXT, Gpr28),
238     FIELD_OFFSET(CONTEXT, Gpr29),
239     FIELD_OFFSET(CONTEXT, Gpr30),
240     FIELD_OFFSET(CONTEXT, Gpr31),
241     FIELD_OFFSET(CONTEXT, Fpr0),
242     FIELD_OFFSET(CONTEXT, Fpr1),
243     FIELD_OFFSET(CONTEXT, Fpr2),
244     FIELD_OFFSET(CONTEXT, Fpr3),
245     FIELD_OFFSET(CONTEXT, Fpr4),
246     FIELD_OFFSET(CONTEXT, Fpr5),
247     FIELD_OFFSET(CONTEXT, Fpr6),
248     FIELD_OFFSET(CONTEXT, Fpr7),
249     FIELD_OFFSET(CONTEXT, Fpr8),
250     FIELD_OFFSET(CONTEXT, Fpr9),
251     FIELD_OFFSET(CONTEXT, Fpr10),
252     FIELD_OFFSET(CONTEXT, Fpr11),
253     FIELD_OFFSET(CONTEXT, Fpr12),
254     FIELD_OFFSET(CONTEXT, Fpr13),
255     FIELD_OFFSET(CONTEXT, Fpr14),
256     FIELD_OFFSET(CONTEXT, Fpr15),
257     FIELD_OFFSET(CONTEXT, Fpr16),
258     FIELD_OFFSET(CONTEXT, Fpr17),
259     FIELD_OFFSET(CONTEXT, Fpr18),
260     FIELD_OFFSET(CONTEXT, Fpr19),
261     FIELD_OFFSET(CONTEXT, Fpr20),
262     FIELD_OFFSET(CONTEXT, Fpr21),
263     FIELD_OFFSET(CONTEXT, Fpr22),
264     FIELD_OFFSET(CONTEXT, Fpr23),
265     FIELD_OFFSET(CONTEXT, Fpr24),
266     FIELD_OFFSET(CONTEXT, Fpr25),
267     FIELD_OFFSET(CONTEXT, Fpr26),
268     FIELD_OFFSET(CONTEXT, Fpr27),
269     FIELD_OFFSET(CONTEXT, Fpr28),
270     FIELD_OFFSET(CONTEXT, Fpr29),
271     FIELD_OFFSET(CONTEXT, Fpr30),
272     FIELD_OFFSET(CONTEXT, Fpr31),
273 
274     FIELD_OFFSET(CONTEXT, Iar),
275     FIELD_OFFSET(CONTEXT, Msr),
276     FIELD_OFFSET(CONTEXT, Cr),
277     FIELD_OFFSET(CONTEXT, Lr),
278     FIELD_OFFSET(CONTEXT, Ctr),
279     FIELD_OFFSET(CONTEXT, Xer),
280     /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
281     /* see gdb/nlm/ppc.c */
282 };
283 #elif defined(__ALPHA__)
284 static size_t cpu_register_map[] = {
285     FIELD_OFFSET(CONTEXT, IntV0),
286     FIELD_OFFSET(CONTEXT, IntT0),
287     FIELD_OFFSET(CONTEXT, IntT1),
288     FIELD_OFFSET(CONTEXT, IntT2),
289     FIELD_OFFSET(CONTEXT, IntT3),
290     FIELD_OFFSET(CONTEXT, IntT4),
291     FIELD_OFFSET(CONTEXT, IntT5),
292     FIELD_OFFSET(CONTEXT, IntT6),
293     FIELD_OFFSET(CONTEXT, IntT7),
294     FIELD_OFFSET(CONTEXT, IntS0),
295     FIELD_OFFSET(CONTEXT, IntS1),
296     FIELD_OFFSET(CONTEXT, IntS2),
297     FIELD_OFFSET(CONTEXT, IntS3),
298     FIELD_OFFSET(CONTEXT, IntS4),
299     FIELD_OFFSET(CONTEXT, IntS5),
300     FIELD_OFFSET(CONTEXT, IntFp),
301     FIELD_OFFSET(CONTEXT, IntA0),
302     FIELD_OFFSET(CONTEXT, IntA1),
303     FIELD_OFFSET(CONTEXT, IntA2),
304     FIELD_OFFSET(CONTEXT, IntA3),
305     FIELD_OFFSET(CONTEXT, IntA4),
306     FIELD_OFFSET(CONTEXT, IntA5),
307     FIELD_OFFSET(CONTEXT, IntT8),
308     FIELD_OFFSET(CONTEXT, IntT9),
309     FIELD_OFFSET(CONTEXT, IntT10),
310     FIELD_OFFSET(CONTEXT, IntT11),
311     FIELD_OFFSET(CONTEXT, IntRa),
312     FIELD_OFFSET(CONTEXT, IntT12),
313     FIELD_OFFSET(CONTEXT, IntAt),
314     FIELD_OFFSET(CONTEXT, IntGp),
315     FIELD_OFFSET(CONTEXT, IntSp),
316     FIELD_OFFSET(CONTEXT, IntZero),
317     FIELD_OFFSET(CONTEXT, FltF0),
318     FIELD_OFFSET(CONTEXT, FltF1),
319     FIELD_OFFSET(CONTEXT, FltF2),
320     FIELD_OFFSET(CONTEXT, FltF3),
321     FIELD_OFFSET(CONTEXT, FltF4),
322     FIELD_OFFSET(CONTEXT, FltF5),
323     FIELD_OFFSET(CONTEXT, FltF6),
324     FIELD_OFFSET(CONTEXT, FltF7),
325     FIELD_OFFSET(CONTEXT, FltF8),
326     FIELD_OFFSET(CONTEXT, FltF9),
327     FIELD_OFFSET(CONTEXT, FltF10),
328     FIELD_OFFSET(CONTEXT, FltF11),
329     FIELD_OFFSET(CONTEXT, FltF12),
330     FIELD_OFFSET(CONTEXT, FltF13),
331     FIELD_OFFSET(CONTEXT, FltF14),
332     FIELD_OFFSET(CONTEXT, FltF15),
333     FIELD_OFFSET(CONTEXT, FltF16),
334     FIELD_OFFSET(CONTEXT, FltF17),
335     FIELD_OFFSET(CONTEXT, FltF18),
336     FIELD_OFFSET(CONTEXT, FltF19),
337     FIELD_OFFSET(CONTEXT, FltF20),
338     FIELD_OFFSET(CONTEXT, FltF21),
339     FIELD_OFFSET(CONTEXT, FltF22),
340     FIELD_OFFSET(CONTEXT, FltF23),
341     FIELD_OFFSET(CONTEXT, FltF24),
342     FIELD_OFFSET(CONTEXT, FltF25),
343     FIELD_OFFSET(CONTEXT, FltF26),
344     FIELD_OFFSET(CONTEXT, FltF27),
345     FIELD_OFFSET(CONTEXT, FltF28),
346     FIELD_OFFSET(CONTEXT, FltF29),
347     FIELD_OFFSET(CONTEXT, FltF30),
348     FIELD_OFFSET(CONTEXT, FltF31),
349 
350     /* FIXME: Didn't look for the right order yet */
351     FIELD_OFFSET(CONTEXT, Fir),
352     FIELD_OFFSET(CONTEXT, Fpcr),
353     FIELD_OFFSET(CONTEXT, SoftFpcr),
354 };
355 #elif defined(__x86_64__)
356 static size_t cpu_register_map[] = {
357     FIELD_OFFSET(CONTEXT, Rax),
358     FIELD_OFFSET(CONTEXT, Rbx),
359     FIELD_OFFSET(CONTEXT, Rcx),
360     FIELD_OFFSET(CONTEXT, Rdx),
361     FIELD_OFFSET(CONTEXT, Rsi),
362     FIELD_OFFSET(CONTEXT, Rdi),
363     FIELD_OFFSET(CONTEXT, Rbp),
364     FIELD_OFFSET(CONTEXT, Rsp),
365     FIELD_OFFSET(CONTEXT, R8),
366     FIELD_OFFSET(CONTEXT, R9),
367     FIELD_OFFSET(CONTEXT, R10),
368     FIELD_OFFSET(CONTEXT, R11),
369     FIELD_OFFSET(CONTEXT, R12),
370     FIELD_OFFSET(CONTEXT, R13),
371     FIELD_OFFSET(CONTEXT, R14),
372     FIELD_OFFSET(CONTEXT, R15),
373     FIELD_OFFSET(CONTEXT, Rip),
374     FIELD_OFFSET(CONTEXT, EFlags),
375     FIELD_OFFSET(CONTEXT, SegCs),
376     FIELD_OFFSET(CONTEXT, SegSs),
377     FIELD_OFFSET(CONTEXT, SegDs),
378     FIELD_OFFSET(CONTEXT, SegEs),
379     FIELD_OFFSET(CONTEXT, SegFs),
380     FIELD_OFFSET(CONTEXT, SegGs),
381 };
382 #else
383 # error Define the registers map for your CPU
384 #endif
385 
386 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
387 
388 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
389 {
390     assert(idx < cpu_num_regs);
391     return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
392 }
393 
394 /* =============================================== *
395  *    W I N 3 2   D E B U G   I N T E R F A C E    *
396  * =============================================== *
397  */
398 
399 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
400 {
401     ctx->ContextFlags =  CONTEXT_CONTROL
402                        | CONTEXT_INTEGER
403 #ifdef CONTEXT_SEGMENTS
404                        | CONTEXT_SEGMENTS
405 #endif
406 #ifdef CONTEXT_DEBUG_REGISTERS
407                        | CONTEXT_DEBUG_REGISTERS
408 #endif
409                        ;
410     if (!GetThreadContext(h, ctx))
411     {
412         if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
413             fprintf(stderr, "Can't get thread's context\n");
414         return FALSE;
415     }
416     return TRUE;
417 }
418 
419 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
420 {
421     EXCEPTION_RECORD*   rec = &exc->ExceptionRecord;
422     BOOL                ret = FALSE;
423 
424     switch (rec->ExceptionCode)
425     {
426     case EXCEPTION_ACCESS_VIOLATION:
427     case EXCEPTION_PRIV_INSTRUCTION:
428     case EXCEPTION_STACK_OVERFLOW:
429     case EXCEPTION_GUARD_PAGE:
430         gdbctx->last_sig = SIGSEGV;
431         ret = TRUE;
432         break;
433     case EXCEPTION_DATATYPE_MISALIGNMENT:
434         gdbctx->last_sig = SIGBUS;
435         ret = TRUE;
436         break;
437     case EXCEPTION_SINGLE_STEP:
438         /* fall thru */
439     case EXCEPTION_BREAKPOINT:
440         gdbctx->last_sig = SIGTRAP;
441         ret = TRUE;
442         break;
443     case EXCEPTION_FLT_DENORMAL_OPERAND:
444     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
445     case EXCEPTION_FLT_INEXACT_RESULT:
446     case EXCEPTION_FLT_INVALID_OPERATION:
447     case EXCEPTION_FLT_OVERFLOW:
448     case EXCEPTION_FLT_STACK_CHECK:
449     case EXCEPTION_FLT_UNDERFLOW:
450         gdbctx->last_sig = SIGFPE;
451         ret = TRUE;
452         break;
453     case EXCEPTION_INT_DIVIDE_BY_ZERO:
454     case EXCEPTION_INT_OVERFLOW:
455         gdbctx->last_sig = SIGFPE;
456         ret = TRUE;
457         break;
458     case EXCEPTION_ILLEGAL_INSTRUCTION:
459         gdbctx->last_sig = SIGILL;
460         ret = TRUE;
461         break;
462     case CONTROL_C_EXIT:
463         gdbctx->last_sig = SIGINT;
464         ret = TRUE;
465         break;
466     case STATUS_POSSIBLE_DEADLOCK:
467         gdbctx->last_sig = SIGALRM;
468         ret = TRUE;
469         /* FIXME: we could also add here a O packet with additional information */
470         break;
471     default:
472         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
473             fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
474         gdbctx->last_sig = SIGABRT;
475         ret = TRUE;
476         break;
477     }
478     return ret;
479 }
480 
481 static  void    handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
482 {
483     char                buffer[256];
484 
485     dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
486 
487     switch (de->dwDebugEventCode)
488     {
489     case CREATE_PROCESS_DEBUG_EVENT:
490         gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
491                                           de->u.CreateProcessInfo.hProcess);
492         if (!gdbctx->process) break;
493         memory_get_string_indirect(gdbctx->process,
494                                    de->u.CreateProcessInfo.lpImageName,
495                                    de->u.CreateProcessInfo.fUnicode,
496                                    buffer, sizeof(buffer));
497         dbg_set_process_name(gdbctx->process, buffer);
498 
499         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
500             fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
501                     de->dwProcessId, de->dwThreadId,
502                     buffer, de->u.CreateProcessInfo.lpImageName,
503                     de->u.CreateProcessInfo.lpStartAddress,
504                     de->u.CreateProcessInfo.dwDebugInfoFileOffset,
505                     de->u.CreateProcessInfo.nDebugInfoSize);
506 
507         /* de->u.CreateProcessInfo.lpStartAddress; */
508         if (!SymInitialize(gdbctx->process->handle, NULL, TRUE))
509             fprintf(stderr, "Couldn't initiate DbgHelp\n");
510 
511         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
512             fprintf(stderr, "%04x:%04x: create thread I @%p\n",
513                     de->dwProcessId, de->dwThreadId,
514                     de->u.CreateProcessInfo.lpStartAddress);
515 
516         assert(dbg_curr_thread == NULL); /* shouldn't be there */
517         dbg_add_thread(gdbctx->process, de->dwThreadId,
518                        de->u.CreateProcessInfo.hThread,
519                        de->u.CreateProcessInfo.lpThreadLocalBase);
520         break;
521 
522     case LOAD_DLL_DEBUG_EVENT:
523         assert(dbg_curr_thread);
524         memory_get_string_indirect(gdbctx->process,
525                                    de->u.LoadDll.lpImageName,
526                                    de->u.LoadDll.fUnicode,
527                                    buffer, sizeof(buffer));
528         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
529             fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
530                     de->dwProcessId, de->dwThreadId,
531                     buffer, de->u.LoadDll.lpBaseOfDll,
532                     de->u.LoadDll.dwDebugInfoFileOffset,
533                     de->u.LoadDll.nDebugInfoSize);
534         SymLoadModule(gdbctx->process->handle, de->u.LoadDll.hFile, buffer, NULL,
535                       (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
536         break;
537 
538     case UNLOAD_DLL_DEBUG_EVENT:
539         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
540             fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
541                     de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
542         SymUnloadModule(gdbctx->process->handle, 
543                         (unsigned long)de->u.UnloadDll.lpBaseOfDll);
544         break;
545 
546     case EXCEPTION_DEBUG_EVENT:
547         assert(dbg_curr_thread);
548         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
549             fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
550                     de->dwProcessId, de->dwThreadId,
551                     de->u.Exception.ExceptionRecord.ExceptionCode);
552 
553         if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
554         {
555             gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
556         }
557         break;
558 
559     case CREATE_THREAD_DEBUG_EVENT:
560         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
561             fprintf(stderr, "%08x:%08x: create thread D @%p\n",
562                     de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
563 
564         dbg_add_thread(gdbctx->process,
565                        de->dwThreadId,
566                        de->u.CreateThread.hThread,
567                        de->u.CreateThread.lpThreadLocalBase);
568         break;
569 
570     case EXIT_THREAD_DEBUG_EVENT:
571         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
572             fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
573                     de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
574 
575         assert(dbg_curr_thread);
576         if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
577         if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
578         dbg_del_thread(dbg_curr_thread);
579         break;
580 
581     case EXIT_PROCESS_DEBUG_EVENT:
582         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
583             fprintf(stderr, "%08x:%08x: exit process (%u)\n",
584                     de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
585 
586         dbg_del_process(gdbctx->process);
587         gdbctx->process = NULL;
588         /* now signal gdb that we're done */
589         gdbctx->last_sig = SIGTERM;
590         gdbctx->in_trap = TRUE;
591         break;
592 
593     case OUTPUT_DEBUG_STRING_EVENT:
594         assert(dbg_curr_thread);
595         memory_get_string(gdbctx->process,
596                           de->u.DebugString.lpDebugStringData, TRUE,
597                           de->u.DebugString.fUnicode, buffer, sizeof(buffer));
598         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
599             fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
600                     de->dwProcessId, de->dwThreadId, buffer);
601         break;
602 
603     case RIP_EVENT:
604         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
605             fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
606                     de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
607                     de->u.RipInfo.dwType);
608         break;
609 
610     default:
611         if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
612             fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
613                     de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
614     }
615 }
616 
617 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
618 {
619     if (dbg_curr_thread)
620     {
621         if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
622             if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
623                 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
624         if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
625             if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
626                 fprintf(stderr, "Cannot continue on %04x (%x)\n",
627                         dbg_curr_thread->tid, cont);
628     }
629     else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
630         fprintf(stderr, "Cannot find last thread\n");
631 }
632 
633 
634 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
635 {
636 
637     if (dbg_curr_thread)
638     {
639         if(dbg_curr_thread->tid  == threadid){
640             /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
641             if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
642                 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
643                     fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
644             if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
645                 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
646                     fprintf(stderr, "Cannot continue on %04x (%x)\n",
647                             dbg_curr_thread->tid, cont);
648         }
649     }
650     else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
651         fprintf(stderr, "Cannot find last thread\n");
652 }
653 
654 static BOOL     check_for_interrupt(struct gdb_context* gdbctx)
655 {
656         struct pollfd       pollfd;
657         int ret;
658         char pkt;
659                                 
660         pollfd.fd = gdbctx->sock;
661         pollfd.events = POLLIN;
662         pollfd.revents = 0;
663                                 
664         if ((ret = poll(&pollfd, 1, 0)) == 1) {
665                 ret = read(gdbctx->sock, &pkt, 1);
666                 if (ret != 1) {
667                         if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
668                                 fprintf(stderr, "read failed\n");
669                         }
670                         return FALSE;
671                 }
672                 if (pkt != '\003') {
673                         if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
674                                 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);                               
675                         }
676                         return FALSE;
677                 }
678                 return TRUE;
679         } else if (ret == -1) {
680                 fprintf(stderr, "poll failed\n");
681         }
682         return FALSE;
683 }
684 
685 static void    wait_for_debuggee(struct gdb_context* gdbctx)
686 {
687     DEBUG_EVENT         de;
688 
689     gdbctx->in_trap = FALSE;
690     for (;;)
691     {
692                 if (!WaitForDebugEvent(&de, 10))
693                 {
694                         if (GetLastError() == ERROR_SEM_TIMEOUT)
695                         {
696                                 if (check_for_interrupt(gdbctx)) {
697                                         if (!DebugBreakProcess(gdbctx->process->handle)) {
698                                                 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
699                                                         fprintf(stderr, "Failed to break into debugee\n");
700                                                 }
701                                                 break;
702                                         }
703                                         WaitForDebugEvent(&de, INFINITE);       
704                                 } else {
705                                         continue;
706                                 } 
707                         } else {
708                                 break;
709                         } 
710                 }
711         handle_debug_event(gdbctx, &de);
712         assert(!gdbctx->process ||
713                gdbctx->process->pid == 0 ||
714                de.dwProcessId == gdbctx->process->pid);
715         assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
716         if (gdbctx->in_trap) break;
717         ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
718     }
719 }
720 
721 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
722 {
723     be_cpu->single_step(&gdbctx->context, FALSE);
724     resume_debuggee(gdbctx, DBG_CONTINUE);
725     if (!kill)
726         DebugActiveProcessStop(gdbctx->process->pid);
727     dbg_del_process(gdbctx->process);
728     gdbctx->process = NULL;
729 }
730 
731 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
732 {
733     DWORD status;
734 
735     if (!GetExitCodeProcess(gdbctx->process->handle, &status))
736     {
737         strcpy(buffer, "Unknown process");
738         return;
739     }
740     if (status == STILL_ACTIVE)
741     {
742         strcpy(buffer, "Running");
743     }
744     else
745         snprintf(buffer, len, "Terminated (%u)", status);
746 
747     switch (GetPriorityClass(gdbctx->process->handle))
748     {
749     case 0: break;
750 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
751     case ABOVE_NORMAL_PRIORITY_CLASS:   strcat(buffer, ", above normal priority");      break;
752 #endif
753 #ifdef BELOW_NORMAL_PRIORITY_CLASS
754     case BELOW_NORMAL_PRIORITY_CLASS:   strcat(buffer, ", below normal priotity");      break;
755 #endif
756     case HIGH_PRIORITY_CLASS:           strcat(buffer, ", high priority");              break;
757     case IDLE_PRIORITY_CLASS:           strcat(buffer, ", idle priority");              break;
758     case NORMAL_PRIORITY_CLASS:         strcat(buffer, ", normal priority");            break;
759     case REALTIME_PRIORITY_CLASS:       strcat(buffer, ", realtime priority");          break;
760     }
761     strcat(buffer, "\n");
762 }
763 
764 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
765                             char* buffer, size_t len)
766 {
767     struct dbg_thread*  thd;
768     DWORD               status;
769     int                 prio;
770 
771     /* FIXME: use the size of buffer */
772     thd = dbg_get_thread(gdbctx->process, tid);
773     if (thd == NULL)
774     {
775         strcpy(buffer, "No information");
776         return;
777     }
778     if (GetExitCodeThread(thd->handle, &status))
779     {
780         if (status == STILL_ACTIVE)
781         {
782             /* FIXME: this is a bit brutal... some nicer way shall be found */
783             switch (status = SuspendThread(thd->handle))
784             {
785             case -1: break;
786             case 0:  strcpy(buffer, "Running"); break;
787             default: snprintf(buffer, len, "Suspended (%u)", status - 1);
788             }
789             ResumeThread(thd->handle);
790         }
791         else
792             snprintf(buffer, len, "Terminated (exit code = %u)", status);
793     }
794     else
795     {
796         strcpy(buffer, "Unknown threadID");
797     }
798     switch (prio = GetThreadPriority(thd->handle))
799     {
800     case THREAD_PRIORITY_ERROR_RETURN:  break;
801     case THREAD_PRIORITY_ABOVE_NORMAL:  strcat(buffer, ", priority +1 above normal"); break;
802     case THREAD_PRIORITY_BELOW_NORMAL:  strcat(buffer, ", priority -1 below normal"); break;
803     case THREAD_PRIORITY_HIGHEST:       strcat(buffer, ", priority +2 above normal"); break;
804     case THREAD_PRIORITY_LOWEST:        strcat(buffer, ", priority -2 below normal"); break;
805     case THREAD_PRIORITY_IDLE:          strcat(buffer, ", priority idle"); break;
806     case THREAD_PRIORITY_NORMAL:        strcat(buffer, ", priority normal"); break;
807     case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
808     default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
809     }
810     assert(strlen(buffer) < len);
811 }
812 
813 /* =============================================== *
814  *          P A C K E T        U T I L S           *
815  * =============================================== *
816  */
817 
818 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
819                     packet_last_f = 0x80};
820 
821 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
822 {
823     if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
824     {
825         gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
826         gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
827     }
828 }
829 
830 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
831 {
832     packet_reply_grow(gdbctx, len * 2);
833     hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
834     gdbctx->out_len += len * 2;
835 }
836 
837 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
838 {
839     packet_reply_hex_to(gdbctx, src, strlen(src));
840 }
841 
842 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
843 {
844     int i, shift;
845 
846     shift = (len - 1) * 8;
847     packet_reply_grow(gdbctx, len * 2);
848     for (i = 0; i < len; i++, shift -= 8)
849     {
850         gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
851         gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >>  shift     ) & 0x0F);
852     }
853 }
854 
855 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
856 {
857     packet_reply_grow(gdbctx, len);
858     memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
859     gdbctx->out_len += len;
860 }
861 
862 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
863 {
864     packet_reply_add(gdbctx, str, strlen(str));
865 }
866 
867 static inline void