Moved a number of 16-bit functions to file16.c.
[wine.git] / programs / winedbg / gdbproxy.c
blob0d87ba00261e02cc1d3c06726aa9fa0ae8c1e29f
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
6 * Copyright (c) Eric Pouech 2002-2003
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.
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.
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
23 /* Protocol specification can be found here:
24 * http://sources.redhat.com/gdb/onlinedocs/gdb_32.html
27 #include "config.h"
28 #include "wine/port.h"
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
48 #include "windef.h"
49 #include "winbase.h"
50 #include "tlhelp32.h"
52 /* those two are needed only for the SHOWNORMAL flag */
53 #include "wingdi.h"
54 #include "winuser.h"
56 #include "debugger.h"
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
66 struct gdb_ctx_Xpoint
68 int type; /* -1 means free */
69 void* addr;
70 unsigned long val;
73 struct gdb_context
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 DBG_THREAD* exec_thread; /* thread used in step & continue */
91 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 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) */
105 /* =============================================== *
106 * B A S I C M A N I P U L A T I O N S *
107 * =============================================== *
110 static inline int hex_from0(char ch)
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;
116 assert(0);
117 return 0;
120 static inline unsigned char hex_to0(int x)
122 assert(x >= 0 && x < 16);
123 return "0123456789abcdef"[x];
126 static void hex_from(void* dst, const char* src, size_t len)
128 unsigned char *p = dst;
129 while (len--)
131 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
132 src += 2;
136 static void hex_to(char* dst, const void* src, size_t len)
138 const unsigned char *p = src;
139 while (len--)
141 *dst++ = hex_to0(*p >> 4);
142 *dst++ = hex_to0(*p & 0x0F);
143 p++;
147 static unsigned char checksum(const char* ptr, int len)
149 unsigned cksum = 0;
151 while (len-- > 0)
152 cksum += (unsigned char)*ptr++;
153 return cksum;
156 /* =============================================== *
157 * C P U H A N D L E R S *
158 * =============================================== *
161 #define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0)))
163 #ifdef __i386__
164 static size_t cpu_register_map[] = {
165 OFFSET_OF(CONTEXT, Eax),
166 OFFSET_OF(CONTEXT, Ecx),
167 OFFSET_OF(CONTEXT, Edx),
168 OFFSET_OF(CONTEXT, Ebx),
169 OFFSET_OF(CONTEXT, Esp),
170 OFFSET_OF(CONTEXT, Ebp),
171 OFFSET_OF(CONTEXT, Esi),
172 OFFSET_OF(CONTEXT, Edi),
173 OFFSET_OF(CONTEXT, Eip),
174 OFFSET_OF(CONTEXT, EFlags),
175 OFFSET_OF(CONTEXT, SegCs),
176 OFFSET_OF(CONTEXT, SegSs),
177 OFFSET_OF(CONTEXT, SegDs),
178 OFFSET_OF(CONTEXT, SegEs),
179 OFFSET_OF(CONTEXT, SegFs),
180 OFFSET_OF(CONTEXT, SegGs),
182 #else
183 # ifdef __powerpc__
184 static size_t cpu_register_map[] = {
185 OFFSET_OF(CONTEXT, Gpr0),
186 OFFSET_OF(CONTEXT, Gpr1),
187 OFFSET_OF(CONTEXT, Gpr2),
188 OFFSET_OF(CONTEXT, Gpr3),
189 OFFSET_OF(CONTEXT, Gpr4),
190 OFFSET_OF(CONTEXT, Gpr5),
191 OFFSET_OF(CONTEXT, Gpr6),
192 OFFSET_OF(CONTEXT, Gpr7),
193 OFFSET_OF(CONTEXT, Gpr8),
194 OFFSET_OF(CONTEXT, Gpr9),
195 OFFSET_OF(CONTEXT, Gpr10),
196 OFFSET_OF(CONTEXT, Gpr11),
197 OFFSET_OF(CONTEXT, Gpr12),
198 OFFSET_OF(CONTEXT, Gpr13),
199 OFFSET_OF(CONTEXT, Gpr14),
200 OFFSET_OF(CONTEXT, Gpr15),
201 OFFSET_OF(CONTEXT, Gpr16),
202 OFFSET_OF(CONTEXT, Gpr17),
203 OFFSET_OF(CONTEXT, Gpr18),
204 OFFSET_OF(CONTEXT, Gpr19),
205 OFFSET_OF(CONTEXT, Gpr20),
206 OFFSET_OF(CONTEXT, Gpr21),
207 OFFSET_OF(CONTEXT, Gpr22),
208 OFFSET_OF(CONTEXT, Gpr23),
209 OFFSET_OF(CONTEXT, Gpr24),
210 OFFSET_OF(CONTEXT, Gpr25),
211 OFFSET_OF(CONTEXT, Gpr26),
212 OFFSET_OF(CONTEXT, Gpr27),
213 OFFSET_OF(CONTEXT, Gpr28),
214 OFFSET_OF(CONTEXT, Gpr29),
215 OFFSET_OF(CONTEXT, Gpr30),
216 OFFSET_OF(CONTEXT, Gpr31),
217 OFFSET_OF(CONTEXT, Fpr0),
218 OFFSET_OF(CONTEXT, Fpr1),
219 OFFSET_OF(CONTEXT, Fpr2),
220 OFFSET_OF(CONTEXT, Fpr3),
221 OFFSET_OF(CONTEXT, Fpr4),
222 OFFSET_OF(CONTEXT, Fpr5),
223 OFFSET_OF(CONTEXT, Fpr6),
224 OFFSET_OF(CONTEXT, Fpr7),
225 OFFSET_OF(CONTEXT, Fpr8),
226 OFFSET_OF(CONTEXT, Fpr9),
227 OFFSET_OF(CONTEXT, Fpr10),
228 OFFSET_OF(CONTEXT, Fpr11),
229 OFFSET_OF(CONTEXT, Fpr12),
230 OFFSET_OF(CONTEXT, Fpr13),
231 OFFSET_OF(CONTEXT, Fpr14),
232 OFFSET_OF(CONTEXT, Fpr15),
233 OFFSET_OF(CONTEXT, Fpr16),
234 OFFSET_OF(CONTEXT, Fpr17),
235 OFFSET_OF(CONTEXT, Fpr18),
236 OFFSET_OF(CONTEXT, Fpr19),
237 OFFSET_OF(CONTEXT, Fpr20),
238 OFFSET_OF(CONTEXT, Fpr21),
239 OFFSET_OF(CONTEXT, Fpr22),
240 OFFSET_OF(CONTEXT, Fpr23),
241 OFFSET_OF(CONTEXT, Fpr24),
242 OFFSET_OF(CONTEXT, Fpr25),
243 OFFSET_OF(CONTEXT, Fpr26),
244 OFFSET_OF(CONTEXT, Fpr27),
245 OFFSET_OF(CONTEXT, Fpr28),
246 OFFSET_OF(CONTEXT, Fpr29),
247 OFFSET_OF(CONTEXT, Fpr30),
248 OFFSET_OF(CONTEXT, Fpr31),
250 OFFSET_OF(CONTEXT, Iar),
251 OFFSET_OF(CONTEXT, Msr),
252 OFFSET_OF(CONTEXT, Cr),
253 OFFSET_OF(CONTEXT, Lr),
254 OFFSET_OF(CONTEXT, Ctr),
255 OFFSET_OF(CONTEXT, Xer),
256 /* FIXME: MQ is missing? OFFSET_OF(CONTEXT, Mq), */
257 /* see gdb/nlm/ppc.c */
259 # else
260 # error "Define the registers map for your CPU"
261 # endif
262 #endif
263 #undef OFFSET_OF
265 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
267 static inline unsigned long* cpu_register(const CONTEXT* ctx, unsigned idx)
269 assert(idx < cpu_num_regs);
270 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
273 static inline BOOL cpu_enter_stepping(struct gdb_context* gdbctx)
275 #ifdef __i386__
276 gdbctx->context.EFlags |= 0x100;
277 return TRUE;
278 #elif __powerpc__
279 #ifndef MSR_SE
280 # define MSR_SE (1<<10)
281 #endif
282 gdbctx->context.Msr |= MSR_SE;
283 return TRUE;
284 #else
285 #error "Define step mode enter for your CPU"
286 #endif
287 return FALSE;
290 static inline BOOL cpu_leave_stepping(struct gdb_context* gdbctx)
292 #ifdef __i386__
293 /* The Win32 debug API always resets the Step bit in EFlags after
294 * a single step instruction, so we don't need to clear when the
295 * step is done.
297 return TRUE;
298 #elif __powerpc__
299 gdbctx->context.Msr &= MSR_SE;
300 return TRUE;
301 #else
302 #error "Define step mode leave for your CPU"
303 #endif
304 return FALSE;
307 #ifdef __i386__
308 #define DR7_CONTROL_SHIFT 16
309 #define DR7_CONTROL_SIZE 4
311 #define DR7_RW_EXECUTE (0x0)
312 #define DR7_RW_WRITE (0x1)
313 #define DR7_RW_READ (0x3)
315 #define DR7_LEN_1 (0x0)
316 #define DR7_LEN_2 (0x4)
317 #define DR7_LEN_4 (0xC)
319 #define DR7_LOCAL_ENABLE_SHIFT 0
320 #define DR7_GLOBAL_ENABLE_SHIFT 1
321 #define DR7_ENABLE_SIZE 2
323 #define DR7_LOCAL_ENABLE_MASK (0x55)
324 #define DR7_GLOBAL_ENABLE_MASK (0xAA)
326 #define DR7_CONTROL_RESERVED (0xFC00)
327 #define DR7_LOCAL_SLOWDOWN (0x100)
328 #define DR7_GLOBAL_SLOWDOWN (0x200)
330 #define DR7_ENABLE_MASK(dr) (1<<(DR7_LOCAL_ENABLE_SHIFT+DR7_ENABLE_SIZE*(dr)))
331 #define IS_DR7_SET(ctrl,dr) ((ctrl)&DR7_ENABLE_MASK(dr))
333 static inline int i386_get_unused_DR(struct gdb_context* gdbctx,
334 unsigned long** r)
336 if (!IS_DR7_SET(gdbctx->context.Dr7, 0))
338 *r = &gdbctx->context.Dr0;
339 return 0;
341 if (!IS_DR7_SET(gdbctx->context.Dr7, 1))
343 *r = &gdbctx->context.Dr1;
344 return 1;
346 if (!IS_DR7_SET(gdbctx->context.Dr7, 2))
348 *r = &gdbctx->context.Dr2;
349 return 2;
351 if (!IS_DR7_SET(gdbctx->context.Dr7, 3))
353 *r = &gdbctx->context.Dr3;
354 return 3;
356 return -1;
358 #endif
360 /******************************************************************
361 * cpu_insert_Xpoint
363 * returns 1 if ok
364 * 0 if error
365 * -1 if operation isn't supported by CPU
367 static inline int cpu_insert_Xpoint(struct gdb_context* gdbctx,
368 struct gdb_ctx_Xpoint* xpt, size_t len)
370 #ifdef __i386__
371 unsigned char ch;
372 unsigned long sz;
373 unsigned long* pr;
374 int reg;
375 unsigned long bits;
377 switch (xpt->type)
379 case '0':
380 if (len != 1) return 0;
381 if (!ReadProcessMemory(gdbctx->process->handle, xpt->addr, &ch, 1, &sz) || sz != 1) return 0;
382 xpt->val = ch;
383 ch = 0xcc;
384 if (!WriteProcessMemory(gdbctx->process->handle, xpt->addr, &ch, 1, &sz) || sz != 1) return 0;
385 break;
386 case '1':
387 bits = DR7_RW_EXECUTE;
388 goto hw_bp;
389 case '2':
390 bits = DR7_RW_READ;
391 goto hw_bp;
392 case '3':
393 bits = DR7_RW_WRITE;
394 hw_bp:
395 if ((reg = i386_get_unused_DR(gdbctx, &pr)) == -1) return 0;
396 *pr = (unsigned long)xpt->addr;
397 if (xpt->type != '1') switch (len)
399 case 4: bits |= DR7_LEN_4; break;
400 case 2: bits |= DR7_LEN_2; break;
401 case 1: bits |= DR7_LEN_1; break;
402 default: return 0;
404 xpt->val = reg;
405 /* clear old values */
406 gdbctx->context.Dr7 &= ~(0x0F << (DR7_CONTROL_SHIFT + DR7_CONTROL_SIZE * reg));
407 /* set the correct ones */
408 gdbctx->context.Dr7 |= bits << (DR7_CONTROL_SHIFT + DR7_CONTROL_SIZE * reg);
409 gdbctx->context.Dr7 |= DR7_ENABLE_MASK(reg) | DR7_LOCAL_SLOWDOWN;
410 break;
411 default:
412 fprintf(stderr, "Unknown bp type %c\n", xpt->type);
413 return 0;
415 return 1;
416 #elif defined(__powerpc__)
417 unsigned long xbp;
418 unsigned long sz;
420 switch (xpt->type)
422 case '0':
423 if (len != 4) return 0;
424 if (!ReadProcessMemory(gdbctx->process->handle, xpt->addr, &xbp, 4, &sz) || sz != 4) return 0;
425 xpt->val = xbp;
426 xbp = 0x7d821008; /* 7d 82 10 08 ... in big endian */
427 if (!WriteProcessMemory(gdbctx->process->handle, xpt->addr, &xbp, 4, &sz) || sz != 4) return 0;
428 break;
429 default:
430 fprintf(stderr, "Unknown/unsupported bp type %c\n", xpt->type);
431 return 0;
433 return 1;
434 #else
435 #error "Define insert Xpoint for your CPU"
436 #endif
437 return -1;
440 /******************************************************************
441 * cpu_remove_Xpoint
443 * returns 1 if ok
444 * 0 if error
445 * -1 if operation isn't supported by CPU
447 static inline BOOL cpu_remove_Xpoint(struct gdb_context* gdbctx,
448 struct gdb_ctx_Xpoint* xpt, size_t len)
450 #ifdef __i386__
451 unsigned long sz;
452 unsigned char ch;
454 switch (xpt->type)
456 case '0':
457 if (len != 1) return 0;
458 ch = (unsigned char)xpt->val;
459 if (!WriteProcessMemory(gdbctx->process->handle, xpt->addr, &ch, 1, &sz) || sz != 1) return 0;
460 break;
461 case '1':
462 case '2':
463 case '3':
464 /* simply disable the entry */
465 gdbctx->context.Dr7 &= ~DR7_ENABLE_MASK(xpt->val);
466 break;
467 default:
468 fprintf(stderr, "Unknown bp type %c\n", xpt->type);
469 return 0;
471 return 1;
472 #elif defined(__powerpc__)
473 unsigned long sz;
474 unsigned long xbp;
476 switch (xpt->type)
478 case '0':
479 if (len != 4) return 0;
480 xbp = xpt->val;
481 if (!WriteProcessMemory(gdbctx->process->handle, xpt->addr, &xbp, 4, &sz) || sz != 4) return 0;
482 break;
483 case '1':
484 case '2':
485 case '3':
486 default:
487 fprintf(stderr, "Unknown/unsupported bp type %c\n", xpt->type);
488 return 0;
490 return 1;
491 #else
492 #error "Define remove Xpoint for your CPU"
493 #endif
494 return -1;
496 /* =============================================== *
497 * W I N 3 2 D E B U G I N T E R F A C E *
498 * =============================================== *
501 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
503 ctx->ContextFlags = CONTEXT_CONTROL
504 | CONTEXT_INTEGER
505 #ifdef CONTEXT_SEGMENTS
506 | CONTEXT_SEGMENTS
507 #endif
508 #ifdef CONTEXT_DEBUG_REGISTERS
509 | CONTEXT_DEBUG_REGISTERS
510 #endif
512 if (!GetThreadContext(h, ctx))
514 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
515 fprintf(stderr, "Can't get thread's context\n");
516 return FALSE;
518 return TRUE;
521 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
523 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
524 BOOL ret = FALSE;
526 switch (rec->ExceptionCode)
528 case EXCEPTION_ACCESS_VIOLATION:
529 case EXCEPTION_PRIV_INSTRUCTION:
530 case EXCEPTION_STACK_OVERFLOW:
531 case EXCEPTION_GUARD_PAGE:
532 gdbctx->last_sig = SIGSEGV;
533 ret = TRUE;
534 break;
535 case EXCEPTION_DATATYPE_MISALIGNMENT:
536 gdbctx->last_sig = SIGBUS;
537 ret = TRUE;
538 break;
539 case EXCEPTION_SINGLE_STEP:
540 /* fall thru */
541 case EXCEPTION_BREAKPOINT:
542 gdbctx->last_sig = SIGTRAP;
543 ret = TRUE;
544 break;
545 case EXCEPTION_FLT_DENORMAL_OPERAND:
546 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
547 case EXCEPTION_FLT_INEXACT_RESULT:
548 case EXCEPTION_FLT_INVALID_OPERATION:
549 case EXCEPTION_FLT_OVERFLOW:
550 case EXCEPTION_FLT_STACK_CHECK:
551 case EXCEPTION_FLT_UNDERFLOW:
552 gdbctx->last_sig = SIGFPE;
553 ret = TRUE;
554 break;
555 case EXCEPTION_INT_DIVIDE_BY_ZERO:
556 case EXCEPTION_INT_OVERFLOW:
557 gdbctx->last_sig = SIGFPE;
558 ret = TRUE;
559 break;
560 case EXCEPTION_ILLEGAL_INSTRUCTION:
561 gdbctx->last_sig = SIGILL;
562 ret = TRUE;
563 break;
564 case CONTROL_C_EXIT:
565 gdbctx->last_sig = SIGINT;
566 ret = TRUE;
567 break;
568 case STATUS_POSSIBLE_DEADLOCK:
569 gdbctx->last_sig = SIGALRM;
570 ret = TRUE;
571 /* FIXME: we could also add here a O packet with additional information */
572 break;
573 default:
574 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
575 fprintf(stderr, "Unhandled exception code %08lx\n", rec->ExceptionCode);
576 gdbctx->last_sig = SIGABRT;
577 ret = TRUE;
578 break;
580 return ret;
583 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
585 char buffer[256];
587 DEBUG_CurrThread = DEBUG_GetThread(gdbctx->process, de->dwThreadId);
589 switch (de->dwDebugEventCode)
591 case CREATE_PROCESS_DEBUG_EVENT:
592 DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
593 de->u.CreateProcessInfo.hProcess,
594 de->u.CreateProcessInfo.lpImageName,
595 de->u.CreateProcessInfo.fUnicode);
597 /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
598 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
599 fprintf(stderr, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
600 de->dwProcessId, de->dwThreadId,
601 buffer, de->u.CreateProcessInfo.lpImageName,
602 (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
603 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
604 de->u.CreateProcessInfo.nDebugInfoSize);
606 gdbctx->process = DEBUG_AddProcess(de->dwProcessId,
607 de->u.CreateProcessInfo.hProcess,
608 buffer);
609 /* de->u.CreateProcessInfo.lpStartAddress; */
611 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
612 fprintf(stderr, "%08lx:%08lx: create thread I @%08lx\n",
613 de->dwProcessId, de->dwThreadId,
614 (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
616 assert(DEBUG_CurrThread == NULL); /* shouldn't be there */
617 DEBUG_AddThread(gdbctx->process, de->dwThreadId,
618 de->u.CreateProcessInfo.hThread,
619 de->u.CreateProcessInfo.lpStartAddress,
620 de->u.CreateProcessInfo.lpThreadLocalBase);
621 break;
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 de->u.LoadDll.fUnicode);
630 /* FIXME unicode: de->u.LoadDll.fUnicode */
631 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
632 fprintf(stderr, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
633 de->dwProcessId, de->dwThreadId,
634 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
635 de->u.LoadDll.dwDebugInfoFileOffset,
636 de->u.LoadDll.nDebugInfoSize);
637 #if 0
638 _strupr(buffer);
639 DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, de->u.LoadDll.lpBaseOfDll);
640 DEBUG_CheckDelayedBP();
641 if (DBG_IVAR(BreakOnDllLoad))
643 DEBUG_Printf("Stopping on DLL %s loading at %08lx\n",
644 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
645 DEBUG_Parser();
647 #endif
648 break;
650 case UNLOAD_DLL_DEBUG_EVENT:
651 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
652 fprintf(stderr, "%08lx:%08lx: unload DLL @%08lx\n",
653 de->dwProcessId, de->dwThreadId, (unsigned long)de->u.UnloadDll.lpBaseOfDll);
654 break;
656 case EXCEPTION_DEBUG_EVENT:
657 assert(DEBUG_CurrThread);
658 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
659 fprintf(stderr, "%08lx:%08lx: exception code=%08lx\n",
660 de->dwProcessId, de->dwThreadId,
661 de->u.Exception.ExceptionRecord.ExceptionCode);
663 if (fetch_context(gdbctx, DEBUG_CurrThread->handle, &gdbctx->context))
665 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
667 break;
669 case CREATE_THREAD_DEBUG_EVENT:
670 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
671 fprintf(stderr, "%08lx:%08lx: create thread D @%08lx\n",
672 de->dwProcessId, de->dwThreadId, (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
674 DEBUG_AddThread(gdbctx->process,
675 de->dwThreadId,
676 de->u.CreateThread.hThread,
677 de->u.CreateThread.lpStartAddress,
678 de->u.CreateThread.lpThreadLocalBase);
679 break;
681 case EXIT_THREAD_DEBUG_EVENT:
682 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
683 fprintf(stderr, "%08lx:%08lx: exit thread (%ld)\n",
684 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
686 assert(DEBUG_CurrThread);
687 if (DEBUG_CurrThread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
688 if (DEBUG_CurrThread == gdbctx->other_thread) gdbctx->other_thread = NULL;
689 DEBUG_DelThread(DEBUG_CurrThread);
690 break;
692 case EXIT_PROCESS_DEBUG_EVENT:
693 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
694 fprintf(stderr, "%08lx:%08lx: exit process (%ld)\n",
695 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
697 DEBUG_DelProcess(gdbctx->process);
698 gdbctx->process = NULL;
699 /* now signal gdb that we're done */
700 gdbctx->last_sig = SIGTERM;
701 gdbctx->in_trap = TRUE;
702 break;
704 case OUTPUT_DEBUG_STRING_EVENT:
705 assert(DEBUG_CurrThread);
706 DEBUG_ProcessGetString(buffer, sizeof(buffer),
707 gdbctx->process->handle,
708 de->u.DebugString.lpDebugStringData);
709 /* FIXME unicode de->u.DebugString.fUnicode ? */
710 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
711 fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n",
712 de->dwProcessId, de->dwThreadId, buffer);
713 break;
715 case RIP_EVENT:
716 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
717 fprintf(stderr, "%08lx:%08lx: rip error=%ld type=%ld\n",
718 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
719 de->u.RipInfo.dwType);
720 break;
722 default:
723 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
724 fprintf(stderr, "%08lx:%08lx: unknown event (%ld)\n",
725 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
729 static void resume_debuggee(struct gdb_context* gdbctx, unsigned long cont)
731 if (DEBUG_CurrThread)
733 if (!SetThreadContext(DEBUG_CurrThread->handle, &gdbctx->context))
734 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
735 fprintf(stderr, "Cannot set context on thread %lu\n", DEBUG_CurrThread->tid);
736 if (!ContinueDebugEvent(gdbctx->process->pid, DEBUG_CurrThread->tid, cont))
737 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
738 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
739 DEBUG_CurrThread->tid, cont);
741 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
742 fprintf(stderr, "Cannot find last thread (%lu)\n", DEBUG_CurrThread->tid);
745 static void wait_for_debuggee(struct gdb_context* gdbctx)
747 DEBUG_EVENT de;
749 gdbctx->in_trap = FALSE;
750 while (WaitForDebugEvent(&de, INFINITE))
752 handle_debug_event(gdbctx, &de);
753 assert(!gdbctx->process ||
754 gdbctx->process->pid == 0 ||
755 de.dwProcessId == gdbctx->process->pid);
756 assert(!DEBUG_CurrThread || de.dwThreadId == DEBUG_CurrThread->tid);
757 if (gdbctx->in_trap) break;
758 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
762 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
764 cpu_leave_stepping(gdbctx);
765 resume_debuggee(gdbctx, DBG_CONTINUE);
766 if (!kill)
767 DebugActiveProcessStop(gdbctx->process->pid);
768 DEBUG_DelProcess(gdbctx->process);
769 gdbctx->process = NULL;
772 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
774 unsigned long status;
776 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
778 strcpy(buffer, "Unknown process");
779 return;
781 if (status == STILL_ACTIVE)
783 strcpy(buffer, "Running");
785 else
786 snprintf(buffer, len, "Terminated (%lu)", status);
788 switch (GetPriorityClass(gdbctx->process->handle))
790 case 0: break;
791 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
792 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
793 #endif
794 #ifdef BELOW_NORMAL_PRIORITY_CLASS
795 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
796 #endif
797 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
798 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
799 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
800 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
802 strcat(buffer, "\n");
805 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
806 char* buffer, size_t len)
808 DBG_THREAD* thd;
809 unsigned long status;
810 int prio;
812 /* FIXME: use the size of buffer */
813 thd = DEBUG_GetThread(gdbctx->process, tid);
814 if (thd == NULL)
816 strcpy(buffer, "No information");
817 return;
819 if (GetExitCodeThread(thd->handle, &status))
821 if (status == STILL_ACTIVE)
823 /* FIXME: this is a bit brutal... some nicer way shall be found */
824 switch (status = SuspendThread(thd->handle))
826 case -1: break;
827 case 0: strcpy(buffer, "Running"); break;
828 default: snprintf(buffer, len, "Suspended (%lu)", status - 1);
830 ResumeThread(thd->handle);
832 else
833 snprintf(buffer, len, "Terminated (exit code = %lu)", status);
835 else
837 strcpy(buffer, "Unknown threadID");
839 switch (prio = GetThreadPriority(thd->handle))
841 case THREAD_PRIORITY_ERROR_RETURN: break;
842 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
843 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
844 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
845 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
846 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
847 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
848 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
849 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
851 assert(strlen(buffer) < len);
854 /* =============================================== *
855 * P A C K E T U T I L S *
856 * =============================================== *
859 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
860 packet_last_f = 0x80};
862 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
864 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
866 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
867 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
871 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
873 packet_reply_grow(gdbctx, len * 2);
874 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
875 gdbctx->out_len += len * 2;
878 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
880 packet_reply_hex_to(gdbctx, src, strlen(src));
883 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
885 int i, shift;
887 shift = (len - 1) * 8;
888 packet_reply_grow(gdbctx, len * 2);
889 for (i = 0; i < len; i++, shift -= 8)
891 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
892 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
896 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
898 packet_reply_grow(gdbctx, len);
899 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
900 gdbctx->out_len += len;
903 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
905 packet_reply_add(gdbctx, str, strlen(str));
908 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
910 packet_reply_add(gdbctx, &ch, 1);
913 static void packet_reply_open(struct gdb_context* gdbctx)
915 assert(gdbctx->out_curr_packet == -1);
916 packet_reply_catc(gdbctx, '$');
917 gdbctx->out_curr_packet = gdbctx->out_len;
920 static void packet_reply_close(struct gdb_context* gdbctx)
922 unsigned char cksum;
923 int plen;
925 plen = gdbctx->out_len - gdbctx->out_curr_packet;
926 packet_reply_catc(gdbctx, '#');
927 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
928 packet_reply_hex_to(gdbctx, &cksum, 1);
929 if (gdbctx->trace & GDBPXY_TRC_PACKET)
930 fprintf(stderr, "Reply : %*.*s\n",
931 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
932 gdbctx->out_curr_packet = -1;
935 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
937 packet_reply_open(gdbctx);
939 if (len == -1) len = strlen(packet);
940 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
942 packet_reply_add(gdbctx, packet, len);
944 packet_reply_close(gdbctx);
946 return packet_done;
949 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
951 packet_reply_open(gdbctx);
953 packet_reply_add(gdbctx, "E", 1);
954 packet_reply_val(gdbctx, error, 1);
956 packet_reply_close(gdbctx);
958 return packet_done;
961 /* =============================================== *
962 * P A C K E T H A N D L E R S *
963 * =============================================== *
966 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
968 enum packet_return ret = packet_done;
970 packet_reply_open(gdbctx);
972 if (gdbctx->process != NULL)
974 unsigned char sig;
975 unsigned i;
977 packet_reply_catc(gdbctx, 'T');
978 sig = gdbctx->last_sig;
979 packet_reply_val(gdbctx, sig, 1);
980 packet_reply_add(gdbctx, "thread:", 7);
981 packet_reply_val(gdbctx, DEBUG_CurrThread->tid, 4);
982 packet_reply_catc(gdbctx, ';');
984 for (i = 0; i < cpu_num_regs; i++)
986 /* FIXME: this call will also grow the buffer...
987 * unneeded, but not harmful
989 packet_reply_val(gdbctx, i, 1);
990 packet_reply_catc(gdbctx, ':');
991 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
992 packet_reply_catc(gdbctx, ';');
995 else
997 /* Try to put an exit code
998 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
999 * just indicate the end of process and exit */
1000 packet_reply_add(gdbctx, "W00", 3);
1001 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1004 packet_reply_close(gdbctx);
1006 return ret;
1009 #if 0
1010 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1012 gdbctx->extended = 1;
1013 return packet_ok;
1015 #endif
1017 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1019 assert(gdbctx->in_packet_len == 0);
1020 return packet_reply_status(gdbctx);
1023 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1025 /* FIXME: add support for address in packet */
1026 assert(gdbctx->in_packet_len == 0);
1027 if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
1028 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1029 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
1030 gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
1031 resume_debuggee(gdbctx, DBG_CONTINUE);
1032 wait_for_debuggee(gdbctx);
1033 return packet_reply_status(gdbctx);
1036 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1038 unsigned char sig;
1040 /* FIXME: add support for address in packet */
1041 assert(gdbctx->in_packet_len == 2);
1042 if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
1043 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1044 fprintf(stderr, "NIY: cont/sig on %lu, while last thread is %lu\n",
1045 gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
1046 hex_from(&sig, gdbctx->in_packet, 1);
1047 /* cannot change signals on the fly */
1048 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1049 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1050 if (sig != gdbctx->last_sig)
1051 return packet_error;
1052 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1053 wait_for_debuggee(gdbctx);
1054 return packet_reply_status(gdbctx);
1057 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1059 detach_debuggee(gdbctx, FALSE);
1060 return packet_ok | packet_last_f;
1063 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1065 int i;
1066 CONTEXT ctx;
1067 CONTEXT* pctx = &gdbctx->context;
1069 assert(gdbctx->in_trap);
1071 if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
1073 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1074 return packet_error;
1077 packet_reply_open(gdbctx);
1078 for (i = 0; i < cpu_num_regs; i++)
1080 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1082 packet_reply_close(gdbctx);
1083 return packet_done;
1086 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1088 unsigned i;
1089 CONTEXT ctx;
1090 CONTEXT* pctx = &gdbctx->context;
1092 assert(gdbctx->in_trap);
1093 if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
1095 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1096 return packet_error;
1098 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1100 for (i = 0; i < cpu_num_regs; i++)
1101 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1102 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1104 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1105 fprintf(stderr, "Cannot set context on thread %lu\n", gdbctx->other_thread->tid);
1106 return packet_error;
1108 return packet_ok;
1111 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1113 detach_debuggee(gdbctx, TRUE);
1114 #if 0
1115 if (!gdbctx->extended)
1116 /* dunno whether GDB cares or not */
1117 #endif
1118 wait(NULL);
1119 exit(0);
1120 /* assume we can't really answer something here */
1121 /* return packet_done; */
1124 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1126 char* end;
1127 unsigned thread;
1129 switch (gdbctx->in_packet[0])
1131 case 'c':
1132 case 'g':
1133 if (gdbctx->in_packet[1] == '-')
1134 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1135 else
1136 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1137 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1139 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1140 fprintf(stderr, "Cannot get threadid %*.*s\n",
1141 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1142 gdbctx->in_packet + 1);
1143 return packet_error;
1145 if (gdbctx->in_packet[0] == 'c')
1146 gdbctx->exec_thread = DEBUG_GetThread(gdbctx->process, thread);
1147 else
1148 gdbctx->other_thread = DEBUG_GetThread(gdbctx->process, thread);
1149 return packet_ok;
1150 default:
1151 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1152 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1153 return packet_error;
1157 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1159 char *addr;
1160 size_t len, blk_len, nread;
1161 char buffer[32];
1162 unsigned long r = 0;
1164 assert(gdbctx->in_trap);
1165 /* FIXME:check in_packet_len for reading %p,%x */
1166 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1167 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1168 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1169 for (nread = 0; nread < len > 0; nread += r, addr += r)
1171 blk_len = min(sizeof(buffer), len - nread);
1172 if (!ReadProcessMemory(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1173 r == 0)
1175 /* fail at first address, return error */
1176 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1177 /* something has already been read, return partial information */
1178 break;
1180 if (nread == 0) packet_reply_open(gdbctx);
1181 packet_reply_hex_to(gdbctx, buffer, r);
1183 packet_reply_close(gdbctx);
1184 return packet_done;
1187 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1189 char* addr;
1190 size_t len, blk_len;
1191 char* ptr;
1192 char buffer[32];
1193 unsigned long w;
1195 assert(gdbctx->in_trap);
1196 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1197 if (ptr == NULL)
1199 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1200 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1201 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1202 return packet_error;
1204 *ptr++ = '\0';
1206 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1208 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1209 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1210 return packet_error;
1212 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1214 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1215 fprintf(stderr, "Wrong sizes %u <> %u\n",
1216 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1217 return packet_error;
1219 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1220 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1221 while (len > 0)
1223 blk_len = min(sizeof(buffer), len);
1224 hex_from(buffer, ptr, blk_len);
1226 BOOL ret;
1228 ret = WriteProcessMemory(gdbctx->process->handle, addr, buffer, blk_len, &w);
1229 if (!ret || w != blk_len)
1230 break;
1232 addr += w;
1233 len -= w;
1234 ptr += w;
1236 return packet_ok; /* FIXME: error while writing ? */
1239 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1241 unsigned reg;
1242 char* ptr;
1243 char* end;
1244 CONTEXT ctx;
1245 CONTEXT* pctx = &gdbctx->context;
1247 assert(gdbctx->in_trap);
1249 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1250 *ptr++ = '\0';
1251 reg = strtoul(gdbctx->in_packet, &end, 16);
1252 if (end == NULL || reg > cpu_num_regs)
1254 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1255 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1256 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1257 * it wouldn't matter too much, and it fakes our support for all regs
1259 return (end == NULL) ? packet_error : packet_ok;
1261 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1263 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1264 fprintf(stderr, "Wrong sizes %u <> %u\n",
1265 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1266 return packet_error;
1268 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1269 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1270 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1271 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1273 if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
1275 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1276 return packet_error;
1279 hex_from(cpu_register(pctx, reg), ptr, 4);
1280 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1282 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1283 fprintf(stderr, "Cannot set context for thread %lu\n", gdbctx->other_thread->tid);
1284 return packet_error;
1287 return packet_ok;
1290 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1292 char buffer[128];
1293 char clsName[128];
1294 char wndName[128];
1295 HWND child;
1297 do {
1298 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1299 strcpy(clsName, "-- Unknown --");
1300 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1301 strcpy(wndName, "-- Empty --");
1303 packet_reply_open(gdbctx);
1304 packet_reply_catc(gdbctx, 'O');
1305 snprintf(buffer, sizeof(buffer),
1306 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1307 indent, "", (UINT)hWnd, 13 - indent, "",
1308 clsName, GetWindowLong(hWnd, GWL_STYLE),
1309 GetWindowLong(hWnd, GWL_WNDPROC), wndName);
1310 packet_reply_hex_to_str(gdbctx, buffer);
1311 packet_reply_close(gdbctx);
1313 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1314 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1315 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1318 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1320 char buffer[128];
1322 /* we do the output in several 'O' packets, with the last one being just OK for
1323 * marking the end of the output */
1324 packet_reply_open(gdbctx);
1325 packet_reply_catc(gdbctx, 'O');
1326 snprintf(buffer, sizeof(buffer),
1327 "%-16.16s %-17.17s %-8.8s %s\n",
1328 "hwnd", "Class Name", " Style", " WndProc Text");
1329 packet_reply_hex_to_str(gdbctx, buffer);
1330 packet_reply_close(gdbctx);
1332 /* FIXME: could also add a pmt to this command in str... */
1333 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1334 packet_reply(gdbctx, "OK", 2);
1337 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1339 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1340 char buffer[128];
1341 char deco;
1342 PROCESSENTRY32 entry;
1343 BOOL ok;
1345 if (snap == INVALID_HANDLE_VALUE)
1346 return;
1348 entry.dwSize = sizeof(entry);
1349 ok = Process32First( snap, &entry );
1351 /* we do the output in several 'O' packets, with the last one being just OK for
1352 * marking the end of the output */
1354 packet_reply_open(gdbctx);
1355 packet_reply_catc(gdbctx, 'O');
1356 snprintf(buffer, sizeof(buffer),
1357 " %-8.8s %-8.8s %-8.8s %s\n",
1358 "pid", "threads", "parent", "executable" );
1359 packet_reply_hex_to_str(gdbctx, buffer);
1360 packet_reply_close(gdbctx);
1362 while (ok)
1364 deco = ' ';
1365 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1366 packet_reply_open(gdbctx);
1367 packet_reply_catc(gdbctx, 'O');
1368 snprintf(buffer, sizeof(buffer),
1369 "%c%08lx %-8ld %08lx '%s'\n",
1370 deco, entry.th32ProcessID, entry.cntThreads,
1371 entry.th32ParentProcessID, entry.szExeFile);
1372 packet_reply_hex_to_str(gdbctx, buffer);
1373 packet_reply_close(gdbctx);
1374 ok = Process32Next(snap, &entry);
1376 CloseHandle(snap);
1377 packet_reply(gdbctx, "OK", 2);
1380 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1382 MEMORY_BASIC_INFORMATION mbi;
1383 char* addr = 0;
1384 const char* state;
1385 const char* type;
1386 char prot[3+1];
1387 char buffer[128];
1389 /* we do the output in several 'O' packets, with the last one being just OK for
1390 * marking the end of the output */
1391 packet_reply_open(gdbctx);
1392 packet_reply_catc(gdbctx, 'O');
1393 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1394 packet_reply_close(gdbctx);
1396 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1398 switch (mbi.State)
1400 case MEM_COMMIT: state = "commit "; break;
1401 case MEM_FREE: state = "free "; break;
1402 case MEM_RESERVE: state = "reserve"; break;
1403 default: state = "??? "; break;
1405 if (mbi.State != MEM_FREE)
1407 switch (mbi.Type)
1409 case MEM_IMAGE: type = "image "; break;
1410 case MEM_MAPPED: type = "mapped "; break;
1411 case MEM_PRIVATE: type = "private"; break;
1412 case 0: type = " "; break;
1413 default: type = "??? "; break;
1415 memset(prot, ' ' , sizeof(prot)-1);
1416 prot[sizeof(prot)-1] = '\0';
1417 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1418 prot[0] = 'R';
1419 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1420 prot[1] = 'W';
1421 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1422 prot[1] = 'C';
1423 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1424 prot[2] = 'X';
1426 else
1428 type = "";
1429 prot[0] = '\0';
1431 packet_reply_open(gdbctx);
1432 snprintf(buffer, sizeof(buffer),
1433 "%08lx %08lx %s %s %s\n",
1434 (DWORD)addr, mbi.RegionSize, state, type, prot);
1435 packet_reply_catc(gdbctx, 'O');
1436 packet_reply_hex_to_str(gdbctx, buffer);
1437 packet_reply_close(gdbctx);
1439 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1440 break;
1441 addr += mbi.RegionSize;
1443 packet_reply(gdbctx, "OK", 2);
1446 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1447 int len, const char* str)
1449 char buffer[128];
1451 if (len == 0)
1453 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1455 else if (len >= 2 && str[0] == '=')
1457 unsigned val = atoi(&str[1]);
1458 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1459 gdbctx->trace = val;
1461 else
1463 /* FIXME: ugly but can use error packet here */
1464 packet_reply_cat(gdbctx, "E00");
1465 return;
1467 packet_reply_open(gdbctx);
1468 packet_reply_hex_to_str(gdbctx, buffer);
1469 packet_reply_close(gdbctx);
1472 #ifdef __i386__
1473 static void packet_query_monitor_linear(struct gdb_context* gdbctx,
1474 int len, const char* str)
1476 unsigned seg, ofs;
1477 LDT_ENTRY le;
1478 unsigned linear;
1479 char buffer[32];
1481 while (len > 0 && (*str == ' ' || *str == '\t'))
1483 str++; len--;
1485 /* FIXME: do a better scanning (allow both decimal and hex numbers) */
1486 if (!len || sscanf(str, "%x:%x", &seg, &ofs) != 2)
1488 packet_reply_error(gdbctx, 0);
1489 return;
1492 /* V86 mode ? */
1493 if (gdbctx->context.EFlags & 0x00020000) linear = (LOWORD(seg) << 4) + ofs;
1494 /* linux system selector ? */
1495 else if (!(seg & 4) || ((seg >> 3) < 17)) linear = ofs;
1496 /* standard selector */
1497 else if (GetThreadSelectorEntry(gdbctx->process->threads->handle, seg, &le))
1498 linear = (le.HighWord.Bits.BaseHi << 24) + (le.HighWord.Bits.BaseMid << 16) +
1499 le.BaseLow + ofs;
1500 /* error */
1501 else linear = 0;
1502 snprintf(buffer, sizeof(buffer), "0x%x", linear);
1503 packet_reply_open(gdbctx);
1504 packet_reply_hex_to_str(gdbctx, buffer);
1505 packet_reply_close(gdbctx);
1507 #endif
1509 struct query_detail
1511 int with_arg;
1512 const char* name;
1513 size_t len;
1514 void (*handler)(struct gdb_context*, int, const char*);
1515 } query_details[] =
1517 {0, "wnd", 3, packet_query_monitor_wnd},
1518 {0, "window", 6, packet_query_monitor_wnd},
1519 {0, "proc", 4, packet_query_monitor_process},
1520 {0, "process", 7, packet_query_monitor_process},
1521 {0, "mem", 3, packet_query_monitor_mem},
1522 {1, "trace", 5, packet_query_monitor_trace},
1523 #ifdef __i386__
1524 {1, "linear", 6, packet_query_monitor_linear},
1525 #endif
1526 {0, NULL, 0, NULL},
1529 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1530 const char* hxcmd, size_t len)
1532 char buffer[128];
1533 struct query_detail* qd;
1535 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1536 len /= 2;
1537 hex_from(buffer, hxcmd, len);
1539 for (qd = &query_details[0]; qd->name != NULL; qd++)
1541 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1542 if (!qd->with_arg && len != qd->len) continue;
1544 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1545 return packet_done;
1547 return packet_reply_error(gdbctx, EINVAL);
1550 static enum packet_return packet_query(struct gdb_context* gdbctx)
1552 switch (gdbctx->in_packet[0])
1554 case 'f':
1555 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1557 DBG_THREAD* thd;
1559 packet_reply_open(gdbctx);
1560 packet_reply_add(gdbctx, "m", 1);
1561 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1563 packet_reply_val(gdbctx, thd->tid, 4);
1564 if (thd->next != NULL)
1565 packet_reply_add(gdbctx, ",", 1);
1567 packet_reply_close(gdbctx);
1568 return packet_done;
1570 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1572 char result[128];
1574 packet_reply_open(gdbctx);
1575 packet_reply_catc(gdbctx, 'O');
1576 get_process_info(gdbctx, result, sizeof(result));
1577 packet_reply_hex_to_str(gdbctx, result);
1578 packet_reply_close(gdbctx);
1579 return packet_done;
1581 break;
1582 case 's':
1583 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1585 packet_reply(gdbctx, "l", 1);
1586 return packet_done;
1588 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1590 packet_reply(gdbctx, "l", 1);
1591 return packet_done;
1593 break;
1594 case 'C':
1595 if (gdbctx->in_packet_len == 1)
1597 DBG_THREAD* thd;
1598 /* FIXME: doc says 16 bit val ??? */
1599 /* grab first created thread, aka last in list */
1600 assert(gdbctx->process && gdbctx->process->threads);
1601 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1602 packet_reply_open(gdbctx);
1603 packet_reply_add(gdbctx, "QC", 2);
1604 packet_reply_val(gdbctx, thd->tid, 4);
1605 packet_reply_close(gdbctx);
1606 return packet_done;
1608 break;
1609 case 'O':
1610 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1612 char buf[64];
1614 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1615 gdbctx->wine_segs[2] == 0)
1616 return packet_error;
1617 snprintf(buf, sizeof(buf),
1618 "Text=%08lx;Data=%08lx;Bss=%08lx",
1619 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1620 gdbctx->wine_segs[2]);
1621 return packet_reply(gdbctx, buf, -1);
1623 break;
1624 case 'R':
1625 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1627 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1628 gdbctx->in_packet_len - 5);
1630 break;
1631 case 'S':
1632 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1633 return packet_ok;
1634 break;
1635 case 'T':
1636 if (gdbctx->in_packet_len > 15 &&
1637 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1638 gdbctx->in_packet[15] == ',')
1640 unsigned tid;
1641 char* end;
1642 char result[128];
1644 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1645 if (end == NULL) break;
1646 get_thread_info(gdbctx, tid, result, sizeof(result));
1647 packet_reply_open(gdbctx);
1648 packet_reply_hex_to_str(gdbctx, result);
1649 packet_reply_close(gdbctx);
1650 return packet_done;
1652 break;
1654 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1655 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1656 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1657 return packet_error;
1660 static enum packet_return packet_step(struct gdb_context* gdbctx)
1662 /* FIXME: add support for address in packet */
1663 assert(gdbctx->in_packet_len == 0);
1664 if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
1665 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1666 fprintf(stderr, "NIY: step on %lu, while last thread is %lu\n",
1667 gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
1668 if (!cpu_enter_stepping(gdbctx)) return packet_error;
1669 resume_debuggee(gdbctx, DBG_CONTINUE);
1670 wait_for_debuggee(gdbctx);
1671 if (!cpu_leave_stepping(gdbctx)) return packet_error;
1672 return packet_reply_status(gdbctx);
1675 #if 0
1676 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1678 unsigned char sig;
1680 /* FIXME: add support for address in packet */
1681 assert(gdbctx->in_packet_len == 2);
1682 if (DEBUG_CurrThread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1683 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1684 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1685 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1686 hex_from(&sig, gdbctx->in_packet, 1);
1687 /* cannot change signals on the fly */
1688 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1689 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1690 if (sig != gdbctx->last_sig)
1691 return packet_error;
1692 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1693 wait_for_debuggee(gdbctx);
1694 return packet_reply_status(gdbctx);
1696 #endif
1698 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1700 char* end;
1701 unsigned tid;
1703 tid = strtol(gdbctx->in_packet, &end, 16);
1704 if (tid == -1 || tid == 0)
1705 return packet_reply_error(gdbctx, EINVAL);
1706 if (DEBUG_GetThread(gdbctx->process, tid) != NULL)
1707 return packet_ok;
1708 return packet_reply_error(gdbctx, ESRCH);
1711 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1713 void* addr;
1714 unsigned len;
1715 struct gdb_ctx_Xpoint* xpt;
1717 /* FIXME: check packet_len */
1718 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1719 gdbctx->in_packet[1] != ',' ||
1720 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1721 return packet_error;
1722 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1723 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1724 addr, len, gdbctx->in_packet[0]);
1725 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1727 if (xpt->addr == addr && xpt->type == gdbctx->in_packet[0])
1729 switch (cpu_remove_Xpoint(gdbctx, xpt, len))
1731 case 1: xpt->type = -1; return packet_ok;
1732 case 0: return packet_error;
1733 case -1: return packet_done;
1734 default: assert(0);
1738 return packet_error;
1741 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1743 void* addr;
1744 unsigned len;
1745 struct gdb_ctx_Xpoint* xpt;
1747 /* FIXME: check packet_len */
1748 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1749 gdbctx->in_packet[1] != ',' ||
1750 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1751 return packet_error;
1752 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1753 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1754 addr, len, gdbctx->in_packet[0]);
1755 /* because of packet command handling, this should be made idempotent */
1756 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1758 if (xpt->addr == addr && xpt->type == gdbctx->in_packet[0])
1759 return packet_ok; /* nothing to do */
1761 /* really set the Xpoint */
1762 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1764 if (xpt->type == -1)
1766 xpt->addr = addr;
1767 xpt->type = gdbctx->in_packet[0];
1768 switch (cpu_insert_Xpoint(gdbctx, xpt, len))
1770 case 1: return packet_ok;
1771 case 0: return packet_error;
1772 case -1: return packet_done;
1773 default: assert(0);
1777 /* no more entries... eech */
1778 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1779 return packet_error;
1782 /* =============================================== *
1783 * P A C K E T I N F R A S T R U C T U R E *
1784 * =============================================== *
1787 struct packet_entry
1789 char key;
1790 enum packet_return (*handler)(struct gdb_context* gdbctx);
1793 static struct packet_entry packet_entries[] =
1795 /* {'!', packet_extended}, */
1796 {'?', packet_last_signal},
1797 {'c', packet_continue},
1798 {'C', packet_continue_signal},
1799 {'D', packet_detach},
1800 {'g', packet_read_registers},
1801 {'G', packet_write_registers},
1802 {'k', packet_kill},
1803 {'H', packet_thread},
1804 {'m', packet_read_memory},
1805 {'M', packet_write_memory},
1806 /* {'p', packet_read_register}, doesn't seem needed */
1807 {'P', packet_write_register},
1808 {'q', packet_query},
1809 {'s', packet_step},
1810 /*{'S', packet_step_signal}, hard(er) to implement */
1811 {'T', packet_thread_alive},
1812 {'z', packet_remove_breakpoint},
1813 {'Z', packet_set_breakpoint},
1816 static BOOL extract_packets(struct gdb_context* gdbctx)
1818 char* end;
1819 int plen;
1820 unsigned char in_cksum, loc_cksum;
1821 char* ptr;
1822 enum packet_return ret = packet_error;
1823 int num_packet = 0;
1825 while ((ret & packet_last_f) == 0)
1827 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1828 fprintf(stderr, "In-buf: %*.*s\n",
1829 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1830 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1831 if (ptr == NULL) return FALSE;
1832 if (ptr != gdbctx->in_buf)
1834 int glen = ptr - gdbctx->in_buf; /* garbage len */
1835 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1836 fprintf(stderr, "Removing garbage: %*.*s\n",
1837 glen, glen, gdbctx->in_buf);
1838 gdbctx->in_len -= glen;
1839 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1841 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1842 if (end == NULL) return FALSE;
1843 /* no checksum yet */
1844 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1845 plen = end - gdbctx->in_buf - 1;
1846 hex_from(&in_cksum, end + 1, 1);
1847 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1848 if (loc_cksum == in_cksum)
1850 if (num_packet == 0) {
1851 int i;
1853 ret = packet_error;
1855 write(gdbctx->sock, "+", 1);
1856 assert(plen);
1858 /* FIXME: should use bsearch if packet_entries was sorted */
1859 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1861 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1863 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1865 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1866 fprintf(stderr, "Unknown packet request %*.*s\n",
1867 plen, plen, &gdbctx->in_buf[1]);
1869 else
1871 gdbctx->in_packet = gdbctx->in_buf + 2;
1872 gdbctx->in_packet_len = plen - 1;
1873 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1874 fprintf(stderr, "Packet: %c%*.*s\n",
1875 gdbctx->in_buf[1],
1876 gdbctx->in_packet_len, gdbctx->in_packet_len,
1877 gdbctx->in_packet);
1878 ret = (packet_entries[i].handler)(gdbctx);
1880 switch (ret & ~packet_last_f)
1882 case packet_error: packet_reply(gdbctx, "", 0); break;
1883 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
1884 case packet_done: break;
1886 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1887 fprintf(stderr, "Reply-full: %*.*s\n",
1888 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
1889 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
1890 assert(i == gdbctx->out_len);
1891 /* if this fails, we'll have to use POLLOUT...
1893 gdbctx->out_len = 0;
1894 num_packet++;
1896 else
1898 /* FIXME: if we have in our input buffer more than one packet,
1899 * it's very likely that we took too long to answer to a given packet
1900 * and gdb is sending us again the same packet
1901 * We simply drop the second packet. This will lower the risk of error,
1902 * but there's still some race conditions here
1903 * A better fix (yet not perfect) would be to have two threads:
1904 * - one managing the packets for gdb
1905 * - the second one managing the commands...
1906 * This would allow us also the reply with the '+' character (Ack of
1907 * the command) way sooner than what we do now
1909 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1910 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
1913 else
1915 write(gdbctx->sock, "+", 1);
1916 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1917 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
1919 gdbctx->in_len -= plen + 4;
1920 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
1922 return TRUE;
1925 static int fetch_data(struct gdb_context* gdbctx)
1927 int len, in_len = gdbctx->in_len;
1929 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
1930 for (;;)
1932 #define STEP 128
1933 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
1934 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
1935 #undef STEP
1936 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1937 fprintf(stderr, "%d %d %*.*s\n",
1938 gdbctx->in_len, gdbctx->in_buf_alloc,
1939 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1940 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
1941 if (len <= 0) break;
1942 gdbctx->in_len += len;
1943 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
1944 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
1946 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1947 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
1948 return gdbctx->in_len - in_len;
1951 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
1953 int sock;
1954 struct sockaddr_in s_addrs;
1955 int s_len = sizeof(s_addrs);
1956 struct pollfd pollfd;
1957 char wine_path[MAX_PATH];
1958 struct elf_info elf_info;
1960 /* step 1: create socket for gdb connection request */
1961 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1963 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1964 fprintf(stderr, "Can't create socket");
1965 return FALSE;
1968 if (listen(sock, 1) == -1 ||
1969 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
1970 return FALSE;
1972 /* step 2: find out wine executable location (as a Unix filename) */
1973 elf_info.flags = ELF_INFO_PATH | ELF_INFO_SEGMENTS;
1974 elf_info.elf_path = wine_path;
1975 elf_info.elf_path_len = sizeof(wine_path);
1976 if (DEBUG_ReadWineLoaderDbgInfo(de->u.CreateProcessInfo.hProcess, &elf_info) == DIL_ERROR)
1977 return FALSE;
1978 gdbctx->wine_segs[0] = elf_info.segments[0];
1979 gdbctx->wine_segs[1] = elf_info.segments[1];
1980 gdbctx->wine_segs[2] = elf_info.segments[2];
1982 fprintf(stderr, "Using wine_path: %s\n", wine_path);
1984 /* step 3: fire up gdb (if requested) */
1985 if (flags & 1)
1986 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
1987 else
1988 switch (fork())
1990 case -1: /* error in parent... */
1991 fprintf(stderr, "Cannot create gdb\n");
1992 return FALSE;
1993 break;
1994 default: /* in parent... success */
1995 break;
1996 case 0: /* in child... and alive */
1998 char buf[MAX_PATH];
1999 int fd;
2000 const char* gdb_path;
2001 FILE* f;
2003 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2004 strcpy(buf,"/tmp/winegdb.XXXXXX");
2005 fd = mkstemps(buf,0);
2006 if (fd == -1) return FALSE;
2007 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2008 fprintf(f, "file %s\n", wine_path);
2009 fprintf(f, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2010 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2011 fprintf(f, "set prompt Wine-gdb>\\ \n");
2012 /* gdb 5.1 seems to require it, won't hurt anyway */
2013 fprintf(f, "sharedlibrary\n");
2014 /* tell gdb to delete this file when done handling it... */
2015 fprintf(f, "shell rm -f \"%s\"\n", buf);
2016 fclose(f);
2017 if (flags & 2)
2018 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2019 else
2020 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2021 assert(0); /* never reached */
2022 break;
2024 break;
2027 /* step 4: do the process internal creation */
2028 handle_debug_event(gdbctx, de);
2030 /* step 5: wait for gdb to connect actually */
2031 pollfd.fd = sock;
2032 pollfd.events = POLLIN;
2033 pollfd.revents = 0;
2035 switch (poll(&pollfd, 1, -1))
2037 case 1:
2038 if (pollfd.revents & POLLIN)
2040 int dummy = 1;
2041 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2042 if (gdbctx->sock == -1)
2043 break;
2044 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2045 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2046 /* don't keep our small packets too long: send them ASAP back to GDB
2047 * without this, GDB really crawls
2049 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2051 break;
2052 case 0:
2053 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2054 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2055 return FALSE;
2056 case -1:
2057 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2058 fprintf(stderr, "Poll for cnx failed (error)\n");
2059 return FALSE;
2060 default:
2061 assert(0);
2064 close(sock);
2065 return TRUE;
2068 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2070 DEBUG_EVENT de;
2071 int i;
2073 gdbctx->sock = -1;
2074 gdbctx->in_buf = NULL;
2075 gdbctx->in_buf_alloc = 0;
2076 gdbctx->in_len = 0;
2077 gdbctx->out_buf = NULL;
2078 gdbctx->out_buf_alloc = 0;
2079 gdbctx->out_len = 0;
2080 gdbctx->out_curr_packet = -1;
2082 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2083 gdbctx->last_sig = 0;
2084 gdbctx->in_trap = FALSE;
2085 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2086 gdbctx->process = NULL;
2087 for (i = 0; i < NUM_XPOINT; i++)
2088 gdbctx->Xpoints[i].type = -1;
2090 /* wait for first trap */
2091 while (WaitForDebugEvent(&de, INFINITE))
2093 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2095 /* this should be the first event we get,
2096 * and the only one of this type */
2097 assert(gdbctx->process == NULL && de.dwProcessId == DEBUG_CurrPid);
2098 /*gdbctx->dwProcessId = pid; */
2099 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2100 assert(!gdbctx->in_trap);
2102 else
2104 handle_debug_event(gdbctx, &de);
2105 if (gdbctx->in_trap) break;
2107 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2109 return TRUE;
2112 BOOL DEBUG_GdbRemote(unsigned flags)
2114 struct pollfd pollfd;
2115 struct gdb_context gdbctx;
2116 BOOL doLoop;
2118 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2120 pollfd.fd = gdbctx.sock;
2121 pollfd.events = POLLIN;
2122 pollfd.revents = 0;
2124 switch (poll(&pollfd, 1, -1))
2126 case 1:
2127 /* got something */
2128 if (pollfd.revents & (POLLHUP | POLLERR))
2130 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2131 fprintf(stderr, "Gdb hung up\n");
2132 /* kill also debuggee process - questionnable - */
2133 detach_debuggee(&gdbctx, TRUE);
2134 doLoop = FALSE;
2135 break;
2137 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2139 if (extract_packets(&gdbctx)) doLoop = FALSE;
2141 break;
2142 case 0:
2143 /* timeout, should never happen (infinite timeout) */
2144 break;
2145 case -1:
2146 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2147 fprintf(stderr, "Poll failed\n");
2148 doLoop = FALSE;
2149 break;
2152 wait(NULL);
2153 return 0;