Index: server.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/server.c,v retrieving revision 1.97 diff -u -r1.97 server.c --- server.c 24 May 2009 21:06:53 -0000 1.97 +++ server.c 14 Jun 2009 08:29:23 -0000 @@ -1995,11 +1995,13 @@ continue; } +#if 0 if (setjmp (toplevel)) { fprintf (stderr, "Exiting\n"); exit (1); } +#endif port = *next_arg; next_arg++; @@ -2077,11 +2079,13 @@ shared library event" notice on gdb side. */ dlls_changed = 0; +#if 0 if (setjmp (toplevel)) { detach_or_kill_for_exit (); exit (1); } +#endif if (last_status.kind == TARGET_WAITKIND_EXITED || last_status.kind == TARGET_WAITKIND_SIGNALLED) @@ -2103,6 +2107,7 @@ remote_open (port); +#if 0 if (setjmp (toplevel) != 0) { /* An error occurred. */ @@ -2112,6 +2117,7 @@ putpkt (own_buf); } } +#endif /* Wait for events. This will return when all event sources are removed from the event loop. */ Index: utils.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/utils.c,v retrieving revision 1.18 diff -u -r1.18 utils.c --- utils.c 19 Jan 2009 00:16:46 -0000 1.18 +++ utils.c 14 Jun 2009 08:29:23 -0000 @@ -139,7 +139,11 @@ fflush (stdout); vfprintf (stderr, string, args); fprintf (stderr, "\n"); +#ifdef __MINGW32CE__ + exit(1); +#else longjmp (toplevel, 1); +#endif } /* Print an error message and exit reporting failure. Index: win32-i386-low.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/win32-i386-low.c,v retrieving revision 1.14 diff -u -r1.14 win32-i386-low.c --- win32-i386-low.c 3 Jan 2009 05:57:57 -0000 1.14 +++ win32-i386-low.c 14 Jun 2009 08:29:23 -0000 @@ -39,16 +39,36 @@ 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,27 @@ collect_register (r, context_offset); } +/* + * The INT 3 instruction is traditionally used for x86 platform breakpointing. + * Microsoft also appears to use a DebugBreak function, which probably does the same. + * Gas translates "int $3" (or "int3") to a one-byte instruction : 0xCC . + * + * From Wikipedia : + * + * The INT 3 instruction is defined for use by debuggers to temporarily replace + * an instruction in a running program, in order to set a breakpoint. Other INT + * instructions are encoded using two bytes. This makes them unsuitable for use + * in patching instructions (which can be one byte long). + * + * The opcode for INT 3 is 0xCC, as opposite from the opcode for INT immediate, + * which is 0xCD imm8. According to Intel documentation: "Intel and Microsoft + * assemblers will not generate the CD03 opcode from any mnemonic" and 0xCC + * has some special features, which are not shared by "the normal 2-byte + * opcode for INT 3 (CD03)" [IA-32 Arch. Software Developer’s Manual. Vol. 2A] + */ +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 +244,6 @@ 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 -r1.35 win32-low.c --- win32-low.c 1 Apr 2009 22:50:24 -0000 1.35 +++ win32-low.c 14 Jun 2009 08:29:24 -0000 @@ -873,14 +873,19 @@ 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 @@ 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) @@ -915,11 +939,10 @@ WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR)); ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR), &done); - WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0); } - return buf; +#endif } typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *, @@ -969,8 +992,9 @@ DWORD cbNeeded; BOOL ok; - if (!load_psapi ()) + if (!load_psapi ()) { goto failed; + } cbNeeded = 0; ok = (*win32_EnumProcessModules) (current_process_handle, @@ -1123,6 +1147,7 @@ /* Windows does not report the image name of the dlls in the debug event on attaches. We resort to iterating over the list of loaded dlls looking for a match by image base. */ + /* Note : no psapi.dll on CE, fall back to get_image_name below. */ if (!psapi_get_dll_name ((DWORD) event->lpBaseOfDll, dll_buf)) { if (!server_waiting) @@ -1349,6 +1374,7 @@ happen is the user will see a spurious breakpoint. */ current_event.dwDebugEventCode = 0; + OUTMSG2(("attaching: before WaitForDebugEvent\n")); if (!WaitForDebugEvent (¤t_event, 0)) { OUTMSG2(("no attach events left\n")); @@ -1365,7 +1391,20 @@ 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: