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 char* packet_realloc(char* buf
, int size
)
829 return HeapAlloc(GetProcessHeap(), 0, size
);
830 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
834 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
836 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
838 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
839 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
843 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
845 packet_reply_grow(gdbctx
, len
* 2);
846 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
847 gdbctx
->out_len
+= len
* 2;
850 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
852 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
855 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
859 shift
= (len
- 1) * 8;
860 packet_reply_grow(gdbctx
, len
* 2);
861 for (i
= 0; i
< len
; i
++, shift
-= 8)
863 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
864 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
868 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
870 packet_reply_grow(gdbctx
, len
);
871 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
872 gdbctx
->out_len
+= len
;
875 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
877 packet_reply_add(gdbctx
, str
, strlen(str
));
880 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
882 packet_reply_add(gdbctx
, &ch
, 1);
885 static void packet_reply_open(struct gdb_context
* gdbctx
)
887 assert(gdbctx
->out_curr_packet
== -1);
888 packet_reply_catc(gdbctx
, '$');
889 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
892 static void packet_reply_close(struct gdb_context
* gdbctx
)
897 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
898 packet_reply_catc(gdbctx
, '#');
899 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
900 packet_reply_hex_to(gdbctx
, &cksum
, 1);
901 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
902 fprintf(stderr
, "Reply : %*.*s\n",
903 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
904 gdbctx
->out_curr_packet
= -1;
907 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
909 packet_reply_open(gdbctx
);
911 if (len
== -1) len
= strlen(packet
);
912 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
914 packet_reply_add(gdbctx
, packet
, len
);
916 packet_reply_close(gdbctx
);
921 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
923 packet_reply_open(gdbctx
);
925 packet_reply_add(gdbctx
, "E", 1);
926 packet_reply_val(gdbctx
, error
, 1);
928 packet_reply_close(gdbctx
);
933 /* =============================================== *
934 * P A C K E T H A N D L E R S *
935 * =============================================== *
938 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
940 enum packet_return ret
= packet_done
;
942 packet_reply_open(gdbctx
);
944 if (gdbctx
->process
!= NULL
)
949 packet_reply_catc(gdbctx
, 'T');
950 sig
= gdbctx
->last_sig
;
951 packet_reply_val(gdbctx
, sig
, 1);
952 packet_reply_add(gdbctx
, "thread:", 7);
953 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
954 packet_reply_catc(gdbctx
, ';');
956 for (i
= 0; i
< cpu_num_regs
; i
++)
958 /* FIXME: this call will also grow the buffer...
959 * unneeded, but not harmful
961 packet_reply_val(gdbctx
, i
, 1);
962 packet_reply_catc(gdbctx
, ':');
963 packet_reply_hex_to(gdbctx
, cpu_register(&gdbctx
->context
, i
), 4);
964 packet_reply_catc(gdbctx
, ';');
969 /* Try to put an exit code
970 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
971 * just indicate the end of process and exit */
972 packet_reply_add(gdbctx
, "W00", 3);
973 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
976 packet_reply_close(gdbctx
);
982 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
984 gdbctx
->extended
= 1;
989 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
991 assert(gdbctx
->in_packet_len
== 0);
992 return packet_reply_status(gdbctx
);
995 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
997 /* FIXME: add support for address in packet */
998 assert(gdbctx
->in_packet_len
== 0);
999 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1000 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1001 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1002 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1003 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1004 wait_for_debuggee(gdbctx
);
1005 return packet_reply_status(gdbctx
);
1008 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1011 int defaultAction
= -1; /* magic non action */
1014 int actionIndex
[20]; /* allow for up to 20 actions */
1015 int threadIndex
[20];
1016 int threadCount
= 0;
1017 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1018 unsigned int threadID
= 0;
1019 struct dbg_thread
* thd
;
1022 assert(gdbctx
->in_packet_len
>= 4);
1024 /* OK we have vCont followed by..
1026 * c for packet_continue
1027 * Csig for packet_continue_signal
1029 * Ssig for step signal
1030 * and then an optional thread ID at the end..
1031 * *******************************************/
1033 fprintf(stderr
, "trying to process a verbose packet\n");
1034 /* now check that we've got Cont */
1035 assert(strncmp(gdbctx
->in_packet
, "Cont", 4) == 0);
1038 if (gdbctx
->in_packet
[4] == '?')
1043 The vCont packet is supported. Each action is a supported command in the vCont packet.
1045 The vCont packet is not supported. (this didn't seem to be obeyed!)
1047 packet_reply_open(gdbctx
);
1048 packet_reply_add(gdbctx
, "vCont", 5);
1049 /* add all the supported actions to the reply (all of them for now) */
1050 packet_reply_add(gdbctx
, ";c", 2);
1051 packet_reply_add(gdbctx
, ";C", 2);
1052 packet_reply_add(gdbctx
, ";s", 2);
1053 packet_reply_add(gdbctx
, ";S", 2);
1054 packet_reply_close(gdbctx
);
1058 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1059 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1060 now if only gdb talked XML.... */
1061 #if 0 /* handy for debugging */
1062 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1065 /* go through the packet and identify where all the actions start at */
1066 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1068 if (gdbctx
->in_packet
[i
] == ';')
1070 threadIndex
[actions
] = 0;
1071 actionIndex
[actions
++] = i
;
1073 else if (gdbctx
->in_packet
[i
] == ':')
1075 threadIndex
[actions
- 1] = i
;
1079 /* now look up the default action */
1080 for (i
= 0 ; i
< actions
; i
++)
1082 if (threadIndex
[i
] == 0)
1084 if (defaultAction
!= -1)
1086 fprintf(stderr
,"Too many default actions specified\n");
1087 return packet_error
;
1093 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1095 /* go through all the threads and stick their ids in the to be done list. */
1096 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1098 threadIDs
[threadCount
++] = thd
->tid
;
1099 /* check to see if we have more threads than I counted on, and tell the user what to do
1100 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1101 if (threadCount
== 100)
1103 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programms/winedgb/gdbproxy.c to be higher\n");
1108 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1109 * that remains is to apply the actions to the threads and the default action to any threads
1111 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1112 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1113 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1114 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1116 /* deal with the threaded stuff first */
1117 for (i
= 0; i
< actions
; i
++)
1119 if (threadIndex
[i
] != 0)
1121 int j
, idLength
= 0;
1122 if (i
< actions
- 1)
1124 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1128 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1131 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1132 /* process the action */
1133 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1135 case 's': /* step */
1136 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1138 case 'c': /* continue */
1139 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1141 case 'S': /* step Sig, */
1142 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1144 case 'C': /* continue sig */
1145 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1146 /* cannot change signals on the fly */
1147 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1148 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1149 if (sig
!= gdbctx
->last_sig
)
1150 return packet_error
;
1151 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1154 for (j
= 0 ; j
< threadCount
; j
++)
1156 if (threadIDs
[j
] == threadID
)
1163 } /* for i=0 ; i< actions */
1165 /* now we have manage the default action */
1166 if (defaultAction
>= 0)
1168 for (i
= 0 ; i
< threadCount
; i
++)
1170 /* check to see if we've already done something to the thread*/
1171 if (threadIDs
[i
] != 0)
1173 /* if not apply the default action*/
1174 threadID
= threadIDs
[i
];
1175 /* process the action (yes this is almost identical to the one above!) */
1176 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1178 case 's': /* step */
1179 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1181 case 'c': /* continue */
1182 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1185 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1187 case 'C': /* continue sig */
1188 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1189 /* cannot change signals on the fly */
1190 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1191 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1192 if (sig
!= gdbctx
->last_sig
)
1193 return packet_error
;
1194 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1199 } /* if(defaultAction >=0) */
1201 wait_for_debuggee(gdbctx
);
1202 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1203 return packet_reply_status(gdbctx
);
1206 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1210 /* FIXME: add support for address in packet */
1211 assert(gdbctx
->in_packet_len
== 2);
1212 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1213 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1214 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1215 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1216 hex_from(&sig
, gdbctx
->in_packet
, 1);
1217 /* cannot change signals on the fly */
1218 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1219 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1220 if (sig
!= gdbctx
->last_sig
)
1221 return packet_error
;
1222 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1223 wait_for_debuggee(gdbctx
);
1224 return packet_reply_status(gdbctx
);
1227 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1229 detach_debuggee(gdbctx
, FALSE
);
1230 return packet_ok
| packet_last_f
;
1233 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1237 CONTEXT
* pctx
= &gdbctx
->context
;
1239 assert(gdbctx
->in_trap
);
1241 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1243 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1244 return packet_error
;
1247 packet_reply_open(gdbctx
);
1248 for (i
= 0; i
< cpu_num_regs
; i
++)
1250 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, i
), 4);
1252 packet_reply_close(gdbctx
);
1256 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1260 CONTEXT
* pctx
= &gdbctx
->context
;
1262 assert(gdbctx
->in_trap
);
1263 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1265 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1266 return packet_error
;
1268 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1270 for (i
= 0; i
< cpu_num_regs
; i
++)
1271 hex_from(cpu_register(pctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
1272 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1274 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1275 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1276 return packet_error
;
1281 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1283 detach_debuggee(gdbctx
, TRUE
);
1285 if (!gdbctx
->extended
)
1286 /* dunno whether GDB cares or not */
1290 /* assume we can't really answer something here */
1291 /* return packet_done; */
1294 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1299 switch (gdbctx
->in_packet
[0])
1303 if (gdbctx
->in_packet
[1] == '-')
1304 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1306 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1307 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1309 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1310 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1311 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1312 gdbctx
->in_packet
+ 1);
1313 return packet_error
;
1315 if (gdbctx
->in_packet
[0] == 'c')
1316 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1318 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1321 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1322 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1323 return packet_error
;
1327 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1330 unsigned int len
, blk_len
, nread
;
1334 assert(gdbctx
->in_trap
);
1335 /* FIXME:check in_packet_len for reading %p,%x */
1336 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1337 if (len
<= 0) return packet_error
;
1338 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1339 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1340 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1342 blk_len
= min(sizeof(buffer
), len
- nread
);
1343 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1346 /* fail at first address, return error */
1347 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1348 /* something has already been read, return partial information */
1351 if (nread
== 0) packet_reply_open(gdbctx
);
1352 packet_reply_hex_to(gdbctx
, buffer
, r
);
1354 packet_reply_close(gdbctx
);
1358 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1361 unsigned int len
, blk_len
;
1366 assert(gdbctx
->in_trap
);
1367 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1370 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1371 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1372 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1373 return packet_error
;
1377 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1379 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1380 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1381 return packet_error
;
1383 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1385 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1386 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1387 ptr
- gdbctx
->in_packet
+ len
* 2, gdbctx
->in_packet_len
);
1388 return packet_error
;
1390 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1391 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1394 blk_len
= min(sizeof(buffer
), len
);
1395 hex_from(buffer
, ptr
, blk_len
);
1396 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1403 return packet_ok
; /* FIXME: error while writing ? */
1406 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1410 CONTEXT
* pctx
= &gdbctx
->context
;
1412 assert(gdbctx
->in_trap
);
1413 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1414 if (reg
>= cpu_num_regs
)
1416 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1417 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1418 return packet_error
;
1420 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1422 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1423 return packet_error
;
1425 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1426 fprintf(stderr
, "Read register %x => %lx\n", reg
, *cpu_register(pctx
, reg
));
1427 packet_reply_open(gdbctx
);
1428 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, reg
), 4);
1429 packet_reply_close(gdbctx
);
1433 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1439 CONTEXT
* pctx
= &gdbctx
->context
;
1441 assert(gdbctx
->in_trap
);
1443 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1445 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1446 if (end
== NULL
|| reg
> cpu_num_regs
)
1448 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1449 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1450 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1451 * it wouldn't matter too much, and it fakes our support for all regs
1453 return (end
== NULL
) ? packet_error
: packet_ok
;
1455 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1457 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1458 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1459 ptr
+ 8 - gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1460 return packet_error
;
1462 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1463 fprintf(stderr
, "Writing reg %u <= %*.*s\n",
1464 reg
, gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
),
1465 gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
), ptr
);
1467 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1469 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1470 return packet_error
;
1473 hex_from(cpu_register(pctx
, reg
), ptr
, 4);
1474 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1476 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1477 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1478 return packet_error
;
1484 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1492 if (!GetClassName(hWnd
, clsName
, sizeof(clsName
)))
1493 strcpy(clsName
, "-- Unknown --");
1494 if (!GetWindowText(hWnd
, wndName
, sizeof(wndName
)))
1495 strcpy(wndName
, "-- Empty --");
1497 packet_reply_open(gdbctx
);
1498 packet_reply_catc(gdbctx
, 'O');
1499 snprintf(buffer
, sizeof(buffer
),
1500 "%*s%04lx%*s%-17.17s %08x %08x %.14s\n",
1501 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1502 clsName
, GetWindowLong(hWnd
, GWL_STYLE
),
1503 GetWindowLongPtr(hWnd
, GWLP_WNDPROC
), wndName
);
1504 packet_reply_hex_to_str(gdbctx
, buffer
);
1505 packet_reply_close(gdbctx
);
1507 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1508 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1509 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1512 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1516 /* we do the output in several 'O' packets, with the last one being just OK for
1517 * marking the end of the output */
1518 packet_reply_open(gdbctx
);
1519 packet_reply_catc(gdbctx
, 'O');
1520 snprintf(buffer
, sizeof(buffer
),
1521 "%-16.16s %-17.17s %-8.8s %s\n",
1522 "hwnd", "Class Name", " Style", " WndProc Text");
1523 packet_reply_hex_to_str(gdbctx
, buffer
);
1524 packet_reply_close(gdbctx
);
1526 /* FIXME: could also add a pmt to this command in str... */
1527 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1528 packet_reply(gdbctx
, "OK", 2);
1531 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1533 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1536 PROCESSENTRY32 entry
;
1539 if (snap
== INVALID_HANDLE_VALUE
)
1542 entry
.dwSize
= sizeof(entry
);
1543 ok
= Process32First(snap
, &entry
);
1545 /* we do the output in several 'O' packets, with the last one being just OK for
1546 * marking the end of the output */
1548 packet_reply_open(gdbctx
);
1549 packet_reply_catc(gdbctx
, 'O');
1550 snprintf(buffer
, sizeof(buffer
),
1551 " %-8.8s %-8.8s %-8.8s %s\n",
1552 "pid", "threads", "parent", "executable");
1553 packet_reply_hex_to_str(gdbctx
, buffer
);
1554 packet_reply_close(gdbctx
);
1559 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1560 packet_reply_open(gdbctx
);
1561 packet_reply_catc(gdbctx
, 'O');
1562 snprintf(buffer
, sizeof(buffer
),
1563 "%c%08x %-8d %08x '%s'\n",
1564 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1565 entry
.th32ParentProcessID
, entry
.szExeFile
);
1566 packet_reply_hex_to_str(gdbctx
, buffer
);
1567 packet_reply_close(gdbctx
);
1568 ok
= Process32Next(snap
, &entry
);
1571 packet_reply(gdbctx
, "OK", 2);
1574 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1576 MEMORY_BASIC_INFORMATION mbi
;
1583 /* we do the output in several 'O' packets, with the last one being just OK for
1584 * marking the end of the output */
1585 packet_reply_open(gdbctx
);
1586 packet_reply_catc(gdbctx
, 'O');
1587 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1588 packet_reply_close(gdbctx
);
1590 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1594 case MEM_COMMIT
: state
= "commit "; break;
1595 case MEM_FREE
: state
= "free "; break;
1596 case MEM_RESERVE
: state
= "reserve"; break;
1597 default: state
= "??? "; break;
1599 if (mbi
.State
!= MEM_FREE
)
1603 case MEM_IMAGE
: type
= "image "; break;
1604 case MEM_MAPPED
: type
= "mapped "; break;
1605 case MEM_PRIVATE
: type
= "private"; break;
1606 case 0: type
= " "; break;
1607 default: type
= "??? "; break;
1609 memset(prot
, ' ' , sizeof(prot
)-1);
1610 prot
[sizeof(prot
)-1] = '\0';
1611 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1613 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1615 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1617 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1625 packet_reply_open(gdbctx
);
1626 snprintf(buffer
, sizeof(buffer
), "%08lx %08lx %s %s %s\n",
1627 (DWORD_PTR
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1628 packet_reply_catc(gdbctx
, 'O');
1629 packet_reply_hex_to_str(gdbctx
, buffer
);
1630 packet_reply_close(gdbctx
);
1632 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1634 addr
+= mbi
.RegionSize
;
1636 packet_reply(gdbctx
, "OK", 2);
1639 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1640 int len
, const char* str
)
1646 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1648 else if (len
>= 2 && str
[0] == '=')
1650 unsigned val
= atoi(&str
[1]);
1651 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1652 gdbctx
->trace
= val
;
1656 /* FIXME: ugly but can use error packet here */
1657 packet_reply_cat(gdbctx
, "E00");
1660 packet_reply_open(gdbctx
);
1661 packet_reply_hex_to_str(gdbctx
, buffer
);
1662 packet_reply_close(gdbctx
);
1670 void (*handler
)(struct gdb_context
*, int, const char*);
1673 {0, "wnd", 3, packet_query_monitor_wnd
},
1674 {0, "window", 6, packet_query_monitor_wnd
},
1675 {0, "proc", 4, packet_query_monitor_process
},
1676 {0, "process", 7, packet_query_monitor_process
},
1677 {0, "mem", 3, packet_query_monitor_mem
},
1678 {1, "trace", 5, packet_query_monitor_trace
},
1682 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1683 const char* hxcmd
, size_t len
)
1686 struct query_detail
* qd
;
1688 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1690 hex_from(buffer
, hxcmd
, len
);
1692 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1694 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1695 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1697 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1700 return packet_reply_error(gdbctx
, EINVAL
);
1703 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1705 switch (gdbctx
->in_packet
[0])
1708 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1710 struct dbg_thread
* thd
;
1712 packet_reply_open(gdbctx
);
1713 packet_reply_add(gdbctx
, "m", 1);
1714 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1716 packet_reply_val(gdbctx
, thd
->tid
, 4);
1717 if (thd
->next
!= NULL
)
1718 packet_reply_add(gdbctx
, ",", 1);
1720 packet_reply_close(gdbctx
);
1723 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1727 packet_reply_open(gdbctx
);
1728 packet_reply_catc(gdbctx
, 'O');
1729 get_process_info(gdbctx
, result
, sizeof(result
));
1730 packet_reply_hex_to_str(gdbctx
, result
);
1731 packet_reply_close(gdbctx
);
1736 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1738 packet_reply(gdbctx
, "l", 1);
1741 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1743 packet_reply(gdbctx
, "l", 1);
1748 if (gdbctx
->in_packet_len
== 1)
1750 struct dbg_thread
* thd
;
1751 /* FIXME: doc says 16 bit val ??? */
1752 /* grab first created thread, aka last in list */
1753 assert(gdbctx
->process
&& gdbctx
->process
->threads
);
1754 for (thd
= gdbctx
->process
->threads
; thd
->next
; thd
= thd
->next
);
1755 packet_reply_open(gdbctx
);
1756 packet_reply_add(gdbctx
, "QC", 2);
1757 packet_reply_val(gdbctx
, thd
->tid
, 4);
1758 packet_reply_close(gdbctx
);
1763 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1767 if (gdbctx
->wine_segs
[0] == 0 && gdbctx
->wine_segs
[1] == 0 &&
1768 gdbctx
->wine_segs
[2] == 0)
1769 return packet_error
;
1770 snprintf(buf
, sizeof(buf
),
1771 "Text=%08lx;Data=%08lx;Bss=%08lx",
1772 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1773 gdbctx
->wine_segs
[2]);
1774 return packet_reply(gdbctx
, buf
, -1);
1778 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1780 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1781 gdbctx
->in_packet_len
- 5);
1785 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1787 if (strncmp(gdbctx
->in_packet
, "Supported", gdbctx
->in_packet_len
) == 0)
1789 packet_reply_open(gdbctx
);
1790 packet_reply_close(gdbctx
);
1795 if (gdbctx
->in_packet_len
> 15 &&
1796 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1797 gdbctx
->in_packet
[15] == ',')
1803 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1804 if (end
== NULL
) break;
1805 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1806 packet_reply_open(gdbctx
);
1807 packet_reply_hex_to_str(gdbctx
, result
);
1808 packet_reply_close(gdbctx
);
1813 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1814 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1815 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1816 return packet_error
;
1819 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1821 /* FIXME: add support for address in packet */
1822 assert(gdbctx
->in_packet_len
== 0);
1823 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1824 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1825 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
1826 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1827 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1828 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1829 wait_for_debuggee(gdbctx
);
1830 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1831 return packet_reply_status(gdbctx
);
1835 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1839 /* FIXME: add support for address in packet */
1840 assert(gdbctx
->in_packet_len
== 2);
1841 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1842 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1843 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1844 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1845 hex_from(&sig
, gdbctx
->in_packet
, 1);
1846 /* cannot change signals on the fly */
1847 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1848 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1849 if (sig
!= gdbctx
->last_sig
)
1850 return packet_error
;
1851 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1852 wait_for_debuggee(gdbctx
);
1853 return packet_reply_status(gdbctx
);
1857 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1862 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1863 if (tid
== -1 || tid
== 0)
1864 return packet_reply_error(gdbctx
, EINVAL
);
1865 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1867 return packet_reply_error(gdbctx
, ESRCH
);
1870 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1874 struct gdb_ctx_Xpoint
* xpt
;
1875 enum be_xpoint_type t
;
1877 /* FIXME: check packet_len */
1878 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1879 gdbctx
->in_packet
[1] != ',' ||
1880 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1881 return packet_error
;
1882 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1883 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1884 addr
, len
, gdbctx
->in_packet
[0]);
1885 switch (gdbctx
->in_packet
[0])
1887 case '0': t
= be_xpoint_break
; len
= 0; break;
1888 case '1': t
= be_xpoint_watch_exec
; break;
1889 case '2': t
= be_xpoint_watch_read
; break;
1890 case '3': t
= be_xpoint_watch_write
; break;
1891 default: return packet_error
;
1893 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1895 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1897 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
1898 gdbctx
->process
->process_io
, &gdbctx
->context
,
1899 t
, xpt
->addr
, xpt
->val
, len
))
1907 return packet_error
;
1910 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1914 struct gdb_ctx_Xpoint
* xpt
;
1915 enum be_xpoint_type t
;
1917 /* FIXME: check packet_len */
1918 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1919 gdbctx
->in_packet
[1] != ',' ||
1920 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1921 return packet_error
;
1922 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1923 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
1924 addr
, len
, gdbctx
->in_packet
[0]);
1925 switch (gdbctx
->in_packet
[0])
1927 case '0': t
= be_xpoint_break
; len
= 0; break;
1928 case '1': t
= be_xpoint_watch_exec
; break;
1929 case '2': t
= be_xpoint_watch_read
; break;
1930 case '3': t
= be_xpoint_watch_write
; break;
1931 default: return packet_error
;
1933 /* because of packet command handling, this should be made idempotent */
1934 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1936 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1937 return packet_ok
; /* nothing to do */
1939 /* really set the Xpoint */
1940 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1942 if (xpt
->type
== -1)
1944 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
1945 gdbctx
->process
->process_io
, &gdbctx
->context
,
1946 t
, addr
, &xpt
->val
, len
))
1952 fprintf(stderr
, "cannot set xpoint\n");
1956 /* no more entries... eech */
1957 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
1958 return packet_error
;
1961 /* =============================================== *
1962 * P A C K E T I N F R A S T R U C T U R E *
1963 * =============================================== *
1969 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1972 static struct packet_entry packet_entries
[] =
1974 /*{'!', packet_extended}, */
1975 {'?', packet_last_signal
},
1976 {'c', packet_continue
},
1977 {'C', packet_continue_signal
},
1978 {'D', packet_detach
},
1979 {'g', packet_read_registers
},
1980 {'G', packet_write_registers
},
1982 {'H', packet_thread
},
1983 {'m', packet_read_memory
},
1984 {'M', packet_write_memory
},
1985 {'p', packet_read_register
},
1986 {'P', packet_write_register
},
1987 {'q', packet_query
},
1988 /* {'Q', packet_set}, */
1989 /* {'R', packet,restart}, only in extended mode ! */
1991 /*{'S', packet_step_signal}, hard(er) to implement */
1992 {'T', packet_thread_alive
},
1993 {'v', packet_verbose
},
1994 {'z', packet_remove_breakpoint
},
1995 {'Z', packet_set_breakpoint
},
1998 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2002 unsigned char in_cksum
, loc_cksum
;
2004 enum packet_return ret
= packet_error
;
2007 while ((ret
& packet_last_f
) == 0)
2009 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2010 fprintf(stderr
, "In-buf: %*.*s\n",
2011 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2012 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2013 if (ptr
== NULL
) return FALSE
;
2014 if (ptr
!= gdbctx
->in_buf
)
2016 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2017 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2018 fprintf(stderr
, "Removing garbage: %*.*s\n",
2019 glen
, glen
, gdbctx
->in_buf
);
2020 gdbctx
->in_len
-= glen
;
2021 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2023 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2024 if (end
== NULL
) return FALSE
;
2025 /* no checksum yet */
2026 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2027 plen
= end
- gdbctx
->in_buf
- 1;
2028 hex_from(&in_cksum
, end
+ 1, 1);
2029 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2030 if (loc_cksum
== in_cksum
)
2032 if (num_packet
== 0) {
2037 write(gdbctx
->sock
, "+", 1);
2040 /* FIXME: should use bsearch if packet_entries was sorted */
2041 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2043 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2045 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2047 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2048 fprintf(stderr
, "Unknown packet request %*.*s\n",
2049 plen
, plen
, &gdbctx
->in_buf
[1]);
2053 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2054 gdbctx
->in_packet_len
= plen
- 1;
2055 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2056 fprintf(stderr
, "Packet: %c%*.*s\n",
2058 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2060 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2062 switch (ret
& ~packet_last_f
)
2064 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2065 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2066 case packet_done
: break;
2068 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2069 fprintf(stderr
, "Reply-full: %*.*s\n",
2070 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2071 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2072 assert(i
== gdbctx
->out_len
);
2073 /* if this fails, we'll have to use POLLOUT...
2075 gdbctx
->out_len
= 0;
2080 /* FIXME: if we have in our input buffer more than one packet,
2081 * it's very likely that we took too long to answer to a given packet
2082 * and gdb is sending us again the same packet
2083 * We simply drop the second packet. This will lower the risk of error,
2084 * but there's still some race conditions here
2085 * A better fix (yet not perfect) would be to have two threads:
2086 * - one managing the packets for gdb
2087 * - the second one managing the commands...
2088 * This would allow us also the reply with the '+' character (Ack of
2089 * the command) way sooner than what we do now
2091 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2092 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2097 write(gdbctx
->sock
, "+", 1);
2098 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2099 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2101 gdbctx
->in_len
-= plen
+ 4;
2102 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2107 static int fetch_data(struct gdb_context
* gdbctx
)
2109 int len
, in_len
= gdbctx
->in_len
;
2111 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2115 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2116 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2118 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2119 fprintf(stderr
, "%d %d %*.*s\n",
2120 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2121 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2122 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2123 if (len
<= 0) break;
2124 gdbctx
->in_len
+= len
;
2125 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2126 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2128 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2129 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2130 return gdbctx
->in_len
- in_len
;
2133 #define FLAG_NO_START 1
2134 #define FLAG_WITH_XTERM 2
2136 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2140 const char* gdb_path
;
2143 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2144 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2145 fd
= mkstemps(buf
, 0);
2146 if (fd
== -1) return FALSE
;
2147 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2148 fprintf(f
, "file %s\n", wine_path
);
2149 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2150 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2151 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2152 /* gdb 5.1 seems to require it, won't hurt anyway */
2153 fprintf(f
, "sharedlibrary\n");
2154 /* This is needed (but not a decent & final fix)
2155 * Without this, gdb would skip our inter-DLL relay code (because
2156 * we don't have any line number information for the relay code)
2157 * With this, we will stop on first instruction of the stub, and
2158 * reusing step, will get us through the relay stub at the actual
2159 * function we're looking at.
2161 fprintf(f
, "set step-mode on\n");
2162 /* tell gdb to delete this file when done handling it... */
2163 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2165 if (flags
& FLAG_WITH_XTERM
)
2166 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2168 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2169 assert(0); /* never reached */
2173 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2176 struct sockaddr_in s_addrs
;
2177 unsigned int s_len
= sizeof(s_addrs
);
2178 struct pollfd pollfd
;
2179 IMAGEHLP_MODULE imh_mod
;
2181 /* step 1: create socket for gdb connection request */
2182 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2184 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2185 fprintf(stderr
, "Can't create socket");
2189 if (listen(sock
, 1) == -1 ||
2190 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2193 /* step 2: do the process internal creation */
2194 handle_debug_event(gdbctx
, de
);
2196 /* step3: get the wine loader name */
2197 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
)) return FALSE
;
2199 /* step 4: fire up gdb (if requested) */
2200 if (flags
& FLAG_NO_START
)
2201 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2205 case -1: /* error in parent... */
2206 fprintf(stderr
, "Cannot create gdb\n");
2208 default: /* in parent... success */
2210 case 0: /* in child... and alive */
2211 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2212 /* if we're here, exec failed, so report failure */
2216 /* step 5: wait for gdb to connect actually */
2218 pollfd
.events
= POLLIN
;
2221 switch (poll(&pollfd
, 1, -1))
2224 if (pollfd
.revents
& POLLIN
)
2227 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2228 if (gdbctx
->sock
== -1)
2230 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2231 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2232 /* don't keep our small packets too long: send them ASAP back to GDB
2233 * without this, GDB really crawls
2235 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2239 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2240 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2243 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2244 fprintf(stderr
, "Poll for cnx failed (error)\n");
2254 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2260 gdbctx
->in_buf
= NULL
;
2261 gdbctx
->in_buf_alloc
= 0;
2263 gdbctx
->out_buf
= NULL
;
2264 gdbctx
->out_buf_alloc
= 0;
2265 gdbctx
->out_len
= 0;
2266 gdbctx
->out_curr_packet
= -1;
2268 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2269 gdbctx
->last_sig
= 0;
2270 gdbctx
->in_trap
= FALSE
;
2271 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2272 gdbctx
->process
= NULL
;
2273 for (i
= 0; i
< NUM_XPOINT
; i
++)
2274 gdbctx
->Xpoints
[i
].type
= -1;
2276 /* wait for first trap */
2277 while (WaitForDebugEvent(&de
, INFINITE
))
2279 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2281 /* this should be the first event we get,
2282 * and the only one of this type */
2283 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2284 /* gdbctx->dwProcessId = pid; */
2285 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2286 assert(!gdbctx
->in_trap
);
2290 handle_debug_event(gdbctx
, &de
);
2291 if (gdbctx
->in_trap
) break;
2293 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2298 static int gdb_remote(unsigned flags
)
2300 struct pollfd pollfd
;
2301 struct gdb_context gdbctx
;
2304 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2306 pollfd
.fd
= gdbctx
.sock
;
2307 pollfd
.events
= POLLIN
;
2310 switch (poll(&pollfd
, 1, -1))
2314 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2316 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2317 fprintf(stderr
, "Gdb hung up\n");
2318 /* kill also debuggee process - questionnable - */
2319 detach_debuggee(&gdbctx
, TRUE
);
2323 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2325 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2329 /* timeout, should never happen (infinite timeout) */
2332 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2333 fprintf(stderr
, "Poll failed\n");
2343 int gdb_main(int argc
, char* argv
[])
2346 unsigned gdb_flags
= 0;
2349 while (argc
> 0 && argv
[0][0] == '-')
2351 if (strcmp(argv
[0], "--no-start") == 0)
2353 gdb_flags
|= FLAG_NO_START
;
2357 if (strcmp(argv
[0], "--with-xterm") == 0)
2359 gdb_flags
|= FLAG_WITH_XTERM
;
2365 if (dbg_active_attach(argc
, argv
) == start_ok
||
2366 dbg_active_launch(argc
, argv
) == start_ok
)
2367 return gdb_remote(gdb_flags
);
2369 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");