Modify ok("xxx") calls into ok("xxx\n") as is now expected.
[wine/testsucceed.git] / programs / winedbg / gdbproxy.c
blob54254dfb25ca29800e3fd447842c18af87d76fe4
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 #include <unistd.h>
46 #include "windef.h"
47 #include "winbase.h"
48 #include "tlhelp32.h"
50 /* those two are needed only for the SHOWNORMAL flag */
51 #include "wingdi.h"
52 #include "winuser.h"
54 #include "debugger.h"
56 #define GDBPXY_TRC_LOWLEVEL 0x01
57 #define GDBPXY_TRC_PACKET 0x02
58 #define GDBPXY_TRC_COMMAND 0x04
59 #define GDBPXY_TRC_COMMAND_ERROR 0x08
60 #define GDBPXY_TRC_WIN32_EVENT 0x10
61 #define GDBPXY_TRC_WIN32_ERROR 0x20
62 #define GDBPXY_TRC_COMMAND_FIXME 0x80
64 struct gdb_ctx_Xpoint
66 int type; /* -1 means free */
67 void* addr;
68 unsigned long val;
71 struct gdb_context
73 /* gdb information */
74 int sock;
75 /* incoming buffer */
76 char* in_buf;
77 int in_buf_alloc;
78 int in_len;
79 /* split into individual packet */
80 char* in_packet;
81 int in_packet_len;
82 /* outgoing buffer */
83 char* out_buf;
84 int out_buf_alloc;
85 int out_len;
86 int out_curr_packet;
87 /* generic GDB thread information */
88 DBG_THREAD* exec_thread; /* thread used in step & continue */
89 DBG_THREAD* other_thread; /* thread to be used in any other operation */
90 unsigned trace;
91 /* current Win32 trap env */
92 unsigned last_sig;
93 BOOL in_trap;
94 CONTEXT context;
95 /* Win32 information */
96 DBG_PROCESS* process;
97 #define NUM_XPOINT 32
98 struct gdb_ctx_Xpoint Xpoints[NUM_XPOINT];
99 /* Unix environment */
100 unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
103 extern int read_elf_info(const char* filename, unsigned long tab[]);
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);
596 /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
597 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
598 fprintf(stderr, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
599 de->dwProcessId, de->dwThreadId,
600 buffer, de->u.CreateProcessInfo.lpImageName,
601 (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
602 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
603 de->u.CreateProcessInfo.nDebugInfoSize);
605 gdbctx->process = DEBUG_AddProcess(de->dwProcessId,
606 de->u.CreateProcessInfo.hProcess,
607 buffer);
608 /* de->u.CreateProcessInfo.lpStartAddress; */
610 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
611 fprintf(stderr, "%08lx:%08lx: create thread I @%08lx\n",
612 de->dwProcessId, de->dwThreadId,
613 (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
615 assert(DEBUG_CurrThread == NULL); /* shouldn't be there */
616 DEBUG_AddThread(gdbctx->process, de->dwThreadId,
617 de->u.CreateProcessInfo.hThread,
618 de->u.CreateProcessInfo.lpStartAddress,
619 de->u.CreateProcessInfo.lpThreadLocalBase);
620 #if 0
621 DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile,
622 de->u.CreateProcessInfo.lpBaseOfImage);
624 if (buffer[0]) /* we got a process name */
626 DWORD type;
627 if (!GetBinaryTypeA( buffer, &type ))
629 /* not a Windows binary, assume it's a Unix executable then */
630 char unixname[MAX_PATH];
631 /* HACK!! should fix DEBUG_ReadExecutableDbgInfo to accept DOS filenames */
632 if (wine_get_unix_file_name( buffer, unixname, sizeof(unixname) ))
634 DEBUG_ReadExecutableDbgInfo( unixname );
635 break;
639 /* if it is a Windows binary, or an invalid or missing file name,
640 * we use wine itself as the main executable */
641 DEBUG_ReadExecutableDbgInfo( "wine" );
642 #endif
643 break;
645 case LOAD_DLL_DEBUG_EVENT:
646 assert(DEBUG_CurrThread);
647 DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
648 gdbctx->process->handle,
649 de->u.LoadDll.lpImageName);
651 /* FIXME unicode: de->u.LoadDll.fUnicode */
652 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
653 fprintf(stderr, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
654 de->dwProcessId, de->dwThreadId,
655 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
656 de->u.LoadDll.dwDebugInfoFileOffset,
657 de->u.LoadDll.nDebugInfoSize);
658 #if 0
659 _strupr(buffer);
660 DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, de->u.LoadDll.lpBaseOfDll);
661 DEBUG_CheckDelayedBP();
662 if (DBG_IVAR(BreakOnDllLoad))
664 DEBUG_Printf(DBG_CHN_MESG, "Stopping on DLL %s loading at %08lx\n",
665 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
666 DEBUG_Parser();
668 #endif
669 break;
671 case UNLOAD_DLL_DEBUG_EVENT:
672 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
673 fprintf(stderr, "%08lx:%08lx: unload DLL @%08lx\n",
674 de->dwProcessId, de->dwThreadId, (unsigned long)de->u.UnloadDll.lpBaseOfDll);
675 break;
677 case EXCEPTION_DEBUG_EVENT:
678 assert(DEBUG_CurrThread);
679 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
680 fprintf(stderr, "%08lx:%08lx: exception code=%08lx\n",
681 de->dwProcessId, de->dwThreadId,
682 de->u.Exception.ExceptionRecord.ExceptionCode);
684 if (fetch_context(gdbctx, DEBUG_CurrThread->handle, &gdbctx->context))
686 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
688 break;
690 case CREATE_THREAD_DEBUG_EVENT:
691 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
692 fprintf(stderr, "%08lx:%08lx: create thread D @%08lx\n",
693 de->dwProcessId, de->dwThreadId, (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
695 DEBUG_AddThread(gdbctx->process,
696 de->dwThreadId,
697 de->u.CreateThread.hThread,
698 de->u.CreateThread.lpStartAddress,
699 de->u.CreateThread.lpThreadLocalBase);
700 break;
702 case EXIT_THREAD_DEBUG_EVENT:
703 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
704 fprintf(stderr, "%08lx:%08lx: exit thread (%ld)\n",
705 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
707 assert(DEBUG_CurrThread);
708 if (DEBUG_CurrThread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
709 if (DEBUG_CurrThread == gdbctx->other_thread) gdbctx->other_thread = NULL;
710 DEBUG_DelThread(DEBUG_CurrThread);
711 break;
713 case EXIT_PROCESS_DEBUG_EVENT:
714 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
715 fprintf(stderr, "%08lx:%08lx: exit process (%ld)\n",
716 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
718 DEBUG_DelProcess(gdbctx->process);
719 gdbctx->process = NULL;
720 /* now signal gdb that we're done */
721 gdbctx->last_sig = SIGTERM;
722 gdbctx->in_trap = TRUE;
723 break;
725 case OUTPUT_DEBUG_STRING_EVENT:
726 assert(DEBUG_CurrThread);
727 DEBUG_ProcessGetString(buffer, sizeof(buffer),
728 gdbctx->process->handle,
729 de->u.DebugString.lpDebugStringData);
730 /* FIXME unicode de->u.DebugString.fUnicode ? */
731 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
732 fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n",
733 de->dwProcessId, de->dwThreadId, buffer);
734 break;
736 case RIP_EVENT:
737 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
738 fprintf(stderr, "%08lx:%08lx: rip error=%ld type=%ld\n",
739 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
740 de->u.RipInfo.dwType);
741 break;
743 default:
744 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
745 fprintf(stderr, "%08lx:%08lx: unknown event (%ld)\n",
746 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
750 static void resume_debuggee(struct gdb_context* gdbctx, unsigned long cont)
752 if (DEBUG_CurrThread)
754 if (!SetThreadContext(DEBUG_CurrThread->handle, &gdbctx->context))
755 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
756 fprintf(stderr, "Cannot set context on thread %lu\n", DEBUG_CurrThread->tid);
757 if (!ContinueDebugEvent(gdbctx->process->pid, DEBUG_CurrThread->tid, cont))
758 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
759 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
760 DEBUG_CurrThread->tid, cont);
762 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
763 fprintf(stderr, "Cannot find last thread (%lu)\n", DEBUG_CurrThread->tid);
766 static void wait_for_debuggee(struct gdb_context* gdbctx)
768 DEBUG_EVENT de;
770 gdbctx->in_trap = FALSE;
771 while (WaitForDebugEvent(&de, INFINITE))
773 handle_debug_event(gdbctx, &de);
774 assert(!gdbctx->process ||
775 gdbctx->process->pid == 0 ||
776 de.dwProcessId == gdbctx->process->pid);
777 assert(!DEBUG_CurrThread || de.dwThreadId == DEBUG_CurrThread->tid);
778 if (gdbctx->in_trap) break;
779 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
783 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
785 cpu_leave_stepping(gdbctx);
786 resume_debuggee(gdbctx, DBG_CONTINUE);
787 if (!kill)
788 DebugActiveProcessStop(gdbctx->process->pid);
789 DEBUG_DelProcess(gdbctx->process);
790 gdbctx->process = NULL;
793 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
795 unsigned long status;
797 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
799 strcpy(buffer, "Unknown process");
800 return;
802 if (status == STILL_ACTIVE)
804 strcpy(buffer, "Running");
806 else
807 snprintf(buffer, len, "Terminated (%lu)", status);
809 switch (GetPriorityClass(gdbctx->process->handle))
811 case 0: break;
812 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
813 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
814 #endif
815 #ifdef BELOW_NORMAL_PRIORITY_CLASS
816 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
817 #endif
818 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
819 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
820 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
821 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
823 strcat(buffer, "\n");
826 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
827 char* buffer, size_t len)
829 DBG_THREAD* thd;
830 unsigned long status;
831 int prio;
833 /* FIXME: use the size of buffer */
834 thd = DEBUG_GetThread(gdbctx->process, tid);
835 if (thd == NULL)
837 strcpy(buffer, "No information");
838 return;
840 if (GetExitCodeThread(thd->handle, &status))
842 if (status == STILL_ACTIVE)
844 /* FIXME: this is a bit brutal... some nicer way shall be found */
845 switch (status = SuspendThread(thd->handle))
847 case -1: break;
848 case 0: strcpy(buffer, "Running"); break;
849 default: snprintf(buffer, len, "Suspended (%lu)", status - 1);
851 ResumeThread(thd->handle);
853 else
854 snprintf(buffer, len, "Terminated (exit code = %lu)", status);
856 else
858 strcpy(buffer, "Unknown threadID");
860 switch (prio = GetThreadPriority(thd->handle))
862 case THREAD_PRIORITY_ERROR_RETURN: break;
863 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
864 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
865 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
866 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
867 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
868 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
869 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
870 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
872 assert(strlen(buffer) < len);
875 /* =============================================== *
876 * P A C K E T U T I L S *
877 * =============================================== *
880 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
881 packet_last_f = 0x80};
883 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
885 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
887 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
888 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
892 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
894 packet_reply_grow(gdbctx, len * 2);
895 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
896 gdbctx->out_len += len * 2;
899 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
901 packet_reply_hex_to(gdbctx, src, strlen(src));
904 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
906 int i, shift;
908 shift = (len - 1) * 8;
909 packet_reply_grow(gdbctx, len * 2);
910 for (i = 0; i < len; i++, shift -= 8)
912 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
913 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
917 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
919 packet_reply_grow(gdbctx, len);
920 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
921 gdbctx->out_len += len;
924 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
926 packet_reply_add(gdbctx, str, strlen(str));
929 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
931 packet_reply_add(gdbctx, &ch, 1);
934 static void packet_reply_open(struct gdb_context* gdbctx)
936 assert(gdbctx->out_curr_packet == -1);
937 packet_reply_catc(gdbctx, '$');
938 gdbctx->out_curr_packet = gdbctx->out_len;
941 static void packet_reply_close(struct gdb_context* gdbctx)
943 unsigned char cksum;
944 int plen;
946 plen = gdbctx->out_len - gdbctx->out_curr_packet;
947 packet_reply_catc(gdbctx, '#');
948 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
949 packet_reply_hex_to(gdbctx, &cksum, 1);
950 if (gdbctx->trace & GDBPXY_TRC_PACKET)
951 fprintf(stderr, "Reply : %*.*s\n",
952 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
953 gdbctx->out_curr_packet = -1;
956 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
958 packet_reply_open(gdbctx);
960 if (len == -1) len = strlen(packet);
961 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
963 packet_reply_add(gdbctx, packet, len);
965 packet_reply_close(gdbctx);
967 return packet_done;
970 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
972 packet_reply_open(gdbctx);
974 packet_reply_add(gdbctx, "E", 1);
975 packet_reply_val(gdbctx, error, 1);
977 packet_reply_close(gdbctx);
979 return packet_done;
982 /* =============================================== *
983 * P A C K E T H A N D L E R S *
984 * =============================================== *
987 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
989 enum packet_return ret = packet_done;
991 packet_reply_open(gdbctx);
993 if (gdbctx->process != NULL)
995 unsigned char sig;
996 unsigned i;
998 packet_reply_catc(gdbctx, 'T');
999 sig = gdbctx->last_sig;
1000 packet_reply_val(gdbctx, sig, 1);
1001 packet_reply_add(gdbctx, "thread:", 7);
1002 packet_reply_val(gdbctx, DEBUG_CurrThread->tid, 4);
1003 packet_reply_catc(gdbctx, ';');
1005 for (i = 0; i < cpu_num_regs; i++)
1007 /* FIXME: this call will also grow the buffer...
1008 * unneeded, but not harmful
1010 packet_reply_val(gdbctx, i, 1);
1011 packet_reply_catc(gdbctx, ':');
1012 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
1013 packet_reply_catc(gdbctx, ';');
1016 else
1018 /* Try to put an exit code
1019 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1020 * just indicate the end of process and exit */
1021 packet_reply_add(gdbctx, "W00", 3);
1022 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1025 packet_reply_close(gdbctx);
1027 return ret;
1030 #if 0
1031 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1033 gdbctx->extended = 1;
1034 return packet_ok;
1036 #endif
1038 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1040 assert(gdbctx->in_packet_len == 0);
1041 return packet_reply_status(gdbctx);
1044 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1046 /* FIXME: add support for address in packet */
1047 assert(gdbctx->in_packet_len == 0);
1048 if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
1049 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1050 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
1051 gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
1052 resume_debuggee(gdbctx, DBG_CONTINUE);
1053 wait_for_debuggee(gdbctx);
1054 return packet_reply_status(gdbctx);
1057 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1059 unsigned char sig;
1061 /* FIXME: add support for address in packet */
1062 assert(gdbctx->in_packet_len == 2);
1063 if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
1064 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1065 fprintf(stderr, "NIY: cont/sig on %lu, while last thread is %lu\n",
1066 gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
1067 hex_from(&sig, gdbctx->in_packet, 1);
1068 /* cannot change signals on the fly */
1069 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1070 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1071 if (sig != gdbctx->last_sig)
1072 return packet_error;
1073 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1074 wait_for_debuggee(gdbctx);
1075 return packet_reply_status(gdbctx);
1078 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1080 detach_debuggee(gdbctx, FALSE);
1081 return packet_ok | packet_last_f;
1084 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1086 int i;
1087 CONTEXT ctx;
1088 CONTEXT* pctx = &gdbctx->context;
1090 assert(gdbctx->in_trap);
1092 if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
1094 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1095 return packet_error;
1098 packet_reply_open(gdbctx);
1099 for (i = 0; i < cpu_num_regs; i++)
1101 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1103 packet_reply_close(gdbctx);
1104 return packet_done;
1107 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1109 unsigned i;
1110 CONTEXT ctx;
1111 CONTEXT* pctx = &gdbctx->context;
1113 assert(gdbctx->in_trap);
1114 if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
1116 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1117 return packet_error;
1119 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1121 for (i = 0; i < cpu_num_regs; i++)
1122 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1123 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1125 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1126 fprintf(stderr, "Cannot set context on thread %lu\n", gdbctx->other_thread->tid);
1127 return packet_error;
1129 return packet_ok;
1132 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1134 detach_debuggee(gdbctx, TRUE);
1135 #if 0
1136 if (!gdbctx->extended)
1137 /* dunno whether GDB cares or not */
1138 #endif
1139 wait(NULL);
1140 exit(0);
1141 /* assume we can't really answer something here */
1142 /* return packet_done; */
1145 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1147 char* end;
1148 unsigned thread;
1150 switch (gdbctx->in_packet[0])
1152 case 'c':
1153 case 'g':
1154 if (gdbctx->in_packet[1] == '-')
1155 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1156 else
1157 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1158 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1160 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1161 fprintf(stderr, "Cannot get threadid %*.*s\n",
1162 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1163 gdbctx->in_packet + 1);
1164 return packet_error;
1166 if (gdbctx->in_packet[0] == 'c')
1167 gdbctx->exec_thread = DEBUG_GetThread(gdbctx->process, thread);
1168 else
1169 gdbctx->other_thread = DEBUG_GetThread(gdbctx->process, thread);
1170 return packet_ok;
1171 default:
1172 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1173 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1174 return packet_error;
1178 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1180 char *addr;
1181 size_t len, blk_len, nread;
1182 char buffer[32];
1183 unsigned long r = 0;
1185 assert(gdbctx->in_trap);
1186 /* FIXME:check in_packet_len for reading %p,%x */
1187 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1188 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1189 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1190 for (nread = 0; nread < len > 0; nread += r, addr += r)
1192 blk_len = min(sizeof(buffer), len - nread);
1193 if (!ReadProcessMemory(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1194 r == 0)
1196 /* fail at first address, return error */
1197 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1198 /* something has already been read, return partial information */
1199 break;
1201 if (nread == 0) packet_reply_open(gdbctx);
1202 packet_reply_hex_to(gdbctx, buffer, r);
1204 packet_reply_close(gdbctx);
1205 return packet_done;
1208 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1210 char* addr;
1211 size_t len, blk_len;
1212 char* ptr;
1213 char buffer[32];
1214 unsigned long w;
1216 assert(gdbctx->in_trap);
1217 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1218 if (ptr == NULL)
1220 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1221 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1222 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1223 return packet_error;
1225 *ptr++ = '\0';
1227 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1229 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1230 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1231 return packet_error;
1233 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1235 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1236 fprintf(stderr, "Wrong sizes %u <> %u\n",
1237 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1238 return packet_error;
1240 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1241 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1242 while (len > 0)
1244 blk_len = min(sizeof(buffer), len);
1245 hex_from(buffer, ptr, blk_len);
1247 BOOL ret;
1249 ret = WriteProcessMemory(gdbctx->process->handle, addr, buffer, blk_len, &w);
1250 if (!ret || w != blk_len)
1251 break;
1253 addr += w;
1254 len -= w;
1255 ptr += w;
1257 return packet_ok; /* FIXME: error while writing ? */
1260 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1262 unsigned reg;
1263 char* ptr;
1264 char* end;
1265 CONTEXT ctx;
1266 CONTEXT* pctx = &gdbctx->context;
1268 assert(gdbctx->in_trap);
1270 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1271 *ptr++ = '\0';
1272 reg = strtoul(gdbctx->in_packet, &end, 16);
1273 if (end == NULL || reg > cpu_num_regs)
1275 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1276 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1277 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1278 * it wouldn't matter too much, and it fakes our support for all regs
1280 return (end == NULL) ? packet_error : packet_ok;
1282 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1284 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1285 fprintf(stderr, "Wrong sizes %u <> %u\n",
1286 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1287 return packet_error;
1289 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1290 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1291 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1292 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1294 if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
1296 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1297 return packet_error;
1300 hex_from(cpu_register(pctx, reg), ptr, 4);
1301 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1303 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1304 fprintf(stderr, "Cannot set context for thread %lu\n", gdbctx->other_thread->tid);
1305 return packet_error;
1308 return packet_ok;
1311 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1313 char buffer[128];
1314 char clsName[128];
1315 char wndName[128];
1316 HWND child;
1318 do {
1319 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1320 strcpy(clsName, "-- Unknown --");
1321 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1322 strcpy(wndName, "-- Empty --");
1324 packet_reply_open(gdbctx);
1325 packet_reply_catc(gdbctx, 'O');
1326 snprintf(buffer, sizeof(buffer),
1327 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1328 indent, "", (UINT)hWnd, 13 - indent, "",
1329 clsName, GetWindowLong(hWnd, GWL_STYLE),
1330 GetWindowLong(hWnd, GWL_WNDPROC), wndName);
1331 packet_reply_hex_to_str(gdbctx, buffer);
1332 packet_reply_close(gdbctx);
1334 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1335 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1336 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1339 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1341 char buffer[128];
1343 /* we do the output in several 'O' packets, with the last one being just OK for
1344 * marking the end of the output */
1345 packet_reply_open(gdbctx);
1346 packet_reply_catc(gdbctx, 'O');
1347 snprintf(buffer, sizeof(buffer),
1348 "%-16.16s %-17.17s %-8.8s %s\n",
1349 "hwnd", "Class Name", " Style", " WndProc Text");
1350 packet_reply_hex_to_str(gdbctx, buffer);
1351 packet_reply_close(gdbctx);
1353 /* FIXME: could also add a pmt to this command in str... */
1354 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1355 packet_reply(gdbctx, "OK", 2);
1358 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1360 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1361 char buffer[128];
1362 char deco;
1363 PROCESSENTRY32 entry;
1364 BOOL ok;
1366 if (snap == INVALID_HANDLE_VALUE)
1367 return;
1369 entry.dwSize = sizeof(entry);
1370 ok = Process32First( snap, &entry );
1372 /* we do the output in several 'O' packets, with the last one being just OK for
1373 * marking the end of the output */
1375 packet_reply_open(gdbctx);
1376 packet_reply_catc(gdbctx, 'O');
1377 snprintf(buffer, sizeof(buffer),
1378 " %-8.8s %-8.8s %-8.8s %s\n",
1379 "pid", "threads", "parent", "executable" );
1380 packet_reply_hex_to_str(gdbctx, buffer);
1381 packet_reply_close(gdbctx);
1383 while (ok)
1385 deco = ' ';
1386 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1387 packet_reply_open(gdbctx);
1388 packet_reply_catc(gdbctx, 'O');
1389 snprintf(buffer, sizeof(buffer),
1390 "%c%08lx %-8ld %08lx '%s'\n",
1391 deco, entry.th32ProcessID, entry.cntThreads,
1392 entry.th32ParentProcessID, entry.szExeFile);
1393 packet_reply_hex_to_str(gdbctx, buffer);
1394 packet_reply_close(gdbctx);
1395 ok = Process32Next(snap, &entry);
1397 CloseHandle(snap);
1398 packet_reply(gdbctx, "OK", 2);
1401 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1403 MEMORY_BASIC_INFORMATION mbi;
1404 char* addr = 0;
1405 char* state;
1406 char* type;
1407 char prot[3+1];
1408 char buffer[128];
1410 /* we do the output in several 'O' packets, with the last one being just OK for
1411 * marking the end of the output */
1412 packet_reply_open(gdbctx);
1413 packet_reply_catc(gdbctx, 'O');
1414 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1415 packet_reply_close(gdbctx);
1417 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1419 switch (mbi.State)
1421 case MEM_COMMIT: state = "commit "; break;
1422 case MEM_FREE: state = "free "; break;
1423 case MEM_RESERVE: state = "reserve"; break;
1424 default: state = "??? "; break;
1426 if (mbi.State != MEM_FREE)
1428 switch (mbi.Type)
1430 case MEM_IMAGE: type = "image "; break;
1431 case MEM_MAPPED: type = "mapped "; break;
1432 case MEM_PRIVATE: type = "private"; break;
1433 case 0: type = " "; break;
1434 default: type = "??? "; break;
1436 memset(prot, ' ' , sizeof(prot)-1);
1437 prot[sizeof(prot)-1] = '\0';
1438 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1439 prot[0] = 'R';
1440 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1441 prot[1] = 'W';
1442 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1443 prot[1] = 'C';
1444 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1445 prot[2] = 'X';
1447 else
1449 type = "";
1450 prot[0] = '\0';
1452 packet_reply_open(gdbctx);
1453 snprintf(buffer, sizeof(buffer),
1454 "%08lx %08lx %s %s %s\n",
1455 (DWORD)addr, mbi.RegionSize, state, type, prot);
1456 packet_reply_catc(gdbctx, 'O');
1457 packet_reply_hex_to_str(gdbctx, buffer);
1458 packet_reply_close(gdbctx);
1460 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1461 break;
1462 addr += mbi.RegionSize;
1464 packet_reply(gdbctx, "OK", 2);
1467 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1468 int len, const char* str)
1470 char buffer[128];
1472 if (len == 0)
1474 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1476 else if (len >= 2 && str[0] == '=')
1478 unsigned val = atoi(&str[1]);
1479 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1480 gdbctx->trace = val;
1482 else
1484 /* FIXME: ugly but can use error packet here */
1485 packet_reply_cat(gdbctx, "E00");
1486 return;
1488 packet_reply_open(gdbctx);
1489 packet_reply_hex_to_str(gdbctx, buffer);
1490 packet_reply_close(gdbctx);
1493 #ifdef __i386__
1494 static void packet_query_monitor_linear(struct gdb_context* gdbctx,
1495 int len, const char* str)
1497 unsigned seg, ofs;
1498 LDT_ENTRY le;
1499 unsigned linear;
1500 char buffer[32];
1502 while (len > 0 && (*str == ' ' || *str == '\t'))
1504 str++; len--;
1506 /* FIXME: do a better scanning (allow both decimal and hex numbers) */
1507 if (!len || sscanf(str, "%x:%x", &seg, &ofs) != 2)
1509 packet_reply_error(gdbctx, 0);
1510 return;
1513 /* V86 mode ? */
1514 if (gdbctx->context.EFlags & 0x00020000) linear = (LOWORD(seg) << 4) + ofs;
1515 /* linux system selector ? */
1516 else if (!(seg & 4) || ((seg >> 3) < 17)) linear = ofs;
1517 /* standard selector */
1518 else if (GetThreadSelectorEntry(gdbctx->process->threads->handle, seg, &le))
1519 linear = (le.HighWord.Bits.BaseHi << 24) + (le.HighWord.Bits.BaseMid << 16) +
1520 le.BaseLow + ofs;
1521 /* error */
1522 else linear = 0;
1523 snprintf(buffer, sizeof(buffer), "0x%x", linear);
1524 packet_reply_open(gdbctx);
1525 packet_reply_hex_to_str(gdbctx, buffer);
1526 packet_reply_close(gdbctx);
1528 #endif
1530 struct query_detail
1532 int with_arg;
1533 const char* name;
1534 size_t len;
1535 void (*handler)(struct gdb_context*, int, const char*);
1536 } query_details[] =
1538 {0, "wnd", 3, packet_query_monitor_wnd},
1539 {0, "window", 6, packet_query_monitor_wnd},
1540 {0, "proc", 4, packet_query_monitor_process},
1541 {0, "process", 7, packet_query_monitor_process},
1542 {0, "mem", 3, packet_query_monitor_mem},
1543 {1, "trace", 5, packet_query_monitor_trace},
1544 #ifdef __i386__
1545 {1, "linear", 6, packet_query_monitor_linear},
1546 #endif
1547 {0, NULL, 0, NULL},
1550 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1551 const char* hxcmd, size_t len)
1553 char buffer[128];
1554 struct query_detail* qd;
1556 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1557 len /= 2;
1558 hex_from(buffer, hxcmd, len);
1560 for (qd = &query_details[0]; qd->name != NULL; qd++)
1562 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1563 if (!qd->with_arg && len != qd->len) continue;
1565 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1566 return packet_done;
1568 return packet_reply_error(gdbctx, EINVAL);
1571 static enum packet_return packet_query(struct gdb_context* gdbctx)
1573 switch (gdbctx->in_packet[0])
1575 case 'f':
1576 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1578 DBG_THREAD* thd;
1580 packet_reply_open(gdbctx);
1581 packet_reply_add(gdbctx, "m", 1);
1582 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1584 packet_reply_val(gdbctx, thd->tid, 4);
1585 if (thd->next != NULL)
1586 packet_reply_add(gdbctx, ",", 1);
1588 packet_reply_close(gdbctx);
1589 return packet_done;
1591 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1593 char result[128];
1595 packet_reply_open(gdbctx);
1596 packet_reply_catc(gdbctx, 'O');
1597 get_process_info(gdbctx, result, sizeof(result));
1598 packet_reply_hex_to_str(gdbctx, result);
1599 packet_reply_close(gdbctx);
1600 return packet_done;
1602 break;
1603 case 's':
1604 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1606 packet_reply(gdbctx, "l", 1);
1607 return packet_done;
1609 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1611 packet_reply(gdbctx, "l", 1);
1612 return packet_done;
1614 break;
1615 case 'C':
1616 if (gdbctx->in_packet_len == 1)
1618 DBG_THREAD* thd;
1619 /* FIXME: doc says 16 bit val ??? */
1620 /* grab first created thread, aka last in list */
1621 assert(gdbctx->process && gdbctx->process->threads);
1622 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1623 packet_reply_open(gdbctx);
1624 packet_reply_add(gdbctx, "QC", 2);
1625 packet_reply_val(gdbctx, thd->tid, 4);
1626 packet_reply_close(gdbctx);
1627 return packet_done;
1629 break;
1630 case 'O':
1631 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1633 char buf[64];
1635 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1636 gdbctx->wine_segs[2] == 0)
1637 return packet_error;
1638 snprintf(buf, sizeof(buf),
1639 "Text=%08lx;Data=%08lx;Bss=%08lx",
1640 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1641 gdbctx->wine_segs[2]);
1642 return packet_reply(gdbctx, buf, -1);
1644 break;
1645 case 'R':
1646 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1648 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1649 gdbctx->in_packet_len - 5);
1651 break;
1652 case 'S':
1653 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1654 return packet_ok;
1655 break;
1656 case 'T':
1657 if (gdbctx->in_packet_len > 15 &&
1658 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1659 gdbctx->in_packet[15] == ',')
1661 unsigned tid;
1662 char* end;
1663 char result[128];
1665 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1666 if (end == NULL) break;
1667 get_thread_info(gdbctx, tid, result, sizeof(result));
1668 packet_reply_open(gdbctx);
1669 packet_reply_hex_to_str(gdbctx, result);
1670 packet_reply_close(gdbctx);
1671 return packet_done;
1673 break;
1675 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1676 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1677 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1678 return packet_error;
1681 static enum packet_return packet_step(struct gdb_context* gdbctx)
1683 /* FIXME: add support for address in packet */
1684 assert(gdbctx->in_packet_len == 0);
1685 if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
1686 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1687 fprintf(stderr, "NIY: step on %lu, while last thread is %lu\n",
1688 gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
1689 if (!cpu_enter_stepping(gdbctx)) return packet_error;
1690 resume_debuggee(gdbctx, DBG_CONTINUE);
1691 wait_for_debuggee(gdbctx);
1692 if (!cpu_leave_stepping(gdbctx)) return packet_error;
1693 return packet_reply_status(gdbctx);
1696 #if 0
1697 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1699 unsigned char sig;
1701 /* FIXME: add support for address in packet */
1702 assert(gdbctx->in_packet_len == 2);
1703 if (DEBUG_CurrThread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1704 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1705 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1706 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1707 hex_from(&sig, gdbctx->in_packet, 1);
1708 /* cannot change signals on the fly */
1709 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1710 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1711 if (sig != gdbctx->last_sig)
1712 return packet_error;
1713 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1714 wait_for_debuggee(gdbctx);
1715 return packet_reply_status(gdbctx);
1717 #endif
1719 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1721 char* end;
1722 unsigned tid;
1724 tid = strtol(gdbctx->in_packet, &end, 16);
1725 if (tid == -1 || tid == 0)
1726 return packet_reply_error(gdbctx, EINVAL);
1727 if (DEBUG_GetThread(gdbctx->process, tid) != NULL)
1728 return packet_ok;
1729 return packet_reply_error(gdbctx, ESRCH);
1732 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1734 void* addr;
1735 unsigned len;
1736 struct gdb_ctx_Xpoint* xpt;
1738 /* FIXME: check packet_len */
1739 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1740 gdbctx->in_packet[1] != ',' ||
1741 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1742 return packet_error;
1743 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1744 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1745 addr, len, gdbctx->in_packet[0]);
1746 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1748 if (xpt->addr == addr && xpt->type == gdbctx->in_packet[0])
1750 switch (cpu_remove_Xpoint(gdbctx, xpt, len))
1752 case 1: xpt->type = -1; return packet_ok;
1753 case 0: return packet_error;
1754 case -1: return packet_done;
1755 default: assert(0);
1759 return packet_error;
1762 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1764 void* addr;
1765 unsigned len;
1766 struct gdb_ctx_Xpoint* xpt;
1768 /* FIXME: check packet_len */
1769 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1770 gdbctx->in_packet[1] != ',' ||
1771 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1772 return packet_error;
1773 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1774 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1775 addr, len, gdbctx->in_packet[0]);
1776 /* because of packet command handling, this should be made idempotent */
1777 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1779 if (xpt->addr == addr && xpt->type == gdbctx->in_packet[0])
1780 return packet_ok; /* nothing to do */
1782 /* really set the Xpoint */
1783 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1785 if (xpt->type == -1)
1787 xpt->addr = addr;
1788 xpt->type = gdbctx->in_packet[0];
1789 switch (cpu_insert_Xpoint(gdbctx, xpt, len))
1791 case 1: return packet_ok;
1792 case 0: return packet_error;
1793 case -1: return packet_done;
1794 default: assert(0);
1798 /* no more entries... eech */
1799 fprintf(stderr, "Running out of spots for {break|watch}points\n");
1800 return packet_error;
1803 /* =============================================== *
1804 * P A C K E T I N F R A S T R U C T U R E *
1805 * =============================================== *
1808 struct packet_entry
1810 char key;
1811 enum packet_return (*handler)(struct gdb_context* gdbctx);
1814 static struct packet_entry packet_entries[] =
1816 /* {'!', packet_extended}, */
1817 {'?', packet_last_signal},
1818 {'c', packet_continue},
1819 {'C', packet_continue_signal},
1820 {'D', packet_detach},
1821 {'g', packet_read_registers},
1822 {'G', packet_write_registers},
1823 {'k', packet_kill},
1824 {'H', packet_thread},
1825 {'m', packet_read_memory},
1826 {'M', packet_write_memory},
1827 /* {'p', packet_read_register}, doesn't seem needed */
1828 {'P', packet_write_register},
1829 {'q', packet_query},
1830 {'s', packet_step},
1831 /*{'S', packet_step_signal}, hard(er) to implement */
1832 {'T', packet_thread_alive},
1833 {'z', packet_remove_breakpoint},
1834 {'Z', packet_set_breakpoint},
1837 static BOOL extract_packets(struct gdb_context* gdbctx)
1839 char* end;
1840 int plen;
1841 unsigned char in_cksum, loc_cksum;
1842 char* ptr;
1843 enum packet_return ret = packet_error;
1844 int num_packet = 0;
1846 while ((ret & packet_last_f) == 0)
1848 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1849 fprintf(stderr, "In-buf: %*.*s\n",
1850 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1851 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1852 if (ptr == NULL) return FALSE;
1853 if (ptr != gdbctx->in_buf)
1855 int glen = ptr - gdbctx->in_buf; /* garbage len */
1856 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1857 fprintf(stderr, "Removing garbage: %*.*s\n",
1858 glen, glen, gdbctx->in_buf);
1859 gdbctx->in_len -= glen;
1860 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1862 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1863 if (end == NULL) return FALSE;
1864 /* no checksum yet */
1865 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1866 plen = end - gdbctx->in_buf - 1;
1867 hex_from(&in_cksum, end + 1, 1);
1868 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1869 if (loc_cksum == in_cksum)
1871 if (num_packet == 0) {
1872 int i;
1874 ret = packet_error;
1876 write(gdbctx->sock, "+", 1);
1877 assert(plen);
1879 /* FIXME: should use bsearch if packet_entries was sorted */
1880 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1882 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1884 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1886 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1887 fprintf(stderr, "Unknown packet request %*.*s\n",
1888 plen, plen, &gdbctx->in_buf[1]);
1890 else
1892 gdbctx->in_packet = gdbctx->in_buf + 2;
1893 gdbctx->in_packet_len = plen - 1;
1894 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1895 fprintf(stderr, "Packet: %c%*.*s\n",
1896 gdbctx->in_buf[1],
1897 gdbctx->in_packet_len, gdbctx->in_packet_len,
1898 gdbctx->in_packet);
1899 ret = (packet_entries[i].handler)(gdbctx);
1901 switch (ret & ~packet_last_f)
1903 case packet_error: packet_reply(gdbctx, "", 0); break;
1904 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
1905 case packet_done: break;
1907 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1908 fprintf(stderr, "Reply-full: %*.*s\n",
1909 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
1910 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
1911 assert(i == gdbctx->out_len);
1912 /* if this fails, we'll have to use POLLOUT...
1914 gdbctx->out_len = 0;
1915 num_packet++;
1917 else
1919 /* FIXME: if we have in our input buffer more than one packet,
1920 * it's very likely that we took too long to answer to a given packet
1921 * and gdb is sending us again the same packet
1922 * We simply drop the second packet. This will lower the risk of error,
1923 * but there's still some race conditions here
1924 * A better fix (yet not perfect) would be to have two threads:
1925 * - one managing the packets for gdb
1926 * - the second one managing the commands...
1927 * This would allow us also the reply with the '+' character (Ack of
1928 * the command) way sooner than what we do now
1930 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1931 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
1934 else
1936 write(gdbctx->sock, "+", 1);
1937 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1938 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
1940 gdbctx->in_len -= plen + 4;
1941 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
1943 return TRUE;
1946 static int fetch_data(struct gdb_context* gdbctx)
1948 int len, in_len = gdbctx->in_len;
1950 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
1951 for (;;)
1953 #define STEP 128
1954 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
1955 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
1956 #undef STEP
1957 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1958 fprintf(stderr, "%d %d %*.*s\n",
1959 gdbctx->in_len, gdbctx->in_buf_alloc,
1960 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1961 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
1962 if (len <= 0) break;
1963 gdbctx->in_len += len;
1964 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
1965 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
1967 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1968 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
1969 return gdbctx->in_len - in_len;
1972 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
1974 int sock;
1975 struct sockaddr_in s_addrs;
1976 int s_len = sizeof(s_addrs);
1977 struct pollfd pollfd;
1978 char wine_path[MAX_PATH];
1979 char* ptr;
1981 /* step 1: create socket for gdb connection request */
1982 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1984 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1985 fprintf(stderr, "Can't create socket");
1986 return FALSE;
1989 if (listen(sock, 1) == -1 ||
1990 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
1991 return FALSE;
1993 /* step 2: find out wine executable location (as a Unix filename) */
1994 ptr = getenv("WINELOADER");
1995 strcpy(wine_path, ptr ? ptr : "wine");
1997 fprintf(stderr, "Using wine_path: %s\n", wine_path);
1998 read_elf_info(wine_path, gdbctx->wine_segs);
2000 /* step 3: fire up gdb (if requested) */
2001 if (flags & 1)
2002 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2003 else
2004 switch (fork())
2006 case -1: /* error in parent... */
2007 fprintf(stderr, "Cannot create gdb\n");
2008 return FALSE;
2009 break;
2010 default: /* in parent... success */
2011 break;
2012 case 0: /* in child... and alive */
2014 char buf[MAX_PATH];
2015 int fd;
2016 char* gdb_path;
2017 FILE* f;
2019 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2020 strcpy(buf,"/tmp/winegdb.XXXXXX");
2021 fd = mkstemps(buf,0);
2022 if (fd == -1) return FALSE;
2023 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2024 fprintf(f, "file %s\n", wine_path);
2025 fprintf(f, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2026 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2027 fprintf(f, "set prompt Wine-gdb>\\ \n");
2028 /* gdb 5.1 seems to require it, won't hurt anyway */
2029 fprintf(f, "sharedlibrary\n");
2030 /* tell gdb to delete this file when done handling it... */
2031 fprintf(f, "shell rm -f \"%s\"\n", buf);
2032 fclose(f);
2033 if (flags & 2)
2034 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2035 else
2036 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2037 assert(0); /* never reached */
2038 break;
2040 break;
2043 /* step 4: do the process internal creation */
2044 handle_debug_event(gdbctx, de);
2046 /* step 5: wait for gdb to connect actually */
2047 pollfd.fd = sock;
2048 pollfd.events = POLLIN;
2049 pollfd.revents = 0;
2051 switch (poll(&pollfd, 1, -1))
2053 case 1:
2054 if (pollfd.revents & POLLIN)
2056 int dummy = 1;
2057 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2058 if (gdbctx->sock == -1)
2059 break;
2060 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2061 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2062 /* don't keep our small packets too long: send them ASAP back to GDB
2063 * without this, GDB really crawls
2065 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2067 break;
2068 case 0:
2069 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2070 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2071 return FALSE;
2072 case -1:
2073 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2074 fprintf(stderr, "Poll for cnx failed (error)\n");
2075 return FALSE;
2076 default:
2077 assert(0);
2080 close(sock);
2081 return TRUE;
2084 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2086 DEBUG_EVENT de;
2087 int i;
2089 gdbctx->sock = -1;
2090 gdbctx->in_buf = NULL;
2091 gdbctx->in_buf_alloc = 0;
2092 gdbctx->in_len = 0;
2093 gdbctx->out_buf = NULL;
2094 gdbctx->out_buf_alloc = 0;
2095 gdbctx->out_len = 0;
2096 gdbctx->out_curr_packet = -1;
2098 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2099 gdbctx->last_sig = 0;
2100 gdbctx->in_trap = FALSE;
2101 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2102 gdbctx->process = NULL;
2103 for (i = 0; i < NUM_XPOINT; i++)
2104 gdbctx->Xpoints[i].type = -1;
2106 /* wait for first trap */
2107 while (WaitForDebugEvent(&de, INFINITE))
2109 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2111 /* this should be the first event we get,
2112 * and the only one of this type */
2113 assert(gdbctx->process == NULL && de.dwProcessId == DEBUG_CurrPid);
2114 /*gdbctx->dwProcessId = pid; */
2115 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2116 assert(!gdbctx->in_trap);
2118 else
2120 handle_debug_event(gdbctx, &de);
2121 if (gdbctx->in_trap) break;
2123 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2125 return TRUE;
2128 BOOL DEBUG_GdbRemote(unsigned flags)
2130 struct pollfd pollfd;
2131 struct gdb_context gdbctx;
2132 BOOL doLoop;
2134 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2136 pollfd.fd = gdbctx.sock;
2137 pollfd.events = POLLIN;
2138 pollfd.revents = 0;
2140 switch (poll(&pollfd, 1, -1))
2142 case 1:
2143 /* got something */
2144 if (pollfd.revents & (POLLHUP | POLLERR))
2146 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2147 fprintf(stderr, "Gdb hung up\n");
2148 /* kill also debuggee process - questionnable - */
2149 detach_debuggee(&gdbctx, TRUE);
2150 doLoop = FALSE;
2151 break;
2153 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2155 if (extract_packets(&gdbctx)) doLoop = FALSE;
2157 break;
2158 case 0:
2159 /* timeout, should never happen (infinite timeout) */
2160 break;
2161 case -1:
2162 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2163 fprintf(stderr, "Poll failed\n");
2164 doLoop = FALSE;
2165 break;
2168 wait(NULL);
2169 return 0;