This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: Patch : gdbserver get_image_name on CE
This patch is w.r.t. current CVS, and also fixes a couple of places
where I messed up the indenting. Is that what you referred to with the
standards comment ? I'm trying, I sometimes miss things though :-)
Your comment about I need to address the setjmp issue is correct. I need
to find the cause though. This part of the patch certainly doesn't
belong in gdb's sources. But it's still in discussion phase, isn't it ?
More comments ? Should the INT3 comment go away ? I feel that the code
is under-commented at times, but this one may be somewhat overdone :-)
Danny
On Sat, 2009-06-13 at 19:08 +0100, Pedro Alves wrote:
> One last item: Please do post patches against current
> CVS. A lot has changed since 6.8, although I don't think
> your changes are much affected.
>
--
Danny Backx ; danny.backx - at - scarlet.be ; http://danny.backx.info
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: