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