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...
66 #include "wine/debug.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(winedbg
);
78 /* split into individual packet */
86 /* generic GDB thread information */
87 int exec_tid
; /* tid used in step & continue */
88 int other_tid
; /* tid to be used in any other operation */
89 /* current Win32 trap env */
94 /* Win32 information */
95 struct dbg_process
* process
;
96 /* Unix environment */
97 unsigned long wine_segs
[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
101 static BOOL
tgt_process_gdbproxy_read(HANDLE hProcess
, const void* addr
,
102 void* buffer
, SIZE_T len
, SIZE_T
* rlen
)
104 return ReadProcessMemory( hProcess
, addr
, buffer
, len
, rlen
);
107 static BOOL
tgt_process_gdbproxy_write(HANDLE hProcess
, void* addr
,
108 const void* buffer
, SIZE_T len
, SIZE_T
* wlen
)
110 return WriteProcessMemory( hProcess
, addr
, buffer
, len
, wlen
);
113 static struct be_process_io be_process_gdbproxy_io
=
115 NULL
, /* we shouldn't use close_process() in gdbproxy */
116 tgt_process_gdbproxy_read
,
117 tgt_process_gdbproxy_write
120 /* =============================================== *
121 * B A S I C M A N I P U L A T I O N S *
122 * =============================================== *
125 static inline int hex_from0(char ch
)
127 if (ch
>= '0' && ch
<= '9') return ch
- '0';
128 if (ch
>= 'A' && ch
<= 'F') return ch
- 'A' + 10;
129 if (ch
>= 'a' && ch
<= 'f') return ch
- 'a' + 10;
135 static inline unsigned char hex_to0(int x
)
137 assert(x
>= 0 && x
< 16);
138 return "0123456789abcdef"[x
];
141 static void hex_from(void* dst
, const char* src
, size_t len
)
143 unsigned char *p
= dst
;
146 *p
++ = (hex_from0(src
[0]) << 4) | hex_from0(src
[1]);
151 static void hex_to(char* dst
, const void* src
, size_t len
)
153 const unsigned char *p
= src
;
156 *dst
++ = hex_to0(*p
>> 4);
157 *dst
++ = hex_to0(*p
& 0x0F);
162 static unsigned char checksum(const char* ptr
, int len
)
167 cksum
+= (unsigned char)*ptr
++;
172 static const char target_xml
[] = "";
173 #elif defined(__powerpc__)
174 static const char target_xml
[] = "";
175 #elif defined(__x86_64__)
176 static const char target_xml
[] = "";
177 #elif defined(__arm__)
178 static const char target_xml
[] =
179 "l <target><architecture>arm</architecture>\n"
180 "<feature name=\"org.gnu.gdb.arm.core\">\n"
181 " <reg name=\"r0\" bitsize=\"32\" type=\"uint32\"/>\n"
182 " <reg name=\"r1\" bitsize=\"32\" type=\"uint32\"/>\n"
183 " <reg name=\"r2\" bitsize=\"32\" type=\"uint32\"/>\n"
184 " <reg name=\"r3\" bitsize=\"32\" type=\"uint32\"/>\n"
185 " <reg name=\"r4\" bitsize=\"32\" type=\"uint32\"/>\n"
186 " <reg name=\"r5\" bitsize=\"32\" type=\"uint32\"/>\n"
187 " <reg name=\"r6\" bitsize=\"32\" type=\"uint32\"/>\n"
188 " <reg name=\"r7\" bitsize=\"32\" type=\"uint32\"/>\n"
189 " <reg name=\"r8\" bitsize=\"32\" type=\"uint32\"/>\n"
190 " <reg name=\"r9\" bitsize=\"32\" type=\"uint32\"/>\n"
191 " <reg name=\"r10\" bitsize=\"32\" type=\"uint32\"/>\n"
192 " <reg name=\"r11\" bitsize=\"32\" type=\"uint32\"/>\n"
193 " <reg name=\"r12\" bitsize=\"32\" type=\"uint32\"/>\n"
194 " <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n"
195 " <reg name=\"lr\" bitsize=\"32\"/>\n"
196 " <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n"
197 " <reg name=\"cpsr\" bitsize=\"32\"/>\n"
198 "</feature></target>\n";
199 #elif defined(__aarch64__)
200 static const char target_xml
[] = "";
202 # error Define the registers map for your CPU
205 static inline void* cpu_register_ptr(struct gdb_context
*gdbctx
,
206 dbg_ctx_t
*ctx
, unsigned idx
)
208 assert(idx
< gdbctx
->process
->be_cpu
->gdb_num_regs
);
209 return (char*)ctx
+ gdbctx
->process
->be_cpu
->gdb_register_map
[idx
].ctx_offset
;
212 static inline DWORD64
cpu_register(struct gdb_context
*gdbctx
,
213 dbg_ctx_t
*ctx
, unsigned idx
)
215 switch (gdbctx
->process
->be_cpu
->gdb_register_map
[idx
].ctx_length
)
217 case 1: return *(BYTE
*)cpu_register_ptr(gdbctx
, ctx
, idx
);
218 case 2: return *(WORD
*)cpu_register_ptr(gdbctx
, ctx
, idx
);
219 case 4: return *(DWORD
*)cpu_register_ptr(gdbctx
, ctx
, idx
);
220 case 8: return *(DWORD64
*)cpu_register_ptr(gdbctx
, ctx
, idx
);
222 ERR("got unexpected size: %u\n",
223 (unsigned)gdbctx
->process
->be_cpu
->gdb_register_map
[idx
].ctx_length
);
229 static inline void cpu_register_hex_from(struct gdb_context
*gdbctx
,
230 dbg_ctx_t
* ctx
, unsigned idx
, const char **phex
)
232 const struct gdb_register
*cpu_register_map
= gdbctx
->process
->be_cpu
->gdb_register_map
;
234 if (cpu_register_map
[idx
].gdb_length
== cpu_register_map
[idx
].ctx_length
)
235 hex_from(cpu_register_ptr(gdbctx
, ctx
, idx
), *phex
, cpu_register_map
[idx
].gdb_length
);
242 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
244 hex_from(&b
, *phex
, 1);
246 val
+= (DWORD64
)b
<< (8 * i
);
248 switch (cpu_register_map
[idx
].ctx_length
)
250 case 1: *(BYTE
*)cpu_register_ptr(gdbctx
, ctx
, idx
) = (BYTE
)val
; break;
251 case 2: *(WORD
*)cpu_register_ptr(gdbctx
, ctx
, idx
) = (WORD
)val
; break;
252 case 4: *(DWORD
*)cpu_register_ptr(gdbctx
, ctx
, idx
) = (DWORD
)val
; break;
253 case 8: *(DWORD64
*)cpu_register_ptr(gdbctx
, ctx
, idx
) = val
; break;
259 /* =============================================== *
260 * W I N 3 2 D E B U G I N T E R F A C E *
261 * =============================================== *
264 static struct dbg_thread
* dbg_thread_from_tid(struct gdb_context
* gdbctx
, int tid
)
266 struct dbg_process
*process
= gdbctx
->process
;
267 struct dbg_thread
*thread
;
269 if (!process
) return NULL
;
271 if (tid
== 0) tid
= gdbctx
->de
.dwThreadId
;
272 LIST_FOR_EACH_ENTRY(thread
, &process
->threads
, struct dbg_thread
, entry
)
274 if (tid
> 0 && thread
->tid
!= tid
) continue;
281 static void dbg_thread_set_single_step(struct dbg_thread
*thread
, BOOL enable
)
283 struct backend_cpu
*backend
;
287 if (!thread
->process
) return;
288 if (!(backend
= thread
->process
->be_cpu
)) return;
290 if (!backend
->get_context(thread
->handle
, &ctx
))
292 ERR("get_context failed for thread %04x:%04x\n", thread
->process
->pid
, thread
->tid
);
295 backend
->single_step(&ctx
, enable
);
296 if (!backend
->set_context(thread
->handle
, &ctx
))
297 ERR("set_context failed for thread %04x:%04x\n", thread
->process
->pid
, thread
->tid
);
300 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
302 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
305 switch (rec
->ExceptionCode
)
307 case EXCEPTION_ACCESS_VIOLATION
:
308 case EXCEPTION_PRIV_INSTRUCTION
:
309 case EXCEPTION_STACK_OVERFLOW
:
310 case EXCEPTION_GUARD_PAGE
:
311 gdbctx
->last_sig
= SIGSEGV
;
314 case EXCEPTION_DATATYPE_MISALIGNMENT
:
315 gdbctx
->last_sig
= SIGBUS
;
318 case EXCEPTION_SINGLE_STEP
:
320 case EXCEPTION_BREAKPOINT
:
321 gdbctx
->last_sig
= SIGTRAP
;
324 case EXCEPTION_FLT_DENORMAL_OPERAND
:
325 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
326 case EXCEPTION_FLT_INEXACT_RESULT
:
327 case EXCEPTION_FLT_INVALID_OPERATION
:
328 case EXCEPTION_FLT_OVERFLOW
:
329 case EXCEPTION_FLT_STACK_CHECK
:
330 case EXCEPTION_FLT_UNDERFLOW
:
331 gdbctx
->last_sig
= SIGFPE
;
334 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
335 case EXCEPTION_INT_OVERFLOW
:
336 gdbctx
->last_sig
= SIGFPE
;
339 case EXCEPTION_ILLEGAL_INSTRUCTION
:
340 gdbctx
->last_sig
= SIGILL
;
344 gdbctx
->last_sig
= SIGINT
;
347 case STATUS_POSSIBLE_DEADLOCK
:
348 gdbctx
->last_sig
= SIGALRM
;
350 /* FIXME: we could also add here a O packet with additional information */
352 case EXCEPTION_NAME_THREAD
:
354 const THREADNAME_INFO
*threadname
= (const THREADNAME_INFO
*)rec
->ExceptionInformation
;
355 struct dbg_thread
*thread
;
359 if (threadname
->dwThreadID
== -1)
360 thread
= dbg_get_thread(gdbctx
->process
, gdbctx
->de
.dwThreadId
);
362 thread
= dbg_get_thread(gdbctx
->process
, threadname
->dwThreadID
);
365 if (gdbctx
->process
->process_io
->read( gdbctx
->process
->handle
,
366 threadname
->szName
, name
, sizeof(name
), &read
) && read
== sizeof(name
))
368 fprintf(stderr
, "Thread ID=%04x renamed to \"%.9s\"\n",
369 threadname
->dwThreadID
, name
);
373 ERR("Cannot set name of thread %04x\n", threadname
->dwThreadID
);
376 case EXCEPTION_INVALID_HANDLE
:
379 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
380 gdbctx
->last_sig
= SIGABRT
;
387 static void handle_debug_event(struct gdb_context
* gdbctx
)
389 DEBUG_EVENT
*de
= &gdbctx
->de
;
390 struct dbg_thread
*thread
;
397 gdbctx
->exec_tid
= de
->dwThreadId
;
398 gdbctx
->other_tid
= de
->dwThreadId
;
399 gdbctx
->de_reply
= DBG_REPLY_LATER
;
401 switch (de
->dwDebugEventCode
)
403 case CREATE_PROCESS_DEBUG_EVENT
:
404 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
405 de
->u
.CreateProcessInfo
.hProcess
);
406 if (!gdbctx
->process
) break;
407 memory_get_string_indirect(gdbctx
->process
,
408 de
->u
.CreateProcessInfo
.lpImageName
,
409 de
->u
.CreateProcessInfo
.fUnicode
,
410 u
.buffer
, ARRAY_SIZE(u
.buffer
));
411 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
413 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
414 de
->dwProcessId
, de
->dwThreadId
,
415 dbg_W2A(u
.buffer
, -1),
416 de
->u
.CreateProcessInfo
.lpImageName
,
417 de
->u
.CreateProcessInfo
.lpStartAddress
,
418 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
419 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
421 /* de->u.CreateProcessInfo.lpStartAddress; */
422 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
423 ERR("Couldn't initiate DbgHelp\n");
425 fprintf(stderr
, "%04x:%04x: create thread I @%p\n", de
->dwProcessId
,
426 de
->dwThreadId
, de
->u
.CreateProcessInfo
.lpStartAddress
);
428 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
429 de
->u
.CreateProcessInfo
.hThread
,
430 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
433 case LOAD_DLL_DEBUG_EVENT
:
434 memory_get_string_indirect(gdbctx
->process
,
435 de
->u
.LoadDll
.lpImageName
,
436 de
->u
.LoadDll
.fUnicode
,
437 u
.buffer
, ARRAY_SIZE(u
.buffer
));
438 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
439 de
->dwProcessId
, de
->dwThreadId
,
440 dbg_W2A(u
.buffer
, -1),
441 de
->u
.LoadDll
.lpBaseOfDll
,
442 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
443 de
->u
.LoadDll
.nDebugInfoSize
);
444 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
445 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
448 case UNLOAD_DLL_DEBUG_EVENT
:
449 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
450 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
451 SymUnloadModule(gdbctx
->process
->handle
,
452 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
455 case EXCEPTION_DEBUG_EVENT
:
456 TRACE("%08x:%08x: exception code=0x%08x\n", de
->dwProcessId
,
457 de
->dwThreadId
, de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
459 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
462 case CREATE_THREAD_DEBUG_EVENT
:
463 fprintf(stderr
, "%08x:%08x: create thread D @%p\n", de
->dwProcessId
,
464 de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
466 dbg_add_thread(gdbctx
->process
,
468 de
->u
.CreateThread
.hThread
,
469 de
->u
.CreateThread
.lpThreadLocalBase
);
472 case EXIT_THREAD_DEBUG_EVENT
:
473 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
474 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
475 if ((thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
)))
476 dbg_del_thread(thread
);
479 case EXIT_PROCESS_DEBUG_EVENT
:
480 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
481 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
483 dbg_del_process(gdbctx
->process
);
484 gdbctx
->process
= NULL
;
485 /* now signal gdb that we're done */
486 gdbctx
->last_sig
= SIGTERM
;
487 gdbctx
->in_trap
= TRUE
;
490 case OUTPUT_DEBUG_STRING_EVENT
:
491 memory_get_string(gdbctx
->process
,
492 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
493 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
494 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
495 de
->dwProcessId
, de
->dwThreadId
, debugstr_a(u
.bufferA
));
499 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n", de
->dwProcessId
,
500 de
->dwThreadId
, de
->u
.RipInfo
.dwError
, de
->u
.RipInfo
.dwType
);
504 FIXME("%08x:%08x: unknown event (%u)\n",
505 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
508 if (!gdbctx
->in_trap
|| !gdbctx
->process
) return;
510 LIST_FOR_EACH_ENTRY(thread
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
512 if (!thread
->suspended
) SuspendThread(thread
->handle
);
513 thread
->suspended
= TRUE
;
517 static void handle_step_or_continue(struct gdb_context
* gdbctx
, int tid
, BOOL step
, int sig
)
519 struct dbg_process
*process
= gdbctx
->process
;
520 struct dbg_thread
*thread
;
522 if (tid
== 0) tid
= gdbctx
->de
.dwThreadId
;
523 LIST_FOR_EACH_ENTRY(thread
, &process
->threads
, struct dbg_thread
, entry
)
525 if (tid
!= -1 && thread
->tid
!= tid
) continue;
526 if (!thread
->suspended
) continue;
527 thread
->suspended
= FALSE
;
529 if (process
->pid
== gdbctx
->de
.dwProcessId
&& thread
->tid
== gdbctx
->de
.dwThreadId
)
530 gdbctx
->de_reply
= (sig
== -1 ? DBG_CONTINUE
: DBG_EXCEPTION_NOT_HANDLED
);
532 dbg_thread_set_single_step(thread
, step
);
533 ResumeThread(thread
->handle
);
537 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
539 struct pollfd pollfd
;
543 pollfd
.fd
= gdbctx
->sock
;
544 pollfd
.events
= POLLIN
;
547 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
548 ret
= read(gdbctx
->sock
, &pkt
, 1);
550 ERR("read failed\n");
554 ERR("Unexpected break packet %#02x\n", pkt
);
558 } else if (ret
== -1) {
559 ERR("poll failed\n");
564 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
566 if (gdbctx
->de
.dwDebugEventCode
)
567 ContinueDebugEvent(gdbctx
->de
.dwProcessId
, gdbctx
->de
.dwThreadId
, gdbctx
->de_reply
);
569 gdbctx
->in_trap
= FALSE
;
572 if (!WaitForDebugEvent(&gdbctx
->de
, 10))
574 if (GetLastError() == ERROR_SEM_TIMEOUT
)
576 if (check_for_interrupt(gdbctx
)) {
577 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
578 ERR("Failed to break into debuggee\n");
581 WaitForDebugEvent(&gdbctx
->de
, INFINITE
);
589 handle_debug_event(gdbctx
);
590 assert(!gdbctx
->process
||
591 gdbctx
->process
->pid
== 0 ||
592 gdbctx
->de
.dwProcessId
== gdbctx
->process
->pid
);
593 if (gdbctx
->in_trap
) break;
594 ContinueDebugEvent(gdbctx
->de
.dwProcessId
, gdbctx
->de
.dwThreadId
, DBG_CONTINUE
);
598 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
600 handle_step_or_continue(gdbctx
, -1, FALSE
, -1);
602 if (gdbctx
->de
.dwDebugEventCode
)
603 ContinueDebugEvent(gdbctx
->de
.dwProcessId
, gdbctx
->de
.dwThreadId
, DBG_CONTINUE
);
606 DebugActiveProcessStop(gdbctx
->process
->pid
);
607 dbg_del_process(gdbctx
->process
);
608 gdbctx
->process
= NULL
;
611 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
615 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
617 strcpy(buffer
, "Unknown process");
620 if (status
== STILL_ACTIVE
)
622 strcpy(buffer
, "Running");
625 snprintf(buffer
, len
, "Terminated (%u)", status
);
627 switch (GetPriorityClass(gdbctx
->process
->handle
))
630 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
631 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
633 #ifdef BELOW_NORMAL_PRIORITY_CLASS
634 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priority"); break;
636 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
637 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
638 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
639 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
641 strcat(buffer
, "\n");
644 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
645 char* buffer
, size_t len
)
647 struct dbg_thread
* thd
;
651 /* FIXME: use the size of buffer */
652 thd
= dbg_get_thread(gdbctx
->process
, tid
);
655 strcpy(buffer
, "No information");
658 if (GetExitCodeThread(thd
->handle
, &status
))
660 if (status
== STILL_ACTIVE
)
662 /* FIXME: this is a bit brutal... some nicer way shall be found */
663 switch (status
= SuspendThread(thd
->handle
))
666 case 0: strcpy(buffer
, "Running"); break;
667 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
669 ResumeThread(thd
->handle
);
672 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
676 strcpy(buffer
, "Unknown threadID");
678 switch (prio
= GetThreadPriority(thd
->handle
))
680 case THREAD_PRIORITY_ERROR_RETURN
: break;
681 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
682 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
683 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
684 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
685 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
686 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
687 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
688 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
690 assert(strlen(buffer
) < len
);
693 /* =============================================== *
694 * P A C K E T U T I L S *
695 * =============================================== *
698 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
699 packet_last_f
= 0x80};
701 static char* packet_realloc(char* buf
, int size
)
704 return HeapAlloc(GetProcessHeap(), 0, size
);
705 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
709 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
711 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
713 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
714 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
718 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
720 packet_reply_grow(gdbctx
, len
* 2);
721 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
722 gdbctx
->out_len
+= len
* 2;
725 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
727 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
730 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
734 shift
= (len
- 1) * 8;
735 packet_reply_grow(gdbctx
, len
* 2);
736 for (i
= 0; i
< len
; i
++, shift
-= 8)
738 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
739 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
743 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
)
745 int len
= strlen(str
);
746 packet_reply_grow(gdbctx
, len
);
747 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
748 gdbctx
->out_len
+= len
;
751 static void packet_reply_open(struct gdb_context
* gdbctx
)
753 assert(gdbctx
->out_curr_packet
== -1);
754 packet_reply_add(gdbctx
, "$");
755 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
758 static void packet_reply_close(struct gdb_context
* gdbctx
)
763 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
764 packet_reply_add(gdbctx
, "#");
765 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
766 packet_reply_hex_to(gdbctx
, &cksum
, 1);
767 gdbctx
->out_curr_packet
= -1;
770 static void packet_reply_open_xfer(struct gdb_context
* gdbctx
)
772 packet_reply_open(gdbctx
);
773 packet_reply_add(gdbctx
, "m");
776 static void packet_reply_close_xfer(struct gdb_context
* gdbctx
, int off
, int len
)
778 int begin
= gdbctx
->out_curr_packet
+ 1;
781 if (begin
+ off
< gdbctx
->out_len
)
783 gdbctx
->out_len
-= off
;
784 memmove(gdbctx
->out_buf
+ begin
, gdbctx
->out_buf
+ begin
+ off
, gdbctx
->out_len
);
788 gdbctx
->out_buf
[gdbctx
->out_curr_packet
] = 'l';
789 gdbctx
->out_len
= gdbctx
->out_curr_packet
+ 1;
792 plen
= gdbctx
->out_len
- begin
;
793 if (len
>= 0 && plen
> len
) gdbctx
->out_len
-= (plen
- len
);
794 else gdbctx
->out_buf
[gdbctx
->out_curr_packet
] = 'l';
796 packet_reply_close(gdbctx
);
799 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
)
801 packet_reply_open(gdbctx
);
803 assert(strchr(packet
, '$') == NULL
&& strchr(packet
, '#') == NULL
);
805 packet_reply_add(gdbctx
, packet
);
807 packet_reply_close(gdbctx
);
812 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
814 packet_reply_open(gdbctx
);
816 packet_reply_add(gdbctx
, "E");
817 packet_reply_val(gdbctx
, error
, 1);
819 packet_reply_close(gdbctx
);
824 static inline void packet_reply_register_hex_to(struct gdb_context
* gdbctx
, dbg_ctx_t
* ctx
, unsigned idx
)
826 const struct gdb_register
*cpu_register_map
= gdbctx
->process
->be_cpu
->gdb_register_map
;
828 if (cpu_register_map
[idx
].gdb_length
== cpu_register_map
[idx
].ctx_length
)
829 packet_reply_hex_to(gdbctx
, cpu_register_ptr(gdbctx
, ctx
, idx
),
830 cpu_register_map
[idx
].gdb_length
);
833 DWORD64 val
= cpu_register(gdbctx
, ctx
, idx
);
836 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
839 packet_reply_hex_to(gdbctx
, &b
, 1);
845 /* =============================================== *
846 * P A C K E T H A N D L E R S *
847 * =============================================== *
850 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
852 struct dbg_process
*process
= gdbctx
->process
;
853 struct dbg_thread
*thread
;
854 struct backend_cpu
*backend
;
862 if (!(backend
= process
->be_cpu
)) return packet_error
;
864 if (!(thread
= dbg_get_thread(process
, gdbctx
->de
.dwThreadId
)) ||
865 !backend
->get_context(thread
->handle
, &ctx
))
868 packet_reply_open(gdbctx
);
869 packet_reply_add(gdbctx
, "T");
870 sig
= gdbctx
->last_sig
;
871 packet_reply_val(gdbctx
, sig
, 1);
872 packet_reply_add(gdbctx
, "thread:");
873 packet_reply_val(gdbctx
, gdbctx
->de
.dwThreadId
, 4);
874 packet_reply_add(gdbctx
, ";");
876 for (i
= 0; i
< backend
->gdb_num_regs
; i
++)
878 packet_reply_val(gdbctx
, i
, 1);
879 packet_reply_add(gdbctx
, ":");
880 packet_reply_register_hex_to(gdbctx
, &ctx
, i
);
881 packet_reply_add(gdbctx
, ";");
884 packet_reply_close(gdbctx
);
889 /* Try to put an exit code
890 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
891 * just indicate the end of process and exit */
892 return packet_reply(gdbctx
, "W00") | packet_last_f
;
896 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
898 assert(gdbctx
->in_packet_len
== 0);
899 return packet_reply_status(gdbctx
);
902 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
906 if (sscanf(gdbctx
->in_packet
, "%p", &addr
) == 1)
907 FIXME("Continue at address %p not supported\n", addr
);
909 handle_step_or_continue(gdbctx
, gdbctx
->exec_tid
, FALSE
, -1);
911 wait_for_debuggee(gdbctx
);
912 return packet_reply_status(gdbctx
);
915 static enum packet_return
packet_verbose_cont(struct gdb_context
* gdbctx
)
917 char *buf
= gdbctx
->in_packet
, *end
= gdbctx
->in_packet
+ gdbctx
->in_packet_len
;
919 if (gdbctx
->in_packet
[4] == '?')
921 packet_reply_open(gdbctx
);
922 packet_reply_add(gdbctx
, "vCont");
923 packet_reply_add(gdbctx
, ";c");
924 packet_reply_add(gdbctx
, ";C");
925 packet_reply_add(gdbctx
, ";s");
926 packet_reply_add(gdbctx
, ";S");
927 packet_reply_close(gdbctx
);
931 while (buf
< end
&& (buf
= memchr(buf
+ 1, ';', end
- buf
- 1)))
933 int tid
= -1, sig
= -1;
936 switch ((action
= buf
[1]))
946 if (sscanf(buf
, ";%*c%2x", &sig
) <= 0 ||
947 sig
!= gdbctx
->last_sig
)
955 if (buf
< end
&& *buf
== ':' && (n
= sscanf(buf
, ":%x", &tid
)) <= 0)
958 handle_step_or_continue(gdbctx
, tid
, action
== 's' || action
== 'S', sig
);
961 wait_for_debuggee(gdbctx
);
962 return packet_reply_status(gdbctx
);
965 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
967 if (gdbctx
->in_packet_len
>= 4 && !memcmp(gdbctx
->in_packet
, "Cont", 4))
969 return packet_verbose_cont(gdbctx
);
972 if (gdbctx
->in_packet_len
== 14 && !memcmp(gdbctx
->in_packet
, "MustReplyEmpty", 14))
973 return packet_reply(gdbctx
, "");
978 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
983 if ((n
= sscanf(gdbctx
->in_packet
, "%x;%p", &sig
, &addr
)) == 2)
984 FIXME("Continue at address %p not supported\n", addr
);
985 if (n
< 1) return packet_error
;
987 if (sig
!= gdbctx
->last_sig
)
989 ERR("Changing signals is not supported.\n");
993 handle_step_or_continue(gdbctx
, gdbctx
->exec_tid
, FALSE
, sig
);
995 wait_for_debuggee(gdbctx
);
996 return packet_reply_status(gdbctx
);
999 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1001 detach_debuggee(gdbctx
, FALSE
);
1002 return packet_ok
| packet_last_f
;
1005 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1007 struct dbg_thread
*thread
= dbg_thread_from_tid(gdbctx
, gdbctx
->other_tid
);
1008 struct backend_cpu
*backend
;
1012 assert(gdbctx
->in_trap
);
1014 if (!thread
) return packet_error
;
1015 if (!thread
->process
) return packet_error
;
1016 if (!(backend
= thread
->process
->be_cpu
)) return packet_error
;
1018 if (!backend
->get_context(thread
->handle
, &ctx
))
1019 return packet_error
;
1021 packet_reply_open(gdbctx
);
1022 for (i
= 0; i
< backend
->gdb_num_regs
; i
++)
1023 packet_reply_register_hex_to(gdbctx
, &ctx
, i
);
1025 packet_reply_close(gdbctx
);
1029 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1031 struct dbg_thread
*thread
= dbg_thread_from_tid(gdbctx
, gdbctx
->other_tid
);
1032 struct backend_cpu
*backend
;
1037 assert(gdbctx
->in_trap
);
1039 if (!thread
) return packet_error
;
1040 if (!thread
->process
) return packet_error
;
1041 if (!(backend
= thread
->process
->be_cpu
)) return packet_error
;
1043 if (!backend
->get_context(thread
->handle
, &ctx
))
1044 return packet_error
;
1046 if (gdbctx
->in_packet_len
< backend
->gdb_num_regs
* 2)
1047 return packet_error
;
1049 ptr
= gdbctx
->in_packet
;
1050 for (i
= 0; i
< backend
->gdb_num_regs
; i
++)
1051 cpu_register_hex_from(gdbctx
, &ctx
, i
, &ptr
);
1053 if (!backend
->set_context(thread
->handle
, &ctx
))
1055 ERR("Failed to set context for tid %04x, error %u\n", thread
->tid
, GetLastError());
1056 return packet_error
;
1062 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1064 detach_debuggee(gdbctx
, TRUE
);
1065 return packet_ok
| packet_last_f
;
1068 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1070 switch (gdbctx
->in_packet
[0])
1073 if (sscanf(gdbctx
->in_packet
, "c%x", &gdbctx
->exec_tid
) == 1)
1075 return packet_error
;
1077 if (sscanf(gdbctx
->in_packet
, "g%x", &gdbctx
->other_tid
) == 1)
1079 return packet_error
;
1081 FIXME("Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1082 return packet_error
;
1086 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1089 unsigned int len
, blk_len
, nread
;
1093 assert(gdbctx
->in_trap
);
1094 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1095 if (len
<= 0) return packet_error
;
1096 TRACE("Read %u bytes at %p\n", len
, addr
);
1097 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1099 blk_len
= min(sizeof(buffer
), len
- nread
);
1100 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
,
1101 buffer
, blk_len
, &r
) || r
== 0)
1103 /* fail at first address, return error */
1104 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1105 /* something has already been read, return partial information */
1108 if (nread
== 0) packet_reply_open(gdbctx
);
1109 packet_reply_hex_to(gdbctx
, buffer
, r
);
1111 packet_reply_close(gdbctx
);
1115 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1118 unsigned int len
, blk_len
;
1123 assert(gdbctx
->in_trap
);
1124 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1127 ERR("Cannot find ':' in %s\n", debugstr_an(gdbctx
->in_packet
, gdbctx
->in_packet_len
));
1128 return packet_error
;
1132 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1134 ERR("Failed to parse %s\n", debugstr_a(gdbctx
->in_packet
));
1135 return packet_error
;
1137 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1139 ERR("Length %u does not match packet length %u\n",
1140 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1141 return packet_error
;
1143 TRACE("Write %u bytes at %p\n", len
, addr
);
1146 blk_len
= min(sizeof(buffer
), len
);
1147 hex_from(buffer
, ptr
, blk_len
);
1148 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1155 return packet_ok
; /* FIXME: error while writing ? */
1158 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1160 struct dbg_thread
*thread
= dbg_thread_from_tid(gdbctx
, gdbctx
->other_tid
);
1161 struct backend_cpu
*backend
;
1165 assert(gdbctx
->in_trap
);
1167 if (!thread
) return packet_error
;
1168 if (!thread
->process
) return packet_error
;
1169 if (!(backend
= thread
->process
->be_cpu
)) return packet_error
;
1171 if (!backend
->get_context(thread
->handle
, &ctx
))
1172 return packet_error
;
1174 if (sscanf(gdbctx
->in_packet
, "%zx", ®
) != 1)
1175 return packet_error
;
1176 if (reg
>= backend
->gdb_num_regs
)
1178 WARN("Unhandled register %zu\n", reg
);
1179 return packet_error
;
1182 TRACE("%zu => %s\n", reg
, wine_dbgstr_longlong(cpu_register(gdbctx
, &ctx
, reg
)));
1184 packet_reply_open(gdbctx
);
1185 packet_reply_register_hex_to(gdbctx
, &ctx
, reg
);
1186 packet_reply_close(gdbctx
);
1190 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1192 struct dbg_thread
*thread
= dbg_thread_from_tid(gdbctx
, gdbctx
->other_tid
);
1193 struct backend_cpu
*backend
;
1198 assert(gdbctx
->in_trap
);
1200 if (!thread
) return packet_error
;
1201 if (!thread
->process
) return packet_error
;
1202 if (!(backend
= thread
->process
->be_cpu
)) return packet_error
;
1204 if (!backend
->get_context(thread
->handle
, &ctx
))
1205 return packet_error
;
1207 if (!(ptr
= strchr(gdbctx
->in_packet
, '=')))
1208 return packet_error
;
1211 if (sscanf(gdbctx
->in_packet
, "%zx", ®
) != 1)
1212 return packet_error
;
1213 if (reg
>= backend
->gdb_num_regs
)
1215 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1216 * it wouldn't matter too much, and it fakes our support for all regs
1218 WARN("Unhandled register %zu\n", reg
);
1222 TRACE("%zu <= %s\n", reg
, debugstr_an(ptr
, (int)(gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
))));
1224 cpu_register_hex_from(gdbctx
, &ctx
, reg
, (const char**)&ptr
);
1225 if (!backend
->set_context(thread
->handle
, &ctx
))
1227 ERR("Failed to set context for tid %04x, error %u\n", thread
->tid
, GetLastError());
1228 return packet_error
;
1234 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1242 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1243 strcpy(clsName
, "-- Unknown --");
1244 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1245 strcpy(wndName
, "-- Empty --");
1247 packet_reply_open(gdbctx
);
1248 packet_reply_add(gdbctx
, "O");
1249 snprintf(buffer
, sizeof(buffer
),
1250 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1251 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1252 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1253 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1255 packet_reply_hex_to_str(gdbctx
, buffer
);
1256 packet_reply_close(gdbctx
);
1258 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1259 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1260 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1263 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1267 /* we do the output in several 'O' packets, with the last one being just OK for
1268 * marking the end of the output */
1269 packet_reply_open(gdbctx
);
1270 packet_reply_add(gdbctx
, "O");
1271 snprintf(buffer
, sizeof(buffer
),
1272 "%-16.16s %-17.17s %-8.8s %s\n",
1273 "hwnd", "Class Name", " Style", " WndProc Text");
1274 packet_reply_hex_to_str(gdbctx
, buffer
);
1275 packet_reply_close(gdbctx
);
1277 /* FIXME: could also add a pmt to this command in str... */
1278 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1279 packet_reply(gdbctx
, "OK");
1282 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1284 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1285 char buffer
[31+MAX_PATH
];
1287 PROCESSENTRY32 entry
;
1290 if (snap
== INVALID_HANDLE_VALUE
)
1293 entry
.dwSize
= sizeof(entry
);
1294 ok
= Process32First(snap
, &entry
);
1296 /* we do the output in several 'O' packets, with the last one being just OK for
1297 * marking the end of the output */
1299 packet_reply_open(gdbctx
);
1300 packet_reply_add(gdbctx
, "O");
1301 snprintf(buffer
, sizeof(buffer
),
1302 " %-8.8s %-8.8s %-8.8s %s\n",
1303 "pid", "threads", "parent", "executable");
1304 packet_reply_hex_to_str(gdbctx
, buffer
);
1305 packet_reply_close(gdbctx
);
1310 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1311 packet_reply_open(gdbctx
);
1312 packet_reply_add(gdbctx
, "O");
1313 snprintf(buffer
, sizeof(buffer
),
1314 "%c%08x %-8d %08x '%s'\n",
1315 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1316 entry
.th32ParentProcessID
, entry
.szExeFile
);
1317 packet_reply_hex_to_str(gdbctx
, buffer
);
1318 packet_reply_close(gdbctx
);
1319 ok
= Process32Next(snap
, &entry
);
1322 packet_reply(gdbctx
, "OK");
1325 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1327 MEMORY_BASIC_INFORMATION mbi
;
1334 /* we do the output in several 'O' packets, with the last one being just OK for
1335 * marking the end of the output */
1336 packet_reply_open(gdbctx
);
1337 packet_reply_add(gdbctx
, "O");
1338 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1339 packet_reply_close(gdbctx
);
1341 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1345 case MEM_COMMIT
: state
= "commit "; break;
1346 case MEM_FREE
: state
= "free "; break;
1347 case MEM_RESERVE
: state
= "reserve"; break;
1348 default: state
= "??? "; break;
1350 if (mbi
.State
!= MEM_FREE
)
1354 case MEM_IMAGE
: type
= "image "; break;
1355 case MEM_MAPPED
: type
= "mapped "; break;
1356 case MEM_PRIVATE
: type
= "private"; break;
1357 case 0: type
= " "; break;
1358 default: type
= "??? "; break;
1360 memset(prot
, ' ' , sizeof(prot
)-1);
1361 prot
[sizeof(prot
)-1] = '\0';
1362 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1364 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1366 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1368 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1376 packet_reply_open(gdbctx
);
1377 snprintf(buffer
, sizeof(buffer
), "%0*lx %0*lx %s %s %s\n",
1378 (unsigned)sizeof(void*), (DWORD_PTR
)addr
,
1379 (unsigned)sizeof(void*), mbi
.RegionSize
, state
, type
, prot
);
1380 packet_reply_add(gdbctx
, "O");
1381 packet_reply_hex_to_str(gdbctx
, buffer
);
1382 packet_reply_close(gdbctx
);
1384 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1386 addr
+= mbi
.RegionSize
;
1388 packet_reply(gdbctx
, "OK");
1396 void (*handler
)(struct gdb_context
*, int, const char*);
1399 {0, "wnd", 3, packet_query_monitor_wnd
},
1400 {0, "window", 6, packet_query_monitor_wnd
},
1401 {0, "proc", 4, packet_query_monitor_process
},
1402 {0, "process", 7, packet_query_monitor_process
},
1403 {0, "mem", 3, packet_query_monitor_mem
},
1407 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1408 const char* hxcmd
, size_t len
)
1411 struct query_detail
* qd
;
1413 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1415 hex_from(buffer
, hxcmd
, len
);
1417 for (qd
= query_details
; qd
->name
!= NULL
; qd
++)
1419 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1420 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1422 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1425 return packet_reply_error(gdbctx
, EINVAL
);
1428 static BOOL CALLBACK
packet_query_libraries_cb(PCSTR mod_name
, DWORD64 base
, PVOID ctx
)
1430 struct gdb_context
* gdbctx
= ctx
;
1431 MEMORY_BASIC_INFORMATION mbi
;
1432 IMAGE_SECTION_HEADER
*sec
;
1433 IMAGE_DOS_HEADER
*dos
= NULL
;
1434 IMAGE_NT_HEADERS
*nth
= NULL
;
1435 IMAGEHLP_MODULE64 mod
;
1440 mod
.SizeOfStruct
= sizeof(mod
);
1441 SymGetModuleInfo64(gdbctx
->process
->handle
, base
, &mod
);
1443 packet_reply_add(gdbctx
, "<library name=\"");
1444 if (strcmp(mod
.LoadedImageName
, "[vdso].so") == 0)
1445 packet_reply_add(gdbctx
, "linux-vdso.so.1");
1446 else if (mod
.LoadedImageName
[0] == '/')
1447 packet_reply_add(gdbctx
, mod
.LoadedImageName
);
1450 UNICODE_STRING nt_name
;
1451 ANSI_STRING ansi_name
;
1452 char *unix_path
, *tmp
;
1454 RtlInitAnsiString(&ansi_name
, mod
.LoadedImageName
);
1455 RtlAnsiStringToUnicodeString(&nt_name
, &ansi_name
, TRUE
);
1457 if ((unix_path
= wine_get_unix_file_name(nt_name
.Buffer
)))
1459 if (IsWow64Process(gdbctx
->process
->handle
, &is_wow64
) &&
1460 is_wow64
&& (tmp
= strstr(unix_path
, "system32")))
1461 memcpy(tmp
, "syswow64", 8);
1462 packet_reply_add(gdbctx
, unix_path
);
1465 packet_reply_add(gdbctx
, mod
.LoadedImageName
);
1467 HeapFree(GetProcessHeap(), 0, unix_path
);
1468 RtlFreeUnicodeString(&nt_name
);
1470 packet_reply_add(gdbctx
, "\">");
1472 size
= sizeof(buffer
);
1473 if (VirtualQueryEx(gdbctx
->process
->handle
, (void *)(UINT_PTR
)mod
.BaseOfImage
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
) &&
1474 mbi
.Type
== MEM_IMAGE
&& mbi
.State
!= MEM_FREE
)
1476 if (ReadProcessMemory(gdbctx
->process
->handle
, (void *)(UINT_PTR
)mod
.BaseOfImage
, buffer
, size
, &size
) &&
1477 size
>= sizeof(IMAGE_DOS_HEADER
))
1478 dos
= (IMAGE_DOS_HEADER
*)buffer
;
1480 if (dos
&& dos
->e_magic
== IMAGE_DOS_SIGNATURE
&& dos
->e_lfanew
< size
)
1481 nth
= (IMAGE_NT_HEADERS
*)(buffer
+ dos
->e_lfanew
);
1483 if (nth
&& memcmp(&nth
->Signature
, "PE\0\0", 4))
1487 if (!nth
) memset(buffer
, 0, sizeof(buffer
));
1489 /* if the module is not PE we have cleared buffer with 0, this makes
1490 * the following computation valid in all cases. */
1491 dos
= (IMAGE_DOS_HEADER
*)buffer
;
1492 nth
= (IMAGE_NT_HEADERS
*)(buffer
+ dos
->e_lfanew
);
1493 if (IsWow64Process(gdbctx
->process
->handle
, &is_wow64
) && is_wow64
)
1494 sec
= IMAGE_FIRST_SECTION((IMAGE_NT_HEADERS32
*)nth
);
1496 sec
= IMAGE_FIRST_SECTION((IMAGE_NT_HEADERS64
*)nth
);
1498 for (i
= 0; i
< max(nth
->FileHeader
.NumberOfSections
, 1); ++i
)
1500 if ((char *)(sec
+ i
) >= buffer
+ size
) break;
1501 packet_reply_add(gdbctx
, "<segment address=\"0x");
1502 packet_reply_val(gdbctx
, mod
.BaseOfImage
+ sec
[i
].VirtualAddress
, sizeof(unsigned long));
1503 packet_reply_add(gdbctx
, "\"/>");
1506 packet_reply_add(gdbctx
, "</library>");
1511 static void packet_query_libraries(struct gdb_context
* gdbctx
)
1515 /* this will resynchronize builtin dbghelp's internal ELF module list */
1516 SymLoadModule(gdbctx
->process
->handle
, 0, 0, 0, 0, 0);
1518 packet_reply_add(gdbctx
, "<library-list>");
1519 opt
= SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES
, TRUE
);
1520 SymEnumerateModules64(gdbctx
->process
->handle
, packet_query_libraries_cb
, gdbctx
);
1521 SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES
, opt
);
1522 packet_reply_add(gdbctx
, "</library-list>");
1525 static void packet_query_threads(struct gdb_context
* gdbctx
)
1527 struct dbg_process
* process
= gdbctx
->process
;
1528 struct dbg_thread
* thread
;
1530 packet_reply_add(gdbctx
, "<threads>");
1531 LIST_FOR_EACH_ENTRY(thread
, &process
->threads
, struct dbg_thread
, entry
)
1533 packet_reply_add(gdbctx
, "<thread ");
1534 packet_reply_add(gdbctx
, "id=\"");
1535 packet_reply_val(gdbctx
, thread
->tid
, 4);
1536 packet_reply_add(gdbctx
, "\" name=\"");
1537 packet_reply_add(gdbctx
, thread
->name
);
1538 packet_reply_add(gdbctx
, "\"/>");
1540 packet_reply_add(gdbctx
, "</threads>");
1543 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1547 switch (gdbctx
->in_packet
[0])
1550 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1552 struct dbg_thread
* thd
;
1554 packet_reply_open(gdbctx
);
1555 packet_reply_add(gdbctx
, "m");
1556 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1558 packet_reply_val(gdbctx
, thd
->tid
, 4);
1559 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1560 packet_reply_add(gdbctx
, ",");
1562 packet_reply_close(gdbctx
);
1565 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1569 packet_reply_open(gdbctx
);
1570 packet_reply_add(gdbctx
, "O");
1571 get_process_info(gdbctx
, result
, sizeof(result
));
1572 packet_reply_hex_to_str(gdbctx
, result
);
1573 packet_reply_close(gdbctx
);
1578 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1580 packet_reply(gdbctx
, "l");
1583 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1585 packet_reply(gdbctx
, "l");
1590 if (strncmp(gdbctx
->in_packet
, "Attached", gdbctx
->in_packet_len
) == 0)
1591 return packet_reply(gdbctx
, "1");
1594 if (gdbctx
->in_packet_len
== 1)
1596 struct dbg_thread
* thd
;
1597 /* FIXME: doc says 16 bit val ??? */
1598 /* grab first created thread, aka last in list */
1599 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
1600 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
1601 packet_reply_open(gdbctx
);
1602 packet_reply_add(gdbctx
, "QC");
1603 packet_reply_val(gdbctx
, thd
->tid
, 4);
1604 packet_reply_close(gdbctx
);
1609 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1613 snprintf(buf
, sizeof(buf
),
1614 "Text=%08lx;Data=%08lx;Bss=%08lx",
1615 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1616 gdbctx
->wine_segs
[2]);
1617 return packet_reply(gdbctx
, buf
);
1621 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1623 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1624 gdbctx
->in_packet_len
- 5);
1628 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1630 if (strncmp(gdbctx
->in_packet
, "Supported", 9) == 0)
1632 packet_reply_open(gdbctx
);
1633 packet_reply_add(gdbctx
, "QStartNoAckMode+;");
1634 packet_reply_add(gdbctx
, "qXfer:libraries:read+;");
1635 packet_reply_add(gdbctx
, "qXfer:threads:read+;");
1636 if (*target_xml
) packet_reply_add(gdbctx
, "PacketSize=400;qXfer:features:read+");
1637 packet_reply_close(gdbctx
);
1642 if (gdbctx
->in_packet_len
> 15 &&
1643 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1644 gdbctx
->in_packet
[15] == ',')
1650 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1651 if (end
== NULL
) break;
1652 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1653 packet_reply_open(gdbctx
);
1654 packet_reply_hex_to_str(gdbctx
, result
);
1655 packet_reply_close(gdbctx
);
1658 if (strncmp(gdbctx
->in_packet
, "TStatus", 7) == 0)
1660 /* Tracepoints not supported */
1661 packet_reply_open(gdbctx
);
1662 packet_reply_close(gdbctx
);
1667 if (sscanf(gdbctx
->in_packet
, "Xfer:libraries:read::%x,%x", &off
, &len
) == 2)
1669 if (!gdbctx
->process
) return packet_error
;
1671 packet_reply_open_xfer(gdbctx
);
1672 packet_query_libraries(gdbctx
);
1673 packet_reply_close_xfer(gdbctx
, off
, len
);
1677 if (sscanf(gdbctx
->in_packet
, "Xfer:threads:read::%x,%x", &off
, &len
) == 2)
1679 if (!gdbctx
->process
) return packet_error
;
1681 packet_reply_open_xfer(gdbctx
);
1682 packet_query_threads(gdbctx
);
1683 packet_reply_close_xfer(gdbctx
, off
, len
);
1687 if (*target_xml
&& strncmp(gdbctx
->in_packet
, "Xfer:features:read:target.xml", 29) == 0)
1688 return packet_reply(gdbctx
, target_xml
);
1691 ERR("Unhandled query %s\n", debugstr_an(gdbctx
->in_packet
, gdbctx
->in_packet_len
));
1692 return packet_error
;
1695 static enum packet_return
packet_set(struct gdb_context
* gdbctx
)
1697 if (strncmp(gdbctx
->in_packet
, "StartNoAckMode", 14) == 0)
1699 gdbctx
->no_ack_mode
= TRUE
;
1703 return packet_error
;
1706 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1710 if (sscanf(gdbctx
->in_packet
, "%p", &addr
) == 1)
1711 FIXME("Continue at address %p not supported\n", addr
);
1713 handle_step_or_continue(gdbctx
, gdbctx
->exec_tid
, TRUE
, -1);
1715 wait_for_debuggee(gdbctx
);
1716 return packet_reply_status(gdbctx
);
1719 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1724 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1725 if (tid
== -1 || tid
== 0)
1726 return packet_reply_error(gdbctx
, EINVAL
);
1727 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1729 return packet_reply_error(gdbctx
, ESRCH
);
1732 /* =============================================== *
1733 * P A C K E T I N F R A S T R U C T U R E *
1734 * =============================================== *
1740 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1743 static struct packet_entry packet_entries
[] =
1745 {'?', packet_last_signal
},
1746 {'c', packet_continue
},
1747 {'C', packet_continue_signal
},
1748 {'D', packet_detach
},
1749 {'g', packet_read_registers
},
1750 {'G', packet_write_registers
},
1752 {'H', packet_thread
},
1753 {'m', packet_read_memory
},
1754 {'M', packet_write_memory
},
1755 {'p', packet_read_register
},
1756 {'P', packet_write_register
},
1757 {'q', packet_query
},
1760 {'T', packet_thread_alive
},
1761 {'v', packet_verbose
},
1764 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
1766 char *ptr
, *sum
= gdbctx
->in_buf
, *end
= gdbctx
->in_buf
+ gdbctx
->in_len
;
1767 enum packet_return ret
= packet_error
;
1771 /* ptr points to the beginning ('$') of the current packet
1772 * sum points to the beginning ('#') of the current packet checksum ("#xx")
1773 * len is the length of the current packet data (sum - ptr - 1)
1774 * end points to the end of the received data buffer
1777 while (!gdbctx
->no_ack_mode
&&
1778 (ptr
= memchr(sum
, '$', end
- sum
)) &&
1779 (sum
= memchr(ptr
, '#', end
- ptr
)) &&
1780 (end
- sum
>= 3) && sscanf(sum
, "#%02x", &cksum
) == 1)
1782 len
= sum
- ptr
- 1;
1785 if (cksum
== checksum(ptr
+ 1, len
))
1787 TRACE("Acking: %s\n", debugstr_an(ptr
, sum
- ptr
));
1788 write(gdbctx
->sock
, "+", 1);
1792 ERR("Nacking: %s (checksum: %d != %d)\n", debugstr_an(ptr
, sum
- ptr
),
1793 cksum
, checksum(ptr
+ 1, len
));
1794 write(gdbctx
->sock
, "-", 1);
1798 while ((ret
& packet_last_f
) == 0 &&
1799 (ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
)) &&
1800 (sum
= memchr(ptr
, '#', end
- ptr
)) &&
1801 (end
- sum
>= 3) && sscanf(sum
, "#%02x", &cksum
) == 1)
1803 if (ptr
!= gdbctx
->in_buf
)
1804 WARN("Ignoring: %s\n", debugstr_an(gdbctx
->in_buf
, ptr
- gdbctx
->in_buf
));
1806 len
= sum
- ptr
- 1;
1809 if (cksum
== checksum(ptr
+ 1, len
))
1811 TRACE("Handling: %s\n", debugstr_an(ptr
, sum
- ptr
));
1814 gdbctx
->in_packet
= ptr
+ 2;
1815 gdbctx
->in_packet_len
= len
- 1;
1816 gdbctx
->in_packet
[gdbctx
->in_packet_len
] = '\0';
1818 for (i
= 0; i
< ARRAY_SIZE(packet_entries
); i
++)
1819 if (packet_entries
[i
].key
== ptr
[1])
1822 if (i
== ARRAY_SIZE(packet_entries
))
1823 WARN("Unhandled: %s\n", debugstr_an(ptr
+ 1, len
));
1824 else if (((ret
= (packet_entries
[i
].handler
)(gdbctx
)) & ~packet_last_f
) == packet_error
)
1825 WARN("Failed: %s\n", debugstr_an(ptr
+ 1, len
));
1827 switch (ret
& ~packet_last_f
)
1829 case packet_error
: packet_reply(gdbctx
, ""); break;
1830 case packet_ok
: packet_reply(gdbctx
, "OK"); break;
1831 case packet_done
: break;
1834 TRACE("Reply: %s\n", debugstr_an(gdbctx
->out_buf
, gdbctx
->out_len
));
1835 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
1836 assert(i
== gdbctx
->out_len
);
1837 gdbctx
->out_len
= 0;
1840 WARN("Ignoring: %s (checksum: %d != %d)\n", debugstr_an(ptr
, sum
- ptr
),
1841 cksum
, checksum(ptr
+ 1, len
));
1843 gdbctx
->in_len
= end
- sum
;
1844 memmove(gdbctx
->in_buf
, sum
, end
- sum
);
1845 end
= gdbctx
->in_buf
+ gdbctx
->in_len
;
1848 return (ret
& packet_last_f
);
1851 static int fetch_data(struct gdb_context
* gdbctx
)
1853 int len
, in_len
= gdbctx
->in_len
;
1855 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1859 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
1860 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
1862 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
- 1);
1863 if (len
<= 0) break;
1864 gdbctx
->in_len
+= len
;
1865 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1866 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
1869 gdbctx
->in_buf
[gdbctx
->in_len
] = '\0';
1870 return gdbctx
->in_len
- in_len
;
1873 #define FLAG_NO_START 1
1874 #define FLAG_WITH_XTERM 2
1876 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
1880 const char *gdb_path
, *tmp_path
;
1883 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
1884 if (!(tmp_path
= getenv("TMPDIR"))) tmp_path
= "/tmp";
1885 strcpy(buf
, tmp_path
);
1886 strcat(buf
, "/winegdb.XXXXXX");
1887 fd
= mkstemps(buf
, 0);
1888 if (fd
== -1) return FALSE
;
1889 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
1890 fprintf(f
, "file \"%s\"\n", wine_path
);
1891 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
1892 fprintf(f
, "set prompt Wine-gdb>\\ \n");
1893 /* gdb 5.1 seems to require it, won't hurt anyway */
1894 fprintf(f
, "sharedlibrary\n");
1895 /* This is needed (but not a decent & final fix)
1896 * Without this, gdb would skip our inter-DLL relay code (because
1897 * we don't have any line number information for the relay code)
1898 * With this, we will stop on first instruction of the stub, and
1899 * reusing step, will get us through the relay stub at the actual
1900 * function we're looking at.
1902 fprintf(f
, "set step-mode on\n");
1903 /* tell gdb to delete this file when done handling it... */
1904 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
1906 if (flags
& FLAG_WITH_XTERM
)
1907 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
1909 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
1910 assert(0); /* never reached */
1914 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, unsigned flags
, unsigned port
)
1917 struct sockaddr_in s_addrs
= {0};
1918 socklen_t s_len
= sizeof(s_addrs
);
1919 struct pollfd pollfd
;
1920 IMAGEHLP_MODULE64 imh_mod
;
1923 /* step 1: create socket for gdb connection request */
1924 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1926 ERR("Failed to create socket: %s\n", strerror(errno
));
1930 s_addrs
.sin_family
= AF_INET
;
1931 s_addrs
.sin_addr
.s_addr
= INADDR_ANY
;
1932 s_addrs
.sin_port
= htons(port
);
1933 if (bind(sock
, (struct sockaddr
*)&s_addrs
, sizeof(s_addrs
)) == -1)
1936 if (listen(sock
, 1) == -1 || getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
1939 /* step 2: do the process internal creation */
1940 handle_debug_event(gdbctx
);
1942 /* step3: get the wine loader name */
1943 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
))
1946 /* step 4: fire up gdb (if requested) */
1947 if (flags
& FLAG_NO_START
)
1948 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
1952 case -1: /* error in parent... */
1953 ERR("Failed to start gdb: fork: %s\n", strerror(errno
));
1955 default: /* in parent... success */
1956 signal(SIGINT
, SIG_IGN
);
1958 case 0: /* in child... and alive */
1959 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
1960 /* if we're here, exec failed, so report failure */
1964 /* step 5: wait for gdb to connect actually */
1966 pollfd
.events
= POLLIN
;
1969 switch (poll(&pollfd
, 1, -1))
1972 if (pollfd
.revents
& POLLIN
)
1975 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
1976 if (gdbctx
->sock
== -1)
1979 TRACE("connected on %d\n", gdbctx
->sock
);
1980 /* don't keep our small packets too long: send them ASAP back to GDB
1981 * without this, GDB really crawls
1983 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
1987 ERR("Timed out connecting to gdb\n");
1990 ERR("Failed to connect to gdb: poll: %s\n", strerror(errno
));
2001 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
, unsigned port
)
2006 gdbctx
->in_buf
= NULL
;
2007 gdbctx
->in_buf_alloc
= 0;
2009 gdbctx
->out_buf
= NULL
;
2010 gdbctx
->out_buf_alloc
= 0;
2011 gdbctx
->out_len
= 0;
2012 gdbctx
->out_curr_packet
= -1;
2014 gdbctx
->exec_tid
= -1;
2015 gdbctx
->other_tid
= -1;
2016 gdbctx
->last_sig
= 0;
2017 gdbctx
->in_trap
= FALSE
;
2018 gdbctx
->process
= NULL
;
2019 gdbctx
->no_ack_mode
= FALSE
;
2020 for (i
= 0; i
< ARRAY_SIZE(gdbctx
->wine_segs
); i
++)
2021 gdbctx
->wine_segs
[i
] = 0;
2023 /* wait for first trap */
2024 while (WaitForDebugEvent(&gdbctx
->de
, INFINITE
))
2026 if (gdbctx
->de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2028 /* this should be the first event we get,
2029 * and the only one of this type */
2030 assert(gdbctx
->process
== NULL
&& gdbctx
->de
.dwProcessId
== dbg_curr_pid
);
2031 /* gdbctx->dwProcessId = pid; */
2032 if (!gdb_startup(gdbctx
, flags
, port
)) return FALSE
;
2033 assert(!gdbctx
->in_trap
);
2037 handle_debug_event(gdbctx
);
2038 if (gdbctx
->in_trap
) break;
2040 ContinueDebugEvent(gdbctx
->de
.dwProcessId
, gdbctx
->de
.dwThreadId
, DBG_CONTINUE
);
2045 static int gdb_remote(unsigned flags
, unsigned port
)
2047 struct pollfd pollfd
;
2048 struct gdb_context gdbctx
;
2051 for (doLoop
= gdb_init_context(&gdbctx
, flags
, port
); doLoop
;)
2053 pollfd
.fd
= gdbctx
.sock
;
2054 pollfd
.events
= POLLIN
;
2057 switch (poll(&pollfd
, 1, -1))
2061 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2063 ERR("gdb hung up\n");
2064 /* kill also debuggee process - questionnable - */
2065 detach_debuggee(&gdbctx
, TRUE
);
2069 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2071 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2075 /* timeout, should never happen (infinite timeout) */
2078 ERR("poll failed: %s\n", strerror(errno
));
2088 int gdb_main(int argc
, char* argv
[])
2091 unsigned gdb_flags
= 0, port
= 0;
2095 while (argc
> 0 && argv
[0][0] == '-')
2097 if (strcmp(argv
[0], "--no-start") == 0)
2099 gdb_flags
|= FLAG_NO_START
;
2103 if (strcmp(argv
[0], "--with-xterm") == 0)
2105 gdb_flags
|= FLAG_WITH_XTERM
;
2109 if (strcmp(argv
[0], "--port") == 0 && argc
> 1)
2111 port
= strtoul(argv
[1], &port_end
, 10);
2114 fprintf(stderr
, "Invalid port: %s\n", argv
[1]);
2117 argc
-= 2; argv
+= 2;
2122 if (dbg_active_attach(argc
, argv
) == start_ok
||
2123 dbg_active_launch(argc
, argv
) == start_ok
)
2124 return gdb_remote(gdb_flags
, port
);
2126 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");