Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Danny Backx <danny.backx@scarlet.be>
To: gdb-patches@sourceware.org
Subject: Re: Patch : gdbserver get_image_name on CE
Date: Sat, 13 Jun 2009 14:29:00 -0000	[thread overview]
Message-ID: <1244903385.20290.9.camel@pavilion> (raw)

[-- 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:

             reply	other threads:[~2009-06-13 14:29 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-13 14:29 Danny Backx [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1244903385.20290.9.camel@pavilion \
    --to=danny.backx@scarlet.be \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox