Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* Re: Patch : gdbserver get_image_name on CE
@ 2009-06-13 14:29 Danny Backx
  2009-06-13 18:05 ` Pedro Alves
  0 siblings, 1 reply; 31+ messages in thread
From: Danny Backx @ 2009-06-13 14:29 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1086 bytes --]

As I said gdbserver works with this patch, on CE on an x86 clone.

For the record, I'm testing this with a Via Eden ULV processor on
Windows Embedded CE 6.0 .

Several issues solved with this patch :
1. Initialize the breakpoint structure to the right instruction.
2. Handle a case where the inferior refuses to start. See the
   code after WaitForDebugEvent in win32-low.c .
3. Setjmp won't work on this platform, I've "#if 0"-ed it out.
   Clearly not the right solution. Comment please.
4. Handle the failing call to GetThreadContext.
5. Read the DLL names in a way that works on x86.

The patch I've attached is relative to gdb-6.8 .
The configure.srv bit in the attachment was sent (by me) and committed
(by Pedro) earlier, don't pay attention to it.
The patch for #5 was also recently sent by me, probably not committed
yet.

After comments on this, I'll transform this into a real patch.

Note that gdb also requires a bit of work, I've not polluted this patch
with that. I have it working too.

	Danny


-- 
Danny Backx ; danny.backx - at - scarlet.be ; http://danny.backx.info

[-- Attachment #2: gdbserver-diffs --]
[-- Type: text/x-patch, Size: 11303 bytes --]

diff -c /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/configure.srv ./configure.srv
*** /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/configure.srv	2008-02-11 23:00:31.000000000 +0100
--- ./configure.srv	2009-04-17 19:49:46.000000000 +0200
***************
*** 65,70 ****
--- 65,79 ----
  			srv_linux_regsets=yes
  			srv_linux_thread_db=yes
  			;;
+   i[34567]86-*-mingw*ce*)
+ 			srv_regobj=reg-i386.o
+ 			srv_tgtobj="win32-low.o win32-i386-low.o"
+ 			srv_tgtobj="${srv_tgtobj} wincecompat.o"
+ 			# hostio_last_error implementation is in win32-low.c
+ 			srv_hostio_err_objs=""
+ 			srv_mingw=yes
+ 			srv_mingwce=yes
+ 			;;
    i[34567]86-*-mingw*)	srv_regobj=reg-i386.o
  			srv_tgtobj="win32-low.o win32-i386-low.o"
  			srv_mingw=yes
diff -c /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/server.c ./server.c
*** /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/server.c	2008-02-19 22:36:54.000000000 +0100
--- ./server.c	2009-06-13 11:57:58.000000000 +0200
***************
*** 1061,1071 ****
--- 1061,1073 ----
        continue;
      }
  
+ #if 0
    if (setjmp (toplevel))
      {
        fprintf (stderr, "Exiting\n");
        exit (1);
      }
+ #endif
  
    port = *next_arg;
    next_arg++;
***************
*** 1141,1153 ****
       shared library event" notice on gdb side.  */
    dlls_changed = 0;
  
    if (setjmp (toplevel))
      {
        fprintf (stderr, "Killing inferior\n");
        kill_inferior ();
        exit (1);
      }
! 
    if (status == 'W' || status == 'X')
      was_running = 0;
    else
--- 1143,1156 ----
       shared library event" notice on gdb side.  */
    dlls_changed = 0;
  
+ #if 0
    if (setjmp (toplevel))
      {
        fprintf (stderr, "Killing inferior\n");
        kill_inferior ();
        exit (1);
      }
! #endif
    if (status == 'W' || status == 'X')
      was_running = 0;
    else
***************
*** 1164,1169 ****
--- 1167,1173 ----
        remote_open (port);
  
      restart:
+ #if 0
        if (setjmp (toplevel) != 0)
  	{
  	  /* An error occurred.  */
***************
*** 1173,1178 ****
--- 1177,1183 ----
  	      putpkt (own_buf);
  	    }
  	}
+ #endif
  
        disable_async_io ();
        while (!exit_requested)
Only in .: spu-low.c~
diff -c /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/utils.c ./utils.c
*** /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/utils.c	2008-01-01 23:53:14.000000000 +0100
--- ./utils.c	2009-05-31 15:38:07.000000000 +0200
***************
*** 65,71 ****
--- 65,75 ----
    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.
diff -c /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/win32-i386-low.c ./win32-i386-low.c
*** /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/win32-i386-low.c	2008-01-01 23:53:14.000000000 +0100
--- ./win32-i386-low.c	2009-06-13 11:50:19.000000000 +0200
***************
*** 36,51 ****
    debug_registers_used = 0;
  }
  
  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 | \
      CONTEXT_DEBUG_REGISTERS;
  
!   GetThreadContext (th->h, &th->context);
  
    debug_registers_changed = 0;
  
--- 36,71 ----
    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)
  {
!   /* try all flags */
!   th->context.ContextFlags =
!     CONTEXT_FULL |
!     CONTEXT_FLOATING_POINT |
!     CONTEXT_EXTENDED_REGISTERS |
      CONTEXT_DEBUG_REGISTERS;
  
!   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;
  
***************
*** 190,195 ****
--- 210,236 ----
    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 = {
    sizeof (mappings) / sizeof (mappings[0]),
    i386_initial_stuff,
***************
*** 199,205 ****
    i386_fetch_inferior_register,
    i386_store_inferior_register,
    i386_single_step,
!   NULL, /* breakpoint */
!   0, /* breakpoint_len */
    "i386" /* arch_string */
  };
--- 240,246 ----
    i386_fetch_inferior_register,
    i386_store_inferior_register,
    i386_single_step,
!   &i386_wince_breakpoint, /* breakpoint */
!   i386_wince_breakpoint_len, /* breakpoint_len */
    "i386" /* arch_string */
  };
diff -c /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/win32-low.c ./win32-low.c
*** /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/win32-low.c	2008-02-14 23:41:39.000000000 +0100
--- ./win32-low.c	2009-06-13 16:18:48.000000000 +0200
***************
*** 894,907 ****
    loaded_dll (buf2, load_addr);
  }
  
  static char *
  get_image_name (HANDLE h, void *address, int unicode)
  {
!   static char buf[(2 * MAX_PATH) + 1];
    DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
    char *address_ptr;
    int len = 0;
!   char b[2];
    DWORD done;
  
    /* Attempt to read the name of the dll that was detected.
--- 894,912 ----
    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]; /* here */
    DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
    char *address_ptr;
+ #ifndef _WIN32_WCE
    int len = 0;
!   char b[2]; /* here */
! #endif
    DWORD done;
  
    /* Attempt to read the name of the dll that was detected.
***************
*** 924,932 ****
      return NULL;
  #endif
  
    /* 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)
      continue;
  
    if (!unicode)
--- 929,956 ----
      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) /* here */
      continue;
  
    if (!unicode)
***************
*** 936,946 ****
        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;
  }
  
  typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
--- 960,969 ----
        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 *,
***************
*** 990,997 ****
    DWORD cbNeeded;
    BOOL ok;
  
!   if (!load_psapi ())
      goto failed;
  
    cbNeeded = 0;
    ok = (*win32_EnumProcessModules) (current_process_handle,
--- 1013,1021 ----
    DWORD cbNeeded;
    BOOL ok;
  
!   if (!load_psapi ()) {
      goto failed;
+   }
  
    cbNeeded = 0;
    ok = (*win32_EnumProcessModules) (current_process_handle,
***************
*** 1144,1149 ****
--- 1168,1174 ----
    /* 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)
***************
*** 1368,1373 ****
--- 1393,1399 ----
   	 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"));
***************
*** 1383,1390 ****
        /* Keep the wait time low enough for confortable remote
   	 interruption, but high enough so gdbserver doesn't become a
   	 bottleneck.  */
!       if (!WaitForDebugEvent (&current_event, 250))
   	return 0;
      }
  
   gotevent:
--- 1409,1427 ----
        /* Keep the wait time low enough for confortable remote
   	 interruption, but high enough so gdbserver doesn't become a
   	 bottleneck.  */
!       if (!WaitForDebugEvent (&current_event, 250)) {
! 	/*
! 	 * 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:

^ permalink raw reply	[flat|nested] 31+ messages in thread
* Patch : gdbserver get_image_name on CE
@ 2009-06-07  9:18 Danny Backx
  2009-06-07 17:03 ` Pedro Alves
  0 siblings, 1 reply; 31+ messages in thread
