From: Christopher Faylor Date: Fri, 21 Apr 2000 03:04:35 +0000 (+0000) Subject: * wince-stub.c (FREE): New macro. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=61c37cee5da9d08b107ec331b1080f1982f5afa1;p=binutils-gdb.git * wince-stub.c (FREE): New macro. (mempool): Just free any buffer prior to reuse. Don't bother with realloc. (flag_single_step): New function. (skip_message): Detect "helpful" Windows CE messages and skip sending them to the host. (wait_for_debug_event): Use skip_message to avoid sending debug messages to the host. (dispatch): Prelimary implementation of single step detection. * wince.c: Rework SH single stepping code to be more consistent with other wince targets. (handle_output_debug_string): Allow first chance exceptions to come through since they seem to be all that we get on some versions of Windows CE. (check_for_step): New function, conditionally compiled based on target. (regptr): Delete obsolete function. (handle_exception): Detect illegal instructions. (get_child_debug_event): Return success only if event code matches target. (child_create_inferior): Reflect change to get_child_debug_event arguments. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index efb8921a22e..0f1f773541d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2000-04-20 Christopher Faylor + + * wince-stub.c (FREE): New macro. + (mempool): Just free any buffer prior to reuse. Don't bother with + realloc. + (flag_single_step): New function. + (skip_message): Detect "helpful" Windows CE messages and skip sending + them to the host. + (wait_for_debug_event): Use skip_message to avoid sending debug + messages to the host. + (dispatch): Prelimary implementation of single step detection. + * wince.c: Rework SH single stepping code to be more consistent with + other wince targets. + (handle_output_debug_string): Allow first chance exceptions to come + through since they seem to be all that we get on some versions of + Windows CE. + (check_for_step): New function, conditionally compiled based on target. + (regptr): Delete obsolete function. + (handle_exception): Detect illegal instructions. + (get_child_debug_event): Return success only if event code matches + target. + (child_create_inferior): Reflect change to get_child_debug_event + arguments. + 2000-04-20 Christopher Faylor * win32-nat.c (thread_rec): Be more defensive about suspending already diff --git a/gdb/config/sh/tm-wince.h b/gdb/config/sh/tm-wince.h index 16816141d35..88e2a6fefc6 100644 --- a/gdb/config/sh/tm-wince.h +++ b/gdb/config/sh/tm-wince.h @@ -1,5 +1,5 @@ /* Target-specific definition for Window CE - Copyright 2000 Free Software Foundation, Inc. + Copyright (C) 2000 Free Software Foundation, Inc. This file is part of GDB. diff --git a/gdb/wince-stub.c b/gdb/wince-stub.c index d20223c1690..ce872d8137e 100644 --- a/gdb/wince-stub.c +++ b/gdb/wince-stub.c @@ -28,12 +28,13 @@ #include #include "wince-stub.h" -#define MALLOC(n) (void *) LocalAlloc (LMEM_MOVEABLE, (UINT)(n)) +#define MALLOC(n) (void *) LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, (UINT)(n)) #define REALLOC(s, n) (void *) LocalReAlloc ((HLOCAL)(s), (UINT)(n), LMEM_MOVEABLE) +#define FREE(s) LocalFree ((HLOCAL)(s)) static int skip_next_id = 0; /* Don't read next API code from socket */ -/* v-style interface for handling varying argyment list error messages. +/* v-style interface for handling varying argument list error messages. Displays the error message in a dialog box and exits when user clicks on OK. */ static void @@ -56,6 +57,27 @@ stub_error (LPCWSTR fmt, ...) vstub_error (fmt, args); } +/* Allocate a limited pool of memory, reallocating over unused + buffers. This assumes that there will never be more than four + "buffers" required which, so far, is a safe assumption. */ +static LPVOID +mempool (unsigned int len) +{ + static int outn = -1; + static LPWSTR outs[4] = {NULL, NULL, NULL, NULL}; + + if (++outn >= (sizeof (outs) / sizeof (outs[0]))) + outn = 0; + + /* Allocate space for the converted string, reusing any previously allocated + space, if applicable. */ + if (outs[outn]) + FREE (outs[outn]); + outs[outn] = (LPWSTR) MALLOC (len); + + return outs[outn]; +} + /* Standard "oh well" can't communicate error. Someday this might attempt synchronization. */ static void @@ -88,28 +110,6 @@ sockwrite (LPCWSTR huh, int s, const void *str, size_t n) } } -/* Allocate a limited pool of memory, reallocating over unused - buffers. This assumes that there will never be more than four - "buffers" required which, so far, is a safe assumption. */ -static LPVOID -mempool (gdb_wince_len len) -{ - static int n = -1; - static LPWSTR outs[4] = {NULL /*, NULL, etc. */}; - - if (++n >= (sizeof (outs) / sizeof (outs[0]))) - n = 0; - - /* Allocate space for the converted string, reusing any previously allocated - space, if applicable. */ - if (outs[n]) - outs[n] = (LPWSTR) REALLOC (outs[n], len); - else - outs[n] = (LPWSTR) MALLOC (len); - - return outs[n]; -} - /* Get a an ID (possibly) and a DWORD from the host gdb. Don't bother with the id if the main loop has already read it. */ @@ -175,7 +175,7 @@ getmemory (LPCWSTR huh, int s, gdb_wince_id what, gdb_wince_len *inlen) *inlen = getlen (huh, s, what); - p = mempool (*inlen); /* FIXME: check for error */ + p = mempool ((unsigned int) *inlen); /* FIXME: check for error */ if ((gdb_wince_len) sockread (huh, s, p, *inlen) != *inlen) stub_error (L"error getting string from host."); @@ -269,6 +269,49 @@ terminate_process (int s) &res, sizeof (res)); } +static int stepped = 0; +/* Handle single step instruction. FIXME: unneded? */ +static void +flag_single_step (int s) +{ + stepped = 1; + skip_next_id = 0; +} + +struct skipper +{ + wchar_t *s; + int nskip; +} skippy[] = +{ + {L"Undefined Instruction:", 1}, + {L"Data Abort:", 2}, + {NULL, 0} +}; + +static int +skip_message (DEBUG_EVENT *ev) +{ + char s[80]; + DWORD nread; + struct skipper *skp; + int nbytes = ev->u.DebugString.nDebugStringLength; + + if (nbytes > sizeof(s)) + nbytes = sizeof(s); + + memset (s, 0, sizeof (s)); + if (!ReadProcessMemory (curproc, ev->u.DebugString.lpDebugStringData, + s, nbytes, &nread)) + return 0; + + for (skp = skippy; skp->s != NULL; skp++) + if (wcsncmp ((wchar_t *) s, skp->s, wcslen (skp->s)) == 0) + return skp->nskip; + + return 0; +} + /* Emulate WaitForDebugEvent. Returns the debug event on success. */ static void wait_for_debug_event (int s) @@ -276,10 +319,32 @@ wait_for_debug_event (int s) DWORD ms = getdword (L"WaitForDebugEvent ms", s, GDB_WAITFORDEBUGEVENT); gdb_wince_result res; DEBUG_EVENT ev; + static int skip_next = 0; + + for (;;) + { + res = WaitForDebugEvent (&ev, ms); + + if (ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) + { + if (skip_next) + { + skip_next--; + goto ignore; + } + if (skip_next = skip_message (&ev)) + goto ignore; + } + + putresult (L"WaitForDebugEvent event", res, s, GDB_WAITFORDEBUGEVENT, + &ev, sizeof (ev)); + break; + + ignore: + ContinueDebugEvent (ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); + } - res = WaitForDebugEvent (&ev, ms); - putresult (L"WaitForDebugEvent event", res, s, GDB_WAITFORDEBUGEVENT, - &ev, sizeof (ev)); + return; } /* Emulate GetThreadContext. Returns CONTEXT structure on success. */ @@ -291,7 +356,7 @@ get_thread_context (int s) gdb_wince_result res; memset (&c, 0, sizeof (c)); - c.ContextFlags = getdword (L"GetThreadContext handle", s, GDB_GETTHREADCONTEXT); + c.ContextFlags = getdword (L"GetThreadContext flags", s, GDB_GETTHREADCONTEXT); res = (gdb_wince_result) GetThreadContext (h, &c); putresult (L"GetThreadContext data", res, s, GDB_GETTHREADCONTEXT, @@ -319,7 +384,7 @@ read_process_memory (int s) HANDLE h = gethandle (L"ReadProcessMemory handle", s, GDB_READPROCESSMEMORY); LPVOID p = getpvoid (L"ReadProcessMemory base", s, GDB_READPROCESSMEMORY); gdb_wince_len len = getlen (L"ReadProcessMemory size", s, GDB_READPROCESSMEMORY); - LPVOID buf = mempool ((gdb_wince_len) len); + LPVOID buf = mempool ((unsigned int) len); DWORD outlen; gdb_wince_result res; @@ -400,12 +465,6 @@ close_handle (int s) putresult (L"CloseHandle result", res, s, GDB_CLOSEHANDLE, &res, sizeof (res)); } -/* Handle single step instruction */ -static void -single_step (int s) -{ -} - /* Main loop for reading requests from gdb host on the socket. */ static void dispatch (int s) @@ -458,8 +517,8 @@ dispatch (int s) terminate_process (s); return; case GDB_SINGLESTEP: - single_step (s); - return; + flag_single_step (s); + break; default: { WCHAR buf[80]; @@ -495,8 +554,6 @@ WinMain (HINSTANCE hi, HINSTANCE hp, LPWSTR cmd, int show) wcstombs (host, whost, 80); /* Convert from UNICODE to ascii */ } - MessageBoxW (NULL, whost, L"GDB", MB_ICONERROR); - /* Winsock initialization. */ if (WSAStartup (MAKEWORD (1, 1), &wd)) stub_error (L"Couldn't initialize WINSOCK."); diff --git a/gdb/wince.c b/gdb/wince.c index 77780d4dbc0..27d3de222bf 100644 --- a/gdb/wince.c +++ b/gdb/wince.c @@ -55,6 +55,7 @@ #include #include "wince-stub.h" #include "dcache.h" +#include /* The ui's event loop. */ extern int (*ui_loop_hook) PARAMS ((int signo)); @@ -147,7 +148,6 @@ typedef struct thread_info_struct int suspend_count; int stepped; /* True if stepped. */ CORE_ADDR step_pc; - unsigned long step_instr; unsigned long step_prev; CONTEXT context; } @@ -155,6 +155,7 @@ thread_info; static thread_info thread_head = {NULL}; +static thread_info * thread_rec (DWORD id, int get_context); /* The process and thread handles for the above context. */ @@ -374,24 +375,21 @@ static const int mappings[NUM_REGS + 1] = -1 }; -/* This vector maps the target's idea of an exception (extracted - from the DEBUG_EVENT structure) to GDB's idea. */ - -struct xlate_exception - { - int them; - enum target_signal us; - }; - -static const struct xlate_exception - xlate[] = +/* Return a pointer into a CONTEXT field indexed by gdb register number. + Return a pointer to an address pointing to zero if there is no + corresponding CONTEXT field for the given register number. + */ +static ULONG * +regptr (LPCONTEXT c, int r) { - {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV}, - {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV}, - {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP}, - {DBG_CONTROL_C, TARGET_SIGNAL_INT}, - {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP}, - {-1, -1}}; + static ULONG zero = 0; + ULONG *p; + if (mappings[r] < 0) + p = &zero; + else + p = (ULONG *) (((char *) c) + mappings[r]); + return p; +} /******************** Beginning of stub interface ********************/ @@ -629,6 +627,7 @@ towide (const char *s, gdb_wince_len * out_len) typedef in wince-stub.h and change the putlen/getlen macros in this file and in the stub. */ + static int create_process (LPSTR exec_file, LPSTR args, DWORD flags, PROCESS_INFORMATION * pi) { @@ -798,6 +797,227 @@ stop_stub () /******************** End of emulation routines. ********************/ /******************** End of stub interface ********************/ +#define check_for_step(a, x) (x) + +#ifdef MIPS +static void +undoSStep (thread_info * th) +{ + if (th->stepped) + { + memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev); + th->stepped = 0; + } +} + +void +wince_software_single_step (unsigned int ignore, int insert_breakpoints_p) +{ + unsigned long pc; + thread_info *th = current_thread; /* Info on currently selected thread */ + CORE_ADDR mips_next_pc (CORE_ADDR pc); + + if (!insert_breakpoints_p) + { + undoSStep (th); + return; + } + + th->stepped = 1; + pc = read_register (PC_REGNUM); + th->step_pc = mips_next_pc (pc); + th->step_prev = 0; + memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev); + return; +} +#elif SHx +/* Hitachi SH architecture instruction encoding masks */ + +#define COND_BR_MASK 0xff00 +#define UCOND_DBR_MASK 0xe000 +#define UCOND_RBR_MASK 0xf0df +#define TRAPA_MASK 0xff00 + +#define COND_DISP 0x00ff +#define UCOND_DISP 0x0fff +#define UCOND_REG 0x0f00 + +/* Hitachi SH instruction opcodes */ + +#define BF_INSTR 0x8b00 +#define BT_INSTR 0x8900 +#define BRA_INSTR 0xa000 +#define BSR_INSTR 0xb000 +#define JMP_INSTR 0x402b +#define JSR_INSTR 0x400b +#define RTS_INSTR 0x000b +#define RTE_INSTR 0x002b +#define TRAPA_INSTR 0xc300 +#define SSTEP_INSTR 0xc3ff + + +#define T_BIT_MASK 0x0001 + +static CORE_ADDR +sh_get_next_pc (CONTEXT *c) +{ + short *instrMem; + int displacement; + int reg; + unsigned short opcode; + + instrMem = (short *) c->Fir; + + opcode = read_memory_integer ((CORE_ADDR) c->Fir, sizeof (opcode)); + + if ((opcode & COND_BR_MASK) == BT_INSTR) + { + if (c->Psr & T_BIT_MASK) + { + displacement = (opcode & COND_DISP) << 1; + if (displacement & 0x80) + displacement |= 0xffffff00; + /* + * Remember PC points to second instr. + * after PC of branch ... so add 4 + */ + instrMem = (short *) (c->Fir + displacement + 4); + } + else + instrMem += 1; + } + else if ((opcode & COND_BR_MASK) == BF_INSTR) + { + if (c->Psr & T_BIT_MASK) + instrMem += 1; + else + { + displacement = (opcode & COND_DISP) << 1; + if (displacement & 0x80) + displacement |= 0xffffff00; + /* + * Remember PC points to second instr. + * after PC of branch ... so add 4 + */ + instrMem = (short *) (c->Fir + displacement + 4); + } + } + else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR) + { + displacement = (opcode & UCOND_DISP) << 1; + if (displacement & 0x0800) + displacement |= 0xfffff000; + + /* + * Remember PC points to second instr. + * after PC of branch ... so add 4 + */ + instrMem = (short *) (c->Fir + displacement + 4); + } + else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR) + { + reg = (char) ((opcode & UCOND_REG) >> 8); + + instrMem = (short *) *regptr (c, reg); + } + else if (opcode == RTS_INSTR) + instrMem = (short *) c->PR; + else if (opcode == RTE_INSTR) + instrMem = (short *) *regptr (c, 15); + else if ((opcode & TRAPA_MASK) == TRAPA_INSTR) + instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2); + else + instrMem += 1; + + return (CORE_ADDR) instrMem; +} +/* Single step (in a painstaking fashion) by inspecting the current + instruction and setting a breakpoint on the "next" instruction + which would be executed. This code hails from sh-stub.c. + */ +static void +undoSStep (thread_info * th) +{ + if (th->stepped) + { + memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev); + th->stepped = 0; + } + return; +} + +/* Single step (in a painstaking fashion) by inspecting the current + instruction and setting a breakpoint on the "next" instruction + which would be executed. This code hails from sh-stub.c. + */ +void +wince_software_single_step (unsigned int ignore, int insert_breakpoints_p) +{ + thread_info *th = current_thread; /* Info on currently selected thread */ + + if (!insert_breakpoints_p) + { + undoSStep (th); + return; + } + + th->stepped = 1; + th->step_pc = sh_get_next_pc (&th->context); + th->step_prev = 0; + memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev); + return; +} +#elif defined (ARM) +#undef check_for_step + +static enum target_signal +check_for_step (DEBUG_EVENT *ev, enum target_signal x) +{ + thread_info *th = thread_rec (ev->dwThreadId, 1); + + if (th->stepped && + th->step_pc == (CORE_ADDR) ev->u.Exception.ExceptionRecord.ExceptionAddress) + return TARGET_SIGNAL_TRAP; + else + return x; +} + +/* Single step (in a painstaking fashion) by inspecting the current + instruction and setting a breakpoint on the "next" instruction + which would be executed. This code hails from sh-stub.c. + */ +static void +undoSStep (thread_info * th) +{ + if (th->stepped) + { + memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev); + th->stepped = 0; + } +} + +void +wince_software_single_step (unsigned int ignore, int insert_breakpoints_p) +{ + unsigned long pc; + thread_info *th = current_thread; /* Info on currently selected thread */ + CORE_ADDR mips_next_pc (CORE_ADDR pc); + + if (!insert_breakpoints_p) + { + undoSStep (th); + return; + } + + th->stepped = 1; + pc = read_register (PC_REGNUM); + th->step_pc = arm_get_next_pc (pc); + th->step_prev = 0; + memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev); + return; +} +#endif + /* Find a thread record given a thread id. If get_context then also retrieve the context for this thread. */ @@ -893,22 +1113,6 @@ check (BOOL ok, const char *file, int line) printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ()); } -/* Return a pointer into a CONTEXT field indexed by gdb register number. - Return a pointer to an address pointing to zero if there is no - corresponding CONTEXT field for the given register number. - */ -static ULONG * -regptr (LPCONTEXT c, int r) -{ - static ULONG zero = 0; - ULONG *p; - if (mappings[r] < 0) - p = &zero; - else - p = (ULONG *) (((char *) c) + mappings[r]); - return p; -} - static void do_child_fetch_inferior_registers (int r) { @@ -991,7 +1195,9 @@ handle_load_dll (PTR dummy) out: if (!len) return 1; +#if 0 dll_buf[len] = '\0'; +#endif dll_name = alloca (len); if (!dll_name) @@ -1021,22 +1227,12 @@ out: FIXME: Is this the real reason that we need the 0x1000 ? */ printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name); -#if 0 /* FIXME: Need to use RAPI stuff to read the file someday. */ - { - struct section_addr_info section_addrs; - memset (§ion_addrs, 0, sizeof (section_addrs)); - section_addrs.text_addr = (int) event->lpBaseOfDll + 0x1000; - symbol_file_add (dll_name, 0, §ion_addrs, 0, OBJF_SHARED); - } -#endif printf_unfiltered ("\n"); return 1; } -/* Handle DEBUG_STRING output from child process. - Cygwin prepends its messages with a "cygwin:". Interpret this as - a Cygwin signal. Otherwise just print the string as a warning. */ +/* Handle DEBUG_STRING output from child process. */ static void handle_output_debug_string (struct target_waitstatus *ourstatus) { @@ -1068,6 +1264,7 @@ handle_output_debug_string (struct target_waitstatus *ourstatus) } warning (s); + return; } @@ -1075,16 +1272,13 @@ handle_output_debug_string (struct target_waitstatus *ourstatus) static int handle_exception (struct target_waitstatus *ourstatus) { - thread_info *th; - +#if 0 if (current_event.u.Exception.dwFirstChance) return 0; +#endif ourstatus->kind = TARGET_WAITKIND_STOPPED; - /* Record the context of the current thread */ - th = thread_rec (current_event.dwThreadId, -1); - switch (current_event.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: @@ -1114,10 +1308,15 @@ handle_exception (struct target_waitstatus *ourstatus) (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress)); ourstatus->value.sig = TARGET_SIGNAL_TRAP; break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08x\n", + current_event.u.Exception.ExceptionRecord.ExceptionAddress)); + ourstatus->value.sig = check_for_step (¤t_event, TARGET_SIGNAL_ILL); + break; default: /* This may be a structured exception handling exception. In - that case, we want to let the program try to handle it, and - only break if we see the exception a second time. */ + that case, we want to let the program try to handle it, and + only break if we see the exception a second time. */ printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n", current_event.u.Exception.ExceptionRecord.ExceptionCode, @@ -1159,23 +1358,29 @@ child_continue (DWORD continue_status, int id) handling by WFI (or whatever). */ static int -get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * event_code, int *retval) +get_child_debug_event (int pid, struct target_waitstatus *ourstatus, + DWORD target_event_code, int *retval) { + int breakout = 0; BOOL debug_event; - DWORD continue_status; - int breakout = 1; + DWORD continue_status, event_code; + thread_info *th = NULL; + static thread_info dummy_thread_info; if (!(debug_event = wait_for_debug_event (¤t_event, 1000))) { - breakout = *retval = *event_code = 0; + *retval = 0; goto out; } - this_thread = thread_rec (current_event.dwThreadId, FALSE); event_count++; continue_status = DBG_CONTINUE; *retval = 0; - switch (*event_code = current_event.dwDebugEventCode) + + event_code = current_event.dwDebugEventCode; + breakout = event_code == target_event_code; + + switch (event_code) { case CREATE_THREAD_DEBUG_EVENT: DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n", @@ -1183,8 +1388,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve (unsigned) current_event.dwThreadId, "CREATE_THREAD_DEBUG_EVENT")); /* Record the existence of this thread */ - child_add_thread (current_event.dwThreadId, - current_event.u.CreateThread.hThread); + th = child_add_thread (current_event.dwThreadId, + current_event.u.CreateThread.hThread); if (info_verbose) printf_unfiltered ("[New %s]\n", target_pid_to_str (current_event.dwThreadId)); @@ -1196,6 +1401,7 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve (unsigned) current_event.dwThreadId, "EXIT_THREAD_DEBUG_EVENT")); child_delete_thread (current_event.dwThreadId); + th = &dummy_thread_info; break; case CREATE_PROCESS_DEBUG_EVENT: @@ -1207,8 +1413,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve main_thread_id = inferior_pid = current_event.dwThreadId; /* Add the main thread */ - current_thread = child_add_thread (inferior_pid, - current_event.u.CreateProcessInfo.hThread); + th = child_add_thread (inferior_pid, + current_event.u.CreateProcessInfo.hThread); break; case EXIT_PROCESS_DEBUG_EVENT: @@ -1220,7 +1426,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode; close_handle (current_process_handle); *retval = current_event.dwProcessId; - goto out; + breakout = 1; + break; case LOAD_DLL_DEBUG_EVENT: DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", @@ -1244,14 +1451,12 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve (unsigned) current_event.dwThreadId, "EXCEPTION_DEBUG_EVENT")); if (handle_exception (ourstatus)) + *retval = current_event.dwThreadId; + else { - char buf[32]; - *retval = current_event.dwThreadId; - remote_read_bytes (read_pc (), buf, sizeof (buf)); - dcache_xfer_memory (remote_dcache, read_pc (), buf, sizeof (buf), 0); - goto out; + continue_status = DBG_EXCEPTION_NOT_HANDLED; + breakout = 0; } - continue_status = DBG_EXCEPTION_NOT_HANDLED; break; case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */ @@ -1259,7 +1464,7 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve (unsigned) current_event.dwProcessId, (unsigned) current_event.dwThreadId, "OUTPUT_DEBUG_STRING_EVENT")); - handle_output_debug_string (ourstatus); + handle_output_debug_string ( ourstatus); break; default: printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n", @@ -1270,8 +1475,10 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve break; } - breakout = 0; - CHECK (child_continue (continue_status, -1)); + if (breakout) + this_thread = current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE); + else + CHECK (child_continue (continue_status, -1)); out: return breakout; @@ -1291,7 +1498,7 @@ child_wait (int pid, struct target_waitstatus *ourstatus) isn't necessarily what you think it is. */ while (1) - if (get_child_debug_event (pid, ourstatus, &event_code, &retval)) + if (get_child_debug_event (pid, ourstatus, EXCEPTION_DEBUG_EVENT, &retval)) return retval; else { @@ -1351,14 +1558,15 @@ char * upload_to_device (const char *to, const char *from) { HANDLE h; - const char *dir = remote_directory ? : "\\gdb"; + const char *dir = remote_directory ?: "\\gdb"; int len; static char *remotefile = NULL; LPWSTR wstr; char *p; DWORD err; const char *in_to = to; - FILETIME ctime, atime, wtime; + FILETIME crtime, actime, wrtime; + time_t utime; struct stat st; int fd; @@ -1397,15 +1605,25 @@ upload_to_device (const char *to, const char *from) /* Some kind of problem? */ err = CeGetLastError (); - if (h == NULL) - error ("error creating file to \"%s\". Windows error %d.", + if (h == NULL || h == INVALID_HANDLE_VALUE) + error ("error opening file \"%s\". Windows error %d.", remotefile, err); + CeGetFileTime (h, &crtime, &actime, &wrtime); + utime = to_time_t (&wrtime); +#if 0 + if (utime < st.st_mtime) + { + char buf[80]; + strcpy (buf, ctime(&utime)); + printf ("%s < %s\n", buf, ctime(&st.st_mtime)); + } +#endif /* See if we need to upload the file. */ if (upload_when == UPLOAD_ALWAYS || err != ERROR_ALREADY_EXISTS || - !CeGetFileTime (h, &ctime, &atime, &wtime) || - to_time_t (&wtime) < st.st_mtime) + !CeGetFileTime (h, &crtime, &actime, &wrtime) || + to_time_t (&wrtime) < st.st_mtime) { DWORD nbytes; char buf[4096]; @@ -1419,7 +1637,8 @@ upload_to_device (const char *to, const char *from) } close (fd); - CeCloseHandle (h); + if (!CeCloseHandle (h)) + error ("error closing remote file - %d.", CeGetLastError ()); return remotefile; } @@ -1555,11 +1774,10 @@ child_create_inferior (char *exec_file, char *args, char **env) target_terminal_init (); target_terminal_inferior (); - /* Run until process and threads are loaded */ - do - get_child_debug_event (inferior_pid, &dummy, &event_code, &ret); - while (event_code != CREATE_PROCESS_DEBUG_EVENT); + while (!get_child_debug_event (inferior_pid, &dummy, + CREATE_PROCESS_DEBUG_EVENT, &ret)) + continue; proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); } @@ -1607,213 +1825,6 @@ child_kill_inferior (void) target_mourn_inferior (); /* or just child_mourn_inferior? */ } -#ifdef MIPS -static void -undoSStep (thread_info * th) -{ - if (th->stepped) - { - memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev); - th->stepped = 0; - } -} - -void -wince_software_single_step (unsigned int ignore, int insert_breakpoints_p) -{ - unsigned long pc; - thread_info *th = current_thread; /* Info on currently selected thread */ - CORE_ADDR mips_next_pc (CORE_ADDR pc); - - if (!insert_breakpoints_p) - { - undoSStep (th); - return; - } - - th->stepped = 1; - pc = read_register (PC_REGNUM); - th->step_pc = mips_next_pc (pc); - th->step_prev = 0; - memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev); -} -#elif SHx -/* Hitachi SH architecture instruction encoding masks */ - -#define COND_BR_MASK 0xff00 -#define UCOND_DBR_MASK 0xe000 -#define UCOND_RBR_MASK 0xf0df -#define TRAPA_MASK 0xff00 - -#define COND_DISP 0x00ff -#define UCOND_DISP 0x0fff -#define UCOND_REG 0x0f00 - -/* Hitachi SH instruction opcodes */ - -#define BF_INSTR 0x8b00 -#define BT_INSTR 0x8900 -#define BRA_INSTR 0xa000 -#define BSR_INSTR 0xb000 -#define JMP_INSTR 0x402b -#define JSR_INSTR 0x400b -#define RTS_INSTR 0x000b -#define RTE_INSTR 0x002b -#define TRAPA_INSTR 0xc300 -#define SSTEP_INSTR 0xc3ff - - -#define T_BIT_MASK 0x0001 - -/* Undo the effect of a previous doSStep. If we single stepped, - restore the old instruction. */ - -static void -undoSStep (thread_info * th) -{ - if (th->stepped) - { - gdb_wince_len done; - write_process_memory (current_process_handle, (LPVOID) th->step_pc, - (LPVOID) & th->step_instr, sizeof (short), &done); - if (done != sizeof (short)) - error ("error unsetting single step."); - th->stepped = 0; - } -} - -/* Single step (in a painstaking fashion) by inspecting the current - instruction and setting a breakpoint on the "next" instruction - which would be executed. This code hails from sh-stub.c. - */ -void -wince_software_single_step (unsigned int ignore, int insert_breakpoints_p) -{ - thread_info *th = current_thread; /* Info on currently selected thread */ - - if (!insert_breakpoints_p) - undoSStep (th); - else - { - short *instrMem; - int displacement; - int reg; - unsigned short opcode; - gdb_wince_len done; - LPCONTEXT c = &th->context; - - instrMem = (short *) c->Fir; - - read_process_memory (current_process_handle, (LPCVOID) c->Fir, &opcode, - sizeof (opcode), &done); - if (done != sizeof (opcode)) - error ("couldn't retrieve opcode"); - th->stepped = 1; - - if ((opcode & COND_BR_MASK) == BT_INSTR) - { - if (c->Psr & T_BIT_MASK) - { - displacement = (opcode & COND_DISP) << 1; - if (displacement & 0x80) - displacement |= 0xffffff00; - /* - * Remember PC points to second instr. - * after PC of branch ... so add 4 - */ - instrMem = (short *) (c->Fir + displacement + 4); - } - else - instrMem += 1; - } - else if ((opcode & COND_BR_MASK) == BF_INSTR) - { - if (c->Psr & T_BIT_MASK) - instrMem += 1; - else - { - displacement = (opcode & COND_DISP) << 1; - if (displacement & 0x80) - displacement |= 0xffffff00; - /* - * Remember PC points to second instr. - * after PC of branch ... so add 4 - */ - instrMem = (short *) (c->Fir + displacement + 4); - } - } - else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR) - { - displacement = (opcode & UCOND_DISP) << 1; - if (displacement & 0x0800) - displacement |= 0xfffff000; - - /* - * Remember PC points to second instr. - * after PC of branch ... so add 4 - */ - instrMem = (short *) (c->Fir + displacement + 4); - } - else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR) - { - reg = (char) ((opcode & UCOND_REG) >> 8); - - instrMem = (short *) *regptr (c, reg); - } - else if (opcode == RTS_INSTR) - instrMem = (short *) c->PR; - else if (opcode == RTE_INSTR) - instrMem = (short *) *regptr (c, 15); - else if ((opcode & TRAPA_MASK) == TRAPA_INSTR) - instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2); - else - instrMem += 1; - - th->step_pc = (CORE_ADDR) instrMem; - - read_process_memory (current_process_handle, (LPVOID) instrMem, - (LPVOID) & th->step_instr, sizeof (short), &done); - opcode = SSTEP_INSTR; - write_process_memory (current_process_handle, (LPVOID) instrMem, - (LPVOID) & opcode, sizeof (short), &done); - } -} -#elif defined (ARM) -/* Single step (in a painstaking fashion) by inspecting the current - instruction and setting a breakpoint on the "next" instruction - which would be executed. This code hails from sh-stub.c. - */ -static void -undoSStep (thread_info * th) -{ - if (th->stepped) - { - memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev); - th->stepped = 0; - } -} - -void -wince_software_single_step (unsigned int ignore, int insert_breakpoints_p) -{ - unsigned long pc; - thread_info *th = current_thread; /* Info on currently selected thread */ - CORE_ADDR mips_next_pc (CORE_ADDR pc); - - if (!insert_breakpoints_p) - { - undoSStep (th); - return; - } - - th->stepped = 1; - pc = read_register (PC_REGNUM); - th->step_pc = arm_get_next_pc (pc); - th->step_prev = 0; - memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev); -} -#endif - /* Resume the child after an exception. */ void child_resume (int pid, int step, enum target_signal sig) @@ -1917,8 +1928,8 @@ init_child_ops (void) /* Handle 'set remoteupload' parameter. */ #define replace_upload(what) \ - upload_when = UPLOAD_NEWER; \ - remote_upload = realloc (remote_upload, strlen (upload_options[upload_when].name)); \ + upload_when = what; \ + remote_upload = realloc (remote_upload, strlen (upload_options[upload_when].name) + 1); \ strcpy (remote_upload, upload_options[upload_when].name); static void @@ -1940,8 +1951,7 @@ set_upload_type (char *ignore, int from_tty) if (len >= upload_options[i].abbrev && strncasecmp (remote_upload, upload_options[i].name, len) == 0) { - remote_upload = (char *) upload_options[i].name; - upload_when = i; + replace_upload (i); return; }