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(X0
, 8, CONTEXT_INTEGER
),
403 REG(X1
, 8, CONTEXT_INTEGER
),
404 REG(X2
, 8, CONTEXT_INTEGER
),
405 REG(X3
, 8, CONTEXT_INTEGER
),
406 REG(X4
, 8, CONTEXT_INTEGER
),
407 REG(X5
, 8, CONTEXT_INTEGER
),
408 REG(X6
, 8, CONTEXT_INTEGER
),
409 REG(X7
, 8, CONTEXT_INTEGER
),
410 REG(X8
, 8, CONTEXT_INTEGER
),
411 REG(X9
, 8, CONTEXT_INTEGER
),
412 REG(X10
, 8, CONTEXT_INTEGER
),
413 REG(X11
, 8, CONTEXT_INTEGER
),
414 REG(X12
, 8, CONTEXT_INTEGER
),
415 REG(X13
, 8, CONTEXT_INTEGER
),
416 REG(X14
, 8, CONTEXT_INTEGER
),
417 REG(X15
, 8, CONTEXT_INTEGER
),
418 REG(X16
, 8, CONTEXT_INTEGER
),
419 REG(X17
, 8, CONTEXT_INTEGER
),
420 REG(X18
, 8, CONTEXT_INTEGER
),
421 REG(X19
, 8, CONTEXT_INTEGER
),
422 REG(X20
, 8, CONTEXT_INTEGER
),
423 REG(X21
, 8, CONTEXT_INTEGER
),
424 REG(X22
, 8, CONTEXT_INTEGER
),
425 REG(X23
, 8, CONTEXT_INTEGER
),
426 REG(X24
, 8, CONTEXT_INTEGER
),
427 REG(X25
, 8, CONTEXT_INTEGER
),
428 REG(X26
, 8, CONTEXT_INTEGER
),
429 REG(X27
, 8, CONTEXT_INTEGER
),
430 REG(X28
, 8, CONTEXT_INTEGER
),
431 REG(X29
, 8, CONTEXT_INTEGER
),
432 REG(X30
, 8, CONTEXT_INTEGER
),
433 REG(Sp
, 8, CONTEXT_CONTROL
),
434 REG(Pc
, 8, CONTEXT_CONTROL
),
435 REG(PState
, 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
)
1403 CONTEXT
* pctx
= &gdbctx
->context
;
1405 assert(gdbctx
->in_trap
);
1407 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1409 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1410 return packet_error
;
1413 packet_reply_open(gdbctx
);
1414 for (i
= 0; i
< cpu_num_regs
; i
++)
1416 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1417 if ((gdbctx
->context
.ContextFlags
& flags
) != flags
)
1419 packet_reply_register_hex_to(gdbctx
, i
);
1421 packet_reply_close(gdbctx
);
1425 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1429 CONTEXT
* pctx
= &gdbctx
->context
;
1432 assert(gdbctx
->in_trap
);
1433 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1435 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1436 return packet_error
;
1438 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1440 ptr
= gdbctx
->in_packet
;
1441 for (i
= 0; i
< cpu_num_regs
; i
++)
1443 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1444 if ((pctx
->ContextFlags
& flags
) != flags
)
1446 cpu_register_hex_from(pctx
, i
, &ptr
);
1448 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1450 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1451 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1452 return packet_error
;
1457 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1459 detach_debuggee(gdbctx
, TRUE
);
1461 if (!gdbctx
->extended
)
1462 /* dunno whether GDB cares or not */
1466 /* assume we can't really answer something here */
1467 /* return packet_done; */
1470 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1475 switch (gdbctx
->in_packet
[0])
1479 if (gdbctx
->in_packet
[1] == '-')
1480 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1482 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1483 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1485 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1486 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1487 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1488 gdbctx
->in_packet
+ 1);
1489 return packet_error
;
1491 if (gdbctx
->in_packet
[0] == 'c')
1492 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1494 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1497 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1498 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1499 return packet_error
;
1503 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1506 unsigned int len
, blk_len
, nread
;
1510 assert(gdbctx
->in_trap
);
1511 /* FIXME:check in_packet_len for reading %p,%x */
1512 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1513 if (len
<= 0) return packet_error
;
1514 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1515 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1516 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1518 blk_len
= min(sizeof(buffer
), len
- nread
);
1519 if (!gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1522 /* fail at first address, return error */
1523 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1524 /* something has already been read, return partial information */
1527 if (nread
== 0) packet_reply_open(gdbctx
);
1528 packet_reply_hex_to(gdbctx
, buffer
, r
);
1530 packet_reply_close(gdbctx
);
1534 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1537 unsigned int len
, blk_len
;
1542 assert(gdbctx
->in_trap
);
1543 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1546 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1547 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1548 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1549 return packet_error
;
1553 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1555 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1556 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1557 return packet_error
;
1559 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1561 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1562 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1563 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1564 return packet_error
;
1566 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1567 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1570 blk_len
= min(sizeof(buffer
), len
);
1571 hex_from(buffer
, ptr
, blk_len
);
1572 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1579 return packet_ok
; /* FIXME: error while writing ? */
1582 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1586 CONTEXT
* pctx
= &gdbctx
->context
;
1588 assert(gdbctx
->in_trap
);
1589 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1590 if (reg
>= cpu_num_regs
)
1592 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1593 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1594 return packet_error
;
1596 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1598 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1599 return packet_error
;
1601 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1603 if (cpu_register_map
[reg
].ctx_length
<= sizeof(DWORD64
))
1604 fprintf(stderr
, "Read register %x => %08x%08x\n", reg
,
1605 (unsigned)(cpu_register(pctx
, reg
) >> 32), (unsigned)cpu_register(pctx
, reg
));
1607 fprintf(stderr
, "Read register %x\n", reg
);
1609 packet_reply_open(gdbctx
);
1610 packet_reply_register_hex_to(gdbctx
, reg
);
1611 packet_reply_close(gdbctx
);
1615 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1620 CONTEXT
* pctx
= &gdbctx
->context
;
1622 assert(gdbctx
->in_trap
);
1624 reg
= strtoul(gdbctx
->in_packet
, &ptr
, 16);
1625 if (ptr
== NULL
|| reg
>= cpu_num_regs
|| *ptr
++ != '=')
1627 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1628 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1629 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1630 * it wouldn't matter too much, and it fakes our support for all regs
1632 return (ptr
== NULL
) ? packet_error
: packet_ok
;
1634 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1636 int len
= gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
);
1637 fprintf(stderr
, "Writing reg %u <= %*.*s\n", reg
, len
, len
, ptr
);
1640 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1642 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1643 return packet_error
;
1645 if ((pctx
->ContextFlags
& cpu_register_map
[reg
].ctx_flags
) != cpu_register_map
[reg
].ctx_flags
)
1647 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1648 fprintf(stderr
, "Writing reg %u is not supported on this host\n", reg
);
1649 return packet_error
;
1652 cpu_register_hex_from(pctx
, reg
, (const char**)&ptr
);
1653 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1655 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1656 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1657 return packet_error
;
1663 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1671 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1672 strcpy(clsName
, "-- Unknown --");
1673 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1674 strcpy(wndName
, "-- Empty --");
1676 packet_reply_open(gdbctx
);
1677 packet_reply_catc(gdbctx
, 'O');
1678 snprintf(buffer
, sizeof(buffer
),
1679 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1680 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1681 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1682 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1684 packet_reply_hex_to_str(gdbctx
, buffer
);
1685 packet_reply_close(gdbctx
);
1687 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1688 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1689 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1692 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1696 /* we do the output in several 'O' packets, with the last one being just OK for
1697 * marking the end of the output */
1698 packet_reply_open(gdbctx
);
1699 packet_reply_catc(gdbctx
, 'O');
1700 snprintf(buffer
, sizeof(buffer
),
1701 "%-16.16s %-17.17s %-8.8s %s\n",
1702 "hwnd", "Class Name", " Style", " WndProc Text");
1703 packet_reply_hex_to_str(gdbctx
, buffer
);
1704 packet_reply_close(gdbctx
);
1706 /* FIXME: could also add a pmt to this command in str... */
1707 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1708 packet_reply(gdbctx
, "OK", 2);
1711 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1713 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1716 PROCESSENTRY32 entry
;
1719 if (snap
== INVALID_HANDLE_VALUE
)
1722 entry
.dwSize
= sizeof(entry
);
1723 ok
= Process32First(snap
, &entry
);
1725 /* we do the output in several 'O' packets, with the last one being just OK for
1726 * marking the end of the output */
1728 packet_reply_open(gdbctx
);
1729 packet_reply_catc(gdbctx
, 'O');
1730 snprintf(buffer
, sizeof(buffer
),
1731 " %-8.8s %-8.8s %-8.8s %s\n",
1732 "pid", "threads", "parent", "executable");
1733 packet_reply_hex_to_str(gdbctx
, buffer
);
1734 packet_reply_close(gdbctx
);
1739 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1740 packet_reply_open(gdbctx
);
1741 packet_reply_catc(gdbctx
, 'O');
1742 snprintf(buffer
, sizeof(buffer
),
1743 "%c%08x %-8d %08x '%s'\n",
1744 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1745 entry
.th32ParentProcessID
, entry
.szExeFile
);
1746 packet_reply_hex_to_str(gdbctx
, buffer
);
1747 packet_reply_close(gdbctx
);
1748 ok
= Process32Next(snap
, &entry
);
1751 packet_reply(gdbctx
, "OK", 2);
1754 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1756 MEMORY_BASIC_INFORMATION mbi
;
1763 /* we do the output in several 'O' packets, with the last one being just OK for
1764 * marking the end of the output */
1765 packet_reply_open(gdbctx
);
1766 packet_reply_catc(gdbctx
, 'O');
1767 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1768 packet_reply_close(gdbctx
);
1770 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1774 case MEM_COMMIT
: state
= "commit "; break;
1775 case MEM_FREE
: state
= "free "; break;
1776 case MEM_RESERVE
: state
= "reserve"; break;
1777 default: state
= "??? "; break;
1779 if (mbi
.State
!= MEM_FREE
)
1783 case MEM_IMAGE
: type
= "image "; break;
1784 case MEM_MAPPED
: type
= "mapped "; break;
1785 case MEM_PRIVATE
: type
= "private"; break;
1786 case 0: type
= " "; break;
1787 default: type
= "??? "; break;
1789 memset(prot
, ' ' , sizeof(prot
)-1);
1790 prot
[sizeof(prot
)-1] = '\0';
1791 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1793 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1795 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1797 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1805 packet_reply_open(gdbctx
);
1806 snprintf(buffer
, sizeof(buffer
), "%0*lx %0*lx %s %s %s\n",
1807 (unsigned)sizeof(void*), (DWORD_PTR
)addr
,
1808 (unsigned)sizeof(void*), mbi
.RegionSize
, state
, type
, prot
);
1809 packet_reply_catc(gdbctx
, 'O');
1810 packet_reply_hex_to_str(gdbctx
, buffer
);
1811 packet_reply_close(gdbctx
);
1813 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1815 addr
+= mbi
.RegionSize
;
1817 packet_reply(gdbctx
, "OK", 2);
1820 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1821 int len
, const char* str
)
1827 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1829 else if (len
>= 2 && str
[0] == '=')
1831 unsigned val
= atoi(&str
[1]);
1832 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1833 gdbctx
->trace
= val
;
1837 /* FIXME: ugly but can use error packet here */
1838 packet_reply_cat(gdbctx
, "E00");
1841 packet_reply_open(gdbctx
);
1842 packet_reply_hex_to_str(gdbctx
, buffer
);
1843 packet_reply_close(gdbctx
);
1851 void (*handler
)(struct gdb_context
*, int, const char*);
1854 {0, "wnd", 3, packet_query_monitor_wnd
},
1855 {0, "window", 6, packet_query_monitor_wnd
},
1856 {0, "proc", 4, packet_query_monitor_process
},
1857 {0, "process", 7, packet_query_monitor_process
},
1858 {0, "mem", 3, packet_query_monitor_mem
},
1859 {1, "trace", 5, packet_query_monitor_trace
},
1863 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1864 const char* hxcmd
, size_t len
)
1867 struct query_detail
* qd
;
1869 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1871 hex_from(buffer
, hxcmd
, len
);
1873 for (qd
= query_details
; qd
->name
!= NULL
; qd
++)
1875 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1876 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1878 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1881 return packet_reply_error(gdbctx
, EINVAL
);
1884 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1886 switch (gdbctx
->in_packet
[0])
1889 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1891 struct dbg_thread
* thd
;
1893 packet_reply_open(gdbctx
);
1894 packet_reply_add(gdbctx
, "m", 1);
1895 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1897 packet_reply_val(gdbctx
, thd
->tid
, 4);
1898 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1899 packet_reply_add(gdbctx
, ",", 1);
1901 packet_reply_close(gdbctx
);
1904 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1908 packet_reply_open(gdbctx
);
1909 packet_reply_catc(gdbctx
, 'O');
1910 get_process_info(gdbctx
, result
, sizeof(result
));
1911 packet_reply_hex_to_str(gdbctx
, result
);
1912 packet_reply_close(gdbctx
);
1917 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1919 packet_reply(gdbctx
, "l", 1);
1922 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1924 packet_reply(gdbctx
, "l", 1);
1929 if (strncmp(gdbctx
->in_packet
, "Attached", gdbctx
->in_packet_len
) == 0)
1935 return packet_reply(gdbctx
, buf
, -1);
1939 if (gdbctx
->in_packet_len
== 1)
1941 struct dbg_thread
* thd
;
1942 /* FIXME: doc says 16 bit val ??? */
1943 /* grab first created thread, aka last in list */
1944 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
1945 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
1946 packet_reply_open(gdbctx
);
1947 packet_reply_add(gdbctx
, "QC", 2);
1948 packet_reply_val(gdbctx
, thd
->tid
, 4);
1949 packet_reply_close(gdbctx
);
1954 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1958 snprintf(buf
, sizeof(buf
),
1959 "Text=%08lx;Data=%08lx;Bss=%08lx",
1960 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1961 gdbctx
->wine_segs
[2]);
1962 return packet_reply(gdbctx
, buf
, -1);
1966 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1968 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1969 gdbctx
->in_packet_len
- 5);
1973 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1975 if (strncmp(gdbctx
->in_packet
, "Supported", 9) == 0)
1977 if (strlen(target_xml
))
1978 return packet_reply(gdbctx
, "PacketSize=400;qXfer:features:read+", -1);
1981 /* no features supported */
1982 packet_reply_open(gdbctx
);
1983 packet_reply_close(gdbctx
);
1989 if (gdbctx
->in_packet_len
> 15 &&
1990 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1991 gdbctx
->in_packet
[15] == ',')
1997 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1998 if (end
== NULL
) break;
1999 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
2000 packet_reply_open(gdbctx
);
2001 packet_reply_hex_to_str(gdbctx
, result
);
2002 packet_reply_close(gdbctx
);
2005 if (strncmp(gdbctx
->in_packet
, "TStatus", 7) == 0)
2007 /* Tracepoints not supported */
2008 packet_reply_open(gdbctx
);
2009 packet_reply_close(gdbctx
);
2014 if (strlen(target_xml
) && strncmp(gdbctx
->in_packet
, "Xfer:features:read:target.xml", 29) == 0)
2015 return packet_reply(gdbctx
, target_xml
, -1);
2018 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2019 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
2020 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
2021 return packet_error
;
2024 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
2026 /* FIXME: add support for address in packet */
2027 assert(gdbctx
->in_packet_len
== 0);
2028 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
2029 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
2030 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
2031 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
2032 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
2033 resume_debuggee(gdbctx
, DBG_CONTINUE
);
2034 wait_for_debuggee(gdbctx
);
2035 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
2036 return packet_reply_status(gdbctx
);
2040 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
2044 /* FIXME: add support for address in packet */
2045 assert(gdbctx
->in_packet_len
== 2);
2046 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
2047 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2048 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
2049 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
2050 hex_from(&sig
, gdbctx
->in_packet
, 1);
2051 /* cannot change signals on the fly */
2052 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2053 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
2054 if (sig
!= gdbctx
->last_sig
)
2055 return packet_error
;
2056 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
2057 wait_for_debuggee(gdbctx
);
2058 return packet_reply_status(gdbctx
);
2062 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
2067 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
2068 if (tid
== -1 || tid
== 0)
2069 return packet_reply_error(gdbctx
, EINVAL
);
2070 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
2072 return packet_reply_error(gdbctx
, ESRCH
);
2075 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
2079 struct gdb_ctx_Xpoint
* xpt
;
2080 enum be_xpoint_type t
;
2082 /* FIXME: check packet_len */
2083 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2084 gdbctx
->in_packet
[1] != ',' ||
2085 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2086 return packet_error
;
2087 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2088 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
2089 addr
, len
, gdbctx
->in_packet
[0]);
2090 switch (gdbctx
->in_packet
[0])
2092 case '0': t
= be_xpoint_break
; len
= 0; break;
2093 case '1': t
= be_xpoint_watch_exec
; break;
2094 case '2': t
= be_xpoint_watch_read
; break;
2095 case '3': t
= be_xpoint_watch_write
; break;
2096 default: return packet_error
;
2098 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2100 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2102 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
2103 gdbctx
->process
->process_io
, &gdbctx
->context
,
2104 t
, xpt
->addr
, xpt
->val
, len
))
2112 return packet_error
;
2115 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
2119 struct gdb_ctx_Xpoint
* xpt
;
2120 enum be_xpoint_type t
;
2122 /* FIXME: check packet_len */
2123 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2124 gdbctx
->in_packet
[1] != ',' ||
2125 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2126 return packet_error
;
2127 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2128 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
2129 addr
, len
, gdbctx
->in_packet
[0]);
2130 switch (gdbctx
->in_packet
[0])
2132 case '0': t
= be_xpoint_break
; len
= 0; break;
2133 case '1': t
= be_xpoint_watch_exec
; break;
2134 case '2': t
= be_xpoint_watch_read
; break;
2135 case '3': t
= be_xpoint_watch_write
; break;
2136 default: return packet_error
;
2138 /* because of packet command handling, this should be made idempotent */
2139 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2141 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2142 return packet_ok
; /* nothing to do */
2144 /* really set the Xpoint */
2145 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2147 if (xpt
->type
== -1)
2149 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
2150 gdbctx
->process
->process_io
, &gdbctx
->context
,
2151 t
, addr
, &xpt
->val
, len
))
2157 fprintf(stderr
, "cannot set xpoint\n");
2161 /* no more entries... eech */
2162 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
2163 return packet_error
;
2166 /* =============================================== *
2167 * P A C K E T I N F R A S T R U C T U R E *
2168 * =============================================== *
2174 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
2177 static struct packet_entry packet_entries
[] =
2179 /*{'!', packet_extended}, */
2180 {'?', packet_last_signal
},
2181 {'c', packet_continue
},
2182 {'C', packet_continue_signal
},
2183 {'D', packet_detach
},
2184 {'g', packet_read_registers
},
2185 {'G', packet_write_registers
},
2187 {'H', packet_thread
},
2188 {'m', packet_read_memory
},
2189 {'M', packet_write_memory
},
2190 {'p', packet_read_register
},
2191 {'P', packet_write_register
},
2192 {'q', packet_query
},
2193 /* {'Q', packet_set}, */
2194 /* {'R', packet,restart}, only in extended mode ! */
2196 /*{'S', packet_step_signal}, hard(er) to implement */
2197 {'T', packet_thread_alive
},
2198 {'v', packet_verbose
},
2199 {'z', packet_remove_breakpoint
},
2200 {'Z', packet_set_breakpoint
},
2203 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2207 unsigned char in_cksum
, loc_cksum
;
2209 enum packet_return ret
= packet_error
;
2212 while ((ret
& packet_last_f
) == 0)
2214 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2215 fprintf(stderr
, "In-buf: %*.*s\n",
2216 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2217 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2218 if (ptr
== NULL
) return FALSE
;
2219 if (ptr
!= gdbctx
->in_buf
)
2221 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2222 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2223 fprintf(stderr
, "Removing garbage: %*.*s\n",
2224 glen
, glen
, gdbctx
->in_buf
);
2225 gdbctx
->in_len
-= glen
;
2226 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2228 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2229 if (end
== NULL
) return FALSE
;
2230 /* no checksum yet */
2231 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2232 plen
= end
- gdbctx
->in_buf
- 1;
2233 hex_from(&in_cksum
, end
+ 1, 1);
2234 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2235 if (loc_cksum
== in_cksum
)
2237 if (num_packet
== 0) {
2242 write(gdbctx
->sock
, "+", 1);
2245 /* FIXME: should use bsearch if packet_entries was sorted */
2246 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2248 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2250 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2252 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2253 fprintf(stderr
, "Unknown packet request %*.*s\n",
2254 plen
, plen
, &gdbctx
->in_buf
[1]);
2258 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2259 gdbctx
->in_packet_len
= plen
- 1;
2260 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2261 fprintf(stderr
, "Packet: %c%*.*s\n",
2263 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2265 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2267 switch (ret
& ~packet_last_f
)
2269 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2270 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2271 case packet_done
: break;
2273 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2274 fprintf(stderr
, "Reply-full: %*.*s\n",
2275 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2276 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2277 assert(i
== gdbctx
->out_len
);
2278 /* if this fails, we'll have to use POLLOUT...
2280 gdbctx
->out_len
= 0;
2285 /* FIXME: If we have more than one packet in our input buffer,
2286 * it's very likely that we took too long to answer to a given packet
2287 * and gdb is sending us the same packet again.
2288 * So we simply drop the second packet. This will lower the risk of error,
2289 * but there's still some race conditions here.
2290 * A better fix (yet not perfect) would be to have two threads:
2291 * - one managing the packets for gdb
2292 * - the second one managing the commands...
2293 * This would allow us to send the reply with the '+' character (Ack of
2294 * the command) way sooner than we do now.
2296 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2297 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2302 write(gdbctx
->sock
, "+", 1);
2303 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2304 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2306 gdbctx
->in_len
-= plen
+ 4;
2307 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2312 static int fetch_data(struct gdb_context
* gdbctx
)
2314 int len
, in_len
= gdbctx
->in_len
;
2316 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2320 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2321 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2323 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2324 fprintf(stderr
, "%d %d %*.*s\n",
2325 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2326 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2327 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2328 if (len
<= 0) break;
2329 gdbctx
->in_len
+= len
;
2330 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2331 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2333 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2334 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2335 return gdbctx
->in_len
- in_len
;
2338 #define FLAG_NO_START 1
2339 #define FLAG_WITH_XTERM 2
2341 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2345 const char* gdb_path
;
2348 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2349 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2350 fd
= mkstemps(buf
, 0);
2351 if (fd
== -1) return FALSE
;
2352 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2353 fprintf(f
, "file %s\n", wine_path
);
2354 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2355 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2356 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2357 /* gdb 5.1 seems to require it, won't hurt anyway */
2358 fprintf(f
, "sharedlibrary\n");
2359 /* This is needed (but not a decent & final fix)
2360 * Without this, gdb would skip our inter-DLL relay code (because
2361 * we don't have any line number information for the relay code)
2362 * With this, we will stop on first instruction of the stub, and
2363 * reusing step, will get us through the relay stub at the actual
2364 * function we're looking at.
2366 fprintf(f
, "set step-mode on\n");
2367 /* tell gdb to delete this file when done handling it... */
2368 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2370 if (flags
& FLAG_WITH_XTERM
)
2371 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2373 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2374 assert(0); /* never reached */
2378 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2381 struct sockaddr_in s_addrs
;
2382 socklen_t s_len
= sizeof(s_addrs
);
2383 struct pollfd pollfd
;
2384 IMAGEHLP_MODULE64 imh_mod
;
2387 /* step 1: create socket for gdb connection request */
2388 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2390 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2391 fprintf(stderr
, "Can't create socket");
2395 if (listen(sock
, 1) == -1 || getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2398 /* step 2: do the process internal creation */
2399 handle_debug_event(gdbctx
, de
);
2401 /* step3: get the wine loader name */
2402 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
))
2405 /* step 4: fire up gdb (if requested) */
2406 if (flags
& FLAG_NO_START
)
2407 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2411 case -1: /* error in parent... */
2412 fprintf(stderr
, "Cannot create gdb\n");
2414 default: /* in parent... success */
2415 signal(SIGINT
, SIG_IGN
);
2417 case 0: /* in child... and alive */
2418 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2419 /* if we're here, exec failed, so report failure */
2423 /* step 5: wait for gdb to connect actually */
2425 pollfd
.events
= POLLIN
;
2428 switch (poll(&pollfd
, 1, -1))
2431 if (pollfd
.revents
& POLLIN
)
2434 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2435 if (gdbctx
->sock
== -1)
2438 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2439 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2440 /* don't keep our small packets too long: send them ASAP back to GDB
2441 * without this, GDB really crawls
2443 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2447 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2448 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2451 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2452 fprintf(stderr
, "Poll for cnx failed (error)\n");
2463 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2469 gdbctx
->in_buf
= NULL
;
2470 gdbctx
->in_buf_alloc
= 0;
2472 gdbctx
->out_buf
= NULL
;
2473 gdbctx
->out_buf_alloc
= 0;
2474 gdbctx
->out_len
= 0;
2475 gdbctx
->out_curr_packet
= -1;
2477 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2478 gdbctx
->last_sig
= 0;
2479 gdbctx
->in_trap
= FALSE
;
2480 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2481 gdbctx
->process
= NULL
;
2482 for (i
= 0; i
< NUM_XPOINT
; i
++)
2483 gdbctx
->Xpoints
[i
].type
= -1;
2484 for (i
= 0; i
< sizeof(gdbctx
->wine_segs
) / sizeof(gdbctx
->wine_segs
[0]); i
++)
2485 gdbctx
->wine_segs
[i
] = 0;
2487 /* wait for first trap */
2488 while (WaitForDebugEvent(&de
, INFINITE
))
2490 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2492 /* this should be the first event we get,
2493 * and the only one of this type */
2494 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2495 /* gdbctx->dwProcessId = pid; */
2496 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2497 assert(!gdbctx
->in_trap
);
2501 handle_debug_event(gdbctx
, &de
);
2502 if (gdbctx
->in_trap
) break;
2504 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2509 static int gdb_remote(unsigned flags
)
2511 struct pollfd pollfd
;
2512 struct gdb_context gdbctx
;
2515 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2517 pollfd
.fd
= gdbctx
.sock
;
2518 pollfd
.events
= POLLIN
;
2521 switch (poll(&pollfd
, 1, -1))
2525 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2527 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2528 fprintf(stderr
, "Gdb hung up\n");
2529 /* kill also debuggee process - questionnable - */
2530 detach_debuggee(&gdbctx
, TRUE
);
2534 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2536 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2540 /* timeout, should never happen (infinite timeout) */
2543 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2544 fprintf(stderr
, "Poll failed\n");
2554 int gdb_main(int argc
, char* argv
[])
2557 unsigned gdb_flags
= 0;
2560 while (argc
> 0 && argv
[0][0] == '-')
2562 if (strcmp(argv
[0], "--no-start") == 0)
2564 gdb_flags
|= FLAG_NO_START
;
2568 if (strcmp(argv
[0], "--with-xterm") == 0)
2570 gdb_flags
|= FLAG_WITH_XTERM
;
2576 if (dbg_active_attach(argc
, argv
) == start_ok
||
2577 dbg_active_launch(argc
, argv
) == start_ok
)
2578 return gdb_remote(gdb_flags
);
2580 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");