2009-07-01 Danny Backx * win32-i386-low.c (i386_get_thread_context): Avoid failure by calling GetThreadContext with flags that don't work on every processor. Fall back to querying less registers if that happens. * win32-i386-low.c (the_low_target, i386_wince_breakpoint) : Implement breakpoints. * win32-low.c (get_image_name): Don't rely on return value of ReadProcessMemory. Comment where some of the code still relies on sizeof(WCHAR) == 2. * win32-low.c (get_child_debug_event): Detect and work around a known case where CreateProcess reports success but the inferior dies immediately. Index: win32-i386-low.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/win32-i386-low.c,v retrieving revision 1.14 diff -u -u -p -r1.14 win32-i386-low.c --- win32-i386-low.c 3 Jan 2009 05:57:57 -0000 1.14 +++ win32-i386-low.c 1 Jul 2009 19:28:15 -0000 @@ -39,16 +39,36 @@ i386_initial_stuff (void) debug_registers_used = 0; } +/* + * According to Mike Stall's .net debugging blog + * (http://blogs.msdn.com/jmstall/archive/2005/01/18/355697.aspx) + * the CONTEXT_EXTENDED_REGISTERS flag must be omitted if hardware doesn't + * support it. So I guess the only reasonable thing to do is just try. + */ static void i386_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event) { - th->context.ContextFlags = \ - CONTEXT_FULL | \ - CONTEXT_FLOATING_POINT | \ - CONTEXT_EXTENDED_REGISTERS | \ + /* try all flags */ + th->context.ContextFlags = + CONTEXT_FULL | + CONTEXT_FLOATING_POINT | + CONTEXT_EXTENDED_REGISTERS | CONTEXT_DEBUG_REGISTERS; - GetThreadContext (th->h, &th->context); + if (GetThreadContext (th->h, &th->context) == 0) { + DWORD e = GetLastError(); + + if (e == ERROR_INVALID_PARAMETER) { + /* try limited set */ + th->context.ContextFlags = CONTEXT_FULL | + CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; + if (GetThreadContext (th->h, &th->context) == 0) { + DWORD e = GetLastError(); + printf("GetThreadContext failure %d\n", e); + return; + } + } + } debug_registers_changed = 0; @@ -193,6 +213,12 @@ i386_store_inferior_register (win32_thre collect_register (r, context_offset); } +/* + * The INT 3 instruction is used for x86 platform breakpointing. + */ +static const unsigned char i386_wince_breakpoint = 0xCC; +#define i386_wince_breakpoint_len 1 + struct win32_target_ops the_low_target = { init_registers_i386, sizeof (mappings) / sizeof (mappings[0]), @@ -203,6 +229,6 @@ struct win32_target_ops the_low_target = i386_fetch_inferior_register, i386_store_inferior_register, i386_single_step, - NULL, /* breakpoint */ - 0, /* breakpoint_len */ + &i386_wince_breakpoint, /* breakpoint */ + i386_wince_breakpoint_len, /* breakpoint_len */ }; Index: win32-low.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/win32-low.c,v retrieving revision 1.35 diff -u -u -p -r1.35 win32-low.c --- win32-low.c 1 Apr 2009 22:50:24 -0000 1.35 +++ win32-low.c 1 Jul 2009 19:28:15 -0000 @@ -873,14 +873,19 @@ win32_add_one_solib (const char *name, C loaded_dll (buf2, load_addr); } +/* + * Warning : some parts of this function rely on sizeof(WCHAR) == 2 + */ static char * get_image_name (HANDLE h, void *address, int unicode) { - static char buf[(2 * MAX_PATH) + 1]; + static char buf[(2 * MAX_PATH) + 1]; /* here */ DWORD size = unicode ? sizeof (WCHAR) : sizeof (char); char *address_ptr; +#ifndef _WIN32_WCE int len = 0; - char b[2]; + char b[2]; /* here */ +#endif DWORD done; /* Attempt to read the name of the dll that was detected. @@ -903,9 +908,28 @@ get_image_name (HANDLE h, void *address, return NULL; #endif +#ifdef _WIN32_WCE + /* Always unicode */ + /* Assume you can read it all in one go, or otherwise the done variable will + * tell you how far you've read. + */ + WCHAR *wbuf = alloca ((MAX_PATH + 1) * size); + ReadProcessMemory (h, address_ptr, wbuf, MAX_PATH * size, &done); + if (done < 0 || done > MAX_PATH * size) + buf[0] = '\0'; + else { + int n; + n = wcstombs (buf, wbuf, done); + if (n == (size_t)-1) + buf[0] = '\0'; + /* No need to address the length limit case of the wcstombs call, + * buf has been allocated large enough. */ + } + return buf; +#else /* Find the length of the string */ while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done) - && (b[0] != 0 || b[size - 1] != 0) && done == size) + && (b[0] != 0 || b[size - 1] != 0) && done == size) /* here */ continue; if (!unicode) @@ -920,6 +944,7 @@ get_image_name (HANDLE h, void *address, } return buf; +#endif } typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *, @@ -1365,7 +1390,20 @@ get_child_debug_event (struct target_wai interruption, but high enough so gdbserver doesn't become a bottleneck. */ if (!WaitForDebugEvent (¤t_event, 250)) - return 0; + { + /* + * Sometimes an application will just not start up. + * Detect this here, return in such a way that the loop ends. + */ + DWORD e = GetLastError(); + + if (e == ERROR_PIPE_NOT_CONNECTED) + { + ourstatus->kind = TARGET_WAITKIND_EXITED; + return 1; /* break the loop in our caller */ + } + return 0; + } } gotevent: