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: Windows DLL support update.


Christopher Faylor wrote:
On Tue, Aug 14, 2007 at 01:23:28AM +0100, Pedro Alves wrote:
Here is the new version of the patch that converts native win32
debugging to use the new solib-target.c.

I have a few of questions/observations wrt the win32-nat.c changes.



Thanks for such a quick review.


1) Does it still properly handle the "exceptions" that are thrown by
cygwin which must be ignored?  I believe that the most populr source
of complaints about those came from people who were using pthreads
functions.


Yes. I tried with this: http://www.cygwin.com/ml/cygwin/2006-05/msg00650.html

'set cygwin-exceptions 1' shows the SEGV, 'set cygwin-exceptions 0'
doesn't.

2) Is there some reason you didn't record the cygwin load/start address
in win32_make_so?  Isn't all of the information you need available when
that function is called?


I could open a bfd and look for .text like old solib_symbols_add does, but the so_list of the main list will have one open, so we can use that instead. I'll want to move these bits of cygwin detection and exception ignoring into a win32-tdep.c file that can be reused when remote debugging. This is step in that direction, but I'll understand if you still prefer the old way.

3) If the answer to the above question is no, then it seems like
cygwin_load_start and cygwin_load_end should be static variables local
to ignore_access_violation_p.

Storing the cygwin1.dll addresses and reusing it across runs should be ok if we assume that we are always debugging cygwin apps, but it could mask an access exception in a non-cygwin app that happened to occur in a dll loaded in that range by coincidence. I was going to leave it for later, but since you've asked, I'm now clearing the start/end addresses in do_initial_win32_stuff. This shows why they can't be local static.

> I wonder if that logic should even be
> further broken out into its own inside_cygwin(addr) function.

Wonder no more. Done.

4) I'd prefer it if you dropped the _p from "ignore_access_violation".


Done.



I gave it another testsuite spin, and it looks good.


--
Cheers,
Pedro Alves




2007-07-02  Pedro Alves  <pedro_alves@portugalmail.pt>
	    Daniel Jacobowitz  <dan@codesourcery.com>

	* corelow.c (core_xfer_partial): Pass writebuf to
	deprecated_xfer_memory in TARGET_OBJECT_MEMORY case.  Add
	TARGET_OBJECT_LIBRARIES handling.

	* gdb_obstack.h (obstack_grow_str, obstack_grow_str0): New.

	* gdbcore.h: Include target.h.
	(struct core_fns): Add xfer_shared_libraries.

	* infcmd.c (post_create_inferior): Update comment.
	(run_command_1): Always call post_create_inferior with 0 as
	from_tty.

	* win32-nat.c: Include gdb_obstack.h and xml-support.h.
	(win32_so_ops): Delete.
	(get_relocated_section_addrs): Delete.
	(solib_symbols_add): Delete.
	(register_loaded_dll): Delete.
	(win32_make_so): New.
	(handle_load_dll): Use win32_make_so.
	(win32_free_so): Free the passed in so.
	(win32_relocate_section_addresses): Delete.
	(win32_solib_create_inferior_hook): Delete.
	(handle_unload_dll): Don't add PE offset here.  Free so with
	win32_free_so instead of free_so.
	(win32_special_symbol_handling): Delete.
	(inside_cygwin): New.
	(ignore_access_violation_p): New.
	(handle_exception): Use ignore_access_violation_p.
	(get_win32_debug_event): Remove unneeded calls.  Set state to
	TARGET_WAITKIND_LOADED on a dll unload.
	(map_code_section_args): Delete.
	(solib_to_xml): New.
	(dll_code_sections_add): Delete.
	(struct cspm_data): New.
	(core_section_load_dll_symbols): Delete.
	(core_section_process_module): New.
	(win32_current_sos): Delete.
	(win32_core_xfer_shared_libraries): New.
	(win32_xfer_shared_libraries): New.
	(win32_xfer_partial): New.
	(fetch_elf_core_registers): Rename to ...
	(win32_fetch_elf_core_registers): ... this.
	(open_symbol_file_object): Delete.
	(in_dynsym_resolve_code): Delete.
	(init_win32_ops): Set win32_xfer_partial as to_xfer_partial member
	of win32_ops.  Remove win32_so_ops settings.  Don't set
	current_target_so_ops here.
	(win32_elf_core_fn): The fetch_elf_core_registers function was
	renamed to win32_fetch_elf_core_registers - update.  Add
	win32_core_get_shared_libraries.

	* xml-support.c (gdb_xml_parse): Debug tweaks.
	(xml_escape_text): New.
	* xml-support.h (xml_escape_text): Declare.

---
 gdb/corelow.c     |   10 
 gdb/gdb_obstack.h |    5 
 gdb/gdbcore.h     |    9 
 gdb/infcmd.c      |    8 
 gdb/win32-nat.c   |  553 +++++++++++++++++++++---------------------------------
 gdb/xml-support.c |   67 ++++++
 gdb/xml-support.h |   42 ++--
 7 files changed, 341 insertions(+), 353 deletions(-)

Index: src/gdb/corelow.c
===================================================================
--- src.orig/gdb/corelow.c	2007-08-13 22:33:58.000000000 +0100
+++ src/gdb/corelow.c	2007-08-13 22:34:42.000000000 +0100
@@ -526,8 +526,8 @@ core_xfer_partial (struct target_ops *op
 	return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
 					       0/*write*/, NULL, ops);
       if (writebuf)
-	return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
-					       1/*write*/, NULL, ops);
+	return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
+					       len, 1/*write*/, NULL, ops);
       return -1;
 
     case TARGET_OBJECT_AUXV:
@@ -594,6 +594,12 @@ core_xfer_partial (struct target_ops *op
 	}
       return -1;
 
+    case TARGET_OBJECT_LIBRARIES:
+      if (core_vec->xfer_shared_libraries != NULL)
+	return core_vec->xfer_shared_libraries (ops, object, annex, readbuf,
+					       writebuf, offset, len);
+      /* FALL THROUGH */
+
     default:
       if (ops->beneath != NULL)
 	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
Index: src/gdb/gdb_obstack.h
===================================================================
--- src.orig/gdb/gdb_obstack.h	2007-08-13 22:33:52.000000000 +0100
+++ src/gdb/gdb_obstack.h	2007-08-13 22:34:10.000000000 +0100
@@ -42,4 +42,9 @@
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free xfree
 
+#define obstack_grow_str(OBSTACK,STRING) \
+  obstack_grow (OBSTACK, STRING, strlen (STRING))
+#define obstack_grow_str0(OBSTACK,STRING) \
+  obstack_grow0 (OBSTACK, STRING, strlen (STRING))
+
 #endif
Index: src/gdb/gdbcore.h
===================================================================
--- src.orig/gdb/gdbcore.h	2007-08-13 22:33:52.000000000 +0100
+++ src/gdb/gdbcore.h	2007-08-13 22:34:10.000000000 +0100
@@ -29,6 +29,7 @@ struct type;
 struct regcache;
 
 #include "bfd.h"
+#include "target.h"
 
 /* Return the name of the executable file as a string.
    ERR nonzero means get error if there is none specified;
@@ -193,6 +194,14 @@ struct core_fns
 				 unsigned core_reg_size,
 				 int which, CORE_ADDR reg_addr);
 
+    /* Refresh the list of shared libraries.  */
+    LONGEST (*xfer_shared_libraries) (struct target_ops *ops,
+				      enum target_object object,
+				      const char *annex,
+				      gdb_byte *readbuf,
+				      const gdb_byte *writebuf,
+				      ULONGEST offset, LONGEST len);
+
     /* Finds the next struct core_fns.  They are allocated and
        initialized in whatever module implements the functions pointed
        to; an initializer calls deprecated_add_core_fns to add them to
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c	2007-08-13 22:33:52.000000000 +0100
+++ src/gdb/infcmd.c	2007-08-13 22:34:10.000000000 +0100
@@ -419,7 +419,9 @@ post_create_inferior (struct target_ops 
     {
       /* Sometimes the platform-specific hook loads initial shared
 	 libraries, and sometimes it doesn't.  Try to do so first, so
-	 that we can add them with the correct value for FROM_TTY.  */
+	 that we can add them with the correct value for FROM_TTY.
+	 If we made all the inferior hook methods consistent,
+	 this call could be removed.  */
 #ifdef SOLIB_ADD
       SOLIB_ADD (NULL, from_tty, target, auto_solib_add);
 #else
