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-2003
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"
38 #ifdef HAVE_SYS_SOCKET_H
39 # include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <netinet/tcp.h>
49 /* those two are needed only for the SHOWNORMAL flag */
55 #define GDBPXY_TRC_LOWLEVEL 0x01
56 #define GDBPXY_TRC_PACKET 0x02
57 #define GDBPXY_TRC_COMMAND 0x04
58 #define GDBPXY_TRC_COMMAND_ERROR 0x08
59 #define GDBPXY_TRC_WIN32_EVENT 0x10
60 #define GDBPXY_TRC_WIN32_ERROR 0x20
61 #define GDBPXY_TRC_COMMAND_FIXME 0x80
65 int type
; /* -1 means free */
78 /* split into individual packet */
86 /* generic GDB thread information */
87 DBG_THREAD
* exec_thread
; /* thread used in step & continue */
88 DBG_THREAD
* other_thread
; /* thread to be used in any other operation */
90 /* current Win32 trap env */
94 /* Win32 information */
97 struct gdb_ctx_Xpoint Xpoints
[NUM_XPOINT
];
98 /* Unix environment */
99 unsigned long wine_segs
[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
102 extern int read_elf_info(const char* filename
, unsigned long tab
[]);
104 /* =============================================== *
105 * B A S I C M A N I P U L A T I O N S *
106 * =============================================== *
109 static inline int hex_from0(char ch
)
111 if (ch
>= '0' && ch
<= '9') return ch
- '0';
112 if (ch
>= 'A' && ch
<= 'F') return ch
- 'A' + 10;
113 if (ch
>= 'a' && ch
<= 'f') return ch
- 'a' + 10;
119 static inline unsigned char hex_to0(int x
)
121 assert(x
>= 0 && x
< 16);
122 return "0123456789abcdef"[x
];
125 static void hex_from(void* dst
, const char* src
, size_t len
)
127 unsigned char *p
= dst
;
130 *p
++ = (hex_from0(src
[0]) << 4) | hex_from0(src
[1]);
135 static void hex_to(char* dst
, const void* src
, size_t len
)
137 const unsigned char *p
= src
;
140 *dst
++ = hex_to0(*p
>> 4);
141 *dst
++ = hex_to0(*p
& 0x0F);
146 static unsigned char checksum(const char* ptr
, int len
)
151 cksum
+= (unsigned char)*ptr
++;
155 /* =============================================== *
156 * C P U H A N D L E R S *
157 * =============================================== *
160 #define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0)))
163 static size_t cpu_register_map
[] = {
164 OFFSET_OF(CONTEXT
, Eax
),
165 OFFSET_OF(CONTEXT
, Ecx
),
166 OFFSET_OF(CONTEXT
, Edx
),
167 OFFSET_OF(CONTEXT
, Ebx
),
168 OFFSET_OF(CONTEXT
, Esp
),
169 OFFSET_OF(CONTEXT
, Ebp
),
170 OFFSET_OF(CONTEXT
, Esi
),
171 OFFSET_OF(CONTEXT
, Edi
),
172 OFFSET_OF(CONTEXT
, Eip
),
173 OFFSET_OF(CONTEXT
, EFlags
),
174 OFFSET_OF(CONTEXT
, SegCs
),
175 OFFSET_OF(CONTEXT
, SegSs
),
176 OFFSET_OF(CONTEXT
, SegDs
),
177 OFFSET_OF(CONTEXT
, SegEs
),
178 OFFSET_OF(CONTEXT
, SegFs
),
179 OFFSET_OF(CONTEXT
, SegGs
),
183 static size_t cpu_register_map
[] = {
184 OFFSET_OF(CONTEXT
, Gpr0
),
185 OFFSET_OF(CONTEXT
, Gpr1
),
186 OFFSET_OF(CONTEXT
, Gpr2
),
187 OFFSET_OF(CONTEXT
, Gpr3
),
188 OFFSET_OF(CONTEXT
, Gpr4
),
189 OFFSET_OF(CONTEXT
, Gpr5
),
190 OFFSET_OF(CONTEXT
, Gpr6
),
191 OFFSET_OF(CONTEXT
, Gpr7
),
192 OFFSET_OF(CONTEXT
, Gpr8
),
193 OFFSET_OF(CONTEXT
, Gpr9
),
194 OFFSET_OF(CONTEXT
, Gpr10
),
195 OFFSET_OF(CONTEXT
, Gpr11
),
196 OFFSET_OF(CONTEXT
, Gpr12
),
197 OFFSET_OF(CONTEXT
, Gpr13
),
198 OFFSET_OF(CONTEXT
, Gpr14
),
199 OFFSET_OF(CONTEXT
, Gpr15
),
200 OFFSET_OF(CONTEXT
, Gpr16
),
201 OFFSET_OF(CONTEXT
, Gpr17
),
202 OFFSET_OF(CONTEXT
, Gpr18
),
203 OFFSET_OF(CONTEXT
, Gpr19
),
204 OFFSET_OF(CONTEXT
, Gpr20
),
205 OFFSET_OF(CONTEXT
, Gpr21
),
206 OFFSET_OF(CONTEXT
, Gpr22
),
207 OFFSET_OF(CONTEXT
, Gpr23
),
208 OFFSET_OF(CONTEXT
, Gpr24
),
209 OFFSET_OF(CONTEXT
, Gpr25
),
210 OFFSET_OF(CONTEXT
, Gpr26
),
211 OFFSET_OF(CONTEXT
, Gpr27
),
212 OFFSET_OF(CONTEXT
, Gpr28
),
213 OFFSET_OF(CONTEXT
, Gpr29
),
214 OFFSET_OF(CONTEXT
, Gpr30
),
215 OFFSET_OF(CONTEXT
, Gpr31
),
216 OFFSET_OF(CONTEXT
, Fpr0
),
217 OFFSET_OF(CONTEXT
, Fpr1
),
218 OFFSET_OF(CONTEXT
, Fpr2
),
219 OFFSET_OF(CONTEXT
, Fpr3
),
220 OFFSET_OF(CONTEXT
, Fpr4
),
221 OFFSET_OF(CONTEXT
, Fpr5
),
222 OFFSET_OF(CONTEXT
, Fpr6
),
223 OFFSET_OF(CONTEXT
, Fpr7
),
224 OFFSET_OF(CONTEXT
, Fpr8
),
225 OFFSET_OF(CONTEXT
, Fpr9
),
226 OFFSET_OF(CONTEXT
, Fpr10
),
227 OFFSET_OF(CONTEXT
, Fpr11
),
228 OFFSET_OF(CONTEXT
, Fpr12
),
229 OFFSET_OF(CONTEXT
, Fpr13
),
230 OFFSET_OF(CONTEXT
, Fpr14
),
231 OFFSET_OF(CONTEXT
, Fpr15
),
232 OFFSET_OF(CONTEXT
, Fpr16
),
233 OFFSET_OF(CONTEXT
, Fpr17
),
234 OFFSET_OF(CONTEXT
, Fpr18
),
235 OFFSET_OF(CONTEXT
, Fpr19
),
236 OFFSET_OF(CONTEXT
, Fpr20
),
237 OFFSET_OF(CONTEXT
, Fpr21
),
238 OFFSET_OF(CONTEXT
, Fpr22
),
239 OFFSET_OF(CONTEXT
, Fpr23
),
240 OFFSET_OF(CONTEXT
, Fpr24
),
241 OFFSET_OF(CONTEXT
, Fpr25
),
242 OFFSET_OF(CONTEXT
, Fpr26
),
243 OFFSET_OF(CONTEXT
, Fpr27
),
244 OFFSET_OF(CONTEXT
, Fpr28
),
245 OFFSET_OF(CONTEXT
, Fpr29
),
246 OFFSET_OF(CONTEXT
, Fpr30
),
247 OFFSET_OF(CONTEXT
, Fpr31
),
249 OFFSET_OF(CONTEXT
, Iar
),
250 OFFSET_OF(CONTEXT
, Msr
),
251 OFFSET_OF(CONTEXT
, Cr
),
252 OFFSET_OF(CONTEXT
, Lr
),
253 OFFSET_OF(CONTEXT
, Ctr
),
254 OFFSET_OF(CONTEXT
, Xer
),
255 /* FIXME: MQ is missing? OFFSET_OF(CONTEXT, Mq), */
256 /* see gdb/nlm/ppc.c */
259 # error "Define the registers map for your CPU"
264 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
266 static inline unsigned long* cpu_register(const CONTEXT
* ctx
, unsigned idx
)
268 assert(idx
< cpu_num_regs
);
269 return (unsigned long*)((char*)ctx
+ cpu_register_map
[idx
]);
272 static inline BOOL
cpu_enter_stepping(struct gdb_context
* gdbctx
)
275 gdbctx
->context
.EFlags
|= 0x100;
279 # define MSR_SE (1<<10)
281 gdbctx
->context
.Msr
|= MSR_SE
;
284 #error "Define step mode enter for your CPU"
289 static inline BOOL
cpu_leave_stepping(struct gdb_context
* gdbctx
)
292 /* The Win32 debug API always resets the Step bit in EFlags after
293 * a single step instruction, so we don't need to clear when the
298 gdbctx
->context
.Msr
&= MSR_SE
;
301 #error "Define step mode leave for your CPU"
307 #define DR7_CONTROL_SHIFT 16
308 #define DR7_CONTROL_SIZE 4
310 #define DR7_RW_EXECUTE (0x0)
311 #define DR7_RW_WRITE (0x1)
312 #define DR7_RW_READ (0x3)
314 #define DR7_LEN_1 (0x0)
315 #define DR7_LEN_2 (0x4)
316 #define DR7_LEN_4 (0xC)
318 #define DR7_LOCAL_ENABLE_SHIFT 0
319 #define DR7_GLOBAL_ENABLE_SHIFT 1
320 #define DR7_ENABLE_SIZE 2
322 #define DR7_LOCAL_ENABLE_MASK (0x55)
323 #define DR7_GLOBAL_ENABLE_MASK (0xAA)
325 #define DR7_CONTROL_RESERVED (0xFC00)
326 #define DR7_LOCAL_SLOWDOWN (0x100)
327 #define DR7_GLOBAL_SLOWDOWN (0x200)
329 #define DR7_ENABLE_MASK(dr) (1<<(DR7_LOCAL_ENABLE_SHIFT+DR7_ENABLE_SIZE*(dr)))
330 #define IS_DR7_SET(ctrl,dr) ((ctrl)&DR7_ENABLE_MASK(dr))
332 static inline int i386_get_unused_DR(struct gdb_context
* gdbctx
,
335 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 0))
337 *r
= &gdbctx
->context
.Dr0
;
340 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 1))
342 *r
= &gdbctx
->context
.Dr1
;
345 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 2))
347 *r
= &gdbctx
->context
.Dr2
;
350 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 3))
352 *r
= &gdbctx
->context
.Dr3
;
359 /******************************************************************
364 * -1 if operation isn't supported by CPU
366 static inline int cpu_insert_Xpoint(struct gdb_context
* gdbctx
,
367 struct gdb_ctx_Xpoint
* xpt
, size_t len
)
379 if (len
!= 1) return 0;
380 if (!ReadProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &ch
, 1, &sz
) || sz
!= 1) return 0;
383 if (!WriteProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &ch
, 1, &sz
) || sz
!= 1) return 0;
386 bits
= DR7_RW_EXECUTE
;
394 if ((reg
= i386_get_unused_DR(gdbctx
, &pr
)) == -1) return 0;
395 *pr
= (unsigned long)xpt
->addr
;
396 if (xpt
->type
!= '1') switch (len
)
398 case 4: bits
|= DR7_LEN_4
; break;
399 case 2: bits
|= DR7_LEN_2
; break;
400 case 1: bits
|= DR7_LEN_1
; break;
404 /* clear old values */
405 gdbctx
->context
.Dr7
&= ~(0x0F << (DR7_CONTROL_SHIFT
+ DR7_CONTROL_SIZE
* reg
));
406 /* set the correct ones */
407 gdbctx
->context
.Dr7
|= bits
<< (DR7_CONTROL_SHIFT
+ DR7_CONTROL_SIZE
* reg
);
408 gdbctx
->context
.Dr7
|= DR7_ENABLE_MASK(reg
) | DR7_LOCAL_SLOWDOWN
;
411 fprintf(stderr
, "Unknown bp type %c\n", xpt
->type
);
415 #elif defined(__powerpc__)
422 if (len
!= 4) return 0;
423 if (!ReadProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &xbp
, 4, &sz
) || sz
!= 4) return 0;
425 xbp
= 0x7d821008; /* 7d 82 10 08 ... in big endian */
426 if (!WriteProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &xbp
, 4, &sz
) || sz
!= 4) return 0;
429 fprintf(stderr
, "Unknown/unsupported bp type %c\n", xpt
->type
);
434 #error "Define insert Xpoint for your CPU"
439 /******************************************************************
444 * -1 if operation isn't supported by CPU
446 static inline BOOL
cpu_remove_Xpoint(struct gdb_context
* gdbctx
,
447 struct gdb_ctx_Xpoint
* xpt
, size_t len
)
456 if (len
!= 1) return 0;
457 ch
= (unsigned char)xpt
->val
;
458 if (!WriteProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &ch
, 1, &sz
) || sz
!= 1) return 0;
463 /* simply disable the entry */
464 gdbctx
->context
.Dr7
&= ~DR7_ENABLE_MASK(xpt
->val
);
467 fprintf(stderr
, "Unknown bp type %c\n", xpt
->type
);
471 #elif defined(__powerpc__)
478 if (len
!= 4) return 0;
480 if (!WriteProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &xbp
, 4, &sz
) || sz
!= 4) return 0;
486 fprintf(stderr
, "Unknown/unsupported bp type %c\n", xpt
->type
);
491 #error "Define remove Xpoint for your CPU"
495 /* =============================================== *
496 * W I N 3 2 D E B U G I N T E R F A C E *
497 * =============================================== *
500 static BOOL
fetch_context(struct gdb_context
* gdbctx
, HANDLE h
, CONTEXT
* ctx
)
502 ctx
->ContextFlags
= CONTEXT_CONTROL
504 #ifdef CONTEXT_SEGMENTS
507 #ifdef CONTEXT_DEBUG_REGISTERS
508 | CONTEXT_DEBUG_REGISTERS
511 if (!GetThreadContext(h
, ctx
))
513 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
514 fprintf(stderr
, "Can't get thread's context\n");
520 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
522 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
525 switch (rec
->ExceptionCode
)
527 case EXCEPTION_ACCESS_VIOLATION
:
528 case EXCEPTION_PRIV_INSTRUCTION
:
529 case EXCEPTION_STACK_OVERFLOW
:
530 case EXCEPTION_GUARD_PAGE
:
531 gdbctx
->last_sig
= SIGSEGV
;
534 case EXCEPTION_DATATYPE_MISALIGNMENT
:
535 gdbctx
->last_sig
= SIGBUS
;
538 case EXCEPTION_SINGLE_STEP
:
540 case EXCEPTION_BREAKPOINT
:
541 gdbctx
->last_sig
= SIGTRAP
;
544 case EXCEPTION_FLT_DENORMAL_OPERAND
:
545 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
546 case EXCEPTION_FLT_INEXACT_RESULT
:
547 case EXCEPTION_FLT_INVALID_OPERATION
:
548 case EXCEPTION_FLT_OVERFLOW
:
549 case EXCEPTION_FLT_STACK_CHECK
:
550 case EXCEPTION_FLT_UNDERFLOW
:
551 gdbctx
->last_sig
= SIGFPE
;
554 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
555 case EXCEPTION_INT_OVERFLOW
:
556 gdbctx
->last_sig
= SIGFPE
;
559 case EXCEPTION_ILLEGAL_INSTRUCTION
:
560 gdbctx
->last_sig
= SIGILL
;
564 gdbctx
->last_sig
= SIGINT
;
567 case STATUS_POSSIBLE_DEADLOCK
:
568 gdbctx
->last_sig
= SIGALRM
;
570 /* FIXME: we could also add here a O packet with additional information */
573 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
574 fprintf(stderr
, "Unhandled exception code %08lx\n", rec
->ExceptionCode
);
575 gdbctx
->last_sig
= SIGABRT
;
582 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
586 DEBUG_CurrThread
= DEBUG_GetThread(gdbctx
->process
, de
->dwThreadId
);
588 switch (de
->dwDebugEventCode
)
590 case CREATE_PROCESS_DEBUG_EVENT
:
591 DEBUG_ProcessGetStringIndirect(buffer
, sizeof(buffer
),
592 de
->u
.CreateProcessInfo
.hProcess
,
593 de
->u
.CreateProcessInfo
.lpImageName
);
595 /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
596 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
597 fprintf(stderr
, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
598 de
->dwProcessId
, de
->dwThreadId
,
599 buffer
, de
->u
.CreateProcessInfo
.lpImageName
,
600 (unsigned long)(LPVOID
)de
->u
.CreateProcessInfo
.lpStartAddress
,
601 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
602 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
604 gdbctx
->process
= DEBUG_AddProcess(de
->dwProcessId
,
605 de
->u
.CreateProcessInfo
.hProcess
,
607 /* de->u.CreateProcessInfo.lpStartAddress; */
609 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
610 fprintf(stderr
, "%08lx:%08lx: create thread I @%08lx\n",
611 de
->dwProcessId
, de
->dwThreadId
,
612 (unsigned long)(LPVOID
)de
->u
.CreateProcessInfo
.lpStartAddress
);
614 assert(DEBUG_CurrThread
== NULL
); /* shouldn't be there */
615 DEBUG_AddThread(gdbctx
->process
, de
->dwThreadId
,
616 de
->u
.CreateProcessInfo
.hThread
,
617 de
->u
.CreateProcessInfo
.lpStartAddress
,
618 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
620 DEBUG_LoadModule32(DEBUG_CurrProcess
->imageName
, de
->u
.CreateProcessInfo
.hFile
,
621 de
->u
.CreateProcessInfo
.lpBaseOfImage
);
623 if (buffer
[0]) /* we got a process name */
626 if (!GetBinaryTypeA( buffer
, &type
))
628 /* not a Windows binary, assume it's a Unix executable then */
629 char unixname
[MAX_PATH
];
630 /* HACK!! should fix DEBUG_ReadExecutableDbgInfo to accept DOS filenames */
631 if (wine_get_unix_file_name( buffer
, unixname
, sizeof(unixname
) ))
633 DEBUG_ReadExecutableDbgInfo( unixname
);
638 /* if it is a Windows binary, or an invalid or missing file name,
639 * we use wine itself as the main executable */
640 DEBUG_ReadExecutableDbgInfo( "wine" );
644 case LOAD_DLL_DEBUG_EVENT
:
645 assert(DEBUG_CurrThread
);
646 DEBUG_ProcessGetStringIndirect(buffer
, sizeof(buffer
),
647 gdbctx
->process
->handle
,
648 de
->u
.LoadDll
.lpImageName
);
650 /* FIXME unicode: de->u.LoadDll.fUnicode */
651 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
652 fprintf(stderr
, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
653 de
->dwProcessId
, de
->dwThreadId
,
654 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
,
655 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
656 de
->u
.LoadDll
.nDebugInfoSize
);
659 DEBUG_LoadModule32(buffer
, de
->u
.LoadDll
.hFile
, de
->u
.LoadDll
.lpBaseOfDll
);
660 DEBUG_CheckDelayedBP();
661 if (DBG_IVAR(BreakOnDllLoad
))
663 DEBUG_Printf(DBG_CHN_MESG
, "Stopping on DLL %s loading at %08lx\n",
664 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
);
670 case UNLOAD_DLL_DEBUG_EVENT
:
671 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
672 fprintf(stderr
, "%08lx:%08lx: unload DLL @%08lx\n",
673 de
->dwProcessId
, de
->dwThreadId
, (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
676 case EXCEPTION_DEBUG_EVENT
:
677 assert(DEBUG_CurrThread
);
678 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
679 fprintf(stderr
, "%08lx:%08lx: exception code=%08lx\n",
680 de
->dwProcessId
, de
->dwThreadId
,
681 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
683 if (fetch_context(gdbctx
, DEBUG_CurrThread
->handle
, &gdbctx
->context
))
685 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
689 case CREATE_THREAD_DEBUG_EVENT
:
690 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
691 fprintf(stderr
, "%08lx:%08lx: create thread D @%08lx\n",
692 de
->dwProcessId
, de
->dwThreadId
, (unsigned long)(LPVOID
)de
->u
.CreateThread
.lpStartAddress
);
694 DEBUG_AddThread(gdbctx
->process
,
696 de
->u
.CreateThread
.hThread
,
697 de
->u
.CreateThread
.lpStartAddress
,
698 de
->u
.CreateThread
.lpThreadLocalBase
);
701 case EXIT_THREAD_DEBUG_EVENT
:
702 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
703 fprintf(stderr
, "%08lx:%08lx: exit thread (%ld)\n",
704 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
706 assert(DEBUG_CurrThread
);
707 if (DEBUG_CurrThread
== gdbctx
->exec_thread
) gdbctx
->exec_thread
= NULL
;
708 if (DEBUG_CurrThread
== gdbctx
->other_thread
) gdbctx
->other_thread
= NULL
;
709 DEBUG_DelThread(DEBUG_CurrThread
);
712 case EXIT_PROCESS_DEBUG_EVENT
:
713 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
714 fprintf(stderr
, "%08lx:%08lx: exit process (%ld)\n",
715 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
717 DEBUG_DelProcess(gdbctx
->process
);
718 gdbctx
->process
= NULL
;
719 /* now signal gdb that we're done */
720 gdbctx
->last_sig
= SIGTERM
;
721 gdbctx
->in_trap
= TRUE
;
724 case OUTPUT_DEBUG_STRING_EVENT
:
725 assert(DEBUG_CurrThread
);
726 DEBUG_ProcessGetString(buffer
, sizeof(buffer
),
727 gdbctx
->process
->handle
,
728 de
->u
.DebugString
.lpDebugStringData
);
729 /* FIXME unicode de->u.DebugString.fUnicode ? */
730 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
731 fprintf(stderr
, "%08lx:%08lx: output debug string (%s)\n",
732 de
->dwProcessId
, de
->dwThreadId
, buffer
);
736 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
737 fprintf(stderr
, "%08lx:%08lx: rip error=%ld type=%ld\n",
738 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
739 de
->u
.RipInfo
.dwType
);
743 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
744 fprintf(stderr
, "%08lx:%08lx: unknown event (%ld)\n",
745 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
749 static void resume_debuggee(struct gdb_context
* gdbctx
, unsigned long cont
)
751 if (DEBUG_CurrThread
)
753 if (!SetThreadContext(DEBUG_CurrThread
->handle
, &gdbctx
->context
))
754 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
755 fprintf(stderr
, "Cannot set context on thread %lu\n", DEBUG_CurrThread
->tid
);
756 if (!ContinueDebugEvent(gdbctx
->process
->pid
, DEBUG_CurrThread
->tid
, cont
))
757 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
758 fprintf(stderr
, "Cannot continue on %lu (%lu)\n",
759 DEBUG_CurrThread
->tid
, cont
);
761 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
762 fprintf(stderr
, "Cannot find last thread (%lu)\n", DEBUG_CurrThread
->tid
);
765 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
769 gdbctx
->in_trap
= FALSE
;
770 while (WaitForDebugEvent(&de
, INFINITE
))
772 handle_debug_event(gdbctx
, &de
);
773 assert(!gdbctx
->process
||
774 gdbctx
->process
->pid
== 0 ||
775 de
.dwProcessId
== gdbctx
->process
->pid
);
776 assert(!DEBUG_CurrThread
|| de
.dwThreadId
== DEBUG_CurrThread
->tid
);
777 if (gdbctx
->in_trap
) break;
778 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
782 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
784 cpu_leave_stepping(gdbctx
);
785 resume_debuggee(gdbctx
, DBG_CONTINUE
);
787 DebugActiveProcessStop(gdbctx
->process
->pid
);
788 DEBUG_DelProcess(gdbctx
->process
);
789 gdbctx
->process
= NULL
;
792 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
794 unsigned long status
;
796 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
798 strcpy(buffer
, "Unknown process");
801 if (status
== STILL_ACTIVE
)
803 strcpy(buffer
, "Running");
806 snprintf(buffer
, len
, "Terminated (%lu)", status
);
808 switch (GetPriorityClass(gdbctx
->process
->handle
))
811 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
812 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
814 #ifdef BELOW_NORMAL_PRIORITY_CLASS
815 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
817 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
818 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
819 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
820 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
822 strcat(buffer
, "\n");
825 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
826 char* buffer
, size_t len
)
829 unsigned long status
;
832 /* FIXME: use the size of buffer */
833 thd
= DEBUG_GetThread(gdbctx
->process
, tid
);
836 strcpy(buffer
, "No information");
839 if (GetExitCodeThread(thd
->handle
, &status
))
841 if (status
== STILL_ACTIVE
)
843 /* FIXME: this is a bit brutal... some nicer way shall be found */
844 switch (status
= SuspendThread(thd
->handle
))
847 case 0: strcpy(buffer
, "Running"); break;
848 default: snprintf(buffer
, len
, "Suspended (%lu)", status
- 1);
850 ResumeThread(thd
->handle
);
853 snprintf(buffer
, len
, "Terminated (exit code = %lu)", status
);
857 strcpy(buffer
, "Unknown threadID");
859 switch (prio
= GetThreadPriority(thd
->handle
))
861 case THREAD_PRIORITY_ERROR_RETURN
: break;
862 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
863 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
864 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
865 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
866 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
867 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
868 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
869 default: snprintf(buffer
+ strlen(buffer
), len
- strlen(buffer
), ", priority = %d", prio
);
871 assert(strlen(buffer
) < len
);
874 /* =============================================== *
875 * P A C K E T U T I L S *
876 * =============================================== *
879 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
880 packet_last_f
= 0x80};
882 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
884 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
886 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
887 gdbctx
->out_buf
= realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
891 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
893 packet_reply_grow(gdbctx
, len
* 2);
894 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
895 gdbctx
->out_len
+= len
* 2;
898 static inline void packet_reply_hex_to_str(struct gdb_context
* gdbctx
, const char* src
)
900 packet_reply_hex_to(gdbctx
, src
, strlen(src
));
903 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
907 shift
= (len
- 1) * 8;
908 packet_reply_grow(gdbctx
, len
* 2);
909 for (i
= 0; i
< len
; i
++, shift
-= 8)
911 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
912 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
916 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
918 packet_reply_grow(gdbctx
, len
);
919 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
920 gdbctx
->out_len
+= len
;
923 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
925 packet_reply_add(gdbctx
, str
, strlen(str
));
928 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
930 packet_reply_add(gdbctx
, &ch
, 1);
933 static void packet_reply_open(struct gdb_context
* gdbctx
)
935 assert(gdbctx
->out_curr_packet
== -1);
936 packet_reply_catc(gdbctx
, '$');
937 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
940 static void packet_reply_close(struct gdb_context
* gdbctx
)
945 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
946 packet_reply_catc(gdbctx
, '#');
947 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
948 packet_reply_hex_to(gdbctx
, &cksum
, 1);
949 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
950 fprintf(stderr
, "Reply : %*.*s\n",
951 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
952 gdbctx
->out_curr_packet
= -1;
955 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
957 packet_reply_open(gdbctx
);
959 if (len
== -1) len
= strlen(packet
);
960 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
962 packet_reply_add(gdbctx
, packet
, len
);
964 packet_reply_close(gdbctx
);
969 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
971 packet_reply_open(gdbctx
);
973 packet_reply_add(gdbctx
, "E", 1);
974 packet_reply_val(gdbctx
, error
, 1);
976 packet_reply_close(gdbctx
);
981 /* =============================================== *
982 * P A C K E T H A N D L E R S *
983 * =============================================== *
986 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
988 enum packet_return ret
= packet_done
;
990 packet_reply_open(gdbctx
);
992 if (gdbctx
->process
!= NULL
)
997 packet_reply_catc(gdbctx
, 'T');
998 sig
= gdbctx
->last_sig
;
999 packet_reply_val(gdbctx
, sig
, 1);
1000 packet_reply_add(gdbctx
, "thread:", 7);
1001 packet_reply_val(gdbctx
, DEBUG_CurrThread
->tid
, 4);
1002 packet_reply_catc(gdbctx
, ';');
1004 for (i
= 0; i
< cpu_num_regs
; i
++)
1006 /* FIXME: this call will also grow the buffer...
1007 * unneeded, but not harmful
1009 packet_reply_val(gdbctx
, i
, 1);
1010 packet_reply_catc(gdbctx
, ':');
1011 packet_reply_hex_to(gdbctx
, cpu_register(&gdbctx
->context
, i
), 4);
1012 packet_reply_catc(gdbctx
, ';');
1017 /* Try to put an exit code
1018 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
1019 * just indicate the end of process and exit */
1020 packet_reply_add(gdbctx
, "W00", 3);
1021 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
1024 packet_reply_close(gdbctx
);
1030 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
1032 gdbctx
->extended
= 1;
1037 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
1039 assert(gdbctx
->in_packet_len
== 0);
1040 return packet_reply_status(gdbctx
);
1043 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
1045 /* FIXME: add support for address in packet */
1046 assert(gdbctx
->in_packet_len
== 0);
1047 if (DEBUG_CurrThread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1048 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1049 fprintf(stderr
, "NIY: cont on %lu, while last thread is %lu\n",
1050 gdbctx
->exec_thread
->tid
, DEBUG_CurrThread
->tid
);
1051 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1052 wait_for_debuggee(gdbctx
);
1053 return packet_reply_status(gdbctx
);
1056 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
1060 /* FIXME: add support for address in packet */
1061 assert(gdbctx
->in_packet_len
== 2);
1062 if (DEBUG_CurrThread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1063 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1064 fprintf(stderr
, "NIY: cont/sig on %lu, while last thread is %lu\n",
1065 gdbctx
->exec_thread
->tid
, DEBUG_CurrThread
->tid
);
1066 hex_from(&sig
, gdbctx
->in_packet
, 1);
1067 /* cannot change signals on the fly */
1068 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1069 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1070 if (sig
!= gdbctx
->last_sig
)
1071 return packet_error
;
1072 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1073 wait_for_debuggee(gdbctx
);
1074 return packet_reply_status(gdbctx
);
1077 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
1079 detach_debuggee(gdbctx
, FALSE
);
1080 return packet_ok
| packet_last_f
;
1083 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
1087 CONTEXT
* pctx
= &gdbctx
->context
;
1089 assert(gdbctx
->in_trap
);
1091 if (DEBUG_CurrThread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1093 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1094 return packet_error
;
1097 packet_reply_open(gdbctx
);
1098 for (i
= 0; i
< cpu_num_regs
; i
++)
1100 packet_reply_hex_to(gdbctx
, cpu_register(pctx
, i
), 4);
1102 packet_reply_close(gdbctx
);
1106 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
1110 CONTEXT
* pctx
= &gdbctx
->context
;
1112 assert(gdbctx
->in_trap
);
1113 if (DEBUG_CurrThread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1115 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1116 return packet_error
;
1118 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
1120 for (i
= 0; i
< cpu_num_regs
; i
++)
1121 hex_from(cpu_register(pctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
1122 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1124 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1125 fprintf(stderr
, "Cannot set context on thread %lu\n", gdbctx
->other_thread
->tid
);
1126 return packet_error
;
1131 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
1133 detach_debuggee(gdbctx
, TRUE
);
1135 if (!gdbctx
->extended
)
1136 /* dunno whether GDB cares or not */
1140 /* assume we can't really answer something here */
1141 /* return packet_done; */
1144 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
1149 switch (gdbctx
->in_packet
[0])
1153 if (gdbctx
->in_packet
[1] == '-')
1154 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
1156 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
1157 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
1159 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1160 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1161 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1162 gdbctx
->in_packet
+ 1);
1163 return packet_error
;
1165 if (gdbctx
->in_packet
[0] == 'c')
1166 gdbctx
->exec_thread
= DEBUG_GetThread(gdbctx
->process
, thread
);
1168 gdbctx
->other_thread
= DEBUG_GetThread(gdbctx
->process
, thread
);
1171 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1172 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1173 return packet_error
;
1177 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1180 size_t len
, blk_len
, nread
;
1182 unsigned long r
= 0;
1184 assert(gdbctx
->in_trap
);
1185 /* FIXME:check in_packet_len for reading %p,%x */
1186 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1187 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1188 fprintf(stderr
, "Read mem at %p for %u bytes\n", addr
, len
);
1189 for (nread
= 0; nread
< len
> 0; nread
+= r
, addr
+= r
)
1191 blk_len
= min(sizeof(buffer
), len
- nread
);
1192 if (!ReadProcessMemory(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1195 /* fail at first address, return error */
1196 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1197 /* something has already been read, return partial information */
1200 if (nread
== 0) packet_reply_open(gdbctx
);
1201 packet_reply_hex_to(gdbctx
, buffer
, r
);
1203 packet_reply_close(gdbctx
);
1207 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1210 size_t len
, blk_len
;
1215 assert(gdbctx
->in_trap
);
1216 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1219 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1220 fprintf(stderr
, "Cannot find ':' in %*.*s\n",
1221 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1222 return packet_error
;
1226 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1228 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1229 fprintf(stderr
, "Cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1230 return packet_error
;
1232 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1234 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1235 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1236 ptr
- gdbctx
->in_packet
+ len
* 2, gdbctx
->in_packet_len
);
1237 return packet_error
;
1239 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1240 fprintf(stderr
, "Write %u bytes at %p\n", len
, addr
);
1243 blk_len
= min(sizeof(buffer
), len
);
1244 hex_from(buffer
, ptr
, blk_len
);
1248 ret
= WriteProcessMemory(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
);
1249 if (!ret
|| w
!= blk_len
)
1256 return packet_ok
; /* FIXME: error while writing ? */
1259 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1265 CONTEXT
* pctx
= &gdbctx
->context
;
1267 assert(gdbctx
->in_trap
);
1269 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1271 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1272 if (end
== NULL
|| reg
> cpu_num_regs
)
1274 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1275 fprintf(stderr
, "Invalid register index %s\n", gdbctx
->in_packet
);
1276 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1277 * it wouldn't matter too much, and it fakes our support for all regs
1279 return (end
== NULL
) ? packet_error
: packet_ok
;
1281 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1283 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1284 fprintf(stderr
, "Wrong sizes %u <> %u\n",
1285 ptr
+ 8 - gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1286 return packet_error
;
1288 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1289 fprintf(stderr
, "Writing reg %u <= %*.*s\n",
1290 reg
, gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
),
1291 gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
), ptr
);
1293 if (DEBUG_CurrThread
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1295 if (!fetch_context(gdbctx
, gdbctx
->other_thread
->handle
, pctx
= &ctx
))
1296 return packet_error
;
1299 hex_from(cpu_register(pctx
, reg
), ptr
, 4);
1300 if (pctx
!= &gdbctx
->context
&& !SetThreadContext(gdbctx
->other_thread
->handle
, pctx
))
1302 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
1303 fprintf(stderr
, "Cannot set context for thread %lu\n", gdbctx
->other_thread
->tid
);
1304 return packet_error
;
1310 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1318 if (!GetClassName(hWnd
, clsName
, sizeof(clsName
)))
1319 strcpy(clsName
, "-- Unknown --");
1320 if (!GetWindowText(hWnd
, wndName
, sizeof(wndName
)))
1321 strcpy(wndName
, "-- Empty --");
1323 packet_reply_open(gdbctx
);
1324 packet_reply_catc(gdbctx
, 'O');
1325 snprintf(buffer
, sizeof(buffer
),
1326 "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1327 indent
, "", (UINT
)hWnd
, 13 - indent
, "",
1328 clsName
, GetWindowLong(hWnd
, GWL_STYLE
),
1329 GetWindowLong(hWnd
, GWL_WNDPROC
), wndName
);
1330 packet_reply_hex_to_str(gdbctx
, buffer
);
1331 packet_reply_close(gdbctx
);
1333 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1334 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1335 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1338 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1342 /* we do the output in several 'O' packets, with the last one being just OK for
1343 * marking the end of the output */
1344 packet_reply_open(gdbctx
);
1345 packet_reply_catc(gdbctx
, 'O');
1346 snprintf(buffer
, sizeof(buffer
),
1347 "%-16.16s %-17.17s %-8.8s %s\n",
1348 "hwnd", "Class Name", " Style", " WndProc Text");
1349 packet_reply_hex_to_str(gdbctx
, buffer
);
1350 packet_reply_close(gdbctx
);
1352 /* FIXME: could also add a pmt to this command in str... */
1353 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1354 packet_reply(gdbctx
, "OK", 2);
1357 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1359 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1362 PROCESSENTRY32 entry
;
1365 if (snap
== INVALID_HANDLE_VALUE
)
1368 entry
.dwSize
= sizeof(entry
);
1369 ok
= Process32First( snap
, &entry
);
1371 /* we do the output in several 'O' packets, with the last one being just OK for
1372 * marking the end of the output */
1374 packet_reply_open(gdbctx
);
1375 packet_reply_catc(gdbctx
, 'O');
1376 snprintf(buffer
, sizeof(buffer
),
1377 " %-8.8s %-8.8s %-8.8s %s\n",
1378 "pid", "threads", "parent", "executable" );
1379 packet_reply_hex_to_str(gdbctx
, buffer
);
1380 packet_reply_close(gdbctx
);
1385 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1386 packet_reply_open(gdbctx
);
1387 packet_reply_catc(gdbctx
, 'O');
1388 snprintf(buffer
, sizeof(buffer
),
1389 "%c%08lx %-8ld %08lx '%s'\n",
1390 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1391 entry
.th32ParentProcessID
, entry
.szExeFile
);
1392 packet_reply_hex_to_str(gdbctx
, buffer
);
1393 packet_reply_close(gdbctx
);
1394 ok
= Process32Next(snap
, &entry
);
1397 packet_reply(gdbctx
, "OK", 2);
1400 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1402 MEMORY_BASIC_INFORMATION mbi
;
1409 /* we do the output in several 'O' packets, with the last one being just OK for
1410 * marking the end of the output */
1411 packet_reply_open(gdbctx
);
1412 packet_reply_catc(gdbctx
, 'O');
1413 packet_reply_hex_to_str(gdbctx
, "Address Size State Type RWX\n");
1414 packet_reply_close(gdbctx
);
1416 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1420 case MEM_COMMIT
: state
= "commit "; break;
1421 case MEM_FREE
: state
= "free "; break;
1422 case MEM_RESERVE
: state
= "reserve"; break;
1423 default: state
= "??? "; break;
1425 if (mbi
.State
!= MEM_FREE
)
1429 case MEM_IMAGE
: type
= "image "; break;
1430 case MEM_MAPPED
: type
= "mapped "; break;
1431 case MEM_PRIVATE
: type
= "private"; break;
1432 case 0: type
= " "; break;
1433 default: type
= "??? "; break;
1435 memset(prot
, ' ' , sizeof(prot
)-1);
1436 prot
[sizeof(prot
)-1] = '\0';
1437 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1439 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1441 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1443 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1451 packet_reply_open(gdbctx
);
1452 snprintf(buffer
, sizeof(buffer
),
1453 "%08lx %08lx %s %s %s\n",
1454 (DWORD
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1455 packet_reply_catc(gdbctx
, 'O');
1456 packet_reply_hex_to_str(gdbctx
, buffer
);
1457 packet_reply_close(gdbctx
);
1459 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1461 addr
+= mbi
.RegionSize
;
1463 packet_reply(gdbctx
, "OK", 2);
1466 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1467 int len
, const char* str
)
1473 snprintf(buffer
, sizeof(buffer
), "trace=%x\n", gdbctx
->trace
);
1475 else if (len
>= 2 && str
[0] == '=')
1477 unsigned val
= atoi(&str
[1]);
1478 snprintf(buffer
, sizeof(buffer
), "trace: %x => %x\n", gdbctx
->trace
, val
);
1479 gdbctx
->trace
= val
;
1483 /* FIXME: ugly but can use error packet here */
1484 packet_reply_cat(gdbctx
, "E00");
1487 packet_reply_open(gdbctx
);
1488 packet_reply_hex_to_str(gdbctx
, buffer
);
1489 packet_reply_close(gdbctx
);
1493 static void packet_query_monitor_linear(struct gdb_context
* gdbctx
,
1494 int len
, const char* str
)
1501 while (len
> 0 && (*str
== ' ' || *str
== '\t'))
1505 /* FIXME: do a better scanning (allow both decimal and hex numbers) */
1506 if (!len
|| sscanf(str
, "%x:%x", &seg
, &ofs
) != 2)
1508 packet_reply_error(gdbctx
, 0);
1513 if (gdbctx
->context
.EFlags
& 0x00020000) linear
= (LOWORD(seg
) << 4) + ofs
;
1514 /* linux system selector ? */
1515 else if (!(seg
& 4) || ((seg
>> 3) < 17)) linear
= ofs
;
1516 /* standard selector */
1517 else if (GetThreadSelectorEntry(gdbctx
->process
->threads
->handle
, seg
, &le
))
1518 linear
= (le
.HighWord
.Bits
.BaseHi
<< 24) + (le
.HighWord
.Bits
.BaseMid
<< 16) +
1522 snprintf(buffer
, sizeof(buffer
), "0x%x", linear
);
1523 packet_reply_open(gdbctx
);
1524 packet_reply_hex_to_str(gdbctx
, buffer
);
1525 packet_reply_close(gdbctx
);
1534 void (*handler
)(struct gdb_context
*, int, const char*);
1537 {0, "wnd", 3, packet_query_monitor_wnd
},
1538 {0, "window", 6, packet_query_monitor_wnd
},
1539 {0, "proc", 4, packet_query_monitor_process
},
1540 {0, "process", 7, packet_query_monitor_process
},
1541 {0, "mem", 3, packet_query_monitor_mem
},
1542 {1, "trace", 5, packet_query_monitor_trace
},
1544 {1, "linear", 6, packet_query_monitor_linear
},
1549 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1550 const char* hxcmd
, size_t len
)
1553 struct query_detail
* qd
;
1555 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1557 hex_from(buffer
, hxcmd
, len
);
1559 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1561 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1562 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1564 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1567 return packet_reply_error(gdbctx
, EINVAL
);
1570 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1572 switch (gdbctx
->in_packet
[0])
1575 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1579 packet_reply_open(gdbctx
);
1580 packet_reply_add(gdbctx
, "m", 1);
1581 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1583 packet_reply_val(gdbctx
, thd
->tid
, 4);
1584 if (thd
->next
!= NULL
)
1585 packet_reply_add(gdbctx
, ",", 1);
1587 packet_reply_close(gdbctx
);
1590 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1594 packet_reply_open(gdbctx
);
1595 packet_reply_catc(gdbctx
, 'O');
1596 get_process_info(gdbctx
, result
, sizeof(result
));
1597 packet_reply_hex_to_str(gdbctx
, result
);
1598 packet_reply_close(gdbctx
);
1603 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1605 packet_reply(gdbctx
, "l", 1);
1608 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1610 packet_reply(gdbctx
, "l", 1);
1615 if (gdbctx
->in_packet_len
== 1)
1618 /* FIXME: doc says 16 bit val ??? */
1619 /* grab first created thread, aka last in list */
1620 assert(gdbctx
->process
&& gdbctx
->process
->threads
);
1621 for (thd
= gdbctx
->process
->threads
; thd
->next
; thd
= thd
->next
);
1622 packet_reply_open(gdbctx
);
1623 packet_reply_add(gdbctx
, "QC", 2);
1624 packet_reply_val(gdbctx
, thd
->tid
, 4);
1625 packet_reply_close(gdbctx
);
1630 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1634 if (gdbctx
->wine_segs
[0] == 0 && gdbctx
->wine_segs
[1] == 0 &&
1635 gdbctx
->wine_segs
[2] == 0)
1636 return packet_error
;
1637 snprintf(buf
, sizeof(buf
),
1638 "Text=%08lx;Data=%08lx;Bss=%08lx",
1639 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1640 gdbctx
->wine_segs
[2]);
1641 return packet_reply(gdbctx
, buf
, -1);
1645 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1647 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1648 gdbctx
->in_packet_len
- 5);
1652 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1656 if (gdbctx
->in_packet_len
> 15 &&
1657 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1658 gdbctx
->in_packet
[15] == ',')
1664 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1665 if (end
== NULL
) break;
1666 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1667 packet_reply_open(gdbctx
);
1668 packet_reply_hex_to_str(gdbctx
, result
);
1669 packet_reply_close(gdbctx
);
1674 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1675 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1676 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1677 return packet_error
;
1680 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1682 /* FIXME: add support for address in packet */
1683 assert(gdbctx
->in_packet_len
== 0);
1684 if (DEBUG_CurrThread
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1685 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_FIXME
)
1686 fprintf(stderr
, "NIY: step on %lu, while last thread is %lu\n",
1687 gdbctx
->exec_thread
->tid
, DEBUG_CurrThread
->tid
);
1688 if (!cpu_enter_stepping(gdbctx
)) return packet_error
;
1689 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1690 wait_for_debuggee(gdbctx
);
1691 if (!cpu_leave_stepping(gdbctx
)) return packet_error
;
1692 return packet_reply_status(gdbctx
);
1696 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1700 /* FIXME: add support for address in packet */
1701 assert(gdbctx
->in_packet_len
== 2);
1702 if (DEBUG_CurrThread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1703 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1704 fprintf(stderr
, "NIY: step/sig on %u, while last thread is %u\n",
1705 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1706 hex_from(&sig
, gdbctx
->in_packet
, 1);
1707 /* cannot change signals on the fly */
1708 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1709 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1710 if (sig
!= gdbctx
->last_sig
)
1711 return packet_error
;
1712 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1713 wait_for_debuggee(gdbctx
);
1714 return packet_reply_status(gdbctx
);
1718 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1723 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1724 if (tid
== -1 || tid
== 0)
1725 return packet_reply_error(gdbctx
, EINVAL
);
1726 if (DEBUG_GetThread(gdbctx
->process
, tid
) != NULL
)
1728 return packet_reply_error(gdbctx
, ESRCH
);
1731 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1735 struct gdb_ctx_Xpoint
* xpt
;
1737 /* FIXME: check packet_len */
1738 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1739 gdbctx
->in_packet
[1] != ',' ||
1740 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1741 return packet_error
;
1742 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1743 fprintf(stderr
, "Remove bp %p[%u] typ=%c\n",
1744 addr
, len
, gdbctx
->in_packet
[0]);
1745 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1747 if (xpt
->addr
== addr
&& xpt
->type
== gdbctx
->in_packet
[0])
1749 switch (cpu_remove_Xpoint(gdbctx
, xpt
, len
))
1751 case 1: xpt
->type
= -1; return packet_ok
;
1752 case 0: return packet_error
;
1753 case -1: return packet_done
;
1758 return packet_error
;
1761 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1765 struct gdb_ctx_Xpoint
* xpt
;
1767 /* FIXME: check packet_len */
1768 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1769 gdbctx
->in_packet
[1] != ',' ||
1770 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1771 return packet_error
;
1772 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1773 fprintf(stderr
, "Set bp %p[%u] typ=%c\n",
1774 addr
, len
, gdbctx
->in_packet
[0]);
1775 /* because of packet command handling, this should be made idempotent */
1776 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1778 if (xpt
->addr
== addr
&& xpt
->type
== gdbctx
->in_packet
[0])
1779 return packet_ok
; /* nothing to do */
1781 /* really set the Xpoint */
1782 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1784 if (xpt
->type
== -1)
1787 xpt
->type
= gdbctx
->in_packet
[0];
1788 switch (cpu_insert_Xpoint(gdbctx
, xpt
, len
))
1790 case 1: return packet_ok
;
1791 case 0: return packet_error
;
1792 case -1: return packet_done
;
1797 /* no more entries... eech */
1798 fprintf(stderr
, "Running out of spots for {break|watch}points\n");
1799 return packet_error
;
1802 /* =============================================== *
1803 * P A C K E T I N F R A S T R U C T U R E *
1804 * =============================================== *
1810 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1813 static struct packet_entry packet_entries
[] =
1815 /* {'!', packet_extended}, */
1816 {'?', packet_last_signal
},
1817 {'c', packet_continue
},
1818 {'C', packet_continue_signal
},
1819 {'D', packet_detach
},
1820 {'g', packet_read_registers
},
1821 {'G', packet_write_registers
},
1823 {'H', packet_thread
},
1824 {'m', packet_read_memory
},
1825 {'M', packet_write_memory
},
1826 /* {'p', packet_read_register}, doesn't seem needed */
1827 {'P', packet_write_register
},
1828 {'q', packet_query
},
1830 /*{'S', packet_step_signal}, hard(er) to implement */
1831 {'T', packet_thread_alive
},
1832 {'z', packet_remove_breakpoint
},
1833 {'Z', packet_set_breakpoint
},
1836 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
1840 unsigned char in_cksum
, loc_cksum
;
1842 enum packet_return ret
= packet_error
;
1845 while ((ret
& packet_last_f
) == 0)
1847 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
1848 fprintf(stderr
, "In-buf: %*.*s\n",
1849 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
1850 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
1851 if (ptr
== NULL
) return FALSE
;
1852 if (ptr
!= gdbctx
->in_buf
)
1854 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
1855 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1856 fprintf(stderr
, "Removing garbage: %*.*s\n",
1857 glen
, glen
, gdbctx
->in_buf
);
1858 gdbctx
->in_len
-= glen
;
1859 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
1861 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
1862 if (end
== NULL
) return FALSE
;
1863 /* no checksum yet */
1864 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
1865 plen
= end
- gdbctx
->in_buf
- 1;
1866 hex_from(&in_cksum
, end
+ 1, 1);
1867 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
1868 if (loc_cksum
== in_cksum
)
1870 if (num_packet
== 0) {
1875 write(gdbctx
->sock
, "+", 1);
1878 /* FIXME: should use bsearch if packet_entries was sorted */
1879 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
1881 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
1883 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
1885 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1886 fprintf(stderr
, "Unknown packet request %*.*s\n",
1887 plen
, plen
, &gdbctx
->in_buf
[1]);
1891 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
1892 gdbctx
->in_packet_len
= plen
- 1;
1893 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
1894 fprintf(stderr
, "Packet: %c%*.*s\n",
1896 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
1898 ret
= (packet_entries
[i
].handler
)(gdbctx
);
1900 switch (ret
& ~packet_last_f
)
1902 case packet_error
: packet_reply(gdbctx
, "", 0); break;
1903 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
1904 case packet_done
: break;
1906 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1907 fprintf(stderr
, "Reply-full: %*.*s\n",
1908 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
1909 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
1910 assert(i
== gdbctx
->out_len
);
1911 /* if this fails, we'll have to use POLLOUT...
1913 gdbctx
->out_len
= 0;
1918 /* FIXME: if we have in our input buffer more than one packet,
1919 * it's very likely that we took too long to answer to a given packet
1920 * and gdb is sending us again the same packet
1921 * We simply drop the second packet. This will lower the risk of error,
1922 * but there's still some race conditions here
1923 * A better fix (yet not perfect) would be to have two threads:
1924 * - one managing the packets for gdb
1925 * - the second one managing the commands...
1926 * This would allow us also the reply with the '+' character (Ack of
1927 * the command) way sooner than what we do now
1929 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1930 fprintf(stderr
, "Dropping packet, I was too slow to respond\n");
1935 write(gdbctx
->sock
, "+", 1);
1936 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1937 fprintf(stderr
, "Dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
1939 gdbctx
->in_len
-= plen
+ 4;
1940 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
1945 static int fetch_data(struct gdb_context
* gdbctx
)
1947 int len
, in_len
= gdbctx
->in_len
;
1949 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1953 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
1954 gdbctx
->in_buf
= realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
1956 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1957 fprintf(stderr
, "%d %d %*.*s\n",
1958 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
1959 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
1960 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
1961 if (len
<= 0) break;
1962 gdbctx
->in_len
+= len
;
1963 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1964 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
1966 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1967 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
1968 return gdbctx
->in_len
- in_len
;
1971 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
1974 struct sockaddr_in s_addrs
;
1975 int s_len
= sizeof(s_addrs
);
1976 struct pollfd pollfd
;
1977 char wine_path
[MAX_PATH
];
1980 /* step 1: create socket for gdb connection request */
1981 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1983 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1984 fprintf(stderr
, "Can't create socket");
1988 if (listen(sock
, 1) == -1 ||
1989 getsockname(sock
, (struct sockaddr
*)&s_addrs
, &s_len
) == -1)
1992 /* step 2: find out wine executable location (as a Unix filename) */
1993 ptr
= getenv("WINELOADER");
1994 strcpy(wine_path
, ptr
? ptr
: "wine");
1996 fprintf(stderr
, "Using wine_path: %s\n", wine_path
);
1997 read_elf_info(wine_path
, gdbctx
->wine_segs
);
1999 /* step 3: fire up gdb (if requested) */
2001 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2005 case -1: /* error in parent... */
2006 fprintf(stderr
, "Cannot create gdb\n");
2009 default: /* in parent... success */
2011 case 0: /* in child... and alive */
2018 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
2019 strcpy(buf
,"/tmp/winegdb.XXXXXX");
2020 fd
= mkstemps(buf
,0);
2021 if (fd
== -1) return FALSE
;
2022 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
2023 fprintf(f
, "file %s\n", wine_path
);
2024 fprintf(f
, "target remote localhost:%d\n", ntohs(s_addrs
.sin_port
));
2025 fprintf(f
, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME
);
2026 fprintf(f
, "set prompt Wine-gdb>\\ \n");
2027 /* gdb 5.1 seems to require it, won't hurt anyway */
2028 fprintf(f
, "sharedlibrary\n");
2029 /* tell gdb to delete this file when done handling it... */
2030 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
2033 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
2035 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
2036 assert(0); /* never reached */
2042 /* step 4: do the process internal creation */
2043 handle_debug_event(gdbctx
, de
);
2045 /* step 5: wait for gdb to connect actually */
2047 pollfd
.events
= POLLIN
;
2050 switch (poll(&pollfd
, 1, -1))
2053 if (pollfd
.revents
& POLLIN
)
2056 gdbctx
->sock
= accept(sock
, (struct sockaddr
*)&s_addrs
, &s_len
);
2057 if (gdbctx
->sock
== -1)
2059 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2060 fprintf(stderr
, "Connected on %d\n", gdbctx
->sock
);
2061 /* don't keep our small packets too long: send them ASAP back to GDB
2062 * without this, GDB really crawls
2064 setsockopt(gdbctx
->sock
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&dummy
, sizeof(dummy
));
2068 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2069 fprintf(stderr
, "Poll for cnx failed (timeout)\n");
2072 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
2073 fprintf(stderr
, "Poll for cnx failed (error)\n");
2083 static BOOL
gdb_init_context(struct gdb_context
* gdbctx
, unsigned flags
)
2089 gdbctx
->in_buf
= NULL
;
2090 gdbctx
->in_buf_alloc
= 0;
2092 gdbctx
->out_buf
= NULL
;
2093 gdbctx
->out_buf_alloc
= 0;
2094 gdbctx
->out_len
= 0;
2095 gdbctx
->out_curr_packet
= -1;
2097 gdbctx
->exec_thread
= gdbctx
->other_thread
= NULL
;
2098 gdbctx
->last_sig
= 0;
2099 gdbctx
->in_trap
= FALSE
;
2100 gdbctx
->trace
= /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR
| GDBPXY_TRC_COMMAND_FIXME
| GDBPXY_TRC_WIN32_EVENT
;
2101 gdbctx
->process
= NULL
;
2102 for (i
= 0; i
< NUM_XPOINT
; i
++)
2103 gdbctx
->Xpoints
[i
].type
= -1;
2105 /* wait for first trap */
2106 while (WaitForDebugEvent(&de
, INFINITE
))
2108 if (de
.dwDebugEventCode
== CREATE_PROCESS_DEBUG_EVENT
)
2110 /* this should be the first event we get,
2111 * and the only one of this type */
2112 assert(gdbctx
->process
== NULL
&& de
.dwProcessId
== DEBUG_CurrPid
);
2113 /*gdbctx->dwProcessId = pid; */
2114 if (!gdb_startup(gdbctx
, &de
, flags
)) return FALSE
;
2115 assert(!gdbctx
->in_trap
);
2119 handle_debug_event(gdbctx
, &de
);
2120 if (gdbctx
->in_trap
) break;
2122 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
2127 BOOL
DEBUG_GdbRemote(unsigned flags
)
2129 struct pollfd pollfd
;
2130 struct gdb_context gdbctx
;
2133 for (doLoop
= gdb_init_context(&gdbctx
, flags
); doLoop
;)
2135 pollfd
.fd
= gdbctx
.sock
;
2136 pollfd
.events
= POLLIN
;
2139 switch (poll(&pollfd
, 1, -1))
2143 if (pollfd
.revents
& (POLLHUP
| POLLERR
))
2145 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2146 fprintf(stderr
, "Gdb hung up\n");
2147 /* kill also debuggee process - questionnable - */
2148 detach_debuggee(&gdbctx
, TRUE
);
2152 if ((pollfd
.revents
& POLLIN
) && fetch_data(&gdbctx
) > 0)
2154 if (extract_packets(&gdbctx
)) doLoop
= FALSE
;
2158 /* timeout, should never happen (infinite timeout) */
2161 if (gdbctx
.trace
& GDBPXY_TRC_LOWLEVEL
)
2162 fprintf(stderr
, "Poll failed\n");