2 * A Win32 based proxy implementing the GBD remote protocol
3 * This allows to debug Wine (and any "emulated" program) under
6 * Copyright (c) Eric Pouech 2002-2004
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 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 * =============================================== *
201 static size_t cpu_register_map
[] = {
202 FIELD_OFFSET(CONTEXT
, Eax
),
203 FIELD_OFFSET(CONTEXT
, Ecx
),
204 FIELD_OFFSET(CONTEXT
, Edx
),
205 FIELD_OFFSET(CONTEXT
, Ebx
),
206 FIELD_OFFSET(CONTEXT
, Esp
),
207 FIELD_OFFSET(CONTEXT
, Ebp
),
208 FIELD_OFFSET(CONTEXT
, Esi
),
209 FIELD_OFFSET(CONTEXT
, Edi
),
210 FIELD_OFFSET(CONTEXT
, Eip
),
211 FIELD_OFFSET(CONTEXT
, EFlags
),
212 FIELD_OFFSET(CONTEXT
, SegCs
),
213 FIELD_OFFSET(CONTEXT
, SegSs
),
214 FIELD_OFFSET(CONTEXT
, SegDs
),
215 FIELD_OFFSET(CONTEXT
, SegEs
),
216 FIELD_OFFSET(CONTEXT
, SegFs
),
217 FIELD_OFFSET(CONTEXT
, SegGs
),
219 #elif defined(__powerpc__)
220 static size_t cpu_register_map
[] = {
221 FIELD_OFFSET(CONTEXT
, Gpr0
),
222 FIELD_OFFSET(CONTEXT
, Gpr1
),
223 FIELD_OFFSET(CONTEXT
, Gpr2
),
224 FIELD_OFFSET(CONTEXT
, Gpr3
),
225 FIELD_OFFSET(CONTEXT
, Gpr4
),
226 FIELD_OFFSET(CONTEXT
, Gpr5
),
227 FIELD_OFFSET(CONTEXT
, Gpr6
),
228 FIELD_OFFSET(CONTEXT
, Gpr7
),
229 FIELD_OFFSET(CONTEXT
, Gpr8
),
230 FIELD_OFFSET(CONTEXT
, Gpr9
),
231 FIELD_OFFSET(CONTEXT
, Gpr10
),
232 FIELD_OFFSET(CONTEXT
, Gpr11
),
233 FIELD_OFFSET(CONTEXT
, Gpr12
),
234 FIELD_OFFSET(CONTEXT
, Gpr13
),
235 FIELD_OFFSET(CONTEXT
, Gpr14
),
236 FIELD_OFFSET(CONTEXT
, Gpr15
),
237 FIELD_OFFSET(CONTEXT
, Gpr16
),
238 FIELD_OFFSET(CONTEXT
, Gpr17
),
239 FIELD_OFFSET(CONTEXT
, Gpr18
),
240 FIELD_OFFSET(CONTEXT
, Gpr19
),
241 FIELD_OFFSET(CONTEXT
, Gpr20
),
242 FIELD_OFFSET(CONTEXT
, Gpr21
),
243 FIELD_OFFSET(CONTEXT
, Gpr22
),
244 FIELD_OFFSET(CONTEXT
, Gpr23
),
245 FIELD_OFFSET(CONTEXT
, Gpr24
),
246 FIELD_OFFSET(CONTEXT
, Gpr25
),
247 FIELD_OFFSET(CONTEXT
, Gpr26
),
248 FIELD_OFFSET(CONTEXT
, Gpr27
),
249 FIELD_OFFSET(CONTEXT
, Gpr28
),
250 FIELD_OFFSET(CONTEXT
, Gpr29
),
251 FIELD_OFFSET(CONTEXT
, Gpr30
),
252 FIELD_OFFSET(CONTEXT
, Gpr31
),
253 FIELD_OFFSET(CONTEXT
, Fpr0
),
254 FIELD_OFFSET(CONTEXT
, Fpr1
),
255 FIELD_OFFSET(CONTEXT
, Fpr2
),
256 FIELD_OFFSET(CONTEXT
, Fpr3
),
257 FIELD_OFFSET(CONTEXT
, Fpr4
),
258 FIELD_OFFSET(CONTEXT
, Fpr5
),
259 FIELD_OFFSET(CONTEXT
, Fpr6
),
260 FIELD_OFFSET(CONTEXT
, Fpr7
),
261 FIELD_OFFSET(CONTEXT
, Fpr8
),
262 FIELD_OFFSET(CONTEXT
, Fpr9
),
263 FIELD_OFFSET(CONTEXT
, Fpr10
),
264 FIELD_OFFSET(CONTEXT
, Fpr11
),
265 FIELD_OFFSET(CONTEXT
, Fpr12
),
266 FIELD_OFFSET(CONTEXT
, Fpr13
),
267 FIELD_OFFSET(CONTEXT
, Fpr14
),
268 FIELD_OFFSET(CONTEXT
, Fpr15
),
269 FIELD_OFFSET(CONTEXT
, Fpr16
),
270 FIELD_OFFSET(CONTEXT
, Fpr17
),
271 FIELD_OFFSET(CONTEXT
, Fpr18
),
272 FIELD_OFFSET(CONTEXT
, Fpr19
),
273 FIELD_OFFSET(CONTEXT
, Fpr20
),
274 FIELD_OFFSET(CONTEXT
, Fpr21
),
275 FIELD_OFFSET(CONTEXT
, Fpr22
),
276 FIELD_OFFSET(CONTEXT
, Fpr23
),
277 FIELD_OFFSET(CONTEXT
, Fpr24
),
278 FIELD_OFFSET(CONTEXT
, Fpr25
),
279 FIELD_OFFSET(CONTEXT
, Fpr26
),
280 FIELD_OFFSET(CONTEXT
, Fpr27
),
281 FIELD_OFFSET(CONTEXT
, Fpr28
),
282 FIELD_OFFSET(CONTEXT
, Fpr29
),
283 FIELD_OFFSET(CONTEXT
, Fpr30
),
284 FIELD_OFFSET(CONTEXT
, Fpr31
),
286 FIELD_OFFSET(CONTEXT
, Iar
),
287 FIELD_OFFSET(CONTEXT
, Msr
),
288 FIELD_OFFSET(CONTEXT
, Cr
),
289 FIELD_OFFSET(CONTEXT
, Lr
),
290 FIELD_OFFSET(CONTEXT
, Ctr
),
291 FIELD_OFFSET(CONTEXT
, Xer
),
292 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
293 /* see gdb/nlm/ppc.c */
295 #elif defined(__ALPHA__)
296 static size_t cpu_register_map
[] = {
297 FIELD_OFFSET(CONTEXT
, IntV0
),
298 FIELD_OFFSET(CONTEXT
, IntT0
),
299 FIELD_OFFSET(CONTEXT
, IntT1
),
300 FIELD_OFFSET(CONTEXT
, IntT2
),
301 FIELD_OFFSET(CONTEXT
, IntT3
),
302 FIELD_OFFSET(CONTEXT
, IntT4
),
303 FIELD_OFFSET(CONTEXT
, IntT5
),
304 FIELD_OFFSET(CONTEXT
, IntT6
),
305 FIELD_OFFSET(CONTEXT
, IntT7
),
306 FIELD_OFFSET(CONTEXT
, IntS0
),
307 FIELD_OFFSET(CONTEXT
, IntS1
),
308 FIELD_OFFSET(CONTEXT
, IntS2
),
309 FIELD_OFFSET(CONTEXT
, IntS3
),
310 FIELD_OFFSET(CONTEXT
, IntS4
),
311 FIELD_OFFSET(CONTEXT
, IntS5
),
312 FIELD_OFFSET(CONTEXT
, IntFp
),
313 FIELD_OFFSET(CONTEXT
, IntA0
),
314 FIELD_OFFSET(CONTEXT
, IntA1
),
315 FIELD_OFFSET(CONTEXT
, IntA2
),
316 FIELD_OFFSET(CONTEXT
, IntA3
),
317 FIELD_OFFSET(CONTEXT
, IntA4
),
318 FIELD_OFFSET(CONTEXT
, IntA5
),
319 FIELD_OFFSET(CONTEXT
, IntT8
),
320 FIELD_OFFSET(CONTEXT
, IntT9
),
321 FIELD_OFFSET(CONTEXT
, IntT10
),
322 FIELD_OFFSET(CONTEXT
, IntT11
),
323 FIELD_OFFSET(CONTEXT
, IntRa
),
324 FIELD_OFFSET(CONTEXT
, IntT12
),
325 FIELD_OFFSET(CONTEXT
, IntAt
),
326 FIELD_OFFSET(CONTEXT
, IntGp
),
327 FIELD_OFFSET(CONTEXT
, IntSp
),
328 FIELD_OFFSET(CONTEXT
, IntZero
),
329 FIELD_OFFSET(CONTEXT
, FltF0
),
330 FIELD_OFFSET(CONTEXT
, FltF1
),
331 FIELD_OFFSET(CONTEXT
, FltF2
),
332 FIELD_OFFSET(CONTEXT
, FltF3
),
333 FIELD_OFFSET(CONTEXT
, FltF4
),
334 FIELD_OFFSET(CONTEXT
, FltF5
),
335 FIELD_OFFSET(CONTEXT
, FltF6
),
336 FIELD_OFFSET(CONTEXT
, FltF7
),
337 FIELD_OFFSET(CONTEXT
, FltF8
),
338 FIELD_OFFSET(CONTEXT
, FltF9
),
339 FIELD_OFFSET(CONTEXT
, FltF10
),
340 FIELD_OFFSET(CONTEXT
, FltF11
),
341 FIELD_OFFSET(CONTEXT
, FltF12
),
342 FIELD_OFFSET(CONTEXT
, FltF13
),
343 FIELD_OFFSET(CONTEXT
, FltF14
),
344 FIELD_OFFSET(CONTEXT
, FltF15
),
345 FIELD_OFFSET(CONTEXT
, FltF16
),
346 FIELD_OFFSET(CONTEXT
, FltF17
),
347 FIELD_OFFSET(CONTEXT
, FltF18
),
348 FIELD_OFFSET(CONTEXT
, FltF19
),
349 FIELD_OFFSET(CONTEXT
, FltF20
),
350 FIELD_OFFSET(CONTEXT
, FltF21
),
351 FIELD_OFFSET(CONTEXT
, FltF22
),
352 FIELD_OFFSET(CONTEXT
, FltF23
),
353 FIELD_OFFSET(CONTEXT
, FltF24
),
354 FIELD_OFFSET(CONTEXT
, FltF25
),
355 FIELD_OFFSET(CONTEXT
, FltF26
),
356 FIELD_OFFSET(CONTEXT
, FltF27
),
357 FIELD_OFFSET(CONTEXT
, FltF28
),
358 FIELD_OFFSET(CONTEXT
, FltF29
),
359 FIELD_OFFSET(CONTEXT
, FltF30
),
360 FIELD_OFFSET(CONTEXT
, FltF31
),
362 /* FIXME: Didn't look for the right order yet */
363 FIELD_OFFSET(CONTEXT
, Fir
),
364 FIELD_OFFSET(CONTEXT
, Fpcr
),
365 FIELD_OFFSET(CONTEXT
, SoftFpcr
),
367 #elif defined(__x86_64__)
368 static size_t cpu_register_map
[] = {
369 FIELD_OFFSET(CONTEXT
, Rax
),
370 FIELD_OFFSET(CONTEXT
, Rbx
),
371 FIELD_OFFSET(CONTEXT
, Rcx
),
372 FIELD_OFFSET(CONTEXT
, Rdx
),
373 FIELD_OFFSET(CONTEXT
, Rsi
),
374 FIELD_OFFSET(CONTEXT
, Rdi
),
375 FIELD_OFFSET(CONTEXT
, Rbp
),
376 FIELD_OFFSET(CONTEXT
, Rsp
),
377 FIELD_OFFSET(CONTEXT
, R8
),
378 FIELD_OFFSET(CONTEXT
, R9
),
379 FIELD_OFFSET(CONTEXT
, R10
),
380 FIELD_OFFSET(CONTEXT
, R11
),
381 FIELD_OFFSET(CONTEXT
, R12
),
382 FIELD_OFFSET(CONTEXT
, R13
),
383 FIELD_OFFSET(CONTEXT
, R14
),
384 FIELD_OFFSET(CONTEXT
, R15
),
385 FIELD_OFFSET(CONTEXT
, Rip
),
386 FIELD_OFFSET(CONTEXT
, EFlags
),
387 FIELD_OFFSET(CONTEXT
, SegCs
),
388 FIELD_OFFSET(CONTEXT
, SegSs
),
389 FIELD_OFFSET(CONTEXT
, SegDs
),
390 FIELD_OFFSET(CONTEXT
, SegEs
),
391 FIELD_OFFSET(CONTEXT
, SegFs
),
392 FIELD_OFFSET(CONTEXT
, SegGs
),
395 # error Define the registers map for your CPU
398 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
400 static inline unsigned long* cpu_register(CONTEXT
* ctx
, unsigned idx
)
402 assert(idx
< cpu_num_regs
);
403 return (unsigned long*)((char*)ctx
+ cpu_register_map
[idx
]);
406 /* =============================================== *
407 * W I N 3 2 D E B U G I N T E R F A C E *
408 * =============================================== *
411 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
413 ctx
->ContextFlags
= CONTEXT_CONTROL
415 #ifdef CONTEXT_SEGMENTS
418 #ifdef CONTEXT_DEBUG_REGISTERS
419 | CONTEXT_DEBUG_REGISTERS
422 if (!GetThreadContext(h
, ctx
))
424 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
425 fprintf(stderr
, "Can't get thread's context\n");
431 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
433 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
436 switch (rec
->ExceptionCode
)
438 case EXCEPTION_ACCESS_VIOLATION
:
439 case EXCEPTION_PRIV_INSTRUCTION
:
440 case EXCEPTION_STACK_OVERFLOW
:
441 case EXCEPTION_GUARD_PAGE
:
442 gdbctx
->last_sig
= SIGSEGV
;
445 case EXCEPTION_DATATYPE_MISALIGNMENT
:
446 gdbctx
->last_sig
= SIGBUS
;
449 case EXCEPTION_SINGLE_STEP
:
451 case EXCEPTION_BREAKPOINT
:
452 gdbctx
->last_sig
= SIGTRAP
;
455 case EXCEPTION_FLT_DENORMAL_OPERAND
:
456 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
457 case EXCEPTION_FLT_INEXACT_RESULT
:
458 case EXCEPTION_FLT_INVALID_OPERATION
:
459 case EXCEPTION_FLT_OVERFLOW
:
460 case EXCEPTION_FLT_STACK_CHECK
:
461 case EXCEPTION_FLT_UNDERFLOW
:
462 gdbctx
->last_sig
= SIGFPE
;
465 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
466 case EXCEPTION_INT_OVERFLOW
:
467 gdbctx
->last_sig
= SIGFPE
;
470 case EXCEPTION_ILLEGAL_INSTRUCTION
:
471 gdbctx
->last_sig
= SIGILL
;
475 gdbctx
->last_sig
= SIGINT
;
478 case STATUS_POSSIBLE_DEADLOCK
:
479 gdbctx
->last_sig
= SIGALRM
;
481 /* FIXME: we could also add here a O packet with additional information */
484 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
485 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
486 gdbctx
->last_sig
= SIGABRT
;
493 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
500 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
502 switch (de
->dwDebugEventCode
)
504 case CREATE_PROCESS_DEBUG_EVENT
:
505 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
506 de
->u
.CreateProcessInfo
.hProcess
);
507 if (!gdbctx
->process
) break;
508 memory_get_string_indirect(gdbctx
->process
,
509 de
->u
.CreateProcessInfo
.lpImageName
,
510 de
->u
.CreateProcessInfo
.fUnicode
,
511 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
512 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
514 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
515 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
516 de
->dwProcessId
, de
->dwThreadId
,
517 dbg_W2A(u
.buffer
, -1),
518 de
->u
.CreateProcessInfo
.lpImageName
,
519 de
->u
.CreateProcessInfo
.lpStartAddress
,
520 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
521 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
523 /* de->u.CreateProcessInfo.lpStartAddress; */
524 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
525 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
527 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
528 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
529 de
->dwProcessId
, de
->dwThreadId
,
530 de
->u
.CreateProcessInfo
.lpStartAddress
);
532 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
533 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
534 de
->u
.CreateProcessInfo
.hThread
,
535 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
538 case LOAD_DLL_DEBUG_EVENT
:
539 assert(dbg_curr_thread
);
540 memory_get_string_indirect(gdbctx
->process
,
541 de
->u
.LoadDll
.lpImageName
,
542 de
->u
.LoadDll
.fUnicode
,
543 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
544 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
545 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
546 de
->dwProcessId
, de
->dwThreadId
,
547 dbg_W2A(u
.buffer
, -1),
548 de
->u
.LoadDll
.lpBaseOfDll
,
549 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
550 de
->u
.LoadDll
.nDebugInfoSize
);
551 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
552 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
555 case UNLOAD_DLL_DEBUG_EVENT
:
556 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
557 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
558 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
559 SymUnloadModule(gdbctx
->process
->handle
,
560 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
563 case EXCEPTION_DEBUG_EVENT
:
564 assert(dbg_curr_thread
);
565 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
566 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
567 de
->dwProcessId
, de
->dwThreadId
,
568 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
570 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
572 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
576 case CREATE_THREAD_DEBUG_EVENT
:
577 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
578 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
579 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
581 dbg_add_thread(gdbctx
->process
,
583 de
->u
.CreateThread
.hThread
,
584 de
->u
.CreateThread
.lpThreadLocalBase
);
587 case EXIT_THREAD_DEBUG_EVENT
:
588 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
589 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
590 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
592 assert(dbg_curr_thread
);
593 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
594 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
595 dbg_del_thread(dbg_curr_thread
);
598 case EXIT_PROCESS_DEBUG_EVENT
:
599 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
600 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
601 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
603 dbg_del_process(gdbctx
->process
);
604 gdbctx
->process
= NULL
;
605 /* now signal gdb that we're done */
606 gdbctx
->last_sig
= SIGTERM
;
607 gdbctx
->in_trap
= TRUE
;
610 case OUTPUT_DEBUG_STRING_EVENT
:
611 assert(dbg_curr_thread
);
612 memory_get_string(gdbctx
->process
,
613 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
614 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
615 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
616 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
617 de
->dwProcessId
, de
->dwThreadId
, u
.bufferA
);
621 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
622 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
623 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
624 de
->u
.RipInfo
.dwType
);
628 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
629 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
630 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
634 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
638 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
639 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
640 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
641 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
642 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
643 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
644 dbg_curr_thread
->tid
, cont
);
646 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
647 fprintf(stderr
, "Cannot find last thread\n");
651 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
656 if(dbg_curr_thread
->tid
== threadid
){
657 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
658 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
659 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
660 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
661 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
662 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
663 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
664 dbg_curr_thread
->tid
, cont
);
667 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
668 fprintf(stderr
, "Cannot find last thread\n");
671 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
673 struct pollfd pollfd
;
677 pollfd
.fd
= gdbctx
->sock
;
678 pollfd
.events
= POLLIN
;
681 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
682 ret
= read(gdbctx
->sock
, &pkt
, 1);
684 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
685 fprintf(stderr
, "read failed\n");
690 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
691 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
696 } else if (ret
== -1) {
697 fprintf(stderr
, "poll failed\n");
702 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
706 gdbctx
->in_trap
= FALSE
;
709 if (!WaitForDebugEvent(&de
, 10))
711 if (GetLastError() == ERROR_SEM_TIMEOUT
)
713 if (check_for_interrupt(gdbctx
)) {
714 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
715 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
716 fprintf(stderr
, "Failed to break into debugee\n");
720 WaitForDebugEvent(&de
, INFINITE
);
728 handle_debug_event(gdbctx
, &de
);
729 assert(!gdbctx
->process
||
730 gdbctx
->process
->pid
== 0 ||
731 de
.dwProcessId
== gdbctx
->process
->pid
);
732 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
733 if (gdbctx
->in_trap
) break;
734 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
738 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
740 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
741 resume_debuggee(gdbctx
, DBG_CONTINUE
);
743 DebugActiveProcessStop(gdbctx
->process
->pid
);
744 dbg_del_process(gdbctx
->process
);
745 gdbctx
->process
= NULL
;
748 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
752 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
754 strcpy(buffer
, "Unknown process");
757 if (status
== STILL_ACTIVE
)
759 strcpy(buffer
, "Running");
762 snprintf(buffer
, len
, "Terminated (%u)", status
);
764 switch (GetPriorityClass(gdbctx
->process
->handle
))
767 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
768 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
770 #ifdef BELOW_NORMAL_PRIORITY_CLASS
771 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
773 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
774 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
775 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
776 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
778 strcat(buffer
, "\n");
781 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
782 char* buffer
, size_t len
)
784 struct dbg_thread
* thd
;
788 /* FIXME: use the size of buffer */
789 thd
= dbg_get_thread(gdbctx
->process
, tid
);
792 strcpy(buffer
, "No information");
795 if (GetExitCodeThread(thd
->handle
, &status
))
797 if (status
== STILL_ACTIVE
)
799 /* FIXME: this is a bit brutal... some nicer way shall be found */
800 switch (status
= SuspendThread(thd
->handle
))
803 case 0: strcpy(buffer
, "Running"); break;
804 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
806 ResumeThread(thd
->handle
);
809 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
813 strcpy(buffer
, "Unknown threadID");
815 switch (prio
= GetThreadPriority(thd
->handle
))
817 case THREAD_PRIORITY_ERROR_RETURN
: break;
818 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
819 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
820 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
821 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
822 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
823 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
824 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
825 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
827 assert(strlen(buffer
) < len
);
830 /* =============================================== *
831 * P A C K E T U T I L S *
832 * =============================================== *
835 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
836 packet_last_f
= 0x80};
838 static char* packet_realloc(char* buf
, int size
)
841 return HeapAlloc(GetProcessHeap(), 0, size
);
842 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
846 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
848 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
850 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
851 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
855 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
857 packet_reply_grow(gdbctx
, len
* 2);
858 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
859 gdbctx
->out_len
+= len
* 2;
862 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
864 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
867 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
871 shift
= (len
- 1) * 8;
872 packet_reply_grow(gdbctx
, len
* 2);
873 for (i
= 0; i
< len
; i
++, shift
-= 8)
875 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
876 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
880 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
882 packet_reply_grow(gdbctx
, len
);
883 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
884 gdbctx
->out_len
+= len
;
887 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
889 packet_reply_add(gdbctx
, str
, strlen(str
));
892 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
894 packet_reply_add(gdbctx
, &ch
, 1);
897 static void packet_reply_open(struct gdb_context
* gdbctx
)
899 assert(gdbctx
->out_curr_packet
== -1);
900 packet_reply_catc(gdbctx
, '$');
901 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
904 static void packet_reply_close(struct gdb_context
* gdbctx
)
909 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
910 packet_reply_catc(gdbctx
, '#');
911 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
912 packet_reply_hex_to(gdbctx
, &cksum
, 1);
913 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
914 fprintf(stderr
, "Reply : %*.*s\n",
915 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
916 gdbctx
->out_curr_packet
= -1;
919 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
921 packet_reply_open(gdbctx
);
923 if (len
== -1) len
= strlen(packet
);
924 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
926 packet_reply_add(gdbctx
, packet
, len
);
928 packet_reply_close(gdbctx
);
933 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
935 packet_reply_open(gdbctx
);
937 packet_reply_add(gdbctx
, "E", 1);
938 packet_reply_val(gdbctx
, error
, 1);
940 packet_reply_close(gdbctx
);
945 /* =============================================== *
946 * P A C K E T H A N D L E R S *
947 * =============================================== *
950 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
952 enum packet_return ret
= packet_done
;
954 packet_reply_open(gdbctx
);
956 if (gdbctx
->process
!= NULL
)
961 packet_reply_catc(gdbctx
, 'T');
962 sig
= gdbctx
->last_sig
;
963 packet_reply_val(gdbctx
, sig
, 1);
964 packet_reply_add(gdbctx
, "thread:", 7);
965 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
966 packet_reply_catc(gdbctx
, ';');
968 for (i
= 0; i
< cpu_num_regs
; i
++)
970 /* FIXME: this call will also grow the buffer...
971 * unneeded, but not harmful
973 packet_reply_val(gdbctx
, i
, 1);
974 packet_reply_catc(gdbctx
, ':');
975 packet_reply_hex_to(gdbctx
, cpu_register(&gdbctx
->context
, i
), 4);
976 packet_reply_catc(gdbctx
, ';');
981 /* Try to put an exit code
982 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
983 * just indicate the end of process and exit */
984 packet_reply_add(gdbctx
, "W00", 3);
985 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
988 packet_reply_close(gdbctx
);
994 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
996 gdbctx
->extended
= 1;
1001 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
1003 assert(gdbctx
->in_packet_len
== 0);
1004 return packet_reply_status(gdbctx
);
1007 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
1009 /* FIXME: add support for address in packet */
1010 assert(gdbctx
->in_packet_len
== 0);
1011 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1012 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1013 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1014 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1015 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1016 wait_for_debuggee(gdbctx
);
1017 return packet_reply_status(gdbctx
);
1020 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1023 int defaultAction
= -1; /* magic non action */
1026 int actionIndex
[20]; /* allow for up to 20 actions */
1027 int threadIndex
[20];
1028 int threadCount
= 0;
1029 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1030 unsigned int threadID
= 0;
1031 struct dbg_thread
* thd
;
1034 assert(gdbctx
->in_packet_len
>= 4);
1036 /* OK we have vCont followed by..
1038 * c for packet_continue
1039 * Csig for packet_continue_signal
1041 * Ssig for step signal
1042 * and then an optional thread ID at the end..
1043 * *******************************************/
1045 fprintf(stderr
, "trying to process a verbose packet\n");
1046 /* now check that we've got Cont */
1047 assert(strncmp(gdbctx
->in_packet
, "Cont", 4) == 0);
1050 if (gdbctx
->in_packet
[4] == '?')
1055 The vCont packet is supported. Each action is a supported command in the vCont packet.
1057 The vCont packet is not supported. (this didn't seem to be obeyed!)
1059 packet_reply_open(gdbctx
);
1060 packet_reply_add(gdbctx
, "vCont", 5);
1061 /* add all the supported actions to the reply (all of them for now) */
1062 packet_reply_add(gdbctx
, ";c", 2);
1063 packet_reply_add(gdbctx
, ";C", 2);
1064 packet_reply_add(gdbctx
, ";s", 2);
1065 packet_reply_add(gdbctx
, ";S", 2);
1066 packet_reply_close(gdbctx
);
1070 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1071 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1072 now if only gdb talked XML.... */
1073 #if 0 /* handy for debugging */
1074 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1077 /* go through the packet and identify where all the actions start at */
1078 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1080 if (gdbctx
->in_packet
[i
] == ';')
1082 threadIndex
[actions
] = 0;
1083 actionIndex
[actions
++] = i
;
1085 else if (gdbctx
->in_packet
[i
] == ':')
1087 threadIndex
[actions
- 1] = i
;
1091 /* now look up the default action */
1092 for (i
= 0 ; i
< actions
; i
++)
1094 if (threadIndex
[i
] == 0)
1096 if (defaultAction
!= -1)
1098 fprintf(stderr
,"Too many default actions specified\n");
1099 return packet_error
;
1105 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1107 /* go through all the threads and stick their ids in the to be done list. */
1108 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1110 threadIDs
[threadCount
++] = thd
->tid
;
1111 /* check to see if we have more threads than I counted on, and tell the user what to do
1112 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1113 if (threadCount
== 100)
1115 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1120 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1121 * that remains is to apply the actions to the threads and the default action to any threads
1123 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1124 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1125 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1126 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1128 /* deal with the threaded stuff first */
1129 for (i
= 0; i
< actions
; i
++)
1131 if (threadIndex
[i
] != 0)
1133 int j
, idLength
= 0;
1134 if (i
< actions
- 1)
1136 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1140 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1143 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1144 /* process the action */
1145 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1147 case 's': /* step */
1148 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1150 case 'c': /* continue */
1151 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1153 case 'S': /* step Sig, */
1154 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1156 case 'C': /* continue sig */
1157 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1158 /* cannot change signals on the fly */
1159 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1160 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1161 if (sig
!= gdbctx
->last_sig
)
1162 return packet_error
;
1163 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1166 for (j
= 0 ; j
< threadCount
; j
++)
1168 if (threadIDs
[j
] == threadID
)
1175 } /* for i=0 ; i< actions */
1177 /* now we have manage the default action */
1178 if (defaultAction
>= 0)
1180 for (i
= 0 ; i
< threadCount
; i
++)
1182 /* check to see if we've already done something to the thread*/
1183 if (threadIDs
[i
] != 0)
1185 /* if not apply the default action*/
1186 threadID
= threadIDs
[i
];
1187 /* process the action (yes this is almost identical to the one above!) */
1188 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1190 case 's': /* step */
1191 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1193 case 'c': /* continue */
1194 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1197 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1199 case 'C': /* continue sig */
1200 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1201 /* cannot change signals on the fly */
1202 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1203 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1204 if (sig
!= gdbctx
->last_sig
)
1205 return packet_error
;
1206 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1211 } /* if(defaultAction >=0) */
1213 wait_for_debuggee(gdbctx
);
1214 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1215 return packet_reply_status(gdbctx
);
1218 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1222 /* FIXME: add support for address in packet */
1223 assert(gdbctx
->in_packet_len
== 2);
1224 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1225 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1226 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1227 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1228 hex_from(&sig
, gdbctx
->in_packet
, 1);
1229 /* cannot change signals on the fly */
1230 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1231 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1232 if (sig
!= gdbctx
->last_sig
)
1233 return packet_error
;
1234 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1235 wait_for_debuggee(gdbctx
);
1236 return packet_reply_status(gdbctx
);
1239 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1241 detach_debuggee(gdbctx
, FALSE
);
1242 return packet_ok
| packet_last_f
;
1245 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1249 CONTEXT
* pctx
= &gdbctx
->context
;
1251 assert(gdbctx
->in_trap
);
1253 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1255 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1256 return packet_error
;
1259 packet_reply_open(gdbctx
);
1260 for (i
= 0; i
< cpu_num_regs
; i
++)
1262 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, i
), 4);
1264 packet_reply_close(gdbctx
);
1268 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1272 CONTEXT
* pctx
= &gdbctx
->context
;
1274 assert(gdbctx
->in_trap
);
1275 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1277 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1278 return packet_error
;
1280 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1282 for (i
= 0; i
< cpu_num_regs
; i
++)
1283 hex_from(cpu_register(pctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
1284 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1286 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1287 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1288 return packet_error
;
1293 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1295 detach_debuggee(gdbctx
, TRUE
);
1297 if (!gdbctx
->extended
)
1298 /* dunno whether GDB cares or not */
1302 /* assume we can't really answer something here */
1303 /* return packet_done; */
1306 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1311 switch (gdbctx
->in_packet
[0])
1315 if (gdbctx
->in_packet
[1] == '-')
1316 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1318 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1319 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1321 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1322 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1323 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1324 gdbctx
->in_packet
+ 1);
1325 return packet_error
;
1327 if (gdbctx
->in_packet
[0] == 'c')
1328 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1330 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1333 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1334 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1335 return packet_error
;
1339 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1342 unsigned int len
, blk_len
, nread
;
1346 assert(gdbctx
->in_trap
);
1347 /* FIXME:check in_packet_len for reading %p,%x */
1348 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1349 if (len
<= 0) return packet_error
;
1350 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1351 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1352 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1354 blk_len
= min(sizeof(buffer
), len
- nread
);
1355 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1358 /* fail at first address, return error */
1359 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1360 /* something has already been read, return partial information */
1363 if (nread
== 0) packet_reply_open(gdbctx
);
1364 packet_reply_hex_to(gdbctx
, buffer
, r
);
1366 packet_reply_close(gdbctx
);
1370 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1373 unsigned int len
, blk_len
;
1378 assert(gdbctx
->in_trap
);
1379 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1382 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1383 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1384 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1385 return packet_error
;
1389 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1391 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1392 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1393 return packet_error
;
1395 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1397 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1398 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1399 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1400 return packet_error
;
1402 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1403 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1406 blk_len
= min(sizeof(buffer
), len
);
1407 hex_from(buffer
, ptr
, blk_len
);
1408 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1415 return packet_ok
; /* FIXME: error while writing ? */
1418 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1422 CONTEXT
* pctx
= &gdbctx
->context
;
1424 assert(gdbctx
->in_trap
);
1425 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1426 if (reg
>= cpu_num_regs
)
1428 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1429 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1430 return packet_error
;
1432 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1434 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1435 return packet_error
;
1437 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1438 fprintf(stderr
, "Read register %x => %lx\n", reg
, *cpu_register(pctx
, reg
));
1439 packet_reply_open(gdbctx
);
1440 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, reg
), 4);
1441 packet_reply_close(gdbctx
);
1445 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1451 CONTEXT
* pctx
= &gdbctx
->context
;
1453 assert(gdbctx
->in_trap
);
1455 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1457 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1458 if (end
== NULL
|| reg
> cpu_num_regs
)
1460 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1461 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1462 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1463 * it wouldn't matter too much, and it fakes our support for all regs
1465 return (end
== NULL
) ? packet_error
: packet_ok
;
1467 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1469 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1470 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1471 (int)(ptr
+ 8 - gdbctx
->in_packet
), gdbctx
->in_packet_len
);
1472 return packet_error
;
1474 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1476 int len
= gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
);
1477 fprintf(stderr
, "Writing reg %u <= %*.*s\n", reg
, len
, len
, ptr
);
1480 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1482 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1483 return packet_error
;
1486 hex_from(cpu_register(pctx
, reg
), ptr
, 4);
1487 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1489 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1490 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1491 return packet_error
;
1497 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1505 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1506 strcpy(clsName
, "-- Unknown --");
1507 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1508 strcpy(wndName
, "-- Empty --");
1510 packet_reply_open(gdbctx
);
1511 packet_reply_catc(gdbctx
, 'O');
1512 snprintf(buffer
, sizeof(buffer
),
1513 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1514 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1515 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1516 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1518 packet_reply_hex_to_str(gdbctx
, buffer
);
1519 packet_reply_close(gdbctx
);
1521 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1522 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1523 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1526 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1530 /* we do the output in several 'O' packets, with the last one being just OK for
1531 * marking the end of the output */
1532 packet_reply_open(gdbctx
);
1533 packet_reply_catc(gdbctx
, 'O');
1534 snprintf(buffer
, sizeof(buffer
),
1535 "%-16.16s %-17.17s %-8.8s %s\n",
1536 "hwnd", "Class Name", " Style", " WndProc Text");
1537 packet_reply_hex_to_str(gdbctx
, buffer
);
1538 packet_reply_close(gdbctx
);
1540 /* FIXME: could also add a pmt to this command in str... */
1541 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1542 packet_reply(gdbctx
, "OK", 2);
1545 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1547 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1550 PROCESSENTRY32 entry
;
1553 if (snap
== INVALID_HANDLE_VALUE
)
1556 entry
.dwSize
= sizeof(entry
);
1557 ok
= Process32First(snap
, &entry
);
1559 /* we do the output in several 'O' packets, with the last one being just OK for
1560 * marking the end of the output */
1562 packet_reply_open(gdbctx
);
1563 packet_reply_catc(gdbctx
, 'O');
1564 snprintf(buffer
, sizeof(buffer
),
1565 " %-8.8s %-8.8s %-8.8s %s\n",
1566 "pid", "threads", "parent", "executable");
1567 packet_reply_hex_to_str(gdbctx
, buffer
);
1568 packet_reply_close(gdbctx
);
1573 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1574 packet_reply_open(gdbctx
);
1575 packet_reply_catc(gdbctx
, 'O');
1576 snprintf(buffer
, sizeof(buffer
),
1577 "%c%08x %-8d %08x '%s'\n",
1578 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1579 entry
.th32ParentProcessID
, entry
.szExeFile
);
1580 packet_reply_hex_to_str(gdbctx
, buffer
);
1581 packet_reply_close(gdbctx
);
1582 ok
= Process32Next(snap
, &entry
);
1585 packet_reply(gdbctx
, "OK", 2);
1588 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1590 MEMORY_BASIC_INFORMATION mbi
;
1597 /* we do the output in several 'O' packets, with the last one being just OK for
1598 * marking the end of the output */
1599 packet_reply_open(gdbctx
);
1600 packet_reply_catc(gdbctx
, 'O');
1601 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1602 packet_reply_close(gdbctx
);
1604 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1608 case MEM_COMMIT
: state
= "commit "; break;
1609 case MEM_FREE
: state
= "free "; break;
1610 case MEM_RESERVE
: state
= "reserve"; break;
1611 default: state
= "??? "; break;
1613 if (mbi
.State
!= MEM_FREE
)
1617 case MEM_IMAGE
: type
= "image "; break;
1618 case MEM_MAPPED
: type
= "mapped "; break;
1619 case MEM_PRIVATE
: type
= "private"; break;
1620 case 0: type
= " "; break;
1621 default: type
= "??? "; break;
1623 memset(prot
, ' ' , sizeof(prot
)-1);
1624 prot
[sizeof(prot
)-1] = '\0';
1625 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1627 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1629 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1631 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1639 packet_reply_open(gdbctx
);
1640 snprintf(buffer
, sizeof(buffer
), "%08lx %08lx %s %s %s\n",
1641 (DWORD_PTR
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1642 packet_reply_catc(gdbctx
, 'O');
1643 packet_reply_hex_to_str(gdbctx
, buffer
);
1644 packet_reply_close(gdbctx
);
1646 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1648 addr
+= mbi
.RegionSize
;
1650 packet_reply(gdbctx
, "OK", 2);
1653 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1654 int len
, const char* str
)
1660 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1662 else if (len
>= 2 && str
[0] == '=')
1664 unsigned val
= atoi(&str
[1]);
1665 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1666 gdbctx
->trace
= val
;
1670 /* FIXME: ugly but can use error packet here */
1671 packet_reply_cat(gdbctx
, "E00");
1674 packet_reply_open(gdbctx
);
1675 packet_reply_hex_to_str(gdbctx
, buffer
);
1676 packet_reply_close(gdbctx
);
1684 void (*handler
)(struct gdb_context
*, int, const char*);
1687 {0, "wnd", 3, packet_query_monitor_wnd
},
1688 {0, "window", 6, packet_query_monitor_wnd
},
1689 {0, "proc", 4, packet_query_monitor_process
},
1690 {0, "process", 7, packet_query_monitor_process
},
1691 {0, "mem", 3, packet_query_monitor_mem
},
1692 {1, "trace", 5, packet_query_monitor_trace
},
1696 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1697 const char* hxcmd
, size_t len
)
1700 struct query_detail
* qd
;
1702 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1704 hex_from(buffer
, hxcmd
, len
);
1706 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1708 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1709 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1711 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1714 return packet_reply_error(gdbctx
, EINVAL
);
1717 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1719 switch (gdbctx
->in_packet
[0])
1722 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1724 struct dbg_thread
* thd
;
1726 packet_reply_open(gdbctx
);
1727 packet_reply_add(gdbctx
, "m", 1);
1728 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1730 packet_reply_val(gdbctx
, thd
->tid
, 4);
1731 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1732 packet_reply_add(gdbctx
, ",", 1);
1734 packet_reply_close(gdbctx
);
1737 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1741 packet_reply_open(gdbctx
);
1742 packet_reply_catc(gdbctx
, 'O');
1743 get_process_info(gdbctx
, result
, sizeof(result
));
1744 packet_reply_hex_to_str(gdbctx
, result
);
1745 packet_reply_close(gdbctx
);
1750 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1752 packet_reply(gdbctx
, "l", 1);
1755 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1757 packet_reply(gdbctx
, "l", 1);
1762 if (gdbctx
->in_packet_len
== 1)
1764 struct dbg_thread
* thd
;
1765 /* FIXME: doc says 16 bit val ??? */
1766 /* grab first created thread, aka last in list */
1767 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
1768 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
1769 packet_reply_open(gdbctx
);
1770 packet_reply_add(gdbctx
, "QC", 2);
1771 packet_reply_val(gdbctx
, thd
->tid
, 4);
1772 packet_reply_close(gdbctx
);
1777 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1781 snprintf(buf
, sizeof(buf
),
1782 "Text=%08lx;Data=%08lx;Bss=%08lx",
1783 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1784 gdbctx
->wine_segs
[2]);
1785 return packet_reply(gdbctx
, buf
, -1);
1789 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1791 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1792 gdbctx
->in_packet_len
- 5);
1796 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1798 if (strncmp(gdbctx
->in_packet
, "Supported", gdbctx
->in_packet_len
) == 0)
1800 packet_reply_open(gdbctx
);
1801 packet_reply_close(gdbctx
);
1806 if (gdbctx
->in_packet_len
> 15 &&
1807 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1808 gdbctx
->in_packet
[15] == ',')
1814 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1815 if (end
== NULL
) break;
1816 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1817 packet_reply_open(gdbctx
);
1818 packet_reply_hex_to_str(gdbctx
, result
);
1819 packet_reply_close(gdbctx
);
1824 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1825 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1826 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1827 return packet_error
;
1830 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1832 /* FIXME: add support for address in packet */
1833 assert(gdbctx
->in_packet_len
== 0);
1834 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1835 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1836 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
1837 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1838 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1839 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1840 wait_for_debuggee(gdbctx
);
1841 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1842 return packet_reply_status(gdbctx
);
1846 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1850 /* FIXME: add support for address in packet */
1851 assert(gdbctx
->in_packet_len
== 2);
1852 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1853 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1854 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1855 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1856 hex_from(&sig
, gdbctx
->in_packet
, 1);
1857 /* cannot change signals on the fly */
1858 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1859 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1860 if (sig
!= gdbctx
->last_sig
)
1861 return packet_error
;
1862 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1863 wait_for_debuggee(gdbctx
);
1864 return packet_reply_status(gdbctx
);
1868 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1873 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1874 if (tid
== -1 || tid
== 0)
1875 return packet_reply_error(gdbctx
, EINVAL
);
1876 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1878 return packet_reply_error(gdbctx
, ESRCH
);
1881 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1885 struct gdb_ctx_Xpoint
* xpt
;
1886 enum be_xpoint_type t
;
1888 /* FIXME: check packet_len */
1889 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1890 gdbctx
->in_packet
[1] != ',' ||
1891 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1892 return packet_error
;
1893 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1894 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1895 addr
, len
, gdbctx
->in_packet
[0]);
1896 switch (gdbctx
->in_packet
[0])
1898 case '0': t
= be_xpoint_break
; len
= 0; break;
1899 case '1': t
= be_xpoint_watch_exec
; break;
1900 case '2': t
= be_xpoint_watch_read
; break;
1901 case '3': t
= be_xpoint_watch_write
; break;
1902 default: return packet_error
;
1904 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1906 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1908 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
1909 gdbctx
->process
->process_io
, &gdbctx
->context
,
1910 t
, xpt
->addr
, xpt
->val
, len
))
1918 return packet_error
;
1921 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1925 struct gdb_ctx_Xpoint
* xpt
;
1926 enum be_xpoint_type t
;
1928 /* FIXME: check packet_len */
1929 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1930 gdbctx
->in_packet
[1] != ',' ||
1931 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1932 return packet_error
;
1933 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1934 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
1935 addr
, len
, gdbctx
->in_packet
[0]);
1936 switch (gdbctx
->in_packet
[0])
1938 case '0': t
= be_xpoint_break
; len
= 0; break;
1939 case '1': t
= be_xpoint_watch_exec
; break;
1940 case '2': t
= be_xpoint_watch_read
; break;
1941 case '3': t
= be_xpoint_watch_write
; break;
1942 default: return packet_error
;
1944 /* because of packet command handling, this should be made idempotent */
1945 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1947 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1948 return packet_ok
; /* nothing to do */
1950 /* really set the Xpoint */
1951 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1953 if (xpt
->type
== -1)
1955 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
1956 gdbctx
->process
->process_io
, &gdbctx
->context
,
1957 t
, addr
, &xpt
->val
, len
))
1963 fprintf(stderr
, "cannot set xpoint\n");
1967 /* no more entries... eech */
1968 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
1969 return packet_error
;
1972 /* =============================================== *
1973 * P A C K E T I N F R A S T R U C T U R E *
1974 * =============================================== *
1980 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1983 static struct packet_entry packet_entries
[] =
1985 /*{'!', packet_extended}, */
1986 {'?', packet_last_signal
},
1987 {'c', packet_continue
},
1988 {'C', packet_continue_signal
},
1989 {'D', packet_detach
},
1990 {'g', packet_read_registers
},
1991 {'G', packet_write_registers
},
1993 {'H', packet_thread
},
1994 {'m', packet_read_memory
},
1995 {'M', packet_write_memory
},
1996 {'p', packet_read_register
},
1997 {'P', packet_write_register
},
1998 {'q', packet_query
},
1999 /* {'Q', packet_set}, */
2000 /* {'R', packet,restart}, only in extended mode ! */
2002 /*{'S', packet_step_signal}, hard(er) to implement */
2003 {'T', packet_thread_alive
},
2004 {'v', packet_verbose
},
2005 {'z', packet_remove_breakpoint
},
2006 {'Z', packet_set_breakpoint
},
2009 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2013 unsigned char in_cksum
, loc_cksum
;
2015 enum packet_return ret
= packet_error
;
2018 while ((ret
& packet_last_f
) == 0)
2020 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2021 fprintf(stderr
, "In-buf: %*.*s\n",
2022 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2023 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2024 if (ptr
== NULL
) return FALSE
;
2025 if (ptr
!= gdbctx
->in_buf
)
2027 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2028 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2029 fprintf(stderr
, "Removing garbage: %*.*s\n",
2030 glen
, glen
, gdbctx
->in_buf
);
2031 gdbctx
->in_len
-= glen
;
2032 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2034 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2035 if (end
== NULL
) return FALSE
;
2036 /* no checksum yet */
2037 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2038 plen
= end
- gdbctx
->in_buf
- 1;
2039 hex_from(&in_cksum
, end
+ 1, 1);
2040 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2041 if (loc_cksum
== in_cksum
)
2043 if (num_packet
== 0) {
2048 write(gdbctx
->sock
, "+", 1);
2051 /* FIXME: should use bsearch if packet_entries was sorted */
2052 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2054 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2056 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2058 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2059 fprintf(stderr
, "Unknown packet request %*.*s\n",
2060 plen
, plen
, &gdbctx
->in_buf
[1]);
2064 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2065 gdbctx
->in_packet_len
= plen
- 1;
2066 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2067 fprintf(stderr
, "Packet: %c%*.*s\n",
2069 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2071 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2073 switch (ret
& ~packet_last_f
)
2075 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2076 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2077 case packet_done
: break;
2079 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2080 fprintf(stderr
, "Reply-full: %*.*s\n",
2081 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2082 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2083 assert(i
== gdbctx
->out_len
);
2084 /* if this fails, we'll have to use POLLOUT...
2086 gdbctx
->out_len
= 0;
2091 /* FIXME: if we have in our input buffer more than one packet,
2092 * it's very likely that we took too long to answer to a given packet
2093 * and gdb is sending us again the same packet
2094 * We simply drop the second packet. This will lower the risk of error,
2095 * but there's still some race conditions here
2096 * A better fix (yet not perfect) would be to have two threads:
2097 * - one managing the packets for gdb
2098 * - the second one managing the commands...
2099 * This would allow us also the reply with the '+' character (Ack of
2100 * the command) way sooner than what we do now
2102 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2103 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2108 write(gdbctx
->sock
, "+", 1);
2109 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2110 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2112 gdbctx
->in_len
-= plen
+ 4;
2113 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2118 static int fetch_data(struct gdb_context
* gdbctx
)
2120 int len
, in_len
= gdbctx
->in_len
;
2122 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2126 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2127 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2129 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2130 fprintf(stderr
, "%d %d %*.*s\n",
2131 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2132 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2133 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2134 if (len
<= 0) break;
2135 gdbctx
->in_len
+= len
;
2136 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2137 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2139 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2140 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2141 return gdbctx
->in_len
- in_len
;
2144 #define FLAG_NO_START 1
2145 #define FLAG_WITH_XTERM 2
2147 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2151 const char* gdb_path
;
2154 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2155 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2156 fd
= mkstemps(buf
, 0);
2157 if (fd
== -1) return FALSE
;
2158 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2159 fprintf(f
, "file %s\n", wine_path
);
2160 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2161 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2162 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2163 /* gdb 5.1 seems to require it, won't hurt anyway */
2164 fprintf(f
, "sharedlibrary\n");
2165 /* This is needed (but not a decent & final fix)
2166 * Without this, gdb would skip our inter-DLL relay code (because
2167 * we don't have any line number information for the relay code)
2168 * With this, we will stop on first instruction of the stub, and
2169 * reusing step, will get us through the relay stub at the actual
2170 * function we're looking at.
2172 fprintf(f
, "set step-mode on\n");
2173 /* tell gdb to delete this file when done handling it... */
2174 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2176 if (flags
& FLAG_WITH_XTERM
)
2177 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2179 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2180 assert(0); /* never reached */
2184 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2187 struct sockaddr_in s_addrs
;
2188 unsigned int s_len
= sizeof(s_addrs
);
2189 struct pollfd pollfd
;
2190 IMAGEHLP_MODULE64 imh_mod
;
2192 /* step 1: create socket for gdb connection request */
2193 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2195 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2196 fprintf(stderr
, "Can't create socket");
2200 if (listen(sock
, 1) == -1 ||
2201 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2204 /* step 2: do the process internal creation */
2205 handle_debug_event(gdbctx
, de
);
2207 /* step3: get the wine loader name */
2208 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
)) return FALSE
;
2210 /* step 4: fire up gdb (if requested) */
2211 if (flags
& FLAG_NO_START
)
2212 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2216 case -1: /* error in parent... */
2217 fprintf(stderr
, "Cannot create gdb\n");
2219 default: /* in parent... success */
2221 case 0: /* in child... and alive */
2222 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2223 /* if we're here, exec failed, so report failure */
2227 /* step 5: wait for gdb to connect actually */
2229 pollfd
.events
= POLLIN
;
2232 switch (poll(&pollfd
, 1, -1))
2235 if (pollfd
.revents
& POLLIN
)
2238 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2239 if (gdbctx
->sock
== -1)
2241 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2242 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2243 /* don't keep our small packets too long: send them ASAP back to GDB
2244 * without this, GDB really crawls
2246 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2250 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2251 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2254 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2255 fprintf(stderr
, "Poll for cnx failed (error)\n");
2265 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2271 gdbctx
->in_buf
= NULL
;
2272 gdbctx
->in_buf_alloc
= 0;
2274 gdbctx
->out_buf
= NULL
;
2275 gdbctx
->out_buf_alloc
= 0;
2276 gdbctx
->out_len
= 0;
2277 gdbctx
->out_curr_packet
= -1;
2279 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2280 gdbctx
->last_sig
= 0;
2281 gdbctx
->in_trap
= FALSE
;
2282 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2283 gdbctx
->process
= NULL
;
2284 for (i
= 0; i
< NUM_XPOINT
; i
++)
2285 gdbctx
->Xpoints
[i
].type
= -1;
2286 for (i
= 0; i
< sizeof(gdbctx
->wine_segs
) / sizeof(gdbctx
->wine_segs
[0]); i
++)
2287 gdbctx
->wine_segs
[i
] = 0;
2289 /* wait for first trap */
2290 while (WaitForDebugEvent(&de
, INFINITE
))
2292 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2294 /* this should be the first event we get,
2295 * and the only one of this type */
2296 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2297 /* gdbctx->dwProcessId = pid; */
2298 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2299 assert(!gdbctx
->in_trap
);
2303 handle_debug_event(gdbctx
, &de
);
2304 if (gdbctx
->in_trap
) break;
2306 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2311 static int gdb_remote(unsigned flags
)
2313 struct pollfd pollfd
;
2314 struct gdb_context gdbctx
;
2317 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2319 pollfd
.fd
= gdbctx
.sock
;
2320 pollfd
.events
= POLLIN
;
2323 switch (poll(&pollfd
, 1, -1))
2327 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2329 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2330 fprintf(stderr
, "Gdb hung up\n");
2331 /* kill also debuggee process - questionnable - */
2332 detach_debuggee(&gdbctx
, TRUE
);
2336 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2338 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2342 /* timeout, should never happen (infinite timeout) */
2345 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2346 fprintf(stderr
, "Poll failed\n");
2356 int gdb_main(int argc
, char* argv
[])
2359 unsigned gdb_flags
= 0;
2362 while (argc
> 0 && argv
[0][0] == '-')
2364 if (strcmp(argv
[0], "--no-start") == 0)
2366 gdb_flags
|= FLAG_NO_START
;
2370 if (strcmp(argv
[0], "--with-xterm") == 0)
2372 gdb_flags
|= FLAG_WITH_XTERM
;
2378 if (dbg_active_attach(argc
, argv
) == start_ok
||
2379 dbg_active_launch(argc
, argv
) == start_ok
)
2380 return gdb_remote(gdb_flags
);
2382 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");