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
),
394 #elif defined(__sparc__)
395 static size_t cpu_register_map
[] = {
396 FIELD_OFFSET(CONTEXT
, g0
),
397 FIELD_OFFSET(CONTEXT
, g1
),
398 FIELD_OFFSET(CONTEXT
, g2
),
399 FIELD_OFFSET(CONTEXT
, g3
),
400 FIELD_OFFSET(CONTEXT
, g4
),
401 FIELD_OFFSET(CONTEXT
, g5
),
402 FIELD_OFFSET(CONTEXT
, g6
),
403 FIELD_OFFSET(CONTEXT
, g7
),
404 FIELD_OFFSET(CONTEXT
, o0
),
405 FIELD_OFFSET(CONTEXT
, o1
),
406 FIELD_OFFSET(CONTEXT
, o2
),
407 FIELD_OFFSET(CONTEXT
, o3
),
408 FIELD_OFFSET(CONTEXT
, o4
),
409 FIELD_OFFSET(CONTEXT
, o5
),
410 FIELD_OFFSET(CONTEXT
, o6
),
411 FIELD_OFFSET(CONTEXT
, o7
),
412 FIELD_OFFSET(CONTEXT
, l0
),
413 FIELD_OFFSET(CONTEXT
, l1
),
414 FIELD_OFFSET(CONTEXT
, l2
),
415 FIELD_OFFSET(CONTEXT
, l3
),
416 FIELD_OFFSET(CONTEXT
, l4
),
417 FIELD_OFFSET(CONTEXT
, l5
),
418 FIELD_OFFSET(CONTEXT
, l6
),
419 FIELD_OFFSET(CONTEXT
, l7
),
420 FIELD_OFFSET(CONTEXT
, i0
),
421 FIELD_OFFSET(CONTEXT
, i1
),
422 FIELD_OFFSET(CONTEXT
, i2
),
423 FIELD_OFFSET(CONTEXT
, i3
),
424 FIELD_OFFSET(CONTEXT
, i4
),
425 FIELD_OFFSET(CONTEXT
, i5
),
426 FIELD_OFFSET(CONTEXT
, i6
),
427 FIELD_OFFSET(CONTEXT
, i7
),
430 # error Define the registers map for your CPU
433 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
435 static inline unsigned long* cpu_register(CONTEXT
* ctx
, unsigned idx
)
437 assert(idx
< cpu_num_regs
);
438 return (unsigned long*)((char*)ctx
+ cpu_register_map
[idx
]);
441 /* =============================================== *
442 * W I N 3 2 D E B U G I N T E R F A C E *
443 * =============================================== *
446 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
448 ctx
->ContextFlags
= CONTEXT_CONTROL
450 #ifdef CONTEXT_SEGMENTS
453 #ifdef CONTEXT_DEBUG_REGISTERS
454 | CONTEXT_DEBUG_REGISTERS
457 if (!GetThreadContext(h
, ctx
))
459 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
460 fprintf(stderr
, "Can't get thread's context\n");
466 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
468 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
471 switch (rec
->ExceptionCode
)
473 case EXCEPTION_ACCESS_VIOLATION
:
474 case EXCEPTION_PRIV_INSTRUCTION
:
475 case EXCEPTION_STACK_OVERFLOW
:
476 case EXCEPTION_GUARD_PAGE
:
477 gdbctx
->last_sig
= SIGSEGV
;
480 case EXCEPTION_DATATYPE_MISALIGNMENT
:
481 gdbctx
->last_sig
= SIGBUS
;
484 case EXCEPTION_SINGLE_STEP
:
486 case EXCEPTION_BREAKPOINT
:
487 gdbctx
->last_sig
= SIGTRAP
;
490 case EXCEPTION_FLT_DENORMAL_OPERAND
:
491 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
492 case EXCEPTION_FLT_INEXACT_RESULT
:
493 case EXCEPTION_FLT_INVALID_OPERATION
:
494 case EXCEPTION_FLT_OVERFLOW
:
495 case EXCEPTION_FLT_STACK_CHECK
:
496 case EXCEPTION_FLT_UNDERFLOW
:
497 gdbctx
->last_sig
= SIGFPE
;
500 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
501 case EXCEPTION_INT_OVERFLOW
:
502 gdbctx
->last_sig
= SIGFPE
;
505 case EXCEPTION_ILLEGAL_INSTRUCTION
:
506 gdbctx
->last_sig
= SIGILL
;
510 gdbctx
->last_sig
= SIGINT
;
513 case STATUS_POSSIBLE_DEADLOCK
:
514 gdbctx
->last_sig
= SIGALRM
;
516 /* FIXME: we could also add here a O packet with additional information */
519 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
520 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
521 gdbctx
->last_sig
= SIGABRT
;
528 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
535 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
537 switch (de
->dwDebugEventCode
)
539 case CREATE_PROCESS_DEBUG_EVENT
:
540 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
541 de
->u
.CreateProcessInfo
.hProcess
);
542 if (!gdbctx
->process
) break;
543 memory_get_string_indirect(gdbctx
->process
,
544 de
->u
.CreateProcessInfo
.lpImageName
,
545 de
->u
.CreateProcessInfo
.fUnicode
,
546 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
547 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
549 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
550 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
551 de
->dwProcessId
, de
->dwThreadId
,
552 dbg_W2A(u
.buffer
, -1),
553 de
->u
.CreateProcessInfo
.lpImageName
,
554 de
->u
.CreateProcessInfo
.lpStartAddress
,
555 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
556 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
558 /* de->u.CreateProcessInfo.lpStartAddress; */
559 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
560 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
562 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
563 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
564 de
->dwProcessId
, de
->dwThreadId
,
565 de
->u
.CreateProcessInfo
.lpStartAddress
);
567 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
568 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
569 de
->u
.CreateProcessInfo
.hThread
,
570 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
573 case LOAD_DLL_DEBUG_EVENT
:
574 assert(dbg_curr_thread
);
575 memory_get_string_indirect(gdbctx
->process
,
576 de
->u
.LoadDll
.lpImageName
,
577 de
->u
.LoadDll
.fUnicode
,
578 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
579 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
580 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
581 de
->dwProcessId
, de
->dwThreadId
,
582 dbg_W2A(u
.buffer
, -1),
583 de
->u
.LoadDll
.lpBaseOfDll
,
584 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
585 de
->u
.LoadDll
.nDebugInfoSize
);
586 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
587 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
590 case UNLOAD_DLL_DEBUG_EVENT
:
591 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
592 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
593 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
594 SymUnloadModule(gdbctx
->process
->handle
,
595 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
598 case EXCEPTION_DEBUG_EVENT
:
599 assert(dbg_curr_thread
);
600 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
601 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
602 de
->dwProcessId
, de
->dwThreadId
,
603 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
605 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
607 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
611 case CREATE_THREAD_DEBUG_EVENT
:
612 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
613 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
614 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
616 dbg_add_thread(gdbctx
->process
,
618 de
->u
.CreateThread
.hThread
,
619 de
->u
.CreateThread
.lpThreadLocalBase
);
622 case EXIT_THREAD_DEBUG_EVENT
:
623 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
624 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
625 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
627 assert(dbg_curr_thread
);
628 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
629 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
630 dbg_del_thread(dbg_curr_thread
);
633 case EXIT_PROCESS_DEBUG_EVENT
:
634 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
635 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
636 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
638 dbg_del_process(gdbctx
->process
);
639 gdbctx
->process
= NULL
;
640 /* now signal gdb that we're done */
641 gdbctx
->last_sig
= SIGTERM
;
642 gdbctx
->in_trap
= TRUE
;
645 case OUTPUT_DEBUG_STRING_EVENT
:
646 assert(dbg_curr_thread
);
647 memory_get_string(gdbctx
->process
,
648 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
649 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
650 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
651 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
652 de
->dwProcessId
, de
->dwThreadId
, u
.bufferA
);
656 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
657 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
658 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
659 de
->u
.RipInfo
.dwType
);
663 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
664 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
665 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
669 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
673 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
674 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
675 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
676 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
677 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
678 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
679 dbg_curr_thread
->tid
, cont
);
681 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
682 fprintf(stderr
, "Cannot find last thread\n");
686 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
691 if(dbg_curr_thread
->tid
== threadid
){
692 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
693 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
694 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
695 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
696 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
697 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
698 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
699 dbg_curr_thread
->tid
, cont
);
702 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
703 fprintf(stderr
, "Cannot find last thread\n");
706 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
708 struct pollfd pollfd
;
712 pollfd
.fd
= gdbctx
->sock
;
713 pollfd
.events
= POLLIN
;
716 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
717 ret
= read(gdbctx
->sock
, &pkt
, 1);
719 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
720 fprintf(stderr
, "read failed\n");
725 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
726 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
731 } else if (ret
== -1) {
732 fprintf(stderr
, "poll failed\n");
737 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
741 gdbctx
->in_trap
= FALSE
;
744 if (!WaitForDebugEvent(&de
, 10))
746 if (GetLastError() == ERROR_SEM_TIMEOUT
)
748 if (check_for_interrupt(gdbctx
)) {
749 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
750 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
751 fprintf(stderr
, "Failed to break into debugee\n");
755 WaitForDebugEvent(&de
, INFINITE
);
763 handle_debug_event(gdbctx
, &de
);
764 assert(!gdbctx
->process
||
765 gdbctx
->process
->pid
== 0 ||
766 de
.dwProcessId
== gdbctx
->process
->pid
);
767 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
768 if (gdbctx
->in_trap
) break;
769 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
773 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
775 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
776 resume_debuggee(gdbctx
, DBG_CONTINUE
);
778 DebugActiveProcessStop(gdbctx
->process
->pid
);
779 dbg_del_process(gdbctx
->process
);
780 gdbctx
->process
= NULL
;
783 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
787 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
789 strcpy(buffer
, "Unknown process");
792 if (status
== STILL_ACTIVE
)
794 strcpy(buffer
, "Running");
797 snprintf(buffer
, len
, "Terminated (%u)", status
);
799 switch (GetPriorityClass(gdbctx
->process
->handle
))
802 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
803 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
805 #ifdef BELOW_NORMAL_PRIORITY_CLASS
806 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
808 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
809 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
810 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
811 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
813 strcat(buffer
, "\n");
816 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
817 char* buffer
, size_t len
)
819 struct dbg_thread
* thd
;
823 /* FIXME: use the size of buffer */
824 thd
= dbg_get_thread(gdbctx
->process
, tid
);
827 strcpy(buffer
, "No information");
830 if (GetExitCodeThread(thd
->handle
, &status
))
832 if (status
== STILL_ACTIVE
)
834 /* FIXME: this is a bit brutal... some nicer way shall be found */
835 switch (status
= SuspendThread(thd
->handle
))
838 case 0: strcpy(buffer
, "Running"); break;
839 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
841 ResumeThread(thd
->handle
);
844 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
848 strcpy(buffer
, "Unknown threadID");
850 switch (prio
= GetThreadPriority(thd
->handle
))
852 case THREAD_PRIORITY_ERROR_RETURN
: break;
853 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
854 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
855 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
856 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
857 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
858 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
859 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
860 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
862 assert(strlen(buffer
) < len
);
865 /* =============================================== *
866 * P A C K E T U T I L S *
867 * =============================================== *
870 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
871 packet_last_f
= 0x80};
873 static char* packet_realloc(char* buf
, int size
)
876 return HeapAlloc(GetProcessHeap(), 0, size
);
877 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
881 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
883 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
885 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
886 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
890 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
892 packet_reply_grow(gdbctx
, len
* 2);
893 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
894 gdbctx
->out_len
+= len
* 2;
897 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
899 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
902 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
906 shift
= (len
- 1) * 8;
907 packet_reply_grow(gdbctx
, len
* 2);
908 for (i
= 0; i
< len
; i
++, shift
-= 8)
910 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
911 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
915 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
917 packet_reply_grow(gdbctx
, len
);
918 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
919 gdbctx
->out_len
+= len
;
922 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
924 packet_reply_add(gdbctx
, str
, strlen(str
));
927 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
929 packet_reply_add(gdbctx
, &ch
, 1);
932 static void packet_reply_open(struct gdb_context
* gdbctx
)
934 assert(gdbctx
->out_curr_packet
== -1);
935 packet_reply_catc(gdbctx
, '$');
936 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
939 static void packet_reply_close(struct gdb_context
* gdbctx
)
944 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
945 packet_reply_catc(gdbctx
, '#');
946 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
947 packet_reply_hex_to(gdbctx
, &cksum
, 1);
948 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
949 fprintf(stderr
, "Reply : %*.*s\n",
950 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
951 gdbctx
->out_curr_packet
= -1;
954 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
956 packet_reply_open(gdbctx
);
958 if (len
== -1) len
= strlen(packet
);
959 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
961 packet_reply_add(gdbctx
, packet
, len
);
963 packet_reply_close(gdbctx
);
968 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
970 packet_reply_open(gdbctx
);
972 packet_reply_add(gdbctx
, "E", 1);
973 packet_reply_val(gdbctx
, error
, 1);
975 packet_reply_close(gdbctx
);
980 /* =============================================== *
981 * P A C K E T H A N D L E R S *
982 * =============================================== *
985 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
987 enum packet_return ret
= packet_done
;
989 packet_reply_open(gdbctx
);
991 if (gdbctx
->process
!= NULL
)
996 packet_reply_catc(gdbctx
, 'T');
997 sig
= gdbctx
->last_sig
;
998 packet_reply_val(gdbctx
, sig
, 1);
999 packet_reply_add(gdbctx
, "thread:", 7);
1000 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
1001 packet_reply_catc(gdbctx
, ';');
1003 for (i
= 0; i
< cpu_num_regs
; i
++)
1005 /* FIXME: this call will also grow the buffer...
1006 * unneeded, but not harmful
1008 packet_reply_val(gdbctx
, i
, 1);
1009 packet_reply_catc(gdbctx
, ':');
1010 packet_reply_hex_to(gdbctx
, cpu_register(&gdbctx
->context
, i
), 4);
1011 packet_reply_catc(gdbctx
, ';');
1016 /* Try to put an exit code
1017 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1018 * just indicate the end of process and exit */
1019 packet_reply_add(gdbctx
, "W00", 3);
1020 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
1023 packet_reply_close(gdbctx
);
1029 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
1031 gdbctx
->extended
= 1;
1036 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
1038 assert(gdbctx
->in_packet_len
== 0);
1039 return packet_reply_status(gdbctx
);
1042 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
1044 /* FIXME: add support for address in packet */
1045 assert(gdbctx
->in_packet_len
== 0);
1046 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1047 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1048 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1049 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1050 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1051 wait_for_debuggee(gdbctx
);
1052 return packet_reply_status(gdbctx
);
1055 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1058 int defaultAction
= -1; /* magic non action */
1061 int actionIndex
[20]; /* allow for up to 20 actions */
1062 int threadIndex
[20];
1063 int threadCount
= 0;
1064 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1065 unsigned int threadID
= 0;
1066 struct dbg_thread
* thd
;
1069 assert(gdbctx
->in_packet_len
>= 4);
1071 /* OK we have vCont followed by..
1073 * c for packet_continue
1074 * Csig for packet_continue_signal
1076 * Ssig for step signal
1077 * and then an optional thread ID at the end..
1078 * *******************************************/
1080 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1081 fprintf(stderr
, "trying to process a verbose packet\n");
1082 /* now check that we've got Cont */
1083 assert(strncmp(gdbctx
->in_packet
, "Cont", 4) == 0);
1086 if (gdbctx
->in_packet
[4] == '?')
1091 The vCont packet is supported. Each action is a supported command in the vCont packet.
1093 The vCont packet is not supported. (this didn't seem to be obeyed!)
1095 packet_reply_open(gdbctx
);
1096 packet_reply_add(gdbctx
, "vCont", 5);
1097 /* add all the supported actions to the reply (all of them for now) */
1098 packet_reply_add(gdbctx
, ";c", 2);
1099 packet_reply_add(gdbctx
, ";C", 2);
1100 packet_reply_add(gdbctx
, ";s", 2);
1101 packet_reply_add(gdbctx
, ";S", 2);
1102 packet_reply_close(gdbctx
);
1106 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1107 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1108 now if only gdb talked XML.... */
1109 #if 0 /* handy for debugging */
1110 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1113 /* go through the packet and identify where all the actions start at */
1114 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1116 if (gdbctx
->in_packet
[i
] == ';')
1118 threadIndex
[actions
] = 0;
1119 actionIndex
[actions
++] = i
;
1121 else if (gdbctx
->in_packet
[i
] == ':')
1123 threadIndex
[actions
- 1] = i
;
1127 /* now look up the default action */
1128 for (i
= 0 ; i
< actions
; i
++)
1130 if (threadIndex
[i
] == 0)
1132 if (defaultAction
!= -1)
1134 fprintf(stderr
,"Too many default actions specified\n");
1135 return packet_error
;
1141 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1143 /* go through all the threads and stick their ids in the to be done list. */
1144 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1146 threadIDs
[threadCount
++] = thd
->tid
;
1147 /* check to see if we have more threads than I counted on, and tell the user what to do
1148 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1149 if (threadCount
== 100)
1151 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1156 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1157 * that remains is to apply the actions to the threads and the default action to any threads
1159 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1160 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1161 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1162 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1164 /* deal with the threaded stuff first */
1165 for (i
= 0; i
< actions
; i
++)
1167 if (threadIndex
[i
] != 0)
1169 int j
, idLength
= 0;
1170 if (i
< actions
- 1)
1172 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1176 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1179 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1180 /* process the action */
1181 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1183 case 's': /* step */
1184 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1186 case 'c': /* continue */
1187 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1189 case 'S': /* step Sig, */
1190 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1192 case 'C': /* continue sig */
1193 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1194 /* cannot change signals on the fly */
1195 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1196 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1197 if (sig
!= gdbctx
->last_sig
)
1198 return packet_error
;
1199 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1202 for (j
= 0 ; j
< threadCount
; j
++)
1204 if (threadIDs
[j
] == threadID
)
1211 } /* for i=0 ; i< actions */
1213 /* now we have manage the default action */
1214 if (defaultAction
>= 0)
1216 for (i
= 0 ; i
< threadCount
; i
++)
1218 /* check to see if we've already done something to the thread*/
1219 if (threadIDs
[i
] != 0)
1221 /* if not apply the default action*/
1222 threadID
= threadIDs
[i
];
1223 /* process the action (yes this is almost identical to the one above!) */
1224 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1226 case 's': /* step */
1227 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1229 case 'c': /* continue */
1230 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1233 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1235 case 'C': /* continue sig */
1236 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1237 /* cannot change signals on the fly */
1238 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1239 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1240 if (sig
!= gdbctx
->last_sig
)
1241 return packet_error
;
1242 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1247 } /* if(defaultAction >=0) */
1249 wait_for_debuggee(gdbctx
);
1250 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1251 return packet_reply_status(gdbctx
);
1254 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1258 /* FIXME: add support for address in packet */
1259 assert(gdbctx
->in_packet_len
== 2);
1260 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1261 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1262 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1263 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1264 hex_from(&sig
, gdbctx
->in_packet
, 1);
1265 /* cannot change signals on the fly */
1266 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1267 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1268 if (sig
!= gdbctx
->last_sig
)
1269 return packet_error
;
1270 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1271 wait_for_debuggee(gdbctx
);
1272 return packet_reply_status(gdbctx
);
1275 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1277 detach_debuggee(gdbctx
, FALSE
);
1278 return packet_ok
| packet_last_f
;
1281 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1285 CONTEXT
* pctx
= &gdbctx
->context
;
1287 assert(gdbctx
->in_trap
);
1289 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1291 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1292 return packet_error
;
1295 packet_reply_open(gdbctx
);
1296 for (i
= 0; i
< cpu_num_regs
; i
++)
1298 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, i
), 4);
1300 packet_reply_close(gdbctx
);
1304 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1308 CONTEXT
* pctx
= &gdbctx
->context
;
1310 assert(gdbctx
->in_trap
);
1311 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1313 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1314 return packet_error
;
1316 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1318 for (i
= 0; i
< cpu_num_regs
; i
++)
1319 hex_from(cpu_register(pctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
1320 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1322 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1323 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1324 return packet_error
;
1329 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1331 detach_debuggee(gdbctx
, TRUE
);
1333 if (!gdbctx
->extended
)
1334 /* dunno whether GDB cares or not */
1338 /* assume we can't really answer something here */
1339 /* return packet_done; */
1342 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1347 switch (gdbctx
->in_packet
[0])
1351 if (gdbctx
->in_packet
[1] == '-')
1352 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1354 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1355 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1357 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1358 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1359 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1360 gdbctx
->in_packet
+ 1);
1361 return packet_error
;
1363 if (gdbctx
->in_packet
[0] == 'c')
1364 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1366 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1369 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1370 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1371 return packet_error
;
1375 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1378 unsigned int len
, blk_len
, nread
;
1382 assert(gdbctx
->in_trap
);
1383 /* FIXME:check in_packet_len for reading %p,%x */
1384 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1385 if (len
<= 0) return packet_error
;
1386 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1387 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1388 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1390 blk_len
= min(sizeof(buffer
), len
- nread
);
1391 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1394 /* fail at first address, return error */
1395 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1396 /* something has already been read, return partial information */
1399 if (nread
== 0) packet_reply_open(gdbctx
);
1400 packet_reply_hex_to(gdbctx
, buffer
, r
);
1402 packet_reply_close(gdbctx
);
1406 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1409 unsigned int len
, blk_len
;
1414 assert(gdbctx
->in_trap
);
1415 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1418 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1419 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1420 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1421 return packet_error
;
1425 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1427 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1428 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1429 return packet_error
;
1431 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1433 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1434 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1435 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1436 return packet_error
;
1438 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1439 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1442 blk_len
= min(sizeof(buffer
), len
);
1443 hex_from(buffer
, ptr
, blk_len
);
1444 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1451 return packet_ok
; /* FIXME: error while writing ? */
1454 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1458 CONTEXT
* pctx
= &gdbctx
->context
;
1460 assert(gdbctx
->in_trap
);
1461 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1462 if (reg
>= cpu_num_regs
)
1464 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1465 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1466 return packet_error
;
1468 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1470 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1471 return packet_error
;
1473 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1474 fprintf(stderr
, "Read register %x => %lx\n", reg
, *cpu_register(pctx
, reg
));
1475 packet_reply_open(gdbctx
);
1476 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, reg
), 4);
1477 packet_reply_close(gdbctx
);
1481 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1487 CONTEXT
* pctx
= &gdbctx
->context
;
1489 assert(gdbctx
->in_trap
);
1491 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1493 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1494 if (end
== NULL
|| reg
> cpu_num_regs
)
1496 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1497 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1498 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1499 * it wouldn't matter too much, and it fakes our support for all regs
1501 return (end
== NULL
) ? packet_error
: packet_ok
;
1503 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1505 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1506 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1507 (int)(ptr
+ 8 - gdbctx
->in_packet
), gdbctx
->in_packet_len
);
1508 return packet_error
;
1510 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1512 int len
= gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
);
1513 fprintf(stderr
, "Writing reg %u <= %*.*s\n", reg
, len
, len
, ptr
);
1516 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1518 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1519 return packet_error
;
1522 hex_from(cpu_register(pctx
, reg
), ptr
, 4);
1523 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1525 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1526 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1527 return packet_error
;
1533 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1541 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1542 strcpy(clsName
, "-- Unknown --");
1543 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1544 strcpy(wndName
, "-- Empty --");
1546 packet_reply_open(gdbctx
);
1547 packet_reply_catc(gdbctx
, 'O');
1548 snprintf(buffer
, sizeof(buffer
),
1549 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1550 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1551 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1552 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1554 packet_reply_hex_to_str(gdbctx
, buffer
);
1555 packet_reply_close(gdbctx
);
1557 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1558 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1559 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1562 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1566 /* we do the output in several 'O' packets, with the last one being just OK for
1567 * marking the end of the output */
1568 packet_reply_open(gdbctx
);
1569 packet_reply_catc(gdbctx
, 'O');
1570 snprintf(buffer
, sizeof(buffer
),
1571 "%-16.16s %-17.17s %-8.8s %s\n",
1572 "hwnd", "Class Name", " Style", " WndProc Text");
1573 packet_reply_hex_to_str(gdbctx
, buffer
);
1574 packet_reply_close(gdbctx
);
1576 /* FIXME: could also add a pmt to this command in str... */
1577 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1578 packet_reply(gdbctx
, "OK", 2);
1581 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1583 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1586 PROCESSENTRY32 entry
;
1589 if (snap
== INVALID_HANDLE_VALUE
)
1592 entry
.dwSize
= sizeof(entry
);
1593 ok
= Process32First(snap
, &entry
);
1595 /* we do the output in several 'O' packets, with the last one being just OK for
1596 * marking the end of the output */
1598 packet_reply_open(gdbctx
);
1599 packet_reply_catc(gdbctx
, 'O');
1600 snprintf(buffer
, sizeof(buffer
),
1601 " %-8.8s %-8.8s %-8.8s %s\n",
1602 "pid", "threads", "parent", "executable");
1603 packet_reply_hex_to_str(gdbctx
, buffer
);
1604 packet_reply_close(gdbctx
);
1609 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1610 packet_reply_open(gdbctx
);
1611 packet_reply_catc(gdbctx
, 'O');
1612 snprintf(buffer
, sizeof(buffer
),
1613 "%c%08x %-8d %08x '%s'\n",
1614 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1615 entry
.th32ParentProcessID
, entry
.szExeFile
);
1616 packet_reply_hex_to_str(gdbctx
, buffer
);
1617 packet_reply_close(gdbctx
);
1618 ok
= Process32Next(snap
, &entry
);
1621 packet_reply(gdbctx
, "OK", 2);
1624 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1626 MEMORY_BASIC_INFORMATION mbi
;
1633 /* we do the output in several 'O' packets, with the last one being just OK for
1634 * marking the end of the output */
1635 packet_reply_open(gdbctx
);
1636 packet_reply_catc(gdbctx
, 'O');
1637 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1638 packet_reply_close(gdbctx
);
1640 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1644 case MEM_COMMIT
: state
= "commit "; break;
1645 case MEM_FREE
: state
= "free "; break;
1646 case MEM_RESERVE
: state
= "reserve"; break;
1647 default: state
= "??? "; break;
1649 if (mbi
.State
!= MEM_FREE
)
1653 case MEM_IMAGE
: type
= "image "; break;
1654 case MEM_MAPPED
: type
= "mapped "; break;
1655 case MEM_PRIVATE
: type
= "private"; break;
1656 case 0: type
= " "; break;
1657 default: type
= "??? "; break;
1659 memset(prot
, ' ' , sizeof(prot
)-1);
1660 prot
[sizeof(prot
)-1] = '\0';
1661 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1663 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1665 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1667 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1675 packet_reply_open(gdbctx
);
1676 snprintf(buffer
, sizeof(buffer
), "%08lx %08lx %s %s %s\n",
1677 (DWORD_PTR
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1678 packet_reply_catc(gdbctx
, 'O');
1679 packet_reply_hex_to_str(gdbctx
, buffer
);
1680 packet_reply_close(gdbctx
);
1682 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1684 addr
+= mbi
.RegionSize
;
1686 packet_reply(gdbctx
, "OK", 2);
1689 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1690 int len
, const char* str
)
1696 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1698 else if (len
>= 2 && str
[0] == '=')
1700 unsigned val
= atoi(&str
[1]);
1701 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1702 gdbctx
->trace
= val
;
1706 /* FIXME: ugly but can use error packet here */
1707 packet_reply_cat(gdbctx
, "E00");
1710 packet_reply_open(gdbctx
);
1711 packet_reply_hex_to_str(gdbctx
, buffer
);
1712 packet_reply_close(gdbctx
);
1720 void (*handler
)(struct gdb_context
*, int, const char*);
1723 {0, "wnd", 3, packet_query_monitor_wnd
},
1724 {0, "window", 6, packet_query_monitor_wnd
},
1725 {0, "proc", 4, packet_query_monitor_process
},
1726 {0, "process", 7, packet_query_monitor_process
},
1727 {0, "mem", 3, packet_query_monitor_mem
},
1728 {1, "trace", 5, packet_query_monitor_trace
},
1732 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1733 const char* hxcmd
, size_t len
)
1736 struct query_detail
* qd
;
1738 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1740 hex_from(buffer
, hxcmd
, len
);
1742 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1744 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1745 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1747 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1750 return packet_reply_error(gdbctx
, EINVAL
);
1753 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1755 switch (gdbctx
->in_packet
[0])
1758 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1760 struct dbg_thread
* thd
;
1762 packet_reply_open(gdbctx
);
1763 packet_reply_add(gdbctx
, "m", 1);
1764 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1766 packet_reply_val(gdbctx
, thd
->tid
, 4);
1767 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1768 packet_reply_add(gdbctx
, ",", 1);
1770 packet_reply_close(gdbctx
);
1773 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1777 packet_reply_open(gdbctx
);
1778 packet_reply_catc(gdbctx
, 'O');
1779 get_process_info(gdbctx
, result
, sizeof(result
));
1780 packet_reply_hex_to_str(gdbctx
, result
);
1781 packet_reply_close(gdbctx
);
1786 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1788 packet_reply(gdbctx
, "l", 1);
1791 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1793 packet_reply(gdbctx
, "l", 1);
1798 if (gdbctx
->in_packet_len
== 1)
1800 struct dbg_thread
* thd
;
1801 /* FIXME: doc says 16 bit val ??? */
1802 /* grab first created thread, aka last in list */
1803 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
1804 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
1805 packet_reply_open(gdbctx
);
1806 packet_reply_add(gdbctx
, "QC", 2);
1807 packet_reply_val(gdbctx
, thd
->tid
, 4);
1808 packet_reply_close(gdbctx
);
1813 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1817 snprintf(buf
, sizeof(buf
),
1818 "Text=%08lx;Data=%08lx;Bss=%08lx",
1819 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1820 gdbctx
->wine_segs
[2]);
1821 return packet_reply(gdbctx
, buf
, -1);
1825 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1827 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1828 gdbctx
->in_packet_len
- 5);
1832 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1834 if (strncmp(gdbctx
->in_packet
, "Supported", 9) == 0)
1836 /* no features supported */
1837 packet_reply_open(gdbctx
);
1838 packet_reply_close(gdbctx
);
1843 if (gdbctx
->in_packet_len
> 15 &&
1844 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1845 gdbctx
->in_packet
[15] == ',')
1851 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1852 if (end
== NULL
) break;
1853 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1854 packet_reply_open(gdbctx
);
1855 packet_reply_hex_to_str(gdbctx
, result
);
1856 packet_reply_close(gdbctx
);
1859 if (strncmp(gdbctx
->in_packet
, "TStatus", 7) == 0)
1861 /* Tracepoints not supported */
1862 packet_reply_open(gdbctx
);
1863 packet_reply_close(gdbctx
);
1868 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1869 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1870 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1871 return packet_error
;
1874 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1876 /* FIXME: add support for address in packet */
1877 assert(gdbctx
->in_packet_len
== 0);
1878 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1879 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1880 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
1881 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1882 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1883 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1884 wait_for_debuggee(gdbctx
);
1885 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1886 return packet_reply_status(gdbctx
);
1890 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1894 /* FIXME: add support for address in packet */
1895 assert(gdbctx
->in_packet_len
== 2);
1896 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1897 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1898 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1899 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1900 hex_from(&sig
, gdbctx
->in_packet
, 1);
1901 /* cannot change signals on the fly */
1902 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1903 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1904 if (sig
!= gdbctx
->last_sig
)
1905 return packet_error
;
1906 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1907 wait_for_debuggee(gdbctx
);
1908 return packet_reply_status(gdbctx
);
1912 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1917 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1918 if (tid
== -1 || tid
== 0)
1919 return packet_reply_error(gdbctx
, EINVAL
);
1920 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1922 return packet_reply_error(gdbctx
, ESRCH
);
1925 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1929 struct gdb_ctx_Xpoint
* xpt
;
1930 enum be_xpoint_type t
;
1932 /* FIXME: check packet_len */
1933 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1934 gdbctx
->in_packet
[1] != ',' ||
1935 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1936 return packet_error
;
1937 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1938 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1939 addr
, len
, gdbctx
->in_packet
[0]);
1940 switch (gdbctx
->in_packet
[0])
1942 case '0': t
= be_xpoint_break
; len
= 0; break;
1943 case '1': t
= be_xpoint_watch_exec
; break;
1944 case '2': t
= be_xpoint_watch_read
; break;
1945 case '3': t
= be_xpoint_watch_write
; break;
1946 default: return packet_error
;
1948 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1950 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1952 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
1953 gdbctx
->process
->process_io
, &gdbctx
->context
,
1954 t
, xpt
->addr
, xpt
->val
, len
))
1962 return packet_error
;
1965 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1969 struct gdb_ctx_Xpoint
* xpt
;
1970 enum be_xpoint_type t
;
1972 /* FIXME: check packet_len */
1973 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1974 gdbctx
->in_packet
[1] != ',' ||
1975 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1976 return packet_error
;
1977 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1978 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
1979 addr
, len
, gdbctx
->in_packet
[0]);
1980 switch (gdbctx
->in_packet
[0])
1982 case '0': t
= be_xpoint_break
; len
= 0; break;
1983 case '1': t
= be_xpoint_watch_exec
; break;
1984 case '2': t
= be_xpoint_watch_read
; break;
1985 case '3': t
= be_xpoint_watch_write
; break;
1986 default: return packet_error
;
1988 /* because of packet command handling, this should be made idempotent */
1989 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1991 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1992 return packet_ok
; /* nothing to do */
1994 /* really set the Xpoint */
1995 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1997 if (xpt
->type
== -1)
1999 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
2000 gdbctx
->process
->process_io
, &gdbctx
->context
,
2001 t
, addr
, &xpt
->val
, len
))
2007 fprintf(stderr
, "cannot set xpoint\n");
2011 /* no more entries... eech */
2012 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
2013 return packet_error
;
2016 /* =============================================== *
2017 * P A C K E T I N F R A S T R U C T U R E *
2018 * =============================================== *
2024 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
2027 static struct packet_entry packet_entries
[] =
2029 /*{'!', packet_extended}, */
2030 {'?', packet_last_signal
},
2031 {'c', packet_continue
},
2032 {'C', packet_continue_signal
},
2033 {'D', packet_detach
},
2034 {'g', packet_read_registers
},
2035 {'G', packet_write_registers
},
2037 {'H', packet_thread
},
2038 {'m', packet_read_memory
},
2039 {'M', packet_write_memory
},
2040 {'p', packet_read_register
},
2041 {'P', packet_write_register
},
2042 {'q', packet_query
},
2043 /* {'Q', packet_set}, */
2044 /* {'R', packet,restart}, only in extended mode ! */
2046 /*{'S', packet_step_signal}, hard(er) to implement */
2047 {'T', packet_thread_alive
},
2048 {'v', packet_verbose
},
2049 {'z', packet_remove_breakpoint
},
2050 {'Z', packet_set_breakpoint
},
2053 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2057 unsigned char in_cksum
, loc_cksum
;
2059 enum packet_return ret
= packet_error
;
2062 while ((ret
& packet_last_f
) == 0)
2064 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2065 fprintf(stderr
, "In-buf: %*.*s\n",
2066 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2067 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2068 if (ptr
== NULL
) return FALSE
;
2069 if (ptr
!= gdbctx
->in_buf
)
2071 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2072 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2073 fprintf(stderr
, "Removing garbage: %*.*s\n",
2074 glen
, glen
, gdbctx
->in_buf
);
2075 gdbctx
->in_len
-= glen
;
2076 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2078 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2079 if (end
== NULL
) return FALSE
;
2080 /* no checksum yet */
2081 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2082 plen
= end
- gdbctx
->in_buf
- 1;
2083 hex_from(&in_cksum
, end
+ 1, 1);
2084 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2085 if (loc_cksum
== in_cksum
)
2087 if (num_packet
== 0) {
2092 write(gdbctx
->sock
, "+", 1);
2095 /* FIXME: should use bsearch if packet_entries was sorted */
2096 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2098 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2100 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2102 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2103 fprintf(stderr
, "Unknown packet request %*.*s\n",
2104 plen
, plen
, &gdbctx
->in_buf
[1]);
2108 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2109 gdbctx
->in_packet_len
= plen
- 1;
2110 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2111 fprintf(stderr
, "Packet: %c%*.*s\n",
2113 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2115 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2117 switch (ret
& ~packet_last_f
)
2119 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2120 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2121 case packet_done
: break;
2123 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2124 fprintf(stderr
, "Reply-full: %*.*s\n",
2125 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2126 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2127 assert(i
== gdbctx
->out_len
);
2128 /* if this fails, we'll have to use POLLOUT...
2130 gdbctx
->out_len
= 0;
2135 /* FIXME: if we have in our input buffer more than one packet,
2136 * it's very likely that we took too long to answer to a given packet
2137 * and gdb is sending us again the same packet
2138 * We simply drop the second packet. This will lower the risk of error,
2139 * but there's still some race conditions here
2140 * A better fix (yet not perfect) would be to have two threads:
2141 * - one managing the packets for gdb
2142 * - the second one managing the commands...
2143 * This would allow us also the reply with the '+' character (Ack of
2144 * the command) way sooner than what we do now
2146 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2147 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2152 write(gdbctx
->sock
, "+", 1);
2153 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2154 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2156 gdbctx
->in_len
-= plen
+ 4;
2157 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2162 static int fetch_data(struct gdb_context
* gdbctx
)
2164 int len
, in_len
= gdbctx
->in_len
;
2166 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2170 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2171 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2173 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2174 fprintf(stderr
, "%d %d %*.*s\n",
2175 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2176 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2177 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2178 if (len
<= 0) break;
2179 gdbctx
->in_len
+= len
;
2180 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2181 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2183 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2184 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2185 return gdbctx
->in_len
- in_len
;
2188 #define FLAG_NO_START 1
2189 #define FLAG_WITH_XTERM 2
2191 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2195 const char* gdb_path
;
2198 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2199 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2200 fd
= mkstemps(buf
, 0);
2201 if (fd
== -1) return FALSE
;
2202 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2203 fprintf(f
, "file %s\n", wine_path
);
2204 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2205 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2206 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2207 /* gdb 5.1 seems to require it, won't hurt anyway */
2208 fprintf(f
, "sharedlibrary\n");
2209 /* This is needed (but not a decent & final fix)
2210 * Without this, gdb would skip our inter-DLL relay code (because
2211 * we don't have any line number information for the relay code)
2212 * With this, we will stop on first instruction of the stub, and
2213 * reusing step, will get us through the relay stub at the actual
2214 * function we're looking at.
2216 fprintf(f
, "set step-mode on\n");
2217 /* tell gdb to delete this file when done handling it... */
2218 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2220 if (flags
& FLAG_WITH_XTERM
)
2221 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2223 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2224 assert(0); /* never reached */
2228 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2231 struct sockaddr_in s_addrs
;
2232 unsigned int s_len
= sizeof(s_addrs
);
2233 struct pollfd pollfd
;
2234 IMAGEHLP_MODULE64 imh_mod
;
2236 /* step 1: create socket for gdb connection request */
2237 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2239 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2240 fprintf(stderr
, "Can't create socket");
2244 if (listen(sock
, 1) == -1 ||
2245 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2248 /* step 2: do the process internal creation */
2249 handle_debug_event(gdbctx
, de
);
2251 /* step3: get the wine loader name */
2252 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
)) return FALSE
;
2254 /* step 4: fire up gdb (if requested) */
2255 if (flags
& FLAG_NO_START
)
2256 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2260 case -1: /* error in parent... */
2261 fprintf(stderr
, "Cannot create gdb\n");
2263 default: /* in parent... success */
2264 signal(SIGINT
, SIG_IGN
);
2266 case 0: /* in child... and alive */
2267 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2268 /* if we're here, exec failed, so report failure */
2272 /* step 5: wait for gdb to connect actually */
2274 pollfd
.events
= POLLIN
;
2277 switch (poll(&pollfd
, 1, -1))
2280 if (pollfd
.revents
& POLLIN
)
2283 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2284 if (gdbctx
->sock
== -1)
2286 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2287 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2288 /* don't keep our small packets too long: send them ASAP back to GDB
2289 * without this, GDB really crawls
2291 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2295 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2296 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2299 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2300 fprintf(stderr
, "Poll for cnx failed (error)\n");
2310 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2316 gdbctx
->in_buf
= NULL
;
2317 gdbctx
->in_buf_alloc
= 0;
2319 gdbctx
->out_buf
= NULL
;
2320 gdbctx
->out_buf_alloc
= 0;
2321 gdbctx
->out_len
= 0;
2322 gdbctx
->out_curr_packet
= -1;
2324 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2325 gdbctx
->last_sig
= 0;
2326 gdbctx
->in_trap
= FALSE
;
2327 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2328 gdbctx
->process
= NULL
;
2329 for (i
= 0; i
< NUM_XPOINT
; i
++)
2330 gdbctx
->Xpoints
[i
].type
= -1;
2331 for (i
= 0; i
< sizeof(gdbctx
->wine_segs
) / sizeof(gdbctx
->wine_segs
[0]); i
++)
2332 gdbctx
->wine_segs
[i
] = 0;
2334 /* wait for first trap */
2335 while (WaitForDebugEvent(&de
, INFINITE
))
2337 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2339 /* this should be the first event we get,
2340 * and the only one of this type */
2341 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2342 /* gdbctx->dwProcessId = pid; */
2343 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2344 assert(!gdbctx
->in_trap
);
2348 handle_debug_event(gdbctx
, &de
);
2349 if (gdbctx
->in_trap
) break;
2351 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2356 static int gdb_remote(unsigned flags
)
2358 struct pollfd pollfd
;
2359 struct gdb_context gdbctx
;
2362 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2364 pollfd
.fd
= gdbctx
.sock
;
2365 pollfd
.events
= POLLIN
;
2368 switch (poll(&pollfd
, 1, -1))
2372 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2374 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2375 fprintf(stderr
, "Gdb hung up\n");
2376 /* kill also debuggee process - questionnable - */
2377 detach_debuggee(&gdbctx
, TRUE
);
2381 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2383 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2387 /* timeout, should never happen (infinite timeout) */
2390 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2391 fprintf(stderr
, "Poll failed\n");
2401 int gdb_main(int argc
, char* argv
[])
2404 unsigned gdb_flags
= 0;
2407 while (argc
> 0 && argv
[0][0] == '-')
2409 if (strcmp(argv
[0], "--no-start") == 0)
2411 gdb_flags
|= FLAG_NO_START
;
2415 if (strcmp(argv
[0], "--with-xterm") == 0)
2417 gdb_flags
|= FLAG_WITH_XTERM
;
2423 if (dbg_active_attach(argc
, argv
) == start_ok
||
2424 dbg_active_launch(argc
, argv
) == start_ok
)
2425 return gdb_remote(gdb_flags
);
2427 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");