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) == be_xpoint_free 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 typedef struct DECLSPEC_ALIGN(16) _M128A
{
222 typedef struct _XMM_SAVE_AREA32
{
223 WORD ControlWord
; /* 000 */
224 WORD StatusWord
; /* 002 */
225 BYTE TagWord
; /* 004 */
226 BYTE Reserved1
; /* 005 */
227 WORD ErrorOpcode
; /* 006 */
228 DWORD ErrorOffset
; /* 008 */
229 WORD ErrorSelector
; /* 00c */
230 WORD Reserved2
; /* 00e */
231 DWORD DataOffset
; /* 010 */
232 WORD DataSelector
; /* 014 */
233 WORD Reserved3
; /* 016 */
234 DWORD MxCsr
; /* 018 */
235 DWORD MxCsr_Mask
; /* 01c */
236 M128A FloatRegisters
[8]; /* 020 */
237 M128A XmmRegisters
[16]; /* 0a0 */
238 BYTE Reserved4
[96]; /* 1a0 */
239 } XMM_SAVE_AREA32
, *PXMM_SAVE_AREA32
;
241 static const char target_xml
[] = "";
242 static struct cpu_register cpu_register_map
[] = {
243 REG(Eax
, 4, CONTEXT_INTEGER
),
244 REG(Ecx
, 4, CONTEXT_INTEGER
),
245 REG(Edx
, 4, CONTEXT_INTEGER
),
246 REG(Ebx
, 4, CONTEXT_INTEGER
),
247 REG(Esp
, 4, CONTEXT_CONTROL
),
248 REG(Ebp
, 4, CONTEXT_CONTROL
),
249 REG(Esi
, 4, CONTEXT_INTEGER
),
250 REG(Edi
, 4, CONTEXT_INTEGER
),
251 REG(Eip
, 4, CONTEXT_CONTROL
),
252 REG(EFlags
, 4, CONTEXT_CONTROL
),
253 REG(SegCs
, 4, CONTEXT_CONTROL
),
254 REG(SegSs
, 4, CONTEXT_SEGMENTS
),
255 REG(SegDs
, 4, CONTEXT_SEGMENTS
),
256 REG(SegEs
, 4, CONTEXT_SEGMENTS
),
257 REG(SegFs
, 4, CONTEXT_SEGMENTS
),
258 REG(SegGs
, 4, CONTEXT_SEGMENTS
),
259 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[ 0]), 10, 10, CONTEXT_FLOATING_POINT
},
260 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[10]), 10, 10, CONTEXT_FLOATING_POINT
},
261 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[20]), 10, 10, CONTEXT_FLOATING_POINT
},
262 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[30]), 10, 10, CONTEXT_FLOATING_POINT
},
263 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[40]), 10, 10, CONTEXT_FLOATING_POINT
},
264 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[50]), 10, 10, CONTEXT_FLOATING_POINT
},
265 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[60]), 10, 10, CONTEXT_FLOATING_POINT
},
266 { FIELD_OFFSET(CONTEXT
, FloatSave
.RegisterArea
[70]), 10, 10, CONTEXT_FLOATING_POINT
},
267 { FIELD_OFFSET(CONTEXT
, FloatSave
.ControlWord
), 2, 4, CONTEXT_FLOATING_POINT
},
268 { FIELD_OFFSET(CONTEXT
, FloatSave
.StatusWord
), 2, 4, CONTEXT_FLOATING_POINT
},
269 { FIELD_OFFSET(CONTEXT
, FloatSave
.TagWord
), 2, 4, CONTEXT_FLOATING_POINT
},
270 { FIELD_OFFSET(CONTEXT
, FloatSave
.ErrorSelector
), 2, 4, CONTEXT_FLOATING_POINT
},
271 REG(FloatSave
.ErrorOffset
, 4, CONTEXT_FLOATING_POINT
),
272 { FIELD_OFFSET(CONTEXT
, FloatSave
.DataSelector
), 2, 4, CONTEXT_FLOATING_POINT
},
273 REG(FloatSave
.DataOffset
, 4, CONTEXT_FLOATING_POINT
),
274 { FIELD_OFFSET(CONTEXT
, FloatSave
.ErrorSelector
)+2, 2, 4, CONTEXT_FLOATING_POINT
},
275 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[0]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
276 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[1]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
277 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[2]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
278 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[3]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
279 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[4]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
280 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[5]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
281 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[6]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
282 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, XmmRegisters
[7]), 16, 16, CONTEXT_EXTENDED_REGISTERS
},
283 { FIELD_OFFSET(CONTEXT
, ExtendedRegisters
) + FIELD_OFFSET(XMM_SAVE_AREA32
, MxCsr
), 4, 4, CONTEXT_EXTENDED_REGISTERS
},
285 #elif defined(__powerpc__)
286 static const char target_xml
[] = "";
287 static struct cpu_register cpu_register_map
[] = {
288 REG(Gpr0
, 4, CONTEXT_INTEGER
),
289 REG(Gpr1
, 4, CONTEXT_INTEGER
),
290 REG(Gpr2
, 4, CONTEXT_INTEGER
),
291 REG(Gpr3
, 4, CONTEXT_INTEGER
),
292 REG(Gpr4
, 4, CONTEXT_INTEGER
),
293 REG(Gpr5
, 4, CONTEXT_INTEGER
),
294 REG(Gpr6
, 4, CONTEXT_INTEGER
),
295 REG(Gpr7
, 4, CONTEXT_INTEGER
),
296 REG(Gpr8
, 4, CONTEXT_INTEGER
),
297 REG(Gpr9
, 4, CONTEXT_INTEGER
),
298 REG(Gpr10
, 4, CONTEXT_INTEGER
),
299 REG(Gpr11
, 4, CONTEXT_INTEGER
),
300 REG(Gpr12
, 4, CONTEXT_INTEGER
),
301 REG(Gpr13
, 4, CONTEXT_INTEGER
),
302 REG(Gpr14
, 4, CONTEXT_INTEGER
),
303 REG(Gpr15
, 4, CONTEXT_INTEGER
),
304 REG(Gpr16
, 4, CONTEXT_INTEGER
),
305 REG(Gpr17
, 4, CONTEXT_INTEGER
),
306 REG(Gpr18
, 4, CONTEXT_INTEGER
),
307 REG(Gpr19
, 4, CONTEXT_INTEGER
),
308 REG(Gpr20
, 4, CONTEXT_INTEGER
),
309 REG(Gpr21
, 4, CONTEXT_INTEGER
),
310 REG(Gpr22
, 4, CONTEXT_INTEGER
),
311 REG(Gpr23
, 4, CONTEXT_INTEGER
),
312 REG(Gpr24
, 4, CONTEXT_INTEGER
),
313 REG(Gpr25
, 4, CONTEXT_INTEGER
),
314 REG(Gpr26
, 4, CONTEXT_INTEGER
),
315 REG(Gpr27
, 4, CONTEXT_INTEGER
),
316 REG(Gpr28
, 4, CONTEXT_INTEGER
),
317 REG(Gpr29
, 4, CONTEXT_INTEGER
),
318 REG(Gpr30
, 4, CONTEXT_INTEGER
),
319 REG(Gpr31
, 4, CONTEXT_INTEGER
),
320 REG(Fpr0
, 4, CONTEXT_FLOATING_POINT
),
321 REG(Fpr1
, 4, CONTEXT_FLOATING_POINT
),
322 REG(Fpr2
, 4, CONTEXT_FLOATING_POINT
),
323 REG(Fpr3
, 4, CONTEXT_FLOATING_POINT
),
324 REG(Fpr4
, 4, CONTEXT_FLOATING_POINT
),
325 REG(Fpr5
, 4, CONTEXT_FLOATING_POINT
),
326 REG(Fpr6
, 4, CONTEXT_FLOATING_POINT
),
327 REG(Fpr7
, 4, CONTEXT_FLOATING_POINT
),
328 REG(Fpr8
, 4, CONTEXT_FLOATING_POINT
),
329 REG(Fpr9
, 4, CONTEXT_FLOATING_POINT
),
330 REG(Fpr10
, 4, CONTEXT_FLOATING_POINT
),
331 REG(Fpr11
, 4, CONTEXT_FLOATING_POINT
),
332 REG(Fpr12
, 4, CONTEXT_FLOATING_POINT
),
333 REG(Fpr13
, 4, CONTEXT_FLOATING_POINT
),
334 REG(Fpr14
, 4, CONTEXT_FLOATING_POINT
),
335 REG(Fpr15
, 4, CONTEXT_FLOATING_POINT
),
336 REG(Fpr16
, 4, CONTEXT_FLOATING_POINT
),
337 REG(Fpr17
, 4, CONTEXT_FLOATING_POINT
),
338 REG(Fpr18
, 4, CONTEXT_FLOATING_POINT
),
339 REG(Fpr19
, 4, CONTEXT_FLOATING_POINT
),
340 REG(Fpr20
, 4, CONTEXT_FLOATING_POINT
),
341 REG(Fpr21
, 4, CONTEXT_FLOATING_POINT
),
342 REG(Fpr22
, 4, CONTEXT_FLOATING_POINT
),
343 REG(Fpr23
, 4, CONTEXT_FLOATING_POINT
),
344 REG(Fpr24
, 4, CONTEXT_FLOATING_POINT
),
345 REG(Fpr25
, 4, CONTEXT_FLOATING_POINT
),
346 REG(Fpr26
, 4, CONTEXT_FLOATING_POINT
),
347 REG(Fpr27
, 4, CONTEXT_FLOATING_POINT
),
348 REG(Fpr28
, 4, CONTEXT_FLOATING_POINT
),
349 REG(Fpr29
, 4, CONTEXT_FLOATING_POINT
),
350 REG(Fpr30
, 4, CONTEXT_FLOATING_POINT
),
351 REG(Fpr31
, 4, CONTEXT_FLOATING_POINT
),
353 REG(Iar
, 4, CONTEXT_CONTROL
),
354 REG(Msr
, 4, CONTEXT_CONTROL
),
355 REG(Cr
, 4, CONTEXT_INTEGER
),
356 REG(Lr
, 4, CONTEXT_CONTROL
),
357 REG(Ctr
, 4, CONTEXT_CONTROL
),
358 REG(Xer
, 4, CONTEXT_INTEGER
),
359 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
360 /* see gdb/nlm/ppc.c */
362 #elif defined(__x86_64__)
363 static const char target_xml
[] = "";
364 static struct cpu_register cpu_register_map
[] = {
365 REG(Rax
, 8, CONTEXT_INTEGER
),
366 REG(Rbx
, 8, CONTEXT_INTEGER
),
367 REG(Rcx
, 8, CONTEXT_INTEGER
),
368 REG(Rdx
, 8, CONTEXT_INTEGER
),
369 REG(Rsi
, 8, CONTEXT_INTEGER
),
370 REG(Rdi
, 8, CONTEXT_INTEGER
),
371 REG(Rbp
, 8, CONTEXT_INTEGER
),
372 REG(Rsp
, 8, CONTEXT_INTEGER
),
373 REG(R8
, 8, CONTEXT_INTEGER
),
374 REG(R9
, 8, CONTEXT_INTEGER
),
375 REG(R10
, 8, CONTEXT_INTEGER
),
376 REG(R11
, 8, CONTEXT_INTEGER
),
377 REG(R12
, 8, CONTEXT_INTEGER
),
378 REG(R13
, 8, CONTEXT_INTEGER
),
379 REG(R14
, 8, CONTEXT_INTEGER
),
380 REG(R15
, 8, CONTEXT_INTEGER
),
381 REG(Rip
, 8, CONTEXT_CONTROL
),
382 REG(EFlags
, 4, CONTEXT_CONTROL
),
383 REG(SegCs
, 4, CONTEXT_CONTROL
),
384 REG(SegSs
, 4, CONTEXT_CONTROL
),
385 REG(SegDs
, 4, CONTEXT_SEGMENTS
),
386 REG(SegEs
, 4, CONTEXT_SEGMENTS
),
387 REG(SegFs
, 4, CONTEXT_SEGMENTS
),
388 REG(SegGs
, 4, CONTEXT_SEGMENTS
),
389 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 0]), 10, 10, CONTEXT_FLOATING_POINT
},
390 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 1]), 10, 10, CONTEXT_FLOATING_POINT
},
391 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 2]), 10, 10, CONTEXT_FLOATING_POINT
},
392 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 3]), 10, 10, CONTEXT_FLOATING_POINT
},
393 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 4]), 10, 10, CONTEXT_FLOATING_POINT
},
394 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 5]), 10, 10, CONTEXT_FLOATING_POINT
},
395 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 6]), 10, 10, CONTEXT_FLOATING_POINT
},
396 { FIELD_OFFSET(CONTEXT
, u
.FltSave
.FloatRegisters
[ 7]), 10, 10, CONTEXT_FLOATING_POINT
},
397 REG(u
.FltSave
.ControlWord
, 4, CONTEXT_FLOATING_POINT
),
398 REG(u
.FltSave
.StatusWord
, 4, CONTEXT_FLOATING_POINT
),
399 REG(u
.FltSave
.TagWord
, 4, CONTEXT_FLOATING_POINT
),
400 REG(u
.FltSave
.ErrorSelector
, 4, CONTEXT_FLOATING_POINT
),
401 REG(u
.FltSave
.ErrorOffset
, 4, CONTEXT_FLOATING_POINT
),
402 REG(u
.FltSave
.DataSelector
, 4, CONTEXT_FLOATING_POINT
),
403 REG(u
.FltSave
.DataOffset
, 4, CONTEXT_FLOATING_POINT
),
404 REG(u
.FltSave
.ErrorOpcode
, 4, CONTEXT_FLOATING_POINT
),
405 REG(u
.s
.Xmm0
, 16, CONTEXT_FLOATING_POINT
),
406 REG(u
.s
.Xmm1
, 16, CONTEXT_FLOATING_POINT
),
407 REG(u
.s
.Xmm2
, 16, CONTEXT_FLOATING_POINT
),
408 REG(u
.s
.Xmm3
, 16, CONTEXT_FLOATING_POINT
),
409 REG(u
.s
.Xmm4
, 16, CONTEXT_FLOATING_POINT
),
410 REG(u
.s
.Xmm5
, 16, CONTEXT_FLOATING_POINT
),
411 REG(u
.s
.Xmm6
, 16, CONTEXT_FLOATING_POINT
),
412 REG(u
.s
.Xmm7
, 16, CONTEXT_FLOATING_POINT
),
413 REG(u
.s
.Xmm8
, 16, CONTEXT_FLOATING_POINT
),
414 REG(u
.s
.Xmm9
, 16, CONTEXT_FLOATING_POINT
),
415 REG(u
.s
.Xmm10
, 16, CONTEXT_FLOATING_POINT
),
416 REG(u
.s
.Xmm11
, 16, CONTEXT_FLOATING_POINT
),
417 REG(u
.s
.Xmm12
, 16, CONTEXT_FLOATING_POINT
),
418 REG(u
.s
.Xmm13
, 16, CONTEXT_FLOATING_POINT
),
419 REG(u
.s
.Xmm14
, 16, CONTEXT_FLOATING_POINT
),
420 REG(u
.s
.Xmm15
, 16, CONTEXT_FLOATING_POINT
),
421 REG(u
.FltSave
.MxCsr
, 4, CONTEXT_FLOATING_POINT
),
423 #elif defined(__arm__)
424 static const char target_xml
[] =
425 "l <target><architecture>arm</architecture>\n"
426 "<feature name=\"org.gnu.gdb.arm.core\">\n"
427 " <reg name=\"r0\" bitsize=\"32\" type=\"uint32\"/>\n"
428 " <reg name=\"r1\" bitsize=\"32\" type=\"uint32\"/>\n"
429 " <reg name=\"r2\" bitsize=\"32\" type=\"uint32\"/>\n"
430 " <reg name=\"r3\" bitsize=\"32\" type=\"uint32\"/>\n"
431 " <reg name=\"r4\" bitsize=\"32\" type=\"uint32\"/>\n"
432 " <reg name=\"r5\" bitsize=\"32\" type=\"uint32\"/>\n"
433 " <reg name=\"r6\" bitsize=\"32\" type=\"uint32\"/>\n"
434 " <reg name=\"r7\" bitsize=\"32\" type=\"uint32\"/>\n"
435 " <reg name=\"r8\" bitsize=\"32\" type=\"uint32\"/>\n"
436 " <reg name=\"r9\" bitsize=\"32\" type=\"uint32\"/>\n"
437 " <reg name=\"r10\" bitsize=\"32\" type=\"uint32\"/>\n"
438 " <reg name=\"r11\" bitsize=\"32\" type=\"uint32\"/>\n"
439 " <reg name=\"r12\" bitsize=\"32\" type=\"uint32\"/>\n"
440 " <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n"
441 " <reg name=\"lr\" bitsize=\"32\"/>\n"
442 " <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n"
443 " <reg name=\"cpsr\" bitsize=\"32\"/>\n"
444 "</feature></target>\n";
446 static struct cpu_register cpu_register_map
[] = {
447 REG(R0
, 4, CONTEXT_INTEGER
),
448 REG(R1
, 4, CONTEXT_INTEGER
),
449 REG(R2
, 4, CONTEXT_INTEGER
),
450 REG(R3
, 4, CONTEXT_INTEGER
),
451 REG(R4
, 4, CONTEXT_INTEGER
),
452 REG(R5
, 4, CONTEXT_INTEGER
),
453 REG(R6
, 4, CONTEXT_INTEGER
),
454 REG(R7
, 4, CONTEXT_INTEGER
),
455 REG(R8
, 4, CONTEXT_INTEGER
),
456 REG(R9
, 4, CONTEXT_INTEGER
),
457 REG(R10
, 4, CONTEXT_INTEGER
),
458 REG(R11
, 4, CONTEXT_INTEGER
),
459 REG(R12
, 4, CONTEXT_INTEGER
),
460 REG(Sp
, 4, CONTEXT_CONTROL
),
461 REG(Lr
, 4, CONTEXT_CONTROL
),
462 REG(Pc
, 4, CONTEXT_CONTROL
),
463 REG(Cpsr
, 4, CONTEXT_CONTROL
),
465 #elif defined(__aarch64__)
466 static const char target_xml
[] = "";
467 static struct cpu_register cpu_register_map
[] = {
468 REG(Cpsr
, 4, CONTEXT_CONTROL
),
469 REG(u
.s
.X0
, 8, CONTEXT_INTEGER
),
470 REG(u
.s
.X1
, 8, CONTEXT_INTEGER
),
471 REG(u
.s
.X2
, 8, CONTEXT_INTEGER
),
472 REG(u
.s
.X3
, 8, CONTEXT_INTEGER
),
473 REG(u
.s
.X4
, 8, CONTEXT_INTEGER
),
474 REG(u
.s
.X5
, 8, CONTEXT_INTEGER
),
475 REG(u
.s
.X6
, 8, CONTEXT_INTEGER
),
476 REG(u
.s
.X7
, 8, CONTEXT_INTEGER
),
477 REG(u
.s
.X8
, 8, CONTEXT_INTEGER
),
478 REG(u
.s
.X9
, 8, CONTEXT_INTEGER
),
479 REG(u
.s
.X10
, 8, CONTEXT_INTEGER
),
480 REG(u
.s
.X11
, 8, CONTEXT_INTEGER
),
481 REG(u
.s
.X12
, 8, CONTEXT_INTEGER
),
482 REG(u
.s
.X13
, 8, CONTEXT_INTEGER
),
483 REG(u
.s
.X14
, 8, CONTEXT_INTEGER
),
484 REG(u
.s
.X15
, 8, CONTEXT_INTEGER
),
485 REG(u
.s
.X16
, 8, CONTEXT_INTEGER
),
486 REG(u
.s
.X17
, 8, CONTEXT_INTEGER
),
487 REG(u
.s
.X18
, 8, CONTEXT_INTEGER
),
488 REG(u
.s
.X19
, 8, CONTEXT_INTEGER
),
489 REG(u
.s
.X20
, 8, CONTEXT_INTEGER
),
490 REG(u
.s
.X21
, 8, CONTEXT_INTEGER
),
491 REG(u
.s
.X22
, 8, CONTEXT_INTEGER
),
492 REG(u
.s
.X23
, 8, CONTEXT_INTEGER
),
493 REG(u
.s
.X24
, 8, CONTEXT_INTEGER
),
494 REG(u
.s
.X25
, 8, CONTEXT_INTEGER
),
495 REG(u
.s
.X26
, 8, CONTEXT_INTEGER
),
496 REG(u
.s
.X27
, 8, CONTEXT_INTEGER
),
497 REG(u
.s
.X28
, 8, CONTEXT_INTEGER
),
498 REG(Fp
, 8, CONTEXT_INTEGER
),
499 REG(Lr
, 8, CONTEXT_INTEGER
),
500 REG(Sp
, 8, CONTEXT_CONTROL
),
501 REG(Pc
, 8, CONTEXT_CONTROL
),
504 # error Define the registers map for your CPU
508 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
510 static inline void* cpu_register_ptr(CONTEXT
* ctx
, unsigned idx
)
512 assert(idx
< cpu_num_regs
);
513 return (char*)ctx
+ cpu_register_map
[idx
].ctx_offset
;
516 static inline DWORD64
cpu_register(CONTEXT
* ctx
, unsigned idx
)
518 switch (cpu_register_map
[idx
].ctx_length
)
520 case 1: return *(BYTE
*)cpu_register_ptr(ctx
, idx
);
521 case 2: return *(WORD
*)cpu_register_ptr(ctx
, idx
);
522 case 4: return *(DWORD
*)cpu_register_ptr(ctx
, idx
);
523 case 8: return *(DWORD64
*)cpu_register_ptr(ctx
, idx
);
525 fprintf(stderr
, "got unexpected size: %u\n", (unsigned)cpu_register_map
[idx
].ctx_length
);
531 static inline void cpu_register_hex_from(CONTEXT
* ctx
, unsigned idx
, const char** phex
)
533 if (cpu_register_map
[idx
].gdb_length
== cpu_register_map
[idx
].ctx_length
)
534 hex_from(cpu_register_ptr(ctx
, idx
), *phex
, cpu_register_map
[idx
].gdb_length
);
541 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
543 hex_from(&b
, *phex
, 1);
545 val
+= (DWORD64
)b
<< (8 * i
);
547 switch (cpu_register_map
[idx
].ctx_length
)
549 case 1: *(BYTE
*)cpu_register_ptr(ctx
, idx
) = (BYTE
)val
; break;
550 case 2: *(WORD
*)cpu_register_ptr(ctx
, idx
) = (WORD
)val
; break;
551 case 4: *(DWORD
*)cpu_register_ptr(ctx
, idx
) = (DWORD
)val
; break;
552 case 8: *(DWORD64
*)cpu_register_ptr(ctx
, idx
) = val
; break;
558 /* =============================================== *
559 * W I N 3 2 D E B U G I N T E R F A C E *
560 * =============================================== *
563 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
565 ctx
->ContextFlags
= CONTEXT_CONTROL
567 #if defined(__powerpc__) || defined(__i386__) || defined(__x86_64__)
568 | CONTEXT_FLOATING_POINT
570 #ifdef CONTEXT_SEGMENTS
573 #ifdef CONTEXT_DEBUG_REGISTERS
574 | CONTEXT_DEBUG_REGISTERS
576 #ifdef CONTEXT_EXTENDED_REGISTERS
577 | CONTEXT_EXTENDED_REGISTERS
580 if (!GetThreadContext(h
, ctx
))
582 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
583 fprintf(stderr
, "Can't get thread's context\n");
589 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
591 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
594 switch (rec
->ExceptionCode
)
596 case EXCEPTION_ACCESS_VIOLATION
:
597 case EXCEPTION_PRIV_INSTRUCTION
:
598 case EXCEPTION_STACK_OVERFLOW
:
599 case EXCEPTION_GUARD_PAGE
:
600 gdbctx
->last_sig
= SIGSEGV
;
603 case EXCEPTION_DATATYPE_MISALIGNMENT
:
604 gdbctx
->last_sig
= SIGBUS
;
607 case EXCEPTION_SINGLE_STEP
:
609 case EXCEPTION_BREAKPOINT
:
610 gdbctx
->last_sig
= SIGTRAP
;
613 case EXCEPTION_FLT_DENORMAL_OPERAND
:
614 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
615 case EXCEPTION_FLT_INEXACT_RESULT
:
616 case EXCEPTION_FLT_INVALID_OPERATION
:
617 case EXCEPTION_FLT_OVERFLOW
:
618 case EXCEPTION_FLT_STACK_CHECK
:
619 case EXCEPTION_FLT_UNDERFLOW
:
620 gdbctx
->last_sig
= SIGFPE
;
623 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
624 case EXCEPTION_INT_OVERFLOW
:
625 gdbctx
->last_sig
= SIGFPE
;
628 case EXCEPTION_ILLEGAL_INSTRUCTION
:
629 gdbctx
->last_sig
= SIGILL
;
633 gdbctx
->last_sig
= SIGINT
;
636 case STATUS_POSSIBLE_DEADLOCK
:
637 gdbctx
->last_sig
= SIGALRM
;
639 /* FIXME: we could also add here a O packet with additional information */
642 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
643 fprintf(stderr
, "Unhandled exception code 0x%08x\n", rec
->ExceptionCode
);
644 gdbctx
->last_sig
= SIGABRT
;
651 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
658 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
660 switch (de
->dwDebugEventCode
)
662 case CREATE_PROCESS_DEBUG_EVENT
:
663 gdbctx
->process
= dbg_add_process(&be_process_gdbproxy_io
, de
->dwProcessId
,
664 de
->u
.CreateProcessInfo
.hProcess
);
665 if (!gdbctx
->process
) break;
666 memory_get_string_indirect(gdbctx
->process
,
667 de
->u
.CreateProcessInfo
.lpImageName
,
668 de
->u
.CreateProcessInfo
.fUnicode
,
669 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
670 dbg_set_process_name(gdbctx
->process
, u
.buffer
);
672 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
673 fprintf(stderr
, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
674 de
->dwProcessId
, de
->dwThreadId
,
675 dbg_W2A(u
.buffer
, -1),
676 de
->u
.CreateProcessInfo
.lpImageName
,
677 de
->u
.CreateProcessInfo
.lpStartAddress
,
678 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
679 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
681 /* de->u.CreateProcessInfo.lpStartAddress; */
682 if (!dbg_init(gdbctx
->process
->handle
, u
.buffer
, TRUE
))
683 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
685 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
686 fprintf(stderr
, "%04x:%04x: create thread I @%p\n",
687 de
->dwProcessId
, de
->dwThreadId
,
688 de
->u
.CreateProcessInfo
.lpStartAddress
);
690 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
691 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
692 de
->u
.CreateProcessInfo
.hThread
,
693 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
696 case LOAD_DLL_DEBUG_EVENT
:
697 assert(dbg_curr_thread
);
698 memory_get_string_indirect(gdbctx
->process
,
699 de
->u
.LoadDll
.lpImageName
,
700 de
->u
.LoadDll
.fUnicode
,
701 u
.buffer
, sizeof(u
.buffer
) / sizeof(WCHAR
));
702 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
703 fprintf(stderr
, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
704 de
->dwProcessId
, de
->dwThreadId
,
705 dbg_W2A(u
.buffer
, -1),
706 de
->u
.LoadDll
.lpBaseOfDll
,
707 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
708 de
->u
.LoadDll
.nDebugInfoSize
);
709 dbg_load_module(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, u
.buffer
,
710 (DWORD_PTR
)de
->u
.LoadDll
.lpBaseOfDll
, 0);
713 case UNLOAD_DLL_DEBUG_EVENT
:
714 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
715 fprintf(stderr
, "%08x:%08x: unload DLL @%p\n",
716 de
->dwProcessId
, de
->dwThreadId
, de
->u
.UnloadDll
.lpBaseOfDll
);
717 SymUnloadModule(gdbctx
->process
->handle
,
718 (DWORD_PTR
)de
->u
.UnloadDll
.lpBaseOfDll
);
721 case EXCEPTION_DEBUG_EVENT
:
722 assert(dbg_curr_thread
);
723 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
724 fprintf(stderr
, "%08x:%08x: exception code=0x%08x\n",
725 de
->dwProcessId
, de
->dwThreadId
,
726 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
728 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
730 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
734 case CREATE_THREAD_DEBUG_EVENT
:
735 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
736 fprintf(stderr
, "%08x:%08x: create thread D @%p\n",
737 de
->dwProcessId
, de
->dwThreadId
, de
->u
.CreateThread
.lpStartAddress
);
739 dbg_add_thread(gdbctx
->process
,
741 de
->u
.CreateThread
.hThread
,
742 de
->u
.CreateThread
.lpThreadLocalBase
);
745 case EXIT_THREAD_DEBUG_EVENT
:
746 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
747 fprintf(stderr
, "%08x:%08x: exit thread (%u)\n",
748 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
750 assert(dbg_curr_thread
);
751 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
752 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
753 dbg_del_thread(dbg_curr_thread
);
756 case EXIT_PROCESS_DEBUG_EVENT
:
757 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
758 fprintf(stderr
, "%08x:%08x: exit process (%u)\n",
759 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
761 dbg_del_process(gdbctx
->process
);
762 gdbctx
->process
= NULL
;
763 /* now signal gdb that we're done */
764 gdbctx
->last_sig
= SIGTERM
;
765 gdbctx
->in_trap
= TRUE
;
768 case OUTPUT_DEBUG_STRING_EVENT
:
769 assert(dbg_curr_thread
);
770 memory_get_string(gdbctx
->process
,
771 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
772 de
->u
.DebugString
.fUnicode
, u
.bufferA
, sizeof(u
.bufferA
));
773 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
774 fprintf(stderr
, "%08x:%08x: output debug string (%s)\n",
775 de
->dwProcessId
, de
->dwThreadId
, u
.bufferA
);
779 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
780 fprintf(stderr
, "%08x:%08x: rip error=%u type=%u\n",
781 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
782 de
->u
.RipInfo
.dwType
);
786 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
787 fprintf(stderr
, "%08x:%08x: unknown event (%u)\n",
788 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
792 static void resume_debuggee(struct gdb_context
* gdbctx
, DWORD cont
)
796 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
797 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
798 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
799 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
800 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
801 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
802 dbg_curr_thread
->tid
, cont
);
804 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
805 fprintf(stderr
, "Cannot find last thread\n");
809 static void resume_debuggee_thread(struct gdb_context
* gdbctx
, DWORD cont
, unsigned int threadid
)
814 if(dbg_curr_thread
->tid
== threadid
){
815 /* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
816 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
817 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
818 fprintf(stderr
, "Cannot set context on thread %04x\n", dbg_curr_thread
->tid
);
819 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
820 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
821 fprintf(stderr
, "Cannot continue on %04x (%x)\n",
822 dbg_curr_thread
->tid
, cont
);
825 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
826 fprintf(stderr
, "Cannot find last thread\n");
829 static BOOL
check_for_interrupt(struct gdb_context
* gdbctx
)
831 struct pollfd pollfd
;
835 pollfd
.fd
= gdbctx
->sock
;
836 pollfd
.events
= POLLIN
;
839 if ((ret
= poll(&pollfd
, 1, 0)) == 1) {
840 ret
= read(gdbctx
->sock
, &pkt
, 1);
842 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
843 fprintf(stderr
, "read failed\n");
848 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
) {
849 fprintf(stderr
, "Unexpected break packet (%c/0x%X)\n", pkt
, pkt
);
854 } else if (ret
== -1) {
855 fprintf(stderr
, "poll failed\n");
860 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
864 gdbctx
->in_trap
= FALSE
;
867 if (!WaitForDebugEvent(&de
, 10))
869 if (GetLastError() == ERROR_SEM_TIMEOUT
)
871 if (check_for_interrupt(gdbctx
)) {
872 if (!DebugBreakProcess(gdbctx
->process
->handle
)) {
873 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
) {
874 fprintf(stderr
, "Failed to break into debugee\n");
878 WaitForDebugEvent(&de
, INFINITE
);
886 handle_debug_event(gdbctx
, &de
);
887 assert(!gdbctx
->process
||
888 gdbctx
->process
->pid
== 0 ||
889 de
.dwProcessId
== gdbctx
->process
->pid
);
890 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
891 if (gdbctx
->in_trap
) break;
892 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
896 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
898 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
899 resume_debuggee(gdbctx
, DBG_CONTINUE
);
901 DebugActiveProcessStop(gdbctx
->process
->pid
);
902 dbg_del_process(gdbctx
->process
);
903 gdbctx
->process
= NULL
;
906 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
910 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
912 strcpy(buffer
, "Unknown process");
915 if (status
== STILL_ACTIVE
)
917 strcpy(buffer
, "Running");
920 snprintf(buffer
, len
, "Terminated (%u)", status
);
922 switch (GetPriorityClass(gdbctx
->process
->handle
))
925 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
926 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
928 #ifdef BELOW_NORMAL_PRIORITY_CLASS
929 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
931 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
932 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
933 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
934 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
936 strcat(buffer
, "\n");
939 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
940 char* buffer
, size_t len
)
942 struct dbg_thread
* thd
;
946 /* FIXME: use the size of buffer */
947 thd
= dbg_get_thread(gdbctx
->process
, tid
);
950 strcpy(buffer
, "No information");
953 if (GetExitCodeThread(thd
->handle
, &status
))
955 if (status
== STILL_ACTIVE
)
957 /* FIXME: this is a bit brutal... some nicer way shall be found */
958 switch (status
= SuspendThread(thd
->handle
))
961 case 0: strcpy(buffer
, "Running"); break;
962 default: snprintf(buffer
, len
, "Suspended (%u)", status
- 1);
964 ResumeThread(thd
->handle
);
967 snprintf(buffer
, len
, "Terminated (exit code = %u)", status
);
971 strcpy(buffer
, "Unknown threadID");
973 switch (prio
= GetThreadPriority(thd
->handle
))
975 case THREAD_PRIORITY_ERROR_RETURN
: break;
976 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
977 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
978 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
979 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
980 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
981 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
982 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
983 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
985 assert(strlen(buffer
) < len
);
988 /* =============================================== *
989 * P A C K E T U T I L S *
990 * =============================================== *
993 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
994 packet_last_f
= 0x80};
996 static char* packet_realloc(char* buf
, int size
)
999 return HeapAlloc(GetProcessHeap(), 0, size
);
1000 return HeapReAlloc(GetProcessHeap(), 0, buf
, size
);
1004 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
1006 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
1008 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
1009 gdbctx
->out_buf
= packet_realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
1013 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
1015 packet_reply_grow(gdbctx
, len
* 2);
1016 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
1017 gdbctx
->out_len
+= len
* 2;
1020 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
1022 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
1025 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
1029 shift
= (len
- 1) * 8;
1030 packet_reply_grow(gdbctx
, len
* 2);
1031 for (i
= 0; i
< len
; i
++, shift
-= 8)
1033 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
1034 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
1038 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
1040 packet_reply_grow(gdbctx
, len
);
1041 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
1042 gdbctx
->out_len
+= len
;
1045 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
1047 packet_reply_add(gdbctx
, str
, strlen(str
));
1050 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
1052 packet_reply_add(gdbctx
, &ch
, 1);
1055 static void packet_reply_open(struct gdb_context
* gdbctx
)
1057 assert(gdbctx
->out_curr_packet
== -1);
1058 packet_reply_catc(gdbctx
, '$');
1059 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
1062 static void packet_reply_close(struct gdb_context
* gdbctx
)
1064 unsigned char cksum
;
1067 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
1068 packet_reply_catc(gdbctx
, '#');
1069 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
1070 packet_reply_hex_to(gdbctx
, &cksum
, 1);
1071 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
1072 fprintf(stderr
, "Reply : %*.*s\n",
1073 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
1074 gdbctx
->out_curr_packet
= -1;
1077 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
1079 packet_reply_open(gdbctx
);
1081 if (len
== -1) len
= strlen(packet
);
1082 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
1084 packet_reply_add(gdbctx
, packet
, len
);
1086 packet_reply_close(gdbctx
);
1091 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
1093 packet_reply_open(gdbctx
);
1095 packet_reply_add(gdbctx
, "E", 1);
1096 packet_reply_val(gdbctx
, error
, 1);
1098 packet_reply_close(gdbctx
);
1103 static inline void packet_reply_register_hex_to(struct gdb_context
* gdbctx
, unsigned idx
)
1105 if (cpu_register_map
[idx
].gdb_length
== cpu_register_map
[idx
].ctx_length
)
1106 packet_reply_hex_to(gdbctx
, cpu_register_ptr(&gdbctx
->context
, idx
), cpu_register_map
[idx
].gdb_length
);
1109 DWORD64 val
= cpu_register(&gdbctx
->context
, idx
);
1112 for (i
= 0; i
< cpu_register_map
[idx
].gdb_length
; i
++)
1115 packet_reply_hex_to(gdbctx
, &b
, 1);
1121 /* =============================================== *
1122 * P A C K E T H A N D L E R S *
1123 * =============================================== *
1126 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
1128 enum packet_return ret
= packet_done
;
1130 packet_reply_open(gdbctx
);
1132 if (gdbctx
->process
!= NULL
)
1137 packet_reply_catc(gdbctx
, 'T');
1138 sig
= gdbctx
->last_sig
;
1139 packet_reply_val(gdbctx
, sig
, 1);
1140 packet_reply_add(gdbctx
, "thread:", 7);
1141 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
1142 packet_reply_catc(gdbctx
, ';');
1144 for (i
= 0; i
< cpu_num_regs
; i
++)
1146 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1147 if ((gdbctx
->context
.ContextFlags
& flags
) != flags
)
1150 /* FIXME: this call will also grow the buffer...
1151 * unneeded, but not harmful
1153 packet_reply_val(gdbctx
, i
, 1);
1154 packet_reply_catc(gdbctx
, ':');
1155 packet_reply_register_hex_to(gdbctx
, i
);
1156 packet_reply_catc(gdbctx
, ';');
1161 /* Try to put an exit code
1162 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1163 * just indicate the end of process and exit */
1164 packet_reply_add(gdbctx
, "W00", 3);
1165 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
1168 packet_reply_close(gdbctx
);
1174 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
1176 gdbctx
->extended
= 1;
1181 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
1183 assert(gdbctx
->in_packet_len
== 0);
1184 return packet_reply_status(gdbctx
);
1187 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
1189 /* FIXME: add support for address in packet */
1190 assert(gdbctx
->in_packet_len
== 0);
1191 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1192 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1193 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1194 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1195 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1196 wait_for_debuggee(gdbctx
);
1197 return packet_reply_status(gdbctx
);
1200 static enum packet_return
packet_verbose_cont(struct gdb_context
* gdbctx
)
1203 int defaultAction
= -1; /* magic non action */
1206 int actionIndex
[20]; /* allow for up to 20 actions */
1207 int threadIndex
[20];
1208 int threadCount
= 0;
1209 unsigned int threadIDs
[100]; /* TODO: Should make this dynamic */
1210 unsigned int threadID
= 0;
1211 struct dbg_thread
* thd
;
1213 /* OK we have vCont followed by..
1215 * c for packet_continue
1216 * Csig for packet_continue_signal
1218 * Ssig for step signal
1219 * and then an optional thread ID at the end..
1220 * *******************************************/
1223 if (gdbctx
->in_packet
[4] == '?')
1228 The vCont packet is supported. Each action is a supported command in the vCont packet.
1230 The vCont packet is not supported. (this didn't seem to be obeyed!)
1232 packet_reply_open(gdbctx
);
1233 packet_reply_add(gdbctx
, "vCont", 5);
1234 /* add all the supported actions to the reply (all of them for now) */
1235 packet_reply_add(gdbctx
, ";c", 2);
1236 packet_reply_add(gdbctx
, ";C", 2);
1237 packet_reply_add(gdbctx
, ";s", 2);
1238 packet_reply_add(gdbctx
, ";S", 2);
1239 packet_reply_close(gdbctx
);
1243 /* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
1244 (as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
1245 now if only gdb talked XML.... */
1246 #if 0 /* handy for debugging */
1247 fprintf(stderr
, "no, but can we find a default packet %.*s %d\n", gdbctx
->in_packet_len
, gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1250 /* go through the packet and identify where all the actions start at */
1251 for (i
= 4; i
< gdbctx
->in_packet_len
- 1; i
++)
1253 if (gdbctx
->in_packet
[i
] == ';')
1255 threadIndex
[actions
] = 0;
1256 actionIndex
[actions
++] = i
;
1258 else if (gdbctx
->in_packet
[i
] == ':')
1260 threadIndex
[actions
- 1] = i
;
1264 /* now look up the default action */
1265 for (i
= 0 ; i
< actions
; i
++)
1267 if (threadIndex
[i
] == 0)
1269 if (defaultAction
!= -1)
1271 fprintf(stderr
,"Too many default actions specified\n");
1272 return packet_error
;
1278 /* Now, I have this default action thing that needs to be applied to all non counted threads */
1280 /* go through all the threads and stick their ids in the to be done list. */
1281 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1283 threadIDs
[threadCount
++] = thd
->tid
;
1284 /* check to see if we have more threads than I counted on, and tell the user what to do
1285 * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
1286 if (threadCount
== 100)
1288 fprintf(stderr
, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
1293 /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
1294 * that remains is to apply the actions to the threads and the default action to any threads
1296 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1297 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1298 fprintf(stderr
, "NIY: cont on %04x, while last thread is %04x\n",
1299 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1301 /* deal with the threaded stuff first */
1302 for (i
= 0; i
< actions
; i
++)
1304 if (threadIndex
[i
] != 0)
1306 int j
, idLength
= 0;
1307 if (i
< actions
- 1)
1309 idLength
= (actionIndex
[i
+1] - threadIndex
[i
]) - 1;
1313 idLength
= (gdbctx
->in_packet_len
- threadIndex
[i
]) - 1;
1316 threadID
= hex_to_int(gdbctx
->in_packet
+ threadIndex
[i
] + 1 , idLength
);
1317 /* process the action */
1318 switch (gdbctx
->in_packet
[actionIndex
[i
] + 1])
1320 case 's': /* step */
1321 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1323 case 'c': /* continue */
1324 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1326 case 'S': /* step Sig, */
1327 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1329 case 'C': /* continue sig */
1330 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[i
] + 2, 1);
1331 /* cannot change signals on the fly */
1332 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1333 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1334 if (sig
!= gdbctx
->last_sig
)
1335 return packet_error
;
1336 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1339 for (j
= 0 ; j
< threadCount
; j
++)
1341 if (threadIDs
[j
] == threadID
)
1348 } /* for i=0 ; i< actions */
1350 /* now we have manage the default action */
1351 if (defaultAction
>= 0)
1353 for (i
= 0 ; i
< threadCount
; i
++)
1355 /* check to see if we've already done something to the thread*/
1356 if (threadIDs
[i
] != 0)
1358 /* if not apply the default action*/
1359 threadID
= threadIDs
[i
];
1360 /* process the action (yes this is almost identical to the one above!) */
1361 switch (gdbctx
->in_packet
[actionIndex
[defaultAction
] + 1])
1363 case 's': /* step */
1364 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1366 case 'c': /* continue */
1367 resume_debuggee_thread(gdbctx
, DBG_CONTINUE
, threadID
);
1370 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1372 case 'C': /* continue sig */
1373 hex_from(&sig
, gdbctx
->in_packet
+ actionIndex
[defaultAction
] + 2, 1);
1374 /* cannot change signals on the fly */
1375 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1376 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1377 if (sig
!= gdbctx
->last_sig
)
1378 return packet_error
;
1379 resume_debuggee_thread(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
, threadID
);
1384 } /* if(defaultAction >=0) */
1386 wait_for_debuggee(gdbctx
);
1387 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1388 return packet_reply_status(gdbctx
);
1391 struct verbose_defail
1395 enum packet_return (*handler
)(struct gdb_context
*);
1396 } verbose_details
[] =
1398 /* {"Attach", 6}, */
1399 {"Cont", 4, packet_verbose_cont
},
1409 static enum packet_return
packet_verbose(struct gdb_context
* gdbctx
)
1414 for (klen
= 0; ; klen
++)
1416 if (klen
== gdbctx
->in_packet_len
||
1417 gdbctx
->in_packet
[klen
] == ';' ||
1418 gdbctx
->in_packet
[klen
] == ':' ||
1419 gdbctx
->in_packet
[klen
] == '?')
1421 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1422 fprintf(stderr
, "trying to process a verbose packet %*.*s\n",
1423 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1424 for (i
= 0; i
< sizeof(verbose_details
)/sizeof(verbose_details
[0]); i
++)
1426 if (klen
== verbose_details
[i
].len
&&
1427 !memcmp(gdbctx
->in_packet
, verbose_details
[i
].name
, verbose_details
[i
].len
))
1429 return verbose_details
[i
].handler(gdbctx
);
1432 /* no matching handler found, abort */
1437 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1438 fprintf(stderr
, "No support for verbose packet %*.*s\n",
1439 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1440 return packet_error
;
1443 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1447 /* FIXME: add support for address in packet */
1448 assert(gdbctx
->in_packet_len
== 2);
1449 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1450 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1451 fprintf(stderr
, "NIY: cont/sig on %04x, while last thread is %04x\n",
1452 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1453 hex_from(&sig
, gdbctx
->in_packet
, 1);
1454 /* cannot change signals on the fly */
1455 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1456 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1457 if (sig
!= gdbctx
->last_sig
)
1458 return packet_error
;
1459 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1460 wait_for_debuggee(gdbctx
);
1461 return packet_reply_status(gdbctx
);
1464 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1466 detach_debuggee(gdbctx
, FALSE
);
1467 return packet_ok
| packet_last_f
;
1470 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1475 assert(gdbctx
->in_trap
);
1477 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1479 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, &ctx
))
1480 return packet_error
;
1483 packet_reply_open(gdbctx
);
1484 for (i
= 0; i
< cpu_num_regs
; i
++)
1486 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1487 if ((gdbctx
->context
.ContextFlags
& flags
) != flags
)
1489 packet_reply_register_hex_to(gdbctx
, i
);
1491 packet_reply_close(gdbctx
);
1495 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1499 CONTEXT
* pctx
= &gdbctx
->context
;
1502 assert(gdbctx
->in_trap
);
1503 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1505 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1506 return packet_error
;
1508 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1510 ptr
= gdbctx
->in_packet
;
1511 for (i
= 0; i
< cpu_num_regs
; i
++)
1513 ULONG flags
= cpu_register_map
[i
].ctx_flags
;
1514 if ((pctx
->ContextFlags
& flags
) != flags
)
1516 cpu_register_hex_from(pctx
, i
, &ptr
);
1518 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1520 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1521 fprintf(stderr
, "Cannot set context on thread %04x\n", gdbctx
->other_thread
->tid
);
1522 return packet_error
;
1527 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1529 detach_debuggee(gdbctx
, TRUE
);
1531 if (!gdbctx
->extended
)
1532 /* dunno whether GDB cares or not */
1536 /* assume we can't really answer something here */
1537 /* return packet_done; */
1540 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1545 switch (gdbctx
->in_packet
[0])
1549 if (gdbctx
->in_packet
[1] == '-')
1550 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1552 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1553 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1555 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1556 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1557 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1558 gdbctx
->in_packet
+ 1);
1559 return packet_error
;
1561 if (gdbctx
->in_packet
[0] == 'c')
1562 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1564 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
1567 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1568 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1569 return packet_error
;
1573 static BOOL
read_memory(struct gdb_context
*gdbctx
, char *addr
, char *buffer
, SIZE_T blk_len
, SIZE_T
*r
)
1575 /* Wrapper around process_io->read() that replaces values displaced by breakpoints. */
1579 ret
= gdbctx
->process
->process_io
->read(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, r
);
1582 struct gdb_ctx_Xpoint
*xpt
;
1584 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1586 char *xpt_addr
= xpt
->addr
;
1588 if (xpt
->type
!= be_xpoint_free
&& xpt_addr
>= addr
&& xpt_addr
< addr
+ blk_len
)
1589 buffer
[xpt_addr
- addr
] = xpt
->val
;
1595 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1598 unsigned int len
, blk_len
, nread
;
1602 assert(gdbctx
->in_trap
);
1603 /* FIXME:check in_packet_len for reading %p,%x */
1604 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1605 if (len
<= 0) return packet_error
;
1606 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1607 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1608 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1610 blk_len
= min(sizeof(buffer
), len
- nread
);
1611 if (!read_memory(gdbctx
, addr
, buffer
, blk_len
, &r
) || r
== 0)
1613 /* fail at first address, return error */
1614 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1615 /* something has already been read, return partial information */
1618 if (nread
== 0) packet_reply_open(gdbctx
);
1619 packet_reply_hex_to(gdbctx
, buffer
, r
);
1621 packet_reply_close(gdbctx
);
1625 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1628 unsigned int len
, blk_len
;
1633 assert(gdbctx
->in_trap
);
1634 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1637 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1638 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1639 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1640 return packet_error
;
1644 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1646 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1647 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1648 return packet_error
;
1650 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1652 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1653 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1654 (int)(ptr
- gdbctx
->in_packet
) + len
* 2, gdbctx
->in_packet_len
);
1655 return packet_error
;
1657 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1658 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1661 blk_len
= min(sizeof(buffer
), len
);
1662 hex_from(buffer
, ptr
, blk_len
);
1663 if (!gdbctx
->process
->process_io
->write(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
) ||
1670 return packet_ok
; /* FIXME: error while writing ? */
1673 static enum packet_return
packet_read_register(struct gdb_context
* gdbctx
)
1677 CONTEXT
* pctx
= &gdbctx
->context
;
1679 assert(gdbctx
->in_trap
);
1680 reg
= hex_to_int(gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1681 if (reg
>= cpu_num_regs
)
1683 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1684 fprintf(stderr
, "Register out of bounds %x\n", reg
);
1685 return packet_error
;
1687 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1689 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1690 return packet_error
;
1692 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1694 if (cpu_register_map
[reg
].ctx_length
<= sizeof(DWORD64
))
1695 fprintf(stderr
, "Read register %x => %08x%08x\n", reg
,
1696 (unsigned)(cpu_register(pctx
, reg
) >> 32), (unsigned)cpu_register(pctx
, reg
));
1698 fprintf(stderr
, "Read register %x\n", reg
);
1700 packet_reply_open(gdbctx
);
1701 packet_reply_register_hex_to(gdbctx
, reg
);
1702 packet_reply_close(gdbctx
);
1706 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1711 CONTEXT
* pctx
= &gdbctx
->context
;
1713 assert(gdbctx
->in_trap
);
1715 reg
= strtoul(gdbctx
->in_packet
, &ptr
, 16);
1716 if (ptr
== NULL
|| reg
>= cpu_num_regs
|| *ptr
++ != '=')
1718 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1719 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1720 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1721 * it wouldn't matter too much, and it fakes our support for all regs
1723 return (ptr
== NULL
) ? packet_error
: packet_ok
;
1725 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1727 int len
= gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
);
1728 fprintf(stderr
, "Writing reg %u <= %*.*s\n", reg
, len
, len
, ptr
);
1731 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1733 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1734 return packet_error
;
1736 if ((pctx
->ContextFlags
& cpu_register_map
[reg
].ctx_flags
) != cpu_register_map
[reg
].ctx_flags
)
1738 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1739 fprintf(stderr
, "Writing reg %u is not supported on this host\n", reg
);
1740 return packet_error
;
1743 cpu_register_hex_from(pctx
, reg
, (const char**)&ptr
);
1744 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1746 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1747 fprintf(stderr
, "Cannot set context for thread %04x\n", gdbctx
->other_thread
->tid
);
1748 return packet_error
;
1754 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1762 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
1763 strcpy(clsName
, "-- Unknown --");
1764 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
1765 strcpy(wndName
, "-- Empty --");
1767 packet_reply_open(gdbctx
);
1768 packet_reply_catc(gdbctx
, 'O');
1769 snprintf(buffer
, sizeof(buffer
),
1770 "%*s%04lx%*s%-17.17s %08x %0*lx %.14s\n",
1771 indent
, "", (ULONG_PTR
)hWnd
, 13 - indent
, "",
1772 clsName
, GetWindowLongW(hWnd
, GWL_STYLE
),
1773 ADDRWIDTH
, (ULONG_PTR
)GetWindowLongPtrW(hWnd
, GWLP_WNDPROC
),
1775 packet_reply_hex_to_str(gdbctx
, buffer
);
1776 packet_reply_close(gdbctx
);
1778 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1779 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1780 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1783 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1787 /* we do the output in several 'O' packets, with the last one being just OK for
1788 * marking the end of the output */
1789 packet_reply_open(gdbctx
);
1790 packet_reply_catc(gdbctx
, 'O');
1791 snprintf(buffer
, sizeof(buffer
),
1792 "%-16.16s %-17.17s %-8.8s %s\n",
1793 "hwnd", "Class Name", " Style", " WndProc Text");
1794 packet_reply_hex_to_str(gdbctx
, buffer
);
1795 packet_reply_close(gdbctx
);
1797 /* FIXME: could also add a pmt to this command in str... */
1798 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1799 packet_reply(gdbctx
, "OK", 2);
1802 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1804 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1805 char buffer
[31+MAX_PATH
];
1807 PROCESSENTRY32 entry
;
1810 if (snap
== INVALID_HANDLE_VALUE
)
1813 entry
.dwSize
= sizeof(entry
);
1814 ok
= Process32First(snap
, &entry
);
1816 /* we do the output in several 'O' packets, with the last one being just OK for
1817 * marking the end of the output */
1819 packet_reply_open(gdbctx
);
1820 packet_reply_catc(gdbctx
, 'O');
1821 snprintf(buffer
, sizeof(buffer
),
1822 " %-8.8s %-8.8s %-8.8s %s\n",
1823 "pid", "threads", "parent", "executable");
1824 packet_reply_hex_to_str(gdbctx
, buffer
);
1825 packet_reply_close(gdbctx
);
1830 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1831 packet_reply_open(gdbctx
);
1832 packet_reply_catc(gdbctx
, 'O');
1833 snprintf(buffer
, sizeof(buffer
),
1834 "%c%08x %-8d %08x '%s'\n",
1835 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1836 entry
.th32ParentProcessID
, entry
.szExeFile
);
1837 packet_reply_hex_to_str(gdbctx
, buffer
);
1838 packet_reply_close(gdbctx
);
1839 ok
= Process32Next(snap
, &entry
);
1842 packet_reply(gdbctx
, "OK", 2);
1845 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1847 MEMORY_BASIC_INFORMATION mbi
;
1854 /* we do the output in several 'O' packets, with the last one being just OK for
1855 * marking the end of the output */
1856 packet_reply_open(gdbctx
);
1857 packet_reply_catc(gdbctx
, 'O');
1858 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1859 packet_reply_close(gdbctx
);
1861 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1865 case MEM_COMMIT
: state
= "commit "; break;
1866 case MEM_FREE
: state
= "free "; break;
1867 case MEM_RESERVE
: state
= "reserve"; break;
1868 default: state
= "??? "; break;
1870 if (mbi
.State
!= MEM_FREE
)
1874 case MEM_IMAGE
: type
= "image "; break;
1875 case MEM_MAPPED
: type
= "mapped "; break;
1876 case MEM_PRIVATE
: type
= "private"; break;
1877 case 0: type
= " "; break;
1878 default: type
= "??? "; break;
1880 memset(prot
, ' ' , sizeof(prot
)-1);
1881 prot
[sizeof(prot
)-1] = '\0';
1882 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1884 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1886 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1888 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1896 packet_reply_open(gdbctx
);
1897 snprintf(buffer
, sizeof(buffer
), "%0*lx %0*lx %s %s %s\n",
1898 (unsigned)sizeof(void*), (DWORD_PTR
)addr
,
1899 (unsigned)sizeof(void*), mbi
.RegionSize
, state
, type
, prot
);
1900 packet_reply_catc(gdbctx
, 'O');
1901 packet_reply_hex_to_str(gdbctx
, buffer
);
1902 packet_reply_close(gdbctx
);
1904 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1906 addr
+= mbi
.RegionSize
;
1908 packet_reply(gdbctx
, "OK", 2);
1911 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1912 int len
, const char* str
)
1918 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1920 else if (len
>= 2 && str
[0] == '=')
1922 unsigned val
= atoi(&str
[1]);
1923 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1924 gdbctx
->trace
= val
;
1928 /* FIXME: ugly but can use error packet here */
1929 packet_reply_cat(gdbctx
, "E00");
1932 packet_reply_open(gdbctx
);
1933 packet_reply_hex_to_str(gdbctx
, buffer
);
1934 packet_reply_close(gdbctx
);
1942 void (*handler
)(struct gdb_context
*, int, const char*);
1945 {0, "wnd", 3, packet_query_monitor_wnd
},
1946 {0, "window", 6, packet_query_monitor_wnd
},
1947 {0, "proc", 4, packet_query_monitor_process
},
1948 {0, "process", 7, packet_query_monitor_process
},
1949 {0, "mem", 3, packet_query_monitor_mem
},
1950 {1, "trace", 5, packet_query_monitor_trace
},
1954 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1955 const char* hxcmd
, size_t len
)
1958 struct query_detail
* qd
;
1960 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1962 hex_from(buffer
, hxcmd
, len
);
1964 for (qd
= query_details
; qd
->name
!= NULL
; qd
++)
1966 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1967 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1969 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1972 return packet_reply_error(gdbctx
, EINVAL
);
1975 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1977 switch (gdbctx
->in_packet
[0])
1980 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1982 struct dbg_thread
* thd
;
1984 packet_reply_open(gdbctx
);
1985 packet_reply_add(gdbctx
, "m", 1);
1986 LIST_FOR_EACH_ENTRY(thd
, &gdbctx
->process
->threads
, struct dbg_thread
, entry
)
1988 packet_reply_val(gdbctx
, thd
->tid
, 4);
1989 if (list_next(&gdbctx
->process
->threads
, &thd
->entry
) != NULL
)
1990 packet_reply_add(gdbctx
, ",", 1);
1992 packet_reply_close(gdbctx
);
1995 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1999 packet_reply_open(gdbctx
);
2000 packet_reply_catc(gdbctx
, 'O');
2001 get_process_info(gdbctx
, result
, sizeof(result
));
2002 packet_reply_hex_to_str(gdbctx
, result
);
2003 packet_reply_close(gdbctx
);
2008 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
2010 packet_reply(gdbctx
, "l", 1);
2013 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
2015 packet_reply(gdbctx
, "l", 1);
2020 if (strncmp(gdbctx
->in_packet
, "Attached", gdbctx
->in_packet_len
) == 0)
2026 return packet_reply(gdbctx
, buf
, -1);
2030 if (gdbctx
->in_packet_len
== 1)
2032 struct dbg_thread
* thd
;
2033 /* FIXME: doc says 16 bit val ??? */
2034 /* grab first created thread, aka last in list */
2035 assert(gdbctx
->process
&& !list_empty(&gdbctx
->process
->threads
));
2036 thd
= LIST_ENTRY(list_tail(&gdbctx
->process
->threads
), struct dbg_thread
, entry
);
2037 packet_reply_open(gdbctx
);
2038 packet_reply_add(gdbctx
, "QC", 2);
2039 packet_reply_val(gdbctx
, thd
->tid
, 4);
2040 packet_reply_close(gdbctx
);
2045 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
2049 snprintf(buf
, sizeof(buf
),
2050 "Text=%08lx;Data=%08lx;Bss=%08lx",
2051 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
2052 gdbctx
->wine_segs
[2]);
2053 return packet_reply(gdbctx
, buf
, -1);
2057 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
2059 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
2060 gdbctx
->in_packet_len
- 5);
2064 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
2066 if (strncmp(gdbctx
->in_packet
, "Supported", 9) == 0)
2068 if (strlen(target_xml
))
2069 return packet_reply(gdbctx
, "PacketSize=400;qXfer:features:read+", -1);
2072 /* no features supported */
2073 packet_reply_open(gdbctx
);
2074 packet_reply_close(gdbctx
);
2080 if (gdbctx
->in_packet_len
> 15 &&
2081 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
2082 gdbctx
->in_packet
[15] == ',')
2088 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
2089 if (end
== NULL
) break;
2090 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
2091 packet_reply_open(gdbctx
);
2092 packet_reply_hex_to_str(gdbctx
, result
);
2093 packet_reply_close(gdbctx
);
2096 if (strncmp(gdbctx
->in_packet
, "TStatus", 7) == 0)
2098 /* Tracepoints not supported */
2099 packet_reply_open(gdbctx
);
2100 packet_reply_close(gdbctx
);
2105 if (strlen(target_xml
) && strncmp(gdbctx
->in_packet
, "Xfer:features:read:target.xml", 29) == 0)
2106 return packet_reply(gdbctx
, target_xml
, -1);
2109 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2110 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
2111 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
2112 return packet_error
;
2115 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
2117 /* FIXME: add support for address in packet */
2118 assert(gdbctx
->in_packet_len
== 0);
2119 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
2120 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
2121 fprintf(stderr
, "NIY: step on %04x, while last thread is %04x\n",
2122 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
2123 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
2124 resume_debuggee(gdbctx
, DBG_CONTINUE
);
2125 wait_for_debuggee(gdbctx
);
2126 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
2127 return packet_reply_status(gdbctx
);
2131 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
2135 /* FIXME: add support for address in packet */
2136 assert(gdbctx
->in_packet_len
== 2);
2137 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
2138 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2139 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
2140 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
2141 hex_from(&sig
, gdbctx
->in_packet
, 1);
2142 /* cannot change signals on the fly */
2143 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2144 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
2145 if (sig
!= gdbctx
->last_sig
)
2146 return packet_error
;
2147 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
2148 wait_for_debuggee(gdbctx
);
2149 return packet_reply_status(gdbctx
);
2153 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
2158 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
2159 if (tid
== -1 || tid
== 0)
2160 return packet_reply_error(gdbctx
, EINVAL
);
2161 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
2163 return packet_reply_error(gdbctx
, ESRCH
);
2166 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
2170 struct gdb_ctx_Xpoint
* xpt
;
2171 enum be_xpoint_type t
;
2173 /* FIXME: check packet_len */
2174 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2175 gdbctx
->in_packet
[1] != ',' ||
2176 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2177 return packet_error
;
2178 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2179 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
2180 addr
, len
, gdbctx
->in_packet
[0]);
2181 switch (gdbctx
->in_packet
[0])
2183 case '0': t
= be_xpoint_break
; len
= 0; break;
2184 case '1': t
= be_xpoint_watch_exec
; break;
2185 case '2': t
= be_xpoint_watch_read
; break;
2186 case '3': t
= be_xpoint_watch_write
; break;
2187 default: return packet_error
;
2189 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2191 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2193 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
,
2194 gdbctx
->process
->process_io
, &gdbctx
->context
,
2195 t
, xpt
->addr
, xpt
->val
, len
))
2197 xpt
->type
= be_xpoint_free
;
2203 return packet_error
;
2206 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
2210 struct gdb_ctx_Xpoint
* xpt
;
2211 enum be_xpoint_type t
;
2213 /* FIXME: check packet_len */
2214 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
2215 gdbctx
->in_packet
[1] != ',' ||
2216 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
2217 return packet_error
;
2218 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
2219 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
2220 addr
, len
, gdbctx
->in_packet
[0]);
2221 switch (gdbctx
->in_packet
[0])
2223 case '0': t
= be_xpoint_break
; len
= 0; break;
2224 case '1': t
= be_xpoint_watch_exec
; break;
2225 case '2': t
= be_xpoint_watch_read
; break;
2226 case '3': t
= be_xpoint_watch_write
; break;
2227 default: return packet_error
;
2229 /* because of packet command handling, this should be made idempotent */
2230 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2232 if (xpt
->addr
== addr
&& xpt
->type
== t
)
2233 return packet_ok
; /* nothing to do */
2235 /* really set the Xpoint */
2236 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
2238 if (xpt
->type
== be_xpoint_free
)
2240 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
,
2241 gdbctx
->process
->process_io
, &gdbctx
->context
,
2242 t
, addr
, &xpt
->val
, len
))
2248 fprintf(stderr
, "cannot set xpoint\n");
2252 /* no more entries... eech */
2253 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
2254 return packet_error
;
2257 /* =============================================== *
2258 * P A C K E T I N F R A S T R U C T U R E *
2259 * =============================================== *
2265 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
2268 static struct packet_entry packet_entries
[] =
2270 /*{'!', packet_extended}, */
2271 {'?', packet_last_signal
},
2272 {'c', packet_continue
},
2273 {'C', packet_continue_signal
},
2274 {'D', packet_detach
},
2275 {'g', packet_read_registers
},
2276 {'G', packet_write_registers
},
2278 {'H', packet_thread
},
2279 {'m', packet_read_memory
},
2280 {'M', packet_write_memory
},
2281 {'p', packet_read_register
},
2282 {'P', packet_write_register
},
2283 {'q', packet_query
},
2284 /* {'Q', packet_set}, */
2285 /* {'R', packet,restart}, only in extended mode ! */
2287 /*{'S', packet_step_signal}, hard(er) to implement */
2288 {'T', packet_thread_alive
},
2289 {'v', packet_verbose
},
2290 {'z', packet_remove_breakpoint
},
2291 {'Z', packet_set_breakpoint
},
2294 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
2298 unsigned char in_cksum
, loc_cksum
;
2300 enum packet_return ret
= packet_error
;
2303 while ((ret
& packet_last_f
) == 0)
2305 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
2306 fprintf(stderr
, "In-buf: %*.*s\n",
2307 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2308 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
2309 if (ptr
== NULL
) return FALSE
;
2310 if (ptr
!= gdbctx
->in_buf
)
2312 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
2313 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2314 fprintf(stderr
, "Removing garbage: %*.*s\n",
2315 glen
, glen
, gdbctx
->in_buf
);
2316 gdbctx
->in_len
-= glen
;
2317 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
2319 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
2320 if (end
== NULL
) return FALSE
;
2321 /* no checksum yet */
2322 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
2323 plen
= end
- gdbctx
->in_buf
- 1;
2324 hex_from(&in_cksum
, end
+ 1, 1);
2325 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
2326 if (loc_cksum
== in_cksum
)
2328 if (num_packet
== 0) {
2333 write(gdbctx
->sock
, "+", 1);
2336 /* FIXME: should use bsearch if packet_entries was sorted */
2337 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
2339 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
2341 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
2343 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
2344 fprintf(stderr
, "Unknown packet request %*.*s\n",
2345 plen
, plen
, &gdbctx
->in_buf
[1]);
2349 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
2350 gdbctx
->in_packet_len
= plen
- 1;
2351 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
2352 fprintf(stderr
, "Packet: %c%*.*s\n",
2354 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
2356 ret
= (packet_entries
[i
].handler
)(gdbctx
);
2358 switch (ret
& ~packet_last_f
)
2360 case packet_error
: packet_reply(gdbctx
, "", 0); break;
2361 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
2362 case packet_done
: break;
2364 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2365 fprintf(stderr
, "Reply-full: %*.*s\n",
2366 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
2367 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
2368 assert(i
== gdbctx
->out_len
);
2369 /* if this fails, we'll have to use POLLOUT...
2371 gdbctx
->out_len
= 0;
2376 /* FIXME: If we have more than one packet in our input buffer,
2377 * it's very likely that we took too long to answer to a given packet
2378 * and gdb is sending us the same packet again.
2379 * So we simply drop the second packet. This will lower the risk of error,
2380 * but there are still some race conditions here.
2381 * A better fix (yet not perfect) would be to have two threads:
2382 * - one managing the packets for gdb
2383 * - the second one managing the commands...
2384 * This would allow us to send the reply with the '+' character (Ack of
2385 * the command) way sooner than we do now.
2387 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2388 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
2393 write(gdbctx
->sock
, "+", 1);
2394 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2395 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
2397 gdbctx
->in_len
-= plen
+ 4;
2398 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
2403 static int fetch_data(struct gdb_context
* gdbctx
)
2405 int len
, in_len
= gdbctx
->in_len
;
2407 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2411 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
2412 gdbctx
->in_buf
= packet_realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
2414 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2415 fprintf(stderr
, "%d %d %*.*s\n",
2416 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
2417 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
2418 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
2419 if (len
<= 0) break;
2420 gdbctx
->in_len
+= len
;
2421 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
2422 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
2424 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2425 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
2426 return gdbctx
->in_len
- in_len
;
2429 #define FLAG_NO_START 1
2430 #define FLAG_WITH_XTERM 2
2432 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
2436 const char *gdb_path
, *tmp_path
;
2439 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2440 if (!(tmp_path
= getenv("TMPDIR"))) tmp_path
= "/tmp";
2441 strcpy(buf
, tmp_path
);
2442 strcat(buf
, "/winegdb.XXXXXX");
2443 fd
= mkstemps(buf
, 0);
2444 if (fd
== -1) return FALSE
;
2445 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2446 fprintf(f
, "file %s\n", wine_path
);
2447 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
2448 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2449 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2450 /* gdb 5.1 seems to require it, won't hurt anyway */
2451 fprintf(f
, "sharedlibrary\n");
2452 /* This is needed (but not a decent & final fix)
2453 * Without this, gdb would skip our inter-DLL relay code (because
2454 * we don't have any line number information for the relay code)
2455 * With this, we will stop on first instruction of the stub, and
2456 * reusing step, will get us through the relay stub at the actual
2457 * function we're looking at.
2459 fprintf(f
, "set step-mode on\n");
2460 /* tell gdb to delete this file when done handling it... */
2461 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2463 if (flags
& FLAG_WITH_XTERM
)
2464 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2466 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2467 assert(0); /* never reached */
2471 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
2474 struct sockaddr_in s_addrs
;
2475 socklen_t s_len
= sizeof(s_addrs
);
2476 struct pollfd pollfd
;
2477 IMAGEHLP_MODULE64 imh_mod
;
2480 /* step 1: create socket for gdb connection request */
2481 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
2483 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2484 fprintf(stderr
, "Can't create socket");
2488 if (listen(sock
, 1) == -1 || getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
2491 /* step 2: do the process internal creation */
2492 handle_debug_event(gdbctx
, de
);
2494 /* step3: get the wine loader name */
2495 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
))
2498 /* step 4: fire up gdb (if requested) */
2499 if (flags
& FLAG_NO_START
)
2500 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2504 case -1: /* error in parent... */
2505 fprintf(stderr
, "Cannot create gdb\n");
2507 default: /* in parent... success */
2508 signal(SIGINT
, SIG_IGN
);
2510 case 0: /* in child... and alive */
2511 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
2512 /* if we're here, exec failed, so report failure */
2516 /* step 5: wait for gdb to connect actually */
2518 pollfd
.events
= POLLIN
;
2521 switch (poll(&pollfd
, 1, -1))
2524 if (pollfd
.revents
& POLLIN
)
2527 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2528 if (gdbctx
->sock
== -1)
2531 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2532 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2533 /* don't keep our small packets too long: send them ASAP back to GDB
2534 * without this, GDB really crawls
2536 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2540 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2541 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2544 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2545 fprintf(stderr
, "Poll for cnx failed (error)\n");
2556 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2562 gdbctx
->in_buf
= NULL
;
2563 gdbctx
->in_buf_alloc
= 0;
2565 gdbctx
->out_buf
= NULL
;
2566 gdbctx
->out_buf_alloc
= 0;
2567 gdbctx
->out_len
= 0;
2568 gdbctx
->out_curr_packet
= -1;
2570 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2571 gdbctx
->last_sig
= 0;
2572 gdbctx
->in_trap
= FALSE
;
2573 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2574 gdbctx
->process
= NULL
;
2575 for (i
= 0; i
< NUM_XPOINT
; i
++)
2576 gdbctx
->Xpoints
[i
].type
= -1;
2577 for (i
= 0; i
< sizeof(gdbctx
->wine_segs
) / sizeof(gdbctx
->wine_segs
[0]); i
++)
2578 gdbctx
->wine_segs
[i
] = 0;
2580 /* wait for first trap */
2581 while (WaitForDebugEvent(&de
, INFINITE
))
2583 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2585 /* this should be the first event we get,
2586 * and the only one of this type */
2587 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
2588 /* gdbctx->dwProcessId = pid; */
2589 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2590 assert(!gdbctx
->in_trap
);
2594 handle_debug_event(gdbctx
, &de
);
2595 if (gdbctx
->in_trap
) break;
2597 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2602 static int gdb_remote(unsigned flags
)
2604 struct pollfd pollfd
;
2605 struct gdb_context gdbctx
;
2608 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2610 pollfd
.fd
= gdbctx
.sock
;
2611 pollfd
.events
= POLLIN
;
2614 switch (poll(&pollfd
, 1, -1))
2618 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2620 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2621 fprintf(stderr
, "Gdb hung up\n");
2622 /* kill also debuggee process - questionnable - */
2623 detach_debuggee(&gdbctx
, TRUE
);
2627 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2629 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2633 /* timeout, should never happen (infinite timeout) */
2636 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2637 fprintf(stderr
, "Poll failed\n");
2647 int gdb_main(int argc
, char* argv
[])
2650 unsigned gdb_flags
= 0;
2653 while (argc
> 0 && argv
[0][0] == '-')
2655 if (strcmp(argv
[0], "--no-start") == 0)
2657 gdb_flags
|= FLAG_NO_START
;
2661 if (strcmp(argv
[0], "--with-xterm") == 0)
2663 gdb_flags
|= FLAG_WITH_XTERM
;
2669 if (dbg_active_attach(argc
, argv
) == start_ok
||
2670 dbg_active_launch(argc
, argv
) == start_ok
)
2671 return gdb_remote(gdb_flags
);
2673 fprintf(stderr
, "GdbProxy mode not supported on this platform\n");