2 * A Win32 based proxy implementing the GBD remote protocol.
3 * This makes it possible to debug Wine (and any "emulated"
4 * program) under Linux using GDB.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* Protocol specification can be found here:
24 * http://sources.redhat.com/gdb/onlinedocs/gdb/Maintenance-Commands.html
28 #include "wine/port.h"
37 #ifdef HAVE_SYS_POLL_H
38 # include <sys/poll.h>
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
43 #ifdef HAVE_SYS_SOCKET_H
44 # include <sys/socket.h>
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
49 #ifdef HAVE_NETINET_TCP_H
50 # include <netinet/tcp.h>
56 /* if we don't have poll support on this system
57 * we won't provide gdb proxy support here...
67 #define GDBPXY_TRC_LOWLEVEL 0x01
68 #define GDBPXY_TRC_PACKET 0x02
69 #define GDBPXY_TRC_COMMAND 0x04
70 #define GDBPXY_TRC_COMMAND_ERROR 0x08
71 #define GDBPXY_TRC_WIN32_EVENT 0x10
72 #define GDBPXY_TRC_WIN32_ERROR 0x20
73 #define GDBPXY_TRC_COMMAND_FIXME 0x80
77 enum be_xpoint_type type; /* -1 means free */
90 /* split into individual packet */
98 /* generic GDB thread information */
99 struct dbg_thread* exec_thread; /* thread used in step & continue */
100 struct dbg_thread* other_thread; /* thread to be used in any other operation */
102 /* current Win32 trap env */
106 /* Win32 information */
107 struct dbg_process* process;
108 #define NUM_XPOINT 32
109 struct gdb_ctx_Xpoint Xpoints[NUM_XPOINT];
110 /* Unix environment */
111 unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
114 static BOOL tgt_process_gdbproxy_read(HANDLE hProcess, const void* addr,
115 void* buffer, SIZE_T len, SIZE_T* rlen)
117 return ReadProcessMemory( hProcess, addr, buffer, len, rlen );
120 static BOOL tgt_process_gdbproxy_write(HANDLE hProcess, void* addr,
121 const void* buffer, SIZE_T len, SIZE_T* wlen)
123 return WriteProcessMemory( hProcess, addr, buffer, len, wlen );
126 static struct be_process_io be_process_gdbproxy_io =
128 NULL, /* we shouldn't use close_process() in gdbproxy */
129 tgt_process_gdbproxy_read,
130 tgt_process_gdbproxy_write
133 /* =============================================== *
134 * B A S I C M A N I P U L A T I O N S *
135 * =============================================== *
138 static inline int hex_from0(char ch)
140 if (ch >= '0' && ch <= '9') return ch - '0';
141 if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
142 if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
148 static inline unsigned char hex_to0(int x)
150 assert(x >= 0 && x < 16);
151 return "0123456789abcdef"[x];
154 static int hex_to_int(const char* src, size_t len)
156 unsigned int returnval = 0;
160 returnval |= hex_from0(*src++);
165 static void hex_from(void* dst, const char* src, size_t len)
167 unsigned char *p = dst;
170 *p++ = (hex_from0(src[0]) << 4) | hex_from0(src[1]);
175 static void hex_to(char* dst, const void* src, size_t len)
177 const unsigned char *p = src;
180 *dst++ = hex_to0(*p >> 4);
181 *dst++ = hex_to0(*p & 0x0F);
186 static unsigned char checksum(const char* ptr, int len)
191 cksum += (unsigned char)*ptr++;
195 /* =============================================== *
196 * C P U H A N D L E R S *
197 * =============================================== *
200 /* This struct helps us to manage the different representations of a register:
201 * ctx_offset and ctx_length are the location and size in Win32 CONTEXT
202 * gdb_length is the length gdb expects on the wire
203 * As the two sizes could be different, we have to convert between the two
204 * (for example, on x86_64, Seg?s are 4 bytes on the wire and 2 in CONTEXT)
213 #define REG(r,gs) {FIELD_OFFSET(CONTEXT, r), sizeof(((CONTEXT*)NULL)->r), gs}
216 static const char target_xml[] = "";
217 static struct cpu_register cpu_register_map[] = {
235 #elif defined(__powerpc__)
236 static const char target_xml[] = "";
237 static struct cpu_register cpu_register_map[] = {
309 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
310 /* see gdb/nlm/ppc.c */
312 #elif defined(__x86_64__)
313 static const char target_xml[] = "";
314 static struct cpu_register cpu_register_map[] = {
340 #elif defined(__arm__)
341 static const char target_xml[] =
342 "l <target><architecture>arm</architecture>\n"
343 "<feature name=\"org.gnu.gdb.arm.core\">\n"
344 " <reg name=\"r0\" bitsize=\"32\" type=\"uint32\"/>\n"
345 " <reg name=\"r1\" bitsize=\"32\" type=\"uint32\"/>\n"
346 " <reg name=\"r2\" bitsize=\"32\" type=\"uint32\"/>\n"
347 " <reg name=\"r3\" bitsize=\"32\" type=\"uint32\"/>\n"
348 " <reg name=\"r4\" bitsize=\"32\" type=\"uint32\"/>\n"
349 " <reg name=\"r5\" bitsize=\"32\" type=\"uint32\"/>\n"
350 " <reg name=\"r6\" bitsize=\"32\" type=\"uint32\"/>\n"
351 " <reg name=\"r7\" bitsize=\"32\" type=\"uint32\"/>\n"
352 " <reg name=\"r8\" bitsize=\"32\" type=\"uint32\"/>\n"
353 " <reg name=\"r9\" bitsize=\"32\" type=\"uint32\"/>\n"
354 " <reg name=\"r10\" bitsize=\"32\" type=\"uint32\"/>\n"
355 " <reg name=\"r11\" bitsize=\"32\" type=\"uint32\"/>\n"
356 " <reg name=\"r12\" bitsize=\"32\" type=\"uint32\"/>\n"
357 " <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n"
358 " <reg name=\"lr\" bitsize=\"32\"/>\n"
359 " <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n"
360 " <reg name=\"cpsr\" bitsize=\"32\"/>\n"
361 "</feature></target>\n";
363 static struct cpu_register cpu_register_map[] = {
382 #elif defined(__aarch64__)
383 static const char target_xml[] = "";
384 static struct cpu_register cpu_register_map[] = {
421 # error Define the registers map for your CPU
425 static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
427 static inline void* cpu_register_ptr(CONTEXT* ctx, unsigned idx)
429 assert(idx < cpu_num_regs);
430 return (char*)ctx + cpu_register_map[idx].ctx_offset;
433 static inline DWORD64 cpu_register(CONTEXT* ctx, unsigned idx)
435 switch (cpu_register_map[idx].ctx_length)
437 case 2: return *(WORD*)cpu_register_ptr(ctx, idx);
438 case 4: return *(DWORD*)cpu_register_ptr(ctx, idx);
439 case 8: return *(DWORD64*)cpu_register_ptr(ctx, idx);
441 fprintf(stderr, "got unexpected size: %u\n", (unsigned)cpu_register_map[idx].ctx_length);
447 static inline void cpu_register_hex_from(CONTEXT* ctx, unsigned idx, const char** phex)
453 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
455 hex_from(&b, *phex, 1);
457 val += (DWORD64)b << (8 * i);
459 switch (cpu_register_map[idx].ctx_length)
461 case 2: *(WORD*)cpu_register_ptr(ctx, idx) = (WORD)val; break;
462 case 4: *(DWORD*)cpu_register_ptr(ctx, idx) = (DWORD)val; break;
463 case 8: *(DWORD64*)cpu_register_ptr(ctx, idx) = val; break;
468 /* =============================================== *
469 * W I N 3 2 D E B U G I N T E R F A C E *
470 * =============================================== *
473 static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
475 ctx->ContextFlags = CONTEXT_CONTROL
477 #ifdef CONTEXT_SEGMENTS
480 #ifdef CONTEXT_DEBUG_REGISTERS
481 | CONTEXT_DEBUG_REGISTERS
484 if (!GetThreadContext(h, ctx))
486 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
487 fprintf(stderr, "Can't get thread's context\n");
493 static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
495 EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
498 switch (rec->ExceptionCode)
500 case EXCEPTION_ACCESS_VIOLATION:
501 case EXCEPTION_PRIV_INSTRUCTION:
502 case EXCEPTION_STACK_OVERFLOW:
503 case EXCEPTION_GUARD_PAGE:
504 gdbctx->last_sig = SIGSEGV;
507 case EXCEPTION_DATATYPE_MISALIGNMENT:
508 gdbctx->last_sig = SIGBUS;
511 case EXCEPTION_SINGLE_STEP:
513 case EXCEPTION_BREAKPOINT:
514 gdbctx->last_sig = SIGTRAP;
517 case EXCEPTION_FLT_DENORMAL_OPERAND:
518 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
519 case EXCEPTION_FLT_INEXACT_RESULT:
520 case EXCEPTION_FLT_INVALID_OPERATION:
521 case EXCEPTION_FLT_OVERFLOW:
522 case EXCEPTION_FLT_STACK_CHECK:
523 case EXCEPTION_FLT_UNDERFLOW:
524 gdbctx->last_sig = SIGFPE;
527 case EXCEPTION_INT_DIVIDE_BY_ZERO:
528 case EXCEPTION_INT_OVERFLOW:
529 gdbctx->last_sig = SIGFPE;
532 case EXCEPTION_ILLEGAL_INSTRUCTION:
533 gdbctx->last_sig = SIGILL;
537 gdbctx->last_sig = SIGINT;
540 case STATUS_POSSIBLE_DEADLOCK:
541 gdbctx->last_sig = SIGALRM;
543 /* FIXME: we could also add here a O packet with additional information */
546 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
547 fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
548 gdbctx->last_sig = SIGABRT;
555 static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
562 dbg_curr_thread = dbg_get_thread(gdbctx->process, de->dwThreadId);
564 switch (de->dwDebugEventCode)
566 case CREATE_PROCESS_DEBUG_EVENT:
567 gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId,
568 de->u.CreateProcessInfo.hProcess);
569 if (!gdbctx->process) break;
570 memory_get_string_indirect(gdbctx->process,
571 de->u.CreateProcessInfo.lpImageName,
572 de->u.CreateProcessInfo.fUnicode,
573 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
574 dbg_set_process_name(gdbctx->process, u.buffer);
576 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
577 fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
578 de->dwProcessId, de->dwThreadId,
579 dbg_W2A(u.buffer, -1),
580 de->u.CreateProcessInfo.lpImageName,
581 de->u.CreateProcessInfo.lpStartAddress,
582 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
583 de->u.CreateProcessInfo.nDebugInfoSize);
585 /* de->u.CreateProcessInfo.lpStartAddress; */
586 if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
587 fprintf(stderr, "Couldn't initiate DbgHelp\n");
589 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
590 fprintf(stderr, "%04x:%04x: create thread I @%p\n",
591 de->dwProcessId, de->dwThreadId,
592 de->u.CreateProcessInfo.lpStartAddress);
594 assert(dbg_curr_thread == NULL); /* shouldn't be there */
595 dbg_add_thread(gdbctx->process, de->dwThreadId,
596 de->u.CreateProcessInfo.hThread,
597 de->u.CreateProcessInfo.lpThreadLocalBase);
600 case LOAD_DLL_DEBUG_EVENT:
601 assert(dbg_curr_thread);
602 memory_get_string_indirect(gdbctx->process,
603 de->u.LoadDll.lpImageName,
604 de->u.LoadDll.fUnicode,
605 u.buffer, sizeof(u.buffer) / sizeof(WCHAR));
606 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
607 fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
608 de->dwProcessId, de->dwThreadId,
609 dbg_W2A(u.buffer, -1),
610 de->u.LoadDll.lpBaseOfDll,
611 de->u.LoadDll.dwDebugInfoFileOffset,
612 de->u.LoadDll.nDebugInfoSize);
613 dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer,
614 (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
617 case UNLOAD_DLL_DEBUG_EVENT:
618 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
619 fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
620 de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
621 SymUnloadModule(gdbctx->process->handle,
622 (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
625 case EXCEPTION_DEBUG_EVENT:
626 assert(dbg_curr_thread);
627 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
628 fprintf(stderr, "%08x:%08x: exception code=0x%08x\n",
629 de->dwProcessId, de->dwThreadId,
630 de->u.Exception.ExceptionRecord.ExceptionCode);
632 if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
634 gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
638 case CREATE_THREAD_DEBUG_EVENT:
639 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
640 fprintf(stderr, "%08x:%08x: create thread D @%p\n",
641 de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
643 dbg_add_thread(gdbctx->process,
645 de->u.CreateThread.hThread,
646 de->u.CreateThread.lpThreadLocalBase);
649 case EXIT_THREAD_DEBUG_EVENT:
650 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
651 fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
652 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
654 assert(dbg_curr_thread);
655 if (dbg_curr_thread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
656 if (dbg_curr_thread == gdbctx->other_thread) gdbctx->other_thread = NULL;
657 dbg_del_thread(dbg_curr_thread);
660 case EXIT_PROCESS_DEBUG_EVENT:
661 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
662 fprintf(stderr, "%08x:%08x: exit process (%u)\n",
663 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
665 dbg_del_process(gdbctx->process);
666 gdbctx->process = NULL;
667 /* now signal gdb that we're done */
668 gdbctx->last_sig = SIGTERM;
669 gdbctx->in_trap = TRUE;
672 case OUTPUT_DEBUG_STRING_EVENT:
673 assert(dbg_curr_thread);
674 memory_get_string(gdbctx->process,
675 de->u.DebugString.lpDebugStringData, TRUE,
676 de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
677 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
678 fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
679 de->dwProcessId, de->dwThreadId, u.bufferA);
683 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
684 fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n",
685 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
686 de->u.RipInfo.dwType);
690 if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
691 fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
692 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
696 static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
700 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
701 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
702 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
703 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
704 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
705 fprintf(stderr, "Cannot continue on %04x (%x)\n",
706 dbg_curr_thread->tid, cont);
708 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
709 fprintf(stderr, "Cannot find last thread\n");
713 static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
718 if(dbg_curr_thread->tid == threadid){
719 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
720 if (!SetThreadContext(dbg_curr_thread->handle, &gdbctx->context))
721 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
722 fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid);
723 if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
724 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
725 fprintf(stderr, "Cannot continue on %04x (%x)\n",
726 dbg_curr_thread->tid, cont);
729 else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
730 fprintf(stderr, "Cannot find last thread\n");
733 static BOOL check_for_interrupt(struct gdb_context* gdbctx)
735 struct pollfd pollfd;
739 pollfd.fd = gdbctx->sock;
740 pollfd.events = POLLIN;
743 if ((ret = poll(&pollfd, 1, 0)) == 1) {
744 ret = read(gdbctx->sock, &pkt, 1);
746 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
747 fprintf(stderr, "read failed\n");
752 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
753 fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
758 } else if (ret == -1) {
759 fprintf(stderr, "poll failed\n");
764 static void wait_for_debuggee(struct gdb_context* gdbctx)
768 gdbctx->in_trap = FALSE;
771 if (!WaitForDebugEvent(&de, 10))
773 if (GetLastError() == ERROR_SEM_TIMEOUT)
775 if (check_for_interrupt(gdbctx)) {
776 if (!DebugBreakProcess(gdbctx->process->handle)) {
777 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) {
778 fprintf(stderr, "Failed to break into debugee\n");
782 WaitForDebugEvent(&de, INFINITE);
790 handle_debug_event(gdbctx, &de);
791 assert(!gdbctx->process ||
792 gdbctx->process->pid == 0 ||
793 de.dwProcessId == gdbctx->process->pid);
794 assert(!dbg_curr_thread || de.dwThreadId == dbg_curr_thread->tid);
795 if (gdbctx->in_trap) break;
796 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
800 static void detach_debuggee(struct gdb_context* gdbctx, BOOL kill)
802 be_cpu->single_step(&gdbctx->context, FALSE);
803 resume_debuggee(gdbctx, DBG_CONTINUE);
805 DebugActiveProcessStop(gdbctx->process->pid);
806 dbg_del_process(gdbctx->process);
807 gdbctx->process = NULL;
810 static void get_process_info(struct gdb_context* gdbctx, char* buffer, size_t len)
814 if (!GetExitCodeProcess(gdbctx->process->handle, &status))
816 strcpy(buffer, "Unknown process");
819 if (status == STILL_ACTIVE)
821 strcpy(buffer, "Running");
824 snprintf(buffer, len, "Terminated (%u)", status);
826 switch (GetPriorityClass(gdbctx->process->handle))
829 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
830 case ABOVE_NORMAL_PRIORITY_CLASS: strcat(buffer, ", above normal priority"); break;
832 #ifdef BELOW_NORMAL_PRIORITY_CLASS
833 case BELOW_NORMAL_PRIORITY_CLASS: strcat(buffer, ", below normal priotity"); break;
835 case HIGH_PRIORITY_CLASS: strcat(buffer, ", high priority"); break;
836 case IDLE_PRIORITY_CLASS: strcat(buffer, ", idle priority"); break;
837 case NORMAL_PRIORITY_CLASS: strcat(buffer, ", normal priority"); break;
838 case REALTIME_PRIORITY_CLASS: strcat(buffer, ", realtime priority"); break;
840 strcat(buffer, "\n");
843 static void get_thread_info(struct gdb_context* gdbctx, unsigned tid,
844 char* buffer, size_t len)
846 struct dbg_thread* thd;
850 /* FIXME: use the size of buffer */
851 thd = dbg_get_thread(gdbctx->process, tid);
854 strcpy(buffer, "No information");
857 if (GetExitCodeThread(thd->handle, &status))
859 if (status == STILL_ACTIVE)
861 /* FIXME: this is a bit brutal... some nicer way shall be found */
862 switch (status = SuspendThread(thd->handle))
865 case 0: strcpy(buffer, "Running"); break;
866 default: snprintf(buffer, len, "Suspended (%u)", status - 1);
868 ResumeThread(thd->handle);
871 snprintf(buffer, len, "Terminated (exit code = %u)", status);
875 strcpy(buffer, "Unknown threadID");
877 switch (prio = GetThreadPriority(thd->handle))
879 case THREAD_PRIORITY_ERROR_RETURN: break;
880 case THREAD_PRIORITY_ABOVE_NORMAL: strcat(buffer, ", priority +1 above normal"); break;
881 case THREAD_PRIORITY_BELOW_NORMAL: strcat(buffer, ", priority -1 below normal"); break;
882 case THREAD_PRIORITY_HIGHEST: strcat(buffer, ", priority +2 above normal"); break;
883 case THREAD_PRIORITY_LOWEST: strcat(buffer, ", priority -2 below normal"); break;
884 case THREAD_PRIORITY_IDLE: strcat(buffer, ", priority idle"); break;
885 case THREAD_PRIORITY_NORMAL: strcat(buffer, ", priority normal"); break;
886 case THREAD_PRIORITY_TIME_CRITICAL: strcat(buffer, ", priority time-critical"); break;
887 default: snprintf(buffer + strlen(buffer), len - strlen(buffer), ", priority = %d", prio);
889 assert(strlen(buffer) < len);
892 /* =============================================== *
893 * P A C K E T U T I L S *
894 * =============================================== *
897 enum packet_return {packet_error = 0x00, packet_ok = 0x01, packet_done = 0x02,
898 packet_last_f = 0x80};
900 static char* packet_realloc(char* buf, int size)
903 return HeapAlloc(GetProcessHeap(), 0, size);
904 return HeapReAlloc(GetProcessHeap(), 0, buf, size);
908 static void packet_reply_grow(struct gdb_context* gdbctx, size_t size)
910 if (gdbctx->out_buf_alloc < gdbctx->out_len + size)
912 gdbctx->out_buf_alloc = ((gdbctx->out_len + size) / 32 + 1) * 32;
913 gdbctx->out_buf = packet_realloc(gdbctx->out_buf, gdbctx->out_buf_alloc);
917 static void packet_reply_hex_to(struct gdb_context* gdbctx, const void* src, int len)
919 packet_reply_grow(gdbctx, len * 2);
920 hex_to(&gdbctx->out_buf[gdbctx->out_len], src, len);
921 gdbctx->out_len += len * 2;
924 static inline void packet_reply_hex_to_str(struct gdb_context* gdbctx, const char* src)
926 packet_reply_hex_to(gdbctx, src, strlen(src));
929 static void packet_reply_val(struct gdb_context* gdbctx, unsigned long val, int len)
933 shift = (len - 1) * 8;
934 packet_reply_grow(gdbctx, len * 2);
935 for (i = 0; i < len; i++, shift -= 8)
937 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> (shift + 4)) & 0x0F);
938 gdbctx->out_buf[gdbctx->out_len++] = hex_to0((val >> shift ) & 0x0F);
942 static inline void packet_reply_add(struct gdb_context* gdbctx, const char* str, int len)
944 packet_reply_grow(gdbctx, len);
945 memcpy(&gdbctx->out_buf[gdbctx->out_len], str, len);
946 gdbctx->out_len += len;
949 static inline void packet_reply_cat(struct gdb_context* gdbctx, const char* str)
951 packet_reply_add(gdbctx, str, strlen(str));
954 static inline void packet_reply_catc(struct gdb_context* gdbctx, char ch)
956 packet_reply_add(gdbctx, &ch, 1);
959 static void packet_reply_open(struct gdb_context* gdbctx)
961 assert(gdbctx->out_curr_packet == -1);
962 packet_reply_catc(gdbctx, '$');
963 gdbctx->out_curr_packet = gdbctx->out_len;
966 static void packet_reply_close(struct gdb_context* gdbctx)
971 plen = gdbctx->out_len - gdbctx->out_curr_packet;
972 packet_reply_catc(gdbctx, '#');
973 cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
974 packet_reply_hex_to(gdbctx, &cksum, 1);
975 if (gdbctx->trace & GDBPXY_TRC_PACKET)
976 fprintf(stderr, "Reply : %*.*s\n",
977 plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
978 gdbctx->out_curr_packet = -1;
981 static enum packet_return packet_reply(struct gdb_context* gdbctx, const char* packet, int len)
983 packet_reply_open(gdbctx);
985 if (len == -1) len = strlen(packet);
986 assert(memchr(packet, '$', len) == NULL && memchr(packet, '#', len) == NULL);
988 packet_reply_add(gdbctx, packet, len);
990 packet_reply_close(gdbctx);
995 static enum packet_return packet_reply_error(struct gdb_context* gdbctx, int error)
997 packet_reply_open(gdbctx);
999 packet_reply_add(gdbctx, "E", 1);
1000 packet_reply_val(gdbctx, error, 1);
1002 packet_reply_close(gdbctx);
1007 static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, unsigned idx)
1009 DWORD64 val = cpu_register(&gdbctx->context, idx);
1012 for (i = 0; i < cpu_register_map[idx].gdb_length; i++)
1015 packet_reply_hex_to(gdbctx, &b, 1);
1020 /* =============================================== *
1021 * P A C K E T H A N D L E R S *
1022 * =============================================== *
1025 static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
1027 enum packet_return ret = packet_done;
1029 packet_reply_open(gdbctx);
1031 if (gdbctx->process != NULL)
1036 packet_reply_catc(gdbctx, 'T');
1037 sig = gdbctx->last_sig;
1038 packet_reply_val(gdbctx, sig, 1);
1039 packet_reply_add(gdbctx, "thread:", 7);
1040 packet_reply_val(gdbctx, dbg_curr_thread->tid, 4);
1041 packet_reply_catc(gdbctx, ';');
1043 for (i = 0; i < cpu_num_regs; i++)
1045 /* FIXME: this call will also grow the buffer...
1046 * unneeded, but not harmful
1048 packet_reply_val(gdbctx, i, 1);
1049 packet_reply_catc(gdbctx, ':');
1050 packet_reply_register_hex_to(gdbctx, i);
1051 packet_reply_catc(gdbctx, ';');
1056 /* Try to put an exit code
1057 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1058 * just indicate the end of process and exit */
1059 packet_reply_add(gdbctx, "W00", 3);
1060 /*if (!gdbctx->extended)*/ ret |= packet_last_f;
1063 packet_reply_close(gdbctx);
1069 static enum packet_return packet_extended(struct gdb_context* gdbctx)
1071 gdbctx->extended = 1;
1076 static enum packet_return packet_last_signal(struct gdb_context* gdbctx)
1078 assert(gdbctx->in_packet_len == 0);
1079 return packet_reply_status(gdbctx);
1082 static enum packet_return packet_continue(struct gdb_context* gdbctx)
1084 /* FIXME: add support for address in packet */
1085 assert(gdbctx->in_packet_len == 0);
1086 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1087 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1088 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1089 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1090 resume_debuggee(gdbctx, DBG_CONTINUE);
1091 wait_for_debuggee(gdbctx);
1092 return packet_reply_status(gdbctx);
1095 static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
1098 int defaultAction = -1; /* magic non action */
1101 int actionIndex[20]; /* allow for up to 20 actions */
1102 int threadIndex[20];
1103 int threadCount = 0;
1104 unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
1105 unsigned int threadID = 0;
1106 struct dbg_thread* thd;
1108 /* OK we have vCont followed by..
1110 * c for packet_continue
1111 * Csig for packet_continue_signal
1113 * Ssig for step signal
1114 * and then an optional thread ID at the end..
1115 * *******************************************/
1118 if (gdbctx->in_packet[4] == '?')
1123 The vCont packet is supported. Each action is a supported command in the vCont packet.
1125 The vCont packet is not supported. (this didn't seem to be obeyed!)
1127 packet_reply_open(gdbctx);
1128 packet_reply_add(gdbctx, "vCont", 5);
1129 /* add all the supported actions to the reply (all of them for now) */
1130 packet_reply_add(gdbctx, ";c", 2);
1131 packet_reply_add(gdbctx, ";C", 2);
1132 packet_reply_add(gdbctx, ";s", 2);
1133 packet_reply_add(gdbctx, ";S", 2);
1134 packet_reply_close(gdbctx);
1138 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1139 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1140 now if only gdb talked XML.... */
1141 #if 0 /* handy for debugging */
1142 fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
1145 /* go through the packet and identify where all the actions start at */
1146 for (i = 4; i < gdbctx->in_packet_len - 1; i++)
1148 if (gdbctx->in_packet[i] == ';')
1150 threadIndex[actions] = 0;
1151 actionIndex[actions++] = i;
1153 else if (gdbctx->in_packet[i] == ':')
1155 threadIndex[actions - 1] = i;
1159 /* now look up the default action */
1160 for (i = 0 ; i < actions; i++)
1162 if (threadIndex[i] == 0)
1164 if (defaultAction != -1)
1166 fprintf(stderr,"Too many default actions specified\n");
1167 return packet_error;
1173 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1175 /* go through all the threads and stick their ids in the to be done list. */
1176 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1178 threadIDs[threadCount++] = thd->tid;
1179 /* check to see if we have more threads than I counted on, and tell the user what to do
1180 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1181 if (threadCount == 100)
1183 fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1188 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1189 * that remains is to apply the actions to the threads and the default action to any threads
1191 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1192 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1193 fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
1194 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1196 /* deal with the threaded stuff first */
1197 for (i = 0; i < actions ; i++)
1199 if (threadIndex[i] != 0)
1201 int j, idLength = 0;
1202 if (i < actions - 1)
1204 idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
1208 idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
1211 threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
1212 /* process the action */
1213 switch (gdbctx->in_packet[actionIndex[i] + 1])
1215 case 's': /* step */
1216 be_cpu->single_step(&gdbctx->context, TRUE);
1218 case 'c': /* continue */
1219 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1221 case 'S': /* step Sig, */
1222 be_cpu->single_step(&gdbctx->context, TRUE);
1224 case 'C': /* continue sig */
1225 hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
1226 /* cannot change signals on the fly */
1227 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1228 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1229 if (sig != gdbctx->last_sig)
1230 return packet_error;
1231 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1234 for (j = 0 ; j < threadCount; j++)
1236 if (threadIDs[j] == threadID)
1243 } /* for i=0 ; i< actions */
1245 /* now we have manage the default action */
1246 if (defaultAction >= 0)
1248 for (i = 0 ; i< threadCount; i++)
1250 /* check to see if we've already done something to the thread*/
1251 if (threadIDs[i] != 0)
1253 /* if not apply the default action*/
1254 threadID = threadIDs[i];
1255 /* process the action (yes this is almost identical to the one above!) */
1256 switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
1258 case 's': /* step */
1259 be_cpu->single_step(&gdbctx->context, TRUE);
1261 case 'c': /* continue */
1262 resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
1265 be_cpu->single_step(&gdbctx->context, TRUE);
1267 case 'C': /* continue sig */
1268 hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
1269 /* cannot change signals on the fly */
1270 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1271 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1272 if (sig != gdbctx->last_sig)
1273 return packet_error;
1274 resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
1279 } /* if(defaultAction >=0) */
1281 wait_for_debuggee(gdbctx);
1282 be_cpu->single_step(&gdbctx->context, FALSE);
1283 return packet_reply_status(gdbctx);
1286 struct verbose_defail
1290 enum packet_return (*handler)(struct gdb_context*);
1291 } verbose_details[] =
1293 /* {"Attach", 6}, */
1294 {"Cont", 4, packet_verbose_cont},
1304 static enum packet_return packet_verbose(struct gdb_context* gdbctx)
1309 for (klen = 0; ; klen++)
1311 if (klen == gdbctx->in_packet_len ||
1312 gdbctx->in_packet[klen] == ';' ||
1313 gdbctx->in_packet[klen] == ':' ||
1314 gdbctx->in_packet[klen] == '?')
1316 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1317 fprintf(stderr, "trying to process a verbose packet %*.*s\n",
1318 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1319 for (i = 0; i < sizeof(verbose_details)/sizeof(verbose_details[0]); i++)
1321 if (klen == verbose_details[i].len &&
1322 !memcmp(gdbctx->in_packet, verbose_details[i].name, verbose_details[i].len))
1324 return verbose_details[i].handler(gdbctx);
1327 /* no matching handler found, abort */
1332 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1333 fprintf(stderr, "No support for verbose packet %*.*s\n",
1334 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1335 return packet_error;
1338 static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
1342 /* FIXME: add support for address in packet */
1343 assert(gdbctx->in_packet_len == 2);
1344 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1345 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1346 fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
1347 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1348 hex_from(&sig, gdbctx->in_packet, 1);
1349 /* cannot change signals on the fly */
1350 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1351 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
1352 if (sig != gdbctx->last_sig)
1353 return packet_error;
1354 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
1355 wait_for_debuggee(gdbctx);
1356 return packet_reply_status(gdbctx);
1359 static enum packet_return packet_detach(struct gdb_context* gdbctx)
1361 detach_debuggee(gdbctx, FALSE);
1362 return packet_ok | packet_last_f;
1365 static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
1369 CONTEXT* pctx = &gdbctx->context;
1371 assert(gdbctx->in_trap);
1373 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1375 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1376 return packet_error;
1379 packet_reply_open(gdbctx);
1380 for (i = 0; i < cpu_num_regs; i++)
1382 packet_reply_register_hex_to(gdbctx, i);
1384 packet_reply_close(gdbctx);
1388 static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
1392 CONTEXT* pctx = &gdbctx->context;
1395 assert(gdbctx->in_trap);
1396 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1398 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1399 return packet_error;
1401 if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
1403 ptr = gdbctx->in_packet;
1404 for (i = 0; i < cpu_num_regs; i++)
1406 cpu_register_hex_from(pctx, i, &ptr);
1408 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1410 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1411 fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid);
1412 return packet_error;
1417 static enum packet_return packet_kill(struct gdb_context* gdbctx)
1419 detach_debuggee(gdbctx, TRUE);
1421 if (!gdbctx->extended)
1422 /* dunno whether GDB cares or not */
1426 /* assume we can't really answer something here */
1427 /* return packet_done; */
1430 static enum packet_return packet_thread(struct gdb_context* gdbctx)
1435 switch (gdbctx->in_packet[0])
1439 if (gdbctx->in_packet[1] == '-')
1440 thread = -strtol(gdbctx->in_packet + 2, &end, 16);
1442 thread = strtol(gdbctx->in_packet + 1, &end, 16);
1443 if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
1445 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1446 fprintf(stderr, "Cannot get threadid %*.*s\n",
1447 gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
1448 gdbctx->in_packet + 1);
1449 return packet_error;
1451 if (gdbctx->in_packet[0] == 'c')
1452 gdbctx->exec_thread = dbg_get_thread(gdbctx->process, thread);
1454 gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
1457 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1458 fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
1459 return packet_error;
1463 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
1466 unsigned int len, blk_len, nread;
1470 assert(gdbctx->in_trap);
1471 /* FIXME:check in_packet_len for reading %p,%x */
1472 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
1473 if (len <= 0) return packet_error;
1474 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1475 fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
1476 for (nread = 0; nread < len; nread += r, addr += r)
1478 blk_len = min(sizeof(buffer), len - nread);
1479 if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
1482 /* fail at first address, return error */
1483 if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
1484 /* something has already been read, return partial information */
1487 if (nread == 0) packet_reply_open(gdbctx);
1488 packet_reply_hex_to(gdbctx, buffer, r);
1490 packet_reply_close(gdbctx);
1494 static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
1497 unsigned int len, blk_len;
1502 assert(gdbctx->in_trap);
1503 ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
1506 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1507 fprintf(stderr, "Cannot find ':' in %*.*s\n",
1508 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1509 return packet_error;
1513 if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
1515 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1516 fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
1517 return packet_error;
1519 if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
1521 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1522 fprintf(stderr, "Wrong sizes %u <> %u\n",
1523 (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
1524 return packet_error;
1526 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1527 fprintf(stderr, "Write %u bytes at %p\n", len, addr);
1530 blk_len = min(sizeof(buffer), len);
1531 hex_from(buffer, ptr, blk_len);
1532 if (!gdbctx->process->process_io->write(gdbctx->process->handle, addr, buffer, blk_len, &w) ||
1539 return packet_ok; /* FIXME: error while writing ? */
1542 static enum packet_return packet_read_register(struct gdb_context* gdbctx)
1546 CONTEXT* pctx = &gdbctx->context;
1548 assert(gdbctx->in_trap);
1549 reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
1550 if (reg >= cpu_num_regs)
1552 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1553 fprintf(stderr, "Register out of bounds %x\n", reg);
1554 return packet_error;
1556 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1558 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1559 return packet_error;
1561 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1562 fprintf(stderr, "Read register %x => %08x%08x\n", reg,
1563 (unsigned)(cpu_register(pctx, reg) >> 32), (unsigned)cpu_register(pctx, reg));
1564 packet_reply_open(gdbctx);
1565 packet_reply_register_hex_to(gdbctx, reg);
1566 packet_reply_close(gdbctx);
1570 static enum packet_return packet_write_register(struct gdb_context* gdbctx)
1575 CONTEXT* pctx = &gdbctx->context;
1577 assert(gdbctx->in_trap);
1579 reg = strtoul(gdbctx->in_packet, &ptr, 16);
1580 if (ptr == NULL || reg >= cpu_num_regs || *ptr++ != '=')
1582 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1583 fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
1584 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1585 * it wouldn't matter too much, and it fakes our support for all regs
1587 return (ptr == NULL) ? packet_error : packet_ok;
1589 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
1591 int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet);
1592 fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
1595 if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
1597 if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
1598 return packet_error;
1601 cpu_register_hex_from(pctx, reg, (const char**)&ptr);
1602 if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
1604 if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
1605 fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid);
1606 return packet_error;
1612 static void packet_query_monitor_wnd_helper(struct gdb_context* gdbctx, HWND hWnd, int indent)
1620 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
1621 strcpy(clsName, "-- Unknown --");
1622 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
1623 strcpy(wndName, "-- Empty --");
1625 packet_reply_open(gdbctx);
1626 packet_reply_catc(gdbctx, 'O');
1627 snprintf(buffer, sizeof(buffer),
1628 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1629 indent, "", (ULONG_PTR)hWnd, 13 - indent, "",
1630 clsName, GetWindowLongW(hWnd, GWL_STYLE),
1631 ADDRWIDTH, (ULONG_PTR)GetWindowLongPtrW(hWnd, GWLP_WNDPROC),
1633 packet_reply_hex_to_str(gdbctx, buffer);
1634 packet_reply_close(gdbctx);
1636 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
1637 packet_query_monitor_wnd_helper(gdbctx, child, indent + 1);
1638 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
1641 static void packet_query_monitor_wnd(struct gdb_context* gdbctx, int len, const char* str)
1645 /* we do the output in several 'O' packets, with the last one being just OK for
1646 * marking the end of the output */
1647 packet_reply_open(gdbctx);
1648 packet_reply_catc(gdbctx, 'O');
1649 snprintf(buffer, sizeof(buffer),
1650 "%-16.16s %-17.17s %-8.8s %s\n",
1651 "hwnd", "Class Name", " Style", " WndProc Text");
1652 packet_reply_hex_to_str(gdbctx, buffer);
1653 packet_reply_close(gdbctx);
1655 /* FIXME: could also add a pmt to this command in str... */
1656 packet_query_monitor_wnd_helper(gdbctx, GetDesktopWindow(), 0);
1657 packet_reply(gdbctx, "OK", 2);
1660 static void packet_query_monitor_process(struct gdb_context* gdbctx, int len, const char* str)
1662 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1665 PROCESSENTRY32 entry;
1668 if (snap == INVALID_HANDLE_VALUE)
1671 entry.dwSize = sizeof(entry);
1672 ok = Process32First(snap, &entry);
1674 /* we do the output in several 'O' packets, with the last one being just OK for
1675 * marking the end of the output */
1677 packet_reply_open(gdbctx);
1678 packet_reply_catc(gdbctx, 'O');
1679 snprintf(buffer, sizeof(buffer),
1680 " %-8.8s %-8.8s %-8.8s %s\n",
1681 "pid", "threads", "parent", "executable");
1682 packet_reply_hex_to_str(gdbctx, buffer);
1683 packet_reply_close(gdbctx);
1688 if (entry.th32ProcessID == gdbctx->process->pid) deco = '>';
1689 packet_reply_open(gdbctx);
1690 packet_reply_catc(gdbctx, 'O');
1691 snprintf(buffer, sizeof(buffer),
1692 "%c%08x %-8d %08x '%s'\n",
1693 deco, entry.th32ProcessID, entry.cntThreads,
1694 entry.th32ParentProcessID, entry.szExeFile);
1695 packet_reply_hex_to_str(gdbctx, buffer);
1696 packet_reply_close(gdbctx);
1697 ok = Process32Next(snap, &entry);
1700 packet_reply(gdbctx, "OK", 2);
1703 static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const char* str)
1705 MEMORY_BASIC_INFORMATION mbi;
1712 /* we do the output in several 'O' packets, with the last one being just OK for
1713 * marking the end of the output */
1714 packet_reply_open(gdbctx);
1715 packet_reply_catc(gdbctx, 'O');
1716 packet_reply_hex_to_str(gdbctx, "Address Size State Type RWX\n");
1717 packet_reply_close(gdbctx);
1719 while (VirtualQueryEx(gdbctx->process->handle, addr, &mbi, sizeof(mbi)) >= sizeof(mbi))
1723 case MEM_COMMIT: state = "commit "; break;
1724 case MEM_FREE: state = "free "; break;
1725 case MEM_RESERVE: state = "reserve"; break;
1726 default: state = "??? "; break;
1728 if (mbi.State != MEM_FREE)
1732 case MEM_IMAGE: type = "image "; break;
1733 case MEM_MAPPED: type = "mapped "; break;
1734 case MEM_PRIVATE: type = "private"; break;
1735 case 0: type = " "; break;
1736 default: type = "??? "; break;
1738 memset(prot, ' ' , sizeof(prot)-1);
1739 prot[sizeof(prot)-1] = '\0';
1740 if (mbi.AllocationProtect & (PAGE_READONLY|PAGE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1742 if (mbi.AllocationProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
1744 if (mbi.AllocationProtect & (PAGE_WRITECOPY|PAGE_EXECUTE_WRITECOPY))
1746 if (mbi.AllocationProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))
1754 packet_reply_open(gdbctx);
1755 snprintf(buffer, sizeof(buffer), "%0*lx %0*lx %s %s %s\n",
1756 (unsigned)sizeof(void*), (DWORD_PTR)addr,
1757 (unsigned)sizeof(void*), mbi.RegionSize, state, type, prot);
1758 packet_reply_catc(gdbctx, 'O');
1759 packet_reply_hex_to_str(gdbctx, buffer);
1760 packet_reply_close(gdbctx);
1762 if (addr + mbi.RegionSize < addr) /* wrap around ? */
1764 addr += mbi.RegionSize;
1766 packet_reply(gdbctx, "OK", 2);
1769 static void packet_query_monitor_trace(struct gdb_context* gdbctx,
1770 int len, const char* str)
1776 snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
1778 else if (len >= 2 && str[0] == '=')
1780 unsigned val = atoi(&str[1]);
1781 snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
1782 gdbctx->trace = val;
1786 /* FIXME: ugly but can use error packet here */
1787 packet_reply_cat(gdbctx, "E00");
1790 packet_reply_open(gdbctx);
1791 packet_reply_hex_to_str(gdbctx, buffer);
1792 packet_reply_close(gdbctx);
1800 void (*handler)(struct gdb_context*, int, const char*);
1803 {0, "wnd", 3, packet_query_monitor_wnd},
1804 {0, "window", 6, packet_query_monitor_wnd},
1805 {0, "proc", 4, packet_query_monitor_process},
1806 {0, "process", 7, packet_query_monitor_process},
1807 {0, "mem", 3, packet_query_monitor_mem},
1808 {1, "trace", 5, packet_query_monitor_trace},
1812 static enum packet_return packet_query_remote_command(struct gdb_context* gdbctx,
1813 const char* hxcmd, size_t len)
1816 struct query_detail* qd;
1818 assert((len & 1) == 0 && len < 2 * sizeof(buffer));
1820 hex_from(buffer, hxcmd, len);
1822 for (qd = query_details; qd->name != NULL; qd++)
1824 if (len < qd->len || strncmp(buffer, qd->name, qd->len) != 0) continue;
1825 if (!qd->with_arg && len != qd->len) continue;
1827 (qd->handler)(gdbctx, len - qd->len, buffer + qd->len);
1830 return packet_reply_error(gdbctx, EINVAL);
1833 static enum packet_return packet_query(struct gdb_context* gdbctx)
1835 switch (gdbctx->in_packet[0])
1838 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1840 struct dbg_thread* thd;
1842 packet_reply_open(gdbctx);
1843 packet_reply_add(gdbctx, "m", 1);
1844 LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
1846 packet_reply_val(gdbctx, thd->tid, 4);
1847 if (list_next(&gdbctx->process->threads, &thd->entry) != NULL)
1848 packet_reply_add(gdbctx, ",", 1);
1850 packet_reply_close(gdbctx);
1853 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1857 packet_reply_open(gdbctx);
1858 packet_reply_catc(gdbctx, 'O');
1859 get_process_info(gdbctx, result, sizeof(result));
1860 packet_reply_hex_to_str(gdbctx, result);
1861 packet_reply_close(gdbctx);
1866 if (strncmp(gdbctx->in_packet + 1, "ThreadInfo", gdbctx->in_packet_len - 1) == 0)
1868 packet_reply(gdbctx, "l", 1);
1871 else if (strncmp(gdbctx->in_packet + 1, "ProcessInfo", gdbctx->in_packet_len - 1) == 0)
1873 packet_reply(gdbctx, "l", 1);
1878 if (strncmp(gdbctx->in_packet, "Attached", gdbctx->in_packet_len) == 0)
1884 return packet_reply(gdbctx, buf, -1);
1888 if (gdbctx->in_packet_len == 1)
1890 struct dbg_thread* thd;
1891 /* FIXME: doc says 16 bit val ??? */
1892 /* grab first created thread, aka last in list */
1893 assert(gdbctx->process && !list_empty(&gdbctx->process->threads));
1894 thd = LIST_ENTRY(list_tail(&gdbctx->process->threads), struct dbg_thread, entry);
1895 packet_reply_open(gdbctx);
1896 packet_reply_add(gdbctx, "QC", 2);
1897 packet_reply_val(gdbctx, thd->tid, 4);
1898 packet_reply_close(gdbctx);
1903 if (strncmp(gdbctx->in_packet, "Offsets", gdbctx->in_packet_len) == 0)
1907 snprintf(buf, sizeof(buf),
1908 "Text=%08lx;Data=%08lx;Bss=%08lx",
1909 gdbctx->wine_segs[0], gdbctx->wine_segs[1],
1910 gdbctx->wine_segs[2]);
1911 return packet_reply(gdbctx, buf, -1);
1915 if (gdbctx->in_packet_len > 5 && strncmp(gdbctx->in_packet, "Rcmd,", 5) == 0)
1917 return packet_query_remote_command(gdbctx, gdbctx->in_packet + 5,
1918 gdbctx->in_packet_len - 5);
1922 if (strncmp(gdbctx->in_packet, "Symbol::", gdbctx->in_packet_len) == 0)
1924 if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
1926 if (strlen(target_xml))
1927 return packet_reply(gdbctx, "PacketSize=400;qXfer:features:read+", -1);
1930 /* no features supported */
1931 packet_reply_open(gdbctx);
1932 packet_reply_close(gdbctx);
1938 if (gdbctx->in_packet_len > 15 &&
1939 strncmp(gdbctx->in_packet, "ThreadExtraInfo", 15) == 0 &&
1940 gdbctx->in_packet[15] == ',')
1946 tid = strtol(gdbctx->in_packet + 16, &end, 16);
1947 if (end == NULL) break;
1948 get_thread_info(gdbctx, tid, result, sizeof(result));
1949 packet_reply_open(gdbctx);
1950 packet_reply_hex_to_str(gdbctx, result);
1951 packet_reply_close(gdbctx);
1954 if (strncmp(gdbctx->in_packet, "TStatus", 7) == 0)
1956 /* Tracepoints not supported */
1957 packet_reply_open(gdbctx);
1958 packet_reply_close(gdbctx);
1963 if (strlen(target_xml) && strncmp(gdbctx->in_packet, "Xfer:features:read:target.xml", 29) == 0)
1964 return packet_reply(gdbctx, target_xml, -1);
1967 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1968 fprintf(stderr, "Unknown or malformed query %*.*s\n",
1969 gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
1970 return packet_error;
1973 static enum packet_return packet_step(struct gdb_context* gdbctx)
1975 /* FIXME: add support for address in packet */
1976 assert(gdbctx->in_packet_len == 0);
1977 if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
1978 if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
1979 fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
1980 gdbctx->exec_thread->tid, dbg_curr_thread->tid);
1981 be_cpu->single_step(&gdbctx->context, TRUE);
1982 resume_debuggee(gdbctx, DBG_CONTINUE);
1983 wait_for_debuggee(gdbctx);
1984 be_cpu->single_step(&gdbctx->context, FALSE);
1985 return packet_reply_status(gdbctx);
1989 static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
1993 /* FIXME: add support for address in packet */
1994 assert(gdbctx->in_packet_len == 2);
1995 if (dbg_curr_thread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
1996 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
1997 fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
1998 gdbctx->exec_thread, DEBUG_CurrThread->tid);
1999 hex_from(&sig, gdbctx->in_packet, 1);
2000 /* cannot change signals on the fly */
2001 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2002 fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
2003 if (sig != gdbctx->last_sig)
2004 return packet_error;
2005 resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
2006 wait_for_debuggee(gdbctx);
2007 return packet_reply_status(gdbctx);
2011 static enum packet_return packet_thread_alive(struct gdb_context* gdbctx)
2016 tid = strtol(gdbctx->in_packet, &end, 16);
2017 if (tid == -1 || tid == 0)
2018 return packet_reply_error(gdbctx, EINVAL);
2019 if (dbg_get_thread(gdbctx->process, tid) != NULL)
2021 return packet_reply_error(gdbctx, ESRCH);
2024 static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
2028 struct gdb_ctx_Xpoint* xpt;
2029 enum be_xpoint_type t;
2031 /* FIXME: check packet_len */
2032 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2033 gdbctx->in_packet[1] != ',' ||
2034 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2035 return packet_error;
2036 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2037 fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
2038 addr, len, gdbctx->in_packet[0]);
2039 switch (gdbctx->in_packet[0])
2041 case '0': t = be_xpoint_break; len = 0; break;
2042 case '1': t = be_xpoint_watch_exec; break;
2043 case '2': t = be_xpoint_watch_read; break;
2044 case '3': t = be_xpoint_watch_write; break;
2045 default: return packet_error;
2047 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2049 if (xpt->addr == addr && xpt->type == t)
2051 if (be_cpu->remove_Xpoint(gdbctx->process->handle,
2052 gdbctx->process->process_io, &gdbctx->context,
2053 t, xpt->addr, xpt->val, len))
2061 return packet_error;
2064 static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
2068 struct gdb_ctx_Xpoint* xpt;
2069 enum be_xpoint_type t;
2071 /* FIXME: check packet_len */
2072 if (gdbctx->in_packet[0] < '0' || gdbctx->in_packet[0] > '4' ||
2073 gdbctx->in_packet[1] != ',' ||
2074 sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
2075 return packet_error;
2076 if (gdbctx->trace & GDBPXY_TRC_COMMAND)
2077 fprintf(stderr, "Set bp %p[%u] typ=%c\n",
2078 addr, len, gdbctx->in_packet[0]);
2079 switch (gdbctx->in_packet[0])
2081 case '0': t = be_xpoint_break; len = 0; break;
2082 case '1': t = be_xpoint_watch_exec; break;
2083 case '2': t = be_xpoint_watch_read; break;
2084 case '3': t = be_xpoint_watch_write; break;
2085 default: return packet_error;
2087 /* because of packet command handling, this should be made idempotent */
2088 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2090 if (xpt->addr == addr && xpt->type == t)
2091 return packet_ok; /* nothing to do */
2093 /* really set the Xpoint */
2094 for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
2096 if (xpt->type == -1)
2098 if (be_cpu->insert_Xpoint(gdbctx->process->handle,
2099 gdbctx->process->process_io, &gdbctx->context,
2100 t, addr, &xpt->val, len))
2106 fprintf(stderr, "cannot set xpoint\n");
2110 /* no more entries... eech */
2111 fprintf(stderr, "Running out of spots for {break|watch}points\n");
2112 return packet_error;
2115 /* =============================================== *
2116 * P A C K E T I N F R A S T R U C T U R E *
2117 * =============================================== *
2123 enum packet_return (*handler)(struct gdb_context* gdbctx);
2126 static struct packet_entry packet_entries[] =
2128 /*{'!', packet_extended}, */
2129 {'?', packet_last_signal},
2130 {'c', packet_continue},
2131 {'C', packet_continue_signal},
2132 {'D', packet_detach},
2133 {'g', packet_read_registers},
2134 {'G', packet_write_registers},
2136 {'H', packet_thread},
2137 {'m', packet_read_memory},
2138 {'M', packet_write_memory},
2139 {'p', packet_read_register},
2140 {'P', packet_write_register},
2141 {'q', packet_query},
2142 /* {'Q', packet_set}, */
2143 /* {'R', packet,restart}, only in extended mode ! */
2145 /*{'S', packet_step_signal}, hard(er) to implement */
2146 {'T', packet_thread_alive},
2147 {'v', packet_verbose},
2148 {'z', packet_remove_breakpoint},
2149 {'Z', packet_set_breakpoint},
2152 static BOOL extract_packets(struct gdb_context* gdbctx)
2156 unsigned char in_cksum, loc_cksum;
2158 enum packet_return ret = packet_error;
2161 while ((ret & packet_last_f) == 0)
2163 if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
2164 fprintf(stderr, "In-buf: %*.*s\n",
2165 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2166 ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
2167 if (ptr == NULL) return FALSE;
2168 if (ptr != gdbctx->in_buf)
2170 int glen = ptr - gdbctx->in_buf; /* garbage len */
2171 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2172 fprintf(stderr, "Removing garbage: %*.*s\n",
2173 glen, glen, gdbctx->in_buf);
2174 gdbctx->in_len -= glen;
2175 memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
2177 end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
2178 if (end == NULL) return FALSE;
2179 /* no checksum yet */
2180 if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
2181 plen = end - gdbctx->in_buf - 1;
2182 hex_from(&in_cksum, end + 1, 1);
2183 loc_cksum = checksum(gdbctx->in_buf + 1, plen);
2184 if (loc_cksum == in_cksum)
2186 if (num_packet == 0) {
2191 write(gdbctx->sock, "+", 1);
2194 /* FIXME: should use bsearch if packet_entries was sorted */
2195 for (i = 0; i < sizeof(packet_entries)/sizeof(packet_entries[0]); i++)
2197 if (packet_entries[i].key == gdbctx->in_buf[1]) break;
2199 if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
2201 if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
2202 fprintf(stderr, "Unknown packet request %*.*s\n",
2203 plen, plen, &gdbctx->in_buf[1]);
2207 gdbctx->in_packet = gdbctx->in_buf + 2;
2208 gdbctx->in_packet_len = plen - 1;
2209 if (gdbctx->trace & GDBPXY_TRC_PACKET)
2210 fprintf(stderr, "Packet: %c%*.*s\n",
2212 gdbctx->in_packet_len, gdbctx->in_packet_len,
2214 ret = (packet_entries[i].handler)(gdbctx);
2216 switch (ret & ~packet_last_f)
2218 case packet_error: packet_reply(gdbctx, "", 0); break;
2219 case packet_ok: packet_reply(gdbctx, "OK", 2); break;
2220 case packet_done: break;
2222 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2223 fprintf(stderr, "Reply-full: %*.*s\n",
2224 gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
2225 i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
2226 assert(i == gdbctx->out_len);
2227 /* if this fails, we'll have to use POLLOUT...
2229 gdbctx->out_len = 0;
2234 /* FIXME: If we have more than one packet in our input buffer,
2235 * it's very likely that we took too long to answer to a given packet
2236 * and gdb is sending us the same packet again.
2237 * So we simply drop the second packet. This will lower the risk of error,
2238 * but there's still some race conditions here.
2239 * A better fix (yet not perfect) would be to have two threads:
2240 * - one managing the packets for gdb
2241 * - the second one managing the commands...
2242 * This would allow us to send the reply with the '+' character (Ack of
2243 * the command) way sooner than we do now.
2245 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2246 fprintf(stderr, "Dropping packet, I was too slow to respond\n");
2251 write(gdbctx->sock, "+", 1);
2252 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2253 fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
2255 gdbctx->in_len -= plen + 4;
2256 memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
2261 static int fetch_data(struct gdb_context* gdbctx)
2263 int len, in_len = gdbctx->in_len;
2265 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2269 if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
2270 gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
2272 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2273 fprintf(stderr, "%d %d %*.*s\n",
2274 gdbctx->in_len, gdbctx->in_buf_alloc,
2275 gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
2276 len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
2277 if (len <= 0) break;
2278 gdbctx->in_len += len;
2279 assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
2280 if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
2282 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2283 fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
2284 return gdbctx->in_len - in_len;
2287 #define FLAG_NO_START 1
2288 #define FLAG_WITH_XTERM 2
2290 static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
2294 const char* gdb_path;
2297 if (!(gdb_path = getenv("WINE_GDB"))) gdb_path = "gdb";
2298 strcpy(buf,"/tmp/winegdb.XXXXXX");
2299 fd = mkstemps(buf, 0);
2300 if (fd == -1) return FALSE;
2301 if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
2302 fprintf(f, "file %s\n", wine_path);
2303 fprintf(f, "target remote localhost:%d\n", ntohs(port));
2304 fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
2305 fprintf(f, "set prompt Wine-gdb>\\ \n");
2306 /* gdb 5.1 seems to require it, won't hurt anyway */
2307 fprintf(f, "sharedlibrary\n");
2308 /* This is needed (but not a decent & final fix)
2309 * Without this, gdb would skip our inter-DLL relay code (because
2310 * we don't have any line number information for the relay code)
2311 * With this, we will stop on first instruction of the stub, and
2312 * reusing step, will get us through the relay stub at the actual
2313 * function we're looking at.
2315 fprintf(f, "set step-mode on\n");
2316 /* tell gdb to delete this file when done handling it... */
2317 fprintf(f, "shell rm -f \"%s\"\n", buf);
2319 if (flags & FLAG_WITH_XTERM)
2320 execlp("xterm", "xterm", "-e", gdb_path, "-x", buf, NULL);
2322 execlp(gdb_path, gdb_path, "-x", buf, NULL);
2323 assert(0); /* never reached */
2327 static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned flags)
2330 struct sockaddr_in s_addrs;
2331 socklen_t s_len = sizeof(s_addrs);
2332 struct pollfd pollfd;
2333 IMAGEHLP_MODULE64 imh_mod;
2336 /* step 1: create socket for gdb connection request */
2337 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2339 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2340 fprintf(stderr, "Can't create socket");
2344 if (listen(sock, 1) == -1 || getsockname(sock, (struct sockaddr*)&s_addrs, &s_len) == -1)
2347 /* step 2: do the process internal creation */
2348 handle_debug_event(gdbctx, de);
2350 /* step3: get the wine loader name */
2351 if (!dbg_get_debuggee_info(gdbctx->process->handle, &imh_mod))
2354 /* step 4: fire up gdb (if requested) */
2355 if (flags & FLAG_NO_START)
2356 fprintf(stderr, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
2360 case -1: /* error in parent... */
2361 fprintf(stderr, "Cannot create gdb\n");
2363 default: /* in parent... success */
2364 signal(SIGINT, SIG_IGN);
2366 case 0: /* in child... and alive */
2367 gdb_exec(imh_mod.LoadedImageName, s_addrs.sin_port, flags);
2368 /* if we're here, exec failed, so report failure */
2372 /* step 5: wait for gdb to connect actually */
2374 pollfd.events = POLLIN;
2377 switch (poll(&pollfd, 1, -1))
2380 if (pollfd.revents & POLLIN)
2383 gdbctx->sock = accept(sock, (struct sockaddr*)&s_addrs, &s_len);
2384 if (gdbctx->sock == -1)
2387 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2388 fprintf(stderr, "Connected on %d\n", gdbctx->sock);
2389 /* don't keep our small packets too long: send them ASAP back to GDB
2390 * without this, GDB really crawls
2392 setsockopt(gdbctx->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&dummy, sizeof(dummy));
2396 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2397 fprintf(stderr, "Poll for cnx failed (timeout)\n");
2400 if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
2401 fprintf(stderr, "Poll for cnx failed (error)\n");
2412 static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
2418 gdbctx->in_buf = NULL;
2419 gdbctx->in_buf_alloc = 0;
2421 gdbctx->out_buf = NULL;
2422 gdbctx->out_buf_alloc = 0;
2423 gdbctx->out_len = 0;
2424 gdbctx->out_curr_packet = -1;
2426 gdbctx->exec_thread = gdbctx->other_thread = NULL;
2427 gdbctx->last_sig = 0;
2428 gdbctx->in_trap = FALSE;
2429 gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
2430 gdbctx->process = NULL;
2431 for (i = 0; i < NUM_XPOINT; i++)
2432 gdbctx->Xpoints[i].type = -1;
2433 for (i = 0; i < sizeof(gdbctx->wine_segs) / sizeof(gdbctx->wine_segs[0]); i++)
2434 gdbctx->wine_segs[i] = 0;
2436 /* wait for first trap */
2437 while (WaitForDebugEvent(&de, INFINITE))
2439 if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
2441 /* this should be the first event we get,
2442 * and the only one of this type */
2443 assert(gdbctx->process == NULL && de.dwProcessId == dbg_curr_pid);
2444 /* gdbctx->dwProcessId = pid; */
2445 if (!gdb_startup(gdbctx, &de, flags)) return FALSE;
2446 assert(!gdbctx->in_trap);
2450 handle_debug_event(gdbctx, &de);
2451 if (gdbctx->in_trap) break;
2453 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
2458 static int gdb_remote(unsigned flags)
2460 struct pollfd pollfd;
2461 struct gdb_context gdbctx;
2464 for (doLoop = gdb_init_context(&gdbctx, flags); doLoop;)
2466 pollfd.fd = gdbctx.sock;
2467 pollfd.events = POLLIN;
2470 switch (poll(&pollfd, 1, -1))
2474 if (pollfd.revents & (POLLHUP | POLLERR))
2476 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2477 fprintf(stderr, "Gdb hung up\n");
2478 /* kill also debuggee process - questionnable - */
2479 detach_debuggee(&gdbctx, TRUE);
2483 if ((pollfd.revents & POLLIN) && fetch_data(&gdbctx) > 0)
2485 if (extract_packets(&gdbctx)) doLoop = FALSE;
2489 /* timeout, should never happen (infinite timeout) */
2492 if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
2493 fprintf(stderr, "Poll failed\n");
2503 int gdb_main(int argc, char* argv[])
2506 unsigned gdb_flags = 0;
2509 while (argc > 0 && argv[0][0] == '-')
2511 if (strcmp(argv[0], "--no-start") == 0)
2513 gdb_flags |= FLAG_NO_START;
2517 if (strcmp(argv[0], "--with-xterm") == 0)
2519 gdb_flags |= FLAG_WITH_XTERM;
2525 if (dbg_active_attach(argc, argv) == start_ok ||
2526 dbg_active_launch(argc, argv) == start_ok)
2527 return gdb_remote(gdb_flags);
2529 fprintf(stderr, "GdbProxy mode not supported on this platform\n");