2 * A Win32 based proxy implementing the GBD remote protocol.
3 * This makes it possible to debug Wine (and any "emulated"
4 * program) under Linux using GDB.
6 * Copyright (c) Eric Pouech 2002-2004
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* Protocol specification can be found here:
24 * http://sources.redhat.com/gdb/onlinedocs/gdb/Maintenance-Commands.html
28 #include "wine/port.h"
37 #ifdef HAVE_SYS_POLL_H
38 # include <sys/poll.h>
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
43 #ifdef HAVE_SYS_SOCKET_H
44 # include <sys/socket.h>
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
49 #ifdef HAVE_NETINET_TCP_H
50 # include <netinet/tcp.h>
56 /* if we don't have poll support on this system
57 * we won't provide gdb proxy support here...
67 #define GDBPXY_TRC_LOWLEVEL 0x01
68 #define GDBPXY_TRC_PACKET 0x02
69 #define GDBPXY_TRC_COMMAND 0x04
70 #define GDBPXY_TRC_COMMAND_ERROR 0x08
71 #define GDBPXY_TRC_WIN32_EVENT 0x10
72 #define GDBPXY_TRC_WIN32_ERROR 0x20
73 #define GDBPXY_TRC_COMMAND_FIXME 0x80
77 enum be_xpoint_type type
; /* -1 means free */
90 /* split into individual packet */
98 /* generic GDB thread information */
99 struct dbg_thread
* exec_thread
; /* thread used in step & continue */
100 struct dbg_thread
* other_thread
; /* thread to be used in any other operation */
102 /* current Win32 trap env */
106 /* Win32 information */
107 struct dbg_process
* process
;
108 #define NUM_XPOINT 32
109 struct gdb_ctx_Xpoint Xpoints
[NUM_XPOINT
];
110 /* Unix environment */
111 unsigned long wine_segs
[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
114 static BOOL
tgt_process_gdbproxy_read(HANDLE hProcess
, const void* addr
,
115 void* buffer
, SIZE_T len
, SIZE_T
* rlen
)
117 return ReadProcessMemory( hProcess
, addr
, buffer
, len
, rlen
);
120 static BOOL
tgt_process_gdbproxy_write(HANDLE hProcess
, void* addr
,
121 const void* buffer
, SIZE_T len
, SIZE_T
* wlen
)
123 return WriteProcessMemory( hProcess
, addr
, buffer
, len
, wlen
);
126 static struct be_process_io be_process_gdbproxy_io
=
128 NULL
, /* we shouldn't use close_process() in gdbproxy */
129 tgt_process_gdbproxy_read
,
130 tgt_process_gdbproxy_write
133 /* =============================================== *
134 * B A S I C M A N I P U L A T I O N S *
135 * =============================================== *
138 static inline int hex_from0(char ch
)
140 if (ch
>= '0' && ch
<= '9') return ch
- '0';
141 if (ch
>= 'A' && ch
<= 'F') return ch
- 'A' + 10;
142 if (ch
>= 'a' && ch
<= 'f') return ch
- 'a' + 10;
148 static inline unsigned char hex_to0(int x
)
150 assert(x
>= 0 && x
< 16);
151 return "0123456789abcdef"[x
];
154 static int hex_to_int(const char* src
, size_t len
)
156 unsigned int returnval
= 0;
160 returnval
|= hex_from0(*src
++);
165 static void hex_from(void* dst
, const char* src
, size_t len
)
167 unsigned char *p
= dst
;
170 *p
++ = (hex_from0(src
[0]) << 4) | hex_from0(src
[1]);
175 static void hex_to(char* dst
, const void* src
, size_t len
)
177 const unsigned char *p
= src
;
180 *dst
++ = hex_to0(*p
>> 4);
181 *dst
++ = hex_to0(*p
& 0x0F);
186 static unsigned char checksum(const char* ptr
, int len
)
191 cksum
+= (unsigned char)*ptr
++;
195 /* =============================================== *
196 * C P U H A N D L E R S *
197 * =============================================== *
200 /* This struct helps us to manage the different representations of a register:
201 * ctx_offset and ctx_length are the location and size in Win32 CONTEXT
202 * gdb_length is the length gdb expects on the wire
203 * As the two sizes could be different, we have to convert between the two
204 * (for example, on x86_64, Seg?s are 4 bytes on the wire and 2 in CONTEXT)
214 #define REG(r,gs,m) {FIELD_OFFSET(CONTEXT, r), sizeof(((CONTEXT*)NULL)->r), gs, m}
217 static const char target_xml
[] = "";
218 static struct cpu_register cpu_register_map
[] = {
219 REG(Eax
, 4, CONTEXT_INTEGER
),
220 REG(Ecx
, 4, CONTEXT_INTEGER
),
221 REG(Edx
, 4, CONTEXT_INTEGER
),
222 REG(Ebx
, 4, CONTEXT_INTEGER
),
223 REG(Esp
, 4, CONTEXT_CONTROL
),
224 REG(Ebp
, 4, CONTEXT_CONTROL
),
225 REG(Esi
, 4, CONTEXT_INTEGER
),
226 REG(Edi
, 4, CONTEXT_INTEGER
),
227 REG(Eip
, 4, CONTEXT_CONTROL
),
228 REG(EFlags
, 4, CONTEXT_CONTROL
),
229 REG(SegCs
, 4, CONTEXT_CONTROL
),
230 REG(SegSs
, 4, CONTEXT_SEGMENTS
),
231 REG(SegDs
, 4, CONTEXT_SEGMENTS
),
232 REG(SegEs
, 4, CONTEXT_SEGMENTS
),
233 REG(SegFs
, 4, CONTEXT_SEGMENTS
),
234 REG(SegGs
, 4, CONTEXT_SEGMENTS
),
235 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[ 0]), 10, 10, CONTEXT_FLOATING_POINT
},
236 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[10]), 10, 10, CONTEXT_FLOATING_POINT
},
237 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[20]), 10, 10, CONTEXT_FLOATING_POINT
},
238 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[30]), 10, 10, CONTEXT_FLOATING_POINT
},
239 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[40]), 10, 10, CONTEXT_FLOATING_POINT
},
240 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[50]), 10, 10, CONTEXT_FLOATING_POINT
},
241 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[60]), 10, 10, CONTEXT_FLOATING_POINT
},
242 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[70]), 10, 10, CONTEXT_FLOATING_POINT
},
243 { FIELD_OFFSET(CONTEXT
, FloatSave
.ControlWord
), 2, 4, CONTEXT_FLOATING_POINT
},
244 { FIELD_OFFSET(CONTEXT
, FloatSave
.StatusWord
), 2, 4, CONTEXT_FLOATING_POINT
},
245 { FIELD_OFFSET(CONTEXT
, FloatSave
.TagWord
), 2, 4, CONTEXT_FLOATING_POINT
},
246 { FIELD_OFFSET(CONTEXT
, FloatSave
.ErrorSelector
), 2, 4, CONTEXT_FLOATING_POINT
},
247 REG(FloatSave
.ErrorOffset
, 4, CONTEXT_FLOATING_POINT
),
248 { FIELD_OFFSET(CONTEXT
, FloatSave
.DataSelector
), 2, 4, CONTEXT_FLOATING_POINT
},
249 REG(FloatSave
.DataOffset
, 4, CONTEXT_FLOATING_POINT
),
250 { FIELD_OFFSET(CONTEXT
, FloatSave
.ErrorSelector
)+2, 2, 4, CONTEXT_FLOATING_POINT
},
252 #elif defined(__powerpc__)
253 static const char target_xml
[] = "";
254 static struct cpu_register cpu_register_map
[] = {
255 REG(Gpr0
, 4, CONTEXT_INTEGER
),
256 REG(Gpr1
, 4, CONTEXT_INTEGER
),
257 REG(Gpr2
, 4, CONTEXT_INTEGER
),
258 REG(Gpr3
, 4, CONTEXT_INTEGER
),
259 REG(Gpr4
, 4, CONTEXT_INTEGER
),
260 REG(Gpr5
, 4, CONTEXT_INTEGER
),
261 REG(Gpr6
, 4, CONTEXT_INTEGER
),
262 REG(Gpr7
, 4, CONTEXT_INTEGER
),
263 REG(Gpr8
, 4, CONTEXT_INTEGER
),
264 REG(Gpr9
, 4, CONTEXT_INTEGER
),
265 REG(Gpr10
, 4, CONTEXT_INTEGER
),
266 REG(Gpr11
, 4, CONTEXT_INTEGER
),
267 REG(Gpr12
, 4, CONTEXT_INTEGER
),
268 REG(Gpr13
, 4, CONTEXT_INTEGER
),
269 REG(Gpr14
, 4, CONTEXT_INTEGER
),
270 REG(Gpr15
, 4, CONTEXT_INTEGER
),
271 REG(Gpr16
, 4, CONTEXT_INTEGER
),
272 REG(Gpr17
, 4, CONTEXT_INTEGER
),
273 REG(Gpr18
, 4, CONTEXT_INTEGER
),
274 REG(Gpr19
, 4, CONTEXT_INTEGER
),
275 REG(Gpr20
, 4, CONTEXT_INTEGER
),
276 REG(Gpr21
, 4, CONTEXT_INTEGER
),
277 REG(Gpr22
, 4, CONTEXT_INTEGER
),
278 REG(Gpr23
, 4, CONTEXT_INTEGER
),
279 REG(Gpr24
, 4, CONTEXT_INTEGER
),
280 REG(Gpr25
, 4, CONTEXT_INTEGER
),
281 REG(Gpr26
, 4, CONTEXT_INTEGER
),
282 REG(Gpr27
, 4, CONTEXT_INTEGER
),
283 REG(Gpr28
, 4, CONTEXT_INTEGER
),
284 REG(Gpr29
, 4, CONTEXT_INTEGER
),
285 REG(Gpr30
, 4, CONTEXT_INTEGER
),
286 REG(Gpr31
, 4, CONTEXT_INTEGER
),
287 REG(Fpr0
, 4, CONTEXT_FLOATING_POINT
),
288 REG(Fpr1
, 4, CONTEXT_FLOATING_POINT
),
289 REG(Fpr2
, 4, CONTEXT_FLOATING_POINT
),
290 REG(Fpr3
, 4, CONTEXT_FLOATING_POINT
),
291 REG(Fpr4
, 4, CONTEXT_FLOATING_POINT
),
292 REG(Fpr5
, 4, CONTEXT_FLOATING_POINT
),
293 REG(Fpr6
, 4, CONTEXT_FLOATING_POINT
),
294 REG(Fpr7
, 4, CONTEXT_FLOATING_POINT
),
295 REG(Fpr8
, 4, CONTEXT_FLOATING_POINT
),
296 REG(Fpr9
, 4, CONTEXT_FLOATING_POINT
),
297 REG(Fpr10
, 4, CONTEXT_FLOATING_POINT
),
298 REG(Fpr11
, 4, CONTEXT_FLOATING_POINT
),
299 REG(Fpr12
, 4, CONTEXT_FLOATING_POINT
),
300 REG(Fpr13
, 4, CONTEXT_FLOATING_POINT
),
301 REG(Fpr14
, 4, CONTEXT_FLOATING_POINT
),
302 REG(Fpr15
, 4, CONTEXT_FLOATING_POINT
),
303 REG(Fpr16
, 4, CONTEXT_FLOATING_POINT
),
304 REG(Fpr17
, 4, CONTEXT_FLOATING_POINT
),
305 REG(Fpr18
, 4, CONTEXT_FLOATING_POINT
),
306 REG(Fpr19
, 4, CONTEXT_FLOATING_POINT
),
307 REG(Fpr20
, 4, CONTEXT_FLOATING_POINT
),
308 REG(Fpr21
, 4, CONTEXT_FLOATING_POINT
),
309 REG(Fpr22
, 4, CONTEXT_FLOATING_POINT
),
310 REG(Fpr23
, 4, CONTEXT_FLOATING_POINT
),
311 REG(Fpr24
, 4, CONTEXT_FLOATING_POINT
),
312 REG(Fpr25
, 4, CONTEXT_FLOATING_POINT
),
313 REG(Fpr26
, 4, CONTEXT_FLOATING_POINT
),
314 REG(Fpr27
, 4, CONTEXT_FLOATING_POINT
),
315 REG(Fpr28
, 4, CONTEXT_FLOATING_POINT
),
316 REG(Fpr29
, 4, CONTEXT_FLOATING_POINT
),
317 REG(Fpr30
, 4, CONTEXT_FLOATING_POINT
),
318 REG(Fpr31
, 4, CONTEXT_FLOATING_POINT
),
320 REG(Iar
, 4, CONTEXT_CONTROL
),
321 REG(Msr
, 4, CONTEXT_CONTROL
),
322 REG(Cr
, 4, CONTEXT_INTEGER
),
323 REG(Lr
, 4, CONTEXT_CONTROL
),
324 REG(Ctr
, 4, CONTEXT_CONTROL
),
325 REG(Xer
, 4, CONTEXT_INTEGER
),
326 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
327 /* see gdb/nlm/ppc.c */
329 #elif defined(__x86_64__)
330 static const char target_xml
[] = "";
331 static struct cpu_register cpu_register_map
[] = {
332 REG(Rax
, 8, CONTEXT_INTEGER
),
333 REG(Rbx
, 8, CONTEXT_INTEGER
),
334 REG(Rcx
, 8, CONTEXT_INTEGER
),
335 REG(Rdx
, 8, CONTEXT_INTEGER
),
336 REG(Rsi
, 8, CONTEXT_INTEGER
),
337 REG(Rdi
, 8, CONTEXT_INTEGER
),
338 REG(Rbp
, 8, CONTEXT_INTEGER
),
339 REG(Rsp
, 8, CONTEXT_INTEGER
),
340 REG(R8
, 8, CONTEXT_INTEGER
),
341 REG(R9
, 8, CONTEXT_INTEGER
),
342 REG(R10
, 8, CONTEXT_INTEGER
),
343 REG(R11
, 8, CONTEXT_INTEGER
),
344 REG(R12
, 8, CONTEXT_INTEGER
),
345 REG(R13
, 8, CONTEXT_INTEGER
),
346 REG(R14
, 8, CONTEXT_INTEGER
),
347 REG(R15
, 8, CONTEXT_INTEGER
),
348 REG(Rip
, 8, CONTEXT_CONTROL
),
349 REG(EFlags
, 4, CONTEXT_CONTROL
),
350 REG(SegCs
, 4, CONTEXT_CONTROL
),
351 REG(SegSs
, 4, CONTEXT_CONTROL
),
352 REG(SegDs
, 4, CONTEXT_SEGMENTS
),
353 REG(SegEs
, 4, CONTEXT_SEGMENTS
),
354 REG(SegFs
, 4, CONTEXT_SEGMENTS
),
355 REG(SegGs
, 4, CONTEXT_SEGMENTS
),
357 #elif defined(__arm__)
358 static const char target_xml
[] =
359 "l <target><architecture>arm</architecture>\n"
360 "<feature name=\"org.gnu.gdb.arm.core\">\n"
361 " <reg name=\"r0\" bitsize=\"32\" type=\"uint32\"/>\n"
362 " <reg name=\"r1\" bitsize=\"32\" type=\"uint32\"/>\n"
363 " <reg name=\"r2\" bitsize=\"32\" type=\"uint32\"/>\n"
364 " <reg name=\"r3\" bitsize=\"32\" type=\"uint32\"/>\n"
365 " <reg name=\"r4\" bitsize=\"32\" type=\"uint32\"/>\n"
366 " <reg name=\"r5\" bitsize=\"32\" type=\"uint32\"/>\n"
367 " <reg name=\"r6\" bitsize=\"32\" type=\"uint32\"/>\n"
368 " <reg name=\"r7\" bitsize=\"32\" type=\"uint32\"/>\n"
369 " <reg name=\"r8\" bitsize=\"32\" type=\"uint32\"/>\n"
370 " <reg name=\"r9\" bitsize=\"32\" type=\"uint32\"/>\n"
371 " <reg name=\"r10\" bitsize=\"32\" type=\"uint32\"/>\n"
372 " <reg name=\"r11\" bitsize=\"32\" type=\"uint32\"/>\n"
373 " <reg name=\"r12\" bitsize=\"32\" type=\"uint32\"/>\n"
374 " <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n"
375 " <reg name=\"lr\" bitsize=\"32\"/>\n"
376 " <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n"
377 " <reg name=\"cpsr\" bitsize=\"32\"/>\n"
378 "</feature></target>\n";
380 static struct cpu_register cpu_register_map
[] = {
381 REG(R0
, 4, CONTEXT_INTEGER
),
382 REG(R1
, 4, CONTEXT_INTEGER
),
383 REG(R2
, 4, CONTEXT_INTEGER
),
384 REG(R3
, 4, CONTEXT_INTEGER
),
385 REG(R4
, 4, CONTEXT_INTEGER
),
386 REG(R5
, 4, CONTEXT_INTEGER
),
387 REG(R6
, 4, CONTEXT_INTEGER
),
388 REG(R7
, 4, CONTEXT_INTEGER
),
389 REG(R8
, 4, CONTEXT_INTEGER
),
390 REG(R9
, 4, CONTEXT_INTEGER
),
391 REG(R10
, 4, CONTEXT_INTEGER
),
392 REG(Fp
, 4, CONTEXT_INTEGER
),
393 REG(Ip
, 4, CONTEXT_INTEGER
),
394 REG(Sp
, 4, CONTEXT_CONTROL
),
395 REG(Lr
, 4, CONTEXT_CONTROL
),
396 REG(Pc
, 4, CONTEXT_CONTROL
),
397 REG(Cpsr
, 4, CONTEXT_CONTROL
),
399 #elif defined(__aarch64__)
400 static const char target_xml
[] = "";
401 static struct cpu_register cpu_register_map
[] = {
402 REG(Cpsr
, 4, CONTEXT_CONTROL
),
403 REG(X0
, 8, CONTEXT_INTEGER
),
404 REG(X1
, 8, CONTEXT_INTEGER
),
405 REG(X2
, 8, CONTEXT_INTEGER
),
406 REG(X3
, 8, CONTEXT_INTEGER
),
407 REG(X4
, 8, CONTEXT_INTEGER
),
408 REG(X5
, 8, CONTEXT_INTEGER
),
409 REG(X6
, 8, CONTEXT_INTEGER
),
410 REG(X7
, 8, CONTEXT_INTEGER
),
411 REG(X8
, 8, CONTEXT_INTEGER
),
412 REG(X9
, 8, CONTEXT_INTEGER
),
413 REG(X10
, 8, CONTEXT_INTEGER
),
414 REG(X11
, 8, CONTEXT_INTEGER
),
415 REG(X12
, 8, CONTEXT_INTEGER
),
416 REG(X13
, 8, CONTEXT_INTEGER
),
417 REG(X14
, 8, CONTEXT_INTEGER
),
418 REG(X15
, 8, CONTEXT_INTEGER
),
419 REG(X16
, 8, CONTEXT_INTEGER
),
420 REG(X17
, 8, CONTEXT_INTEGER
),
421 REG(X18
, 8, CONTEXT_INTEGER
),
422 REG(X19
, 8, CONTEXT_INTEGER
),
423 REG(X20
, 8, CONTEXT_INTEGER
),
424 REG(X21
, 8, CONTEXT_INTEGER
),
425 REG(X22
, 8, CONTEXT_INTEGER
),
426 REG(X23
, 8, CONTEXT_INTEGER
),
427 REG(X24
, 8, CONTEXT_INTEGER
),
428 REG(X25
, 8, CONTEXT_INTEGER
),
429 REG(X26
, 8, CONTEXT_INTEGER
),
430 REG(X27
, 8, CONTEXT_INTEGER
),
431 REG(X28
, 8, CONTEXT_INTEGER
),
432 REG(Fp
, 8, CONTEXT_INTEGER
),
433 REG(Lr
, 8, CONTEXT_INTEGER
),
434 REG(Sp
, 8, CONTEXT_CONTROL
),
435 REG(Pc
, 8, CONTEXT_CONTROL
),
438 # error Define the registers map for your CPU
442 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
444 static inline void* cpu_register_ptr(CONTEXT
* ctx
, unsigned idx
)
446 assert(idx
< cpu_num_regs
);
447 return (char*)ctx
+ cpu_register_map
[idx
].ctx_offset
;
450 static inline DWORD64
cpu_register(CONTEXT
* ctx
, unsigned idx
)
452 switch (cpu_register_map
[idx
].ctx_length
)
454 case 2: return *(WORD
*)cpu_register_ptr(ctx
, idx
);
455 case 4: return *(DWORD
*)cpu_register_ptr(ctx
, idx
);
456 case 8: return *(DWORD64
*)cpu_register_ptr(ctx
, idx
);
458 fprintf(stderr
, "got unexpected size: %u\n", (unsigned)cpu_register_map
[idx
].ctx_length
);
464 static inline void cpu_register_hex_from(CONTEXT
* ctx
, unsigned idx
, const char** phex
)
466 if (cpu_register_map
[idx
].gdb_length
== cpu_register_map
[idx
].ctx_length
)
467 hex_from(cpu_register_ptr(ctx
, idx
), *phex
, cpu_register_map
[idx
].gdb_length
);
474 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
476 hex_from(&b
, *phex
, 1);
478 val
+= (DWORD64
)b
<< (8 * i
);
480 switch (cpu_register_map
[idx
].ctx_length
)
482 case 2: *(WORD
*)cpu_register_ptr(ctx
, idx
) = (WORD
)val
; break;
483 case 4: *(DWORD
*)cpu_register_ptr(ctx
, idx
) = (DWORD
)val
; break;
484 case 8: *(DWORD64
*)cpu_register_ptr(ctx
, idx
) = val
; break;
490 /* =============================================== *
491 * W I N 3 2 D E B U G I N T E R F A C E *
492 * =============================================== *
495 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
497 ctx
->ContextFlags
= CONTEXT_CONTROL
499 #if defined(__powerpc__) || defined(__i386__)
500 | CONTEXT_FLOATING_POINT
502 #ifdef CONTEXT_SEGMENTS
505 #ifdef CONTEXT_DEBUG_REGISTERS
506 | CONTEXT_DEBUG_REGISTERS
509 if (!GetThreadContext(h
, ctx
))
511 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
512 fprintf(stderr
, "Can't get thread's context\n");
518 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
520 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
523 switch (rec
->ExceptionCode
)
525 case EXCEPTION_ACCESS_VIOLATION
:
526 case EXCEPTION_PRIV_INSTRUCTION
:
527 case EXCEPTION_STACK_OVERFLOW
:
528 case EXCEPTION_GUARD_PAGE
:
529 gdbctx
->last_sig
= SIGSEGV
;
532 case EXCEPTION_DATATYPE_MISALIGNMENT
:
533 gdbctx
->last_sig
= SIGBUS
;
536 case EXCEPTION_SINGLE_STEP
:
538 case EXCEPTION_BREAKPOINT
:
539 gdbctx
->last_sig
= SIGTRAP
;
542 case EXCEPTION_FLT_DENORMAL_OPERAND
:
543 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
544 case EXCEPTION_FLT_INEXACT_RESULT
:
545 case EXCEPTION_FLT_INVALID_OPERATION
:
546 case EXCEPTION_FLT_OVERFLOW
:
547 case EXCEPTION_FLT_STACK_CHECK
:
548 case EXCEPTION_FLT_UNDERFLOW
:
549 gdbctx
->last_sig
= SIGFPE
;
552 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
553 case EXCEPTION_INT_OVERFLOW
:
554 gdbctx
->last_sig
= SIGFPE
;
557 case EXCEPTION_ILLEGAL_INSTRUCTION
:
558 gdbctx
->last_sig
= SIGILL
;
562 gdbctx
->last_sig
= SIGINT
;
565 case STATUS_POSSIBLE_DEADLOCK
:
566 gdbctx
->last_sig
= SIGALRM
;
568 /* FIXME: we could also add here a O packet with additional information */
571 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
572 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
573 gdbctx
->last_sig
= SIGABRT
;
580 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
587 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
589 switch (de
->dwDebugEventCode
)
591 case CREATE_PROCESS_DEBUG_EVENT
:
592 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
593 de
->u
.CreateProcessInfo
.hProcess
);
594 if (!gdbctx
->process
) break;
595 memory_get_string_indirect(gdbctx
->process
,
596 de
->u
.CreateProcessInfo
.lpImageName
,
597 de
->u
.CreateProcessInfo
.fUnicode
,
598 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
599 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
601 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
602 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
603 de
->dwProcessId
, de
->dwThreadId
,
604 dbg_W2A(u
.buffer
, -1),
605 de
->u
.CreateProcessInfo
.lpImageName
,
606 de
->u
.CreateProcessInfo
.lpStartAddress
,
607 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
608 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
610 /* de->u.CreateProcessInfo.lpStartAddress; */
611 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
612 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
614 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
615 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
616 de
->dwProcessId
, de
->dwThreadId
,
617 de
->u
.CreateProcessInfo
.lpStartAddress
);
619 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
620 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
621 de
->u
.CreateProcessInfo
.hThread
,
622 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
625 case LOAD_DLL_DEBUG_EVENT
:
626 assert(dbg_curr_thread
);
627 memory_get_string_indirect(gdbctx
->process
,
628 de
->u
.LoadDll
.lpImageName
,
629 de
->u
.LoadDll
.fUnicode
,
630 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
631 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
632 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
633 de
->dwProcessId
, de
->dwThreadId
,
634 dbg_W2A(u
.buffer
, -1),
635 de
->u
.LoadDll
.lpBaseOfDll
,
636 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
637 de
->u
.LoadDll
.nDebugInfoSize
);
638 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
639 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
642 case UNLOAD_DLL_DEBUG_EVENT
:
643 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
644 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
645 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
646 SymUnloadModule(gdbctx
->process
->handle
,
647 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
650 case EXCEPTION_DEBUG_EVENT
:
651 assert(dbg_curr_thread
);
652 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
653 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
654 de
->dwProcessId
, de
->dwThreadId
,
655 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
657 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
659 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
663 case CREATE_THREAD_DEBUG_EVENT
:
664 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
665 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
666 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
668 dbg_add_thread(gdbctx
->process
,
670 de
->u
.CreateThread
.hThread
,
671 de
->u
.CreateThread
.lpThreadLocalBase
);
674 case EXIT_THREAD_DEBUG_EVENT
:
675 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
676 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
677 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
679 assert(dbg_curr_thread
);
680 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
681 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
682 dbg_del_thread(dbg_curr_thread
);
685 case EXIT_PROCESS_DEBUG_EVENT
:
686 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
687 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
688 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
690 dbg_del_process(gdbctx
->process
);
691 gdbctx
->process
= NULL
;
692 /* now signal gdb that we're done */
693 gdbctx
->last_sig
= SIGTERM
;
694 gdbctx
->in_trap
= TRUE
;
697 case OUTPUT_DEBUG_STRING_EVENT
:
698 assert(dbg_curr_thread
);
699 memory_get_string(gdbctx
->process
,
700 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
701 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
702 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
703 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
704 de
->dwProcessId
, de
->dwThreadId
, u
.bufferA
);
708 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
709 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
710 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
711 de
->u
.RipInfo
.dwType
);
715 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
716 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
717 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
721 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
725 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
726 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
727 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
728 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
729 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
730 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
731 dbg_curr_thread
->tid
, cont
);
733 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
734 fprintf(stderr
, "Cannot find last thread\n");
738 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
743 if(dbg_curr_thread
->tid
== threadid
){
744 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
745 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
746 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
747 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
748 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
749 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
750 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
751 dbg_curr_thread
->tid
, cont
);
754 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
755 fprintf(stderr
, "Cannot find last thread\n");
758 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
760 struct pollfd pollfd
;
764 pollfd
.fd
= gdbctx
->sock
;
765 pollfd
.events
= POLLIN
;
768 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
769 ret
= read(gdbctx
->sock
, &pkt
, 1);
771 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
772 fprintf(stderr
, "read failed\n");
777 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
778 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
783 } else if (ret
== -1) {
784 fprintf(stderr
, "poll failed\n");
789 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
793 gdbctx
->in_trap
= FALSE
;
796 if (!WaitForDebugEvent(&de
, 10))
798 if (GetLastError() == ERROR_SEM_TIMEOUT
)
800 if (check_for_interrupt(gdbctx
)) {
801 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
802 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
803 fprintf(stderr
, "Failed to break into debugee\n");
807 WaitForDebugEvent(&de
, INFINITE
);
815 handle_debug_event(gdbctx
, &de
);
816 assert(!gdbctx
->process
||
817 gdbctx
->process
->pid
== 0 ||
818 de
.dwProcessId
== gdbctx
->process
->pid
);
819 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
820 if (gdbctx
->in_trap
) break;
821 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
825 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
827 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
828 resume_debuggee(gdbctx
, DBG_CONTINUE
);
830 DebugActiveProcessStop(gdbctx
->process
->pid
);
831 dbg_del_process(gdbctx
->process
);
832 gdbctx
->process
= NULL
;
835 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
839 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
841 strcpy(buffer
, "Unknown process");
844 if (status
== STILL_ACTIVE
)
846 strcpy(buffer
, "Running");
849 snprintf(buffer
, len
, "Terminated (%u)", status
);
851 switch (GetPriorityClass(gdbctx
->process
->handle
))
854 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
855 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
857 #ifdef BELOW_NORMAL_PRIORITY_CLASS
858 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
860 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
861 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
862 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
863 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
865 strcat(buffer
, "\n");
868 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
869 char* buffer
, size_t len
)
871 struct dbg_thread
* thd
;
875 /* FIXME: use the size of buffer */
876 thd
= dbg_get_thread(gdbctx
->process
, tid
);
879 strcpy(buffer
, "No information");
882 if (GetExitCodeThread(thd
->handle
, &status
))
884 if (status
== STILL_ACTIVE
)
886 /* FIXME: this is a bit brutal... some nicer way shall be found */
887 switch (status
= SuspendThread(thd
->handle
))
890 case 0: strcpy(buffer
, "Running"); break;
891 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
893 ResumeThread(thd
->handle
);
896 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
900 strcpy(buffer
, "Unknown threadID");
902 switch (prio
= GetThreadPriority(thd
->handle
))
904 case THREAD_PRIORITY_ERROR_RETURN
: break;
905 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
906 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
907 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
908 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
909 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
910 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
911 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
912 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
914 assert(strlen(buffer
) < len
);
917 /* =============================================== *
918 * P A C K E T U T I L S *
919 * =============================================== *
922 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
923 packet_last_f
= 0x80};
925 static char* packet_realloc(char* buf
, int size
)
928 return HeapAlloc(GetProcessHeap(), 0, size
);
929 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
933 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
935 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
937 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
938 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
942 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
944 packet_reply_grow(gdbctx
, len
* 2);
945 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
946 gdbctx
->out_len
+= len
* 2;
949 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
951 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
954 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
958 shift
= (len
- 1) * 8;
959 packet_reply_grow(gdbctx
, len
* 2);
960 for (i
= 0; i
< len
; i
++, shift
-= 8)
962 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
963 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
967 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
969 packet_reply_grow(gdbctx
, len
);
970 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
971 gdbctx
->out_len
+= len
;
974 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
976 packet_reply_add(gdbctx
, str
, strlen(str
));
979 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
981 packet_reply_add(gdbctx
, &ch
, 1);
984 static void packet_reply_open(struct gdb_context
* gdbctx
)
986 assert(gdbctx
->out_curr_packet
== -1);
987 packet_reply_catc(gdbctx
, '$');
988 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
991 static void packet_reply_close(struct gdb_context
* gdbctx
)
996 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
997 packet_reply_catc(gdbctx
, '#');
998 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
999 packet_reply_hex_to(gdbctx
, &cksum
, 1);
1000 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
1001 fprintf(stderr
, "Reply : %*.*s\n",
1002 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
1003 gdbctx
->out_curr_packet
= -1;
1006 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
1008 packet_reply_open(gdbctx
);
1010 if (len
== -1) len
= strlen(packet
);
1011 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
1013 packet_reply_add(gdbctx
, packet
, len
);
1015 packet_reply_close(gdbctx
);
1020 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
1022 packet_reply_open(gdbctx
);
1024 packet_reply_add(gdbctx
, "E", 1);
1025 packet_reply_val(gdbctx
, error
, 1);
1027 packet_reply_close(gdbctx
);
1032 static inline void packet_reply_register_hex_to(struct gdb_context
* gdbctx
, unsigned idx
)
1034 if (cpu_register_map
[idx
].gdb_length
== cpu_register_map
[idx
].ctx_length
)
1035 packet_reply_hex_to(gdbctx
, cpu_register_ptr(&gdbctx
->context
, idx
), cpu_register_map
[idx
].gdb_length
);
1038 DWORD64 val
= cpu_register(&gdbctx
->context
, idx
);
1041 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
1044 packet_reply_hex_to(gdbctx
, &b
, 1);
1050 /* =============================================== *
1051 * P A C K E T H A N D L E R S *
1052 * =============================================== *
1055 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
1057 enum packet_return ret
= packet_done
;
1059 packet_reply_open(gdbctx
);
1061 if (gdbctx
->process
!= NULL
)
1066 packet_reply_catc(gdbctx
, 'T');
1067 sig
= gdbctx
->last_sig
;
1068 packet_reply_val(gdbctx
, sig
, 1);
1069 packet_reply_add(gdbctx
, "thread:", 7);
1070 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
1071 packet_reply_catc(gdbctx
, ';');
1073 for (i
= 0; i
< cpu_num_regs
; i
++)
1075 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1076 if ((gdbctx
->context
.ContextFlags
& flags
) != flags
)
1079 /* FIXME: this call will also grow the buffer...
1080 * unneeded, but not harmful
1082 packet_reply_val(gdbctx
, i
, 1);
1083 packet_reply_catc(gdbctx
, ':');
1084 packet_reply_register_hex_to(gdbctx
, i
);
1085 packet_reply_catc(gdbctx
, ';');
1090 /* Try to put an exit code
1091 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1092 * just indicate the end of process and exit */
1093 packet_reply_add(gdbctx
, "W00", 3);
1094 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
1097 packet_reply_close(gdbctx
);
1103 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
1105 gdbctx
->extended
= 1;
1110 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
1112 assert(gdbctx
->in_packet_len
== 0);
1113 return packet_reply_status(gdbctx
);
1116 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
1118 /* FIXME: add support for address in packet */
1119 assert(gdbctx
->in_packet_len
== 0);
1120 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1121 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1122 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1123 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1124 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1125 wait_for_debuggee(gdbctx
);
1126 return packet_reply_status(gdbctx
);
1129 static enum packet_return
packet_verbose_cont(struct gdb_context
* gdbctx
)
1132 int defaultAction
= -1; /* magic non action */
1135 int actionIndex
[20]; /* allow for up to 20 actions */
1136 int threadIndex
[20];
1137 int threadCount
= 0;
1138 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1139 unsigned int threadID
= 0;
1140 struct dbg_thread
* thd
;
1142 /* OK we have vCont followed by..
1144 * c for packet_continue
1145 * Csig for packet_continue_signal
1147 * Ssig for step signal
1148 * and then an optional thread ID at the end..
1149 * *******************************************/
1152 if (gdbctx
->in_packet
[4] == '?')
1157 The vCont packet is supported. Each action is a supported command in the vCont packet.
1159 The vCont packet is not supported. (this didn't seem to be obeyed!)
1161 packet_reply_open(gdbctx
);
1162 packet_reply_add(gdbctx
, "vCont", 5);
1163 /* add all the supported actions to the reply (all of them for now) */
1164 packet_reply_add(gdbctx
, ";c", 2);
1165 packet_reply_add(gdbctx
, ";C", 2);
1166 packet_reply_add(gdbctx
, ";s", 2);
1167 packet_reply_add(gdbctx
, ";S", 2);
1168 packet_reply_close(gdbctx
);
1172 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1173 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1174 now if only gdb talked XML.... */
1175 #if 0 /* handy for debugging */
1176 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1179 /* go through the packet and identify where all the actions start at */
1180 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1182 if (gdbctx
->in_packet
[i
] == ';')
1184 threadIndex
[actions
] = 0;
1185 actionIndex
[actions
++] = i
;
1187 else if (gdbctx
->in_packet
[i
] == ':')
1189 threadIndex
[actions
- 1] = i
;
1193 /* now look up the default action */
1194 for (i
= 0 ; i
< actions
; i
++)
1196 if (threadIndex
[i
] == 0)
1198 if (defaultAction
!= -1)
1200 fprintf(stderr
,"Too many default actions specified\n");
1201 return packet_error
;
1207 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1209 /* go through all the threads and stick their ids in the to be done list. */
1210 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1212 threadIDs
[threadCount
++] = thd
->tid
;
1213 /* check to see if we have more threads than I counted on, and tell the user what to do
1214 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1215 if (threadCount
== 100)
1217 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1222 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1223 * that remains is to apply the actions to the threads and the default action to any threads
1225 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1226 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1227 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1228 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1230 /* deal with the threaded stuff first */
1231 for (i
= 0; i
< actions
; i
++)
1233 if (threadIndex
[i
] != 0)
1235 int j
, idLength
= 0;
1236 if (i
< actions
- 1)
1238 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1242 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1245 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1246 /* process the action */
1247 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1249 case 's': /* step */
1250 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1252 case 'c': /* continue */
1253 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1255 case 'S': /* step Sig, */
1256 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1258 case 'C': /* continue sig */
1259 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1260 /* cannot change signals on the fly */
1261 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1262 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1263 if (sig
!= gdbctx
->last_sig
)
1264 return packet_error
;
1265 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1268 for (j
= 0 ; j
< threadCount
; j
++)
1270 if (threadIDs
[j
] == threadID
)
1277 } /* for i=0 ; i< actions */
1279 /* now we have manage the default action */
1280 if (defaultAction
>= 0)
1282 for (i
= 0 ; i
< threadCount
; i
++)
1284 /* check to see if we've already done something to the thread*/
1285 if (threadIDs
[i
] != 0)
1287 /* if not apply the default action*/
1288 threadID
= threadIDs
[i
];
1289 /* process the action (yes this is almost identical to the one above!) */
1290 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1292 case 's': /* step */
1293 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1295 case 'c': /* continue */
1296 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1299 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1301 case 'C': /* continue sig */
1302 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1303 /* cannot change signals on the fly */
1304 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1305 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1306 if (sig
!= gdbctx
->last_sig
)
1307 return packet_error
;
1308 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1313 } /* if(defaultAction >=0) */
1315 wait_for_debuggee(gdbctx
);
1316 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1317 return packet_reply_status(gdbctx
);
1320 struct verbose_defail
1324 enum packet_return (*handler
)(struct gdb_context
*);
1325 } verbose_details
[] =
1327 /* {"Attach", 6}, */
1328 {"Cont", 4, packet_verbose_cont
},
1338 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1343 for (klen
= 0; ; klen
++)
1345 if (klen
== gdbctx
->in_packet_len
||
1346 gdbctx
->in_packet
[klen
] == ';' ||
1347 gdbctx
->in_packet
[klen
] == ':' ||
1348 gdbctx
->in_packet
[klen
] == '?')
1350 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1351 fprintf(stderr
, "trying to process a verbose packet %*.*s\n",
1352 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1353 for (i
= 0; i
< sizeof(verbose_details
)/sizeof(verbose_details
[0]); i
++)
1355 if (klen
== verbose_details
[i
].len
&&
1356 !memcmp(gdbctx
->in_packet
, verbose_details
[i
].name
, verbose_details
[i
].len
))
1358 return verbose_details
[i
].handler(gdbctx
);
1361 /* no matching handler found, abort */
1366 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1367 fprintf(stderr
, "No support for verbose packet %*.*s\n",
1368 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1369 return packet_error
;
1372 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1376 /* FIXME: add support for address in packet */
1377 assert(gdbctx
->in_packet_len
== 2);
1378 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1379 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1380 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1381 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1382 hex_from(&sig
, gdbctx
->in_packet
, 1);
1383 /* cannot change signals on the fly */
1384 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1385 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1386 if (sig
!= gdbctx
->last_sig
)
1387 return packet_error
;
1388 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1389 wait_for_debuggee(gdbctx
);
1390 return packet_reply_status(gdbctx
);
1393 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1395 detach_debuggee(gdbctx
, FALSE
);
1396 return packet_ok
| packet_last_f
;
1399 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1404 assert(gdbctx
->in_trap
);
1406 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1408 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, &ctx
))
1409 return packet_error
;
1412 packet_reply_open(gdbctx
);
1413 for (i
= 0; i
< cpu_num_regs
; i
++)
1415 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1416 if ((gdbctx
->context
.ContextFlags
& flags
) != flags
)
1418 packet_reply_register_hex_to(gdbctx
, i
);
1420 packet_reply_close(gdbctx
);
1424 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1428 CONTEXT
* pctx
= &gdbctx
->context
;
1431 assert(gdbctx
->in_trap
);
1432 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1434 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1435 return packet_error
;
1437 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1439 ptr
= gdbctx
->in_packet
;
1440 for (i
= 0; i
< cpu_num_regs
; i
++)
1442 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1443 if ((pctx
->ContextFlags
& flags
) != flags
)
1445 cpu_register_hex_from(pctx
, i
, &ptr
);
1447 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1449 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1450 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1451 return packet_error
;
1456 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1458 detach_debuggee(gdbctx
, TRUE
);
1460 if (!gdbctx
->extended
)
1461 /* dunno whether GDB cares or not */
1465 /* assume we can't really answer something here */
1466 /* return packet_done; */
1469 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1474 switch (gdbctx
->in_packet
[0])
1478 if (gdbctx
->in_packet
[1] == '-')
1479 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1481 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1482 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1484 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1485 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1486 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1487 gdbctx
->in_packet
+ 1);
1488 return packet_error
;
1490 if (gdbctx
->in_packet
[0] == 'c')
1491 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1493 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1496 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1497 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1498 return packet_error
;
1502 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1505 unsigned int len
, blk_len
, nread
;
1509 assert(gdbctx
->in_trap
);
1510 /* FIXME:check in_packet_len for reading %p,%x */
1511 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1512 if (len
<= 0) return packet_error
;
1513 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1514 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1515 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1517 blk_len
= min(sizeof(buffer
), len
- nread
);
1518 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1521 /* fail at first address, return error */
1522 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1523 /* something has already been read, return partial information */
1526 if (nread
== 0) packet_reply_open(gdbctx
);
1527 packet_reply_hex_to(gdbctx
, buffer
, r
);
1529 packet_reply_close(gdbctx
);
1533 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1536 unsigned int len
, blk_len
;
1541 assert(gdbctx
->in_trap
);
1542 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1545 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1546 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1547 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1548 return packet_error
;
1552 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1554 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1555 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1556 return packet_error
;
1558 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1560 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1561 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1562 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1563 return packet_error
;
1565 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1566 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1569 blk_len
= min(sizeof(buffer
), len
);
1570 hex_from(buffer
, ptr
, blk_len
);
1571 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1578 return packet_ok
; /* FIXME: error while writing ? */
1581 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1585 CONTEXT
* pctx
= &gdbctx
->context
;
1587 assert(gdbctx
->in_trap
);
1588 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1589 if (reg
>= cpu_num_regs
)
1591 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1592 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1593 return packet_error
;
1595 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1597 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1598 return packet_error
;
1600 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1602 if (cpu_register_map
[reg
].ctx_length
<= sizeof(DWORD64
))
1603 fprintf(stderr
, "Read register %x => %08x%08x\n", reg
,
1604 (unsigned)(cpu_register(pctx
, reg
) >> 32), (unsigned)cpu_register(pctx
, reg
));
1606 fprintf(stderr
, "Read register %x\n", reg
);
1608 packet_reply_open(gdbctx
);
1609 packet_reply_register_hex_to(gdbctx
, reg
);
1610 packet_reply_close(gdbctx
);
1614 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1619 CONTEXT
* pctx
= &gdbctx
->context
;
1621 assert(gdbctx
->in_trap
);
1623 reg
= strtoul(gdbctx
->in_packet
, &ptr
, 16);
1624 if (ptr
== NULL
|| reg
>= cpu_num_regs
|| *ptr
++ != '=')
1626 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1627 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1628 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1629 * it wouldn't matter too much, and it fakes our support for all regs
1631 return (ptr
== NULL
) ? packet_error
: packet_ok
;
1633 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1635 int len
= gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
);
1636 fprintf(stderr
, "Writing reg %u <= %*.*s\n", reg
, len
, len
, ptr
);
1639 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1641 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1642 return packet_error
;
1644 if ((pctx
->ContextFlags
& cpu_register_map
[reg
].ctx_flags
) != cpu_register_map
[reg
].ctx_flags
)
1646 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1647 fprintf(stderr
, "Writing reg %u is not supported on this host\n", reg
);
1648 return packet_error
;
1651 cpu_register_hex_from(pctx
, reg
, (const char**)&ptr
);
1652 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1654 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1655 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1656 return packet_error
;
1662 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1670 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1671 strcpy(clsName
, "-- Unknown --");
1672 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1673 strcpy(wndName
, "-- Empty --");
1675 packet_reply_open(gdbctx
);
1676 packet_reply_catc(gdbctx
, 'O');
1677 snprintf(buffer
, sizeof(buffer
),
1678 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1679 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1680 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1681 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1683 packet_reply_hex_to_str(gdbctx
, buffer
);
1684 packet_reply_close(gdbctx
);
1686 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1687 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1688 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1691 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1695 /* we do the output in several 'O' packets, with the last one being just OK for
1696 * marking the end of the output */
1697 packet_reply_open(gdbctx
);
1698 packet_reply_catc(gdbctx
, 'O');
1699 snprintf(buffer
, sizeof(buffer
),
1700 "%-16.16s %-17.17s %-8.8s %s\n",
1701 "hwnd", "Class Name", " Style", " WndProc Text");
1702 packet_reply_hex_to_str(gdbctx
, buffer
);
1703 packet_reply_close(gdbctx
);
1705 /* FIXME: could also add a pmt to this command in str... */
1706 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1707 packet_reply(gdbctx
, "OK", 2);
1710 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1712 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1713 char buffer
[31+MAX_PATH
];
1715 PROCESSENTRY32 entry
;
1718 if (snap
== INVALID_HANDLE_VALUE
)
1721 entry
.dwSize
= sizeof(entry
);
1722 ok
= Process32First(snap
, &entry
);
1724 /* we do the output in several 'O' packets, with the last one being just OK for
1725 * marking the end of the output */
1727 packet_reply_open(gdbctx
);
1728 packet_reply_catc(gdbctx
, 'O');
1729 snprintf(buffer
, sizeof(buffer
),
1730 " %-8.8s %-8.8s %-8.8s %s\n",
1731 "pid", "threads", "parent", "executable");
1732 packet_reply_hex_to_str(gdbctx
, buffer
);
1733 packet_reply_close(gdbctx
);
1738 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1739 packet_reply_open(gdbctx
);
1740 packet_reply_catc(gdbctx
, 'O');
1741 snprintf(buffer
, sizeof(buffer
),
1742 "%c%08x %-8d %08x '%s'\n",
1743 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1744 entry
.th32ParentProcessID
, entry
.szExeFile
);
1745 packet_reply_hex_to_str(gdbctx
, buffer
);
1746 packet_reply_close(gdbctx
);
1747 ok
= Process32Next(snap
, &entry
);
1750 packet_reply(gdbctx
, "OK", 2);
1753 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1755 MEMORY_BASIC_INFORMATION mbi
;
1762 /* we do the output in several 'O' packets, with the last one being just OK for
1763 * marking the end of the output */
1764 packet_reply_open(gdbctx
);
1765 packet_reply_catc(gdbctx
, 'O');
1766 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1767 packet_reply_close(gdbctx
);
1769 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1773 case MEM_COMMIT
: state
= "commit "; break;
1774 case MEM_FREE
: state
= "free "; break;
1775 case MEM_RESERVE
: state
= "reserve"; break;
1776 default: state
= "??? "; break;
1778 if (mbi
.State
!= MEM_FREE
)
1782 case MEM_IMAGE
: type
= "image "; break;
1783 case MEM_MAPPED
: type
= "mapped "; break;
1784 case MEM_PRIVATE
: type
= "private"; break;
1785 case 0: type
= " "; break;
1786 default: type
= "??? "; break;
1788 memset(prot
, ' ' , sizeof(prot
)-1);
1789 prot
[sizeof(prot
)-1] = '\0';
1790 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1792 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1794 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1796 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1804 packet_reply_open(gdbctx
);
1805 snprintf(buffer
, sizeof(buffer
), "%0*lx %0*lx %s %s %s\n",
1806 (unsigned)sizeof(void*), (DWORD_PTR
)addr
,
1807 (unsigned)sizeof(void*), mbi
.RegionSize
, state
, type
, prot
);
1808 packet_reply_catc(gdbctx
, 'O');
1809 packet_reply_hex_to_str(gdbctx
, buffer
);
1810 packet_reply_close(gdbctx
);
1812 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1814 addr
+= mbi
.RegionSize
;
1816 packet_reply(gdbctx
, "OK", 2);
1819 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1820 int len
, const char* str
)
1826 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1828 else if (len
>= 2 && str
[0] == '=')
1830 unsigned val
= atoi(&str
[1]);
1831 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1832 gdbctx
->trace
= val
;
1836 /* FIXME: ugly but can use error packet here */
1837 packet_reply_cat(gdbctx
, "E00");
1840 packet_reply_open(gdbctx
);
1841 packet_reply_hex_to_str(gdbctx
, buffer
);
1842 packet_reply_close(gdbctx
);
1850 void (*handler
)(struct gdb_context
*, int, const char*);
1853 {0, "wnd", 3, packet_query_monitor_wnd
},
1854 {0, "window", 6, packet_query_monitor_wnd
},
1855 {0, "proc", 4, packet_query_monitor_process
},
1856 {0, "process", 7, packet_query_monitor_process
},
1857 {0, "mem", 3, packet_query_monitor_mem
},
1858 {1, "trace", 5, packet_query_monitor_trace
},
1862 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1863 const char* hxcmd
, size_t len
)
1866 struct query_detail
* qd
;
1868 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1870 hex_from(buffer
, hxcmd
, len
);
1872 for (qd
= query_details
; qd
->name
!= NULL
; qd
++)
1874 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1875 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1877 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1880 return packet_reply_error(gdbctx
, EINVAL
);
1883 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1885 switch (gdbctx
->in_packet
[0])
1888 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1890 struct dbg_thread
* thd
;
1892 packet_reply_open(gdbctx
);
1893 packet_reply_add(gdbctx
, "m", 1);
1894 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1896 packet_reply_val(gdbctx
, thd
->tid
, 4);
1897 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1898 packet_reply_add(gdbctx
, ",", 1);
1900 packet_reply_close(gdbctx
);
1903 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1907 packet_reply_open(gdbctx
);
1908 packet_reply_catc(gdbctx
, 'O');
1909 get_process_info(gdbctx
, result
, sizeof(result
));
1910 packet_reply_hex_to_str(gdbctx
, result
);
1911 packet_reply_close(gdbctx
);
1916 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1918 packet_reply(gdbctx
, "l", 1);
1921 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1923 packet_reply(gdbctx
, "l", 1);
1928 if (strncmp(gdbctx
->in_packet
, "Attached", gdbctx
->in_packet_len
) == 0)
1934 return packet_reply(gdbctx
, buf
, -1);
1938 if (gdbctx
->in_packet_len
== 1)
1940 struct dbg_thread
* thd
;
1941 /* FIXME: doc says 16 bit val ??? */
1942 /* grab first created thread, aka last in list */
1943 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
1944 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
1945 packet_reply_open(gdbctx
);
1946 packet_reply_add(gdbctx
, "QC", 2);
1947 packet_reply_val(gdbctx
, thd
->tid
, 4);
1948 packet_reply_close(gdbctx
);
1953 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1957 snprintf(buf
, sizeof(buf
),
1958 "Text=%08lx;Data=%08lx;Bss=%08lx",
1959 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1960 gdbctx
->wine_segs
[2]);
1961 return packet_reply(gdbctx
, buf
, -1);
1965 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1967 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1968 gdbctx
->in_packet_len
- 5);
1972 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1974 if (strncmp(gdbctx
->in_packet
, "Supported", 9) == 0)
1976 if (strlen(target_xml
))
1977 return packet_reply(gdbctx
, "PacketSize=400;qXfer:features:read+", -1);
1980 /* no features supported */
1981 packet_reply_open(gdbctx
);
1982 packet_reply_close(gdbctx
);
1988 if (gdbctx
->in_packet_len
> 15 &&
1989 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1990 gdbctx
->in_packet
[15] == ',')
1996 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1997 if (end
== NULL
) break;
1998 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1999 packet_reply_open(gdbctx
);
2000 packet_reply_hex_to_str(gdbctx
, result
);
2001 packet_reply_close(gdbctx
);
2004 if (strncmp(gdbctx
->in_packet
, "TStatus", 7) == 0)
2006 /* Tracepoints not supported */
2007 packet_reply_open(gdbctx
);
2008 packet_reply_close(gdbctx
);
2013 if (strlen(target_xml
) && strncmp(gdbctx
->in_packet
, "Xfer:features:read:target.xml", 29) == 0)
2014 return packet_reply(gdbctx
, target_xml
, -1);
2017 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2018 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
2019 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
2020 return packet_error
;
2023 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
2025 /* FIXME: add support for address in packet */
2026 assert(gdbctx
->in_packet_len
== 0);
2027 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
2028 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
2029 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
2030 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
2031 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
2032 resume_debuggee(gdbctx
, DBG_CONTINUE
);
2033 wait_for_debuggee(gdbctx
);
2034 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
2035 return packet_reply_status(gdbctx
);
2039 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
2043 /* FIXME: add support for address in packet */
2044 assert(gdbctx
->in_packet_len
== 2);
2045 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
2046 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2047 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
2048 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
2049 hex_from(&sig
, gdbctx
->in_packet
, 1);
2050 /* cannot change signals on the fly */
2051 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2052 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
2053 if (sig
!= gdbctx
->last_sig
)
2054 return packet_error
;
2055 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
2056 wait_for_debuggee(gdbctx
);
2057 return packet_reply_status(gdbctx
);
2061 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
2066 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
2067 if (tid
== -1 || tid
== 0)
2068 return packet_reply_error(gdbctx
, EINVAL
);
2069 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
2071 return packet_reply_error(gdbctx
, ESRCH
);
2074 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
2078 struct gdb_ctx_Xpoint
* xpt
;
2079 enum be_xpoint_type t
;
2081 /* FIXME: check packet_len */
2082 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2083 gdbctx
->in_packet
[1] != ',' ||
2084 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2085 return packet_error
;
2086 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2087 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
2088 addr
, len
, gdbctx
->in_packet
[0]);
2089 switch (gdbctx
->in_packet
[0])
2091 case '0': t
= be_xpoint_break
; len
= 0; break;
2092 case '1': t
= be_xpoint_watch_exec
; break;
2093 case '2': t
= be_xpoint_watch_read
; break;
2094 case '3': t
= be_xpoint_watch_write
; break;
2095 default: return packet_error
;
2097 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2099 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2101 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
2102 gdbctx
->process
->process_io
, &gdbctx
->context
,
2103 t
, xpt
->addr
, xpt
->val
, len
))
2111 return packet_error
;
2114 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
2118 struct gdb_ctx_Xpoint
* xpt
;
2119 enum be_xpoint_type t
;
2121 /* FIXME: check packet_len */
2122 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2123 gdbctx
->in_packet
[1] != ',' ||
2124 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2125 return packet_error
;
2126 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2127 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
2128 addr
, len
, gdbctx
->in_packet
[0]);
2129 switch (gdbctx
->in_packet
[0])
2131 case '0': t
= be_xpoint_break
; len
= 0; break;
2132 case '1': t
= be_xpoint_watch_exec
; break;
2133 case '2': t
= be_xpoint_watch_read
; break;
2134 case '3': t
= be_xpoint_watch_write
; break;
2135 default: return packet_error
;
2137 /* because of packet command handling, this should be made idempotent */
2138 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2140 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2141 return packet_ok
; /* nothing to do */
2143 /* really set the Xpoint */
2144 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2146 if (xpt
->type
== -1)
2148 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
2149 gdbctx
->process
->process_io
, &gdbctx
->context
,
2150 t
, addr
, &xpt
->val
, len
))
2156 fprintf(stderr
, "cannot set xpoint\n");
2160 /* no more entries... eech */
2161 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
2162 return packet_error
;
2165 /* =============================================== *
2166 * P A C K E T I N F R A S T R U C T U R E *
2167 * =============================================== *
2173 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
2176 static struct packet_entry packet_entries
[] =
2178 /*{'!', packet_extended}, */
2179 {'?', packet_last_signal
},
2180 {'c', packet_continue
},
2181 {'C', packet_continue_signal
},
2182 {'D', packet_detach
},
2183 {'g', packet_read_registers
},
2184 {'G', packet_write_registers
},
2186 {'H', packet_thread
},
2187 {'m', packet_read_memory
},
2188 {'M', packet_write_memory
},
2189 {'p', packet_read_register
},
2190 {'P', packet_write_register
},
2191 {'q', packet_query
},
2192 /* {'Q', packet_set}, */
2193 /* {'R', packet,restart}, only in extended mode ! */
2195 /*{'S', packet_step_signal}, hard(er) to implement */
2196 {'T', packet_thread_alive
},
2197 {'v', packet_verbose
},
2198 {'z', packet_remove_breakpoint
},
2199 {'Z', packet_set_breakpoint
},
2202 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2206 unsigned char in_cksum
, loc_cksum
;
2208 enum packet_return ret
= packet_error
;
2211 while ((ret
& packet_last_f
) == 0)
2213 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2214 fprintf(stderr
, "In-buf: %*.*s\n",
2215 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2216 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2217 if (ptr
== NULL
) return FALSE
;
2218 if (ptr
!= gdbctx
->in_buf
)
2220 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2221 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2222 fprintf(stderr
, "Removing garbage: %*.*s\n",
2223 glen
, glen
, gdbctx
->in_buf
);
2224 gdbctx
->in_len
-= glen
;
2225 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2227 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2228 if (end
== NULL
) return FALSE
;
2229 /* no checksum yet */
2230 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2231 plen
= end
- gdbctx
->in_buf
- 1;
2232 hex_from(&in_cksum
, end
+ 1, 1);
2233 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2234 if (loc_cksum
== in_cksum
)
2236 if (num_packet
== 0) {
2241 write(gdbctx
->sock
, "+", 1);
2244 /* FIXME: should use bsearch if packet_entries was sorted */
2245 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2247 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2249 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2251 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2252 fprintf(stderr
, "Unknown packet request %*.*s\n",
2253 plen
, plen
, &gdbctx
->in_buf
[1]);
2257 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2258 gdbctx
->in_packet_len
= plen
- 1;
2259 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2260 fprintf(stderr
, "Packet: %c%*.*s\n",
2262 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2264 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2266 switch (ret
& ~packet_last_f
)
2268 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2269 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2270 case packet_done
: break;
2272 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2273 fprintf(stderr
, "Reply-full: %*.*s\n",
2274 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2275 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2276 assert(i
== gdbctx
->out_len
);
2277 /* if this fails, we'll have to use POLLOUT...
2279 gdbctx
->out_len
= 0;
2284 /* FIXME: If we have more than one packet in our input buffer,
2285 * it's very likely that we took too long to answer to a given packet
2286 * and gdb is sending us the same packet again.
2287 * So we simply drop the second packet. This will lower the risk of error,
2288 * but there are still some race conditions here.
2289 * A better fix (yet not perfect) would be to have two threads:
2290 * - one managing the packets for gdb
2291 * - the second one managing the commands...
2292 * This would allow us to send the reply with the '+' character (Ack of
2293 * the command) way sooner than we do now.
2295 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2296 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2301 write(gdbctx
->sock
, "+", 1);
2302 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2303 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2305 gdbctx
->in_len
-= plen
+ 4;
2306 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2311 static int fetch_data(struct gdb_context
* gdbctx
)
2313 int len
, in_len
= gdbctx
->in_len
;
2315 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2319 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2320 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2322 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2323 fprintf(stderr
, "%d %d %*.*s\n",
2324 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2325 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2326 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2327 if (len
<= 0) break;
2328 gdbctx
->in_len
+= len
;
2329 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2330 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2332 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2333 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2334 return gdbctx
->in_len
- in_len
;
2337 #define FLAG_NO_START 1
2338 #define FLAG_WITH_XTERM 2
2340 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2344 const char *gdb_path
, *tmp_path
;
2347 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2348 if (!(tmp_path
= getenv("TMPDIR"))) tmp_path
= "/tmp";
2349 strcpy(buf
, tmp_path
);
2350 strcat(buf
, "/winegdb.XXXXXX");
2351 fd
= mkstemps(buf
, 0);
2352 if (fd
== -1) return FALSE
;
2353 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2354 fprintf(f
, "file %s\n", wine_path
);
2355 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2356 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2357 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2358 /* gdb 5.1 seems to require it, won't hurt anyway */
2359 fprintf(f
, "sharedlibrary\n");
2360 /* This is needed (but not a decent & final fix)
2361 * Without this, gdb would skip our inter-DLL relay code (because
2362 * we don't have any line number information for the relay code)
2363 * With this, we will stop on first instruction of the stub, and
2364 * reusing step, will get us through the relay stub at the actual
2365 * function we're looking at.
2367 fprintf(f
, "set step-mode on\n");
2368 /* tell gdb to delete this file when done handling it... */
2369 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2371 if (flags
& FLAG_WITH_XTERM
)
2372 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2374 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2375 assert(0); /* never reached */
2379 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2382 struct sockaddr_in s_addrs
;
2383 socklen_t s_len
= sizeof(s_addrs
);
2384 struct pollfd pollfd
;
2385 IMAGEHLP_MODULE64 imh_mod
;
2388 /* step 1: create socket for gdb connection request */
2389 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2391 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2392 fprintf(stderr
, "Can't create socket");
2396 if (listen(sock
, 1) == -1 || getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2399 /* step 2: do the process internal creation */
2400 handle_debug_event(gdbctx
, de
);
2402 /* step3: get the wine loader name */
2403 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
))
2406 /* step 4: fire up gdb (if requested) */
2407 if (flags
& FLAG_NO_START
)
2408 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2412 case -1: /* error in parent... */
2413 fprintf(stderr
, "Cannot create gdb\n");
2415 default: /* in parent... success */
2416 signal(SIGINT
, SIG_IGN
);
2418 case 0: /* in child... and alive */
2419 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2420 /* if we're here, exec failed, so report failure */
2424 /* step 5: wait for gdb to connect actually */
2426 pollfd
.events
= POLLIN
;
2429 switch (poll(&pollfd
, 1, -1))
2432 if (pollfd
.revents
& POLLIN
)
2435 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2436 if (gdbctx
->sock
== -1)
2439 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2440 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2441 /* don't keep our small packets too long: send them ASAP back to GDB
2442 * without this, GDB really crawls
2444 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2448 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2449 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2452 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2453 fprintf(stderr
, "Poll for cnx failed (error)\n");
2464 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2470 gdbctx
->in_buf
= NULL
;
2471 gdbctx
->in_buf_alloc
= 0;
2473 gdbctx
->out_buf
= NULL
;
2474 gdbctx
->out_buf_alloc
= 0;
2475 gdbctx
->out_len
= 0;
2476 gdbctx
->out_curr_packet
= -1;
2478 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2479 gdbctx
->last_sig
= 0;
2480 gdbctx
->in_trap
= FALSE
;
2481 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2482 gdbctx
->process
= NULL
;
2483 for (i
= 0; i
< NUM_XPOINT
; i
++)
2484 gdbctx
->Xpoints
[i
].type
= -1;
2485 for (i
= 0; i
< sizeof(gdbctx
->wine_segs
) / sizeof(gdbctx
->wine_segs
[0]); i
++)
2486 gdbctx
->wine_segs
[i
] = 0;
2488 /* wait for first trap */
2489 while (WaitForDebugEvent(&de
, INFINITE
))
2491 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2493 /* this should be the first event we get,
2494 * and the only one of this type */
2495 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2496 /* gdbctx->dwProcessId = pid; */
2497 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2498 assert(!gdbctx
->in_trap
);
2502 handle_debug_event(gdbctx
, &de
);
2503 if (gdbctx
->in_trap
) break;
2505 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2510 static int gdb_remote(unsigned flags
)
2512 struct pollfd pollfd
;
2513 struct gdb_context gdbctx
;
2516 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2518 pollfd
.fd
= gdbctx
.sock
;
2519 pollfd
.events
= POLLIN
;
2522 switch (poll(&pollfd
, 1, -1))
2526 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2528 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2529 fprintf(stderr
, "Gdb hung up\n");
2530 /* kill also debuggee process - questionnable - */
2531 detach_debuggee(&gdbctx
, TRUE
);
2535 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2537 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2541 /* timeout, should never happen (infinite timeout) */
2544 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2545 fprintf(stderr
, "Poll failed\n");
2555 int gdb_main(int argc
, char* argv
[])
2558 unsigned gdb_flags
= 0;
2561 while (argc
> 0 && argv
[0][0] == '-')
2563 if (strcmp(argv
[0], "--no-start") == 0)
2565 gdb_flags
|= FLAG_NO_START
;
2569 if (strcmp(argv
[0], "--with-xterm") == 0)
2571 gdb_flags
|= FLAG_WITH_XTERM
;
2577 if (dbg_active_attach(argc
, argv
) == start_ok
||
2578 dbg_active_launch(argc
, argv
) == start_ok
)
2579 return gdb_remote(gdb_flags
);
2581 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");