2 * A Win32 based proxy implementing the GBD remote protocol
3 * This allows to debug Wine (and any "emulated" program) under
6 * Copyright (c) Eric Pouech 2002-2004
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /* Protocol specification can be found here:
24 * http://sources.redhat.com/gdb/onlinedocs/gdb_32.html
28 #include "wine/port.h"
39 #ifdef HAVE_SYS_SOCKET_H
40 # include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
52 /* those two are needed only for the SHOWNORMAL flag */
58 #define GDBPXY_TRC_LOWLEVEL 0x01
59 #define GDBPXY_TRC_PACKET 0x02
60 #define GDBPXY_TRC_COMMAND 0x04
61 #define GDBPXY_TRC_COMMAND_ERROR 0x08
62 #define GDBPXY_TRC_WIN32_EVENT 0x10
63 #define GDBPXY_TRC_WIN32_ERROR 0x20
64 #define GDBPXY_TRC_COMMAND_FIXME 0x80
68 enum be_xpoint_type type
; /* -1 means free */
81 /* split into individual packet */
89 /* generic GDB thread information */
90 struct dbg_thread
* exec_thread
; /* thread used in step & continue */
91 struct dbg_thread
* other_thread
; /* thread to be used in any other operation */
93 /* current Win32 trap env */
97 /* Win32 information */
98 struct dbg_process
* process
;
100 struct gdb_ctx_Xpoint Xpoints
[NUM_XPOINT
];
101 /* Unix environment */
102 unsigned long wine_segs
[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
105 /* =============================================== *
106 * B A S I C M A N I P U L A T I O N S *
107 * =============================================== *
110 static inline int hex_from0(char ch
)
112 if (ch
>= '0' && ch
<= '9') return ch
- '0';
113 if (ch
>= 'A' && ch
<= 'F') return ch
- 'A' + 10;
114 if (ch
>= 'a' && ch
<= 'f') return ch
- 'a' + 10;
120 static inline unsigned char hex_to0(int x
)
122 assert(x
>= 0 && x
< 16);
123 return "0123456789abcdef"[x
];
126 static void hex_from(void* dst
, const char* src
, size_t len
)
128 unsigned char *p
= dst
;
131 *p
++ = (hex_from0(src
[0]) << 4) | hex_from0(src
[1]);
136 static void hex_to(char* dst
, const void* src
, size_t len
)
138 const unsigned char *p
= src
;
141 *dst
++ = hex_to0(*p
>> 4);
142 *dst
++ = hex_to0(*p
& 0x0F);
147 static unsigned char checksum(const char* ptr
, int len
)
152 cksum
+= (unsigned char)*ptr
++;
156 /* =============================================== *
157 * C P U H A N D L E R S *
158 * =============================================== *
162 static size_t cpu_register_map
[] = {
163 FIELD_OFFSET(CONTEXT
, Eax
),
164 FIELD_OFFSET(CONTEXT
, Ecx
),
165 FIELD_OFFSET(CONTEXT
, Edx
),
166 FIELD_OFFSET(CONTEXT
, Ebx
),
167 FIELD_OFFSET(CONTEXT
, Esp
),
168 FIELD_OFFSET(CONTEXT
, Ebp
),
169 FIELD_OFFSET(CONTEXT
, Esi
),
170 FIELD_OFFSET(CONTEXT
, Edi
),
171 FIELD_OFFSET(CONTEXT
, Eip
),
172 FIELD_OFFSET(CONTEXT
, EFlags
),
173 FIELD_OFFSET(CONTEXT
, SegCs
),
174 FIELD_OFFSET(CONTEXT
, SegSs
),
175 FIELD_OFFSET(CONTEXT
, SegDs
),
176 FIELD_OFFSET(CONTEXT
, SegEs
),
177 FIELD_OFFSET(CONTEXT
, SegFs
),
178 FIELD_OFFSET(CONTEXT
, SegGs
),
180 #elif defined(__powerpc__)
181 static size_t cpu_register_map
[] = {
182 FIELD_OFFSET(CONTEXT
, Gpr0
),
183 FIELD_OFFSET(CONTEXT
, Gpr1
),
184 FIELD_OFFSET(CONTEXT
, Gpr2
),
185 FIELD_OFFSET(CONTEXT
, Gpr3
),
186 FIELD_OFFSET(CONTEXT
, Gpr4
),
187 FIELD_OFFSET(CONTEXT
, Gpr5
),
188 FIELD_OFFSET(CONTEXT
, Gpr6
),
189 FIELD_OFFSET(CONTEXT
, Gpr7
),
190 FIELD_OFFSET(CONTEXT
, Gpr8
),
191 FIELD_OFFSET(CONTEXT
, Gpr9
),
192 FIELD_OFFSET(CONTEXT
, Gpr10
),
193 FIELD_OFFSET(CONTEXT
, Gpr11
),
194 FIELD_OFFSET(CONTEXT
, Gpr12
),
195 FIELD_OFFSET(CONTEXT
, Gpr13
),
196 FIELD_OFFSET(CONTEXT
, Gpr14
),
197 FIELD_OFFSET(CONTEXT
, Gpr15
),
198 FIELD_OFFSET(CONTEXT
, Gpr16
),
199 FIELD_OFFSET(CONTEXT
, Gpr17
),
200 FIELD_OFFSET(CONTEXT
, Gpr18
),
201 FIELD_OFFSET(CONTEXT
, Gpr19
),
202 FIELD_OFFSET(CONTEXT
, Gpr20
),
203 FIELD_OFFSET(CONTEXT
, Gpr21
),
204 FIELD_OFFSET(CONTEXT
, Gpr22
),
205 FIELD_OFFSET(CONTEXT
, Gpr23
),
206 FIELD_OFFSET(CONTEXT
, Gpr24
),
207 FIELD_OFFSET(CONTEXT
, Gpr25
),
208 FIELD_OFFSET(CONTEXT
, Gpr26
),
209 FIELD_OFFSET(CONTEXT
, Gpr27
),
210 FIELD_OFFSET(CONTEXT
, Gpr28
),
211 FIELD_OFFSET(CONTEXT
, Gpr29
),
212 FIELD_OFFSET(CONTEXT
, Gpr30
),
213 FIELD_OFFSET(CONTEXT
, Gpr31
),
214 FIELD_OFFSET(CONTEXT
, Fpr0
),
215 FIELD_OFFSET(CONTEXT
, Fpr1
),
216 FIELD_OFFSET(CONTEXT
, Fpr2
),
217 FIELD_OFFSET(CONTEXT
, Fpr3
),
218 FIELD_OFFSET(CONTEXT
, Fpr4
),
219 FIELD_OFFSET(CONTEXT
, Fpr5
),
220 FIELD_OFFSET(CONTEXT
, Fpr6
),
221 FIELD_OFFSET(CONTEXT
, Fpr7
),
222 FIELD_OFFSET(CONTEXT
, Fpr8
),
223 FIELD_OFFSET(CONTEXT
, Fpr9
),
224 FIELD_OFFSET(CONTEXT
, Fpr10
),
225 FIELD_OFFSET(CONTEXT
, Fpr11
),
226 FIELD_OFFSET(CONTEXT
, Fpr12
),
227 FIELD_OFFSET(CONTEXT
, Fpr13
),
228 FIELD_OFFSET(CONTEXT
, Fpr14
),
229 FIELD_OFFSET(CONTEXT
, Fpr15
),
230 FIELD_OFFSET(CONTEXT
, Fpr16
),
231 FIELD_OFFSET(CONTEXT
, Fpr17
),
232 FIELD_OFFSET(CONTEXT
, Fpr18
),
233 FIELD_OFFSET(CONTEXT
, Fpr19
),
234 FIELD_OFFSET(CONTEXT
, Fpr20
),
235 FIELD_OFFSET(CONTEXT
, Fpr21
),
236 FIELD_OFFSET(CONTEXT
, Fpr22
),
237 FIELD_OFFSET(CONTEXT
, Fpr23
),
238 FIELD_OFFSET(CONTEXT
, Fpr24
),
239 FIELD_OFFSET(CONTEXT
, Fpr25
),
240 FIELD_OFFSET(CONTEXT
, Fpr26
),
241 FIELD_OFFSET(CONTEXT
, Fpr27
),
242 FIELD_OFFSET(CONTEXT
, Fpr28
),
243 FIELD_OFFSET(CONTEXT
, Fpr29
),
244 FIELD_OFFSET(CONTEXT
, Fpr30
),
245 FIELD_OFFSET(CONTEXT
, Fpr31
),
247 FIELD_OFFSET(CONTEXT
, Iar
),
248 FIELD_OFFSET(CONTEXT
, Msr
),
249 FIELD_OFFSET(CONTEXT
, Cr
),
250 FIELD_OFFSET(CONTEXT
, Lr
),
251 FIELD_OFFSET(CONTEXT
, Ctr
),
252 FIELD_OFFSET(CONTEXT
, Xer
),
253 /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */
254 /* see gdb/nlm/ppc.c */
256 #elif defined(__ALPHA__)
257 static size_t cpu_register_map
[] = {
258 FIELD_OFFSET(CONTEXT
, IntV0
),
259 FIELD_OFFSET(CONTEXT
, IntT0
),
260 FIELD_OFFSET(CONTEXT
, IntT1
),
261 FIELD_OFFSET(CONTEXT
, IntT2
),
262 FIELD_OFFSET(CONTEXT
, IntT3
),
263 FIELD_OFFSET(CONTEXT
, IntT4
),
264 FIELD_OFFSET(CONTEXT
, IntT5
),
265 FIELD_OFFSET(CONTEXT
, IntT6
),
266 FIELD_OFFSET(CONTEXT
, IntT7
),
267 FIELD_OFFSET(CONTEXT
, IntS0
),
268 FIELD_OFFSET(CONTEXT
, IntS1
),
269 FIELD_OFFSET(CONTEXT
, IntS2
),
270 FIELD_OFFSET(CONTEXT
, IntS3
),
271 FIELD_OFFSET(CONTEXT
, IntS4
),
272 FIELD_OFFSET(CONTEXT
, IntS5
),
273 FIELD_OFFSET(CONTEXT
, IntFp
),
274 FIELD_OFFSET(CONTEXT
, IntA0
),
275 FIELD_OFFSET(CONTEXT
, IntA1
),
276 FIELD_OFFSET(CONTEXT
, IntA2
),
277 FIELD_OFFSET(CONTEXT
, IntA3
),
278 FIELD_OFFSET(CONTEXT
, IntA4
),
279 FIELD_OFFSET(CONTEXT
, IntA5
),
280 FIELD_OFFSET(CONTEXT
, IntT8
),
281 FIELD_OFFSET(CONTEXT
, IntT9
),
282 FIELD_OFFSET(CONTEXT
, IntT10
),
283 FIELD_OFFSET(CONTEXT
, IntT11
),
284 FIELD_OFFSET(CONTEXT
, IntRa
),
285 FIELD_OFFSET(CONTEXT
, IntT12
),
286 FIELD_OFFSET(CONTEXT
, IntAt
),
287 FIELD_OFFSET(CONTEXT
, IntGp
),
288 FIELD_OFFSET(CONTEXT
, IntSp
),
289 FIELD_OFFSET(CONTEXT
, IntZero
),
290 FIELD_OFFSET(CONTEXT
, FltF0
),
291 FIELD_OFFSET(CONTEXT
, FltF1
),
292 FIELD_OFFSET(CONTEXT
, FltF2
),
293 FIELD_OFFSET(CONTEXT
, FltF3
),
294 FIELD_OFFSET(CONTEXT
, FltF4
),
295 FIELD_OFFSET(CONTEXT
, FltF5
),
296 FIELD_OFFSET(CONTEXT
, FltF6
),
297 FIELD_OFFSET(CONTEXT
, FltF7
),
298 FIELD_OFFSET(CONTEXT
, FltF8
),
299 FIELD_OFFSET(CONTEXT
, FltF9
),
300 FIELD_OFFSET(CONTEXT
, FltF10
),
301 FIELD_OFFSET(CONTEXT
, FltF11
),
302 FIELD_OFFSET(CONTEXT
, FltF12
),
303 FIELD_OFFSET(CONTEXT
, FltF13
),
304 FIELD_OFFSET(CONTEXT
, FltF14
),
305 FIELD_OFFSET(CONTEXT
, FltF15
),
306 FIELD_OFFSET(CONTEXT
, FltF16
),
307 FIELD_OFFSET(CONTEXT
, FltF17
),
308 FIELD_OFFSET(CONTEXT
, FltF18
),
309 FIELD_OFFSET(CONTEXT
, FltF19
),
310 FIELD_OFFSET(CONTEXT
, FltF20
),
311 FIELD_OFFSET(CONTEXT
, FltF21
),
312 FIELD_OFFSET(CONTEXT
, FltF22
),
313 FIELD_OFFSET(CONTEXT
, FltF23
),
314 FIELD_OFFSET(CONTEXT
, FltF24
),
315 FIELD_OFFSET(CONTEXT
, FltF25
),
316 FIELD_OFFSET(CONTEXT
, FltF26
),
317 FIELD_OFFSET(CONTEXT
, FltF27
),
318 FIELD_OFFSET(CONTEXT
, FltF28
),
319 FIELD_OFFSET(CONTEXT
, FltF29
),
320 FIELD_OFFSET(CONTEXT
, FltF30
),
321 FIELD_OFFSET(CONTEXT
, FltF31
),
323 /* FIXME: Didn't look for the right order yet */
324 FIELD_OFFSET(CONTEXT
, Fir
),
325 FIELD_OFFSET(CONTEXT
, Fpcr
),
326 FIELD_OFFSET(CONTEXT
, SoftFpcr
),
329 # error Define the registers map for your CPU
332 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
334 static inline unsigned long* cpu_register(CONTEXT
* ctx
, unsigned idx
)
336 assert(idx
< cpu_num_regs
);
337 return (unsigned long*)((char*)ctx
+ cpu_register_map
[idx
]);
340 /* =============================================== *
341 * W I N 3 2 D E B U G I N T E R F A C E *
342 * =============================================== *
345 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
347 ctx
->ContextFlags
= CONTEXT_CONTROL
349 #ifdef CONTEXT_SEGMENTS
352 #ifdef CONTEXT_DEBUG_REGISTERS
353 | CONTEXT_DEBUG_REGISTERS
356 if (!GetThreadContext(h
, ctx
))
358 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
359 fprintf(stderr
, "Can't get thread's context\n");
365 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
367 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
370 switch (rec
->ExceptionCode
)
372 case EXCEPTION_ACCESS_VIOLATION
:
373 case EXCEPTION_PRIV_INSTRUCTION
:
374 case EXCEPTION_STACK_OVERFLOW
:
375 case EXCEPTION_GUARD_PAGE
:
376 gdbctx
->last_sig
= SIGSEGV
;
379 case EXCEPTION_DATATYPE_MISALIGNMENT
:
380 gdbctx
->last_sig
= SIGBUS
;
383 case EXCEPTION_SINGLE_STEP
:
385 case EXCEPTION_BREAKPOINT
:
386 gdbctx
->last_sig
= SIGTRAP
;
389 case EXCEPTION_FLT_DENORMAL_OPERAND
:
390 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
391 case EXCEPTION_FLT_INEXACT_RESULT
:
392 case EXCEPTION_FLT_INVALID_OPERATION
:
393 case EXCEPTION_FLT_OVERFLOW
:
394 case EXCEPTION_FLT_STACK_CHECK
:
395 case EXCEPTION_FLT_UNDERFLOW
:
396 gdbctx
->last_sig
= SIGFPE
;
399 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
400 case EXCEPTION_INT_OVERFLOW
:
401 gdbctx
->last_sig
= SIGFPE
;
404 case EXCEPTION_ILLEGAL_INSTRUCTION
:
405 gdbctx
->last_sig
= SIGILL
;
409 gdbctx
->last_sig
= SIGINT
;
412 case STATUS_POSSIBLE_DEADLOCK
:
413 gdbctx
->last_sig
= SIGALRM
;
415 /* FIXME: we could also add here a O packet with additional information */
418 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
419 fprintf(stderr
, "Unhandled exception code 0x%08lx\n", rec
->ExceptionCode
);
420 gdbctx
->last_sig
= SIGABRT
;
427 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
431 dbg_curr_thread
= dbg_get_thread(gdbctx
->process
, de
->dwThreadId
);
433 switch (de
->dwDebugEventCode
)
435 case CREATE_PROCESS_DEBUG_EVENT
:
436 memory_get_string_indirect(de
->u
.CreateProcessInfo
.hProcess
,
437 de
->u
.CreateProcessInfo
.lpImageName
,
438 de
->u
.CreateProcessInfo
.fUnicode
,
439 buffer
, sizeof(buffer
));
441 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
442 fprintf(stderr
, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
443 de
->dwProcessId
, de
->dwThreadId
,
444 buffer
, de
->u
.CreateProcessInfo
.lpImageName
,
445 (unsigned long)(void*)de
->u
.CreateProcessInfo
.lpStartAddress
,
446 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
447 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
449 gdbctx
->process
= dbg_add_process(de
->dwProcessId
,
450 de
->u
.CreateProcessInfo
.hProcess
,
452 /* de->u.CreateProcessInfo.lpStartAddress; */
453 if (!SymInitialize(gdbctx
->process
->handle
, NULL
, TRUE
))
454 fprintf(stderr
, "Couldn't initiate DbgHelp\n");
456 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
457 fprintf(stderr
, "%08lx:%08lx: create thread I @%08lx\n",
458 de
->dwProcessId
, de
->dwThreadId
,
459 (unsigned long)(void*)de
->u
.CreateProcessInfo
.lpStartAddress
);
461 assert(dbg_curr_thread
== NULL
); /* shouldn't be there */
462 dbg_add_thread(gdbctx
->process
, de
->dwThreadId
,
463 de
->u
.CreateProcessInfo
.hThread
,
464 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
467 case LOAD_DLL_DEBUG_EVENT
:
468 assert(dbg_curr_thread
);
469 memory_get_string_indirect(gdbctx
->process
->handle
,
470 de
->u
.LoadDll
.lpImageName
,
471 de
->u
.LoadDll
.fUnicode
,
472 buffer
, sizeof(buffer
));
473 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
474 fprintf(stderr
, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
475 de
->dwProcessId
, de
->dwThreadId
,
476 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
,
477 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
478 de
->u
.LoadDll
.nDebugInfoSize
);
479 SymLoadModule(gdbctx
->process
->handle
, de
->u
.LoadDll
.hFile
, buffer
, NULL
,
480 (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
, 0);
483 case UNLOAD_DLL_DEBUG_EVENT
:
484 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
485 fprintf(stderr
, "%08lx:%08lx: unload DLL @%08lx\n",
486 de
->dwProcessId
, de
->dwThreadId
, (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
487 SymUnloadModule(gdbctx
->process
->handle
,
488 (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
491 case EXCEPTION_DEBUG_EVENT
:
492 assert(dbg_curr_thread
);
493 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
494 fprintf(stderr
, "%08lx:%08lx: exception code=0x%08lx\n",
495 de
->dwProcessId
, de
->dwThreadId
,
496 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
498 if (fetch_context(gdbctx
, dbg_curr_thread
->handle
, &gdbctx
->context
))
500 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
504 case CREATE_THREAD_DEBUG_EVENT
:
505 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
506 fprintf(stderr
, "%08lx:%08lx: create thread D @%08lx\n",
507 de
->dwProcessId
, de
->dwThreadId
, (unsigned long)(void*)de
->u
.CreateThread
.lpStartAddress
);
509 dbg_add_thread(gdbctx
->process
,
511 de
->u
.CreateThread
.hThread
,
512 de
->u
.CreateThread
.lpThreadLocalBase
);
515 case EXIT_THREAD_DEBUG_EVENT
:
516 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
517 fprintf(stderr
, "%08lx:%08lx: exit thread (%ld)\n",
518 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
520 assert(dbg_curr_thread
);
521 if (dbg_curr_thread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
522 if (dbg_curr_thread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
523 dbg_del_thread(dbg_curr_thread
);
526 case EXIT_PROCESS_DEBUG_EVENT
:
527 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
528 fprintf(stderr
, "%08lx:%08lx: exit process (%ld)\n",
529 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
531 dbg_del_process(gdbctx
->process
);
532 gdbctx
->process
= NULL
;
533 /* now signal gdb that we're done */
534 gdbctx
->last_sig
= SIGTERM
;
535 gdbctx
->in_trap
= TRUE
;
538 case OUTPUT_DEBUG_STRING_EVENT
:
539 assert(dbg_curr_thread
);
540 memory_get_string(gdbctx
->process
->handle
,
541 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
542 de
->u
.DebugString
.fUnicode
, buffer
, sizeof(buffer
));
543 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
544 fprintf(stderr
, "%08lx:%08lx: output debug string (%s)\n",
545 de
->dwProcessId
, de
->dwThreadId
, buffer
);
549 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
550 fprintf(stderr
, "%08lx:%08lx: rip error=%ld type=%ld\n",
551 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
552 de
->u
.RipInfo
.dwType
);
556 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
557 fprintf(stderr
, "%08lx:%08lx: unknown event (%ld)\n",
558 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
562 static void resume_debuggee(struct gdb_context
* gdbctx
, unsigned long cont
)
566 if (!SetThreadContext(dbg_curr_thread
->handle
, &gdbctx
->context
))
567 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
568 fprintf(stderr
, "Cannot set context on thread %lu\n", dbg_curr_thread
->tid
);
569 if (!ContinueDebugEvent(gdbctx
->process
->pid
, dbg_curr_thread
->tid
, cont
))
570 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
571 fprintf(stderr
, "Cannot continue on %lu (%lu)\n",
572 dbg_curr_thread
->tid
, cont
);
574 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
575 fprintf(stderr
, "Cannot find last thread (%lu)\n", dbg_curr_thread
->tid
);
578 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
582 gdbctx
->in_trap
= FALSE
;
583 while (WaitForDebugEvent(&de
, INFINITE
))
585 handle_debug_event(gdbctx
, &de
);
586 assert(!gdbctx
->process
||
587 gdbctx
->process
->pid
== 0 ||
588 de
.dwProcessId
== gdbctx
->process
->pid
);
589 assert(!dbg_curr_thread
|| de
.dwThreadId
== dbg_curr_thread
->tid
);
590 if (gdbctx
->in_trap
) break;
591 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
595 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
597 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
598 resume_debuggee(gdbctx
, DBG_CONTINUE
);
600 DebugActiveProcessStop(gdbctx
->process
->pid
);
601 dbg_del_process(gdbctx
->process
);
602 gdbctx
->process
= NULL
;
605 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
607 unsigned long status
;
609 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
611 strcpy(buffer
, "Unknown process");
614 if (status
== STILL_ACTIVE
)
616 strcpy(buffer
, "Running");
619 snprintf(buffer
, len
, "Terminated (%lu)", status
);
621 switch (GetPriorityClass(gdbctx
->process
->handle
))
624 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
625 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
627 #ifdef BELOW_NORMAL_PRIORITY_CLASS
628 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
630 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
631 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
632 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
633 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
635 strcat(buffer
, "\n");
638 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
639 char* buffer
, size_t len
)
641 struct dbg_thread
* thd
;
642 unsigned long status
;
645 /* FIXME: use the size of buffer */
646 thd
= dbg_get_thread(gdbctx
->process
, tid
);
649 strcpy(buffer
, "No information");
652 if (GetExitCodeThread(thd
->handle
, &status
))
654 if (status
== STILL_ACTIVE
)
656 /* FIXME: this is a bit brutal... some nicer way shall be found */
657 switch (status
= SuspendThread(thd
->handle
))
660 case 0: strcpy(buffer
, "Running"); break;
661 default: snprintf(buffer
, len
, "Suspended (%lu)", status
- 1);
663 ResumeThread(thd
->handle
);
666 snprintf(buffer
, len
, "Terminated (exit code = %lu)", status
);
670 strcpy(buffer
, "Unknown threadID");
672 switch (prio
= GetThreadPriority(thd
->handle
))
674 case THREAD_PRIORITY_ERROR_RETURN
: break;
675 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
676 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
677 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
678 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
679 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
680 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
681 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
682 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
684 assert(strlen(buffer
) < len
);
687 /* =============================================== *
688 * P A C K E T U T I L S *
689 * =============================================== *
692 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
693 packet_last_f
= 0x80};
695 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
697 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
699 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
700 gdbctx
->out_buf
= realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
704 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
706 packet_reply_grow(gdbctx
, len
* 2);
707 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
708 gdbctx
->out_len
+= len
* 2;
711 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
713 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
716 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
720 shift
= (len
- 1) * 8;
721 packet_reply_grow(gdbctx
, len
* 2);
722 for (i
= 0; i
< len
; i
++, shift
-= 8)
724 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
725 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
729 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
731 packet_reply_grow(gdbctx
, len
);
732 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
733 gdbctx
->out_len
+= len
;
736 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
738 packet_reply_add(gdbctx
, str
, strlen(str
));
741 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
743 packet_reply_add(gdbctx
, &ch
, 1);
746 static void packet_reply_open(struct gdb_context
* gdbctx
)
748 assert(gdbctx
->out_curr_packet
== -1);
749 packet_reply_catc(gdbctx
, '$');
750 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
753 static void packet_reply_close(struct gdb_context
* gdbctx
)
758 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
759 packet_reply_catc(gdbctx
, '#');
760 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
761 packet_reply_hex_to(gdbctx
, &cksum
, 1);
762 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
763 fprintf(stderr
, "Reply : %*.*s\n",
764 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
765 gdbctx
->out_curr_packet
= -1;
768 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
770 packet_reply_open(gdbctx
);
772 if (len
== -1) len
= strlen(packet
);
773 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
775 packet_reply_add(gdbctx
, packet
, len
);
777 packet_reply_close(gdbctx
);
782 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
784 packet_reply_open(gdbctx
);
786 packet_reply_add(gdbctx
, "E", 1);
787 packet_reply_val(gdbctx
, error
, 1);
789 packet_reply_close(gdbctx
);
794 /* =============================================== *
795 * P A C K E T H A N D L E R S *
796 * =============================================== *
799 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
801 enum packet_return ret
= packet_done
;
803 packet_reply_open(gdbctx
);
805 if (gdbctx
->process
!= NULL
)
810 packet_reply_catc(gdbctx
, 'T');
811 sig
= gdbctx
->last_sig
;
812 packet_reply_val(gdbctx
, sig
, 1);
813 packet_reply_add(gdbctx
, "thread:", 7);
814 packet_reply_val(gdbctx
, dbg_curr_thread
->tid
, 4);
815 packet_reply_catc(gdbctx
, ';');
817 for (i
= 0; i
< cpu_num_regs
; i
++)
819 /* FIXME: this call will also grow the buffer...
820 * unneeded, but not harmful
822 packet_reply_val(gdbctx
, i
, 1);
823 packet_reply_catc(gdbctx
, ':');
824 packet_reply_hex_to(gdbctx
, cpu_register(&gdbctx
->context
, i
), 4);
825 packet_reply_catc(gdbctx
, ';');
830 /* Try to put an exit code
831 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
832 * just indicate the end of process and exit */
833 packet_reply_add(gdbctx
, "W00", 3);
834 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
837 packet_reply_close(gdbctx
);
843 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
845 gdbctx
->extended
= 1;
850 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
852 assert(gdbctx
->in_packet_len
== 0);
853 return packet_reply_status(gdbctx
);
856 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
858 /* FIXME: add support for address in packet */
859 assert(gdbctx
->in_packet_len
== 0);
860 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
861 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
862 fprintf(stderr
, "NIY: cont on %lu, while last thread is %lu\n",
863 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
864 resume_debuggee(gdbctx
, DBG_CONTINUE
);
865 wait_for_debuggee(gdbctx
);
866 return packet_reply_status(gdbctx
);
869 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
873 /* FIXME: add support for address in packet */
874 assert(gdbctx
->in_packet_len
== 2);
875 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
876 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
877 fprintf(stderr
, "NIY: cont/sig on %lu, while last thread is %lu\n",
878 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
879 hex_from(&sig
, gdbctx
->in_packet
, 1);
880 /* cannot change signals on the fly */
881 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
882 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
883 if (sig
!= gdbctx
->last_sig
)
885 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
886 wait_for_debuggee(gdbctx
);
887 return packet_reply_status(gdbctx
);
890 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
892 detach_debuggee(gdbctx
, FALSE
);
893 return packet_ok
| packet_last_f
;
896 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
900 CONTEXT
* pctx
= &gdbctx
->context
;
902 assert(gdbctx
->in_trap
);
904 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
906 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
910 packet_reply_open(gdbctx
);
911 for (i
= 0; i
< cpu_num_regs
; i
++)
913 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, i
), 4);
915 packet_reply_close(gdbctx
);
919 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
923 CONTEXT
* pctx
= &gdbctx
->context
;
925 assert(gdbctx
->in_trap
);
926 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
928 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
931 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
933 for (i
= 0; i
< cpu_num_regs
; i
++)
934 hex_from(cpu_register(pctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
935 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
937 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
938 fprintf(stderr
, "Cannot set context on thread %lu\n", gdbctx
->other_thread
->tid
);
944 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
946 detach_debuggee(gdbctx
, TRUE
);
948 if (!gdbctx
->extended
)
949 /* dunno whether GDB cares or not */
953 /* assume we can't really answer something here */
954 /* return packet_done; */
957 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
962 switch (gdbctx
->in_packet
[0])
966 if (gdbctx
->in_packet
[1] == '-')
967 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
969 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
970 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
972 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
973 fprintf(stderr
, "Cannot get threadid %*.*s\n",
974 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
975 gdbctx
->in_packet
+ 1);
978 if (gdbctx
->in_packet
[0] == 'c')
979 gdbctx
->exec_thread
= dbg_get_thread(gdbctx
->process
, thread
);
981 gdbctx
->other_thread
= dbg_get_thread(gdbctx
->process
, thread
);
984 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
985 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
990 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
993 size_t len
, blk_len
, nread
;
997 assert(gdbctx
->in_trap
);
998 /* FIXME:check in_packet_len for reading %p,%x */
999 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1000 if (len
<= 0) return packet_error
;
1001 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1002 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1003 for (nread
= 0; nread
< len
; nread
+= r
, addr
+= r
)
1005 blk_len
= min(sizeof(buffer
), len
- nread
);
1006 if (!ReadProcessMemory(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1009 /* fail at first address, return error */
1010 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1011 /* something has already been read, return partial information */
1014 if (nread
== 0) packet_reply_open(gdbctx
);
1015 packet_reply_hex_to(gdbctx
, buffer
, r
);
1017 packet_reply_close(gdbctx
);
1021 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1024 size_t len
, blk_len
;
1029 assert(gdbctx
->in_trap
);
1030 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1033 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1034 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1035 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1036 return packet_error
;
1040 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1042 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1043 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1044 return packet_error
;
1046 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1048 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1049 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1050 ptr
- gdbctx
->in_packet
+ len
* 2, gdbctx
->in_packet_len
);
1051 return packet_error
;
1053 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1054 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1057 blk_len
= min(sizeof(buffer
), len
);
1058 hex_from(buffer
, ptr
, blk_len
);
1062 ret
= WriteProcessMemory(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
);
1063 if (!ret
|| w
!= blk_len
)
1070 return packet_ok
; /* FIXME: error while writing ? */
1073 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1079 CONTEXT
* pctx
= &gdbctx
->context
;
1081 assert(gdbctx
->in_trap
);
1083 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1085 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1086 if (end
== NULL
|| reg
> cpu_num_regs
)
1088 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1089 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1090 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1091 * it wouldn't matter too much, and it fakes our support for all regs
1093 return (end
== NULL
) ? packet_error
: packet_ok
;
1095 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1097 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1098 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1099 ptr
+ 8 - gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1100 return packet_error
;
1102 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1103 fprintf(stderr
, "Writing reg %u <= %*.*s\n",
1104 reg
, gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
),
1105 gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
), ptr
);
1107 if (dbg_curr_thread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1109 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1110 return packet_error
;
1113 hex_from(cpu_register(pctx
, reg
), ptr
, 4);
1114 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1116 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1117 fprintf(stderr
, "Cannot set context for thread %lu\n", gdbctx
->other_thread
->tid
);
1118 return packet_error
;
1124 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1132 if (!GetClassName(hWnd
, clsName
, sizeof(clsName
)))
1133 strcpy(clsName
, "-- Unknown --");
1134 if (!GetWindowText(hWnd
, wndName
, sizeof(wndName
)))
1135 strcpy(wndName
, "-- Empty --");
1137 packet_reply_open(gdbctx
);
1138 packet_reply_catc(gdbctx
, 'O');
1139 snprintf(buffer
, sizeof(buffer
),
1140 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1141 indent
, "", (UINT
)hWnd
, 13 - indent
, "",
1142 clsName
, GetWindowLong(hWnd
, GWL_STYLE
),
1143 GetWindowLong(hWnd
, GWL_WNDPROC
), wndName
);
1144 packet_reply_hex_to_str(gdbctx
, buffer
);
1145 packet_reply_close(gdbctx
);
1147 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1148 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1149 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1152 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1156 /* we do the output in several 'O' packets, with the last one being just OK for
1157 * marking the end of the output */
1158 packet_reply_open(gdbctx
);
1159 packet_reply_catc(gdbctx
, 'O');
1160 snprintf(buffer
, sizeof(buffer
),
1161 "%-16.16s %-17.17s %-8.8s %s\n",
1162 "hwnd", "Class Name", " Style", " WndProc Text");
1163 packet_reply_hex_to_str(gdbctx
, buffer
);
1164 packet_reply_close(gdbctx
);
1166 /* FIXME: could also add a pmt to this command in str... */
1167 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1168 packet_reply(gdbctx
, "OK", 2);
1171 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1173 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1176 PROCESSENTRY32 entry
;
1179 if (snap
== INVALID_HANDLE_VALUE
)
1182 entry
.dwSize
= sizeof(entry
);
1183 ok
= Process32First(snap
, &entry
);
1185 /* we do the output in several 'O' packets, with the last one being just OK for
1186 * marking the end of the output */
1188 packet_reply_open(gdbctx
);
1189 packet_reply_catc(gdbctx
, 'O');
1190 snprintf(buffer
, sizeof(buffer
),
1191 " %-8.8s %-8.8s %-8.8s %s\n",
1192 "pid", "threads", "parent", "executable");
1193 packet_reply_hex_to_str(gdbctx
, buffer
);
1194 packet_reply_close(gdbctx
);
1199 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1200 packet_reply_open(gdbctx
);
1201 packet_reply_catc(gdbctx
, 'O');
1202 snprintf(buffer
, sizeof(buffer
),
1203 "%c%08lx %-8ld %08lx '%s'\n",
1204 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1205 entry
.th32ParentProcessID
, entry
.szExeFile
);
1206 packet_reply_hex_to_str(gdbctx
, buffer
);
1207 packet_reply_close(gdbctx
);
1208 ok
= Process32Next(snap
, &entry
);
1211 packet_reply(gdbctx
, "OK", 2);
1214 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1216 MEMORY_BASIC_INFORMATION mbi
;
1223 /* we do the output in several 'O' packets, with the last one being just OK for
1224 * marking the end of the output */
1225 packet_reply_open(gdbctx
);
1226 packet_reply_catc(gdbctx
, 'O');
1227 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1228 packet_reply_close(gdbctx
);
1230 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1234 case MEM_COMMIT
: state
= "commit "; break;
1235 case MEM_FREE
: state
= "free "; break;
1236 case MEM_RESERVE
: state
= "reserve"; break;
1237 default: state
= "??? "; break;
1239 if (mbi
.State
!= MEM_FREE
)
1243 case MEM_IMAGE
: type
= "image "; break;
1244 case MEM_MAPPED
: type
= "mapped "; break;
1245 case MEM_PRIVATE
: type
= "private"; break;
1246 case 0: type
= " "; break;
1247 default: type
= "??? "; break;
1249 memset(prot
, ' ' , sizeof(prot
)-1);
1250 prot
[sizeof(prot
)-1] = '\0';
1251 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1253 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1255 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1257 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1265 packet_reply_open(gdbctx
);
1266 snprintf(buffer
, sizeof(buffer
),
1267 "%08lx %08lx %s %s %s\n",
1268 (DWORD
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1269 packet_reply_catc(gdbctx
, 'O');
1270 packet_reply_hex_to_str(gdbctx
, buffer
);
1271 packet_reply_close(gdbctx
);
1273 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1275 addr
+= mbi
.RegionSize
;
1277 packet_reply(gdbctx
, "OK", 2);
1280 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1281 int len
, const char* str
)
1287 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1289 else if (len
>= 2 && str
[0] == '=')
1291 unsigned val
= atoi(&str
[1]);
1292 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1293 gdbctx
->trace
= val
;
1297 /* FIXME: ugly but can use error packet here */
1298 packet_reply_cat(gdbctx
, "E00");
1301 packet_reply_open(gdbctx
);
1302 packet_reply_hex_to_str(gdbctx
, buffer
);
1303 packet_reply_close(gdbctx
);
1311 void (*handler
)(struct gdb_context
*, int, const char*);
1314 {0, "wnd", 3, packet_query_monitor_wnd
},
1315 {0, "window", 6, packet_query_monitor_wnd
},
1316 {0, "proc", 4, packet_query_monitor_process
},
1317 {0, "process", 7, packet_query_monitor_process
},
1318 {0, "mem", 3, packet_query_monitor_mem
},
1319 {1, "trace", 5, packet_query_monitor_trace
},
1323 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1324 const char* hxcmd
, size_t len
)
1327 struct query_detail
* qd
;
1329 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1331 hex_from(buffer
, hxcmd
, len
);
1333 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1335 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1336 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1338 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1341 return packet_reply_error(gdbctx
, EINVAL
);
1344 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1346 switch (gdbctx
->in_packet
[0])
1349 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1351 struct dbg_thread
* thd
;
1353 packet_reply_open(gdbctx
);
1354 packet_reply_add(gdbctx
, "m", 1);
1355 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1357 packet_reply_val(gdbctx
, thd
->tid
, 4);
1358 if (thd
->next
!= NULL
)
1359 packet_reply_add(gdbctx
, ",", 1);
1361 packet_reply_close(gdbctx
);
1364 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1368 packet_reply_open(gdbctx
);
1369 packet_reply_catc(gdbctx
, 'O');
1370 get_process_info(gdbctx
, result
, sizeof(result
));
1371 packet_reply_hex_to_str(gdbctx
, result
);
1372 packet_reply_close(gdbctx
);
1377 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1379 packet_reply(gdbctx
, "l", 1);
1382 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1384 packet_reply(gdbctx
, "l", 1);
1389 if (gdbctx
->in_packet_len
== 1)
1391 struct dbg_thread
* thd
;
1392 /* FIXME: doc says 16 bit val ??? */
1393 /* grab first created thread, aka last in list */
1394 assert(gdbctx
->process
&& gdbctx
->process
->threads
);
1395 for (thd
= gdbctx
->process
->threads
; thd
->next
; thd
= thd
->next
);
1396 packet_reply_open(gdbctx
);
1397 packet_reply_add(gdbctx
, "QC", 2);
1398 packet_reply_val(gdbctx
, thd
->tid
, 4);
1399 packet_reply_close(gdbctx
);
1404 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1408 if (gdbctx
->wine_segs
[0] == 0 && gdbctx
->wine_segs
[1] == 0 &&
1409 gdbctx
->wine_segs
[2] == 0)
1410 return packet_error
;
1411 snprintf(buf
, sizeof(buf
),
1412 "Text=%08lx;Data=%08lx;Bss=%08lx",
1413 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1414 gdbctx
->wine_segs
[2]);
1415 return packet_reply(gdbctx
, buf
, -1);
1419 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1421 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1422 gdbctx
->in_packet_len
- 5);
1426 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1430 if (gdbctx
->in_packet_len
> 15 &&
1431 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1432 gdbctx
->in_packet
[15] == ',')
1438 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1439 if (end
== NULL
) break;
1440 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1441 packet_reply_open(gdbctx
);
1442 packet_reply_hex_to_str(gdbctx
, result
);
1443 packet_reply_close(gdbctx
);
1448 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1449 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1450 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1451 return packet_error
;
1454 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1456 /* FIXME: add support for address in packet */
1457 assert(gdbctx
->in_packet_len
== 0);
1458 if (dbg_curr_thread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1459 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1460 fprintf(stderr
, "NIY: step on %lu, while last thread is %lu\n",
1461 gdbctx
->exec_thread
->tid
, dbg_curr_thread
->tid
);
1462 be_cpu
->single_step(&gdbctx
->context
, TRUE
);
1463 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1464 wait_for_debuggee(gdbctx
);
1465 be_cpu
->single_step(&gdbctx
->context
, FALSE
);
1466 return packet_reply_status(gdbctx
);
1470 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1474 /* FIXME: add support for address in packet */
1475 assert(gdbctx
->in_packet_len
== 2);
1476 if (dbg_curr_thread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1477 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1478 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1479 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1480 hex_from(&sig
, gdbctx
->in_packet
, 1);
1481 /* cannot change signals on the fly */
1482 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1483 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1484 if (sig
!= gdbctx
->last_sig
)
1485 return packet_error
;
1486 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1487 wait_for_debuggee(gdbctx
);
1488 return packet_reply_status(gdbctx
);
1492 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1497 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1498 if (tid
== -1 || tid
== 0)
1499 return packet_reply_error(gdbctx
, EINVAL
);
1500 if (dbg_get_thread(gdbctx
->process
, tid
) != NULL
)
1502 return packet_reply_error(gdbctx
, ESRCH
);
1505 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1509 struct gdb_ctx_Xpoint
* xpt
;
1510 enum be_xpoint_type t
;
1512 /* FIXME: check packet_len */
1513 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1514 gdbctx
->in_packet
[1] != ',' ||
1515 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1516 return packet_error
;
1517 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1518 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1519 addr
, len
, gdbctx
->in_packet
[0]);
1520 switch (gdbctx
->in_packet
[0])
1522 case '0': t
= be_xpoint_break
; len
= 0; break;
1523 case '1': t
= be_xpoint_watch_exec
; break;
1524 case '2': t
= be_xpoint_watch_read
; break;
1525 case '3': t
= be_xpoint_watch_write
; break;
1526 default: return packet_error
;
1528 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1530 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1532 if (be_cpu
->remove_Xpoint(gdbctx
->process
->handle
, &gdbctx
->context
,
1533 t
, xpt
->addr
, xpt
->val
, len
))
1541 return packet_error
;
1544 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1548 struct gdb_ctx_Xpoint
* xpt
;
1549 enum be_xpoint_type t
;
1551 /* FIXME: check packet_len */
1552 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1553 gdbctx
->in_packet
[1] != ',' ||
1554 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1555 return packet_error
;
1556 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1557 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
1558 addr
, len
, gdbctx
->in_packet
[0]);
1559 switch (gdbctx
->in_packet
[0])
1561 case '0': t
= be_xpoint_break
; len
= 0; break;
1562 case '1': t
= be_xpoint_watch_exec
; break;
1563 case '2': t
= be_xpoint_watch_read
; break;
1564 case '3': t
= be_xpoint_watch_write
; break;
1565 default: return packet_error
;
1567 /* because of packet command handling, this should be made idempotent */
1568 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1570 if (xpt
->addr
== addr
&& xpt
->type
== t
)
1571 return packet_ok
; /* nothing to do */
1573 /* really set the Xpoint */
1574 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1576 if (xpt
->type
== -1)
1578 if (be_cpu
->insert_Xpoint(gdbctx
->process
->handle
, &gdbctx
->context
,
1579 t
, addr
, &xpt
->val
, len
))
1585 fprintf(stderr
, "cannot set xpoint\n");
1589 /* no more entries... eech */
1590 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
1591 return packet_error
;
1594 /* =============================================== *
1595 * P A C K E T I N F R A S T R U C T U R E *
1596 * =============================================== *
1602 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1605 static struct packet_entry packet_entries
[] =
1607 /* {'!', packet_extended}, */
1608 {'?', packet_last_signal
},
1609 {'c', packet_continue
},
1610 {'C', packet_continue_signal
},
1611 {'D', packet_detach
},
1612 {'g', packet_read_registers
},
1613 {'G', packet_write_registers
},
1615 {'H', packet_thread
},
1616 {'m', packet_read_memory
},
1617 {'M', packet_write_memory
},
1618 /* {'p', packet_read_register}, doesn't seem needed */
1619 {'P', packet_write_register
},
1620 {'q', packet_query
},
1622 /*{'S', packet_step_signal}, hard(er) to implement */
1623 {'T', packet_thread_alive
},
1624 {'z', packet_remove_breakpoint
},
1625 {'Z', packet_set_breakpoint
},
1628 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
1632 unsigned char in_cksum
, loc_cksum
;
1634 enum packet_return ret
= packet_error
;
1637 while ((ret
& packet_last_f
) == 0)
1639 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
1640 fprintf(stderr
, "In-buf: %*.*s\n",
1641 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
1642 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
1643 if (ptr
== NULL
) return FALSE
;
1644 if (ptr
!= gdbctx
->in_buf
)
1646 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
1647 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1648 fprintf(stderr
, "Removing garbage: %*.*s\n",
1649 glen
, glen
, gdbctx
->in_buf
);
1650 gdbctx
->in_len
-= glen
;
1651 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
1653 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
1654 if (end
== NULL
) return FALSE
;
1655 /* no checksum yet */
1656 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
1657 plen
= end
- gdbctx
->in_buf
- 1;
1658 hex_from(&in_cksum
, end
+ 1, 1);
1659 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
1660 if (loc_cksum
== in_cksum
)
1662 if (num_packet
== 0) {
1667 write(gdbctx
->sock
, "+", 1);
1670 /* FIXME: should use bsearch if packet_entries was sorted */
1671 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
1673 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
1675 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
1677 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1678 fprintf(stderr
, "Unknown packet request %*.*s\n",
1679 plen
, plen
, &gdbctx
->in_buf
[1]);
1683 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
1684 gdbctx
->in_packet_len
= plen
- 1;
1685 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
1686 fprintf(stderr
, "Packet: %c%*.*s\n",
1688 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
1690 ret
= (packet_entries
[i
].handler
)(gdbctx
);
1692 switch (ret
& ~packet_last_f
)
1694 case packet_error
: packet_reply(gdbctx
, "", 0); break;
1695 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
1696 case packet_done
: break;
1698 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1699 fprintf(stderr
, "Reply-full: %*.*s\n",
1700 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
1701 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
1702 assert(i
== gdbctx
->out_len
);
1703 /* if this fails, we'll have to use POLLOUT...
1705 gdbctx
->out_len
= 0;
1710 /* FIXME: if we have in our input buffer more than one packet,
1711 * it's very likely that we took too long to answer to a given packet
1712 * and gdb is sending us again the same packet
1713 * We simply drop the second packet. This will lower the risk of error,
1714 * but there's still some race conditions here
1715 * A better fix (yet not perfect) would be to have two threads:
1716 * - one managing the packets for gdb
1717 * - the second one managing the commands...
1718 * This would allow us also the reply with the '+' character (Ack of
1719 * the command) way sooner than what we do now
1721 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1722 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
1727 write(gdbctx
->sock
, "+", 1);
1728 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1729 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
1731 gdbctx
->in_len
-= plen
+ 4;
1732 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
1737 static int fetch_data(struct gdb_context
* gdbctx
)
1739 int len
, in_len
= gdbctx
->in_len
;
1741 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1745 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
1746 gdbctx
->in_buf
= realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
1748 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1749 fprintf(stderr
, "%d %d %*.*s\n",
1750 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
1751 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
1752 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
1753 if (len
<= 0) break;
1754 gdbctx
->in_len
+= len
;
1755 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1756 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
1758 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1759 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
1760 return gdbctx
->in_len
- in_len
;
1763 static BOOL
gdb_exec(const char* wine_path
, unsigned port
, unsigned flags
)
1767 const char* gdb_path
;
1770 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
1771 strcpy(buf
,"/tmp/winegdb.XXXXXX");
1772 fd
= mkstemps(buf
, 0);
1773 if (fd
== -1) return FALSE
;
1774 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
1775 fprintf(f
, "file %s\n", wine_path
);
1776 fprintf(f
, "target remote localhost:%d\n", ntohs(port
));
1777 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
1778 fprintf(f
, "set prompt Wine-gdb>\\ \n");
1779 /* gdb 5.1 seems to require it, won't hurt anyway */
1780 fprintf(f
, "sharedlibrary\n");
1781 /* This is needed (but not a decent & final fix)
1782 * Without this, gdb would skip our inter-DLL relay code (because
1783 * we don't have any line number information for the relay code)
1784 * With this, we will stop on first instruction of the stub, and
1785 * reusing step, will get us through the relay stub at the actual
1786 * function we're looking at.
1788 fprintf(f
, "set step-mode on\n");
1789 /* tell gdb to delete this file when done handling it... */
1790 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
1793 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
1795 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
1796 assert(0); /* never reached */
1800 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
1803 struct sockaddr_in s_addrs
;
1804 int s_len
= sizeof(s_addrs
);
1805 struct pollfd pollfd
;
1806 IMAGEHLP_MODULE imh_mod
;
1808 /* step 1: create socket for gdb connection request */
1809 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1811 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1812 fprintf(stderr
, "Can't create socket");
1816 if (listen(sock
, 1) == -1 ||
1817 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
1820 /* step 2: do the process internal creation */
1821 handle_debug_event(gdbctx
, de
);
1823 /* step3: get the wine loader name */
1824 if (!dbg_get_debuggee_info(gdbctx
->process
->handle
, &imh_mod
)) return FALSE
;
1826 /* step 4: fire up gdb (if requested) */
1828 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
1832 case -1: /* error in parent... */
1833 fprintf(stderr
, "Cannot create gdb\n");
1836 default: /* in parent... success */
1838 case 0: /* in child... and alive */
1839 gdb_exec(imh_mod
.LoadedImageName
, s_addrs
.sin_port
, flags
);
1840 /* if we're here, exec failed, so report failure */
1844 /* step 5: wait for gdb to connect actually */
1846 pollfd
.events
= POLLIN
;
1849 switch (poll(&pollfd
, 1, -1))
1852 if (pollfd
.revents
& POLLIN
)
1855 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
1856 if (gdbctx
->sock
== -1)
1858 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1859 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
1860 /* don't keep our small packets too long: send them ASAP back to GDB
1861 * without this, GDB really crawls
1863 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
1867 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1868 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
1871 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1872 fprintf(stderr
, "Poll for cnx failed (error)\n");
1882 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
1888 gdbctx
->in_buf
= NULL
;
1889 gdbctx
->in_buf_alloc
= 0;
1891 gdbctx
->out_buf
= NULL
;
1892 gdbctx
->out_buf_alloc
= 0;
1893 gdbctx
->out_len
= 0;
1894 gdbctx
->out_curr_packet
= -1;
1896 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
1897 gdbctx
->last_sig
= 0;
1898 gdbctx
->in_trap
= FALSE
;
1899 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
1900 gdbctx
->process
= NULL
;
1901 for (i
= 0; i
< NUM_XPOINT
; i
++)
1902 gdbctx
->Xpoints
[i
].type
= -1;
1904 /* wait for first trap */
1905 while (WaitForDebugEvent(&de
, INFINITE
))
1907 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
1909 /* this should be the first event we get,
1910 * and the only one of this type */
1911 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== dbg_curr_pid
);
1912 /* gdbctx->dwProcessId = pid; */
1913 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
1914 assert(!gdbctx
->in_trap
);
1918 handle_debug_event(gdbctx
, &de
);
1919 if (gdbctx
->in_trap
) break;
1921 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
1926 BOOL
gdb_remote(unsigned flags
)
1928 struct pollfd pollfd
;
1929 struct gdb_context gdbctx
;
1932 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
1934 pollfd
.fd
= gdbctx
.sock
;
1935 pollfd
.events
= POLLIN
;
1938 switch (poll(&pollfd
, 1, -1))
1942 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
1944 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
1945 fprintf(stderr
, "Gdb hung up\n");
1946 /* kill also debuggee process - questionnable - */
1947 detach_debuggee(&gdbctx
, TRUE
);
1951 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
1953 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
1957 /* timeout, should never happen (infinite timeout) */
1960 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
1961 fprintf(stderr
, "Poll failed\n");