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
)
488 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
490 switch (de
->dwDebugEventCode
)
492 case CREATE_PROCESS_DEBUG_EVENT
:
493 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
494 de
->u
.CreateProcessInfo
.hProcess
);
495 if (!gdbctx
->process
) break;
496 memory_get_string_indirect(gdbctx
->process
,
497 de
->u
.CreateProcessInfo
.lpImageName
,
498 de
->u
.CreateProcessInfo
.fUnicode
,
499 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
500 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
502 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
503 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
504 de
->dwProcessId
, de
->dwThreadId
,
505 dbg_W2A(u
.buffer
, -1),
506 de
->u
.CreateProcessInfo
.lpImageName
,
507 de
->u
.CreateProcessInfo
.lpStartAddress
,
508 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
509 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
511 /* de->u.CreateProcessInfo.lpStartAddress; */
512 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
513 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
515 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
516 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
517 de
->dwProcessId
, de
->dwThreadId
,
518 de
->u
.CreateProcessInfo
.lpStartAddress
);
520 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
521 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
522 de
->u
.CreateProcessInfo
.hThread
,
523 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
526 case LOAD_DLL_DEBUG_EVENT
:
527 assert(dbg_curr_thread
);
528 memory_get_string_indirect(gdbctx
->process
,
529 de
->u
.LoadDll
.lpImageName
,
530 de
->u
.LoadDll
.fUnicode
,
531 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
532 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
533 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
534 de
->dwProcessId
, de
->dwThreadId
,
535 dbg_W2A(u
.buffer
, -1),
536 de
->u
.LoadDll
.lpBaseOfDll
,
537 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
538 de
->u
.LoadDll
.nDebugInfoSize
);
539 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
540 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
543 case UNLOAD_DLL_DEBUG_EVENT
:
544 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
545 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
546 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
547 SymUnloadModule(gdbctx
->process
->handle
,
548 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
551 case EXCEPTION_DEBUG_EVENT
:
552 assert(dbg_curr_thread
);
553 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
554 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
555 de
->dwProcessId
, de
->dwThreadId
,
556 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
558 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
560 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
564 case CREATE_THREAD_DEBUG_EVENT
:
565 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
566 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
567 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
569 dbg_add_thread(gdbctx
->process
,
571 de
->u
.CreateThread
.hThread
,
572 de
->u
.CreateThread
.lpThreadLocalBase
);
575 case EXIT_THREAD_DEBUG_EVENT
:
576 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
577 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
578 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
580 assert(dbg_curr_thread
);
581 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
582 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
583 dbg_del_thread(dbg_curr_thread
);
586 case EXIT_PROCESS_DEBUG_EVENT
:
587 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
588 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
589 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
591 dbg_del_process(gdbctx
->process
);
592 gdbctx
->process
= NULL
;
593 /* now signal gdb that we're done */
594 gdbctx
->last_sig
= SIGTERM
;
595 gdbctx
->in_trap
= TRUE
;
598 case OUTPUT_DEBUG_STRING_EVENT
:
599 assert(dbg_curr_thread
);
600 memory_get_string(gdbctx
->process
,
601 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
602 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
603 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
604 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
605 de
->dwProcessId
, de
->dwThreadId
, u
.bufferA
);
609 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
610 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
611 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
612 de
->u
.RipInfo
.dwType
);
616 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
617 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
618 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
622 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
626 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
627 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
628 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
629 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
630 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
631 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
632 dbg_curr_thread
->tid
, cont
);
634 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
635 fprintf(stderr
, "Cannot find last thread\n");
639 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
644 if(dbg_curr_thread
->tid
== threadid
){
645 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
646 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
647 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
648 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
649 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
650 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
651 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
652 dbg_curr_thread
->tid
, cont
);
655 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
656 fprintf(stderr
, "Cannot find last thread\n");
659 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
661 struct pollfd pollfd
;
665 pollfd
.fd
= gdbctx
->sock
;
666 pollfd
.events
= POLLIN
;
669 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
670 ret
= read(gdbctx
->sock
, &pkt
, 1);
672 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
673 fprintf(stderr
, "read failed\n");
678 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
679 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
684 } else if (ret
== -1) {
685 fprintf(stderr
, "poll failed\n");
690 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
694 gdbctx
->in_trap
= FALSE
;
697 if (!WaitForDebugEvent(&de
, 10))
699 if (GetLastError() == ERROR_SEM_TIMEOUT
)
701 if (check_for_interrupt(gdbctx
)) {
702 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
703 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
704 fprintf(stderr
, "Failed to break into debugee\n");
708 WaitForDebugEvent(&de
, INFINITE
);
716 handle_debug_event(gdbctx
, &de
);
717 assert(!gdbctx
->process
||
718 gdbctx
->process
->pid
== 0 ||
719 de
.dwProcessId
== gdbctx
->process
->pid
);
720 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
721 if (gdbctx
->in_trap
) break;
722 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
726 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
728 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
729 resume_debuggee(gdbctx
, DBG_CONTINUE
);
731 DebugActiveProcessStop(gdbctx
->process
->pid
);
732 dbg_del_process(gdbctx
->process
);
733 gdbctx
->process
= NULL
;
736 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
740 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
742 strcpy(buffer
, "Unknown process");
745 if (status
== STILL_ACTIVE
)
747 strcpy(buffer
, "Running");
750 snprintf(buffer
, len
, "Terminated (%u)", status
);
752 switch (GetPriorityClass(gdbctx
->process
->handle
))
755 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
756 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
758 #ifdef BELOW_NORMAL_PRIORITY_CLASS
759 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
761 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
762 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
763 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
764 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
766 strcat(buffer
, "\n");
769 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
770 char* buffer
, size_t len
)
772 struct dbg_thread
* thd
;
776 /* FIXME: use the size of buffer */
777 thd
= dbg_get_thread(gdbctx
->process
, tid
);
780 strcpy(buffer
, "No information");
783 if (GetExitCodeThread(thd
->handle
, &status
))
785 if (status
== STILL_ACTIVE
)
787 /* FIXME: this is a bit brutal... some nicer way shall be found */
788 switch (status
= SuspendThread(thd
->handle
))
791 case 0: strcpy(buffer
, "Running"); break;
792 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
794 ResumeThread(thd
->handle
);
797 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
801 strcpy(buffer
, "Unknown threadID");
803 switch (prio
= GetThreadPriority(thd
->handle
))
805 case THREAD_PRIORITY_ERROR_RETURN
: break;
806 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
807 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
808 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
809 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
810 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
811 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
812 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
813 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
815 assert(strlen(buffer
) < len
);
818 /* =============================================== *
819 * P A C K E T U T I L S *
820 * =============================================== *
823 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
824 packet_last_f
= 0x80};
826 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
828 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
830 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
831 gdbctx
->out_buf
= realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
835 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
837 packet_reply_grow(gdbctx
, len
* 2);
838 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
839 gdbctx
->out_len
+= len
* 2;
842 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
844 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
847 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
851 shift
= (len
- 1) * 8;
852 packet_reply_grow(gdbctx
, len
* 2);
853 for (i
= 0; i
< len
; i
++, shift
-= 8)
855 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
856 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
860 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
862 packet_reply_grow(gdbctx
, len
);
863 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
864 gdbctx
->out_len
+= len
;
867 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
869 packet_reply_add(gdbctx
, str
, strlen(str
));
872 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
874 packet_reply_add(gdbctx
, &ch
, 1);
877 static void packet_reply_open(struct gdb_context
* gdbctx
)
879 assert(gdbctx
->out_curr_packet
== -1);
880 packet_reply_catc(gdbctx
, '$');
881 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
884 static void packet_reply_close(struct gdb_context
* gdbctx
)
889 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
890 packet_reply_catc(gdbctx
, '#');
891 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
892 packet_reply_hex_to(gdbctx
, &cksum
, 1);
893 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
894 fprintf(stderr
, "Reply : %*.*s\n",
895 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
896 gdbctx
->out_curr_packet
= -1;
899 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
901 packet_reply_open(gdbctx
);
903 if (len
== -1) len
= strlen(packet
);
904 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
906 packet_reply_add(gdbctx
, packet
, len
);
908 packet_reply_close(gdbctx
);
913 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
915 packet_reply_open(gdbctx
);
917 packet_reply_add(gdbctx
, "E", 1);
918 packet_reply_val(gdbctx
, error
, 1);
920 packet_reply_close(gdbctx
);
925 /* =============================================== *
926 * P A C K E T H A N D L E R S *
927 * =============================================== *
930 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
932 enum packet_return ret
= packet_done
;
934 packet_reply_open(gdbctx
);
936 if (gdbctx
->process
!= NULL
)
941 packet_reply_catc(gdbctx
, 'T');
942 sig
= gdbctx
->last_sig
;
943 packet_reply_val(gdbctx
, sig
, 1);
944 packet_reply_add(gdbctx
, "thread:", 7);
945 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
946 packet_reply_catc(gdbctx
, ';');
948 for (i
= 0; i
< cpu_num_regs
; i
++)
950 /* FIXME: this call will also grow the buffer...
951 * unneeded, but not harmful
953 packet_reply_val(gdbctx
, i
, 1);
954 packet_reply_catc(gdbctx
, ':');
955 packet_reply_hex_to(gdbctx
, cpu_register(&gdbctx
->context
, i
), 4);
956 packet_reply_catc(gdbctx
, ';');
961 /* Try to put an exit code
962 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
963 * just indicate the end of process and exit */
964 packet_reply_add(gdbctx
, "W00", 3);
965 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
968 packet_reply_close(gdbctx
);
974 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
976 gdbctx
->extended
= 1;
981 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
983 assert(gdbctx
->in_packet_len
== 0);
984 return packet_reply_status(gdbctx
);
987 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
989 /* FIXME: add support for address in packet */
990 assert(gdbctx
->in_packet_len
== 0);
991 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
992 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
993 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
994 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
995 resume_debuggee(gdbctx
, DBG_CONTINUE
);
996 wait_for_debuggee(gdbctx
);
997 return packet_reply_status(gdbctx
);
1000 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1003 int defaultAction
= -1; /* magic non action */
1006 int actionIndex
[20]; /* allow for up to 20 actions */
1007 int threadIndex
[20];
1008 int threadCount
= 0;
1009 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1010 unsigned int threadID
= 0;
1011 struct dbg_thread
* thd
;
1014 assert(gdbctx
->in_packet_len
>= 4);
1016 /* OK we have vCont followed by..
1018 * c for packet_continue
1019 * Csig for packet_continue_signal
1021 * Ssig for step signal
1022 * and then an optional thread ID at the end..
1023 * *******************************************/
1025 fprintf(stderr
, "trying to process a verbose packet\n");
1026 /* now check that we've got Cont */
1027 assert(strncmp(gdbctx
->in_packet
, "Cont", 4) == 0);
1030 if (gdbctx
->in_packet
[4] == '?')
1035 The vCont packet is supported. Each action is a supported command in the vCont packet.
1037 The vCont packet is not supported. (this didn't seem to be obeyed!)
1039 packet_reply_open(gdbctx
);
1040 packet_reply_add(gdbctx
, "vCont", 5);
1041 /* add all the supported actions to the reply (all of them for now) */
1042 packet_reply_add(gdbctx
, ";c", 2);
1043 packet_reply_add(gdbctx
, ";C", 2);
1044 packet_reply_add(gdbctx
, ";s", 2);
1045 packet_reply_add(gdbctx
, ";S", 2);
1046 packet_reply_close(gdbctx
);
1050 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1051 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1052 now if only gdb talked XML.... */
1053 #if 0 /* handy for debugging */
1054 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1057 /* go through the packet and identify where all the actions start at */
1058 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1060 if (gdbctx
->in_packet
[i
] == ';')
1062 threadIndex
[actions
] = 0;
1063 actionIndex
[actions
++] = i
;
1065 else if (gdbctx
->in_packet
[i
] == ':')
1067 threadIndex
[actions
- 1] = i
;
1071 /* now look up the default action */
1072 for (i
= 0 ; i
< actions
; i
++)
1074 if (threadIndex
[i
] == 0)
1076 if (defaultAction
!= -1)
1078 fprintf(stderr
,"Too many default actions specified\n");
1079 return packet_error
;
1085 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1087 /* go through all the threads and stick their ids in the to be done list. */
1088 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1090 threadIDs
[threadCount
++] = thd
->tid
;
1091 /* check to see if we have more threads than I counted on, and tell the user what to do
1092 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1093 if (threadCount
== 100)
1095 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1100 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1101 * that remains is to apply the actions to the threads and the default action to any threads
1103 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1104 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1105 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1106 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1108 /* deal with the threaded stuff first */
1109 for (i
= 0; i
< actions
; i
++)
1111 if (threadIndex
[i
] != 0)
1113 int j
, idLength
= 0;
1114 if (i
< actions
- 1)
1116 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1120 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1123 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1124 /* process the action */
1125 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1127 case 's': /* step */
1128 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1130 case 'c': /* continue */
1131 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1133 case 'S': /* step Sig, */
1134 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1136 case 'C': /* continue sig */
1137 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1138 /* cannot change signals on the fly */
1139 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1140 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1141 if (sig
!= gdbctx
->last_sig
)
1142 return packet_error
;
1143 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1146 for (j
= 0 ; j
< threadCount
; j
++)
1148 if (threadIDs
[j
] == threadID
)
1155 } /* for i=0 ; i< actions */
1157 /* now we have manage the default action */
1158 if (defaultAction
>= 0)
1160 for (i
= 0 ; i
< threadCount
; i
++)
1162 /* check to see if we've already done something to the thread*/
1163 if (threadIDs
[i
] != 0)
1165 /* if not apply the default action*/
1166 threadID
= threadIDs
[i
];
1167 /* process the action (yes this is almost identical to the one above!) */
1168 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1170 case 's': /* step */
1171 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1173 case 'c': /* continue */
1174 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1177 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1179 case 'C': /* continue sig */
1180 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1181 /* cannot change signals on the fly */
1182 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1183 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1184 if (sig
!= gdbctx
->last_sig
)
1185 return packet_error
;
1186 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1191 } /* if(defaultAction >=0) */
1193 wait_for_debuggee(gdbctx
);
1194 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1195 return packet_reply_status(gdbctx
);
1198 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1202 /* FIXME: add support for address in packet */
1203 assert(gdbctx
->in_packet_len
== 2);
1204 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1205 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1206 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1207 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1208 hex_from(&sig
, gdbctx
->in_packet
, 1);
1209 /* cannot change signals on the fly */
1210 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1211 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1212 if (sig
!= gdbctx
->last_sig
)
1213 return packet_error
;
1214 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1215 wait_for_debuggee(gdbctx
);
1216 return packet_reply_status(gdbctx
);
1219 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1221 detach_debuggee(gdbctx
, FALSE
);
1222 return packet_ok
| packet_last_f
;
1225 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1229 CONTEXT
* pctx
= &gdbctx
->context
;
1231 assert(gdbctx
->in_trap
);
1233 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1235 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1236 return packet_error
;
1239 packet_reply_open(gdbctx
);
1240 for (i
= 0; i
< cpu_num_regs
; i
++)
1242 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, i
), 4);
1244 packet_reply_close(gdbctx
);
1248 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1252 CONTEXT
* pctx
= &gdbctx
->context
;
1254 assert(gdbctx
->in_trap
);
1255 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1257 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1258 return packet_error
;
1260 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1262 for (i
= 0; i
< cpu_num_regs
; i
++)
1263 hex_from(cpu_register(pctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
1264 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1266 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1267 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1268 return packet_error
;
1273 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1275 detach_debuggee(gdbctx
, TRUE
);
1277 if (!gdbctx
->extended
)
1278 /* dunno whether GDB cares or not */
1282 /* assume we can't really answer something here */
1283 /* return packet_done; */
1286 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1291 switch (gdbctx
->in_packet
[0])
1295 if (gdbctx
->in_packet
[1] == '-')
1296 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1298 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1299 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1301 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1302 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1303 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1304 gdbctx
->in_packet
+ 1);
1305 return packet_error
;
1307 if (gdbctx
->in_packet
[0] == 'c')
1308 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1310 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1313 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1314 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1315 return packet_error
;
1319 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1322 unsigned int len
, blk_len
, nread
;
1326 assert(gdbctx
->in_trap
);
1327 /* FIXME:check in_packet_len for reading %p,%x */
1328 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1329 if (len
<= 0) return packet_error
;
1330 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1331 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1332 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1334 blk_len
= min(sizeof(buffer
), len
- nread
);
1335 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1338 /* fail at first address, return error */
1339 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1340 /* something has already been read, return partial information */
1343 if (nread
== 0) packet_reply_open(gdbctx
);
1344 packet_reply_hex_to(gdbctx
, buffer
, r
);
1346 packet_reply_close(gdbctx
);
1350 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1353 unsigned int len
, blk_len
;
1358 assert(gdbctx
->in_trap
);
1359 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1362 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1363 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1364 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1365 return packet_error
;
1369 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1371 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1372 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1373 return packet_error
;
1375 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1377 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1378 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1379 ptr
- gdbctx
->in_packet
+ len
* 2, gdbctx
->in_packet_len
);
1380 return packet_error
;
1382 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1383 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1386 blk_len
= min(sizeof(buffer
), len
);
1387 hex_from(buffer
, ptr
, blk_len
);
1388 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1395 return packet_ok
; /* FIXME: error while writing ? */
1398 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1402 CONTEXT
* pctx
= &gdbctx
->context
;
1404 assert(gdbctx
->in_trap
);
1405 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1406 if (reg
>= cpu_num_regs
)
1408 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1409 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1410 return packet_error
;
1412 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1414 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1415 return packet_error
;
1417 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1418 fprintf(stderr
, "Read register %x => %lx\n", reg
, *cpu_register(pctx
, reg
));
1419 packet_reply_open(gdbctx
);
1420 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, reg
), 4);
1421 packet_reply_close(gdbctx
);
1425 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1431 CONTEXT
* pctx
= &gdbctx
->context
;
1433 assert(gdbctx
->in_trap
);
1435 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1437 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1438 if (end
== NULL
|| reg
> cpu_num_regs
)
1440 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1441 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1442 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1443 * it wouldn't matter too much, and it fakes our support for all regs
1445 return (end
== NULL
) ? packet_error
: packet_ok
;
1447 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1449 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1450 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1451 ptr
+ 8 - gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1452 return packet_error
;
1454 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1455 fprintf(stderr
, "Writing reg %u <= %*.*s\n",
1456 reg
, gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
),
1457 gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
), ptr
);
1459 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1461 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1462 return packet_error
;
1465 hex_from(cpu_register(pctx
, reg
), ptr
, 4);
1466 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1468 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1469 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1470 return packet_error
;
1476 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1484 if (!GetClassName(hWnd
, clsName
, sizeof(clsName
)))
1485 strcpy(clsName
, "-- Unknown --");
1486 if (!GetWindowText(hWnd
, wndName
, sizeof(wndName
)))
1487 strcpy(wndName
, "-- Empty --");
1489 packet_reply_open(gdbctx
);
1490 packet_reply_catc(gdbctx
, 'O');
1491 snprintf(buffer
, sizeof(buffer
),
1492 "%*s%04lx%*s%-17.17s %08x %08x %.14s\n",
1493 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1494 clsName
, GetWindowLong(hWnd
, GWL_STYLE
),
1495 GetWindowLongPtr(hWnd
, GWLP_WNDPROC
), wndName
);
1496 packet_reply_hex_to_str(gdbctx
, buffer
);
1497 packet_reply_close(gdbctx
);
1499 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1500 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1501 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1504 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1508 /* we do the output in several 'O' packets, with the last one being just OK for
1509 * marking the end of the output */
1510 packet_reply_open(gdbctx
);
1511 packet_reply_catc(gdbctx
, 'O');
1512 snprintf(buffer
, sizeof(buffer
),
1513 "%-16.16s %-17.17s %-8.8s %s\n",
1514 "hwnd", "Class Name", " Style", " WndProc Text");
1515 packet_reply_hex_to_str(gdbctx
, buffer
);
1516 packet_reply_close(gdbctx
);
1518 /* FIXME: could also add a pmt to this command in str... */
1519 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1520 packet_reply(gdbctx
, "OK", 2);
1523 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1525 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1528 PROCESSENTRY32 entry
;
1531 if (snap
== INVALID_HANDLE_VALUE
)
1534 entry
.dwSize
= sizeof(entry
);
1535 ok
= Process32First(snap
, &entry
);
1537 /* we do the output in several 'O' packets, with the last one being just OK for
1538 * marking the end of the output */
1540 packet_reply_open(gdbctx
);
1541 packet_reply_catc(gdbctx
, 'O');
1542 snprintf(buffer
, sizeof(buffer
),
1543 " %-8.8s %-8.8s %-8.8s %s\n",
1544 "pid", "threads", "parent", "executable");
1545 packet_reply_hex_to_str(gdbctx
, buffer
);
1546 packet_reply_close(gdbctx
);
1551 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1552 packet_reply_open(gdbctx
);
1553 packet_reply_catc(gdbctx
, 'O');
1554 snprintf(buffer
, sizeof(buffer
),
1555 "%c%08x %-8d %08x '%s'\n",
1556 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1557 entry
.th32ParentProcessID
, entry
.szExeFile
);
1558 packet_reply_hex_to_str(gdbctx
, buffer
);
1559 packet_reply_close(gdbctx
);
1560 ok
= Process32Next(snap
, &entry
);
1563 packet_reply(gdbctx
, "OK", 2);
1566 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1568 MEMORY_BASIC_INFORMATION mbi
;
1575 /* we do the output in several 'O' packets, with the last one being just OK for
1576 * marking the end of the output */
1577 packet_reply_open(gdbctx
);
1578 packet_reply_catc(gdbctx
, 'O');
1579 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1580 packet_reply_close(gdbctx
);
1582 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1586 case MEM_COMMIT
: state
= "commit "; break;
1587 case MEM_FREE
: state
= "free "; break;
1588 case MEM_RESERVE
: state
= "reserve"; break;
1589 default: state
= "??? "; break;
1591 if (mbi
.State
!= MEM_FREE
)
1595 case MEM_IMAGE
: type
= "image "; break;
1596 case MEM_MAPPED
: type
= "mapped "; break;
1597 case MEM_PRIVATE
: type
= "private"; break;
1598 case 0: type
= " "; break;
1599 default: type
= "??? "; break;
1601 memset(prot
, ' ' , sizeof(prot
)-1);
1602 prot
[sizeof(prot
)-1] = '\0';
1603 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1605 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1607 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1609 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1617 packet_reply_open(gdbctx
);
1618 snprintf(buffer
, sizeof(buffer
), "%08lx %08lx %s %s %s\n",
1619 (DWORD_PTR
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1620 packet_reply_catc(gdbctx
, 'O');
1621 packet_reply_hex_to_str(gdbctx
, buffer
);
1622 packet_reply_close(gdbctx
);
1624 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1626 addr
+= mbi
.RegionSize
;
1628 packet_reply(gdbctx
, "OK", 2);
1631 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1632 int len
, const char* str
)
1638 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1640 else if (len
>= 2 && str
[0] == '=')
1642 unsigned val
= atoi(&str
[1]);
1643 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1644 gdbctx
->trace
= val
;
1648 /* FIXME: ugly but can use error packet here */
1649 packet_reply_cat(gdbctx
, "E00");
1652 packet_reply_open(gdbctx
);
1653 packet_reply_hex_to_str(gdbctx
, buffer
);
1654 packet_reply_close(gdbctx
);
1662 void (*handler
)(struct gdb_context
*, int, const char*);
1665 {0, "wnd", 3, packet_query_monitor_wnd
},
1666 {0, "window", 6, packet_query_monitor_wnd
},
1667 {0, "proc", 4, packet_query_monitor_process
},
1668 {0, "process", 7, packet_query_monitor_process
},
1669 {0, "mem", 3, packet_query_monitor_mem
},
1670 {1, "trace", 5, packet_query_monitor_trace
},
1674 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1675 const char* hxcmd
, size_t len
)
1678 struct query_detail
* qd
;
1680 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1682 hex_from(buffer
, hxcmd
, len
);
1684 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1686 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1687 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1689 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1692 return packet_reply_error(gdbctx
, EINVAL
);
1695 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1697 switch (gdbctx
->in_packet
[0])
1700 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1702 struct dbg_thread
* thd
;
1704 packet_reply_open(gdbctx
);
1705 packet_reply_add(gdbctx
, "m", 1);
1706 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1708 packet_reply_val(gdbctx
, thd
->tid
, 4);
1709 if (thd
->next
!= NULL
)
1710 packet_reply_add(gdbctx
, ",", 1);
1712 packet_reply_close(gdbctx
);
1715 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1719 packet_reply_open(gdbctx
);
1720 packet_reply_catc(gdbctx
, 'O');
1721 get_process_info(gdbctx
, result
, sizeof(result
));
1722 packet_reply_hex_to_str(gdbctx
, result
);
1723 packet_reply_close(gdbctx
);
1728 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1730 packet_reply(gdbctx
, "l", 1);
1733 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1735 packet_reply(gdbctx
, "l", 1);
1740 if (gdbctx
->in_packet_len
== 1)
1742 struct dbg_thread
* thd
;
1743 /* FIXME: doc says 16 bit val ??? */
1744 /* grab first created thread, aka last in list */
1745 assert(gdbctx
->process
&& gdbctx
->process
->threads
);
1746 for (thd
= gdbctx
->process
->threads
; thd
->next
; thd
= thd
->next
);
1747 packet_reply_open(gdbctx
);
1748 packet_reply_add(gdbctx
, "QC", 2);
1749 packet_reply_val(gdbctx
, thd
->tid
, 4);
1750 packet_reply_close(gdbctx
);
1755 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1759 if (gdbctx
->wine_segs
[0] == 0 && gdbctx
->wine_segs
[1] == 0 &&
1760 gdbctx
->wine_segs
[2] == 0)
1761 return packet_error
;
1762 snprintf(buf
, sizeof(buf
),
1763 "Text=%08lx;Data=%08lx;Bss=%08lx",
1764 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1765 gdbctx
->wine_segs
[2]);
1766 return packet_reply(gdbctx
, buf
, -1);
1770 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1772 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1773 gdbctx
->in_packet_len
- 5);
1777 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1779 if (strncmp(gdbctx
->in_packet
, "Supported", gdbctx
->in_packet_len
) == 0)
1781 packet_reply_open(gdbctx
);
1782 packet_reply_close(gdbctx
);
1787 if (gdbctx
->in_packet_len
> 15 &&
1788 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1789 gdbctx
->in_packet
[15] == ',')
1795 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1796 if (end
== NULL
) break;
1797 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1798 packet_reply_open(gdbctx
);
1799 packet_reply_hex_to_str(gdbctx
, result
);
1800 packet_reply_close(gdbctx
);
1805 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1806 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1807 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1808 return packet_error
;
1811 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1813 /* FIXME: add support for address in packet */
1814 assert(gdbctx
->in_packet_len
== 0);
1815 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1816 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1817 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
1818 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1819 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1820 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1821 wait_for_debuggee(gdbctx
);
1822 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1823 return packet_reply_status(gdbctx
);
1827 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1831 /* FIXME: add support for address in packet */
1832 assert(gdbctx
->in_packet_len
== 2);
1833 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1834 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1835 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1836 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1837 hex_from(&sig
, gdbctx
->in_packet
, 1);
1838 /* cannot change signals on the fly */
1839 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1840 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1841 if (sig
!= gdbctx
->last_sig
)
1842 return packet_error
;
1843 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1844 wait_for_debuggee(gdbctx
);
1845 return packet_reply_status(gdbctx
);
1849 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1854 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1855 if (tid
== -1 || tid
== 0)
1856 return packet_reply_error(gdbctx
, EINVAL
);
1857 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1859 return packet_reply_error(gdbctx
, ESRCH
);
1862 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1866 struct gdb_ctx_Xpoint
* xpt
;
1867 enum be_xpoint_type t
;
1869 /* FIXME: check packet_len */
1870 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1871 gdbctx
->in_packet
[1] != ',' ||
1872 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1873 return packet_error
;
1874 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1875 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1876 addr
, len
, gdbctx
->in_packet
[0]);
1877 switch (gdbctx
->in_packet
[0])
1879 case '0': t
= be_xpoint_break
; len
= 0; break;
1880 case '1': t
= be_xpoint_watch_exec
; break;
1881 case '2': t
= be_xpoint_watch_read
; break;
1882 case '3': t
= be_xpoint_watch_write
; break;
1883 default: return packet_error
;
1885 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1887 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1889 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
1890 gdbctx
->process
->process_io
, &gdbctx
->context
,
1891 t
, xpt
->addr
, xpt
->val
, len
))
1899 return packet_error
;
1902 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1906 struct gdb_ctx_Xpoint
* xpt
;
1907 enum be_xpoint_type t
;
1909 /* FIXME: check packet_len */
1910 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1911 gdbctx
->in_packet
[1] != ',' ||
1912 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1913 return packet_error
;
1914 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1915 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
1916 addr
, len
, gdbctx
->in_packet
[0]);
1917 switch (gdbctx
->in_packet
[0])
1919 case '0': t
= be_xpoint_break
; len
= 0; break;
1920 case '1': t
= be_xpoint_watch_exec
; break;
1921 case '2': t
= be_xpoint_watch_read
; break;
1922 case '3': t
= be_xpoint_watch_write
; break;
1923 default: return packet_error
;
1925 /* because of packet command handling, this should be made idempotent */
1926 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1928 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1929 return packet_ok
; /* nothing to do */
1931 /* really set the Xpoint */
1932 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1934 if (xpt
->type
== -1)
1936 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
1937 gdbctx
->process
->process_io
, &gdbctx
->context
,
1938 t
, addr
, &xpt
->val
, len
))
1944 fprintf(stderr
, "cannot set xpoint\n");
1948 /* no more entries... eech */
1949 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
1950 return packet_error
;
1953 /* =============================================== *
1954 * P A C K E T I N F R A S T R U C T U R E *
1955 * =============================================== *
1961 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1964 static struct packet_entry packet_entries
[] =
1966 /*{'!', packet_extended}, */
1967 {'?', packet_last_signal
},
1968 {'c', packet_continue
},
1969 {'C', packet_continue_signal
},
1970 {'D', packet_detach
},
1971 {'g', packet_read_registers
},
1972 {'G', packet_write_registers
},
1974 {'H', packet_thread
},
1975 {'m', packet_read_memory
},
1976 {'M', packet_write_memory
},
1977 {'p', packet_read_register
},
1978 {'P', packet_write_register
},
1979 {'q', packet_query
},
1980 /* {'Q', packet_set}, */
1981 /* {'R', packet,restart}, only in extended mode ! */
1983 /*{'S', packet_step_signal}, hard(er) to implement */
1984 {'T', packet_thread_alive
},
1985 {'v', packet_verbose
},
1986 {'z', packet_remove_breakpoint
},
1987 {'Z', packet_set_breakpoint
},
1990 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
1994 unsigned char in_cksum
, loc_cksum
;
1996 enum packet_return ret
= packet_error
;
1999 while ((ret
& packet_last_f
) == 0)
2001 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2002 fprintf(stderr
, "In-buf: %*.*s\n",
2003 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2004 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2005 if (ptr
== NULL
) return FALSE
;
2006 if (ptr
!= gdbctx
->in_buf
)
2008 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2009 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2010 fprintf(stderr
, "Removing garbage: %*.*s\n",
2011 glen
, glen
, gdbctx
->in_buf
);
2012 gdbctx
->in_len
-= glen
;
2013 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2015 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2016 if (end
== NULL
) return FALSE
;
2017 /* no checksum yet */
2018 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2019 plen
= end
- gdbctx
->in_buf
- 1;
2020 hex_from(&in_cksum
, end
+ 1, 1);
2021 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2022 if (loc_cksum
== in_cksum
)
2024 if (num_packet
== 0) {
2029 write(gdbctx
->sock
, "+", 1);
2032 /* FIXME: should use bsearch if packet_entries was sorted */
2033 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2035 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2037 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2039 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2040 fprintf(stderr
, "Unknown packet request %*.*s\n",
2041 plen
, plen
, &gdbctx
->in_buf
[1]);
2045 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2046 gdbctx
->in_packet_len
= plen
- 1;
2047 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2048 fprintf(stderr
, "Packet: %c%*.*s\n",
2050 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2052 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2054 switch (ret
& ~packet_last_f
)
2056 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2057 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2058 case packet_done
: break;
2060 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2061 fprintf(stderr
, "Reply-full: %*.*s\n",
2062 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2063 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2064 assert(i
== gdbctx
->out_len
);
2065 /* if this fails, we'll have to use POLLOUT...
2067 gdbctx
->out_len
= 0;
2072 /* FIXME: if we have in our input buffer more than one packet,
2073 * it's very likely that we took too long to answer to a given packet
2074 * and gdb is sending us again the same packet
2075 * We simply drop the second packet. This will lower the risk of error,
2076 * but there's still some race conditions here
2077 * A better fix (yet not perfect) would be to have two threads:
2078 * - one managing the packets for gdb
2079 * - the second one managing the commands...
2080 * This would allow us also the reply with the '+' character (Ack of
2081 * the command) way sooner than what we do now
2083 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2084 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2089 write(gdbctx
->sock
, "+", 1);
2090 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2091 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2093 gdbctx
->in_len
-= plen
+ 4;
2094 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2099 static int fetch_data(struct gdb_context
* gdbctx
)
2101 int len
, in_len
= gdbctx
->in_len
;
2103 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2107 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2108 gdbctx
->in_buf
= realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2110 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2111 fprintf(stderr
, "%d %d %*.*s\n",
2112 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2113 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2114 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2115 if (len
<= 0) break;
2116 gdbctx
->in_len
+= len
;
2117 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2118 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2120 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2121 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2122 return gdbctx
->in_len
- in_len
;
2125 #define FLAG_NO_START 1
2126 #define FLAG_WITH_XTERM 2
2128 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2132 const char* gdb_path
;
2135 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2136 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2137 fd
= mkstemps(buf
, 0);
2138 if (fd
== -1) return FALSE
;
2139 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2140 fprintf(f
, "file %s\n", wine_path
);
2141 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2142 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2143 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2144 /* gdb 5.1 seems to require it, won't hurt anyway */
2145 fprintf(f
, "sharedlibrary\n");
2146 /* This is needed (but not a decent & final fix)
2147 * Without this, gdb would skip our inter-DLL relay code (because
2148 * we don't have any line number information for the relay code)
2149 * With this, we will stop on first instruction of the stub, and
2150 * reusing step, will get us through the relay stub at the actual
2151 * function we're looking at.
2153 fprintf(f
, "set step-mode on\n");
2154 /* tell gdb to delete this file when done handling it... */
2155 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2157 if (flags
& FLAG_WITH_XTERM
)
2158 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2160 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2161 assert(0); /* never reached */
2165 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2168 struct sockaddr_in s_addrs
;
2169 unsigned int s_len
= sizeof(s_addrs
);
2170 struct pollfd pollfd
;
2171 IMAGEHLP_MODULE imh_mod
;
2173 /* step 1: create socket for gdb connection request */
2174 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2176 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2177 fprintf(stderr
, "Can't create socket");
2181 if (listen(sock
, 1) == -1 ||
2182 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2185 /* step 2: do the process internal creation */
2186 handle_debug_event(gdbctx
, de
);
2188 /* step3: get the wine loader name */
2189 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
)) return FALSE
;
2191 /* step 4: fire up gdb (if requested) */
2192 if (flags
& FLAG_NO_START
)
2193 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2197 case -1: /* error in parent... */
2198 fprintf(stderr
, "Cannot create gdb\n");
2200 default: /* in parent... success */
2202 case 0: /* in child... and alive */
2203 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2204 /* if we're here, exec failed, so report failure */
2208 /* step 5: wait for gdb to connect actually */
2210 pollfd
.events
= POLLIN
;
2213 switch (poll(&pollfd
, 1, -1))
2216 if (pollfd
.revents
& POLLIN
)
2219 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2220 if (gdbctx
->sock
== -1)
2222 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2223 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2224 /* don't keep our small packets too long: send them ASAP back to GDB
2225 * without this, GDB really crawls
2227 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2231 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2232 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2235 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2236 fprintf(stderr
, "Poll for cnx failed (error)\n");
2246 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2252 gdbctx
->in_buf
= NULL
;
2253 gdbctx
->in_buf_alloc
= 0;
2255 gdbctx
->out_buf
= NULL
;
2256 gdbctx
->out_buf_alloc
= 0;
2257 gdbctx
->out_len
= 0;
2258 gdbctx
->out_curr_packet
= -1;
2260 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2261 gdbctx
->last_sig
= 0;
2262 gdbctx
->in_trap
= FALSE
;
2263 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2264 gdbctx
->process
= NULL
;
2265 for (i
= 0; i
< NUM_XPOINT
; i
++)
2266 gdbctx
->Xpoints
[i
].type
= -1;
2268 /* wait for first trap */
2269 while (WaitForDebugEvent(&de
, INFINITE
))
2271 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2273 /* this should be the first event we get,
2274 * and the only one of this type */
2275 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2276 /* gdbctx->dwProcessId = pid; */
2277 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2278 assert(!gdbctx
->in_trap
);
2282 handle_debug_event(gdbctx
, &de
);
2283 if (gdbctx
->in_trap
) break;
2285 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2290 static int gdb_remote(unsigned flags
)
2292 struct pollfd pollfd
;
2293 struct gdb_context gdbctx
;
2296 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2298 pollfd
.fd
= gdbctx
.sock
;
2299 pollfd
.events
= POLLIN
;
2302 switch (poll(&pollfd
, 1, -1))
2306 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2308 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2309 fprintf(stderr
, "Gdb hung up\n");
2310 /* kill also debuggee process - questionnable - */
2311 detach_debuggee(&gdbctx
, TRUE
);
2315 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2317 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2321 /* timeout, should never happen (infinite timeout) */
2324 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2325 fprintf(stderr
, "Poll failed\n");
2335 int gdb_main(int argc
, char* argv
[])
2338 unsigned gdb_flags
= 0;
2341 while (argc
> 0 && argv
[0][0] == '-')
2343 if (strcmp(argv
[0], "--no-start") == 0)
2345 gdb_flags
|= FLAG_NO_START
;
2349 if (strcmp(argv
[0], "--with-xterm") == 0)
2351 gdb_flags
|= FLAG_WITH_XTERM
;
2357 if (dbg_active_attach(argc
, argv
) == start_ok
||
2358 dbg_active_launch(argc
, argv
) == start_ok
)
2359 return gdb_remote(gdb_flags
);
2361 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");