@@ -560,7 +562,9 @@ run_command_1 (char *args, int from_tty,
   target_create_inferior (exec_file, get_inferior_args (),
 			  environ_vector (inferior_environ), from_tty);
 
-  post_create_inferior (&current_target, from_tty);
+  /* Pass zero for FROM_TTY, because at this point the "run" command
+     has done its thing; now we are setting up the running program.  */
+  post_create_inferior (&current_target, 0);
 
   /* Start the target running.  */
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
Index: src/gdb/win32-nat.c
===================================================================
--- src.orig/gdb/win32-nat.c	2007-08-13 22:33:52.000000000 +0100
+++ src/gdb/win32-nat.c	2007-08-16 01:08:48.000000000 +0100
@@ -48,6 +48,7 @@
 #include "buildsym.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "gdb_obstack.h"
 #include "gdb_string.h"
 #include "gdbthread.h"
 #include "gdbcmd.h"
@@ -56,12 +57,12 @@
 #include "exec.h"
 #include "solist.h"
 #include "solib.h"
+#include "xml-support.h"
 
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
 static struct target_ops win32_ops;
-static struct target_so_ops win32_so_ops;
 
 /* The starting and ending address of the cygwin1.dll text segment. */
 static bfd_vma cygwin_load_start;
@@ -600,123 +601,8 @@ safe_symbol_file_add (char *name, int fr
   return p.ret;
 }
 
-/* Get the loaded address of all sections, given that .text was loaded
-   at text_load. Assumes that all sections are subject to the same
-   relocation offset. Returns NULL if problems occur or if the
-   sections were not relocated. */
-
-static struct section_addr_info *
-get_relocated_section_addrs (bfd *abfd, CORE_ADDR text_load)
-{
-  struct section_addr_info *result = NULL;
-  int section_count = bfd_count_sections (abfd);
-  asection *text_section = bfd_get_section_by_name (abfd, ".text");
-  CORE_ADDR text_vma;
-
-  if (!text_section)
-    {
-      /* Couldn't get the .text section. Weird. */
-    }
-  else if (text_load == (text_vma = bfd_get_section_vma (abfd, text_section)))
-    {
-      /* DLL wasn't relocated. */
-    }
-  else
-    {
-      /* Figure out all sections' loaded addresses. The offset here is
-	 such that taking a bfd_get_section_vma() result and adding
-	 offset will give the real load address of the section. */
-
-      CORE_ADDR offset = text_load - text_vma;
-
-      struct section_table *table_start = NULL;
-      struct section_table *table_end = NULL;
-      struct section_table *iter = NULL;
-
-      build_section_table (abfd, &table_start, &table_end);
-
-      for (iter = table_start; iter < table_end; ++iter)
-	{
-	  /* Relocated addresses. */
-	  iter->addr += offset;
-	  iter->endaddr += offset;
-	}
-
-      result = build_section_addr_info_from_section_table (table_start,
-							   table_end);
-
-      xfree (table_start);
-    }
-
-  return result;
-}
-
-/* Add DLL symbol information. */
-static void
-solib_symbols_add (struct so_list *so, CORE_ADDR load_addr)
-{
-  struct section_addr_info *addrs = NULL;
-  static struct objfile *result = NULL;
-  char *name = so->so_name;
-  bfd *abfd = NULL;
-  char *p;
-
-  /* The symbols in a dll are offset by 0x1000, which is the
-     the offset from 0 of the first byte in an image - because
-     of the file header and the section alignment. */
-
-  if (!name || !name[0])
-    return;
-
-  abfd = bfd_openr (name, "pei-i386");
-
-  if (!abfd)
-    {
-      /* pei failed - try pe */
-      abfd = bfd_openr (name, "pe-i386");
-    }
-
-  if (abfd)
-    {
-      if (bfd_check_format (abfd, bfd_object))
-	addrs = get_relocated_section_addrs (abfd, load_addr);
-    }
-
-  if (addrs)
-    {
-      result = safe_symbol_file_add (name, 0, addrs, 0, OBJF_SHARED);
-      free_section_addr_info (addrs);
-    }
-  else
-    {
-      /* Fallback on handling just the .text section. */
-      struct cleanup *my_cleanups;
-
-      addrs = alloc_section_addr_info (1);
-      my_cleanups = make_cleanup (xfree, addrs);
-      addrs->other[0].name = ".text";
-      addrs->other[0].addr = load_addr;
-
-      result = safe_symbol_file_add (name, 0, addrs, 0, OBJF_SHARED);
-      do_cleanups (my_cleanups);
-    }
-
-  p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
-  if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
-    {
-      asection *text = bfd_get_section_by_name (abfd, ".text");
-      cygwin_load_start = bfd_section_vma (abfd, text);
-      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
-    }
-
-  bfd_close (abfd);
-
-  so->symbols_loaded = !!result;
-  return;
-}
-
-static char *
-register_loaded_dll (const char *name, DWORD load_addr, int readsyms)
+static struct so_list *
+win32_make_so (const char *name, DWORD load_addr)
 {
   struct so_list *so;
   char buf[MAX_PATH + 1];
@@ -725,7 +611,6 @@ register_loaded_dll (const char *name, D
   WIN32_FIND_DATA w32_fd;
   HANDLE h = FindFirstFile(name, &w32_fd);
   MEMORY_BASIC_INFORMATION m;
-  size_t len;
 
   if (h == INVALID_HANDLE_VALUE)
     strcpy (buf, name);
@@ -753,15 +638,9 @@ register_loaded_dll (const char *name, D
   so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
   so->lm_info->load_addr = load_addr;
   cygwin_conv_to_posix_path (buf, so->so_name);
-  strcpy (so->so_original_name, so->so_name);
-
-  solib_end->next = so;
-  solib_end = so;
-  len = strlen (so->so_name);
-  if (readsyms)
-    solib_symbols_add (so, (CORE_ADDR) load_addr);
+  strcpy (so->so_original_name, name);
 
-  return so->so_name;
+  return so;
 }
 
 static char *
@@ -822,11 +701,13 @@ handle_load_dll (void *dummy)
   dll_name = dll_buf;
 
   if (*dll_name == '\0')
-    dll_name = get_image_name (current_process_handle, event->lpImageName, event->fUnicode);
+    dll_name = get_image_name (current_process_handle,
+			       event->lpImageName, event->fUnicode);
   if (!dll_name)
     return 1;
 
-  register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000, auto_solib_add);
+  solib_end->next = win32_make_so (dll_name, (DWORD) event->lpBaseOfDll);
+  solib_end = solib_end->next;
 
   return 1;
 }
@@ -836,27 +717,13 @@ win32_free_so (struct so_list *so)
 {
   if (so->lm_info)
     xfree (so->lm_info);
-}
-
-static void
-win32_relocate_section_addresses (struct so_list *so,
-				  struct section_table *sec)
-{
-  /* FIXME */
-  return;
-}
-
-static void
-win32_solib_create_inferior_hook (void)
-{
-  solib_add (NULL, 0, NULL, auto_solib_add);
-  return;
+  xfree (so);
 }
 
 static int
 handle_unload_dll (void *dummy)
 {
-  DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000;
+  DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
   struct so_list *so;
 
   for (so = &solib_start; so->next != NULL; so = so->next)
@@ -866,7 +733,7 @@ handle_unload_dll (void *dummy)
 	so->next = sodel->next;
 	if (!so->next)
 	  solib_end = so;
-	free_so (sodel);
+	win32_free_so (sodel);
 	solib_add (NULL, 0, NULL, auto_solib_add);
 	return 1;
       }
@@ -884,12 +751,6 @@ win32_clear_solib (void)
   solib_end = &solib_start;
 }
 
-static void
-win32_special_symbol_handling (void)
-{
-  return;
-}
-
 /* Load DLL symbol info. */
 void
 dll_symbol_command (char *args, int from_tty)
@@ -1084,6 +945,67 @@ info_w32_command (char *args, int from_t
   help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout);
 }
 
+/* Returns 1 if ADDR is within the cygwin1.dll text segment, returns 0
+   otherwise.  */
+static int
+inside_cygwin (CORE_ADDR addr)
+{
+  if (cygwin_load_start == 0)
+    {
+      struct so_list *so;
+
+      for (so = master_so_list (); so; so = so->next)
+	{
+	  char *p;
+	  p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
+	  if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
+	    {
+	      asection *text = bfd_get_section_by_name (so->abfd, ".text");
+	      if (text)
+		{
+		  cygwin_load_start = bfd_section_vma (so->abfd, text);
+		  cygwin_load_end = cygwin_load_start
+		    + bfd_section_size (so->abfd, text);
+		}
+	      break;
+	    }
+	}
+    }
+
+  if (cygwin_load_start == 0)
+    return 0;
+
+  return (cygwin_load_start <= addr && addr < cygwin_load_end);
+}
+
+static int
+ignore_access_violation (CORE_ADDR addr)
+{
+  if (!cygwin_exceptions)
+    {
+      /* See if the access violation happened within the cygwin DLL
+	 itself.  Cygwin uses a kind of exception handling to deal
+	 with passed-in invalid addresses. gdb should not treat these
+	 as real SEGVs since they will be silently handled by cygwin.
+	 A real SEGV will (theoretically) be caught by cygwin later in
+	 the process and will be sent as a cygwin-specific-signal.
+	 So, ignore SEGVs if they show up within the text segment of
+	 the DLL itself. */
+      if (inside_cygwin (addr))
+	return 1;
+    }
+
+  {
+    /* The IsBadXxxPtr family of Win32 functions triggers an access
+       violation by design.  */
+    char *fn;
+    if (find_pc_partial_function (addr, &fn, NULL, NULL)
+	&& strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0)
+      return 1;
+  }
+
+  return 0;
+}
 
 #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
   printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \
@@ -1105,20 +1027,10 @@ handle_exception (struct target_waitstat
     case EXCEPTION_ACCESS_VIOLATION:
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      {
-	/* See if the access violation happened within the cygwin DLL itself.  Cygwin uses
-	   a kind of exception handling to deal with passed-in invalid addresses. gdb
-	   should not treat these as real SEGVs since they will be silently handled by
-	   cygwin.  A real SEGV will (theoretically) be caught by cygwin later in the process
-	   and will be sent as a cygwin-specific-signal.  So, ignore SEGVs if they show up
-	   within the text segment of the DLL itself. */
-	char *fn;
-	bfd_vma addr = (bfd_vma) current_event.u.Exception.ExceptionRecord.ExceptionAddress;
-	if ((!cygwin_exceptions && (addr >= cygwin_load_start && addr < cygwin_load_end))
-	    || (find_pc_partial_function (addr, &fn, NULL, NULL)
-		&& strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0))
-	  return 0;
-      }
+      if (ignore_access_violation
+	  ((CORE_ADDR) current_event.u.
+	   Exception.ExceptionRecord.ExceptionAddress))
+	return 0;
       break;
     case STATUS_STACK_OVERFLOW:
       DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
@@ -1457,11 +1369,9 @@ get_win32_debug_event (int pid, struct t
       if (saw_create != 1)
 	break;
       catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
-      registers_changed ();	/* mark all regs invalid */
       ourstatus->kind = TARGET_WAITKIND_LOADED;
       ourstatus->value.integer = 0;
       retval = main_thread_id;
-      re_enable_breakpoints_in_shlibs ();
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
@@ -1472,9 +1382,9 @@ get_win32_debug_event (int pid, struct t
       if (saw_create != 1)
 	break;
       catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
-      registers_changed ();	/* mark all regs invalid */
-      /* ourstatus->kind = TARGET_WAITKIND_UNLOADED;
-	 does not exist yet. */
+      ourstatus->kind = TARGET_WAITKIND_LOADED;
+      ourstatus->value.integer = 0;
+      retval = main_thread_id;
       break;
 
     case EXCEPTION_DEBUG_EVENT:
@@ -1582,6 +1492,7 @@ do_initial_win32_stuff (DWORD pid)
   debug_registers_used = 0;
   for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
     dr[i] = 0;
+  cygwin_load_start = cygwin_load_end = 0;
   current_event.dwProcessId = pid;
   memset (&current_event, 0, sizeof (current_event));
   push_target (&win32_ops);
@@ -2072,140 +1983,82 @@ cygwin_pid_to_str (ptid_t ptid)
   return buf;
 }
 
-typedef struct
-{
-  struct target_ops *target;
-  bfd_vma addr;
-} map_code_section_args;
-
 static void
-map_single_dll_code_section (bfd *abfd, asection *sect, void *obj)
+solib_to_xml (struct so_list *so, struct obstack *obstack)
 {
-  int old;
-  int update_coreops;
-  struct section_table *new_target_sect_ptr;
-
-  map_code_section_args *args = (map_code_section_args *) obj;
-  struct target_ops *target = args->target;
-  if (sect->flags & SEC_CODE)
-    {
-      update_coreops = core_ops.to_sections == target->to_sections;
-
-      if (target->to_sections)
-	{
-	  old = target->to_sections_end - target->to_sections;
-	  target->to_sections = (struct section_table *)
-	    xrealloc ((char *) target->to_sections,
-		      (sizeof (struct section_table)) * (1 + old));
-	}
-      else
-	{
-	  old = 0;
-	  target->to_sections = (struct section_table *)
-	    xmalloc ((sizeof (struct section_table)));
-	}
-      target->to_sections_end = target->to_sections + (1 + old);
-
-      /* Update the to_sections field in the core_ops structure
-	 if needed.  */
-      if (update_coreops)
-	{
-	  core_ops.to_sections = target->to_sections;
-	  core_ops.to_sections_end = target->to_sections_end;
-	}
-      new_target_sect_ptr = target->to_sections + old;
-      new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
-      new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
-	bfd_section_size (abfd, sect);;
-      new_target_sect_ptr->the_bfd_section = sect;
-      new_target_sect_ptr->bfd = abfd;
-    }
+  char *p;
+  obstack_grow_str (obstack, "<library name=\"");
+  p = xml_escape_text (so->so_name);
+  obstack_grow_str (obstack, p);
+  xfree (p);
+  obstack_grow_str (obstack, "\"><segment address=\"0x");
+  /* The symbols in a dll are offset by 0x1000, which is the the
+     offset from 0 of the first byte in an image - because of the file
+     header and the section alignment. */
+  p = paddr_nz (so->lm_info->load_addr + 0x1000);
+  obstack_grow_str (obstack, p);
+  obstack_grow_str (obstack, "\"/></library>");
 }
 
-static int
-dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
+struct cspm_data
 {
-  bfd *dll_bfd;
-  map_code_section_args map_args;
-  asection *lowest_sect;
-  char *name;
-  if (dll_name == NULL || target == NULL)
-    return 0;
-  name = xstrdup (dll_name);
-  dll_bfd = bfd_openr (name, "pei-i386");
-  if (dll_bfd == NULL)
-    return 0;
-
-  if (bfd_check_format (dll_bfd, bfd_object))
-    {
-      lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
-      if (lowest_sect == NULL)
-	return 0;
-      map_args.target = target;
-      map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
-
-      bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
-    }
-
-  return 1;
-}
+  struct target_ops *target;
+  int module_count;
+  struct obstack *obstack;
+};
 
 static void
-core_section_load_dll_symbols (bfd *abfd, asection *sect, void *obj)
+core_section_process_module (bfd *abfd, asection *sect, void *obj)
 {
-  struct target_ops *target = (struct target_ops *) obj;
+  struct cspm_data *data = obj;
 
+  struct win32_pstatus *pstatus;
+  char *module_name;
+  int module_name_offset;
+  int module_name_size;
   DWORD base_addr;
 
-  int dll_name_size;
-  struct win32_pstatus *pstatus;
-  struct so_list *so;
-  char *dll_name;
   char *buf = NULL;
-  char *p;
-  struct objfile *objfile;
-  const char *dll_basename;
 
   if (strncmp (sect->name, ".module", 7) != 0)
     return;
 
-  buf = (char *) xmalloc (bfd_get_section_size (sect) + 1);
+  buf = xmalloc (bfd_get_section_size (sect) + 1);
   if (!buf)
     {
       printf_unfiltered ("memory allocation failed for %s\n", sect->name);
       goto out;
     }
-  if (!bfd_get_section_contents (abfd, sect, buf, 0, bfd_get_section_size (sect)))
+  if (!bfd_get_section_contents (abfd, sect,
+				 buf, 0, bfd_get_section_size (sect)))
     goto out;
 
   pstatus = (struct win32_pstatus *) buf;
 
-  memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
-  dll_name_size = pstatus->data.module_info.module_name_size;
-  if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > bfd_get_section_size (sect))
-      goto out;
-
-  dll_name = pstatus->data.module_info.module_name;
-
-  if (!(dll_basename = strrchr (dll_name, '/')))
-    dll_basename = dll_name;
-  else
-    dll_basename++;
-
-  ALL_OBJFILES (objfile)
-  {
-    char *objfile_basename = strrchr (objfile->name, '/');
+  memcpy (&base_addr, &pstatus->data.module_info.base_address,
+	  sizeof (base_addr));
 
-    if (objfile_basename &&
-	strcasecmp (dll_basename, objfile_basename + 1) == 0)
+  module_name_size = pstatus->data.module_info.module_name_size;
+  module_name = pstatus->data.module_info.module_name;
+  if (module_name - buf + module_name_size > bfd_get_section_size (sect))
       goto out;
-  }
-
-  base_addr += 0x1000;
-  dll_name = register_loaded_dll (dll_name, base_addr, 1);
 
-  if (!dll_code_sections_add (dll_name, (DWORD) base_addr, target))
-    printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
+  if (data->module_count == 0)
+    {
+#if 0
+      /* TODO: What if the user supplied exec and/or
+	 symbol files on the command line?  */
+      /* The first module is the .exe itself.  */
+      symbol_file_add_main (module_name, 0);
+#endif
+    }
+  else
+    {
+      struct so_list *so = win32_make_so (module_name, base_addr);
+      solib_to_xml (so, data->obstack);
+      win32_free_so (so);
+    }
+  data->module_count++;
 
 out:
   if (buf)
@@ -2213,39 +2066,103 @@ out:
   return;
 }
 
