2 * A Win32 based proxy implementing the GBD remote protocol
3 * This allows to debug Wine (and any "emulated" program) under
6 * Copyright (c) Eric Pouech 2002-2004
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
28 #include "wine/port.h"
39 #ifdef HAVE_SYS_SOCKET_H
40 # include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
52 /* those two are needed only for the SHOWNORMAL flag */
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
68 enum be_xpoint_type type; /* -1 means free */
81 /* split into individual packet */
89 /* generic GDB thread information */
90 struct dbg_thread* exec_thread; /* thread used in step & continue */
91 struct dbg_thread* other_thread; /* thread to be used in any other operation */
93 /* current Win32 trap env */
97 /* Win32 information */
98 struct dbg_process* process;
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;
120 static inline unsigned char hex_to0(int x)
122 assert(x >= 0 && x < 16);
123 return "0123456789abcdef"[x];
126 static int hex_to_int(const char* src, size_t len){
127 unsigned int returnval = 0;
129 returnval=hex_from0(src[0]);
130 if(len) returnval<<=4;
135 static void hex_from(void* dst, const char* src, size_t len)
137 unsigned char *p = dst;
140 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
145 static void hex_to(char* dst, const void* src, size_t len)
147 const unsigned char *p = src;
150 *dst++ = hex_to0(*p >> 4);
151 *dst++ = hex_to0(*p & 0x0F);
156 static unsigned char checksum(const char* ptr, int len)
161 cksum += (unsigned char)*ptr++;
165 /* =============================================== *
166 * C P U H A N D L E R S *
167 * =============================================== *
171 static size_t cpu_register_map[] = {
172 FIELD_OFFSET(CONTEXT, Eax),
173 FIELD_OFFSET(CONTEXT, Ecx),
174 FIELD_OFFSET(CONTEXT, Edx),
175 FIELD_OFFSET(CONTEXT, Ebx),
176 FIELD_OFFSET(CONTEXT, Esp),
177 FIELD_OFFSET(CONTEXT, Ebp),
178 FIELD_OFFSET(CONTEXT, Esi),
179 FIELD_OFFSET(CONTEXT, Edi),
180 FIELD_OFFSET(CONTEXT, Eip),
181 FIELD_OFFSET(CONTEXT, EFlags),
182 FIELD_OFFSET(CONTEXT, SegCs),
183 FIELD_OFFSET(CONTEXT, SegSs),
184 FIELD_OFFSET(CONTEXT, SegDs),
185 FIELD_OFFSET(CONTEXT, SegEs),
186 FIELD_OFFSET(CONTEXT, SegFs),
187 FIELD_OFFSET(CONTEXT, SegGs),
189 #elif defined(__powerpc__)
190 static size_t cpu_register_map[] = {
191 FIELD_OFFSET(CONTEXT, Gpr0),
192 FIELD_OFFSET(CONTEXT, Gpr1),
193 FIELD_OFFSET(CONTEXT, Gpr2),
194 FIELD_OFFSET(CONTEXT, Gpr3),
195 FIELD_OFFSET(CONTEXT, Gpr4),
196 FIELD_OFFSET(CONTEXT, Gpr5),
197 FIELD_OFFSET(CONTEXT, Gpr6),
198 FIELD_OFFSET(CONTEXT, Gpr7),
199 FIELD_OFFSET(CONTEXT, Gpr8),
200 FIELD_OFFSET(CONTEXT, Gpr9),
201 FIELD_OFFSET(CONTEXT, Gpr10),
202 FIELD_OFFSET(CONTEXT, Gpr11),
203 FIELD_OFFSET(CONTEXT, Gpr12),
204 FIELD_OFFSET(CONTEXT, Gpr13),
205 FIELD_OFFSET(CONTEXT, Gpr14),
206 FIELD_OFFSET(CONTEXT, Gpr15),
207 FIELD_OFFSET(CONTEXT, Gpr16),
208 FIELD_OFFSET(CONTEXT, Gpr17),
209 FIELD_OFFSET(CONTEXT, Gpr18),
210 FIELD_OFFSET(CONTEXT, Gpr19),
211 FIELD_OFFSET(CONTEXT, Gpr20),
212 FIELD_OFFSET(CONTEXT, Gpr21),
213 FIELD_OFFSET(CONTEXT, Gpr22),
214 FIELD_OFFSET(CONTEXT, Gpr23),
215 FIELD_OFFSET(CONTEXT, Gpr24),
216 FIELD_OFFSET(CONTEXT, Gpr25),
217 FIELD_OFFSET(CONTEXT, Gpr26),
218 FIELD_OFFSET(CONTEXT, Gpr27),
219 FIELD_OFFSET(CONTEXT, Gpr28),
220 FIELD_OFFSET(CONTEXT, Gpr29),
221 FIELD_OFFSET(CONTEXT, Gpr30),
222 FIELD_OFFSET(CONTEXT, Gpr31),
223 FIELD_OFFSET(CONTEXT, Fpr0),
224 FIELD_OFFSET(CONTEXT, Fpr1),
225 FIELD_OFFSET(CONTEXT, Fpr2),
226 FIELD_OFFSET(CONTEXT, Fpr3),
227 FIELD_OFFSET(CONTEXT, Fpr4),
228 FIELD_OFFSET(CONTEXT, Fpr5),
229 FIELD_OFFSET(CONTEXT, Fpr6),
230 FIELD_OFFSET(CONTEXT, Fpr7),
231 FIELD_OFFSET(CONTEXT, Fpr8),
232 FIELD_OFFSET(CONTEXT, Fpr9),
233 FIELD_OFFSET(CONTEXT, Fpr10),
234 FIELD_OFFSET(CONTEXT, Fpr11),
235 FIELD_OFFSET(CONTEXT, Fpr12),
236 FIELD_OFFSET(CONTEXT, Fpr13),
237 FIELD_OFFSET(CONTEXT, Fpr14),
238 FIELD_OFFSET(CONTEXT, Fpr15),
239 FIELD_OFFSET(CONTEXT, Fpr16),
240 FIELD_OFFSET(CONTEXT, Fpr17),
241 FIELD_OFFSET(CONTEXT, Fpr18),
242 FIELD_OFFSET(CONTEXT, Fpr19),
243 FIELD_OFFSET(CONTEXT, Fpr20),
244 FIELD_OFFSET(CONTEXT, Fpr21),
245 FIELD_OFFSET(CONTEXT, Fpr22),
246 FIELD_OFFSET(CONTEXT, Fpr23),
247 FIELD_OFFSET(CONTEXT, Fpr24),
248 FIELD_OFFSET(CONTEXT, Fpr25),
249 FIELD_OFFSET(CONTEXT, Fpr26),
250 FIELD_OFFSET(CONTEXT, Fpr27),
251 FIELD_OFFSET(CONTEXT, Fpr28),
252 FIELD_OFFSET(CONTEXT, Fpr29),
253 FIELD_OFFSET(CONTEXT, Fpr30),
254 FIELD_OFFSET(CONTEXT, Fpr31),
256 FIELD_OFFSET(CONTEXT, Iar),
257 FIELD_OFFSET(CONTEXT, Msr),
258 FIELD_OFFSET(CONTEXT, Cr),
259 FIELD_OFFSET(CONTEXT, Lr),
260 FIELD_OFFSET(CONTEXT, Ctr),
261 FIELD_OFFSET(CONTEXT, Xer),
262 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
263 /* see gdb/nlm/ppc.c */
265 #elif defined(__ALPHA__)
266 static size_t cpu_register_map[] = {
267 FIELD_OFFSET(CONTEXT, IntV0),
268 FIELD_OFFSET(CONTEXT, IntT0),
269 FIELD_OFFSET(CONTEXT, IntT1),
270 FIELD_OFFSET(CONTEXT, IntT2),
271 FIELD_OFFSET(CONTEXT, IntT3),
272 FIELD_OFFSET(CONTEXT, IntT4),
273 FIELD_OFFSET(CONTEXT, IntT5),
274 FIELD_OFFSET(CONTEXT, IntT6),
275 FIELD_OFFSET(CONTEXT, IntT7),
276 FIELD_OFFSET(CONTEXT, IntS0),
277 FIELD_OFFSET(CONTEXT, IntS1),
278 FIELD_OFFSET(CONTEXT, IntS2),
279 FIELD_OFFSET(CONTEXT, IntS3),
280 FIELD_OFFSET(CONTEXT, IntS4),
281 FIELD_OFFSET(CONTEXT, IntS5),
282 FIELD_OFFSET(CONTEXT, IntFp),
283 FIELD_OFFSET(CONTEXT, IntA0),
284 FIELD_OFFSET(CONTEXT, IntA1),
285 FIELD_OFFSET(CONTEXT, IntA2),
286 FIELD_OFFSET(CONTEXT, IntA3),
287 FIELD_OFFSET(CONTEXT, IntA4),
288 FIELD_OFFSET(CONTEXT, IntA5),
289 FIELD_OFFSET(CONTEXT, IntT8),
290 FIELD_OFFSET(CONTEXT, IntT9),
291 FIELD_OFFSET(CONTEXT, IntT10),
292 FIELD_OFFSET(CONTEXT, IntT11),
293 FIELD_OFFSET(CONTEXT, IntRa),
294 FIELD_OFFSET(CONTEXT, IntT12),
295 FIELD_OFFSET(CONTEXT, IntAt),
296 FIELD_OFFSET(CONTEXT, IntGp),
297 FIELD_OFFSET(CONTEXT, IntSp),
298 FIELD_OFFSET(CONTEXT, IntZero),
299 FIELD_OFFSET(CONTEXT, FltF0),
300 FIELD_OFFSET(CONTEXT, FltF1),
301 FIELD_OFFSET(CONTEXT, FltF2),
302 FIELD_OFFSET(CONTEXT, FltF3),
303 FIELD_OFFSET(CONTEXT, FltF4),
304 FIELD_OFFSET(CONTEXT, FltF5),
305 FIELD_OFFSET(CONTEXT, FltF6),
306 FIELD_OFFSET(CONTEXT, FltF7),
307 FIELD_OFFSET(CONTEXT, FltF8),
308 FIELD_OFFSET(CONTEXT, FltF9),
309 FIELD_OFFSET(CONTEXT, FltF10),
310 FIELD_OFFSET(CONTEXT, FltF11),
311 FIELD_OFFSET(CONTEXT, FltF12),
312 FIELD_OFFSET(CONTEXT, FltF13),
313 FIELD_OFFSET(CONTEXT, FltF14),
314 FIELD_OFFSET(CONTEXT, FltF15),
315 FIELD_OFFSET(CONTEXT, FltF16),
316 FIELD_OFFSET(CONTEXT, FltF17),
317 FIELD_OFFSET(CONTEXT, FltF18),
318 FIELD_OFFSET(CONTEXT, FltF19),
319 FIELD_OFFSET(CONTEXT, FltF20),
320 FIELD_OFFSET(CONTEXT, FltF21),
321 FIELD_OFFSET(CONTEXT, FltF22),
322 FIELD_OFFSET(CONTEXT, FltF23),
323 FIELD_OFFSET(CONTEXT, FltF24),
324 FIELD_OFFSET(CONTEXT, FltF25),
325 FIELD_OFFSET(CONTEXT, FltF26),
326 FIELD_OFFSET(CONTEXT, FltF27),
327 FIELD_OFFSET(CONTEXT, FltF28),
328 FIELD_OFFSET(CONTEXT, FltF29),
329 FIELD_OFFSET(CONTEXT, FltF30),
330 FIELD_OFFSET(CONTEXT, FltF31),
332 /* FIXME: Didn't look for the right order yet */
333 FIELD_OFFSET(CONTEXT, Fir),
334 FIELD_OFFSET(CONTEXT, Fpcr),
335 FIELD_OFFSET(CONTEXT, SoftFpcr),
338 # error Define the registers map for your CPU
341 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
343 static inline unsigned long* cpu_register(CONTEXT* ctx, unsigned idx)
345 assert(idx < cpu_num_regs);
346 return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
349 /* =============================================== *
350 * W I N 3 2 D E B U G I N T E R F A C E *
351 * =============================================== *
354 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
356 ctx->ContextFlags = CONTEXT_CONTROL
358 #ifdef CONTEXT_SEGMENTS
361 #ifdef CONTEXT_DEBUG_REGISTERS
362 | CONTEXT_DEBUG_REGISTERS
365 if (!GetThreadContext(h, ctx))
367 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
368 fprintf(stderr, "Can't get thread's context\n");
374 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
376 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
379 switch (rec->ExceptionCode)
381 case EXCEPTION_ACCESS_VIOLATION:
382 case EXCEPTION_PRIV_INSTRUCTION:
383 case EXCEPTION_STACK_OVERFLOW:
384 case EXCEPTION_GUARD_PAGE:
385 gdbctx->last_sig = SIGSEGV;
388 case EXCEPTION_DATATYPE_MISALIGNMENT:
389 gdbctx->last_sig = SIGBUS;
392 case EXCEPTION_SINGLE_STEP:
394 case EXCEPTION_BREAKPOINT:
395 gdbctx->last_sig = SIGTRAP;
398 case EXCEPTION_FLT_DENORMAL_OPERAND:
399 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
400 case EXCEPTION_FLT_INEXACT_RESULT:
401 case EXCEPTION_FLT_INVALID_OPERATION:
402 case EXCEPTION_FLT_OVERFLOW:
403 case EXCEPTION_FLT_STACK_CHECK:
404 case EXCEPTION_FLT_UNDERFLOW:
405 gdbctx->last_sig = SIGFPE;
408 case EXCEPTION_INT_DIVIDE_BY_ZERO:
409 case EXCEPTION_INT_OVERFLOW:
410 gdbctx->last_sig = SIGFPE;
413 case EXCEPTION_ILLEGAL_INSTRUCTION:
414 gdbctx->last_sig = SIGILL;
418 gdbctx->last_sig = SIGINT;
421 case STATUS_POSSIBLE_DEADLOCK:
422 gdbctx->last_sig = SIGALRM;
424 /* FIXME: we could also add here a O packet with additional information */
427 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
428 fprintf(stderr, "Unhandled exception code 0x%08lx\n", rec->ExceptionCode);
429 gdbctx->last_sig = SIGABRT;
436 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
440 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
442 switch (de->dwDebugEventCode)
444 case CREATE_PROCESS_DEBUG_EVENT:
445 memory_get_string_indirect(de->u.CreateProcessInfo.hProcess,
446 de->u.CreateProcessInfo.lpImageName,
447 de->u.CreateProcessInfo.fUnicode,
448 buffer, sizeof(buffer));
450 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
451 fprintf(stderr, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
452 de->dwProcessId, de->dwThreadId,
453 buffer, de->u.CreateProcessInfo.lpImageName,
454 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress,
455 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
456 de->u.CreateProcessInfo.nDebugInfoSize);
458 gdbctx->process = dbg_add_process(de->dwProcessId,
459 de->u.CreateProcessInfo.hProcess,
461 /* de->u.CreateProcessInfo.lpStartAddress; */
462 if (!SymInitialize(gdbctx->process->handle, NULL, TRUE))
463 fprintf(stderr, "Couldn't initiate DbgHelp\n");
465 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
466 fprintf(stderr, "%08lx:%08lx: create thread I @%08lx\n",
467 de->dwProcessId, de->dwThreadId,
468 (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress);
470 assert(dbg_curr_thread == NULL); /* shouldn't be there */
471 dbg_add_thread(gdbctx->process, de->dwThreadId,
472 de->u.CreateProcessInfo.hThread,
473 de->u.CreateProcessInfo.lpThreadLocalBase);
476 case LOAD_DLL_DEBUG_EVENT:
477 assert(dbg_curr_thread);
478 memory_get_string_indirect(gdbctx->process->handle,
479 de->u.LoadDll.lpImageName,
480 de->u.LoadDll.fUnicode,
481 buffer, sizeof(buffer));
482 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
483 fprintf(stderr, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
484 de->dwProcessId, de->dwThreadId,
485 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
486 de->u.LoadDll.dwDebugInfoFileOffset,
487 de->u.LoadDll.nDebugInfoSize);
488 SymLoadModule(gdbctx->process->handle, de->u.LoadDll.hFile, buffer, NULL,
489 (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
492 case UNLOAD_DLL_DEBUG_EVENT:
493 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
494 fprintf(stderr, "%08lx:%08lx: unload DLL @%08lx\n",
495 de->dwProcessId, de->dwThreadId, (unsigned long)de->u.UnloadDll.lpBaseOfDll);
496 SymUnloadModule(gdbctx->process->handle,
497 (unsigned long)de->u.UnloadDll.lpBaseOfDll);
500 case EXCEPTION_DEBUG_EVENT:
501 assert(dbg_curr_thread);
502 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
503 fprintf(stderr, "%08lx:%08lx: exception code=0x%08lx\n",
504 de->dwProcessId, de->dwThreadId,
505 de->u.Exception.ExceptionRecord.ExceptionCode);
507 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
509 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
513 case CREATE_THREAD_DEBUG_EVENT:
514 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
515 fprintf(stderr, "%08lx:%08lx: create thread D @%08lx\n",
516 de->dwProcessId, de->dwThreadId, (unsigned long)(void*)de->u.CreateThread.lpStartAddress);
518 dbg_add_thread(gdbctx->process,
520 de->u.CreateThread.hThread,
521 de->u.CreateThread.lpThreadLocalBase);
524 case EXIT_THREAD_DEBUG_EVENT:
525 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
526 fprintf(stderr, "%08lx:%08lx: exit thread (%ld)\n",
527 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
529 assert(dbg_curr_thread);
530 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
531 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
532 dbg_del_thread(dbg_curr_thread);
535 case EXIT_PROCESS_DEBUG_EVENT:
536 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
537 fprintf(stderr, "%08lx:%08lx: exit process (%ld)\n",
538 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
540 dbg_del_process(gdbctx->process);
541 gdbctx->process = NULL;
542 /* now signal gdb that we're done */
543 gdbctx->last_sig = SIGTERM;
544 gdbctx->in_trap = TRUE;
547 case OUTPUT_DEBUG_STRING_EVENT:
548 assert(dbg_curr_thread);
549 memory_get_string(gdbctx->process->handle,
550 de->u.DebugString.lpDebugStringData, TRUE,
551 de->u.DebugString.fUnicode, buffer, sizeof(buffer));
552 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
553 fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n",
554 de->dwProcessId, de->dwThreadId, buffer);
558 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
559 fprintf(stderr, "%08lx:%08lx: rip error=%ld type=%ld\n",
560 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
561 de->u.RipInfo.dwType);
565 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
566 fprintf(stderr, "%08lx:%08lx: unknown event (%ld)\n",
567 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
571 static void resume_debuggee(struct gdb_context* gdbctx, unsigned long cont)
575 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
576 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
577 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
578 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
579 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
580 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
581 dbg_curr_thread->tid, cont);
583 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
584 fprintf(stderr, "Cannot find last thread\n");
588 static void resume_debuggee_thread(struct gdb_context* gdbctx, unsigned long cont, unsigned int threadid)
593 if(dbg_curr_thread->tid == threadid){
594 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
595 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
596 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
597 fprintf(stderr, "Cannot set context on thread %lu\n", dbg_curr_thread->tid);
598 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
599 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
600 fprintf(stderr, "Cannot continue on %lu (%lu)\n",
601 dbg_curr_thread->tid, cont);
604 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
605 fprintf(stderr, "Cannot find last thread\n");
608 static void wait_for_debuggee(struct gdb_context* gdbctx)
612 gdbctx->in_trap = FALSE;
613 while (WaitForDebugEvent(&de, INFINITE))
615 handle_debug_event(gdbctx, &de);
616 assert(!gdbctx->process ||
617 gdbctx->process->pid == 0 ||
618 de.dwProcessId == gdbctx->process->pid);
619 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
620 if (gdbctx->in_trap) break;
621 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
625 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
627 be_cpu->single_step(&gdbctx->context, FALSE);
628 resume_debuggee(gdbctx, DBG_CONTINUE);
630 DebugActiveProcessStop(gdbctx->process->pid);
631 dbg_del_process(gdbctx->process);
632 gdbctx->process = NULL;
635 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
637 unsigned long status;
639 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
641 strcpy(buffer, "Unknown process");
644 if (status == STILL_ACTIVE)
646 strcpy(buffer, "Running");
649 snprintf(buffer, len, "Terminated (%lu)", status);
651 switch (GetPriorityClass(gdbctx->process->handle))
654 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
655 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
657 #ifdef BELOW_NORMAL_PRIORITY_CLASS
658 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
660 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
661 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
662 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
663 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
665 strcat(buffer, "\n");
668 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
669 char* buffer, size_t len)
671 struct dbg_thread* thd;
672 unsigned long status;
675 /* FIXME: use the size of buffer */
676 thd = dbg_get_thread(gdbctx->process, tid);
679 strcpy(buffer, "No information");
682 if (GetExitCodeThread(thd->handle, &status))
684 if (status == STILL_ACTIVE)
686 /* FIXME: this is a bit brutal... some nicer way shall be found */
687 switch (status = SuspendThread(thd->handle))
690 case 0: strcpy(buffer, "Running"); break;
691 default: snprintf(buffer, len, "Suspended (%lu)", status - 1);
693 ResumeThread(thd->handle);
696 snprintf(buffer, len, "Terminated (exit code = %lu)", status);
700 strcpy(buffer, "Unknown threadID");
702 switch (prio = GetThreadPriority(thd->handle))
704 case THREAD_PRIORITY_ERROR_RETURN: break;
705 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
706 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
707 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
708 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
709 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
710 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
711 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
712 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
714 assert(strlen(buffer) < len);
717 /* =============================================== *
718 * P A C K E T U T I L S *
719 * =============================================== *
722 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
723 packet_last_f = 0x80};
725 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
727 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
729 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
730 gdbctx->out_buf = realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
734 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
736 packet_reply_grow(gdbctx, len * 2);
737 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
738 gdbctx->out_len += len * 2;
741 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
743 packet_reply_hex_to(gdbctx, src, strlen(src));
746 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
750 shift = (len - 1) * 8;
751 packet_reply_grow(gdbctx, len * 2);
752 for (i = 0; i < len; i++, shift -= 8)
754 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
755 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
759 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
761 packet_reply_grow(gdbctx, len);
762 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
763 gdbctx->out_len += len;
766 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
768 packet_reply_add(gdbctx, str, strlen(str));
771 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
773 packet_reply_add(gdbctx, &ch, 1);
776 static void packet_reply_open(struct gdb_context* gdbctx)
778 assert(gdbctx->out_curr_packet == -1);
779 packet_reply_catc(gdbctx, '$');
780 gdbctx->out_curr_packet = gdbctx->out_len;
783 static void packet_reply_close(struct gdb_context* gdbctx)
788 plen = gdbctx->out_len - gdbctx->out_curr_packet;
789 packet_reply_catc(gdbctx, '#');
790 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
791 packet_reply_hex_to(gdbctx, &cksum, 1);
792 if (gdbctx->trace & GDBPXY_TRC_PACKET)
793 fprintf(stderr, "Reply : %*.*s\n",
794 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
795 gdbctx->out_curr_packet = -1;
798 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
800 packet_reply_open(gdbctx);
802 if (len == -1) len = strlen(packet);
803 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
805 packet_reply_add(gdbctx, packet, len);
807 packet_reply_close(gdbctx);
812 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
814 packet_reply_open(gdbctx);
816 packet_reply_add(gdbctx, "E", 1);
817 packet_reply_val(gdbctx, error, 1);
819 packet_reply_close(gdbctx);
824 /* =============================================== *
825 * P A C K E T H A N D L E R S *
826 * =============================================== *
829 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
831 enum packet_return ret = packet_done;
833 packet_reply_open(gdbctx);
835 if (gdbctx->process != NULL)
840 packet_reply_catc(gdbctx, 'T');
841 sig = gdbctx->last_sig;
842 packet_reply_val(gdbctx, sig, 1);
843 packet_reply_add(gdbctx, "thread:", 7);
844 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
845 packet_reply_catc(gdbctx, ';');
847 for (i = 0; i < cpu_num_regs; i++)
849 /* FIXME: this call will also grow the buffer...
850 * unneeded, but not harmful
852 packet_reply_val(gdbctx, i, 1);
853 packet_reply_catc(gdbctx, ':');
854 packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
855 packet_reply_catc(gdbctx, ';');
860 /* Try to put an exit code
861 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
862 * just indicate the end of process and exit */
863 packet_reply_add(gdbctx, "W00", 3);
864 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
867 packet_reply_close(gdbctx);
873 static enum packet_return packet_extended(struct gdb_context* gdbctx)
875 gdbctx->extended = 1;
880 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
882 assert(gdbctx->in_packet_len == 0);
883 return packet_reply_status(gdbctx);
886 static enum packet_return packet_continue(struct gdb_context* gdbctx)
888 /* FIXME: add support for address in packet */
889 assert(gdbctx->in_packet_len == 0);
890 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
891 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
892 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
893 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
894 resume_debuggee(gdbctx, DBG_CONTINUE);
895 wait_for_debuggee(gdbctx);
896 return packet_reply_status(gdbctx);
899 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
902 int defaultAction = -1; /* magic non action */
905 int actionIndex[20]; /* allow for upto 20 actions */
908 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
909 unsigned int threadID = 0;
910 struct dbg_thread* thd;
913 assert(gdbctx->in_packet_len >= 4);
915 /* OK we have vCont followed by..
917 * c for packet_continue
918 * Csig for packet_continue_signal
920 * Ssig for step signal
921 * and then an optional thread ID at the end..
922 * *******************************************/
924 fprintf(stderr, "trying to process a verbose packet\n");
925 /* now check that we've got Cont */
926 assert(strncmp(gdbctx->in_packet, "Cont", 4) == 0);
929 if(gdbctx->in_packet[4] == '?'){
933 The vCont packet is supported. Each action is a supported command in the vCont packet.
935 The vCont packet is not supported. (this didn't seem to be obayed!)
937 packet_reply_open(gdbctx);
938 packet_reply_add(gdbctx, "vCont", 5);
939 /* add all the supported actions to the reply (all of them for now)*/
940 packet_reply_add(gdbctx, ";c", 2);
941 packet_reply_add(gdbctx, ";C", 2);
942 packet_reply_add(gdbctx, ";s", 2);
943 packet_reply_add(gdbctx, ";S", 2);
944 packet_reply_close(gdbctx);
948 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
949 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
950 now if only gdb talked XML.... */
951 #if 0 /* handy for debugging */
952 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
955 /* go through the packet and identify where all the actions start att */
956 for(i = 4; i < gdbctx->in_packet_len - 1; i++){
957 if(gdbctx->in_packet[i] == ';'){
958 threadIndex[actions] = 0;
959 actionIndex[actions++] = i;
960 }else if(gdbctx->in_packet[i] == ':'){
961 threadIndex[actions - 1] = i;
965 /* now look up the default action */
966 for(i = 0 ; i < actions; i++){
967 if(threadIndex[i] == 0){
968 if(defaultAction != -1){
969 fprintf(stderr,"Too many default actions specified\n");
976 /* Now, I have this default action thing that needs to be applied to all non counted threads */
978 /* go through all the threads and stick there id's in the to be done list. */
979 for (thd = gdbctx->process->threads; thd; thd = thd->next)
981 threadIDs[threadCount++] = thd->tid;
982 /* check to see if we have more threads than I counted on, and tell the user what to do
983 * (their running winedbg, so I'm sure they can fix the problem from the error message!) */
984 if(threadCount == 100){
985 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
990 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
991 * that remains is to apply the actions to the threads and the default action to any threads
993 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
994 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
995 fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
996 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
998 /* deal with the threaded stuff first */
999 for( i = 0; i < actions ; i++){
1001 if(threadIndex[i] != 0){
1003 int j, idLength = 0;
1004 if(i < actions - 1){
1005 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1007 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1010 threadID = hex_to_int( gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1011 /* process the action */
1012 switch(gdbctx->in_packet[actionIndex[i] + 1]){
1013 case 's': /* step */
1014 be_cpu->single_step(&gdbctx->context, TRUE);
1016 case 'c': /* continue */
1017 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1019 case 'S': /* step Sig, */
1020 be_cpu->single_step(&gdbctx->context, TRUE);
1022 case 'C': /* continue sig */
1023 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1024 /* cannot change signals on the fly */
1025 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1026 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1027 if (sig != gdbctx->last_sig)
1028 return packet_error;
1029 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1032 for(j = 0 ; j< threadCount; j++){
1033 if(threadIDs[j] == threadID){
1039 } /* for i=0 ; i< actions */
1041 /* now we have manage the default action */
1042 if(defaultAction >=0){
1043 for(i = 0 ; i< threadCount; i++){
1044 /* check to see if we've already done something to the thread*/
1045 if(threadIDs[i] != 0){
1046 /* if not apply the default action*/
1047 threadID = threadIDs[i];
1048 /* process the action (yes this is almost identical to the one above!) */
1049 switch(gdbctx->in_packet[actionIndex[defaultAction] + 1]){
1050 case 's': /* step */
1051 be_cpu->single_step(&gdbctx->context, TRUE);
1053 case 'c': /* continue */
1054 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1057 be_cpu->single_step(&gdbctx->context, TRUE);
1059 case 'C': /* continue sig */
1060 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1061 /* cannot change signals on the fly */
1062 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1063 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1064 if (sig != gdbctx->last_sig)
1065 return packet_error;
1066 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1071 } /* if(defaultAction >=0) */
1073 wait_for_debuggee(gdbctx);
1074 be_cpu->single_step(&gdbctx->context, FALSE);
1075 return packet_reply_status(gdbctx);
1078 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1082 /* FIXME: add support for address in packet */
1083 assert(gdbctx->in_packet_len == 2);
1084 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1085 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1086 fprintf(stderr, "NIY: cont/sig on %lu, while last thread is %lu\n",
1087 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1088 hex_from(&sig, gdbctx->in_packet, 1);
1089 /* cannot change signals on the fly */
1090 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1091 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1092 if (sig != gdbctx->last_sig)
1093 return packet_error;
1094 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1095 wait_for_debuggee(gdbctx);
1096 return packet_reply_status(gdbctx);
1099 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1101 detach_debuggee(gdbctx, FALSE);
1102 return packet_ok | packet_last_f;
1105 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1109 CONTEXT* pctx = &gdbctx->context;
1111 assert(gdbctx->in_trap);
1113 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1115 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1116 return packet_error;
1119 packet_reply_open(gdbctx);
1120 for (i = 0; i < cpu_num_regs; i++)
1122 packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
1124 packet_reply_close(gdbctx);
1128 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1132 CONTEXT* pctx = &gdbctx->context;
1134 assert(gdbctx->in_trap);
1135 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1137 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1138 return packet_error;
1140 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1142 for (i = 0; i < cpu_num_regs; i++)
1143 hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
1144 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1146 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1147 fprintf(stderr, "Cannot set context on thread %lu\n", gdbctx->other_thread->tid);
1148 return packet_error;
1153 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1155 detach_debuggee(gdbctx, TRUE);
1157 if (!gdbctx->extended)
1158 /* dunno whether GDB cares or not */
1162 /* assume we can't really answer something here */
1163 /* return packet_done; */
1166 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1171 switch (gdbctx->in_packet[0])
1175 if (gdbctx->in_packet[1] == '-')
1176 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1178 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1179 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1181 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1182 fprintf(stderr, "Cannot get threadid %*.*s\n",
1183 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1184 gdbctx->in_packet + 1);
1185 return packet_error;
1187 if (gdbctx->in_packet[0] == 'c')
1188 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1190 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1193 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1194 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1195 return packet_error;
1199 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1202 size_t len, blk_len, nread;
1204 unsigned long r = 0;
1206 assert(gdbctx->in_trap);
1207 /* FIXME:check in_packet_len for reading %p,%x */
1208 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1209 if (len <= 0) return packet_error;
1210 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1211 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1212 for (nread = 0; nread < len; nread += r, addr += r)
1214 blk_len = min(sizeof(buffer), len - nread);
1215 if (!ReadProcessMemory(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1218 /* fail at first address, return error */
1219 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1220 /* something has already been read, return partial information */
1223 if (nread == 0) packet_reply_open(gdbctx);
1224 packet_reply_hex_to(gdbctx, buffer, r);
1226 packet_reply_close(gdbctx);
1230 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1233 size_t len, blk_len;
1238 assert(gdbctx->in_trap);
1239 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1242 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1243 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1244 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1245 return packet_error;
1249 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1251 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1252 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1253 return packet_error;
1255 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1257 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1258 fprintf(stderr, "Wrong sizes %u <> %u\n",
1259 ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
1260 return packet_error;
1262 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1263 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1266 blk_len = min(sizeof(buffer), len);
1267 hex_from(buffer, ptr, blk_len);
1271 ret = WriteProcessMemory(gdbctx->process->handle, addr, buffer, blk_len, &w);
1272 if (!ret || w != blk_len)
1279 return packet_ok; /* FIXME: error while writing ? */
1282 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1288 CONTEXT* pctx = &gdbctx->context;
1290 assert(gdbctx->in_trap);
1292 ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
1294 reg = strtoul(gdbctx->in_packet, &end, 16);
1295 if (end == NULL || reg > cpu_num_regs)
1297 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1298 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1299 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1300 * it wouldn't matter too much, and it fakes our support for all regs
1302 return (end == NULL) ? packet_error : packet_ok;
1304 if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
1306 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1307 fprintf(stderr, "Wrong sizes %u <> %u\n",
1308 ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
1309 return packet_error;
1311 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1312 fprintf(stderr, "Writing reg %u <= %*.*s\n",
1313 reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
1314 gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
1316 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1318 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1319 return packet_error;
1322 hex_from(cpu_register(pctx, reg), ptr, 4);
1323 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1325 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1326 fprintf(stderr, "Cannot set context for thread %lu\n", gdbctx->other_thread->tid);
1327 return packet_error;
1333 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1341 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
1342 strcpy(clsName, "-- Unknown --");
1343 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
1344 strcpy(wndName, "-- Empty --");
1346 packet_reply_open(gdbctx);
1347 packet_reply_catc(gdbctx, 'O');
1348 snprintf(buffer, sizeof(buffer),
1349 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1350 indent, "", (UINT)hWnd, 13 - indent, "",
1351 clsName, GetWindowLong(hWnd, GWL_STYLE),
1352 GetWindowLong(hWnd, GWL_WNDPROC), wndName);
1353 packet_reply_hex_to_str(gdbctx, buffer);
1354 packet_reply_close(gdbctx);
1356 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1357 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1358 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1361 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1365 /* we do the output in several 'O' packets, with the last one being just OK for
1366 * marking the end of the output */
1367 packet_reply_open(gdbctx);
1368 packet_reply_catc(gdbctx, 'O');
1369 snprintf(buffer, sizeof(buffer),
1370 "%-16.16s %-17.17s %-8.8s %s\n",
1371 "hwnd", "Class Name", " Style", " WndProc Text");
1372 packet_reply_hex_to_str(gdbctx, buffer);
1373 packet_reply_close(gdbctx);
1375 /* FIXME: could also add a pmt to this command in str... */
1376 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1377 packet_reply(gdbctx, "OK", 2);
1380 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1382 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1385 PROCESSENTRY32 entry;
1388 if (snap == INVALID_HANDLE_VALUE)
1391 entry.dwSize = sizeof(entry);
1392 ok = Process32First(snap, &entry);
1394 /* we do the output in several 'O' packets, with the last one being just OK for
1395 * marking the end of the output */
1397 packet_reply_open(gdbctx);
1398 packet_reply_catc(gdbctx, 'O');
1399 snprintf(buffer, sizeof(buffer),
1400 " %-8.8s %-8.8s %-8.8s %s\n",
1401 "pid", "threads", "parent", "executable");
1402 packet_reply_hex_to_str(gdbctx, buffer);
1403 packet_reply_close(gdbctx);
1408 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1409 packet_reply_open(gdbctx);
1410 packet_reply_catc(gdbctx, 'O');
1411 snprintf(buffer, sizeof(buffer),
1412 "%c%08lx %-8ld %08lx '%s'\n",
1413 deco, entry.th32ProcessID, entry.cntThreads,
1414 entry.th32ParentProcessID, entry.szExeFile);
1415 packet_reply_hex_to_str(gdbctx, buffer);
1416 packet_reply_close(gdbctx);
1417 ok = Process32Next(snap, &entry);
1420 packet_reply(gdbctx, "OK", 2);
1423 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1425 MEMORY_BASIC_INFORMATION mbi;
1432 /* we do the output in several 'O' packets, with the last one being just OK for
1433 * marking the end of the output */
1434 packet_reply_open(gdbctx);
1435 packet_reply_catc(gdbctx, 'O');
1436 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1437 packet_reply_close(gdbctx);
1439 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1443 case MEM_COMMIT: state = "commit "; break;
1444 case MEM_FREE: state = "free "; break;
1445 case MEM_RESERVE: state = "reserve"; break;
1446 default: state = "??? "; break;
1448 if (mbi.State != MEM_FREE)
1452 case MEM_IMAGE: type = "image "; break;
1453 case MEM_MAPPED: type = "mapped "; break;
1454 case MEM_PRIVATE: type = "private"; break;
1455 case 0: type = " "; break;
1456 default: type = "??? "; break;
1458 memset(prot, ' ' , sizeof(prot)-1);
1459 prot[sizeof(prot)-1] = '\0';
1460 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1462 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1464 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1466 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1474 packet_reply_open(gdbctx);
1475 snprintf(buffer, sizeof(buffer),
1476 "%08lx %08lx %s %s %s\n",
1477 (DWORD)addr, mbi.RegionSize, state, type, prot);
1478 packet_reply_catc(gdbctx, 'O');
1479 packet_reply_hex_to_str(gdbctx, buffer);
1480 packet_reply_close(gdbctx);
1482 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1484 addr += mbi.RegionSize;
1486 packet_reply(gdbctx, "OK", 2);
1489 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1490 int len, const char* str)
1496 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1498 else if (len >= 2 && str[0] == '=')
1500 unsigned val = atoi(&str[1]);
1501 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1502 gdbctx->trace = val;
1506 /* FIXME: ugly but can use error packet here */
1507 packet_reply_cat(gdbctx, "E00");
1510 packet_reply_open(gdbctx);
1511 packet_reply_hex_to_str(gdbctx, buffer);
1512 packet_reply_close(gdbctx);
1520 void (*handler)(struct gdb_context*, int, const char*);
1523 {0, "wnd", 3, packet_query_monitor_wnd},
1524 {0, "window", 6, packet_query_monitor_wnd},
1525 {0, "proc", 4, packet_query_monitor_process},
1526 {0, "process", 7, packet_query_monitor_process},
1527 {0, "mem", 3, packet_query_monitor_mem},
1528 {1, "trace", 5, packet_query_monitor_trace},
1532 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1533 const char* hxcmd, size_t len)
1536 struct query_detail* qd;
1538 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1540 hex_from(buffer, hxcmd, len);
1542 for (qd = &query_details[0]; qd->name != NULL; qd++)
1544 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1545 if (!qd->with_arg && len != qd->len) continue;
1547 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1550 return packet_reply_error(gdbctx, EINVAL);
1553 static enum packet_return packet_query(struct gdb_context* gdbctx)
1555 switch (gdbctx->in_packet[0])
1558 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1560 struct dbg_thread* thd;
1562 packet_reply_open(gdbctx);
1563 packet_reply_add(gdbctx, "m", 1);
1564 for (thd = gdbctx->process->threads; thd; thd = thd->next)
1566 packet_reply_val(gdbctx, thd->tid, 4);
1567 if (thd->next != NULL)
1568 packet_reply_add(gdbctx, ",", 1);
1570 packet_reply_close(gdbctx);
1573 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1577 packet_reply_open(gdbctx);
1578 packet_reply_catc(gdbctx, 'O');
1579 get_process_info(gdbctx, result, sizeof(result));
1580 packet_reply_hex_to_str(gdbctx, result);
1581 packet_reply_close(gdbctx);
1586 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1588 packet_reply(gdbctx, "l", 1);
1591 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1593 packet_reply(gdbctx, "l", 1);
1598 if (gdbctx->in_packet_len == 1)
1600 struct dbg_thread* thd;
1601 /* FIXME: doc says 16 bit val ??? */
1602 /* grab first created thread, aka last in list */
1603 assert(gdbctx->process && gdbctx->process->threads);
1604 for (thd = gdbctx->process->threads; thd->next; thd = thd->next);
1605 packet_reply_open(gdbctx);
1606 packet_reply_add(gdbctx, "QC", 2);
1607 packet_reply_val(gdbctx, thd->tid, 4);
1608 packet_reply_close(gdbctx);
1613 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1617 if (gdbctx->wine_segs[0] == 0 && gdbctx->wine_segs[1] == 0 &&
1618 gdbctx->wine_segs[2] == 0)
1619 return packet_error;
1620 snprintf(buf, sizeof(buf),
1621 "Text=%08lx;Data=%08lx;Bss=%08lx",
1622 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1623 gdbctx->wine_segs[2]);
1624 return packet_reply(gdbctx, buf, -1);
1628 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1630 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1631 gdbctx->in_packet_len - 5);
1635 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1639 if (gdbctx->in_packet_len > 15 &&
1640 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1641 gdbctx->in_packet[15] == ',')
1647 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1648 if (end == NULL) break;
1649 get_thread_info(gdbctx, tid, result, sizeof(result));
1650 packet_reply_open(gdbctx);
1651 packet_reply_hex_to_str(gdbctx, result);
1652 packet_reply_close(gdbctx);
1657 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1658 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1659 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1660 return packet_error;
1663 static enum packet_return packet_step(struct gdb_context* gdbctx)
1665 /* FIXME: add support for address in packet */
1666 assert(gdbctx->in_packet_len == 0);
1667 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1668 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1669 fprintf(stderr, "NIY: step on %lu, while last thread is %lu\n",
1670 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1671 be_cpu->single_step(&gdbctx->context, TRUE);
1672 resume_debuggee(gdbctx, DBG_CONTINUE);
1673 wait_for_debuggee(gdbctx);
1674 be_cpu->single_step(&gdbctx->context, FALSE);
1675 return packet_reply_status(gdbctx);
1679 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1683 /* FIXME: add support for address in packet */
1684 assert(gdbctx->in_packet_len == 2);
1685 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1686 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1687 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1688 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1689 hex_from(&sig, gdbctx->in_packet, 1);
1690 /* cannot change signals on the fly */
1691 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1692 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1693 if (sig != gdbctx->last_sig)
1694 return packet_error;
1695 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1696 wait_for_debuggee(gdbctx);
1697 return packet_reply_status(gdbctx);
1701 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
1706 tid = strtol(gdbctx->in_packet, &end, 16);
1707 if (tid == -1 || tid == 0)
1708 return packet_reply_error(gdbctx, EINVAL);
1709 if (dbg_get_thread(gdbctx->process, tid) != NULL)
1711 return packet_reply_error(gdbctx, ESRCH);
1714 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
1718 struct gdb_ctx_Xpoint* xpt;
1719 enum be_xpoint_type t;
1721 /* FIXME: check packet_len */
1722 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1723 gdbctx->in_packet[1] != ',' ||
1724 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1725 return packet_error;
1726 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1727 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
1728 addr, len, gdbctx->in_packet[0]);
1729 switch (gdbctx->in_packet[0])
1731 case '0': t = be_xpoint_break; len = 0; break;
1732 case '1': t = be_xpoint_watch_exec; break;
1733 case '2': t = be_xpoint_watch_read; break;
1734 case '3': t = be_xpoint_watch_write; break;
1735 default: return packet_error;
1737 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
1739 if (xpt->addr == addr && xpt->type == t)
1741 if (be_cpu->remove_Xpoint(gdbctx->process->handle, &gdbctx->context,
1742 t, xpt->addr, xpt->val, len))
1750 return packet_error;
1753 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
1757 struct gdb_ctx_Xpoint* xpt;
1758 enum be_xpoint_type t;
1760 /* FIXME: check packet_len */
1761 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
1762 gdbctx->in_packet[1] != ',' ||
1763 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
1764 return packet_error;
1765 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1766 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
1767 addr, len, gdbctx->in_packet[0]);
1768 switch (gdbctx->in_packet[0])
1770 case '0': t = be_xpoint_break; len = 0; break;
1771 case '1': t = be_xpoint_watch_exec; break;
1772 case '2': t = be_xpoint_watch_read; break;
1773 case '3': t = be_xpoint_watch_write; break;
1774 default: return packet_error;
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 == t)
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 if (be_cpu->insert_Xpoint(gdbctx->process->handle, &gdbctx->context,
1788 t, addr, &xpt->val, len))
1794 fprintf(stderr, "cannot set xpoint\n");
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 * =============================================== *
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},
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 /* {'Q', packet_set}, */
1831 /* {'R', packet,restart}, only in extended mode ! */
1833 /*{'S', packet_step_signal}, hard(er) to implement */
1834 {'T', packet_thread_alive},
1835 {'v', packet_verbose},
1836 {'z', packet_remove_breakpoint},
1837 {'Z', packet_set_breakpoint},
1840 static BOOL extract_packets(struct gdb_context* gdbctx)
1844 unsigned char in_cksum, loc_cksum;
1846 enum packet_return ret = packet_error;
1849 while ((ret & packet_last_f) == 0)
1851 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
1852 fprintf(stderr, "In-buf: %*.*s\n",
1853 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1854 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
1855 if (ptr == NULL) return FALSE;
1856 if (ptr != gdbctx->in_buf)
1858 int glen = ptr - gdbctx->in_buf; /* garbage len */
1859 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1860 fprintf(stderr, "Removing garbage: %*.*s\n",
1861 glen, glen, gdbctx->in_buf);
1862 gdbctx->in_len -= glen;
1863 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
1865 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
1866 if (end == NULL) return FALSE;
1867 /* no checksum yet */
1868 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
1869 plen = end - gdbctx->in_buf - 1;
1870 hex_from(&in_cksum, end + 1, 1);
1871 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
1872 if (loc_cksum == in_cksum)
1874 if (num_packet == 0) {
1879 write(gdbctx->sock, "+", 1);
1882 /* FIXME: should use bsearch if packet_entries was sorted */
1883 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
1885 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
1887 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
1889 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1890 fprintf(stderr, "Unknown packet request %*.*s\n",
1891 plen, plen, &gdbctx->in_buf[1]);
1895 gdbctx->in_packet = gdbctx->in_buf + 2;
1896 gdbctx->in_packet_len = plen - 1;
1897 if (gdbctx->trace & GDBPXY_TRC_PACKET)
1898 fprintf(stderr, "Packet: %c%*.*s\n",
1900 gdbctx->in_packet_len, gdbctx->in_packet_len,
1902 ret = (packet_entries[i].handler)(gdbctx);
1904 switch (ret & ~packet_last_f)
1906 case packet_error: packet_reply(gdbctx, "", 0); break;
1907 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
1908 case packet_done: break;
1910 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1911 fprintf(stderr, "Reply-full: %*.*s\n",
1912 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
1913 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
1914 assert(i == gdbctx->out_len);
1915 /* if this fails, we'll have to use POLLOUT...
1917 gdbctx->out_len = 0;
1922 /* FIXME: if we have in our input buffer more than one packet,
1923 * it's very likely that we took too long to answer to a given packet
1924 * and gdb is sending us again the same packet
1925 * We simply drop the second packet. This will lower the risk of error,
1926 * but there's still some race conditions here
1927 * A better fix (yet not perfect) would be to have two threads:
1928 * - one managing the packets for gdb
1929 * - the second one managing the commands...
1930 * This would allow us also the reply with the '+' character (Ack of
1931 * the command) way sooner than what we do now
1933 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1934 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
1939 write(gdbctx->sock, "+", 1);
1940 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1941 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
1943 gdbctx->in_len -= plen + 4;
1944 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
1949 static int fetch_data(struct gdb_context* gdbctx)
1951 int len, in_len = gdbctx->in_len;
1953 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
1957 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
1958 gdbctx->in_buf = realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
1960 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1961 fprintf(stderr, "%d %d %*.*s\n",
1962 gdbctx->in_len, gdbctx->in_buf_alloc,
1963 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
1964 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
1965 if (len <= 0) break;
1966 gdbctx->in_len += len;
1967 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
1968 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
1970 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
1971 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
1972 return gdbctx->in_len - in_len;
1975 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
1979 const char* gdb_path;
1982 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
1983 strcpy(buf,"/tmp/winegdb.XXXXXX");
1984 fd = mkstemps(buf, 0);
1985 if (fd == -1) return FALSE;
1986 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
1987 fprintf(f, "file %s\n", wine_path);
1988 fprintf(f, "target remote localhost:%d\n", ntohs(port));
1989 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
1990 fprintf(f, "set prompt Wine-gdb>\\ \n");
1991 /* gdb 5.1 seems to require it, won't hurt anyway */
1992 fprintf(f, "sharedlibrary\n");
1993 /* This is needed (but not a decent & final fix)
1994 * Without this, gdb would skip our inter-DLL relay code (because
1995 * we don't have any line number information for the relay code)
1996 * With this, we will stop on first instruction of the stub, and
1997 * reusing step, will get us through the relay stub at the actual
1998 * function we're looking at.
2000 fprintf(f, "set step-mode on\n");
2001 /* tell gdb to delete this file when done handling it... */
2002 fprintf(f, "shell rm -f \"%s\"\n", buf);
2005 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2007 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2008 assert(0); /* never reached */
2012 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2015 struct sockaddr_in s_addrs;
2016 int s_len = sizeof(s_addrs);
2017 struct pollfd pollfd;
2018 IMAGEHLP_MODULE imh_mod;
2020 /* step 1: create socket for gdb connection request */
2021 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2023 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2024 fprintf(stderr, "Can't create socket");
2028 if (listen(sock, 1) == -1 ||
2029 getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2032 /* step 2: do the process internal creation */
2033 handle_debug_event(gdbctx, de);
2035 /* step3: get the wine loader name */
2036 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod)) return FALSE;
2038 /* step 4: fire up gdb (if requested) */
2040 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2044 case -1: /* error in parent... */
2045 fprintf(stderr, "Cannot create gdb\n");
2048 default: /* in parent... success */
2050 case 0: /* in child... and alive */
2051 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2052 /* if we're here, exec failed, so report failure */
2056 /* step 5: wait for gdb to connect actually */
2058 pollfd.events = POLLIN;
2061 switch (poll(&pollfd, 1, -1))
2064 if (pollfd.revents & POLLIN)
2067 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2068 if (gdbctx->sock == -1)
2070 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2071 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2072 /* don't keep our small packets too long: send them ASAP back to GDB
2073 * without this, GDB really crawls
2075 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2079 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2080 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2083 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2084 fprintf(stderr, "Poll for cnx failed (error)\n");
2094 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2100 gdbctx->in_buf = NULL;
2101 gdbctx->in_buf_alloc = 0;
2103 gdbctx->out_buf = NULL;
2104 gdbctx->out_buf_alloc = 0;
2105 gdbctx->out_len = 0;
2106 gdbctx->out_curr_packet = -1;
2108 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2109 gdbctx->last_sig = 0;
2110 gdbctx->in_trap = FALSE;
2111 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2112 gdbctx->process = NULL;
2113 for (i = 0; i < NUM_XPOINT; i++)
2114 gdbctx->Xpoints[i].type = -1;
2116 /* wait for first trap */
2117 while (WaitForDebugEvent(&de, INFINITE))
2119 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2121 /* this should be the first event we get,
2122 * and the only one of this type */
2123 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2124 /* gdbctx->dwProcessId = pid; */
2125 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2126 assert(!gdbctx->in_trap);
2130 handle_debug_event(gdbctx, &de);
2131 if (gdbctx->in_trap) break;
2133 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2138 BOOL gdb_remote(unsigned flags)
2140 struct pollfd pollfd;
2141 struct gdb_context gdbctx;
2144 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2146 pollfd.fd = gdbctx.sock;
2147 pollfd.events = POLLIN;
2150 switch (poll(&pollfd, 1, -1))
2154 if (pollfd.revents & (POLLHUP | POLLERR))
2156 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2157 fprintf(stderr, "Gdb hung up\n");
2158 /* kill also debuggee process - questionnable - */
2159 detach_debuggee(&gdbctx, TRUE);
2163 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2165 if (extract_packets(&gdbctx)) doLoop = FALSE;
2169 /* timeout, should never happen (infinite timeout) */
2172 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2173 fprintf(stderr, "Poll failed\n");