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_32.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 struct be_process_io be_process_gdbproxy_io
=
116 NULL
, /* we shouldn't use close_process() in gdbproxy */
121 /* =============================================== *
122 * B A S I C M A N I P U L A T I O N S *
123 * =============================================== *
126 static inline int hex_from0(char ch
)
128 if (ch
>= '0' && ch
<= '9') return ch
- '0';
129 if (ch
>= 'A' && ch
<= 'F') return ch
- 'A' + 10;
130 if (ch
>= 'a' && ch
<= 'f') return ch
- 'a' + 10;
136 static inline unsigned char hex_to0(int x
)
138 assert(x
>= 0 && x
< 16);
139 return "0123456789abcdef"[x
];
142 static int hex_to_int(const char* src
, size_t len
)
144 unsigned int returnval
= 0;
148 returnval
|= hex_from0(*src
++);
153 static void hex_from(void* dst
, const char* src
, size_t len
)
155 unsigned char *p
= dst
;
158 *p
++ = (hex_from0(src
[0]) << 4) | hex_from0(src
[1]);
163 static void hex_to(char* dst
, const void* src
, size_t len
)
165 const unsigned char *p
= src
;
168 *dst
++ = hex_to0(*p
>> 4);
169 *dst
++ = hex_to0(*p
& 0x0F);
174 static unsigned char checksum(const char* ptr
, int len
)
179 cksum
+= (unsigned char)*ptr
++;
183 /* =============================================== *
184 * C P U H A N D L E R S *
185 * =============================================== *
189 static size_t cpu_register_map
[] = {
190 FIELD_OFFSET(CONTEXT
, Eax
),
191 FIELD_OFFSET(CONTEXT
, Ecx
),
192 FIELD_OFFSET(CONTEXT
, Edx
),
193 FIELD_OFFSET(CONTEXT
, Ebx
),
194 FIELD_OFFSET(CONTEXT
, Esp
),
195 FIELD_OFFSET(CONTEXT
, Ebp
),
196 FIELD_OFFSET(CONTEXT
, Esi
),
197 FIELD_OFFSET(CONTEXT
, Edi
),
198 FIELD_OFFSET(CONTEXT
, Eip
),
199 FIELD_OFFSET(CONTEXT
, EFlags
),
200 FIELD_OFFSET(CONTEXT
, SegCs
),
201 FIELD_OFFSET(CONTEXT
, SegSs
),
202 FIELD_OFFSET(CONTEXT
, SegDs
),
203 FIELD_OFFSET(CONTEXT
, SegEs
),
204 FIELD_OFFSET(CONTEXT
, SegFs
),
205 FIELD_OFFSET(CONTEXT
, SegGs
),
207 #elif defined(__powerpc__)
208 static size_t cpu_register_map
[] = {
209 FIELD_OFFSET(CONTEXT
, Gpr0
),
210 FIELD_OFFSET(CONTEXT
, Gpr1
),
211 FIELD_OFFSET(CONTEXT
, Gpr2
),
212 FIELD_OFFSET(CONTEXT
, Gpr3
),
213 FIELD_OFFSET(CONTEXT
, Gpr4
),
214 FIELD_OFFSET(CONTEXT
, Gpr5
),
215 FIELD_OFFSET(CONTEXT
, Gpr6
),
216 FIELD_OFFSET(CONTEXT
, Gpr7
),
217 FIELD_OFFSET(CONTEXT
, Gpr8
),
218 FIELD_OFFSET(CONTEXT
, Gpr9
),
219 FIELD_OFFSET(CONTEXT
, Gpr10
),
220 FIELD_OFFSET(CONTEXT
, Gpr11
),
221 FIELD_OFFSET(CONTEXT
, Gpr12
),
222 FIELD_OFFSET(CONTEXT
, Gpr13
),
223 FIELD_OFFSET(CONTEXT
, Gpr14
),
224 FIELD_OFFSET(CONTEXT
, Gpr15
),
225 FIELD_OFFSET(CONTEXT
, Gpr16
),
226 FIELD_OFFSET(CONTEXT
, Gpr17
),
227 FIELD_OFFSET(CONTEXT
, Gpr18
),
228 FIELD_OFFSET(CONTEXT
, Gpr19
),
229 FIELD_OFFSET(CONTEXT
, Gpr20
),
230 FIELD_OFFSET(CONTEXT
, Gpr21
),
231 FIELD_OFFSET(CONTEXT
, Gpr22
),
232 FIELD_OFFSET(CONTEXT
, Gpr23
),
233 FIELD_OFFSET(CONTEXT
, Gpr24
),
234 FIELD_OFFSET(CONTEXT
, Gpr25
),
235 FIELD_OFFSET(CONTEXT
, Gpr26
),
236 FIELD_OFFSET(CONTEXT
, Gpr27
),
237 FIELD_OFFSET(CONTEXT
, Gpr28
),
238 FIELD_OFFSET(CONTEXT
, Gpr29
),
239 FIELD_OFFSET(CONTEXT
, Gpr30
),
240 FIELD_OFFSET(CONTEXT
, Gpr31
),
241 FIELD_OFFSET(CONTEXT
, Fpr0
),
242 FIELD_OFFSET(CONTEXT
, Fpr1
),
243 FIELD_OFFSET(CONTEXT
, Fpr2
),
244 FIELD_OFFSET(CONTEXT
, Fpr3
),
245 FIELD_OFFSET(CONTEXT
, Fpr4
),
246 FIELD_OFFSET(CONTEXT
, Fpr5
),
247 FIELD_OFFSET(CONTEXT
, Fpr6
),
248 FIELD_OFFSET(CONTEXT
, Fpr7
),
249 FIELD_OFFSET(CONTEXT
, Fpr8
),
250 FIELD_OFFSET(CONTEXT
, Fpr9
),
251 FIELD_OFFSET(CONTEXT
, Fpr10
),
252 FIELD_OFFSET(CONTEXT
, Fpr11
),
253 FIELD_OFFSET(CONTEXT
, Fpr12
),
254 FIELD_OFFSET(CONTEXT
, Fpr13
),
255 FIELD_OFFSET(CONTEXT
, Fpr14
),
256 FIELD_OFFSET(CONTEXT
, Fpr15
),
257 FIELD_OFFSET(CONTEXT
, Fpr16
),
258 FIELD_OFFSET(CONTEXT
, Fpr17
),
259 FIELD_OFFSET(CONTEXT
, Fpr18
),
260 FIELD_OFFSET(CONTEXT
, Fpr19
),
261 FIELD_OFFSET(CONTEXT
, Fpr20
),
262 FIELD_OFFSET(CONTEXT
, Fpr21
),
263 FIELD_OFFSET(CONTEXT
, Fpr22
),
264 FIELD_OFFSET(CONTEXT
, Fpr23
),
265 FIELD_OFFSET(CONTEXT
, Fpr24
),
266 FIELD_OFFSET(CONTEXT
, Fpr25
),
267 FIELD_OFFSET(CONTEXT
, Fpr26
),
268 FIELD_OFFSET(CONTEXT
, Fpr27
),
269 FIELD_OFFSET(CONTEXT
, Fpr28
),
270 FIELD_OFFSET(CONTEXT
, Fpr29
),
271 FIELD_OFFSET(CONTEXT
, Fpr30
),
272 FIELD_OFFSET(CONTEXT
, Fpr31
),
274 FIELD_OFFSET(CONTEXT
, Iar
),
275 FIELD_OFFSET(CONTEXT
, Msr
),
276 FIELD_OFFSET(CONTEXT
, Cr
),
277 FIELD_OFFSET(CONTEXT
, Lr
),
278 FIELD_OFFSET(CONTEXT
, Ctr
),
279 FIELD_OFFSET(CONTEXT
, Xer
),
280 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
281 /* see gdb/nlm/ppc.c */
283 #elif defined(__ALPHA__)
284 static size_t cpu_register_map
[] = {
285 FIELD_OFFSET(CONTEXT
, IntV0
),
286 FIELD_OFFSET(CONTEXT
, IntT0
),
287 FIELD_OFFSET(CONTEXT
, IntT1
),
288 FIELD_OFFSET(CONTEXT
, IntT2
),
289 FIELD_OFFSET(CONTEXT
, IntT3
),
290 FIELD_OFFSET(CONTEXT
, IntT4
),
291 FIELD_OFFSET(CONTEXT
, IntT5
),
292 FIELD_OFFSET(CONTEXT
, IntT6
),
293 FIELD_OFFSET(CONTEXT
, IntT7
),
294 FIELD_OFFSET(CONTEXT
, IntS0
),
295 FIELD_OFFSET(CONTEXT
, IntS1
),
296 FIELD_OFFSET(CONTEXT
, IntS2
),
297 FIELD_OFFSET(CONTEXT
, IntS3
),
298 FIELD_OFFSET(CONTEXT
, IntS4
),
299 FIELD_OFFSET(CONTEXT
, IntS5
),
300 FIELD_OFFSET(CONTEXT
, IntFp
),
301 FIELD_OFFSET(CONTEXT
, IntA0
),
302 FIELD_OFFSET(CONTEXT
, IntA1
),
303 FIELD_OFFSET(CONTEXT
, IntA2
),
304 FIELD_OFFSET(CONTEXT
, IntA3
),
305 FIELD_OFFSET(CONTEXT
, IntA4
),
306 FIELD_OFFSET(CONTEXT
, IntA5
),
307 FIELD_OFFSET(CONTEXT
, IntT8
),
308 FIELD_OFFSET(CONTEXT
, IntT9
),
309 FIELD_OFFSET(CONTEXT
, IntT10
),
310 FIELD_OFFSET(CONTEXT
, IntT11
),
311 FIELD_OFFSET(CONTEXT
, IntRa
),
312 FIELD_OFFSET(CONTEXT
, IntT12
),
313 FIELD_OFFSET(CONTEXT
, IntAt
),
314 FIELD_OFFSET(CONTEXT
, IntGp
),
315 FIELD_OFFSET(CONTEXT
, IntSp
),
316 FIELD_OFFSET(CONTEXT
, IntZero
),
317 FIELD_OFFSET(CONTEXT
, FltF0
),
318 FIELD_OFFSET(CONTEXT
, FltF1
),
319 FIELD_OFFSET(CONTEXT
, FltF2
),
320 FIELD_OFFSET(CONTEXT
, FltF3
),
321 FIELD_OFFSET(CONTEXT
, FltF4
),
322 FIELD_OFFSET(CONTEXT
, FltF5
),
323 FIELD_OFFSET(CONTEXT
, FltF6
),
324 FIELD_OFFSET(CONTEXT
, FltF7
),
325 FIELD_OFFSET(CONTEXT
, FltF8
),
326 FIELD_OFFSET(CONTEXT
, FltF9
),
327 FIELD_OFFSET(CONTEXT
, FltF10
),
328 FIELD_OFFSET(CONTEXT
, FltF11
),
329 FIELD_OFFSET(CONTEXT
, FltF12
),
330 FIELD_OFFSET(CONTEXT
, FltF13
),
331 FIELD_OFFSET(CONTEXT
, FltF14
),
332 FIELD_OFFSET(CONTEXT
, FltF15
),
333 FIELD_OFFSET(CONTEXT
, FltF16
),
334 FIELD_OFFSET(CONTEXT
, FltF17
),
335 FIELD_OFFSET(CONTEXT
, FltF18
),
336 FIELD_OFFSET(CONTEXT
, FltF19
),
337 FIELD_OFFSET(CONTEXT
, FltF20
),
338 FIELD_OFFSET(CONTEXT
, FltF21
),
339 FIELD_OFFSET(CONTEXT
, FltF22
),
340 FIELD_OFFSET(CONTEXT
, FltF23
),
341 FIELD_OFFSET(CONTEXT
, FltF24
),
342 FIELD_OFFSET(CONTEXT
, FltF25
),
343 FIELD_OFFSET(CONTEXT
, FltF26
),
344 FIELD_OFFSET(CONTEXT
, FltF27
),
345 FIELD_OFFSET(CONTEXT
, FltF28
),
346 FIELD_OFFSET(CONTEXT
, FltF29
),
347 FIELD_OFFSET(CONTEXT
, FltF30
),
348 FIELD_OFFSET(CONTEXT
, FltF31
),
350 /* FIXME: Didn't look for the right order yet */
351 FIELD_OFFSET(CONTEXT
, Fir
),
352 FIELD_OFFSET(CONTEXT
, Fpcr
),
353 FIELD_OFFSET(CONTEXT
, SoftFpcr
),
355 #elif defined(__x86_64__)
356 static size_t cpu_register_map
[] = {
357 FIELD_OFFSET(CONTEXT
, Rax
),
358 FIELD_OFFSET(CONTEXT
, Rbx
),
359 FIELD_OFFSET(CONTEXT
, Rcx
),
360 FIELD_OFFSET(CONTEXT
, Rdx
),
361 FIELD_OFFSET(CONTEXT
, Rsi
),
362 FIELD_OFFSET(CONTEXT
, Rdi
),
363 FIELD_OFFSET(CONTEXT
, Rbp
),
364 FIELD_OFFSET(CONTEXT
, Rsp
),
365 FIELD_OFFSET(CONTEXT
, R8
),
366 FIELD_OFFSET(CONTEXT
, R9
),
367 FIELD_OFFSET(CONTEXT
, R10
),
368 FIELD_OFFSET(CONTEXT
, R11
),
369 FIELD_OFFSET(CONTEXT
, R12
),
370 FIELD_OFFSET(CONTEXT
, R13
),
371 FIELD_OFFSET(CONTEXT
, R14
),
372 FIELD_OFFSET(CONTEXT
, R15
),
373 FIELD_OFFSET(CONTEXT
, Rip
),
374 FIELD_OFFSET(CONTEXT
, EFlags
),
375 FIELD_OFFSET(CONTEXT
, SegCs
),
376 FIELD_OFFSET(CONTEXT
, SegSs
),
377 FIELD_OFFSET(CONTEXT
, SegDs
),
378 FIELD_OFFSET(CONTEXT
, SegEs
),
379 FIELD_OFFSET(CONTEXT
, SegFs
),
380 FIELD_OFFSET(CONTEXT
, SegGs
),
383 # error Define the registers map for your CPU
386 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
388 static inline unsigned long* cpu_register(CONTEXT
* ctx
, unsigned idx
)
390 assert(idx
< cpu_num_regs
);
391 return (unsigned long*)((char*)ctx
+ cpu_register_map
[idx
]);
394 /* =============================================== *
395 * W I N 3 2 D E B U G I N T E R F A C E *
396 * =============================================== *
399 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
401 ctx
->ContextFlags
= CONTEXT_CONTROL
403 #ifdef CONTEXT_SEGMENTS
406 #ifdef CONTEXT_DEBUG_REGISTERS
407 | CONTEXT_DEBUG_REGISTERS
410 if (!GetThreadContext(h
, ctx
))
412 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
413 fprintf(stderr
, "Can't get thread's context\n");
419 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
421 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
424 switch (rec
->ExceptionCode
)
426 case EXCEPTION_ACCESS_VIOLATION
:
427 case EXCEPTION_PRIV_INSTRUCTION
:
428 case EXCEPTION_STACK_OVERFLOW
:
429 case EXCEPTION_GUARD_PAGE
:
430 gdbctx
->last_sig
= SIGSEGV
;
433 case EXCEPTION_DATATYPE_MISALIGNMENT
:
434 gdbctx
->last_sig
= SIGBUS
;
437 case EXCEPTION_SINGLE_STEP
:
439 case EXCEPTION_BREAKPOINT
:
440 gdbctx
->last_sig
= SIGTRAP
;
443 case EXCEPTION_FLT_DENORMAL_OPERAND
:
444 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
445 case EXCEPTION_FLT_INEXACT_RESULT
:
446 case EXCEPTION_FLT_INVALID_OPERATION
:
447 case EXCEPTION_FLT_OVERFLOW
:
448 case EXCEPTION_FLT_STACK_CHECK
:
449 case EXCEPTION_FLT_UNDERFLOW
:
450 gdbctx
->last_sig
= SIGFPE
;
453 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
454 case EXCEPTION_INT_OVERFLOW
:
455 gdbctx
->last_sig
= SIGFPE
;
458 case EXCEPTION_ILLEGAL_INSTRUCTION
:
459 gdbctx
->last_sig
= SIGILL
;
463 gdbctx
->last_sig
= SIGINT
;
466 case STATUS_POSSIBLE_DEADLOCK
:
467 gdbctx
->last_sig
= SIGALRM
;
469 /* FIXME: we could also add here a O packet with additional information */
472 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
473 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
474 gdbctx
->last_sig
= SIGABRT
;
481 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
485 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
487 switch (de
->dwDebugEventCode
)
489 case CREATE_PROCESS_DEBUG_EVENT
:
490 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
491 de
->u
.CreateProcessInfo
.hProcess
);
492 if (!gdbctx
->process
) break;
493 memory_get_string_indirect(gdbctx
->process
,
494 de
->u
.CreateProcessInfo
.lpImageName
,
495 de
->u
.CreateProcessInfo
.fUnicode
,
496 buffer
, sizeof(buffer
));
497 dbg_set_process_name(gdbctx
->process
, buffer
);
499 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
500 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
501 de
->dwProcessId
, de
->dwThreadId
,
502 buffer
, de
->u
.CreateProcessInfo
.lpImageName
,
503 de
->u
.CreateProcessInfo
.lpStartAddress
,
504 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
505 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
507 /* de->u.CreateProcessInfo.lpStartAddress; */
508 if (!dbg_init(gdbctx
->process
->handle
, buffer
, TRUE
))
509 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
511 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
512 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
513 de
->dwProcessId
, de
->dwThreadId
,
514 de
->u
.CreateProcessInfo
.lpStartAddress
);
516 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
517 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
518 de
->u
.CreateProcessInfo
.hThread
,
519 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
522 case LOAD_DLL_DEBUG_EVENT
:
523 assert(dbg_curr_thread
);
524 memory_get_string_indirect(gdbctx
->process
,
525 de
->u
.LoadDll
.lpImageName
,
526 de
->u
.LoadDll
.fUnicode
,
527 buffer
, sizeof(buffer
));
528 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
529 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
530 de
->dwProcessId
, de
->dwThreadId
,
531 buffer
, de
->u
.LoadDll
.lpBaseOfDll
,
532 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
533 de
->u
.LoadDll
.nDebugInfoSize
);
534 SymLoadModule(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, buffer
, NULL
,
535 (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
, 0);
538 case UNLOAD_DLL_DEBUG_EVENT
:
539 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
540 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
541 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
542 SymUnloadModule(gdbctx
->process
->handle
,
543 (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
546 case EXCEPTION_DEBUG_EVENT
:
547 assert(dbg_curr_thread
);
548 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
549 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
550 de
->dwProcessId
, de
->dwThreadId
,
551 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
553 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
555 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
559 case CREATE_THREAD_DEBUG_EVENT
:
560 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
561 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
562 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
564 dbg_add_thread(gdbctx
->process
,
566 de
->u
.CreateThread
.hThread
,
567 de
->u
.CreateThread
.lpThreadLocalBase
);
570 case EXIT_THREAD_DEBUG_EVENT
:
571 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
572 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
573 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
575 assert(dbg_curr_thread
);
576 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
577 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
578 dbg_del_thread(dbg_curr_thread
);
581 case EXIT_PROCESS_DEBUG_EVENT
:
582 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
583 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
584 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
586 dbg_del_process(gdbctx
->process
);
587 gdbctx
->process
= NULL
;
588 /* now signal gdb that we're done */
589 gdbctx
->last_sig
= SIGTERM
;
590 gdbctx
->in_trap
= TRUE
;
593 case OUTPUT_DEBUG_STRING_EVENT
:
594 assert(dbg_curr_thread
);
595 memory_get_string(gdbctx
->process
,
596 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
597 de
->u
.DebugString
.fUnicode
, buffer
, sizeof(buffer
));
598 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
599 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
600 de
->dwProcessId
, de
->dwThreadId
, buffer
);
604 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
605 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
606 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
607 de
->u
.RipInfo
.dwType
);
611 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
612 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
613 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
617 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
621 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
622 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
623 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
624 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
625 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
626 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
627 dbg_curr_thread
->tid
, cont
);
629 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
630 fprintf(stderr
, "Cannot find last thread\n");
634 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
639 if(dbg_curr_thread
->tid
== threadid
){
640 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
641 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
642 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
643 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
644 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
645 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
646 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
647 dbg_curr_thread
->tid
, cont
);
650 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
651 fprintf(stderr
, "Cannot find last thread\n");
654 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
656 struct pollfd pollfd
;
660 pollfd
.fd
= gdbctx
->sock
;
661 pollfd
.events
= POLLIN
;
664 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
665 ret
= read(gdbctx
->sock
, &pkt
, 1);
667 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
668 fprintf(stderr
, "read failed\n");
673 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
674 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
679 } else if (ret
== -1) {
680 fprintf(stderr
, "poll failed\n");
685 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
689 gdbctx
->in_trap
= FALSE
;
692 if (!WaitForDebugEvent(&de
, 10))
694 if (GetLastError() == ERROR_SEM_TIMEOUT
)
696 if (check_for_interrupt(gdbctx
)) {
697 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
698 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
699 fprintf(stderr
, "Failed to break into debugee\n");
703 WaitForDebugEvent(&de
, INFINITE
);
711 handle_debug_event(gdbctx
, &de
);
712 assert(!gdbctx
->process
||
713 gdbctx
->process
->pid
== 0 ||
714 de
.dwProcessId
== gdbctx
->process
->pid
);
715 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
716 if (gdbctx
->in_trap
) break;
717 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
721 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
723 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
724 resume_debuggee(gdbctx
, DBG_CONTINUE
);
726 DebugActiveProcessStop(gdbctx
->process
->pid
);
727 dbg_del_process(gdbctx
->process
);
728 gdbctx
->process
= NULL
;
731 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
735 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
737 strcpy(buffer
, "Unknown process");
740 if (status
== STILL_ACTIVE
)
742 strcpy(buffer
, "Running");
745 snprintf(buffer
, len
, "Terminated (%u)", status
);
747 switch (GetPriorityClass(gdbctx
->process
->handle
))
750 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
751 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
753 #ifdef BELOW_NORMAL_PRIORITY_CLASS
754 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
756 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
757 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
758 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
759 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
761 strcat(buffer
, "\n");
764 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
765 char* buffer
, size_t len
)
767 struct dbg_thread
* thd
;
771 /* FIXME: use the size of buffer */
772 thd
= dbg_get_thread(gdbctx
->process
, tid
);
775 strcpy(buffer
, "No information");
778 if (GetExitCodeThread(thd
->handle
, &status
))
780 if (status
== STILL_ACTIVE
)
782 /* FIXME: this is a bit brutal... some nicer way shall be found */
783 switch (status
= SuspendThread(thd
->handle
))
786 case 0: strcpy(buffer
, "Running"); break;
787 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
789 ResumeThread(thd
->handle
);
792 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
796 strcpy(buffer
, "Unknown threadID");
798 switch (prio
= GetThreadPriority(thd
->handle
))
800 case THREAD_PRIORITY_ERROR_RETURN
: break;
801 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
802 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
803 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
804 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
805 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
806 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
807 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
808 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
810 assert(strlen(buffer
) < len
);
813 /* =============================================== *
814 * P A C K E T U T I L S *
815 * =============================================== *
818 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
819 packet_last_f
= 0x80};
821 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
823 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
825 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
826 gdbctx
->out_buf
= realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
830 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
832 packet_reply_grow(gdbctx
, len
* 2);
833 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
834 gdbctx
->out_len
+= len
* 2;
837 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
839 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
842 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
846 shift
= (len
- 1) * 8;
847 packet_reply_grow(gdbctx
, len
* 2);
848 for (i
= 0; i
< len
; i
++, shift
-= 8)
850 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
851 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
855 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
857 packet_reply_grow(gdbctx
, len
);
858 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
859 gdbctx
->out_len
+= len
;
862 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
864 packet_reply_add(gdbctx
, str
, strlen(str
));
867 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
869 packet_reply_add(gdbctx
, &ch
, 1);
872 static void packet_reply_open(struct gdb_context
* gdbctx
)
874 assert(gdbctx
->out_curr_packet
== -1);
875 packet_reply_catc(gdbctx
, '$');
876 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
879 static void packet_reply_close(struct gdb_context
* gdbctx
)
884 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
885 packet_reply_catc(gdbctx
, '#');
886 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
887 packet_reply_hex_to(gdbctx
, &cksum
, 1);
888 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
889 fprintf(stderr
, "Reply : %*.*s\n",
890 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
891 gdbctx
->out_curr_packet
= -1;
894 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
896 packet_reply_open(gdbctx
);
898 if (len
== -1) len
= strlen(packet
);
899 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
901 packet_reply_add(gdbctx
, packet
, len
);
903 packet_reply_close(gdbctx
);
908 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
910 packet_reply_open(gdbctx
);
912 packet_reply_add(gdbctx
, "E", 1);
913 packet_reply_val(gdbctx
, error
, 1);
915 packet_reply_close(gdbctx
);
920 /* =============================================== *
921 * P A C K E T H A N D L E R S *
922 * =============================================== *
925 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
927 enum packet_return ret
= packet_done
;
929 packet_reply_open(gdbctx
);
931 if (gdbctx
->process
!= NULL
)
936 packet_reply_catc(gdbctx
, 'T');
937 sig
= gdbctx
->last_sig
;
938 packet_reply_val(gdbctx
, sig
, 1);
939 packet_reply_add(gdbctx
, "thread:", 7);
940 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
941 packet_reply_catc(gdbctx
, ';');
943 for (i
= 0; i
< cpu_num_regs
; i
++)
945 /* FIXME: this call will also grow the buffer...
946 * unneeded, but not harmful
948 packet_reply_val(gdbctx
, i
, 1);
949 packet_reply_catc(gdbctx
, ':');
950 packet_reply_hex_to(gdbctx
, cpu_register(&gdbctx
->context
, i
), 4);
951 packet_reply_catc(gdbctx
, ';');
956 /* Try to put an exit code
957 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
958 * just indicate the end of process and exit */
959 packet_reply_add(gdbctx
, "W00", 3);
960 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
963 packet_reply_close(gdbctx
);
969 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
971 gdbctx
->extended
= 1;
976 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
978 assert(gdbctx
->in_packet_len
== 0);
979 return packet_reply_status(gdbctx
);
982 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
984 /* FIXME: add support for address in packet */
985 assert(gdbctx
->in_packet_len
== 0);
986 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
987 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
988 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
989 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
990 resume_debuggee(gdbctx
, DBG_CONTINUE
);
991 wait_for_debuggee(gdbctx
);
992 return packet_reply_status(gdbctx
);
995 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
998 int defaultAction
= -1; /* magic non action */
1001 int actionIndex
[20]; /* allow for up to 20 actions */
1002 int threadIndex
[20];
1003 int threadCount
= 0;
1004 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1005 unsigned int threadID
= 0;
1006 struct dbg_thread
* thd
;
1009 assert(gdbctx
->in_packet_len
>= 4);
1011 /* OK we have vCont followed by..
1013 * c for packet_continue
1014 * Csig for packet_continue_signal
1016 * Ssig for step signal
1017 * and then an optional thread ID at the end..
1018 * *******************************************/
1020 fprintf(stderr
, "trying to process a verbose packet\n");
1021 /* now check that we've got Cont */
1022 assert(strncmp(gdbctx
->in_packet
, "Cont", 4) == 0);
1025 if (gdbctx
->in_packet
[4] == '?')
1030 The vCont packet is supported. Each action is a supported command in the vCont packet.
1032 The vCont packet is not supported. (this didn't seem to be obeyed!)
1034 packet_reply_open(gdbctx
);
1035 packet_reply_add(gdbctx
, "vCont", 5);
1036 /* add all the supported actions to the reply (all of them for now) */
1037 packet_reply_add(gdbctx
, ";c", 2);
1038 packet_reply_add(gdbctx
, ";C", 2);
1039 packet_reply_add(gdbctx
, ";s", 2);
1040 packet_reply_add(gdbctx
, ";S", 2);
1041 packet_reply_close(gdbctx
);
1045 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1046 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1047 now if only gdb talked XML.... */
1048 #if 0 /* handy for debugging */
1049 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1052 /* go through the packet and identify where all the actions start at */
1053 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1055 if (gdbctx
->in_packet
[i
] == ';')
1057 threadIndex
[actions
] = 0;
1058 actionIndex
[actions
++] = i
;
1060 else if (gdbctx
->in_packet
[i
] == ':')
1062 threadIndex
[actions
- 1] = i
;
1066 /* now look up the default action */
1067 for (i
= 0 ; i
< actions
; i
++)
1069 if (threadIndex
[i
] == 0)
1071 if (defaultAction
!= -1)
1073 fprintf(stderr
,"Too many default actions specified\n");
1074 return packet_error
;
1080 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1082 /* go through all the threads and stick their ids in the to be done list. */
1083 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1085 threadIDs
[threadCount
++] = thd
->tid
;
1086 /* check to see if we have more threads than I counted on, and tell the user what to do
1087 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1088 if (threadCount
== 100)
1090 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1095 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1096 * that remains is to apply the actions to the threads and the default action to any threads
1098 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1099 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1100 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1101 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1103 /* deal with the threaded stuff first */
1104 for (i
= 0; i
< actions
; i
++)
1106 if (threadIndex
[i
] != 0)
1108 int j
, idLength
= 0;
1109 if (i
< actions
- 1)
1111 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1115 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1118 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1119 /* process the action */
1120 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1122 case 's': /* step */
1123 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1125 case 'c': /* continue */
1126 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1128 case 'S': /* step Sig, */
1129 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1131 case 'C': /* continue sig */
1132 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1133 /* cannot change signals on the fly */
1134 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1135 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1136 if (sig
!= gdbctx
->last_sig
)
1137 return packet_error
;
1138 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1141 for (j
= 0 ; j
< threadCount
; j
++)
1143 if (threadIDs
[j
] == threadID
)
1150 } /* for i=0 ; i< actions */
1152 /* now we have manage the default action */
1153 if (defaultAction
>= 0)
1155 for (i
= 0 ; i
< threadCount
; i
++)
1157 /* check to see if we've already done something to the thread*/
1158 if (threadIDs
[i
] != 0)
1160 /* if not apply the default action*/
1161 threadID
= threadIDs
[i
];
1162 /* process the action (yes this is almost identical to the one above!) */
1163 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1165 case 's': /* step */
1166 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1168 case 'c': /* continue */
1169 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1172 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1174 case 'C': /* continue sig */
1175 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1176 /* cannot change signals on the fly */
1177 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1178 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1179 if (sig
!= gdbctx
->last_sig
)
1180 return packet_error
;
1181 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1186 } /* if(defaultAction >=0) */
1188 wait_for_debuggee(gdbctx
);
1189 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1190 return packet_reply_status(gdbctx
);
1193 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1197 /* FIXME: add support for address in packet */
1198 assert(gdbctx
->in_packet_len
== 2);
1199 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1200 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1201 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1202 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1203 hex_from(&sig
, gdbctx
->in_packet
, 1);
1204 /* cannot change signals on the fly */
1205 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1206 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1207 if (sig
!= gdbctx
->last_sig
)
1208 return packet_error
;
1209 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1210 wait_for_debuggee(gdbctx
);
1211 return packet_reply_status(gdbctx
);
1214 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1216 detach_debuggee(gdbctx
, FALSE
);
1217 return packet_ok
| packet_last_f
;
1220 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1224 CONTEXT
* pctx
= &gdbctx
->context
;
1226 assert(gdbctx
->in_trap
);
1228 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1230 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1231 return packet_error
;
1234 packet_reply_open(gdbctx
);
1235 for (i
= 0; i
< cpu_num_regs
; i
++)
1237 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, i
), 4);
1239 packet_reply_close(gdbctx
);
1243 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1247 CONTEXT
* pctx
= &gdbctx
->context
;
1249 assert(gdbctx
->in_trap
);
1250 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1252 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1253 return packet_error
;
1255 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1257 for (i
= 0; i
< cpu_num_regs
; i
++)
1258 hex_from(cpu_register(pctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
1259 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1261 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1262 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1263 return packet_error
;
1268 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1270 detach_debuggee(gdbctx
, TRUE
);
1272 if (!gdbctx
->extended
)
1273 /* dunno whether GDB cares or not */
1277 /* assume we can't really answer something here */
1278 /* return packet_done; */
1281 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1286 switch (gdbctx
->in_packet
[0])
1290 if (gdbctx
->in_packet
[1] == '-')
1291 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1293 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1294 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1296 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1297 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1298 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1299 gdbctx
->in_packet
+ 1);
1300 return packet_error
;
1302 if (gdbctx
->in_packet
[0] == 'c')
1303 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1305 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1308 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1309 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1310 return packet_error
;
1314 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1317 unsigned int len
, blk_len
, nread
;
1321 assert(gdbctx
->in_trap
);
1322 /* FIXME:check in_packet_len for reading %p,%x */
1323 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1324 if (len
<= 0) return packet_error
;
1325 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1326 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1327 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1329 blk_len
= min(sizeof(buffer
), len
- nread
);
1330 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1333 /* fail at first address, return error */
1334 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1335 /* something has already been read, return partial information */
1338 if (nread
== 0) packet_reply_open(gdbctx
);
1339 packet_reply_hex_to(gdbctx
, buffer
, r
);
1341 packet_reply_close(gdbctx
);
1345 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1348 unsigned int len
, blk_len
;
1353 assert(gdbctx
->in_trap
);
1354 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1357 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1358 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1359 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1360 return packet_error
;
1364 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1366 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1367 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1368 return packet_error
;
1370 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1372 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1373 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1374 ptr
- gdbctx
->in_packet
+ len
* 2, gdbctx
->in_packet_len
);
1375 return packet_error
;
1377 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1378 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1381 blk_len
= min(sizeof(buffer
), len
);
1382 hex_from(buffer
, ptr
, blk_len
);
1383 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1390 return packet_ok
; /* FIXME: error while writing ? */
1393 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1397 CONTEXT
* pctx
= &gdbctx
->context
;
1399 assert(gdbctx
->in_trap
);
1400 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1401 if (reg
>= cpu_num_regs
)
1403 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1404 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1405 return packet_error
;
1407 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1409 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1410 return packet_error
;
1412 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1413 fprintf(stderr
, "Read register %x => %lx\n", reg
, *cpu_register(pctx
, reg
));
1414 packet_reply_open(gdbctx
);
1415 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, reg
), 4);
1416 packet_reply_close(gdbctx
);
1420 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1426 CONTEXT
* pctx
= &gdbctx
->context
;
1428 assert(gdbctx
->in_trap
);
1430 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1432 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1433 if (end
== NULL
|| reg
> cpu_num_regs
)
1435 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1436 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1437 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1438 * it wouldn't matter too much, and it fakes our support for all regs
1440 return (end
== NULL
) ? packet_error
: packet_ok
;
1442 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1444 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1445 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1446 ptr
+ 8 - gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1447 return packet_error
;
1449 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1450 fprintf(stderr
, "Writing reg %u <= %*.*s\n",
1451 reg
, gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
),
1452 gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
), ptr
);
1454 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1456 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1457 return packet_error
;
1460 hex_from(cpu_register(pctx
, reg
), ptr
, 4);
1461 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1463 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1464 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1465 return packet_error
;
1471 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1479 if (!GetClassName(hWnd
, clsName
, sizeof(clsName
)))
1480 strcpy(clsName
, "-- Unknown --");
1481 if (!GetWindowText(hWnd
, wndName
, sizeof(wndName
)))
1482 strcpy(wndName
, "-- Empty --");
1484 packet_reply_open(gdbctx
);
1485 packet_reply_catc(gdbctx
, 'O');
1486 snprintf(buffer
, sizeof(buffer
),
1487 "%*s%04lx%*s%-17.17s %08x %08x %.14s\n",
1488 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1489 clsName
, GetWindowLong(hWnd
, GWL_STYLE
),
1490 GetWindowLongPtr(hWnd
, GWLP_WNDPROC
), wndName
);
1491 packet_reply_hex_to_str(gdbctx
, buffer
);
1492 packet_reply_close(gdbctx
);
1494 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1495 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1496 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1499 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1503 /* we do the output in several 'O' packets, with the last one being just OK for
1504 * marking the end of the output */
1505 packet_reply_open(gdbctx
);
1506 packet_reply_catc(gdbctx
, 'O');
1507 snprintf(buffer
, sizeof(buffer
),
1508 "%-16.16s %-17.17s %-8.8s %s\n",
1509 "hwnd", "Class Name", " Style", " WndProc Text");
1510 packet_reply_hex_to_str(gdbctx
, buffer
);
1511 packet_reply_close(gdbctx
);
1513 /* FIXME: could also add a pmt to this command in str... */
1514 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1515 packet_reply(gdbctx
, "OK", 2);
1518 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1520 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1523 PROCESSENTRY32 entry
;
1526 if (snap
== INVALID_HANDLE_VALUE
)
1529 entry
.dwSize
= sizeof(entry
);
1530 ok
= Process32First(snap
, &entry
);
1532 /* we do the output in several 'O' packets, with the last one being just OK for
1533 * marking the end of the output */
1535 packet_reply_open(gdbctx
);
1536 packet_reply_catc(gdbctx
, 'O');
1537 snprintf(buffer
, sizeof(buffer
),
1538 " %-8.8s %-8.8s %-8.8s %s\n",
1539 "pid", "threads", "parent", "executable");
1540 packet_reply_hex_to_str(gdbctx
, buffer
);
1541 packet_reply_close(gdbctx
);
1546 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1547 packet_reply_open(gdbctx
);
1548 packet_reply_catc(gdbctx
, 'O');
1549 snprintf(buffer
, sizeof(buffer
),
1550 "%c%08x %-8d %08x '%s'\n",
1551 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1552 entry
.th32ParentProcessID
, entry
.szExeFile
);
1553 packet_reply_hex_to_str(gdbctx
, buffer
);
1554 packet_reply_close(gdbctx
);
1555 ok
= Process32Next(snap
, &entry
);
1558 packet_reply(gdbctx
, "OK", 2);
1561 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1563 MEMORY_BASIC_INFORMATION mbi
;
1570 /* we do the output in several 'O' packets, with the last one being just OK for
1571 * marking the end of the output */
1572 packet_reply_open(gdbctx
);
1573 packet_reply_catc(gdbctx
, 'O');
1574 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1575 packet_reply_close(gdbctx
);
1577 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1581 case MEM_COMMIT
: state
= "commit "; break;
1582 case MEM_FREE
: state
= "free "; break;
1583 case MEM_RESERVE
: state
= "reserve"; break;
1584 default: state
= "??? "; break;
1586 if (mbi
.State
!= MEM_FREE
)
1590 case MEM_IMAGE
: type
= "image "; break;
1591 case MEM_MAPPED
: type
= "mapped "; break;
1592 case MEM_PRIVATE
: type
= "private"; break;
1593 case 0: type
= " "; break;
1594 default: type
= "??? "; break;
1596 memset(prot
, ' ' , sizeof(prot
)-1);
1597 prot
[sizeof(prot
)-1] = '\0';
1598 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1600 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1602 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1604 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1612 packet_reply_open(gdbctx
);
1613 snprintf(buffer
, sizeof(buffer
), "%08lx %08lx %s %s %s\n",
1614 (DWORD_PTR
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1615 packet_reply_catc(gdbctx
, 'O');
1616 packet_reply_hex_to_str(gdbctx
, buffer
);
1617 packet_reply_close(gdbctx
);
1619 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1621 addr
+= mbi
.RegionSize
;
1623 packet_reply(gdbctx
, "OK", 2);
1626 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1627 int len
, const char* str
)
1633 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1635 else if (len
>= 2 && str
[0] == '=')
1637 unsigned val
= atoi(&str
[1]);
1638 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1639 gdbctx
->trace
= val
;
1643 /* FIXME: ugly but can use error packet here */
1644 packet_reply_cat(gdbctx
, "E00");
1647 packet_reply_open(gdbctx
);
1648 packet_reply_hex_to_str(gdbctx
, buffer
);
1649 packet_reply_close(gdbctx
);
1657 void (*handler
)(struct gdb_context
*, int, const char*);
1660 {0, "wnd", 3, packet_query_monitor_wnd
},
1661 {0, "window", 6, packet_query_monitor_wnd
},
1662 {0, "proc", 4, packet_query_monitor_process
},
1663 {0, "process", 7, packet_query_monitor_process
},
1664 {0, "mem", 3, packet_query_monitor_mem
},
1665 {1, "trace", 5, packet_query_monitor_trace
},
1669 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1670 const char* hxcmd
, size_t len
)
1673 struct query_detail
* qd
;
1675 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1677 hex_from(buffer
, hxcmd
, len
);
1679 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1681 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1682 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1684 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1687 return packet_reply_error(gdbctx
, EINVAL
);
1690 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1692 switch (gdbctx
->in_packet
[0])
1695 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1697 struct dbg_thread
* thd
;
1699 packet_reply_open(gdbctx
);
1700 packet_reply_add(gdbctx
, "m", 1);
1701 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1703 packet_reply_val(gdbctx
, thd
->tid
, 4);
1704 if (thd
->next
!= NULL
)
1705 packet_reply_add(gdbctx
, ",", 1);
1707 packet_reply_close(gdbctx
);
1710 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1714 packet_reply_open(gdbctx
);
1715 packet_reply_catc(gdbctx
, 'O');
1716 get_process_info(gdbctx
, result
, sizeof(result
));
1717 packet_reply_hex_to_str(gdbctx
, result
);
1718 packet_reply_close(gdbctx
);
1723 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1725 packet_reply(gdbctx
, "l", 1);
1728 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1730 packet_reply(gdbctx
, "l", 1);
1735 if (gdbctx
->in_packet_len
== 1)
1737 struct dbg_thread
* thd
;
1738 /* FIXME: doc says 16 bit val ??? */
1739 /* grab first created thread, aka last in list */
1740 assert(gdbctx
->process
&& gdbctx
->process
->threads
);
1741 for (thd
= gdbctx
->process
->threads
; thd
->next
; thd
= thd
->next
);
1742 packet_reply_open(gdbctx
);
1743 packet_reply_add(gdbctx
, "QC", 2);
1744 packet_reply_val(gdbctx
, thd
->tid
, 4);
1745 packet_reply_close(gdbctx
);
1750 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1754 if (gdbctx
->wine_segs
[0] == 0 && gdbctx
->wine_segs
[1] == 0 &&
1755 gdbctx
->wine_segs
[2] == 0)
1756 return packet_error
;
1757 snprintf(buf
, sizeof(buf
),
1758 "Text=%08lx;Data=%08lx;Bss=%08lx",
1759 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1760 gdbctx
->wine_segs
[2]);
1761 return packet_reply(gdbctx
, buf
, -1);
1765 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1767 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1768 gdbctx
->in_packet_len
- 5);
1772 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1774 if (strncmp(gdbctx
->in_packet
, "Supported", gdbctx
->in_packet_len
) == 0)
1776 packet_reply_open(gdbctx
);
1777 packet_reply_close(gdbctx
);
1782 if (gdbctx
->in_packet_len
> 15 &&
1783 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1784 gdbctx
->in_packet
[15] == ',')
1790 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1791 if (end
== NULL
) break;
1792 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1793 packet_reply_open(gdbctx
);
1794 packet_reply_hex_to_str(gdbctx
, result
);
1795 packet_reply_close(gdbctx
);
1800 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1801 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1802 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1803 return packet_error
;
1806 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1808 /* FIXME: add support for address in packet */
1809 assert(gdbctx
->in_packet_len
== 0);
1810 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1811 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1812 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
1813 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1814 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1815 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1816 wait_for_debuggee(gdbctx
);
1817 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1818 return packet_reply_status(gdbctx
);
1822 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1826 /* FIXME: add support for address in packet */
1827 assert(gdbctx
->in_packet_len
== 2);
1828 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1829 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1830 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1831 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1832 hex_from(&sig
, gdbctx
->in_packet
, 1);
1833 /* cannot change signals on the fly */
1834 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1835 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1836 if (sig
!= gdbctx
->last_sig
)
1837 return packet_error
;
1838 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1839 wait_for_debuggee(gdbctx
);
1840 return packet_reply_status(gdbctx
);
1844 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1849 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1850 if (tid
== -1 || tid
== 0)
1851 return packet_reply_error(gdbctx
, EINVAL
);
1852 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1854 return packet_reply_error(gdbctx
, ESRCH
);
1857 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1861 struct gdb_ctx_Xpoint
* xpt
;
1862 enum be_xpoint_type t
;
1864 /* FIXME: check packet_len */
1865 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1866 gdbctx
->in_packet
[1] != ',' ||
1867 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1868 return packet_error
;
1869 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1870 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1871 addr
, len
, gdbctx
->in_packet
[0]);
1872 switch (gdbctx
->in_packet
[0])
1874 case '0': t
= be_xpoint_break
; len
= 0; break;
1875 case '1': t
= be_xpoint_watch_exec
; break;
1876 case '2': t
= be_xpoint_watch_read
; break;
1877 case '3': t
= be_xpoint_watch_write
; break;
1878 default: return packet_error
;
1880 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1882 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1884 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
1885 gdbctx
->process
->process_io
, &gdbctx
->context
,
1886 t
, xpt
->addr
, xpt
->val
, len
))
1894 return packet_error
;
1897 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1901 struct gdb_ctx_Xpoint
* xpt
;
1902 enum be_xpoint_type t
;
1904 /* FIXME: check packet_len */
1905 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1906 gdbctx
->in_packet
[1] != ',' ||
1907 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1908 return packet_error
;
1909 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1910 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
1911 addr
, len
, gdbctx
->in_packet
[0]);
1912 switch (gdbctx
->in_packet
[0])
1914 case '0': t
= be_xpoint_break
; len
= 0; break;
1915 case '1': t
= be_xpoint_watch_exec
; break;
1916 case '2': t
= be_xpoint_watch_read
; break;
1917 case '3': t
= be_xpoint_watch_write
; break;
1918 default: return packet_error
;
1920 /* because of packet command handling, this should be made idempotent */
1921 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1923 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1924 return packet_ok
; /* nothing to do */
1926 /* really set the Xpoint */
1927 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1929 if (xpt
->type
== -1)
1931 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
1932 gdbctx
->process
->process_io
, &gdbctx
->context
,
1933 t
, addr
, &xpt
->val
, len
))
1939 fprintf(stderr
, "cannot set xpoint\n");
1943 /* no more entries... eech */
1944 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
1945 return packet_error
;
1948 /* =============================================== *
1949 * P A C K E T I N F R A S T R U C T U R E *
1950 * =============================================== *
1956 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1959 static struct packet_entry packet_entries
[] =
1961 /*{'!', packet_extended}, */
1962 {'?', packet_last_signal
},
1963 {'c', packet_continue
},
1964 {'C', packet_continue_signal
},
1965 {'D', packet_detach
},
1966 {'g', packet_read_registers
},
1967 {'G', packet_write_registers
},
1969 {'H', packet_thread
},
1970 {'m', packet_read_memory
},
1971 {'M', packet_write_memory
},
1972 {'p', packet_read_register
},
1973 {'P', packet_write_register
},
1974 {'q', packet_query
},
1975 /* {'Q', packet_set}, */
1976 /* {'R', packet,restart}, only in extended mode ! */
1978 /*{'S', packet_step_signal}, hard(er) to implement */
1979 {'T', packet_thread_alive
},
1980 {'v', packet_verbose
},
1981 {'z', packet_remove_breakpoint
},
1982 {'Z', packet_set_breakpoint
},
1985 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
1989 unsigned char in_cksum
, loc_cksum
;
1991 enum packet_return ret
= packet_error
;
1994 while ((ret
& packet_last_f
) == 0)
1996 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
1997 fprintf(stderr
, "In-buf: %*.*s\n",
1998 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
1999 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2000 if (ptr
== NULL
) return FALSE
;
2001 if (ptr
!= gdbctx
->in_buf
)
2003 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2004 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2005 fprintf(stderr
, "Removing garbage: %*.*s\n",
2006 glen
, glen
, gdbctx
->in_buf
);
2007 gdbctx
->in_len
-= glen
;
2008 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2010 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2011 if (end
== NULL
) return FALSE
;
2012 /* no checksum yet */
2013 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2014 plen
= end
- gdbctx
->in_buf
- 1;
2015 hex_from(&in_cksum
, end
+ 1, 1);
2016 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2017 if (loc_cksum
== in_cksum
)
2019 if (num_packet
== 0) {
2024 write(gdbctx
->sock
, "+", 1);
2027 /* FIXME: should use bsearch if packet_entries was sorted */
2028 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2030 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2032 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2034 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2035 fprintf(stderr
, "Unknown packet request %*.*s\n",
2036 plen
, plen
, &gdbctx
->in_buf
[1]);
2040 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2041 gdbctx
->in_packet_len
= plen
- 1;
2042 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2043 fprintf(stderr
, "Packet: %c%*.*s\n",
2045 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2047 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2049 switch (ret
& ~packet_last_f
)
2051 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2052 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2053 case packet_done
: break;
2055 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2056 fprintf(stderr
, "Reply-full: %*.*s\n",
2057 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2058 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2059 assert(i
== gdbctx
->out_len
);
2060 /* if this fails, we'll have to use POLLOUT...
2062 gdbctx
->out_len
= 0;
2067 /* FIXME: if we have in our input buffer more than one packet,
2068 * it's very likely that we took too long to answer to a given packet
2069 * and gdb is sending us again the same packet
2070 * We simply drop the second packet. This will lower the risk of error,
2071 * but there's still some race conditions here
2072 * A better fix (yet not perfect) would be to have two threads:
2073 * - one managing the packets for gdb
2074 * - the second one managing the commands...
2075 * This would allow us also the reply with the '+' character (Ack of
2076 * the command) way sooner than what we do now
2078 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2079 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2084 write(gdbctx
->sock
, "+", 1);
2085 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2086 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2088 gdbctx
->in_len
-= plen
+ 4;
2089 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2094 static int fetch_data(struct gdb_context
* gdbctx
)
2096 int len
, in_len
= gdbctx
->in_len
;
2098 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2102 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2103 gdbctx
->in_buf
= realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2105 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2106 fprintf(stderr
, "%d %d %*.*s\n",
2107 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2108 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2109 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2110 if (len
<= 0) break;
2111 gdbctx
->in_len
+= len
;
2112 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2113 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2115 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2116 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2117 return gdbctx
->in_len
- in_len
;
2120 #define FLAG_NO_START 1
2121 #define FLAG_WITH_XTERM 2
2123 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2127 const char* gdb_path
;
2130 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2131 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2132 fd
= mkstemps(buf
, 0);
2133 if (fd
== -1) return FALSE
;
2134 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2135 fprintf(f
, "file %s\n", wine_path
);
2136 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2137 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2138 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2139 /* gdb 5.1 seems to require it, won't hurt anyway */
2140 fprintf(f
, "sharedlibrary\n");
2141 /* This is needed (but not a decent & final fix)
2142 * Without this, gdb would skip our inter-DLL relay code (because
2143 * we don't have any line number information for the relay code)
2144 * With this, we will stop on first instruction of the stub, and
2145 * reusing step, will get us through the relay stub at the actual
2146 * function we're looking at.
2148 fprintf(f
, "set step-mode on\n");
2149 /* tell gdb to delete this file when done handling it... */
2150 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2152 if (flags
& FLAG_WITH_XTERM
)
2153 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2155 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2156 assert(0); /* never reached */
2160 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2163 struct sockaddr_in s_addrs
;
2164 unsigned int s_len
= sizeof(s_addrs
);
2165 struct pollfd pollfd
;
2166 IMAGEHLP_MODULE imh_mod
;
2168 /* step 1: create socket for gdb connection request */
2169 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2171 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2172 fprintf(stderr
, "Can't create socket");
2176 if (listen(sock
, 1) == -1 ||
2177 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2180 /* step 2: do the process internal creation */
2181 handle_debug_event(gdbctx
, de
);
2183 /* step3: get the wine loader name */
2184 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
)) return FALSE
;
2186 /* step 4: fire up gdb (if requested) */
2187 if (flags
& FLAG_NO_START
)
2188 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2192 case -1: /* error in parent... */
2193 fprintf(stderr
, "Cannot create gdb\n");
2195 default: /* in parent... success */
2197 case 0: /* in child... and alive */
2198 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2199 /* if we're here, exec failed, so report failure */
2203 /* step 5: wait for gdb to connect actually */
2205 pollfd
.events
= POLLIN
;
2208 switch (poll(&pollfd
, 1, -1))
2211 if (pollfd
.revents
& POLLIN
)
2214 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2215 if (gdbctx
->sock
== -1)
2217 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2218 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2219 /* don't keep our small packets too long: send them ASAP back to GDB
2220 * without this, GDB really crawls
2222 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2226 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2227 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2230 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2231 fprintf(stderr
, "Poll for cnx failed (error)\n");
2241 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2247 gdbctx
->in_buf
= NULL
;
2248 gdbctx
->in_buf_alloc
= 0;
2250 gdbctx
->out_buf
= NULL
;
2251 gdbctx
->out_buf_alloc
= 0;
2252 gdbctx
->out_len
= 0;
2253 gdbctx
->out_curr_packet
= -1;
2255 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2256 gdbctx
->last_sig
= 0;
2257 gdbctx
->in_trap
= FALSE
;
2258 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2259 gdbctx
->process
= NULL
;
2260 for (i
= 0; i
< NUM_XPOINT
; i
++)
2261 gdbctx
->Xpoints
[i
].type
= -1;
2263 /* wait for first trap */
2264 while (WaitForDebugEvent(&de
, INFINITE
))
2266 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2268 /* this should be the first event we get,
2269 * and the only one of this type */
2270 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2271 /* gdbctx->dwProcessId = pid; */
2272 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2273 assert(!gdbctx
->in_trap
);
2277 handle_debug_event(gdbctx
, &de
);
2278 if (gdbctx
->in_trap
) break;
2280 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2285 static int gdb_remote(unsigned flags
)
2287 struct pollfd pollfd
;
2288 struct gdb_context gdbctx
;
2291 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2293 pollfd
.fd
= gdbctx
.sock
;
2294 pollfd
.events
= POLLIN
;
2297 switch (poll(&pollfd
, 1, -1))
2301 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2303 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2304 fprintf(stderr
, "Gdb hung up\n");
2305 /* kill also debuggee process - questionnable - */
2306 detach_debuggee(&gdbctx
, TRUE
);
2310 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2312 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2316 /* timeout, should never happen (infinite timeout) */
2319 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2320 fprintf(stderr
, "Poll failed\n");
2330 int gdb_main(int argc
, char* argv
[])
2333 unsigned gdb_flags
= 0;
2336 while (argc
> 0 && argv
[0][0] == '-')
2338 if (strcmp(argv
[0], "--no-start") == 0)
2340 gdb_flags
|= FLAG_NO_START
;
2344 if (strcmp(argv
[0], "--with-xterm") == 0)
2346 gdb_flags
|= FLAG_WITH_XTERM
;
2352 if (dbg_active_attach(argc
, argv
) == start_ok
||
2353 dbg_active_launch(argc
, argv
) == start_ok
)
2354 return gdb_remote(gdb_flags
);
2356 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");