-static struct so_list *
-win32_current_sos (void)
-{
-  struct so_list *sop;
-  struct so_list *start = NULL;
-  struct so_list *last = NULL;
+static LONGEST
+win32_core_xfer_shared_libraries (struct target_ops *ops,
+				  enum target_object object, const char *annex,
+				  gdb_byte *readbuf, const gdb_byte *writebuf,
+				  ULONGEST offset, LONGEST len)
+{
+  struct obstack obstack;
+  const char *buf;
+  LONGEST len_avail;
+  struct cspm_data data = { ops, 0, &obstack };
+
+  if (writebuf)
+    return -1;
+
+  obstack_init (&obstack);
+  obstack_grow_str (&obstack, "<library-list>\n");
+  bfd_map_over_sections (core_bfd,
+			 &core_section_process_module,
+			 &data);
+  obstack_grow_str0 (&obstack, "</library-list>\n");
+
+  buf = obstack_finish (&obstack);
+  len_avail = strlen (buf);
+  if (offset >= len_avail)
+    return 0;
 
-  if (!solib_start.next && core_bfd)
-    {
-      win32_clear_solib ();
-      bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols,
-			     &win32_ops);
-    }
+  if (len > len_avail - offset)
+    len = len_avail - offset;
+  memcpy (readbuf, buf + offset, len);
+
+  obstack_free (&obstack, NULL);
+  return len;
+}
+
+static LONGEST
+win32_xfer_shared_libraries (struct target_ops *ops,
+			     enum target_object object, const char *annex,
+			     gdb_byte *readbuf, const gdb_byte *writebuf,
+			     ULONGEST offset, LONGEST len)
+{
+  struct obstack obstack;
+  const char *buf;
+  LONGEST len_avail;
+  struct so_list *so;
 
-  for (sop = solib_start.next; sop; sop = sop->next)
-    {
-      struct so_list *new = XZALLOC (struct so_list);
-      strcpy (new->so_name, sop->so_name);
-      strcpy (new->so_original_name, sop->so_original_name);
-      if (!start)
-	last = start = new;
-      else
-	{
-	  last->next = new;
-	  last = new;
-	}
-    }
+  if (writebuf)
+    return -1;
+
+  obstack_init (&obstack);
+  obstack_grow_str (&obstack, "<library-list>\n");
+  for (so = solib_start.next; so; so = so->next)
+    solib_to_xml (so, &obstack);
+  obstack_grow_str0 (&obstack, "</library-list>\n");
+
+  buf = obstack_finish (&obstack);
+  len_avail = strlen (buf);
+  if (offset >= len_avail)
+    return 0;
 
-  return start;
+  if (len > len_avail - offset)
+    len = len_avail - offset;
+  memcpy (readbuf, buf + offset, len);
+
+  obstack_free (&obstack, NULL);
+  return len;
+}
+
+static LONGEST
+win32_xfer_partial (struct target_ops *ops, enum target_object object,
+		    const char *annex, gdb_byte *readbuf,
+		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+  switch (object)
+    {
+    case TARGET_OBJECT_MEMORY:
+      if (readbuf)
+	return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
+					       0/*write*/, NULL, ops);
+      if (writebuf)
+	return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
+					       len, 1/*write*/, NULL, ops);
+      return -1;
+
+    case TARGET_OBJECT_LIBRARIES:
+      return win32_xfer_shared_libraries (ops, object, annex, readbuf,
+					  writebuf, offset, len);
+
+    default:
+      if (ops->beneath != NULL)
+	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+					      readbuf, writebuf, offset, len);
+      return -1;
+    }
 }
 
 static void
-fetch_elf_core_registers (struct regcache *regcache,
+win32_fetch_elf_core_registers (struct regcache *regcache,
 			  char *core_reg_sect,
 			  unsigned core_reg_size,
 			  int which,
@@ -2261,18 +2178,6 @@ fetch_elf_core_registers (struct regcach
     regcache_raw_supply (regcache, r, core_reg_sect + mappings[r]);
 }
 
-static int
-open_symbol_file_object (void *from_ttyp)
-{
-  return 0;
-}
-
-static int
-in_dynsym_resolve_code (CORE_ADDR pc)
-{
-  return 0;
-}
-
 static void
 init_win32_ops (void)
 {
@@ -2289,6 +2194,7 @@ init_win32_ops (void)
   win32_ops.to_store_registers = win32_store_inferior_registers;
   win32_ops.to_prepare_to_store = win32_prepare_to_store;
   win32_ops.deprecated_xfer_memory = win32_xfer_memory;
+  win32_ops.to_xfer_partial = win32_xfer_partial;
   win32_ops.to_files_info = win32_files_info;
   win32_ops.to_insert_breakpoint = memory_insert_breakpoint;
   win32_ops.to_remove_breakpoint = memory_remove_breakpoint;
@@ -2313,18 +2219,6 @@ init_win32_ops (void)
   win32_ops.to_has_execution = 1;
   win32_ops.to_magic = OPS_MAGIC;
   win32_ops.to_pid_to_exec_file = win32_pid_to_exec_file;
-
-  win32_so_ops.relocate_section_addresses = win32_relocate_section_addresses;
-  win32_so_ops.free_so = win32_free_so;
-  win32_so_ops.clear_solib = win32_clear_solib;
-  win32_so_ops.solib_create_inferior_hook = win32_solib_create_inferior_hook;
-  win32_so_ops.special_symbol_handling = win32_special_symbol_handling;
-  win32_so_ops.current_sos = win32_current_sos;
-  win32_so_ops.open_symbol_file_object = open_symbol_file_object;
-  win32_so_ops.in_dynsym_resolve_code = in_dynsym_resolve_code;
-
-  /* FIXME: Don't do this here.  *_gdbarch_init() should set so_ops. */
-  current_target_so_ops = &win32_so_ops;
 }
 
 static void
@@ -2467,7 +2361,8 @@ static struct core_fns win32_elf_core_fn
   bfd_target_elf_flavour,
   default_check_format,
   default_core_sniffer,
-  fetch_elf_core_registers,
+  win32_fetch_elf_core_registers,
+  win32_core_xfer_shared_libraries,
   NULL
 };
 
Index: src/gdb/xml-support.c
===================================================================
--- src.orig/gdb/xml-support.c	2007-08-13 22:33:52.000000000 +0100
+++ src/gdb/xml-support.c	2007-08-13 22:34:10.000000000 +0100
@@ -546,6 +546,8 @@ gdb_xml_parse (struct gdb_xml_parser *pa
   enum XML_Status status;
   const char *error_string;
 
+  gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
+
   status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
 
   if (status == XML_STATUS_OK && parser->error.reason == 0)
@@ -871,8 +873,7 @@ xml_process_xincludes (const char *name,
       result = xstrdup (obstack_finish (&data->obstack));
 
       if (depth == 0)
-	gdb_xml_debug (parser, _("XInclude processing succeeded:\n%s"),
-		       result);
+	gdb_xml_debug (parser, _("XInclude processing succeeded."));
     }
   else
     result = NULL;
@@ -936,6 +937,68 @@ show_debug_xml (struct ui_file *file, in
   fprintf_filtered (file, _("XML debugging is %s.\n"), value);
 }
 
+/* Return a malloc allocated string with special characters from TEXT
+   replaced by entity references.  */
+
+char *
+xml_escape_text (const char *text)
+{
+  char *result;
+  int i, special;
+
+  /* Compute the length of the result.  */
+  for (i = 0, special = 0; text[i] != '\0'; i++)
+    switch (text[i])
+      {
+      case '\'':
+      case '\"':
+	special += 5;
+	break;
+      case '&':
+	special += 4;
+	break;
+      case '<':
+      case '>':
+	special += 3;
+	break;
+      default:
+	break;
+      }
+
+  /* Expand the result.  */
+  result = xmalloc (i + special + 1);
+  for (i = 0, special = 0; text[i] != '\0'; i++)
+    switch (text[i])
+      {
+      case '\'':
+	strcpy (result + i + special, "&apos;");
+	special += 5;
+	break;
+      case '\"':
+	strcpy (result + i + special, "&quot;");
+	special += 5;
+	break;
+      case '&':
+	strcpy (result + i + special, "&amp;");
+	special += 4;
+	break;
+      case '<':
+	strcpy (result + i + special, "&lt;");
+	special += 3;
+	break;
+      case '>':
+	strcpy (result + i + special, "&gt;");
+	special += 3;
+	break;
+      default:
+	result[i + special] = text[i];
+	break;
+      }
+  result[i + special] = '\0';
+
+  return result;
+}
+
 void _initialize_xml_support (void);
 
 void
Index: src/gdb/xml-support.h
===================================================================
--- src.orig/gdb/xml-support.h	2007-08-13 22:33:52.000000000 +0100
+++ src/gdb/xml-support.h	2007-08-13 22:34:10.000000000 +0100
@@ -30,24 +30,6 @@ struct gdb_xml_parser;
 struct gdb_xml_element;
 struct gdb_xml_attribute;
 
-/* Support for XInclude.  */
-
-/* Callback to fetch a new XML file, based on the provided HREF.  */
-
-typedef char *(*xml_fetch_another) (const char *href, void *baton);
-
-/* Return a new string which is the expansion of TEXT after processing
-   <xi:include> tags.  FETCHER will be called (with FETCHER_BATON) to
-   retrieve any new files.  DEPTH should be zero on the initial call.
-
-   On failure, this function uses NAME in a warning and returns NULL.
-   It may throw an exception, but does not for XML parsing
-   problems.  */
-
-char *xml_process_xincludes (const char *name, const char *text,
-			     xml_fetch_another fetcher, void *fetcher_baton,
-			     int depth);
-
 /* Return an XML document which was compiled into GDB, from
    the given FILENAME, or NULL if the file was not compiled in.  */
 
@@ -64,8 +46,32 @@ LONGEST xml_builtin_xfer_partial (const 
 
 /* The text of compiled-in XML documents, from xml-builtin.c
    (generated).  */
+
 extern const char *xml_builtin[][2];
 
+/* Return a malloc allocated string with special characters from TEXT
+   replaced by entity references.  */
+
+char *xml_escape_text (const char *text);
+
+/* Support for XInclude.  */
+
+/* Callback to fetch a new XML file, based on the provided HREF.  */
+
+typedef char *(*xml_fetch_another) (const char *href, void *baton);
+
+/* Return a new string which is the expansion of TEXT after processing
+   <xi:include> tags.  FETCHER will be called (with FETCHER_BATON) to
+   retrieve any new files.  DEPTH should be zero on the initial call.
+
+   On failure, this function uses NAME in a warning and returns NULL.
+   It may throw an exception, but does not for XML parsing
+   problems.  */
+
+char *xml_process_xincludes (const char *name, const char *text,
+			     xml_fetch_another fetcher, void *fetcher_baton,
+			     int depth);
+
 /* Simplified XML parser infrastructure.  */
 
 /* A name and value pair, used to record parsed attributes.  */




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