From: Danny Backx @ 2009-06-07  9:18 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 487 bytes --]

Hi,

gdbserver doesn't work well yet on WinCE on x86. I'll send more fixes
when they are ready.

This one fixes obtaining the names of DLLs loaded by the inferior. The
patched code also still works on WinCE on ARM.

	Danny

2009-06-07  Danny Backx  <dannybackx@users.sourceforge.net>

	* win32-low.c (get_image_name) : Fix code to obtain DLL names,
	and document that the other code relies on sizeof(WCHAR) == 2.
-- 
Danny Backx ; danny.backx - at - scarlet.be ; http://danny.backx.info

[-- Attachment #2: gdbserver-get_image_name.patch --]
[-- Type: text/x-patch, Size: 2974 bytes --]

*** /home/danny/src/gdb/gdb/gdb-6.8.orig/gdb/gdbserver/win32-low.c	2008-02-14 23:41:39.000000000 +0100
--- win32-low.c	2009-06-07 11:12:30.000000000 +0200
***************
*** 894,907 ****
    loaded_dll (buf2, load_addr);
  }
  
  static char *
  get_image_name (HANDLE h, void *address, int unicode)
  {
!   static char buf[(2 * MAX_PATH) + 1];
    DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
    char *address_ptr;
    int len = 0;
!   char b[2];
    DWORD done;
  
    /* Attempt to read the name of the dll that was detected.
--- 894,912 ----
    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]; /* here */
    DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
    char *address_ptr;
+ #ifndef _WIN32_WCE
    int len = 0;
!   char b[2]; /* here */
! #endif
    DWORD done;
  
    /* Attempt to read the name of the dll that was detected.
***************
*** 924,932 ****
      return NULL;
  #endif
  
    /* 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)
      continue;
  
    if (!unicode)
--- 929,956 ----
      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) /* here */
      continue;
  
    if (!unicode)
***************
*** 936,946 ****
        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;
  }
  
  typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
