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 struct cpu_register cpu_register_map
[] = {
234 #elif defined(__powerpc__)
235 static struct cpu_register cpu_register_map
[] = {
307 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
308 /* see gdb/nlm/ppc.c */
310 #elif defined(__x86_64__)
311 static struct cpu_register cpu_register_map
[] = {
337 #elif defined(__sparc__)
338 static struct cpu_register cpu_register_map
[] = {
372 #elif defined(__arm__)
373 static struct cpu_register cpu_register_map
[] = {
391 #elif defined(__aarch64__)
392 static struct cpu_register cpu_register_map
[] = {
429 # error Define the registers map for your CPU
433 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
435 static inline void* cpu_register_ptr(CONTEXT
* ctx
, unsigned idx
)
437 assert(idx
< cpu_num_regs
);
438 return (char*)ctx
+ cpu_register_map
[idx
].ctx_offset
;
441 static inline DWORD64
cpu_register(CONTEXT
* ctx
, unsigned idx
)
443 switch (cpu_register_map
[idx
].ctx_length
)
445 case 2: return *(WORD
*)cpu_register_ptr(ctx
, idx
);
446 case 4: return *(DWORD
*)cpu_register_ptr(ctx
, idx
);
447 case 8: return *(DWORD64
*)cpu_register_ptr(ctx
, idx
);
449 fprintf(stderr
, "got unexpected size: %u\n", (unsigned)cpu_register_map
[idx
].ctx_length
);
454 static inline void cpu_register_hex_from(CONTEXT
* ctx
, unsigned idx
, const char** phex
)
460 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
462 hex_from(&b
, *phex
, 1);
464 val
+= (DWORD64
)b
<< (8 * i
);
466 switch (cpu_register_map
[idx
].ctx_length
)
468 case 2: *(WORD
*)cpu_register_ptr(ctx
, idx
) = (WORD
)val
; break;
469 case 4: *(DWORD
*)cpu_register_ptr(ctx
, idx
) = (DWORD
)val
; break;
470 case 8: *(DWORD64
*)cpu_register_ptr(ctx
, idx
) = val
; break;
475 /* =============================================== *
476 * W I N 3 2 D E B U G I N T E R F A C E *
477 * =============================================== *
480 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
482 ctx
->ContextFlags
= CONTEXT_CONTROL
484 #ifdef CONTEXT_SEGMENTS
487 #ifdef CONTEXT_DEBUG_REGISTERS
488 | CONTEXT_DEBUG_REGISTERS
491 if (!GetThreadContext(h
, ctx
))
493 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
494 fprintf(stderr
, "Can't get thread's context\n");
500 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
502 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
505 switch (rec
->ExceptionCode
)
507 case EXCEPTION_ACCESS_VIOLATION
:
508 case EXCEPTION_PRIV_INSTRUCTION
:
509 case EXCEPTION_STACK_OVERFLOW
:
510 case EXCEPTION_GUARD_PAGE
:
511 gdbctx
->last_sig
= SIGSEGV
;
514 case EXCEPTION_DATATYPE_MISALIGNMENT
:
515 gdbctx
->last_sig
= SIGBUS
;
518 case EXCEPTION_SINGLE_STEP
:
520 case EXCEPTION_BREAKPOINT
:
521 gdbctx
->last_sig
= SIGTRAP
;
524 case EXCEPTION_FLT_DENORMAL_OPERAND
:
525 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
526 case EXCEPTION_FLT_INEXACT_RESULT
:
527 case EXCEPTION_FLT_INVALID_OPERATION
:
528 case EXCEPTION_FLT_OVERFLOW
:
529 case EXCEPTION_FLT_STACK_CHECK
:
530 case EXCEPTION_FLT_UNDERFLOW
:
531 gdbctx
->last_sig
= SIGFPE
;
534 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
535 case EXCEPTION_INT_OVERFLOW
:
536 gdbctx
->last_sig
= SIGFPE
;
539 case EXCEPTION_ILLEGAL_INSTRUCTION
:
540 gdbctx
->last_sig
= SIGILL
;
544 gdbctx
->last_sig
= SIGINT
;
547 case STATUS_POSSIBLE_DEADLOCK
:
548 gdbctx
->last_sig
= SIGALRM
;
550 /* FIXME: we could also add here a O packet with additional information */
553 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
554 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
555 gdbctx
->last_sig
= SIGABRT
;
562 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
569 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
571 switch (de
->dwDebugEventCode
)
573 case CREATE_PROCESS_DEBUG_EVENT
:
574 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
575 de
->u
.CreateProcessInfo
.hProcess
);
576 if (!gdbctx
->process
) break;
577 memory_get_string_indirect(gdbctx
->process
,
578 de
->u
.CreateProcessInfo
.lpImageName
,
579 de
->u
.CreateProcessInfo
.fUnicode
,
580 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
581 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
583 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
584 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
585 de
->dwProcessId
, de
->dwThreadId
,
586 dbg_W2A(u
.buffer
, -1),
587 de
->u
.CreateProcessInfo
.lpImageName
,
588 de
->u
.CreateProcessInfo
.lpStartAddress
,
589 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
590 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
592 /* de->u.CreateProcessInfo.lpStartAddress; */
593 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
594 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
596 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
597 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
598 de
->dwProcessId
, de
->dwThreadId
,
599 de
->u
.CreateProcessInfo
.lpStartAddress
);
601 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
602 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
603 de
->u
.CreateProcessInfo
.hThread
,
604 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
607 case LOAD_DLL_DEBUG_EVENT
:
608 assert(dbg_curr_thread
);
609 memory_get_string_indirect(gdbctx
->process
,
610 de
->u
.LoadDll
.lpImageName
,
611 de
->u
.LoadDll
.fUnicode
,
612 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
613 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
614 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
615 de
->dwProcessId
, de
->dwThreadId
,
616 dbg_W2A(u
.buffer
, -1),
617 de
->u
.LoadDll
.lpBaseOfDll
,
618 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
619 de
->u
.LoadDll
.nDebugInfoSize
);
620 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
621 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
624 case UNLOAD_DLL_DEBUG_EVENT
:
625 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
626 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
627 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
628 SymUnloadModule(gdbctx
->process
->handle
,
629 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
632 case EXCEPTION_DEBUG_EVENT
:
633 assert(dbg_curr_thread
);
634 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
635 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
636 de
->dwProcessId
, de
->dwThreadId
,
637 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
639 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
641 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
645 case CREATE_THREAD_DEBUG_EVENT
:
646 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
647 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
648 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
650 dbg_add_thread(gdbctx
->process
,
652 de
->u
.CreateThread
.hThread
,
653 de
->u
.CreateThread
.lpThreadLocalBase
);
656 case EXIT_THREAD_DEBUG_EVENT
:
657 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
658 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
659 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
661 assert(dbg_curr_thread
);
662 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
663 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
664 dbg_del_thread(dbg_curr_thread
);
667 case EXIT_PROCESS_DEBUG_EVENT
:
668 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
669 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
670 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
672 dbg_del_process(gdbctx
->process
);
673 gdbctx
->process
= NULL
;
674 /* now signal gdb that we're done */
675 gdbctx
->last_sig
= SIGTERM
;
676 gdbctx
->in_trap
= TRUE
;
679 case OUTPUT_DEBUG_STRING_EVENT
:
680 assert(dbg_curr_thread
);
681 memory_get_string(gdbctx
->process
,
682 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
683 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
684 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
685 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
686 de
->dwProcessId
, de
->dwThreadId
, u
.bufferA
);
690 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
691 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
692 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
693 de
->u
.RipInfo
.dwType
);
697 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
698 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
699 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
703 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
707 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
708 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
709 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
710 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
711 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
712 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
713 dbg_curr_thread
->tid
, cont
);
715 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
716 fprintf(stderr
, "Cannot find last thread\n");
720 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
725 if(dbg_curr_thread
->tid
== threadid
){
726 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
727 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
728 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
729 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
730 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
731 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
732 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
733 dbg_curr_thread
->tid
, cont
);
736 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
737 fprintf(stderr
, "Cannot find last thread\n");
740 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
742 struct pollfd pollfd
;
746 pollfd
.fd
= gdbctx
->sock
;
747 pollfd
.events
= POLLIN
;
750 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
751 ret
= read(gdbctx
->sock
, &pkt
, 1);
753 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
754 fprintf(stderr
, "read failed\n");
759 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
760 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
765 } else if (ret
== -1) {
766 fprintf(stderr
, "poll failed\n");
771 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
775 gdbctx
->in_trap
= FALSE
;
778 if (!WaitForDebugEvent(&de
, 10))
780 if (GetLastError() == ERROR_SEM_TIMEOUT
)
782 if (check_for_interrupt(gdbctx
)) {
783 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
784 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
785 fprintf(stderr
, "Failed to break into debugee\n");
789 WaitForDebugEvent(&de
, INFINITE
);
797 handle_debug_event(gdbctx
, &de
);
798 assert(!gdbctx
->process
||
799 gdbctx
->process
->pid
== 0 ||
800 de
.dwProcessId
== gdbctx
->process
->pid
);
801 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
802 if (gdbctx
->in_trap
) break;
803 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
807 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
809 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
810 resume_debuggee(gdbctx
, DBG_CONTINUE
);
812 DebugActiveProcessStop(gdbctx
->process
->pid
);
813 dbg_del_process(gdbctx
->process
);
814 gdbctx
->process
= NULL
;
817 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
821 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
823 strcpy(buffer
, "Unknown process");
826 if (status
== STILL_ACTIVE
)
828 strcpy(buffer
, "Running");
831 snprintf(buffer
, len
, "Terminated (%u)", status
);
833 switch (GetPriorityClass(gdbctx
->process
->handle
))
836 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
837 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
839 #ifdef BELOW_NORMAL_PRIORITY_CLASS
840 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
842 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
843 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
844 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
845 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
847 strcat(buffer
, "\n");
850 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
851 char* buffer
, size_t len
)
853 struct dbg_thread
* thd
;
857 /* FIXME: use the size of buffer */
858 thd
= dbg_get_thread(gdbctx
->process
, tid
);
861 strcpy(buffer
, "No information");
864 if (GetExitCodeThread(thd
->handle
, &status
))
866 if (status
== STILL_ACTIVE
)
868 /* FIXME: this is a bit brutal... some nicer way shall be found */
869 switch (status
= SuspendThread(thd
->handle
))
872 case 0: strcpy(buffer
, "Running"); break;
873 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
875 ResumeThread(thd
->handle
);
878 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
882 strcpy(buffer
, "Unknown threadID");
884 switch (prio
= GetThreadPriority(thd
->handle
))
886 case THREAD_PRIORITY_ERROR_RETURN
: break;
887 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
888 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
889 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
890 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
891 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
892 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
893 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
894 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
896 assert(strlen(buffer
) < len
);
899 /* =============================================== *
900 * P A C K E T U T I L S *
901 * =============================================== *
904 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
905 packet_last_f
= 0x80};
907 static char* packet_realloc(char* buf
, int size
)
910 return HeapAlloc(GetProcessHeap(), 0, size
);
911 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
915 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
917 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
919 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
920 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
924 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
926 packet_reply_grow(gdbctx
, len
* 2);
927 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
928 gdbctx
->out_len
+= len
* 2;
931 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
933 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
936 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
940 shift
= (len
- 1) * 8;
941 packet_reply_grow(gdbctx
, len
* 2);
942 for (i
= 0; i
< len
; i
++, shift
-= 8)
944 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
945 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
949 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
951 packet_reply_grow(gdbctx
, len
);
952 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
953 gdbctx
->out_len
+= len
;
956 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
958 packet_reply_add(gdbctx
, str
, strlen(str
));
961 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
963 packet_reply_add(gdbctx
, &ch
, 1);
966 static void packet_reply_open(struct gdb_context
* gdbctx
)
968 assert(gdbctx
->out_curr_packet
== -1);
969 packet_reply_catc(gdbctx
, '$');
970 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
973 static void packet_reply_close(struct gdb_context
* gdbctx
)
978 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
979 packet_reply_catc(gdbctx
, '#');
980 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
981 packet_reply_hex_to(gdbctx
, &cksum
, 1);
982 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
983 fprintf(stderr
, "Reply : %*.*s\n",
984 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
985 gdbctx
->out_curr_packet
= -1;
988 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
990 packet_reply_open(gdbctx
);
992 if (len
== -1) len
= strlen(packet
);
993 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
995 packet_reply_add(gdbctx
, packet
, len
);
997 packet_reply_close(gdbctx
);
1002 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
1004 packet_reply_open(gdbctx
);
1006 packet_reply_add(gdbctx
, "E", 1);
1007 packet_reply_val(gdbctx
, error
, 1);
1009 packet_reply_close(gdbctx
);
1014 static inline void packet_reply_register_hex_to(struct gdb_context
* gdbctx
, unsigned idx
)
1016 DWORD64 val
= cpu_register(&gdbctx
->context
, idx
);
1019 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
1022 packet_reply_hex_to(gdbctx
, &b
, 1);
1027 /* =============================================== *
1028 * P A C K E T H A N D L E R S *
1029 * =============================================== *
1032 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
1034 enum packet_return ret
= packet_done
;
1036 packet_reply_open(gdbctx
);
1038 if (gdbctx
->process
!= NULL
)
1043 packet_reply_catc(gdbctx
, 'T');
1044 sig
= gdbctx
->last_sig
;
1045 packet_reply_val(gdbctx
, sig
, 1);
1046 packet_reply_add(gdbctx
, "thread:", 7);
1047 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
1048 packet_reply_catc(gdbctx
, ';');
1050 for (i
= 0; i
< cpu_num_regs
; i
++)
1052 /* FIXME: this call will also grow the buffer...
1053 * unneeded, but not harmful
1055 packet_reply_val(gdbctx
, i
, 1);
1056 packet_reply_catc(gdbctx
, ':');
1057 packet_reply_register_hex_to(gdbctx
, i
);
1058 packet_reply_catc(gdbctx
, ';');
1063 /* Try to put an exit code
1064 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1065 * just indicate the end of process and exit */
1066 packet_reply_add(gdbctx
, "W00", 3);
1067 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
1070 packet_reply_close(gdbctx
);
1076 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
1078 gdbctx
->extended
= 1;
1083 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
1085 assert(gdbctx
->in_packet_len
== 0);
1086 return packet_reply_status(gdbctx
);
1089 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
1091 /* FIXME: add support for address in packet */
1092 assert(gdbctx
->in_packet_len
== 0);
1093 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1094 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1095 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1096 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1097 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1098 wait_for_debuggee(gdbctx
);
1099 return packet_reply_status(gdbctx
);
1102 static enum packet_return
packet_verbose_cont(struct gdb_context
* gdbctx
)
1105 int defaultAction
= -1; /* magic non action */
1108 int actionIndex
[20]; /* allow for up to 20 actions */
1109 int threadIndex
[20];
1110 int threadCount
= 0;
1111 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1112 unsigned int threadID
= 0;
1113 struct dbg_thread
* thd
;
1115 /* OK we have vCont followed by..
1117 * c for packet_continue
1118 * Csig for packet_continue_signal
1120 * Ssig for step signal
1121 * and then an optional thread ID at the end..
1122 * *******************************************/
1125 if (gdbctx
->in_packet
[4] == '?')
1130 The vCont packet is supported. Each action is a supported command in the vCont packet.
1132 The vCont packet is not supported. (this didn't seem to be obeyed!)
1134 packet_reply_open(gdbctx
);
1135 packet_reply_add(gdbctx
, "vCont", 5);
1136 /* add all the supported actions to the reply (all of them for now) */
1137 packet_reply_add(gdbctx
, ";c", 2);
1138 packet_reply_add(gdbctx
, ";C", 2);
1139 packet_reply_add(gdbctx
, ";s", 2);
1140 packet_reply_add(gdbctx
, ";S", 2);
1141 packet_reply_close(gdbctx
);
1145 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1146 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1147 now if only gdb talked XML.... */
1148 #if 0 /* handy for debugging */
1149 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1152 /* go through the packet and identify where all the actions start at */
1153 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1155 if (gdbctx
->in_packet
[i
] == ';')
1157 threadIndex
[actions
] = 0;
1158 actionIndex
[actions
++] = i
;
1160 else if (gdbctx
->in_packet
[i
] == ':')
1162 threadIndex
[actions
- 1] = i
;
1166 /* now look up the default action */
1167 for (i
= 0 ; i
< actions
; i
++)
1169 if (threadIndex
[i
] == 0)
1171 if (defaultAction
!= -1)
1173 fprintf(stderr
,"Too many default actions specified\n");
1174 return packet_error
;
1180 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1182 /* go through all the threads and stick their ids in the to be done list. */
1183 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1185 threadIDs
[threadCount
++] = thd
->tid
;
1186 /* check to see if we have more threads than I counted on, and tell the user what to do
1187 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1188 if (threadCount
== 100)
1190 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1195 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1196 * that remains is to apply the actions to the threads and the default action to any threads
1198 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1199 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1200 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1201 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1203 /* deal with the threaded stuff first */
1204 for (i
= 0; i
< actions
; i
++)
1206 if (threadIndex
[i
] != 0)
1208 int j
, idLength
= 0;
1209 if (i
< actions
- 1)
1211 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1215 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1218 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1219 /* process the action */
1220 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1222 case 's': /* step */
1223 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1225 case 'c': /* continue */
1226 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1228 case 'S': /* step Sig, */
1229 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1231 case 'C': /* continue sig */
1232 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1233 /* cannot change signals on the fly */
1234 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1235 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1236 if (sig
!= gdbctx
->last_sig
)
1237 return packet_error
;
1238 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1241 for (j
= 0 ; j
< threadCount
; j
++)
1243 if (threadIDs
[j
] == threadID
)
1250 } /* for i=0 ; i< actions */
1252 /* now we have manage the default action */
1253 if (defaultAction
>= 0)
1255 for (i
= 0 ; i
< threadCount
; i
++)
1257 /* check to see if we've already done something to the thread*/
1258 if (threadIDs
[i
] != 0)
1260 /* if not apply the default action*/
1261 threadID
= threadIDs
[i
];
1262 /* process the action (yes this is almost identical to the one above!) */
1263 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1265 case 's': /* step */
1266 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1268 case 'c': /* continue */
1269 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1272 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1274 case 'C': /* continue sig */
1275 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1276 /* cannot change signals on the fly */
1277 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1278 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1279 if (sig
!= gdbctx
->last_sig
)
1280 return packet_error
;
1281 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1286 } /* if(defaultAction >=0) */
1288 wait_for_debuggee(gdbctx
);
1289 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1290 return packet_reply_status(gdbctx
);
1293 struct verbose_defail
1297 enum packet_return (*handler
)(struct gdb_context
*);
1298 } verbose_details
[] =
1300 /* {"Attach", 6}, */
1301 {"Cont", 4, packet_verbose_cont
},
1311 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1316 for (klen
= 0; ; klen
++)
1318 if (klen
== gdbctx
->in_packet_len
||
1319 gdbctx
->in_packet
[klen
] == ';' ||
1320 gdbctx
->in_packet
[klen
] == ':' ||
1321 gdbctx
->in_packet
[klen
] == '?')
1323 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1324 fprintf(stderr
, "trying to process a verbose packet %*.*s\n",
1325 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1326 for (i
= 0; i
< sizeof(verbose_details
)/sizeof(verbose_details
[0]); i
++)
1328 if (klen
== verbose_details
[i
].len
&&
1329 !memcmp(gdbctx
->in_packet
, verbose_details
[i
].name
, verbose_details
[i
].len
))
1331 return verbose_details
[i
].handler(gdbctx
);
1334 /* no matching handler found, abort */
1339 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1340 fprintf(stderr
, "No support for verbose packet %*.*s\n",
1341 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1342 return packet_error
;
1345 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1349 /* FIXME: add support for address in packet */
1350 assert(gdbctx
->in_packet_len
== 2);
1351 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1352 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1353 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1354 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1355 hex_from(&sig
, gdbctx
->in_packet
, 1);
1356 /* cannot change signals on the fly */
1357 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1358 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1359 if (sig
!= gdbctx
->last_sig
)
1360 return packet_error
;
1361 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1362 wait_for_debuggee(gdbctx
);
1363 return packet_reply_status(gdbctx
);
1366 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1368 detach_debuggee(gdbctx
, FALSE
);
1369 return packet_ok
| packet_last_f
;
1372 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1376 CONTEXT
* pctx
= &gdbctx
->context
;
1378 assert(gdbctx
->in_trap
);
1380 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1382 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1383 return packet_error
;
1386 packet_reply_open(gdbctx
);
1387 for (i
= 0; i
< cpu_num_regs
; i
++)
1389 packet_reply_register_hex_to(gdbctx
, i
);
1391 packet_reply_close(gdbctx
);
1395 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1399 CONTEXT
* pctx
= &gdbctx
->context
;
1402 assert(gdbctx
->in_trap
);
1403 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1405 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1406 return packet_error
;
1408 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1410 ptr
= gdbctx
->in_packet
;
1411 for (i
= 0; i
< cpu_num_regs
; i
++)
1413 cpu_register_hex_from(pctx
, i
, &ptr
);
1415 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1417 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1418 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1419 return packet_error
;
1424 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1426 detach_debuggee(gdbctx
, TRUE
);
1428 if (!gdbctx
->extended
)
1429 /* dunno whether GDB cares or not */
1433 /* assume we can't really answer something here */
1434 /* return packet_done; */
1437 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1442 switch (gdbctx
->in_packet
[0])
1446 if (gdbctx
->in_packet
[1] == '-')
1447 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1449 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1450 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1452 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1453 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1454 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1455 gdbctx
->in_packet
+ 1);
1456 return packet_error
;
1458 if (gdbctx
->in_packet
[0] == 'c')
1459 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1461 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1464 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1465 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1466 return packet_error
;
1470 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1473 unsigned int len
, blk_len
, nread
;
1477 assert(gdbctx
->in_trap
);
1478 /* FIXME:check in_packet_len for reading %p,%x */
1479 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1480 if (len
<= 0) return packet_error
;
1481 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1482 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1483 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1485 blk_len
= min(sizeof(buffer
), len
- nread
);
1486 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1489 /* fail at first address, return error */
1490 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1491 /* something has already been read, return partial information */
1494 if (nread
== 0) packet_reply_open(gdbctx
);
1495 packet_reply_hex_to(gdbctx
, buffer
, r
);
1497 packet_reply_close(gdbctx
);
1501 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1504 unsigned int len
, blk_len
;
1509 assert(gdbctx
->in_trap
);
1510 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1513 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1514 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1515 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1516 return packet_error
;
1520 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1522 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1523 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1524 return packet_error
;
1526 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1528 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1529 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1530 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1531 return packet_error
;
1533 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1534 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1537 blk_len
= min(sizeof(buffer
), len
);
1538 hex_from(buffer
, ptr
, blk_len
);
1539 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1546 return packet_ok
; /* FIXME: error while writing ? */
1549 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1553 CONTEXT
* pctx
= &gdbctx
->context
;
1555 assert(gdbctx
->in_trap
);
1556 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1557 if (reg
>= cpu_num_regs
)
1559 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1560 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1561 return packet_error
;
1563 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1565 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1566 return packet_error
;
1568 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1569 fprintf(stderr
, "Read register %x => %08x%08x\n", reg
,
1570 (unsigned)(cpu_register(pctx
, reg
) >> 32), (unsigned)cpu_register(pctx
, reg
));
1571 packet_reply_open(gdbctx
);
1572 packet_reply_register_hex_to(gdbctx
, reg
);
1573 packet_reply_close(gdbctx
);
1577 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1582 CONTEXT
* pctx
= &gdbctx
->context
;
1584 assert(gdbctx
->in_trap
);
1586 reg
= strtoul(gdbctx
->in_packet
, &ptr
, 16);
1587 if (ptr
== NULL
|| reg
>= cpu_num_regs
|| *ptr
++ != '=')
1589 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1590 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1591 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1592 * it wouldn't matter too much, and it fakes our support for all regs
1594 return (ptr
== NULL
) ? packet_error
: packet_ok
;
1596 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1598 int len
= gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
);
1599 fprintf(stderr
, "Writing reg %u <= %*.*s\n", reg
, len
, len
, ptr
);
1602 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1604 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1605 return packet_error
;
1608 cpu_register_hex_from(pctx
, reg
, (const char**)&ptr
);
1609 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1611 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1612 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1613 return packet_error
;
1619 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1627 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1628 strcpy(clsName
, "-- Unknown --");
1629 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1630 strcpy(wndName
, "-- Empty --");
1632 packet_reply_open(gdbctx
);
1633 packet_reply_catc(gdbctx
, 'O');
1634 snprintf(buffer
, sizeof(buffer
),
1635 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1636 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1637 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1638 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1640 packet_reply_hex_to_str(gdbctx
, buffer
);
1641 packet_reply_close(gdbctx
);
1643 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1644 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1645 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1648 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1652 /* we do the output in several 'O' packets, with the last one being just OK for
1653 * marking the end of the output */
1654 packet_reply_open(gdbctx
);
1655 packet_reply_catc(gdbctx
, 'O');
1656 snprintf(buffer
, sizeof(buffer
),
1657 "%-16.16s %-17.17s %-8.8s %s\n",
1658 "hwnd", "Class Name", " Style", " WndProc Text");
1659 packet_reply_hex_to_str(gdbctx
, buffer
);
1660 packet_reply_close(gdbctx
);
1662 /* FIXME: could also add a pmt to this command in str... */
1663 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1664 packet_reply(gdbctx
, "OK", 2);
1667 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1669 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1672 PROCESSENTRY32 entry
;
1675 if (snap
== INVALID_HANDLE_VALUE
)
1678 entry
.dwSize
= sizeof(entry
);
1679 ok
= Process32First(snap
, &entry
);
1681 /* we do the output in several 'O' packets, with the last one being just OK for
1682 * marking the end of the output */
1684 packet_reply_open(gdbctx
);
1685 packet_reply_catc(gdbctx
, 'O');
1686 snprintf(buffer
, sizeof(buffer
),
1687 " %-8.8s %-8.8s %-8.8s %s\n",
1688 "pid", "threads", "parent", "executable");
1689 packet_reply_hex_to_str(gdbctx
, buffer
);
1690 packet_reply_close(gdbctx
);
1695 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1696 packet_reply_open(gdbctx
);
1697 packet_reply_catc(gdbctx
, 'O');
1698 snprintf(buffer
, sizeof(buffer
),
1699 "%c%08x %-8d %08x '%s'\n",
1700 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1701 entry
.th32ParentProcessID
, entry
.szExeFile
);
1702 packet_reply_hex_to_str(gdbctx
, buffer
);
1703 packet_reply_close(gdbctx
);
1704 ok
= Process32Next(snap
, &entry
);
1707 packet_reply(gdbctx
, "OK", 2);
1710 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1712 MEMORY_BASIC_INFORMATION mbi
;
1719 /* we do the output in several 'O' packets, with the last one being just OK for
1720 * marking the end of the output */
1721 packet_reply_open(gdbctx
);
1722 packet_reply_catc(gdbctx
, 'O');
1723 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1724 packet_reply_close(gdbctx
);
1726 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1730 case MEM_COMMIT
: state
= "commit "; break;
1731 case MEM_FREE
: state
= "free "; break;
1732 case MEM_RESERVE
: state
= "reserve"; break;
1733 default: state
= "??? "; break;
1735 if (mbi
.State
!= MEM_FREE
)
1739 case MEM_IMAGE
: type
= "image "; break;
1740 case MEM_MAPPED
: type
= "mapped "; break;
1741 case MEM_PRIVATE
: type
= "private"; break;
1742 case 0: type
= " "; break;
1743 default: type
= "??? "; break;
1745 memset(prot
, ' ' , sizeof(prot
)-1);
1746 prot
[sizeof(prot
)-1] = '\0';
1747 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1749 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1751 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1753 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1761 packet_reply_open(gdbctx
);
1762 snprintf(buffer
, sizeof(buffer
), "%0*lx %0*lx %s %s %s\n",
1763 (unsigned)sizeof(void*), (DWORD_PTR
)addr
,
1764 (unsigned)sizeof(void*), mbi
.RegionSize
, state
, type
, prot
);
1765 packet_reply_catc(gdbctx
, 'O');
1766 packet_reply_hex_to_str(gdbctx
, buffer
);
1767 packet_reply_close(gdbctx
);
1769 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1771 addr
+= mbi
.RegionSize
;
1773 packet_reply(gdbctx
, "OK", 2);
1776 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1777 int len
, const char* str
)
1783 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1785 else if (len
>= 2 && str
[0] == '=')
1787 unsigned val
= atoi(&str
[1]);
1788 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1789 gdbctx
->trace
= val
;
1793 /* FIXME: ugly but can use error packet here */
1794 packet_reply_cat(gdbctx
, "E00");
1797 packet_reply_open(gdbctx
);
1798 packet_reply_hex_to_str(gdbctx
, buffer
);
1799 packet_reply_close(gdbctx
);
1807 void (*handler
)(struct gdb_context
*, int, const char*);
1810 {0, "wnd", 3, packet_query_monitor_wnd
},
1811 {0, "window", 6, packet_query_monitor_wnd
},
1812 {0, "proc", 4, packet_query_monitor_process
},
1813 {0, "process", 7, packet_query_monitor_process
},
1814 {0, "mem", 3, packet_query_monitor_mem
},
1815 {1, "trace", 5, packet_query_monitor_trace
},
1819 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1820 const char* hxcmd
, size_t len
)
1823 struct query_detail
* qd
;
1825 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1827 hex_from(buffer
, hxcmd
, len
);
1829 for (qd
= query_details
; qd
->name
!= NULL
; qd
++)
1831 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1832 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1834 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1837 return packet_reply_error(gdbctx
, EINVAL
);
1840 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1842 switch (gdbctx
->in_packet
[0])
1845 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1847 struct dbg_thread
* thd
;
1849 packet_reply_open(gdbctx
);
1850 packet_reply_add(gdbctx
, "m", 1);
1851 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1853 packet_reply_val(gdbctx
, thd
->tid
, 4);
1854 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1855 packet_reply_add(gdbctx
, ",", 1);
1857 packet_reply_close(gdbctx
);
1860 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1864 packet_reply_open(gdbctx
);
1865 packet_reply_catc(gdbctx
, 'O');
1866 get_process_info(gdbctx
, result
, sizeof(result
));
1867 packet_reply_hex_to_str(gdbctx
, result
);
1868 packet_reply_close(gdbctx
);
1873 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1875 packet_reply(gdbctx
, "l", 1);
1878 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1880 packet_reply(gdbctx
, "l", 1);
1885 if (strncmp(gdbctx
->in_packet
, "Attached", gdbctx
->in_packet_len
) == 0)
1891 return packet_reply(gdbctx
, buf
, -1);
1895 if (gdbctx
->in_packet_len
== 1)
1897 struct dbg_thread
* thd
;
1898 /* FIXME: doc says 16 bit val ??? */
1899 /* grab first created thread, aka last in list */
1900 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
1901 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
1902 packet_reply_open(gdbctx
);
1903 packet_reply_add(gdbctx
, "QC", 2);
1904 packet_reply_val(gdbctx
, thd
->tid
, 4);
1905 packet_reply_close(gdbctx
);
1910 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1914 snprintf(buf
, sizeof(buf
),
1915 "Text=%08lx;Data=%08lx;Bss=%08lx",
1916 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1917 gdbctx
->wine_segs
[2]);
1918 return packet_reply(gdbctx
, buf
, -1);
1922 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1924 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1925 gdbctx
->in_packet_len
- 5);
1929 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1931 if (strncmp(gdbctx
->in_packet
, "Supported", 9) == 0)
1933 /* no features supported */
1934 packet_reply_open(gdbctx
);
1935 packet_reply_close(gdbctx
);
1940 if (gdbctx
->in_packet_len
> 15 &&
1941 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1942 gdbctx
->in_packet
[15] == ',')
1948 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1949 if (end
== NULL
) break;
1950 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1951 packet_reply_open(gdbctx
);
1952 packet_reply_hex_to_str(gdbctx
, result
);
1953 packet_reply_close(gdbctx
);
1956 if (strncmp(gdbctx
->in_packet
, "TStatus", 7) == 0)
1958 /* Tracepoints not supported */
1959 packet_reply_open(gdbctx
);
1960 packet_reply_close(gdbctx
);
1965 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1966 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1967 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1968 return packet_error
;
1971 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1973 /* FIXME: add support for address in packet */
1974 assert(gdbctx
->in_packet_len
== 0);
1975 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1976 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1977 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
1978 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1979 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1980 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1981 wait_for_debuggee(gdbctx
);
1982 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1983 return packet_reply_status(gdbctx
);
1987 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1991 /* FIXME: add support for address in packet */
1992 assert(gdbctx
->in_packet_len
== 2);
1993 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1994 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1995 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1996 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1997 hex_from(&sig
, gdbctx
->in_packet
, 1);
1998 /* cannot change signals on the fly */
1999 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2000 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
2001 if (sig
!= gdbctx
->last_sig
)
2002 return packet_error
;
2003 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
2004 wait_for_debuggee(gdbctx
);
2005 return packet_reply_status(gdbctx
);
2009 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
2014 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
2015 if (tid
== -1 || tid
== 0)
2016 return packet_reply_error(gdbctx
, EINVAL
);
2017 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
2019 return packet_reply_error(gdbctx
, ESRCH
);
2022 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
2026 struct gdb_ctx_Xpoint
* xpt
;
2027 enum be_xpoint_type t
;
2029 /* FIXME: check packet_len */
2030 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2031 gdbctx
->in_packet
[1] != ',' ||
2032 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2033 return packet_error
;
2034 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2035 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
2036 addr
, len
, gdbctx
->in_packet
[0]);
2037 switch (gdbctx
->in_packet
[0])
2039 case '0': t
= be_xpoint_break
; len
= 0; break;
2040 case '1': t
= be_xpoint_watch_exec
; break;
2041 case '2': t
= be_xpoint_watch_read
; break;
2042 case '3': t
= be_xpoint_watch_write
; break;
2043 default: return packet_error
;
2045 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2047 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2049 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
2050 gdbctx
->process
->process_io
, &gdbctx
->context
,
2051 t
, xpt
->addr
, xpt
->val
, len
))
2059 return packet_error
;
2062 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
2066 struct gdb_ctx_Xpoint
* xpt
;
2067 enum be_xpoint_type t
;
2069 /* FIXME: check packet_len */
2070 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2071 gdbctx
->in_packet
[1] != ',' ||
2072 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2073 return packet_error
;
2074 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2075 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
2076 addr
, len
, gdbctx
->in_packet
[0]);
2077 switch (gdbctx
->in_packet
[0])
2079 case '0': t
= be_xpoint_break
; len
= 0; break;
2080 case '1': t
= be_xpoint_watch_exec
; break;
2081 case '2': t
= be_xpoint_watch_read
; break;
2082 case '3': t
= be_xpoint_watch_write
; break;
2083 default: return packet_error
;
2085 /* because of packet command handling, this should be made idempotent */
2086 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2088 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2089 return packet_ok
; /* nothing to do */
2091 /* really set the Xpoint */
2092 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2094 if (xpt
->type
== -1)
2096 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
2097 gdbctx
->process
->process_io
, &gdbctx
->context
,
2098 t
, addr
, &xpt
->val
, len
))
2104 fprintf(stderr
, "cannot set xpoint\n");
2108 /* no more entries... eech */
2109 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
2110 return packet_error
;
2113 /* =============================================== *
2114 * P A C K E T I N F R A S T R U C T U R E *
2115 * =============================================== *
2121 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
2124 static struct packet_entry packet_entries
[] =
2126 /*{'!', packet_extended}, */
2127 {'?', packet_last_signal
},
2128 {'c', packet_continue
},
2129 {'C', packet_continue_signal
},
2130 {'D', packet_detach
},
2131 {'g', packet_read_registers
},
2132 {'G', packet_write_registers
},
2134 {'H', packet_thread
},
2135 {'m', packet_read_memory
},
2136 {'M', packet_write_memory
},
2137 {'p', packet_read_register
},
2138 {'P', packet_write_register
},
2139 {'q', packet_query
},
2140 /* {'Q', packet_set}, */
2141 /* {'R', packet,restart}, only in extended mode ! */
2143 /*{'S', packet_step_signal}, hard(er) to implement */
2144 {'T', packet_thread_alive
},
2145 {'v', packet_verbose
},
2146 {'z', packet_remove_breakpoint
},
2147 {'Z', packet_set_breakpoint
},
2150 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2154 unsigned char in_cksum
, loc_cksum
;
2156 enum packet_return ret
= packet_error
;
2159 while ((ret
& packet_last_f
) == 0)
2161 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2162 fprintf(stderr
, "In-buf: %*.*s\n",
2163 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2164 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2165 if (ptr
== NULL
) return FALSE
;
2166 if (ptr
!= gdbctx
->in_buf
)
2168 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2169 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2170 fprintf(stderr
, "Removing garbage: %*.*s\n",
2171 glen
, glen
, gdbctx
->in_buf
);
2172 gdbctx
->in_len
-= glen
;
2173 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2175 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2176 if (end
== NULL
) return FALSE
;
2177 /* no checksum yet */
2178 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2179 plen
= end
- gdbctx
->in_buf
- 1;
2180 hex_from(&in_cksum
, end
+ 1, 1);
2181 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2182 if (loc_cksum
== in_cksum
)
2184 if (num_packet
== 0) {
2189 write(gdbctx
->sock
, "+", 1);
2192 /* FIXME: should use bsearch if packet_entries was sorted */
2193 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2195 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2197 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2199 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2200 fprintf(stderr
, "Unknown packet request %*.*s\n",
2201 plen
, plen
, &gdbctx
->in_buf
[1]);
2205 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2206 gdbctx
->in_packet_len
= plen
- 1;
2207 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2208 fprintf(stderr
, "Packet: %c%*.*s\n",
2210 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2212 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2214 switch (ret
& ~packet_last_f
)
2216 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2217 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2218 case packet_done
: break;
2220 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2221 fprintf(stderr
, "Reply-full: %*.*s\n",
2222 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2223 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2224 assert(i
== gdbctx
->out_len
);
2225 /* if this fails, we'll have to use POLLOUT...
2227 gdbctx
->out_len
= 0;
2232 /* FIXME: If we have more than one packet in our input buffer,
2233 * it's very likely that we took too long to answer to a given packet
2234 * and gdb is sending us the same packet again.
2235 * So we simply drop the second packet. This will lower the risk of error,
2236 * but there's still some race conditions here.
2237 * A better fix (yet not perfect) would be to have two threads:
2238 * - one managing the packets for gdb
2239 * - the second one managing the commands...
2240 * This would allow us to send the reply with the '+' character (Ack of
2241 * the command) way sooner than we do now.
2243 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2244 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2249 write(gdbctx
->sock
, "+", 1);
2250 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2251 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2253 gdbctx
->in_len
-= plen
+ 4;
2254 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2259 static int fetch_data(struct gdb_context
* gdbctx
)
2261 int len
, in_len
= gdbctx
->in_len
;
2263 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2267 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2268 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2270 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2271 fprintf(stderr
, "%d %d %*.*s\n",
2272 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2273 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2274 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2275 if (len
<= 0) break;
2276 gdbctx
->in_len
+= len
;
2277 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2278 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2280 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2281 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2282 return gdbctx
->in_len
- in_len
;
2285 #define FLAG_NO_START 1
2286 #define FLAG_WITH_XTERM 2
2288 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2292 const char* gdb_path
;
2295 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2296 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2297 fd
= mkstemps(buf
, 0);
2298 if (fd
== -1) return FALSE
;
2299 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2300 fprintf(f
, "file %s\n", wine_path
);
2301 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2302 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2303 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2304 /* gdb 5.1 seems to require it, won't hurt anyway */
2305 fprintf(f
, "sharedlibrary\n");
2306 /* This is needed (but not a decent & final fix)
2307 * Without this, gdb would skip our inter-DLL relay code (because
2308 * we don't have any line number information for the relay code)
2309 * With this, we will stop on first instruction of the stub, and
2310 * reusing step, will get us through the relay stub at the actual
2311 * function we're looking at.
2313 fprintf(f
, "set step-mode on\n");
2314 /* tell gdb to delete this file when done handling it... */
2315 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2317 if (flags
& FLAG_WITH_XTERM
)
2318 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2320 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2321 assert(0); /* never reached */
2325 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2328 struct sockaddr_in s_addrs
;
2329 unsigned int s_len
= sizeof(s_addrs
);
2330 struct pollfd pollfd
;
2331 IMAGEHLP_MODULE64 imh_mod
;
2334 /* step 1: create socket for gdb connection request */
2335 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2337 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2338 fprintf(stderr
, "Can't create socket");
2342 if (listen(sock
, 1) == -1 || getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2345 /* step 2: do the process internal creation */
2346 handle_debug_event(gdbctx
, de
);
2348 /* step3: get the wine loader name */
2349 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
))
2352 /* step 4: fire up gdb (if requested) */
2353 if (flags
& FLAG_NO_START
)
2354 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2358 case -1: /* error in parent... */
2359 fprintf(stderr
, "Cannot create gdb\n");
2361 default: /* in parent... success */
2362 signal(SIGINT
, SIG_IGN
);
2364 case 0: /* in child... and alive */
2365 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2366 /* if we're here, exec failed, so report failure */
2370 /* step 5: wait for gdb to connect actually */
2372 pollfd
.events
= POLLIN
;
2375 switch (poll(&pollfd
, 1, -1))
2378 if (pollfd
.revents
& POLLIN
)
2381 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2382 if (gdbctx
->sock
== -1)
2385 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2386 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2387 /* don't keep our small packets too long: send them ASAP back to GDB
2388 * without this, GDB really crawls
2390 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2394 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2395 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2398 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2399 fprintf(stderr
, "Poll for cnx failed (error)\n");
2410 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2416 gdbctx
->in_buf
= NULL
;
2417 gdbctx
->in_buf_alloc
= 0;
2419 gdbctx
->out_buf
= NULL
;
2420 gdbctx
->out_buf_alloc
= 0;
2421 gdbctx
->out_len
= 0;
2422 gdbctx
->out_curr_packet
= -1;
2424 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2425 gdbctx
->last_sig
= 0;
2426 gdbctx
->in_trap
= FALSE
;
2427 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2428 gdbctx
->process
= NULL
;
2429 for (i
= 0; i
< NUM_XPOINT
; i
++)
2430 gdbctx
->Xpoints
[i
].type
= -1;
2431 for (i
= 0; i
< sizeof(gdbctx
->wine_segs
) / sizeof(gdbctx
->wine_segs
[0]); i
++)
2432 gdbctx
->wine_segs
[i
] = 0;
2434 /* wait for first trap */
2435 while (WaitForDebugEvent(&de
, INFINITE
))
2437 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2439 /* this should be the first event we get,
2440 * and the only one of this type */
2441 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2442 /* gdbctx->dwProcessId = pid; */
2443 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2444 assert(!gdbctx
->in_trap
);
2448 handle_debug_event(gdbctx
, &de
);
2449 if (gdbctx
->in_trap
) break;
2451 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2456 static int gdb_remote(unsigned flags
)
2458 struct pollfd pollfd
;
2459 struct gdb_context gdbctx
;
2462 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2464 pollfd
.fd
= gdbctx
.sock
;
2465 pollfd
.events
= POLLIN
;
2468 switch (poll(&pollfd
, 1, -1))
2472 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2474 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2475 fprintf(stderr
, "Gdb hung up\n");
2476 /* kill also debuggee process - questionnable - */
2477 detach_debuggee(&gdbctx
, TRUE
);
2481 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2483 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2487 /* timeout, should never happen (infinite timeout) */
2490 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2491 fprintf(stderr
, "Poll failed\n");
2501 int gdb_main(int argc
, char* argv
[])
2504 unsigned gdb_flags
= 0;
2507 while (argc
> 0 && argv
[0][0] == '-')
2509 if (strcmp(argv
[0], "--no-start") == 0)
2511 gdb_flags
|= FLAG_NO_START
;
2515 if (strcmp(argv
[0], "--with-xterm") == 0)
2517 gdb_flags
|= FLAG_WITH_XTERM
;
2523 if (dbg_active_attach(argc
, argv
) == start_ok
||
2524 dbg_active_launch(argc
, argv
) == start_ok
)
2525 return gdb_remote(gdb_flags
);
2527 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");