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