This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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 (&current_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 (&current_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:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]