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
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
33 #ifdef HAVE_SYS_SOCKET_H
34 # include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netinet/tcp.h>
44 /* those two are needed only for the SHOWNORMAL flag */
50 #define GDBPXY_TRC_LOWLEVEL 0x01
51 #define GDBPXY_TRC_PACKET 0x02
52 #define GDBPXY_TRC_COMMAND 0x04
53 #define GDBPXY_TRC_COMMAND_ERROR 0x08
54 #define GDBPXY_TRC_WIN32_EVENT 0x10
55 #define GDBPXY_TRC_WIN32_ERROR 0x20
59 int type
; /* -1 means free */
72 /* split into individual packet */
80 /* generic GDB thread information */
81 unsigned exec_thread
; /* thread used in step & continue */
82 unsigned other_thread
; /* thread to be used in any other operation */
84 /* current Win32 trap env */
88 /* Win32 information */
91 struct gdb_ctx_Xpoint Xpoints
[NUM_XPOINT
];
92 /* Unix environment */
93 unsigned long wine_segs
[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
96 extern int read_elf_info(const char* filename
, unsigned long tab
[]);
98 /* =============================================== *
99 * B A S I C M A N I P U L A T I O N S *
100 * =============================================== *
103 static inline int hex_from0(char ch
)
105 if (ch
>= '0' && ch
<= '9') return ch
- '0';
106 if (ch
>= 'A' && ch
<= 'F') return ch
- 'A' + 10;
107 if (ch
>= 'a' && ch
<= 'f') return ch
- 'a' + 10;
111 static inline unsigned char hex_to0(int x
)
113 assert(x
>= 0 && x
< 16);
114 return "0123456789abcdef"[x
];
117 static void hex_from(void* dst
, const char* src
, size_t len
)
121 *(unsigned char*)dst
++ = (hex_from0(src
[0]) << 4) | hex_from0(src
[1]);
126 static void hex_to(char* dst
, const void* src
, size_t len
)
130 *dst
++ = hex_to0(*(const unsigned char*)src
>> 4);
131 *dst
++ = hex_to0(*(const unsigned char*)src
& 0x0F);
136 static unsigned char checksum(const char* ptr
, int len
)
141 cksum
+= (unsigned char)*ptr
++;
145 /* =============================================== *
146 * C P U H A N D L E R S *
147 * =============================================== *
150 #define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0)))
153 static size_t cpu_register_map
[] = {
154 OFFSET_OF(CONTEXT
, Eax
),
155 OFFSET_OF(CONTEXT
, Ecx
),
156 OFFSET_OF(CONTEXT
, Edx
),
157 OFFSET_OF(CONTEXT
, Ebx
),
158 OFFSET_OF(CONTEXT
, Esp
),
159 OFFSET_OF(CONTEXT
, Ebp
),
160 OFFSET_OF(CONTEXT
, Esi
),
161 OFFSET_OF(CONTEXT
, Edi
),
162 OFFSET_OF(CONTEXT
, Eip
),
163 OFFSET_OF(CONTEXT
, EFlags
),
164 OFFSET_OF(CONTEXT
, SegCs
),
165 OFFSET_OF(CONTEXT
, SegSs
),
166 OFFSET_OF(CONTEXT
, SegDs
),
167 OFFSET_OF(CONTEXT
, SegEs
),
168 OFFSET_OF(CONTEXT
, SegFs
),
169 OFFSET_OF(CONTEXT
, SegGs
),
172 #error "Define the registers map for your CPU"
176 static const size_t cpu_num_regs
= (sizeof(cpu_register_map
) / sizeof(cpu_register_map
[0]));
178 static inline unsigned long* cpu_register(struct gdb_context
* gdbctx
, unsigned idx
)
180 assert(idx
< cpu_num_regs
);
181 return (unsigned long*)((char*)&gdbctx
->context
+ cpu_register_map
[idx
]);
184 static inline BOOL
cpu_enter_stepping(struct gdb_context
* gdbctx
)
187 gdbctx
->context
.EFlags
|= 0x100;
190 #error "Define step mode enter for your CPU"
195 static inline BOOL
cpu_leave_stepping(struct gdb_context
* gdbctx
)
198 /* The Win32 debug API always resets the Step bit in EFlags after
199 * a single step instruction, so we don't need to clear when the
204 #error "Define step mode leave for your CPU"
210 #define DR7_CONTROL_SHIFT 16
211 #define DR7_CONTROL_SIZE 4
213 #define DR7_RW_EXECUTE (0x0)
214 #define DR7_RW_WRITE (0x1)
215 #define DR7_RW_READ (0x3)
217 #define DR7_LEN_1 (0x0)
218 #define DR7_LEN_2 (0x4)
219 #define DR7_LEN_4 (0xC)
221 #define DR7_LOCAL_ENABLE_SHIFT 0
222 #define DR7_GLOBAL_ENABLE_SHIFT 1
223 #define DR7_ENABLE_SIZE 2
225 #define DR7_LOCAL_ENABLE_MASK (0x55)
226 #define DR7_GLOBAL_ENABLE_MASK (0xAA)
228 #define DR7_CONTROL_RESERVED (0xFC00)
229 #define DR7_LOCAL_SLOWDOWN (0x100)
230 #define DR7_GLOBAL_SLOWDOWN (0x200)
232 #define DR7_ENABLE_MASK(dr) (1<<(DR7_LOCAL_ENABLE_SHIFT+DR7_ENABLE_SIZE*(dr)))
233 #define IS_DR7_SET(ctrl,dr) ((ctrl)&DR7_ENABLE_MASK(dr))
235 static inline int i386_get_unused_DR(struct gdb_context
* gdbctx
,
238 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 0))
240 *r
= &gdbctx
->context
.Dr0
;
243 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 1))
245 *r
= &gdbctx
->context
.Dr1
;
248 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 2))
250 *r
= &gdbctx
->context
.Dr2
;
253 if (!IS_DR7_SET(gdbctx
->context
.Dr7
, 3))
255 *r
= &gdbctx
->context
.Dr3
;
262 /******************************************************************
267 * -1 if operation isn't supported by CPU
269 static inline int cpu_insert_Xpoint(struct gdb_context
* gdbctx
,
270 struct gdb_ctx_Xpoint
* xpt
, size_t len
)
282 if (len
!= 1) return 0;
283 if (!ReadProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &ch
, 1, &sz
) || sz
!= 1) return 0;
286 if (!WriteProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &ch
, 1, &sz
) || sz
!= 1) return 0;
289 bits
= DR7_RW_EXECUTE
;
297 if ((reg
= i386_get_unused_DR(gdbctx
, &pr
)) == -1) return 0;
298 *pr
= (unsigned long)xpt
->addr
;
299 if (xpt
->type
!= '1') switch (len
)
301 case 4: bits
|= DR7_LEN_4
; break;
302 case 2: bits
|= DR7_LEN_2
; break;
303 case 1: bits
|= DR7_LEN_1
; break;
307 /* clear old values */
308 gdbctx
->context
.Dr7
&= ~(0x0F << (DR7_CONTROL_SHIFT
+ DR7_CONTROL_SIZE
* reg
));
309 /* set the correct ones */
310 gdbctx
->context
.Dr7
|= bits
<< (DR7_CONTROL_SHIFT
+ DR7_CONTROL_SIZE
* reg
);
311 gdbctx
->context
.Dr7
|= DR7_ENABLE_MASK(reg
) | DR7_LOCAL_SLOWDOWN
;
314 fprintf(stderr
, "Unknown bp type %c\n", xpt
->type
);
319 #error "Define insert Xpoint for your CPU"
324 /******************************************************************
329 * -1 if operation isn't supported by CPU
331 static inline BOOL
cpu_remove_Xpoint(struct gdb_context
* gdbctx
,
332 struct gdb_ctx_Xpoint
* xpt
, size_t len
)
341 if (len
!= 1) return 0;
342 ch
= (unsigned char)xpt
->val
;
343 if (!WriteProcessMemory(gdbctx
->process
->handle
, xpt
->addr
, &ch
, 1, &sz
) || sz
!= 1) return 0;
348 /* simply disable the entry */
349 gdbctx
->context
.Dr7
&= ~DR7_ENABLE_MASK(xpt
->val
);
352 fprintf(stderr
, "Unknown bp type %c\n", xpt
->type
);
357 #error "Define remove Xpoint for your CPU"
361 /* =============================================== *
362 * W I N 3 2 D E B U G I N T E R F A C E *
363 * =============================================== *
366 static BOOL
handle_exception(struct gdb_context
* gdbctx
, EXCEPTION_DEBUG_INFO
* exc
)
368 EXCEPTION_RECORD
* rec
= &exc
->ExceptionRecord
;
371 switch (rec
->ExceptionCode
)
373 case EXCEPTION_ACCESS_VIOLATION
:
374 case EXCEPTION_PRIV_INSTRUCTION
:
375 case EXCEPTION_STACK_OVERFLOW
:
376 case EXCEPTION_GUARD_PAGE
:
377 gdbctx
->last_sig
= SIGSEGV
;
380 case EXCEPTION_DATATYPE_MISALIGNMENT
:
381 gdbctx
->last_sig
= SIGBUS
;
384 case EXCEPTION_SINGLE_STEP
:
386 case EXCEPTION_BREAKPOINT
:
387 gdbctx
->last_sig
= SIGTRAP
;
390 case EXCEPTION_FLT_DENORMAL_OPERAND
:
391 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
392 case EXCEPTION_FLT_INEXACT_RESULT
:
393 case EXCEPTION_FLT_INVALID_OPERATION
:
394 case EXCEPTION_FLT_OVERFLOW
:
395 case EXCEPTION_FLT_STACK_CHECK
:
396 case EXCEPTION_FLT_UNDERFLOW
:
397 gdbctx
->last_sig
= SIGFPE
;
400 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
401 case EXCEPTION_INT_OVERFLOW
:
402 gdbctx
->last_sig
= SIGFPE
;
405 case EXCEPTION_ILLEGAL_INSTRUCTION
:
406 gdbctx
->last_sig
= SIGILL
;
410 gdbctx
->last_sig
= SIGINT
;
413 case EXCEPTION_CRITICAL_SECTION_WAIT
:
414 gdbctx
->last_sig
= SIGALRM
;
416 /* FIXME: we could also add here a O packet with additional information */
419 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
420 fprintf(stderr
, "unhandled exception code %08lx\n", rec
->ExceptionCode
);
421 gdbctx
->last_sig
= SIGABRT
;
428 static void handle_debug_event(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
)
432 DEBUG_CurrThread
= DEBUG_GetThread(gdbctx
->process
, de
->dwThreadId
);
434 switch (de
->dwDebugEventCode
)
436 case CREATE_PROCESS_DEBUG_EVENT
:
437 DEBUG_ProcessGetStringIndirect(buffer
, sizeof(buffer
),
438 de
->u
.CreateProcessInfo
.hProcess
,
439 de
->u
.CreateProcessInfo
.lpImageName
);
441 /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
442 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
443 fprintf(stderr
, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
444 de
->dwProcessId
, de
->dwThreadId
,
445 buffer
, de
->u
.CreateProcessInfo
.lpImageName
,
446 (unsigned long)(LPVOID
)de
->u
.CreateProcessInfo
.lpStartAddress
,
447 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
448 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
450 gdbctx
->process
= DEBUG_AddProcess(de
->dwProcessId
,
451 de
->u
.CreateProcessInfo
.hProcess
,
453 /* de->u.CreateProcessInfo.lpStartAddress; */
455 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
456 fprintf(stderr
, "%08lx:%08lx: create thread I @%08lx\n",
457 de
->dwProcessId
, de
->dwThreadId
,
458 (unsigned long)(LPVOID
)de
->u
.CreateProcessInfo
.lpStartAddress
);
460 assert(DEBUG_CurrThread
== NULL
); /* shouldn't be there */
461 DEBUG_AddThread(gdbctx
->process
, de
->dwThreadId
,
462 de
->u
.CreateProcessInfo
.hThread
,
463 de
->u
.CreateProcessInfo
.lpStartAddress
,
464 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
466 DEBUG_LoadModule32(DEBUG_CurrProcess
->imageName
, de
->u
.CreateProcessInfo
.hFile
,
467 (DWORD
)de
->u
.CreateProcessInfo
.lpBaseOfImage
);
469 if (buffer
[0]) /* we got a process name */
472 if (!GetBinaryTypeA( buffer
, &type
))
474 /* not a Windows binary, assume it's a Unix executable then */
475 char unixname
[MAX_PATH
];
476 /* HACK!! should fix DEBUG_ReadExecutableDbgInfo to accept DOS filenames */
477 if (wine_get_unix_file_name( buffer
, unixname
, sizeof(unixname
) ))
479 DEBUG_ReadExecutableDbgInfo( unixname
);
484 /* if it is a Windows binary, or an invalid or missing file name,
485 * we use wine itself as the main executable */
486 DEBUG_ReadExecutableDbgInfo( "wine" );
490 case LOAD_DLL_DEBUG_EVENT
:
491 assert(DEBUG_CurrThread
);
492 DEBUG_ProcessGetStringIndirect(buffer
, sizeof(buffer
),
493 gdbctx
->process
->handle
,
494 de
->u
.LoadDll
.lpImageName
);
496 /* FIXME unicode: de->u.LoadDll.fUnicode */
497 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
498 fprintf(stderr
, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
499 de
->dwProcessId
, de
->dwThreadId
,
500 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
,
501 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
502 de
->u
.LoadDll
.nDebugInfoSize
);
505 DEBUG_LoadModule32(buffer
, de
->u
.LoadDll
.hFile
, (DWORD
)de
->u
.LoadDll
.lpBaseOfDll
);
506 DEBUG_CheckDelayedBP();
507 if (DBG_IVAR(BreakOnDllLoad
))
509 DEBUG_Printf(DBG_CHN_MESG
, "Stopping on DLL %s loading at %08lx\n",
510 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
);
516 case UNLOAD_DLL_DEBUG_EVENT
:
517 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
518 fprintf(stderr
, "%08lx:%08lx: unload DLL @%08lx\n",
519 de
->dwProcessId
, de
->dwThreadId
, (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
522 case EXCEPTION_DEBUG_EVENT
:
523 assert(DEBUG_CurrThread
);
524 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
525 fprintf(stderr
, "%08lx:%08lx: exception code=%08lx\n",
526 de
->dwProcessId
, de
->dwThreadId
,
527 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
529 gdbctx
->context
.ContextFlags
= CONTEXT_CONTROL
531 #ifdef CONTEXT_SEGMENTS
534 #ifdef CONTEXT_DEBUG_REGISTERS
535 | CONTEXT_DEBUG_REGISTERS
538 if (!GetThreadContext(DEBUG_CurrThread
->handle
, &gdbctx
->context
))
540 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
541 fprintf(stderr
, "Can't get thread's context\n");
544 gdbctx
->in_trap
= handle_exception(gdbctx
, &de
->u
.Exception
);
547 case CREATE_THREAD_DEBUG_EVENT
:
548 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
549 fprintf(stderr
, "%08lx:%08lx: create thread D @%08lx\n",
550 de
->dwProcessId
, de
->dwThreadId
, (unsigned long)(LPVOID
)de
->u
.CreateThread
.lpStartAddress
);
552 DEBUG_AddThread(gdbctx
->process
,
554 de
->u
.CreateThread
.hThread
,
555 de
->u
.CreateThread
.lpStartAddress
,
556 de
->u
.CreateThread
.lpThreadLocalBase
);
559 case EXIT_THREAD_DEBUG_EVENT
:
560 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
561 fprintf(stderr
, "%08lx:%08lx: exit thread (%ld)\n",
562 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
564 assert(DEBUG_CurrThread
);
565 DEBUG_DelThread(DEBUG_CurrThread
);
568 case EXIT_PROCESS_DEBUG_EVENT
:
569 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
570 fprintf(stderr
, "%08lx:%08lx: exit process (%ld)\n",
571 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
573 DEBUG_DelProcess(gdbctx
->process
);
574 gdbctx
->process
= NULL
;
575 /* now signal gdb that we're done */
576 gdbctx
->last_sig
= SIGTERM
;
577 gdbctx
->in_trap
= TRUE
;
580 case OUTPUT_DEBUG_STRING_EVENT
:
581 assert(DEBUG_CurrThread
);
582 DEBUG_ProcessGetString(buffer
, sizeof(buffer
),
583 gdbctx
->process
->handle
,
584 de
->u
.DebugString
.lpDebugStringData
);
585 /* FIXME unicode de->u.DebugString.fUnicode ? */
586 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
587 fprintf(stderr
, "%08lx:%08lx: output debug string (%s)\n",
588 de
->dwProcessId
, de
->dwThreadId
, buffer
);
592 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
593 fprintf(stderr
, "%08lx:%08lx: rip error=%ld type=%ld\n",
594 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
595 de
->u
.RipInfo
.dwType
);
599 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_EVENT
)
600 fprintf(stderr
, "%08lx:%08lx: unknown event (%ld)\n",
601 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
605 static void resume_debuggee(struct gdb_context
* gdbctx
, unsigned long cont
)
607 if (DEBUG_CurrThread
)
609 if (!SetThreadContext(DEBUG_CurrThread
->handle
, &gdbctx
->context
))
610 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
611 fprintf(stderr
, "cannot set ctx on %lu\n", DEBUG_CurrThread
->tid
);
612 if (!ContinueDebugEvent(gdbctx
->process
->pid
, DEBUG_CurrThread
->tid
, cont
))
613 if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
614 fprintf(stderr
, "cannot continue on %lu (%lu)\n",
615 DEBUG_CurrThread
->tid
, cont
);
617 else if (gdbctx
->trace
& GDBPXY_TRC_WIN32_ERROR
)
618 fprintf(stderr
, "cannot find last thread (%lu)\n", DEBUG_CurrThread
->tid
);
621 static void wait_for_debuggee(struct gdb_context
* gdbctx
)
625 gdbctx
->in_trap
= FALSE
;
626 while (WaitForDebugEvent(&de
, INFINITE
))
628 handle_debug_event(gdbctx
, &de
);
629 assert(!gdbctx
->process
||
630 gdbctx
->process
->pid
== 0 ||
631 de
.dwProcessId
== gdbctx
->process
->pid
);
632 assert(!DEBUG_CurrThread
|| de
.dwThreadId
== DEBUG_CurrThread
->tid
);
633 if (gdbctx
->in_trap
) break;
634 ContinueDebugEvent(de
.dwProcessId
, de
.dwThreadId
, DBG_CONTINUE
);
638 static void detach_debuggee(struct gdb_context
* gdbctx
, BOOL kill
)
640 cpu_leave_stepping(gdbctx
);
641 resume_debuggee(gdbctx
, DBG_CONTINUE
);
643 DebugActiveProcessStop(gdbctx
->process
->pid
);
644 DEBUG_DelProcess(gdbctx
->process
);
645 gdbctx
->process
= NULL
;
648 static void get_process_info(struct gdb_context
* gdbctx
, char* buffer
, size_t len
)
650 unsigned long status
;
652 if (!GetExitCodeProcess(gdbctx
->process
->handle
, &status
))
654 strcpy(buffer
, "Unknown process");
657 if (status
== STILL_ACTIVE
)
659 strcpy(buffer
, "Running");
662 sprintf(buffer
, "Terminated (%lu)", status
);
664 switch (GetPriorityClass(gdbctx
->process
->handle
))
667 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
668 case ABOVE_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", above normal priority"); break;
670 #ifdef BELOW_NORMAL_PRIORITY_CLASS
671 case BELOW_NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", below normal priotity"); break;
673 case HIGH_PRIORITY_CLASS
: strcat(buffer
, ", high priority"); break;
674 case IDLE_PRIORITY_CLASS
: strcat(buffer
, ", idle priority"); break;
675 case NORMAL_PRIORITY_CLASS
: strcat(buffer
, ", normal priority"); break;
676 case REALTIME_PRIORITY_CLASS
: strcat(buffer
, ", realtime priority"); break;
678 strcat(buffer
, "\n");
681 static void get_thread_info(struct gdb_context
* gdbctx
, unsigned tid
,
682 char* buffer
, size_t len
)
685 unsigned long status
;
688 /* FIXME: use the size of buffer */
689 thd
= DEBUG_GetThread(gdbctx
->process
, tid
);
692 strcpy(buffer
, "No information");
695 if (GetExitCodeThread(thd
->handle
, &status
))
697 if (status
== STILL_ACTIVE
)
699 /* FIXME: this is a bit brutal... some nicer way shall be found */
700 switch (status
= SuspendThread(thd
->handle
))
703 case 0: strcpy(buffer
, "Running"); break;
704 default: sprintf(buffer
, "Suspended (%lu)", status
- 1);
706 ResumeThread(thd
->handle
);
709 sprintf(buffer
, "Terminated (exit code = %lu)", status
);
713 strcpy(buffer
, "Unknown threadID");
715 switch (prio
= GetThreadPriority(thd
->handle
))
717 case THREAD_PRIORITY_ERROR_RETURN
: break;
718 case THREAD_PRIORITY_ABOVE_NORMAL
: strcat(buffer
, ", priority +1 above normal"); break;
719 case THREAD_PRIORITY_BELOW_NORMAL
: strcat(buffer
, ", priority -1 below normal"); break;
720 case THREAD_PRIORITY_HIGHEST
: strcat(buffer
, ", priority +2 above normal"); break;
721 case THREAD_PRIORITY_LOWEST
: strcat(buffer
, ", priority -2 below normal"); break;
722 case THREAD_PRIORITY_IDLE
: strcat(buffer
, ", priority idle"); break;
723 case THREAD_PRIORITY_NORMAL
: strcat(buffer
, ", priority normal"); break;
724 case THREAD_PRIORITY_TIME_CRITICAL
: strcat(buffer
, ", priority time-critical"); break;
725 default: sprintf(buffer
+ strlen(buffer
), ", priority = %d", prio
);
727 assert(strlen(buffer
) < len
);
730 /* =============================================== *
731 * P A C K E T U T I L S *
732 * =============================================== *
735 enum packet_return
{packet_error
= 0x00, packet_ok
= 0x01, packet_done
= 0x02,
736 packet_last_f
= 0x80};
738 static void packet_reply_grow(struct gdb_context
* gdbctx
, size_t size
)
740 if (gdbctx
->out_buf_alloc
< gdbctx
->out_len
+ size
)
742 gdbctx
->out_buf_alloc
= ((gdbctx
->out_len
+ size
) / 32 + 1) * 32;
743 gdbctx
->out_buf
= realloc(gdbctx
->out_buf
, gdbctx
->out_buf_alloc
);
747 static void packet_reply_hex_to(struct gdb_context
* gdbctx
, const void* src
, int len
)
749 packet_reply_grow(gdbctx
, len
* 2);
750 hex_to(&gdbctx
->out_buf
[gdbctx
->out_len
], src
, len
);
751 gdbctx
->out_len
+= len
* 2;
754 static void packet_reply_val(struct gdb_context
* gdbctx
, unsigned long val
, int len
)
758 shift
= (len
- 1) * 8;
759 packet_reply_grow(gdbctx
, len
* 2);
760 for (i
= 0; i
< len
; i
++, shift
-= 8)
762 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> (shift
+ 4)) & 0x0F);
763 gdbctx
->out_buf
[gdbctx
->out_len
++] = hex_to0((val
>> shift
) & 0x0F);
767 static inline void packet_reply_add(struct gdb_context
* gdbctx
, const char* str
, int len
)
769 packet_reply_grow(gdbctx
, len
);
770 memcpy(&gdbctx
->out_buf
[gdbctx
->out_len
], str
, len
);
771 gdbctx
->out_len
+= len
;
774 static inline void packet_reply_cat(struct gdb_context
* gdbctx
, const char* str
)
776 packet_reply_add(gdbctx
, str
, strlen(str
));
779 static inline void packet_reply_catc(struct gdb_context
* gdbctx
, char ch
)
781 packet_reply_add(gdbctx
, &ch
, 1);
784 static void packet_reply_open(struct gdb_context
* gdbctx
)
786 assert(gdbctx
->out_curr_packet
== -1);
787 packet_reply_catc(gdbctx
, '$');
788 gdbctx
->out_curr_packet
= gdbctx
->out_len
;
791 static void packet_reply_close(struct gdb_context
* gdbctx
)
796 plen
= gdbctx
->out_len
- gdbctx
->out_curr_packet
;
797 packet_reply_catc(gdbctx
, '#');
798 cksum
= checksum(&gdbctx
->out_buf
[gdbctx
->out_curr_packet
], plen
);
799 packet_reply_hex_to(gdbctx
, &cksum
, 1);
800 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
801 fprintf(stderr
, "Reply : %*.*s\n",
802 plen
, plen
, &gdbctx
->out_buf
[gdbctx
->out_curr_packet
]);
803 gdbctx
->out_curr_packet
= -1;
806 static enum packet_return
packet_reply(struct gdb_context
* gdbctx
, const char* packet
, int len
)
808 packet_reply_open(gdbctx
);
810 if (len
== -1) len
= strlen(packet
);
811 assert(memchr(packet
, '$', len
) == NULL
&& memchr(packet
, '#', len
) == NULL
);
813 packet_reply_add(gdbctx
, packet
, len
);
815 packet_reply_close(gdbctx
);
820 static enum packet_return
packet_reply_error(struct gdb_context
* gdbctx
, int error
)
822 packet_reply_open(gdbctx
);
824 packet_reply_add(gdbctx
, "E", 1);
825 packet_reply_val(gdbctx
, error
, 1);
827 packet_reply_close(gdbctx
);
832 /* =============================================== *
833 * P A C K E T H A N D L E R S *
834 * =============================================== *
837 static enum packet_return
packet_reply_status(struct gdb_context
* gdbctx
)
839 enum packet_return ret
= packet_done
;
841 packet_reply_open(gdbctx
);
843 if (gdbctx
->process
!= NULL
)
848 packet_reply_catc(gdbctx
, 'T');
849 sig
= gdbctx
->last_sig
;
850 packet_reply_val(gdbctx
, sig
, 1);
851 packet_reply_add(gdbctx
, "thread:", 7);
852 packet_reply_val(gdbctx
, DEBUG_CurrThread
->tid
, 4);
853 packet_reply_catc(gdbctx
, ';');
855 for (i
= 0; i
< cpu_num_regs
; i
++)
857 /* FIXME: this call will also grow the buffer...
858 * unneeded, but not harmful
860 packet_reply_val(gdbctx
, i
, 1);
861 packet_reply_catc(gdbctx
, ':');
862 packet_reply_hex_to(gdbctx
, cpu_register(gdbctx
, i
), 4);
863 packet_reply_catc(gdbctx
, ';');
868 /* Try to put an exit code
869 * Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
870 * just indicate the end of process and exit */
871 packet_reply_add(gdbctx
, "W00", 3);
872 /*if (!gdbctx->extended)*/ ret
|= packet_last_f
;
875 packet_reply_close(gdbctx
);
881 static enum packet_return
packet_extended(struct gdb_context
* gdbctx
)
883 gdbctx
->extended
= 1;
888 static enum packet_return
packet_last_signal(struct gdb_context
* gdbctx
)
890 assert(gdbctx
->in_packet_len
== 0);
891 return packet_reply_status(gdbctx
);
894 static enum packet_return
packet_continue(struct gdb_context
* gdbctx
)
896 /* FIXME: add support for address in packet */
897 assert(gdbctx
->in_packet_len
== 0);
898 if (DEBUG_CurrThread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
899 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
900 fprintf(stderr
, "NIY: cont on %u, while last thd is %lu\n",
901 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
902 resume_debuggee(gdbctx
, DBG_CONTINUE
);
903 wait_for_debuggee(gdbctx
);
904 return packet_reply_status(gdbctx
);
907 static enum packet_return
packet_continue_signal(struct gdb_context
* gdbctx
)
911 /* FIXME: add support for address in packet */
912 assert(gdbctx
->in_packet_len
== 2);
913 if (DEBUG_CurrThread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
914 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
915 fprintf(stderr
, "NIY: cont/sig on %u, while last thd is %lu\n",
916 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
917 hex_from(&sig
, gdbctx
->in_packet
, 1);
918 /* cannot change signals on the fly */
919 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
920 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
921 if (sig
!= gdbctx
->last_sig
)
923 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
924 wait_for_debuggee(gdbctx
);
925 return packet_reply_status(gdbctx
);
928 static enum packet_return
packet_detach(struct gdb_context
* gdbctx
)
930 detach_debuggee(gdbctx
, FALSE
);
931 return packet_ok
| packet_last_f
;
934 static enum packet_return
packet_read_registers(struct gdb_context
* gdbctx
)
938 assert(gdbctx
->in_trap
);
939 if (DEBUG_CurrThread
->tid
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
940 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
941 fprintf(stderr
, "NIY: read regs on %u, while last thd is %lu\n",
942 gdbctx
->other_thread
, DEBUG_CurrThread
->tid
);
944 packet_reply_open(gdbctx
);
946 for (i
= 0; i
< cpu_num_regs
; i
++)
948 packet_reply_hex_to(gdbctx
, cpu_register(gdbctx
, i
), 4);
951 packet_reply_close(gdbctx
);
955 static enum packet_return
packet_write_registers(struct gdb_context
* gdbctx
)
959 assert(gdbctx
->in_trap
);
960 if (DEBUG_CurrThread
->tid
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
961 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
962 fprintf(stderr
, "NIY: write regs on %u, while last thd is %lu\n",
963 gdbctx
->other_thread
, DEBUG_CurrThread
->tid
);
964 if (gdbctx
->in_packet_len
< cpu_num_regs
* 2) return packet_error
;
965 for (i
= 0; i
< cpu_num_regs
; i
++)
966 hex_from(cpu_register(gdbctx
, i
), &gdbctx
->in_packet
[8 * i
], 4);
970 static enum packet_return
packet_kill(struct gdb_context
* gdbctx
)
972 detach_debuggee(gdbctx
, TRUE
);
974 if (!gdbctx
->extended
)
975 /* dunno whether GDB cares or not */
979 /* assume we can't really answer something here */
980 /* return packet_done; */
983 static enum packet_return
packet_thread(struct gdb_context
* gdbctx
)
988 switch (gdbctx
->in_packet
[0])
992 if (gdbctx
->in_packet
[1] == '-')
993 thread
= -strtol(gdbctx
->in_packet
+ 2, &end
, 16);
995 thread
= strtol(gdbctx
->in_packet
+ 1, &end
, 16);
996 if (end
== NULL
|| end
> gdbctx
->in_packet
+ gdbctx
->in_packet_len
)
998 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
999 fprintf(stderr
, "Cannot get threadid %*.*s\n",
1000 gdbctx
->in_packet_len
- 1, gdbctx
->in_packet_len
- 1,
1001 gdbctx
->in_packet
+ 1);
1002 return packet_error
;
1004 if (gdbctx
->in_packet
[0] == 'c')
1005 gdbctx
->exec_thread
= thread
;
1007 gdbctx
->other_thread
= thread
;
1010 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1011 fprintf(stderr
, "Unknown thread sub-command %c\n", gdbctx
->in_packet
[0]);
1012 return packet_error
;
1016 static enum packet_return
packet_read_memory(struct gdb_context
* gdbctx
)
1019 size_t len
, blk_len
, nread
;
1021 unsigned long r
= 0;
1023 assert(gdbctx
->in_trap
);
1024 /* FIXME:check in_packet_len for reading %p,%x */
1025 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2) return packet_error
;
1026 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1027 fprintf(stderr
, "read mem at %p for %u bytes\n", addr
, len
);
1028 for (nread
= 0; nread
< len
> 0; nread
+= r
, addr
+= r
)
1030 blk_len
= min(sizeof(buffer
), len
- nread
);
1031 if (!ReadProcessMemory(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &r
) ||
1034 /* fail at first address, return error */
1035 if (nread
== 0) return packet_reply_error(gdbctx
, EFAULT
);
1036 /* something has already been read, return partial information */
1039 if (nread
== 0) packet_reply_open(gdbctx
);
1040 packet_reply_hex_to(gdbctx
, buffer
, r
);
1042 packet_reply_close(gdbctx
);
1046 static enum packet_return
packet_write_memory(struct gdb_context
* gdbctx
)
1049 size_t len
, blk_len
;
1054 assert(gdbctx
->in_trap
);
1055 ptr
= memchr(gdbctx
->in_packet
, ':', gdbctx
->in_packet_len
);
1058 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1059 fprintf(stderr
, "cannot find ':' in %*.*s\n",
1060 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1061 return packet_error
;
1065 if (sscanf(gdbctx
->in_packet
, "%p,%x", &addr
, &len
) != 2)
1067 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1068 fprintf(stderr
, "cannot scan addr,len in %s\n", gdbctx
->in_packet
);
1069 return packet_error
;
1071 if (ptr
- gdbctx
->in_packet
+ len
* 2 != gdbctx
->in_packet_len
)
1073 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1074 fprintf(stderr
, "wrong sizes %u <> %u\n",
1075 ptr
- gdbctx
->in_packet
+ len
* 2, gdbctx
->in_packet_len
);
1076 return packet_error
;
1078 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1079 fprintf(stderr
, "write %u bytes at %p\n", len
, addr
);
1082 blk_len
= min(sizeof(buffer
), len
);
1083 hex_from(buffer
, ptr
, blk_len
);
1087 ret
= WriteProcessMemory(gdbctx
->process
->handle
, addr
, buffer
, blk_len
, &w
);
1088 if (!ret
|| w
!= blk_len
)
1095 return packet_ok
; /* FIXME: error while writing ? */
1098 static enum packet_return
packet_write_register(struct gdb_context
* gdbctx
)
1104 assert(gdbctx
->in_trap
);
1105 if (DEBUG_CurrThread
->tid
!= gdbctx
->other_thread
&& gdbctx
->other_thread
)
1106 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1107 fprintf(stderr
, "NIY: read reg on %u, while last thd is %lu\n",
1108 gdbctx
->other_thread
, DEBUG_CurrThread
->tid
);
1110 ptr
= memchr(gdbctx
->in_packet
, '=', gdbctx
->in_packet_len
);
1112 reg
= strtoul(gdbctx
->in_packet
, &end
, 16);
1113 if (end
== NULL
|| reg
> cpu_num_regs
)
1115 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1116 fprintf(stderr
, "invalid register index %s\n", gdbctx
->in_packet
);
1117 /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
1118 * it wouldn't matter too much, and it fakes our support for all regs
1120 return (end
== NULL
) ? packet_error
: packet_ok
;
1122 if (ptr
+ 8 - gdbctx
->in_packet
!= gdbctx
->in_packet_len
)
1124 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1125 fprintf(stderr
, "wrong sizes %u <> %u\n",
1126 ptr
+ 8 - gdbctx
->in_packet
, gdbctx
->in_packet_len
);
1127 return packet_error
;
1129 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1130 fprintf(stderr
, "Writing reg %u <= %*.*s\n",
1131 reg
, gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
),
1132 gdbctx
->in_packet_len
- (ptr
- gdbctx
->in_packet
), ptr
);
1133 hex_from(cpu_register(gdbctx
, reg
), ptr
, 4);
1137 static void packet_query_monitor_wnd_helper(struct gdb_context
* gdbctx
, HWND hWnd
, int indent
)
1145 if (!GetClassName(hWnd
, clsName
, sizeof(clsName
)))
1146 strcpy(clsName
, "-- Unknown --");
1147 if (!GetWindowText(hWnd
, wndName
, sizeof(wndName
)))
1148 strcpy(wndName
, "-- Empty --");
1150 packet_reply_open(gdbctx
);
1151 packet_reply_catc(gdbctx
, 'O');
1152 sprintf(buffer
, "%*s%04x%*s%-17.17s %08lx %08lx %.14s\n",
1153 indent
, "", (UINT
)hWnd
, 13 - indent
, "",
1154 clsName
, GetWindowLong(hWnd
, GWL_STYLE
),
1155 GetWindowLong(hWnd
, GWL_WNDPROC
), wndName
);
1156 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1157 packet_reply_close(gdbctx
);
1159 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
1160 packet_query_monitor_wnd_helper(gdbctx
, child
, indent
+ 1);
1161 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
1164 static void packet_query_monitor_wnd(struct gdb_context
* gdbctx
, int len
, const char* str
)
1168 /* we do the output in several 'O' packets, with the last one being just OK for
1169 * marking the end of the output */
1170 packet_reply_open(gdbctx
);
1171 packet_reply_catc(gdbctx
, 'O');
1172 sprintf(buffer
, "%-16.16s %-17.17s %-8.8s %s\n",
1173 "hwnd", "Class Name", " Style", " WndProc Text");
1174 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1175 packet_reply_close(gdbctx
);
1177 /* FIXME: could also add a pmt to this command in str... */
1178 packet_query_monitor_wnd_helper(gdbctx
, GetDesktopWindow(), 0);
1179 packet_reply(gdbctx
, "OK", 2);
1182 static void packet_query_monitor_process(struct gdb_context
* gdbctx
, int len
, const char* str
)
1184 HANDLE snap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
1187 PROCESSENTRY32 entry
;
1190 if (snap
== INVALID_HANDLE_VALUE
)
1193 entry
.dwSize
= sizeof(entry
);
1194 ok
= Process32First( snap
, &entry
);
1196 /* we do the output in several 'O' packets, with the last one being just OK for
1197 * marking the end of the output */
1199 packet_reply_open(gdbctx
);
1200 packet_reply_catc(gdbctx
, 'O');
1201 sprintf(buffer
, " %-8.8s %-8.8s %-8.8s %s\n",
1202 "pid", "threads", "parent", "executable" );
1203 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1204 packet_reply_close(gdbctx
);
1209 if (entry
.th32ProcessID
== gdbctx
->process
->pid
) deco
= '>';
1210 packet_reply_open(gdbctx
);
1211 packet_reply_catc(gdbctx
, 'O');
1212 sprintf(buffer
, "%c%08lx %-8ld %08lx '%s'\n",
1213 deco
, entry
.th32ProcessID
, entry
.cntThreads
,
1214 entry
.th32ParentProcessID
, entry
.szExeFile
);
1215 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1216 packet_reply_close(gdbctx
);
1217 ok
= Process32Next(snap
, &entry
);
1220 packet_reply(gdbctx
, "OK", 2);
1223 static void packet_query_monitor_mem(struct gdb_context
* gdbctx
, int len
, const char* str
)
1225 MEMORY_BASIC_INFORMATION mbi
;
1232 /* we do the output in several 'O' packets, with the last one being just OK for
1233 * marking the end of the output */
1234 packet_reply_open(gdbctx
);
1235 packet_reply_catc(gdbctx
, 'O');
1236 sprintf(buffer
, "Address Size State Type RWX\n");
1237 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1238 packet_reply_close(gdbctx
);
1240 while (VirtualQueryEx(gdbctx
->process
->handle
, addr
, &mbi
, sizeof(mbi
)) >= sizeof(mbi
))
1244 case MEM_COMMIT
: state
= "commit "; break;
1245 case MEM_FREE
: state
= "free "; break;
1246 case MEM_RESERVE
: state
= "reserve"; break;
1247 default: state
= "??? "; break;
1249 if (mbi
.State
!= MEM_FREE
)
1253 case MEM_IMAGE
: type
= "image "; break;
1254 case MEM_MAPPED
: type
= "mapped "; break;
1255 case MEM_PRIVATE
: type
= "private"; break;
1256 case 0: type
= " "; break;
1257 default: type
= "??? "; break;
1259 memset(prot
, ' ' , sizeof(prot
)-1);
1260 prot
[sizeof(prot
)-1] = '\0';
1261 if (mbi
.AllocationProtect
& (PAGE_READONLY
|PAGE_READWRITE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1263 if (mbi
.AllocationProtect
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
1265 if (mbi
.AllocationProtect
& (PAGE_WRITECOPY
|PAGE_EXECUTE_WRITECOPY
))
1267 if (mbi
.AllocationProtect
& (PAGE_EXECUTE
|PAGE_EXECUTE_READ
|PAGE_EXECUTE_READWRITE
))
1275 packet_reply_open(gdbctx
);
1276 sprintf(buffer
, "%08lx %08lx %s %s %s\n",
1277 (DWORD
)addr
, mbi
.RegionSize
, state
, type
, prot
);
1278 packet_reply_catc(gdbctx
, 'O');
1279 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1280 packet_reply_close(gdbctx
);
1282 if (addr
+ mbi
.RegionSize
< addr
) /* wrap around ? */
1284 addr
+= mbi
.RegionSize
;
1286 packet_reply(gdbctx
, "OK", 2);
1289 static void packet_query_monitor_trace(struct gdb_context
* gdbctx
,
1290 int len
, const char* str
)
1296 sprintf(buffer
, "trace=%x\n", gdbctx
->trace
);
1298 else if (len
>= 2 && str
[0] == '=')
1300 unsigned val
= atoi(&str
[1]);
1301 sprintf(buffer
, "trace: %x => %x\n", gdbctx
->trace
, val
);
1302 gdbctx
->trace
= val
;
1306 /* FIXME: ugly but can use error packet here */
1307 packet_reply_cat(gdbctx
, "E00");
1310 packet_reply_open(gdbctx
);
1311 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1312 packet_reply_close(gdbctx
);
1316 static void packet_query_monitor_linear(struct gdb_context
* gdbctx
,
1317 int len
, const char* str
)
1324 while (len
> 0 && (*str
== ' ' || *str
== '\t'))
1328 /* FIXME: do a better scanning (allow both decimal and hex numbers) */
1329 if (!len
|| sscanf(str
, "%x:%x", &seg
, &ofs
) != 2)
1331 packet_reply_error(gdbctx
, 0);
1336 if (gdbctx
->context
.EFlags
& 0x00020000) linear
= (LOWORD(seg
) << 4) + ofs
;
1337 /* linux system selector ? */
1338 else if (!(seg
& 4) || ((seg
>> 3) < 17)) linear
= ofs
;
1339 /* standard selector */
1340 else if (GetThreadSelectorEntry(gdbctx
->process
->threads
->handle
, seg
, &le
))
1341 linear
= (le
.HighWord
.Bits
.BaseHi
<< 24) + (le
.HighWord
.Bits
.BaseMid
<< 16) +
1345 sprintf(buffer
, "0x%x", linear
);
1346 packet_reply_open(gdbctx
);
1347 packet_reply_hex_to(gdbctx
, buffer
, strlen(buffer
));
1348 packet_reply_close(gdbctx
);
1357 void (*handler
)(struct gdb_context
*, int, const char*);
1360 {0, "wnd", 3, packet_query_monitor_wnd
},
1361 {0, "window", 6, packet_query_monitor_wnd
},
1362 {0, "proc", 4, packet_query_monitor_process
},
1363 {0, "process", 7, packet_query_monitor_process
},
1364 {0, "mem", 3, packet_query_monitor_mem
},
1365 {1, "trace", 5, packet_query_monitor_trace
},
1367 {1, "linear", 6, packet_query_monitor_linear
},
1372 static enum packet_return
packet_query_remote_command(struct gdb_context
* gdbctx
,
1373 const char* hxcmd
, size_t len
)
1376 struct query_detail
* qd
;
1378 assert((len
& 1) == 0 && len
< 2 * sizeof(buffer
));
1380 hex_from(buffer
, hxcmd
, len
);
1382 for (qd
= &query_details
[0]; qd
->name
!= NULL
; qd
++)
1384 if (len
< qd
->len
|| strncmp(buffer
, qd
->name
, qd
->len
) != 0) continue;
1385 if (!qd
->with_arg
&& len
!= qd
->len
) continue;
1387 (qd
->handler
)(gdbctx
, len
- qd
->len
, buffer
+ qd
->len
);
1390 return packet_reply_error(gdbctx
, EINVAL
);
1393 static enum packet_return
packet_query(struct gdb_context
* gdbctx
)
1395 switch (gdbctx
->in_packet
[0])
1398 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1402 packet_reply_open(gdbctx
);
1403 packet_reply_add(gdbctx
, "m", 1);
1404 for (thd
= gdbctx
->process
->threads
; thd
; thd
= thd
->next
)
1406 packet_reply_val(gdbctx
, thd
->tid
, 4);
1407 if (thd
->next
!= NULL
)
1408 packet_reply_add(gdbctx
, ",", 1);
1410 packet_reply_close(gdbctx
);
1413 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1417 packet_reply_open(gdbctx
);
1418 packet_reply_catc(gdbctx
, 'O');
1419 get_process_info(gdbctx
, result
, sizeof(result
));
1420 packet_reply_hex_to(gdbctx
, result
, strlen(result
));
1421 packet_reply_close(gdbctx
);
1426 if (strncmp(gdbctx
->in_packet
+ 1, "ThreadInfo", gdbctx
->in_packet_len
- 1) == 0)
1428 packet_reply(gdbctx
, "l", 1);
1431 else if (strncmp(gdbctx
->in_packet
+ 1, "ProcessInfo", gdbctx
->in_packet_len
- 1) == 0)
1433 packet_reply(gdbctx
, "l", 1);
1438 if (gdbctx
->in_packet_len
== 1)
1441 /* FIXME: doc says 16 bit val ??? */
1442 /* grab first created thread, aka last in list */
1443 assert(gdbctx
->process
&& gdbctx
->process
->threads
);
1444 for (thd
= gdbctx
->process
->threads
; thd
->next
; thd
= thd
->next
);
1445 packet_reply_open(gdbctx
);
1446 packet_reply_add(gdbctx
, "QC", 2);
1447 packet_reply_val(gdbctx
, thd
->tid
, 4);
1448 packet_reply_close(gdbctx
);
1453 if (strncmp(gdbctx
->in_packet
, "Offsets", gdbctx
->in_packet_len
) == 0)
1457 if (gdbctx
->wine_segs
[0] == 0 && gdbctx
->wine_segs
[1] == 0 &&
1458 gdbctx
->wine_segs
[2] == 0)
1459 return packet_error
;
1460 sprintf(buf
, "Text=%08lx;Data=%08lx;Bss=%08lx",
1461 gdbctx
->wine_segs
[0], gdbctx
->wine_segs
[1],
1462 gdbctx
->wine_segs
[2]);
1463 return packet_reply(gdbctx
, buf
, -1);
1467 if (gdbctx
->in_packet_len
> 5 && strncmp(gdbctx
->in_packet
, "Rcmd,", 5) == 0)
1469 return packet_query_remote_command(gdbctx
, gdbctx
->in_packet
+ 5,
1470 gdbctx
->in_packet_len
- 5);
1474 if (strncmp(gdbctx
->in_packet
, "Symbol::", gdbctx
->in_packet_len
) == 0)
1478 if (gdbctx
->in_packet_len
> 15 &&
1479 strncmp(gdbctx
->in_packet
, "ThreadExtraInfo", 15) == 0 &&
1480 gdbctx
->in_packet
[15] == ',')
1486 tid
= strtol(gdbctx
->in_packet
+ 16, &end
, 16);
1487 if (end
== NULL
) break;
1488 get_thread_info(gdbctx
, tid
, result
, sizeof(result
));
1489 packet_reply_open(gdbctx
);
1490 packet_reply_hex_to(gdbctx
, result
, strlen(result
));
1491 packet_reply_close(gdbctx
);
1496 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1497 fprintf(stderr
, "Unknown or malformed query %*.*s\n",
1498 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
, gdbctx
->in_packet
);
1499 return packet_error
;
1502 static enum packet_return
packet_step(struct gdb_context
* gdbctx
)
1504 /* FIXME: add support for address in packet */
1505 assert(gdbctx
->in_packet_len
== 0);
1506 if (DEBUG_CurrThread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1507 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1508 fprintf(stderr
, "NIY: step on %u, while last thd is %lu\n",
1509 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1510 if (!cpu_enter_stepping(gdbctx
)) return packet_error
;
1511 resume_debuggee(gdbctx
, DBG_CONTINUE
);
1512 wait_for_debuggee(gdbctx
);
1513 if (!cpu_leave_stepping(gdbctx
)) return packet_error
;
1514 return packet_reply_status(gdbctx
);
1518 static enum packet_return
packet_step_signal(struct gdb_context
* gdbctx
)
1522 /* FIXME: add support for address in packet */
1523 assert(gdbctx
->in_packet_len
== 2);
1524 if (DEBUG_CurrThread
->tid
!= gdbctx
->exec_thread
&& gdbctx
->exec_thread
)
1525 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND_ERROR
)
1526 fprintf(stderr
, "NIY: step/sig on %u, while last thd is %u\n",
1527 gdbctx
->exec_thread
, DEBUG_CurrThread
->tid
);
1528 hex_from(&sig
, gdbctx
->in_packet
, 1);
1529 /* cannot change signals on the fly */
1530 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1531 fprintf(stderr
, "sigs: %u %u\n", sig
, gdbctx
->last_sig
);
1532 if (sig
!= gdbctx
->last_sig
)
1533 return packet_error
;
1534 resume_debuggee(gdbctx
, DBG_EXCEPTION_NOT_HANDLED
);
1535 wait_for_debuggee(gdbctx
);
1536 return packet_reply_status(gdbctx
);
1540 static enum packet_return
packet_thread_alive(struct gdb_context
* gdbctx
)
1545 tid
= strtol(gdbctx
->in_packet
, &end
, 16);
1546 if (tid
== -1 || tid
== 0)
1547 return packet_reply_error(gdbctx
, EINVAL
);
1548 if (DEBUG_GetThread(gdbctx
->process
, tid
) != NULL
)
1550 return packet_reply_error(gdbctx
, ESRCH
);
1553 static enum packet_return
packet_remove_breakpoint(struct gdb_context
* gdbctx
)
1557 struct gdb_ctx_Xpoint
* xpt
;
1559 /* FIXME: check packet_len */
1560 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1561 gdbctx
->in_packet
[1] != ',' ||
1562 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1563 return packet_error
;
1564 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1565 fprintf(stderr
, "remove bp %p[%u] typ=%c\n",
1566 addr
, len
, gdbctx
->in_packet
[0]);
1567 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1569 if (xpt
->addr
== addr
&& xpt
->type
== gdbctx
->in_packet
[0])
1571 switch (cpu_remove_Xpoint(gdbctx
, xpt
, len
))
1573 case 1: xpt
->type
= -1; return packet_ok
;
1574 case 0: return packet_error
;
1575 case -1: return packet_done
;
1580 return packet_error
;
1583 static enum packet_return
packet_set_breakpoint(struct gdb_context
* gdbctx
)
1587 struct gdb_ctx_Xpoint
* xpt
;
1589 /* FIXME: check packet_len */
1590 if (gdbctx
->in_packet
[0] < '0' || gdbctx
->in_packet
[0] > '4' ||
1591 gdbctx
->in_packet
[1] != ',' ||
1592 sscanf(gdbctx
->in_packet
+ 2, "%p,%x", &addr
, &len
) != 2)
1593 return packet_error
;
1594 if (gdbctx
->trace
& GDBPXY_TRC_COMMAND
)
1595 fprintf(stderr
, "set bp %p[%u] typ=%c\n",
1596 addr
, len
, gdbctx
->in_packet
[0]);
1597 /* because of packet command handling, this should be made idempotent */
1598 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1600 if (xpt
->addr
== addr
&& xpt
->type
== gdbctx
->in_packet
[0])
1601 return packet_ok
; /* nothing to do */
1603 /* really set the Xpoint */
1604 for (xpt
= &gdbctx
->Xpoints
[NUM_XPOINT
- 1]; xpt
>= gdbctx
->Xpoints
; xpt
--)
1606 if (xpt
->type
== -1)
1609 xpt
->type
= gdbctx
->in_packet
[0];
1610 switch (cpu_insert_Xpoint(gdbctx
, xpt
, len
))
1612 case 1: return packet_ok
;
1613 case 0: return packet_error
;
1614 case -1: return packet_done
;
1619 /* no more entries... eech */
1620 fprintf(stderr
, "Running out of spot for {break|watcgh}points\n");
1621 return packet_error
;
1624 /* =============================================== *
1625 * P A C K E T I N F R A S T R U C T U R E *
1626 * =============================================== *
1632 enum packet_return (*handler
)(struct gdb_context
* gdbctx
);
1635 static struct packet_entry packet_entries
[] =
1637 /* {'!', packet_extended}, */
1638 {'?', packet_last_signal
},
1639 {'c', packet_continue
},
1640 {'C', packet_continue_signal
},
1641 {'D', packet_detach
},
1642 {'g', packet_read_registers
},
1643 {'G', packet_write_registers
},
1645 {'H', packet_thread
},
1646 {'m', packet_read_memory
},
1647 {'M', packet_write_memory
},
1648 /* {'p', packet_read_register}, doesn't seem needed */
1649 {'P', packet_write_register
},
1650 {'q', packet_query
},
1652 /*{'S', packet_step_signal}, hard(er) to implement */
1653 {'T', packet_thread_alive
},
1654 {'z', packet_remove_breakpoint
},
1655 {'Z', packet_set_breakpoint
},
1658 static BOOL
extract_packets(struct gdb_context
* gdbctx
)
1662 unsigned char in_cksum
, loc_cksum
;
1664 enum packet_return ret
= packet_error
;
1666 while ((ret
& packet_last_f
) == 0)
1668 if (gdbctx
->in_len
&& (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
))
1669 fprintf(stderr
, "in-buf: %*.*s\n",
1670 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
1671 ptr
= memchr(gdbctx
->in_buf
, '$', gdbctx
->in_len
);
1672 if (ptr
== NULL
) return FALSE
;
1673 if (ptr
!= gdbctx
->in_buf
)
1675 int glen
= ptr
- gdbctx
->in_buf
; /* garbage len */
1676 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1677 fprintf(stderr
, "removing garbage: %*.*s\n",
1678 glen
, glen
, gdbctx
->in_buf
);
1679 gdbctx
->in_len
-= glen
;
1680 memmove(gdbctx
->in_buf
, ptr
, gdbctx
->in_len
);
1682 end
= memchr(gdbctx
->in_buf
+ 1, '#', gdbctx
->in_len
);
1683 if (end
== NULL
) return FALSE
;
1684 /* no checksum yet */
1685 if (end
+ 3 > gdbctx
->in_buf
+ gdbctx
->in_len
) return FALSE
;
1686 plen
= end
- gdbctx
->in_buf
- 1;
1687 hex_from(&in_cksum
, end
+ 1, 1);
1688 loc_cksum
= checksum(gdbctx
->in_buf
+ 1, plen
);
1689 if (loc_cksum
== in_cksum
)
1695 write(gdbctx
->sock
, "+", 1);
1698 /* FIXME: should use bsearch if packet_entries was sorted */
1699 for (i
= 0; i
< sizeof(packet_entries
)/sizeof(packet_entries
[0]); i
++)
1701 if (packet_entries
[i
].key
== gdbctx
->in_buf
[1]) break;
1703 if (i
== sizeof(packet_entries
)/sizeof(packet_entries
[0]))
1705 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
1706 fprintf(stderr
, "Unknown packet request %*.*s\n",
1707 plen
, plen
, &gdbctx
->in_buf
[1]);
1711 gdbctx
->in_packet
= gdbctx
->in_buf
+ 2;
1712 gdbctx
->in_packet_len
= plen
- 1;
1713 if (gdbctx
->trace
& GDBPXY_TRC_PACKET
)
1714 fprintf(stderr
, "Packet: %c%*.*s\n",
1716 gdbctx
->in_packet_len
, gdbctx
->in_packet_len
,
1718 ret
= (packet_entries
[i
].handler
)(gdbctx
);
1720 switch (ret
& ~packet_last_f
)
1722 case packet_error
: packet_reply(gdbctx
, "", 0); break;
1723 case packet_ok
: packet_reply(gdbctx
, "OK", 2); break;
1724 case packet_done
: break;
1726 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1727 fprintf(stderr
, "reply-full: %*.*s\n",
1728 gdbctx
->out_len
, gdbctx
->out_len
, gdbctx
->out_buf
);
1729 i
= write(gdbctx
->sock
, gdbctx
->out_buf
, gdbctx
->out_len
);
1730 assert(i
== gdbctx
->out_len
);
1731 /* if this fails, we'll have to use POLLOUT...
1733 gdbctx
->out_len
= 0;
1735 else if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1737 write(gdbctx
->sock
, "+", 1);
1738 fprintf(stderr
, "dropping packet, invalid checksum %d <> %d\n", in_cksum
, loc_cksum
);
1740 gdbctx
->in_len
-= plen
+ 4;
1741 memmove(gdbctx
->in_buf
, end
+ 3, gdbctx
->in_len
);
1746 static int fetch_data(struct gdb_context
* gdbctx
)
1748 int len
, in_len
= gdbctx
->in_len
;
1750 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1754 if (gdbctx
->in_len
+ STEP
> gdbctx
->in_buf_alloc
)
1755 gdbctx
->in_buf
= realloc(gdbctx
->in_buf
, gdbctx
->in_buf_alloc
+= STEP
);
1757 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1758 fprintf(stderr
, "%d %d %*.*s\n",
1759 gdbctx
->in_len
, gdbctx
->in_buf_alloc
,
1760 gdbctx
->in_len
, gdbctx
->in_len
, gdbctx
->in_buf
);
1761 len
= read(gdbctx
->sock
, gdbctx
->in_buf
+ gdbctx
->in_len
, gdbctx
->in_buf_alloc
- gdbctx
->in_len
);
1762 if (len
<= 0) break;
1763 gdbctx
->in_len
+= len
;
1764 assert(gdbctx
->in_len
<= gdbctx
->in_buf_alloc
);
1765 if (len
< gdbctx
->in_buf_alloc
- gdbctx
->in_len
) break;
1767 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1768 fprintf(stderr
, "=> %d\n", gdbctx
->in_len
- in_len
);
1769 return gdbctx
->in_len
- in_len
;
1772 static BOOL
gdb_startup(struct gdb_context
* gdbctx
, DEBUG_EVENT
* de
, unsigned flags
)
1775 struct sockaddr_in s_addr
;
1776 socklen_t s_len
= sizeof(s_addr
);
1777 struct pollfd pollfd
;
1778 char wine_path
[MAX_PATH
];
1781 /* step 1: create socket for gdb connection request */
1782 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1784 if (gdbctx
->trace
& GDBPXY_TRC_LOWLEVEL
)
1785 fprintf(stderr
, "Can't create socket");
1789 if (listen(sock
, 1) == -1 ||
1790 getsockname(sock
, (struct sockaddr
*)&s_addr
, &s_len
) == -1)
1793 /* step 2: find out wine executable location (as a Unix filename) */
1794 ptr
= getenv("WINELOADER");
1795 strcpy(wine_path
, ptr
? ptr
: "wine");
1797 fprintf(stderr
, "using wine_path: %s\n", wine_path
);
1798 read_elf_info(wine_path
, gdbctx
->wine_segs
);
1800 /* step 3: fire up gdb (if requested) */
1802 fprintf(stderr
, "target remote localhost:%d\n", ntohs(s_addr
.sin_port
));
1806 case -1: /* error in parent... */
1807 fprintf(stderr
, "Cannot create gdb\n");
1810 default: /* in parent... success */
1812 case 0: /* in child... and alive */
1819 if (!(gdb_path
= getenv("WINE_GDB"))) gdb_path
= "gdb";
1820 strcpy(buf
,"/tmp/winegdb.XXXXXX");
1822 if (fd
== -1) return FALSE
;
1823 if ((f
= fdopen(fd
, "w+")) == NULL
) return FALSE
;
1824 fprintf(f
, "file %s\n", wine_path
);
1825 fprintf(f
, "target remote localhost:%d\n", ntohs(s_addr
.sin_port
));
1826 fprintf(f
, "monitor trace=0\n");
1827 fprintf(f
, "set prompt Wine-gdb>\\ \n");
1828 /* tell gdb to delete this file when done handling it... */
1829 fprintf(f
, "shell rm -f \"%s\"\n", buf
);
1832 execlp("xterm", "xterm", "-e", gdb_path
, "-x", buf
, NULL
);
1834 execlp(gdb_path
, gdb_path
, "-x", buf
, NULL
);
1835 assert(0); /* never reached */
1841 /* step 4: do the process internal creation */
1842 handle_debug_event(gdbctx
, de
);
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_addr
, &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
= 0;
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_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
== DEBUG_CurrPid
);
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
DEBUG_GdbRemote(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");