--- 960,969 ----
        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 *,

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2009-07-27 19:59 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-13 14:29 Patch : gdbserver get_image_name on CE Danny Backx
2009-06-13 18:05 ` Pedro Alves
2009-06-13 18:08   ` Pedro Alves
2009-06-14  8:35     ` Danny Backx
2009-06-14 13:56       ` Pedro Alves
2009-06-14  8:47   ` Danny Backx
2009-06-14  9:48     ` Danny Backx
2009-06-14 14:23       ` Pedro Alves
2009-06-21  9:50         ` Danny Backx
2009-06-30 21:07           ` Danny Backx
2009-06-30 21:56             ` Pedro Alves
2009-07-01 18:41               ` Danny Backx
2009-07-01 18:52                 ` Pedro Alves
2009-07-01 19:12                   ` Danny Backx
2009-07-01 20:12                 ` Pedro Alves
2009-07-04 18:14                   ` Pedro Alves
2009-07-08  9:55                     ` Danny Backx
2009-07-08 11:34                       ` Danny Backx
2009-07-27 20:40                         ` Danny Backx
2009-07-01 19:31               ` Danny Backx
2009-06-14 14:34       ` Pedro Alves
2009-06-14 14:05     ` Pedro Alves
  -- strict thread matches above, loose matches on Subject: below --
2009-06-07  9:18 Danny Backx
2009-06-07 17:03 ` Pedro Alves
2009-06-07 18:02   ` Danny Backx
2009-06-07 18:15     ` Pedro Alves
2009-06-07 19:13       ` Danny Backx
2009-06-07 19:28         ` Pedro Alves
2009-06-08 18:13           ` Danny Backx
2009-06-12 22:18       ` Danny Backx
2009-06-13  6:28         ` Johnny Willemsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox