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
[] = {
392 # error Define the registers map for your CPU
396 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
398 static inline void* cpu_register_ptr(CONTEXT
* ctx
, unsigned idx
)
400 assert(idx
< cpu_num_regs
);
401 return (char*)ctx
+ cpu_register_map
[idx
].ctx_offset
;
404 static inline DWORD64
cpu_register(CONTEXT
* ctx
, unsigned idx
)
406 switch (cpu_register_map
[idx
].ctx_length
)
408 case 2: return *(WORD
*)cpu_register_ptr(ctx
, idx
);
409 case 4: return *(DWORD
*)cpu_register_ptr(ctx
, idx
);
410 case 8: return *(DWORD64
*)cpu_register_ptr(ctx
, idx
);
412 fprintf(stderr
, "got unexpected size: %u\n", (unsigned)cpu_register_map
[idx
].ctx_length
);
417 static inline void cpu_register_hex_from(CONTEXT
* ctx
, unsigned idx
, const char** phex
)
423 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
425 hex_from(&b
, *phex
, 1);
427 val
+= (DWORD64
)b
<< (8 * i
);
429 switch (cpu_register_map
[idx
].ctx_length
)
431 case 2: *(WORD
*)cpu_register_ptr(ctx
, idx
) = (WORD
)val
; break;
432 case 4: *(DWORD
*)cpu_register_ptr(ctx
, idx
) = (DWORD
)val
; break;
433 case 8: *(DWORD64
*)cpu_register_ptr(ctx
, idx
) = val
; break;
438 /* =============================================== *
439 * W I N 3 2 D E B U G I N T E R F A C E *
440 * =============================================== *
443 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
445 ctx
->ContextFlags
= CONTEXT_CONTROL
447 #ifdef CONTEXT_SEGMENTS
450 #ifdef CONTEXT_DEBUG_REGISTERS
451 | CONTEXT_DEBUG_REGISTERS
454 if (!GetThreadContext(h
, ctx
))
456 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
457 fprintf(stderr
, "Can't get thread's context\n");
463 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
465 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
468 switch (rec
->ExceptionCode
)
470 case EXCEPTION_ACCESS_VIOLATION
:
471 case EXCEPTION_PRIV_INSTRUCTION
:
472 case EXCEPTION_STACK_OVERFLOW
:
473 case EXCEPTION_GUARD_PAGE
:
474 gdbctx
->last_sig
= SIGSEGV
;
477 case EXCEPTION_DATATYPE_MISALIGNMENT
:
478 gdbctx
->last_sig
= SIGBUS
;
481 case EXCEPTION_SINGLE_STEP
:
483 case EXCEPTION_BREAKPOINT
:
484 gdbctx
->last_sig
= SIGTRAP
;
487 case EXCEPTION_FLT_DENORMAL_OPERAND
:
488 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
489 case EXCEPTION_FLT_INEXACT_RESULT
:
490 case EXCEPTION_FLT_INVALID_OPERATION
:
491 case EXCEPTION_FLT_OVERFLOW
:
492 case EXCEPTION_FLT_STACK_CHECK
:
493 case EXCEPTION_FLT_UNDERFLOW
:
494 gdbctx
->last_sig
= SIGFPE
;
497 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
498 case EXCEPTION_INT_OVERFLOW
:
499 gdbctx
->last_sig
= SIGFPE
;
502 case EXCEPTION_ILLEGAL_INSTRUCTION
:
503 gdbctx
->last_sig
= SIGILL
;
507 gdbctx
->last_sig
= SIGINT
;
510 case STATUS_POSSIBLE_DEADLOCK
:
511 gdbctx
->last_sig
= SIGALRM
;
513 /* FIXME: we could also add here a O packet with additional information */
516 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
517 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
518 gdbctx
->last_sig
= SIGABRT
;
525 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
532 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
534 switch (de
->dwDebugEventCode
)
536 case CREATE_PROCESS_DEBUG_EVENT
:
537 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
538 de
->u
.CreateProcessInfo
.hProcess
);
539 if (!gdbctx
->process
) break;
540 memory_get_string_indirect(gdbctx
->process
,
541 de
->u
.CreateProcessInfo
.lpImageName
,
542 de
->u
.CreateProcessInfo
.fUnicode
,
543 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
544 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
546 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
547 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
548 de
->dwProcessId
, de
->dwThreadId
,
549 dbg_W2A(u
.buffer
, -1),
550 de
->u
.CreateProcessInfo
.lpImageName
,
551 de
->u
.CreateProcessInfo
.lpStartAddress
,
552 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
553 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
555 /* de->u.CreateProcessInfo.lpStartAddress; */
556 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
557 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
559 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
560 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
561 de
->dwProcessId
, de
->dwThreadId
,
562 de
->u
.CreateProcessInfo
.lpStartAddress
);
564 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
565 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
566 de
->u
.CreateProcessInfo
.hThread
,
567 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
570 case LOAD_DLL_DEBUG_EVENT
:
571 assert(dbg_curr_thread
);
572 memory_get_string_indirect(gdbctx
->process
,
573 de
->u
.LoadDll
.lpImageName
,
574 de
->u
.LoadDll
.fUnicode
,
575 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
576 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
577 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
578 de
->dwProcessId
, de
->dwThreadId
,
579 dbg_W2A(u
.buffer
, -1),
580 de
->u
.LoadDll
.lpBaseOfDll
,
581 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
582 de
->u
.LoadDll
.nDebugInfoSize
);
583 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
584 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
587 case UNLOAD_DLL_DEBUG_EVENT
:
588 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
589 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
590 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
591 SymUnloadModule(gdbctx
->process
->handle
,
592 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
595 case EXCEPTION_DEBUG_EVENT
:
596 assert(dbg_curr_thread
);
597 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
598 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
599 de
->dwProcessId
, de
->dwThreadId
,
600 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
602 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
604 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
608 case CREATE_THREAD_DEBUG_EVENT
:
609 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
610 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
611 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
613 dbg_add_thread(gdbctx
->process
,
615 de
->u
.CreateThread
.hThread
,
616 de
->u
.CreateThread
.lpThreadLocalBase
);
619 case EXIT_THREAD_DEBUG_EVENT
:
620 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
621 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
622 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
624 assert(dbg_curr_thread
);
625 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
626 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
627 dbg_del_thread(dbg_curr_thread
);
630 case EXIT_PROCESS_DEBUG_EVENT
:
631 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
632 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
633 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
635 dbg_del_process(gdbctx
->process
);
636 gdbctx
->process
= NULL
;
637 /* now signal gdb that we're done */
638 gdbctx
->last_sig
= SIGTERM
;
639 gdbctx
->in_trap
= TRUE
;
642 case OUTPUT_DEBUG_STRING_EVENT
:
643 assert(dbg_curr_thread
);
644 memory_get_string(gdbctx
->process
,
645 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
646 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
647 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
648 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
649 de
->dwProcessId
, de
->dwThreadId
, u
.bufferA
);
653 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
654 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
655 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
656 de
->u
.RipInfo
.dwType
);
660 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
661 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
662 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
666 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
670 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
671 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
672 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
673 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
674 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
675 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
676 dbg_curr_thread
->tid
, cont
);
678 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
679 fprintf(stderr
, "Cannot find last thread\n");
683 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
688 if(dbg_curr_thread
->tid
== threadid
){
689 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
690 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
691 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
692 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
693 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
694 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
695 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
696 dbg_curr_thread
->tid
, cont
);
699 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
700 fprintf(stderr
, "Cannot find last thread\n");
703 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
705 struct pollfd pollfd
;
709 pollfd
.fd
= gdbctx
->sock
;
710 pollfd
.events
= POLLIN
;
713 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
714 ret
= read(gdbctx
->sock
, &pkt
, 1);
716 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
717 fprintf(stderr
, "read failed\n");
722 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
723 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
728 } else if (ret
== -1) {
729 fprintf(stderr
, "poll failed\n");
734 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
738 gdbctx
->in_trap
= FALSE
;
741 if (!WaitForDebugEvent(&de
, 10))
743 if (GetLastError() == ERROR_SEM_TIMEOUT
)
745 if (check_for_interrupt(gdbctx
)) {
746 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
747 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
748 fprintf(stderr
, "Failed to break into debugee\n");
752 WaitForDebugEvent(&de
, INFINITE
);
760 handle_debug_event(gdbctx
, &de
);
761 assert(!gdbctx
->process
||
762 gdbctx
->process
->pid
== 0 ||
763 de
.dwProcessId
== gdbctx
->process
->pid
);
764 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
765 if (gdbctx
->in_trap
) break;
766 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
770 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
772 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
773 resume_debuggee(gdbctx
, DBG_CONTINUE
);
775 DebugActiveProcessStop(gdbctx
->process
->pid
);
776 dbg_del_process(gdbctx
->process
);
777 gdbctx
->process
= NULL
;
780 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
784 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
786 strcpy(buffer
, "Unknown process");
789 if (status
== STILL_ACTIVE
)
791 strcpy(buffer
, "Running");
794 snprintf(buffer
, len
, "Terminated (%u)", status
);
796 switch (GetPriorityClass(gdbctx
->process
->handle
))
799 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
800 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
802 #ifdef BELOW_NORMAL_PRIORITY_CLASS
803 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
805 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
806 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
807 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
808 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
810 strcat(buffer
, "\n");
813 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
814 char* buffer
, size_t len
)
816 struct dbg_thread
* thd
;
820 /* FIXME: use the size of buffer */
821 thd
= dbg_get_thread(gdbctx
->process
, tid
);
824 strcpy(buffer
, "No information");
827 if (GetExitCodeThread(thd
->handle
, &status
))
829 if (status
== STILL_ACTIVE
)
831 /* FIXME: this is a bit brutal... some nicer way shall be found */
832 switch (status
= SuspendThread(thd
->handle
))
835 case 0: strcpy(buffer
, "Running"); break;
836 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
838 ResumeThread(thd
->handle
);
841 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
845 strcpy(buffer
, "Unknown threadID");
847 switch (prio
= GetThreadPriority(thd
->handle
))
849 case THREAD_PRIORITY_ERROR_RETURN
: break;
850 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
851 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
852 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
853 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
854 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
855 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
856 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
857 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
859 assert(strlen(buffer
) < len
);
862 /* =============================================== *
863 * P A C K E T U T I L S *
864 * =============================================== *
867 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
868 packet_last_f
= 0x80};
870 static char* packet_realloc(char* buf
, int size
)
873 return HeapAlloc(GetProcessHeap(), 0, size
);
874 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
878 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
880 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
882 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
883 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
887 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
889 packet_reply_grow(gdbctx
, len
* 2);
890 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
891 gdbctx
->out_len
+= len
* 2;
894 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
896 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
899 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
903 shift
= (len
- 1) * 8;
904 packet_reply_grow(gdbctx
, len
* 2);
905 for (i
= 0; i
< len
; i
++, shift
-= 8)
907 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
908 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
912 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
914 packet_reply_grow(gdbctx
, len
);
915 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
916 gdbctx
->out_len
+= len
;
919 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
921 packet_reply_add(gdbctx
, str
, strlen(str
));
924 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
926 packet_reply_add(gdbctx
, &ch
, 1);
929 static void packet_reply_open(struct gdb_context
* gdbctx
)
931 assert(gdbctx
->out_curr_packet
== -1);
932 packet_reply_catc(gdbctx
, '$');
933 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
936 static void packet_reply_close(struct gdb_context
* gdbctx
)
941 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
942 packet_reply_catc(gdbctx
, '#');
943 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
944 packet_reply_hex_to(gdbctx
, &cksum
, 1);
945 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
946 fprintf(stderr
, "Reply : %*.*s\n",
947 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
948 gdbctx
->out_curr_packet
= -1;
951 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
953 packet_reply_open(gdbctx
);
955 if (len
== -1) len
= strlen(packet
);
956 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
958 packet_reply_add(gdbctx
, packet
, len
);
960 packet_reply_close(gdbctx
);
965 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
967 packet_reply_open(gdbctx
);
969 packet_reply_add(gdbctx
, "E", 1);
970 packet_reply_val(gdbctx
, error
, 1);
972 packet_reply_close(gdbctx
);
977 static inline void packet_reply_register_hex_to(struct gdb_context
* gdbctx
, unsigned idx
)
979 DWORD64 val
= cpu_register(&gdbctx
->context
, idx
);
982 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
985 packet_reply_hex_to(gdbctx
, &b
, 1);
990 /* =============================================== *
991 * P A C K E T H A N D L E R S *
992 * =============================================== *
995 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
997 enum packet_return ret
= packet_done
;
999 packet_reply_open(gdbctx
);
1001 if (gdbctx
->process
!= NULL
)
1006 packet_reply_catc(gdbctx
, 'T');
1007 sig
= gdbctx
->last_sig
;
1008 packet_reply_val(gdbctx
, sig
, 1);
1009 packet_reply_add(gdbctx
, "thread:", 7);
1010 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
1011 packet_reply_catc(gdbctx
, ';');
1013 for (i
= 0; i
< cpu_num_regs
; i
++)
1015 /* FIXME: this call will also grow the buffer...
1016 * unneeded, but not harmful
1018 packet_reply_val(gdbctx
, i
, 1);
1019 packet_reply_catc(gdbctx
, ':');
1020 packet_reply_register_hex_to(gdbctx
, i
);
1021 packet_reply_catc(gdbctx
, ';');
1026 /* Try to put an exit code
1027 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1028 * just indicate the end of process and exit */
1029 packet_reply_add(gdbctx
, "W00", 3);
1030 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
1033 packet_reply_close(gdbctx
);
1039 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
1041 gdbctx
->extended
= 1;
1046 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
1048 assert(gdbctx
->in_packet_len
== 0);
1049 return packet_reply_status(gdbctx
);
1052 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
1054 /* FIXME: add support for address in packet */
1055 assert(gdbctx
->in_packet_len
== 0);
1056 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1057 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1058 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1059 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1060 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1061 wait_for_debuggee(gdbctx
);
1062 return packet_reply_status(gdbctx
);
1065 static enum packet_return
packet_verbose_cont(struct gdb_context
* gdbctx
)
1068 int defaultAction
= -1; /* magic non action */
1071 int actionIndex
[20]; /* allow for up to 20 actions */
1072 int threadIndex
[20];
1073 int threadCount
= 0;
1074 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1075 unsigned int threadID
= 0;
1076 struct dbg_thread
* thd
;
1078 /* OK we have vCont followed by..
1080 * c for packet_continue
1081 * Csig for packet_continue_signal
1083 * Ssig for step signal
1084 * and then an optional thread ID at the end..
1085 * *******************************************/
1088 if (gdbctx
->in_packet
[4] == '?')
1093 The vCont packet is supported. Each action is a supported command in the vCont packet.
1095 The vCont packet is not supported. (this didn't seem to be obeyed!)
1097 packet_reply_open(gdbctx
);
1098 packet_reply_add(gdbctx
, "vCont", 5);
1099 /* add all the supported actions to the reply (all of them for now) */
1100 packet_reply_add(gdbctx
, ";c", 2);
1101 packet_reply_add(gdbctx
, ";C", 2);
1102 packet_reply_add(gdbctx
, ";s", 2);
1103 packet_reply_add(gdbctx
, ";S", 2);
1104 packet_reply_close(gdbctx
);
1108 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1109 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1110 now if only gdb talked XML.... */
1111 #if 0 /* handy for debugging */
1112 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1115 /* go through the packet and identify where all the actions start at */
1116 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1118 if (gdbctx
->in_packet
[i
] == ';')
1120 threadIndex
[actions
] = 0;
1121 actionIndex
[actions
++] = i
;
1123 else if (gdbctx
->in_packet
[i
] == ':')
1125 threadIndex
[actions
- 1] = i
;
1129 /* now look up the default action */
1130 for (i
= 0 ; i
< actions
; i
++)
1132 if (threadIndex
[i
] == 0)
1134 if (defaultAction
!= -1)
1136 fprintf(stderr
,"Too many default actions specified\n");
1137 return packet_error
;
1143 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1145 /* go through all the threads and stick their ids in the to be done list. */
1146 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1148 threadIDs
[threadCount
++] = thd
->tid
;
1149 /* check to see if we have more threads than I counted on, and tell the user what to do
1150 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1151 if (threadCount
== 100)
1153 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1158 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1159 * that remains is to apply the actions to the threads and the default action to any threads
1161 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1162 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1163 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1164 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1166 /* deal with the threaded stuff first */
1167 for (i
= 0; i
< actions
; i
++)
1169 if (threadIndex
[i
] != 0)
1171 int j
, idLength
= 0;
1172 if (i
< actions
- 1)
1174 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1178 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1181 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1182 /* process the action */
1183 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1185 case 's': /* step */
1186 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1188 case 'c': /* continue */
1189 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1191 case 'S': /* step Sig, */
1192 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1194 case 'C': /* continue sig */
1195 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1196 /* cannot change signals on the fly */
1197 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1198 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1199 if (sig
!= gdbctx
->last_sig
)
1200 return packet_error
;
1201 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1204 for (j
= 0 ; j
< threadCount
; j
++)
1206 if (threadIDs
[j
] == threadID
)
1213 } /* for i=0 ; i< actions */
1215 /* now we have manage the default action */
1216 if (defaultAction
>= 0)
1218 for (i
= 0 ; i
< threadCount
; i
++)
1220 /* check to see if we've already done something to the thread*/
1221 if (threadIDs
[i
] != 0)
1223 /* if not apply the default action*/
1224 threadID
= threadIDs
[i
];
1225 /* process the action (yes this is almost identical to the one above!) */
1226 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1228 case 's': /* step */
1229 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1231 case 'c': /* continue */
1232 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1235 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1237 case 'C': /* continue sig */
1238 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1239 /* cannot change signals on the fly */
1240 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1241 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1242 if (sig
!= gdbctx
->last_sig
)
1243 return packet_error
;
1244 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1249 } /* if(defaultAction >=0) */
1251 wait_for_debuggee(gdbctx
);
1252 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1253 return packet_reply_status(gdbctx
);
1256 struct verbose_defail
1260 enum packet_return (*handler
)(struct gdb_context
*);
1261 } verbose_details
[] =
1263 /* {"Attach", 6}, */
1264 {"Cont", 4, packet_verbose_cont
},
1274 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1279 for (klen
= 0; ; klen
++)
1281 if (klen
== gdbctx
->in_packet_len
||
1282 gdbctx
->in_packet
[klen
] == ';' ||
1283 gdbctx
->in_packet
[klen
] == ':' ||
1284 gdbctx
->in_packet
[klen
] == '?')
1286 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1287 fprintf(stderr
, "trying to process a verbose packet %*.*s\n",
1288 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1289 for (i
= 0; i
< sizeof(verbose_details
)/sizeof(verbose_details
[0]); i
++)
1291 if (klen
== verbose_details
[i
].len
&&
1292 !memcmp(gdbctx
->in_packet
, verbose_details
[i
].name
, verbose_details
[i
].len
))
1294 return verbose_details
[i
].handler(gdbctx
);
1297 /* no matching handler found, abort */
1302 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1303 fprintf(stderr
, "No support for verbose packet %*.*s\n",
1304 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1305 return packet_error
;
1308 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1312 /* FIXME: add support for address in packet */
1313 assert(gdbctx
->in_packet_len
== 2);
1314 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1315 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1316 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1317 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1318 hex_from(&sig
, gdbctx
->in_packet
, 1);
1319 /* cannot change signals on the fly */
1320 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1321 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1322 if (sig
!= gdbctx
->last_sig
)
1323 return packet_error
;
1324 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1325 wait_for_debuggee(gdbctx
);
1326 return packet_reply_status(gdbctx
);
1329 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1331 detach_debuggee(gdbctx
, FALSE
);
1332 return packet_ok
| packet_last_f
;
1335 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1339 CONTEXT
* pctx
= &gdbctx
->context
;
1341 assert(gdbctx
->in_trap
);
1343 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1345 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1346 return packet_error
;
1349 packet_reply_open(gdbctx
);
1350 for (i
= 0; i
< cpu_num_regs
; i
++)
1352 packet_reply_register_hex_to(gdbctx
, i
);
1354 packet_reply_close(gdbctx
);
1358 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1362 CONTEXT
* pctx
= &gdbctx
->context
;
1365 assert(gdbctx
->in_trap
);
1366 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1368 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1369 return packet_error
;
1371 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1373 ptr
= gdbctx
->in_packet
;
1374 for (i
= 0; i
< cpu_num_regs
; i
++)
1376 cpu_register_hex_from(pctx
, i
, &ptr
);
1378 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1380 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1381 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1382 return packet_error
;
1387 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1389 detach_debuggee(gdbctx
, TRUE
);
1391 if (!gdbctx
->extended
)
1392 /* dunno whether GDB cares or not */
1396 /* assume we can't really answer something here */
1397 /* return packet_done; */
1400 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1405 switch (gdbctx
->in_packet
[0])
1409 if (gdbctx
->in_packet
[1] == '-')
1410 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1412 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1413 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1415 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1416 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1417 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1418 gdbctx
->in_packet
+ 1);
1419 return packet_error
;
1421 if (gdbctx
->in_packet
[0] == 'c')
1422 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1424 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1427 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1428 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1429 return packet_error
;
1433 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1436 unsigned int len
, blk_len
, nread
;
1440 assert(gdbctx
->in_trap
);
1441 /* FIXME:check in_packet_len for reading %p,%x */
1442 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1443 if (len
<= 0) return packet_error
;
1444 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1445 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1446 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1448 blk_len
= min(sizeof(buffer
), len
- nread
);
1449 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1452 /* fail at first address, return error */
1453 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1454 /* something has already been read, return partial information */
1457 if (nread
== 0) packet_reply_open(gdbctx
);
1458 packet_reply_hex_to(gdbctx
, buffer
, r
);
1460 packet_reply_close(gdbctx
);
1464 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1467 unsigned int len
, blk_len
;
1472 assert(gdbctx
->in_trap
);
1473 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1476 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1477 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1478 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1479 return packet_error
;
1483 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1485 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1486 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1487 return packet_error
;
1489 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1491 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1492 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1493 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1494 return packet_error
;
1496 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1497 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1500 blk_len
= min(sizeof(buffer
), len
);
1501 hex_from(buffer
, ptr
, blk_len
);
1502 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1509 return packet_ok
; /* FIXME: error while writing ? */
1512 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1516 CONTEXT
* pctx
= &gdbctx
->context
;
1518 assert(gdbctx
->in_trap
);
1519 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1520 if (reg
>= cpu_num_regs
)
1522 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1523 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1524 return packet_error
;
1526 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1528 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1529 return packet_error
;
1531 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1532 fprintf(stderr
, "Read register %x => %08x%08x\n", reg
,
1533 (unsigned)(cpu_register(pctx
, reg
) >> 32), (unsigned)cpu_register(pctx
, reg
));
1534 packet_reply_open(gdbctx
);
1535 packet_reply_register_hex_to(gdbctx
, reg
);
1536 packet_reply_close(gdbctx
);
1540 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1545 CONTEXT
* pctx
= &gdbctx
->context
;
1547 assert(gdbctx
->in_trap
);
1549 reg
= strtoul(gdbctx
->in_packet
, &ptr
, 16);
1550 if (ptr
== NULL
|| reg
> cpu_num_regs
|| *ptr
++ != '=')
1552 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1553 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1554 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1555 * it wouldn't matter too much, and it fakes our support for all regs
1557 return (ptr
== NULL
) ? packet_error
: packet_ok
;
1559 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1561 int len
= gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
);
1562 fprintf(stderr
, "Writing reg %u <= %*.*s\n", reg
, len
, len
, ptr
);
1565 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1567 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1568 return packet_error
;
1571 cpu_register_hex_from(pctx
, reg
, (const char**)&ptr
);
1572 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1574 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1575 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1576 return packet_error
;
1582 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1590 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1591 strcpy(clsName
, "-- Unknown --");
1592 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1593 strcpy(wndName
, "-- Empty --");
1595 packet_reply_open(gdbctx
);
1596 packet_reply_catc(gdbctx
, 'O');
1597 snprintf(buffer
, sizeof(buffer
),
1598 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1599 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1600 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1601 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1603 packet_reply_hex_to_str(gdbctx
, buffer
);
1604 packet_reply_close(gdbctx
);
1606 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1607 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1608 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1611 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1615 /* we do the output in several 'O' packets, with the last one being just OK for
1616 * marking the end of the output */
1617 packet_reply_open(gdbctx
);
1618 packet_reply_catc(gdbctx
, 'O');
1619 snprintf(buffer
, sizeof(buffer
),
1620 "%-16.16s %-17.17s %-8.8s %s\n",
1621 "hwnd", "Class Name", " Style", " WndProc Text");
1622 packet_reply_hex_to_str(gdbctx
, buffer
);
1623 packet_reply_close(gdbctx
);
1625 /* FIXME: could also add a pmt to this command in str... */
1626 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1627 packet_reply(gdbctx
, "OK", 2);
1630 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1632 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1635 PROCESSENTRY32 entry
;
1638 if (snap
== INVALID_HANDLE_VALUE
)
1641 entry
.dwSize
= sizeof(entry
);
1642 ok
= Process32First(snap
, &entry
);
1644 /* we do the output in several 'O' packets, with the last one being just OK for
1645 * marking the end of the output */
1647 packet_reply_open(gdbctx
);
1648 packet_reply_catc(gdbctx
, 'O');
1649 snprintf(buffer
, sizeof(buffer
),
1650 " %-8.8s %-8.8s %-8.8s %s\n",
1651 "pid", "threads", "parent", "executable");
1652 packet_reply_hex_to_str(gdbctx
, buffer
);
1653 packet_reply_close(gdbctx
);
1658 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1659 packet_reply_open(gdbctx
);
1660 packet_reply_catc(gdbctx
, 'O');
1661 snprintf(buffer
, sizeof(buffer
),
1662 "%c%08x %-8d %08x '%s'\n",
1663 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1664 entry
.th32ParentProcessID
, entry
.szExeFile
);
1665 packet_reply_hex_to_str(gdbctx
, buffer
);
1666 packet_reply_close(gdbctx
);
1667 ok
= Process32Next(snap
, &entry
);
1670 packet_reply(gdbctx
, "OK", 2);
1673 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1675 MEMORY_BASIC_INFORMATION mbi
;
1682 /* we do the output in several 'O' packets, with the last one being just OK for
1683 * marking the end of the output */
1684 packet_reply_open(gdbctx
);
1685 packet_reply_catc(gdbctx
, 'O');
1686 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1687 packet_reply_close(gdbctx
);
1689 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1693 case MEM_COMMIT
: state
= "commit "; break;
1694 case MEM_FREE
: state
= "free "; break;
1695 case MEM_RESERVE
: state
= "reserve"; break;
1696 default: state
= "??? "; break;
1698 if (mbi
.State
!= MEM_FREE
)
1702 case MEM_IMAGE
: type
= "image "; break;
1703 case MEM_MAPPED
: type
= "mapped "; break;
1704 case MEM_PRIVATE
: type
= "private"; break;
1705 case 0: type
= " "; break;
1706 default: type
= "??? "; break;
1708 memset(prot
, ' ' , sizeof(prot
)-1);
1709 prot
[sizeof(prot
)-1] = '\0';
1710 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1712 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1714 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1716 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1724 packet_reply_open(gdbctx
);
1725 snprintf(buffer
, sizeof(buffer
), "%0*lx %0*lx %s %s %s\n",
1726 (unsigned)sizeof(void*), (DWORD_PTR
)addr
,
1727 (unsigned)sizeof(void*), mbi
.RegionSize
, state
, type
, prot
);
1728 packet_reply_catc(gdbctx
, 'O');
1729 packet_reply_hex_to_str(gdbctx
, buffer
);
1730 packet_reply_close(gdbctx
);
1732 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1734 addr
+= mbi
.RegionSize
;
1736 packet_reply(gdbctx
, "OK", 2);
1739 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1740 int len
, const char* str
)
1746 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1748 else if (len
>= 2 && str
[0] == '=')
1750 unsigned val
= atoi(&str
[1]);
1751 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1752 gdbctx
->trace
= val
;
1756 /* FIXME: ugly but can use error packet here */
1757 packet_reply_cat(gdbctx
, "E00");
1760 packet_reply_open(gdbctx
);
1761 packet_reply_hex_to_str(gdbctx
, buffer
);
1762 packet_reply_close(gdbctx
);
1770 void (*handler
)(struct gdb_context
*, int, const char*);
1773 {0, "wnd", 3, packet_query_monitor_wnd
},
1774 {0, "window", 6, packet_query_monitor_wnd
},
1775 {0, "proc", 4, packet_query_monitor_process
},
1776 {0, "process", 7, packet_query_monitor_process
},
1777 {0, "mem", 3, packet_query_monitor_mem
},
1778 {1, "trace", 5, packet_query_monitor_trace
},
1782 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1783 const char* hxcmd
, size_t len
)
1786 struct query_detail
* qd
;
1788 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1790 hex_from(buffer
, hxcmd
, len
);
1792 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1794 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1795 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1797 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1800 return packet_reply_error(gdbctx
, EINVAL
);
1803 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1805 switch (gdbctx
->in_packet
[0])
1808 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1810 struct dbg_thread
* thd
;
1812 packet_reply_open(gdbctx
);
1813 packet_reply_add(gdbctx
, "m", 1);
1814 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1816 packet_reply_val(gdbctx
, thd
->tid
, 4);
1817 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1818 packet_reply_add(gdbctx
, ",", 1);
1820 packet_reply_close(gdbctx
);
1823 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1827 packet_reply_open(gdbctx
);
1828 packet_reply_catc(gdbctx
, 'O');
1829 get_process_info(gdbctx
, result
, sizeof(result
));
1830 packet_reply_hex_to_str(gdbctx
, result
);
1831 packet_reply_close(gdbctx
);
1836 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1838 packet_reply(gdbctx
, "l", 1);
1841 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1843 packet_reply(gdbctx
, "l", 1);
1848 if (strncmp(gdbctx
->in_packet
, "Attached", gdbctx
->in_packet_len
) == 0)
1854 return packet_reply(gdbctx
, buf
, -1);
1858 if (gdbctx
->in_packet_len
== 1)
1860 struct dbg_thread
* thd
;
1861 /* FIXME: doc says 16 bit val ??? */
1862 /* grab first created thread, aka last in list */
1863 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
1864 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
1865 packet_reply_open(gdbctx
);
1866 packet_reply_add(gdbctx
, "QC", 2);
1867 packet_reply_val(gdbctx
, thd
->tid
, 4);
1868 packet_reply_close(gdbctx
);
1873 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1877 snprintf(buf
, sizeof(buf
),
1878 "Text=%08lx;Data=%08lx;Bss=%08lx",
1879 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1880 gdbctx
->wine_segs
[2]);
1881 return packet_reply(gdbctx
, buf
, -1);
1885 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1887 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1888 gdbctx
->in_packet_len
- 5);
1892 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1894 if (strncmp(gdbctx
->in_packet
, "Supported", 9) == 0)
1896 /* no features supported */
1897 packet_reply_open(gdbctx
);
1898 packet_reply_close(gdbctx
);
1903 if (gdbctx
->in_packet_len
> 15 &&
1904 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1905 gdbctx
->in_packet
[15] == ',')
1911 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1912 if (end
== NULL
) break;
1913 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1914 packet_reply_open(gdbctx
);
1915 packet_reply_hex_to_str(gdbctx
, result
);
1916 packet_reply_close(gdbctx
);
1919 if (strncmp(gdbctx
->in_packet
, "TStatus", 7) == 0)
1921 /* Tracepoints not supported */
1922 packet_reply_open(gdbctx
);
1923 packet_reply_close(gdbctx
);
1928 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1929 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1930 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1931 return packet_error
;
1934 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1936 /* FIXME: add support for address in packet */
1937 assert(gdbctx
->in_packet_len
== 0);
1938 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1939 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1940 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
1941 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1942 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1943 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1944 wait_for_debuggee(gdbctx
);
1945 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1946 return packet_reply_status(gdbctx
);
1950 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1954 /* FIXME: add support for address in packet */
1955 assert(gdbctx
->in_packet_len
== 2);
1956 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1957 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1958 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1959 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1960 hex_from(&sig
, gdbctx
->in_packet
, 1);
1961 /* cannot change signals on the fly */
1962 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1963 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1964 if (sig
!= gdbctx
->last_sig
)
1965 return packet_error
;
1966 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1967 wait_for_debuggee(gdbctx
);
1968 return packet_reply_status(gdbctx
);
1972 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1977 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1978 if (tid
== -1 || tid
== 0)
1979 return packet_reply_error(gdbctx
, EINVAL
);
1980 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1982 return packet_reply_error(gdbctx
, ESRCH
);
1985 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1989 struct gdb_ctx_Xpoint
* xpt
;
1990 enum be_xpoint_type t
;
1992 /* FIXME: check packet_len */
1993 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1994 gdbctx
->in_packet
[1] != ',' ||
1995 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1996 return packet_error
;
1997 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1998 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1999 addr
, len
, gdbctx
->in_packet
[0]);
2000 switch (gdbctx
->in_packet
[0])
2002 case '0': t
= be_xpoint_break
; len
= 0; break;
2003 case '1': t
= be_xpoint_watch_exec
; break;
2004 case '2': t
= be_xpoint_watch_read
; break;
2005 case '3': t
= be_xpoint_watch_write
; break;
2006 default: return packet_error
;
2008 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2010 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2012 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
2013 gdbctx
->process
->process_io
, &gdbctx
->context
,
2014 t
, xpt
->addr
, xpt
->val
, len
))
2022 return packet_error
;
2025 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
2029 struct gdb_ctx_Xpoint
* xpt
;
2030 enum be_xpoint_type t
;
2032 /* FIXME: check packet_len */
2033 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2034 gdbctx
->in_packet
[1] != ',' ||
2035 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2036 return packet_error
;
2037 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2038 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
2039 addr
, len
, gdbctx
->in_packet
[0]);
2040 switch (gdbctx
->in_packet
[0])
2042 case '0': t
= be_xpoint_break
; len
= 0; break;
2043 case '1': t
= be_xpoint_watch_exec
; break;
2044 case '2': t
= be_xpoint_watch_read
; break;
2045 case '3': t
= be_xpoint_watch_write
; break;
2046 default: return packet_error
;
2048 /* because of packet command handling, this should be made idempotent */
2049 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2051 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2052 return packet_ok
; /* nothing to do */
2054 /* really set the Xpoint */
2055 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2057 if (xpt
->type
== -1)
2059 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
2060 gdbctx
->process
->process_io
, &gdbctx
->context
,
2061 t
, addr
, &xpt
->val
, len
))
2067 fprintf(stderr
, "cannot set xpoint\n");
2071 /* no more entries... eech */
2072 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
2073 return packet_error
;
2076 /* =============================================== *
2077 * P A C K E T I N F R A S T R U C T U R E *
2078 * =============================================== *
2084 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
2087 static struct packet_entry packet_entries
[] =
2089 /*{'!', packet_extended}, */
2090 {'?', packet_last_signal
},
2091 {'c', packet_continue
},
2092 {'C', packet_continue_signal
},
2093 {'D', packet_detach
},
2094 {'g', packet_read_registers
},
2095 {'G', packet_write_registers
},
2097 {'H', packet_thread
},
2098 {'m', packet_read_memory
},
2099 {'M', packet_write_memory
},
2100 {'p', packet_read_register
},
2101 {'P', packet_write_register
},
2102 {'q', packet_query
},
2103 /* {'Q', packet_set}, */
2104 /* {'R', packet,restart}, only in extended mode ! */
2106 /*{'S', packet_step_signal}, hard(er) to implement */
2107 {'T', packet_thread_alive
},
2108 {'v', packet_verbose
},
2109 {'z', packet_remove_breakpoint
},
2110 {'Z', packet_set_breakpoint
},
2113 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2117 unsigned char in_cksum
, loc_cksum
;
2119 enum packet_return ret
= packet_error
;
2122 while ((ret
& packet_last_f
) == 0)
2124 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2125 fprintf(stderr
, "In-buf: %*.*s\n",
2126 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2127 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2128 if (ptr
== NULL
) return FALSE
;
2129 if (ptr
!= gdbctx
->in_buf
)
2131 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2132 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2133 fprintf(stderr
, "Removing garbage: %*.*s\n",
2134 glen
, glen
, gdbctx
->in_buf
);
2135 gdbctx
->in_len
-= glen
;
2136 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2138 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2139 if (end
== NULL
) return FALSE
;
2140 /* no checksum yet */
2141 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2142 plen
= end
- gdbctx
->in_buf
- 1;
2143 hex_from(&in_cksum
, end
+ 1, 1);
2144 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2145 if (loc_cksum
== in_cksum
)
2147 if (num_packet
== 0) {
2152 write(gdbctx
->sock
, "+", 1);
2155 /* FIXME: should use bsearch if packet_entries was sorted */
2156 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2158 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2160 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2162 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2163 fprintf(stderr
, "Unknown packet request %*.*s\n",
2164 plen
, plen
, &gdbctx
->in_buf
[1]);
2168 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2169 gdbctx
->in_packet_len
= plen
- 1;
2170 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2171 fprintf(stderr
, "Packet: %c%*.*s\n",
2173 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2175 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2177 switch (ret
& ~packet_last_f
)
2179 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2180 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2181 case packet_done
: break;
2183 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2184 fprintf(stderr
, "Reply-full: %*.*s\n",
2185 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2186 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2187 assert(i
== gdbctx
->out_len
);
2188 /* if this fails, we'll have to use POLLOUT...
2190 gdbctx
->out_len
= 0;
2195 /* FIXME: If we have more than one packet in our input buffer,
2196 * it's very likely that we took too long to answer to a given packet
2197 * and gdb is sending us the same packet again.
2198 * So we simply drop the second packet. This will lower the risk of error,
2199 * but there's still some race conditions here.
2200 * A better fix (yet not perfect) would be to have two threads:
2201 * - one managing the packets for gdb
2202 * - the second one managing the commands...
2203 * This would allow us to send the reply with the '+' character (Ack of
2204 * the command) way sooner than we do now.
2206 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2207 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2212 write(gdbctx
->sock
, "+", 1);
2213 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2214 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2216 gdbctx
->in_len
-= plen
+ 4;
2217 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2222 static int fetch_data(struct gdb_context
* gdbctx
)
2224 int len
, in_len
= gdbctx
->in_len
;
2226 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2230 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2231 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2233 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2234 fprintf(stderr
, "%d %d %*.*s\n",
2235 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2236 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2237 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2238 if (len
<= 0) break;
2239 gdbctx
->in_len
+= len
;
2240 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2241 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2243 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2244 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2245 return gdbctx
->in_len
- in_len
;
2248 #define FLAG_NO_START 1
2249 #define FLAG_WITH_XTERM 2
2251 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2255 const char* gdb_path
;
2258 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2259 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2260 fd
= mkstemps(buf
, 0);
2261 if (fd
== -1) return FALSE
;
2262 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2263 fprintf(f
, "file %s\n", wine_path
);
2264 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2265 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2266 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2267 /* gdb 5.1 seems to require it, won't hurt anyway */
2268 fprintf(f
, "sharedlibrary\n");
2269 /* This is needed (but not a decent & final fix)
2270 * Without this, gdb would skip our inter-DLL relay code (because
2271 * we don't have any line number information for the relay code)
2272 * With this, we will stop on first instruction of the stub, and
2273 * reusing step, will get us through the relay stub at the actual
2274 * function we're looking at.
2276 fprintf(f
, "set step-mode on\n");
2277 /* tell gdb to delete this file when done handling it... */
2278 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2280 if (flags
& FLAG_WITH_XTERM
)
2281 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2283 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2284 assert(0); /* never reached */
2288 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2291 struct sockaddr_in s_addrs
;
2292 unsigned int s_len
= sizeof(s_addrs
);
2293 struct pollfd pollfd
;
2294 IMAGEHLP_MODULE64 imh_mod
;
2296 /* step 1: create socket for gdb connection request */
2297 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2299 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2300 fprintf(stderr
, "Can't create socket");
2304 if (listen(sock
, 1) == -1 ||
2305 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2308 /* step 2: do the process internal creation */
2309 handle_debug_event(gdbctx
, de
);
2311 /* step3: get the wine loader name */
2312 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
)) return FALSE
;
2314 /* step 4: fire up gdb (if requested) */
2315 if (flags
& FLAG_NO_START
)
2316 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2320 case -1: /* error in parent... */
2321 fprintf(stderr
, "Cannot create gdb\n");
2323 default: /* in parent... success */
2324 signal(SIGINT
, SIG_IGN
);
2326 case 0: /* in child... and alive */
2327 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2328 /* if we're here, exec failed, so report failure */
2332 /* step 5: wait for gdb to connect actually */
2334 pollfd
.events
= POLLIN
;
2337 switch (poll(&pollfd
, 1, -1))
2340 if (pollfd
.revents
& POLLIN
)
2343 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2344 if (gdbctx
->sock
== -1)
2346 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2347 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2348 /* don't keep our small packets too long: send them ASAP back to GDB
2349 * without this, GDB really crawls
2351 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2355 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2356 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2359 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2360 fprintf(stderr
, "Poll for cnx failed (error)\n");
2370 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2376 gdbctx
->in_buf
= NULL
;
2377 gdbctx
->in_buf_alloc
= 0;
2379 gdbctx
->out_buf
= NULL
;
2380 gdbctx
->out_buf_alloc
= 0;
2381 gdbctx
->out_len
= 0;
2382 gdbctx
->out_curr_packet
= -1;
2384 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2385 gdbctx
->last_sig
= 0;
2386 gdbctx
->in_trap
= FALSE
;
2387 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2388 gdbctx
->process
= NULL
;
2389 for (i
= 0; i
< NUM_XPOINT
; i
++)
2390 gdbctx
->Xpoints
[i
].type
= -1;
2391 for (i
= 0; i
< sizeof(gdbctx
->wine_segs
) / sizeof(gdbctx
->wine_segs
[0]); i
++)
2392 gdbctx
->wine_segs
[i
] = 0;
2394 /* wait for first trap */
2395 while (WaitForDebugEvent(&de
, INFINITE
))
2397 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2399 /* this should be the first event we get,
2400 * and the only one of this type */
2401 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2402 /* gdbctx->dwProcessId = pid; */
2403 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2404 assert(!gdbctx
->in_trap
);
2408 handle_debug_event(gdbctx
, &de
);
2409 if (gdbctx
->in_trap
) break;
2411 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2416 static int gdb_remote(unsigned flags
)
2418 struct pollfd pollfd
;
2419 struct gdb_context gdbctx
;
2422 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2424 pollfd
.fd
= gdbctx
.sock
;
2425 pollfd
.events
= POLLIN
;
2428 switch (poll(&pollfd
, 1, -1))
2432 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2434 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2435 fprintf(stderr
, "Gdb hung up\n");
2436 /* kill also debuggee process - questionnable - */
2437 detach_debuggee(&gdbctx
, TRUE
);
2441 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2443 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2447 /* timeout, should never happen (infinite timeout) */
2450 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2451 fprintf(stderr
, "Poll failed\n");
2461 int gdb_main(int argc
, char* argv
[])
2464 unsigned gdb_flags
= 0;
2467 while (argc
> 0 && argv
[0][0] == '-')
2469 if (strcmp(argv
[0], "--no-start") == 0)
2471 gdb_flags
|= FLAG_NO_START
;
2475 if (strcmp(argv
[0], "--with-xterm") == 0)
2477 gdb_flags
|= FLAG_WITH_XTERM
;
2483 if (dbg_active_attach(argc
, argv
) == start_ok
||
2484 dbg_active_launch(argc
, argv
) == start_ok
)
2485 return gdb_remote(gdb_flags
);
2487 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");