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]

[RFC,v2] Yank out target_ops->to_sections


[ Following up on: http://sourceware.org/ml/gdb-patches/2009-05/msg00499.html ]

I've taken yet another step back, and I think I found
the correct abstraction now.

I'll start with the same examples that helped see things clearer:

current GDB:

 >gdb ./testsuite/gdb.base/break
 :
 (gdb) info files
 Symbols from "/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break".
 Local exec file:
         `/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break', file type elf64-x86-64.
         Entry point: 0x400550   0x0000000000400200 - 0x000000000040021c is .interp
         0x000000000040021c - 0x000000000040023c is .note.ABI-tag
         0x0000000000400240 - 0x0000000000400278 is .hash
 :
         0x0000000000600cf8 - 0x0000000000600d10 is .data
         0x0000000000600d20 - 0x0000000000600ed0 is .bss
 
 (gdb) start
 Breakpoint 1 at 0x40061b: file ../../../src/gdb/testsuite/gdb.base/break.c, line 86.
 Starting program: /home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break
 main (argc=1, argv=0x7fff8360e9e8, envp=0x7fff8360e9f8) at ../../../src/gdb/testsuite/gdb.base/break.c:86
 86          if (argc == 12345) {  /* an unlikely value < 2^16, in case uninited */ /* set breakpoint 6 here */
 (gdb) info files
 Symbols from "/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break".
 Unix child process:
         Using the running image of child process 13526.
         While running this, GDB does not access memory from...
 Local exec file:
         `/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break', file type elf64-x86-64.
         Entry point: 0x400550   0x0000000000400200 - 0x000000000040021c is .interp
         0x000000000040021c - 0x000000000040023c is .note.ABI-tag
 :
         0x0000000000600cf8 - 0x0000000000600d10 is .data
         0x0000000000600d20 - 0x0000000000600ed0 is .bss
         0x00007ff17b3f1190 - 0x00007ff17b3f124c is .hash in /lib64/ld-linux-x86-64.so.2
 :
         0x00007ff17b16a060 - 0x00007ff17b16ad98 is .data in /lib/libc.so.6
         0x00007ff17b16ada0 - 0x00007ff17b16f278 is .bss in /lib/libc.so.6
 (gdb)  

The issue to notice here, is where the sections of shared library bfds show up.  Through
target_ops->to_section|to_section_end inheritance in update_current_target, and
a gross hack in target_resize_to_sections, the current_target ends up using the same
target sections as the exec target.  Then, when solib_add is passed a
pointer to current_target, it adds the shared library sections to the exec_ops set
of target sections.  The way this happens is a bit convoluted, but, I believe the result
ends up being correct.  Those target sections represent pure memory, untainted bfd files
on the host, that are a special form of "executables" (well, without entry
point, usually).

But now, notice this:

 (gdb) gcore core1
 Saved corefile core1

Starting afresh:

 >gdb ./testsuite/gdb.base/break -c ./core1
 (gdb) info files
 Symbols from "/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break".
 Local core dump file:
         `/home/pedro/gdb/mainline/build/gdb/./core1', file type elf64-x86-64.
         0x0000000000400000 - 0x0000000000400000 is load1
 :
         0xffffffffff600000 - 0xffffffffff601000 is load15
         0x00007f52ebc8f238 - 0x00007f52ebc8f258 is .note.ABI-tag in /lib/libm.so.6
 :
         0x00007f52ebd09610 - 0x00007f52ebd0962c is .interp in /lib/libm.so.6
 :
         0x00007f52ec12eb20 - 0x00007f52ec12eca8 is .bss in /lib64/ld-linux-x86-64.so.2
 Local exec file:
         `/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break', file type elf64-x86-64.
         Entry point: 0x400550   0x0000000000400200 - 0x000000000040021c is .interp
         0x000000000040021c - 0x000000000040023c is .note.ABI-tag
 :
         0x0000000000600d20 - 0x0000000000600ed0 is .bss
 (gdb) 

Huh, the shared library sections are now associated with a different
target layer.  This is wrong for consistency.  It isn't the same
representation we had when the process was "alive".  If you try
combinations of "live debugging" -> "core" -> "file", you manage to
put sections in different layers.

Here's another bad example, one that I mentioned in the other email (v1):

 >gdb ./testsuite/gdb.base/break
 (gdb) start
 :
 (gdb) nosharedlibrary
 (gdb) sharedlibrary
 Reading symbols from /lib/libm.so.6...Reading symbols from /usr/lib/debug/lib/libm-2.7.so...done.
 done.
 Loaded symbols for /lib/libm.so.6
 Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.7.so...done.
 done.
 Loaded symbols for /lib/libc.so.6
 Reading symbols from /lib/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.7.so...done.
 done.
 Loaded symbols for /lib64/ld-linux-x86-64.so.2
 (gdb) info files
 Symbols from "/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break".
 Unix child process:
         Using the running image of child process 14828.
         While running this, GDB does not access memory from...
 Local exec file:
         `/home/pedro/gdb/mainline/build/gdb/testsuite/gdb.base/break', file type elf64-x86-64.
         Entry point: 0x400550   0x0000000000400200 - 0x000000000040021c is .interp
         0x000000000040021c - 0x000000000040023c is .note.ABI-tag
 :
         0x0000000000600d20 - 0x0000000000600ed0 is .bss
 (gdb) 
 
The shared library sections aren't present!  This was because "sharedlibrary" passes
a NULL target_ops pointer to solib_add.  This breaks e.g, setting breakpoints in
shared libraries when "trust-readonly-sections" is set, because prologue
skipping will fail to read memory.

Now, one realisation here, is that core target sections are a different
kind of object from bfd sections of the main executable or shared libraries.  The
former, is nothing else but an implementation detail of the
core target.  We read the "dead" inferior's memory from those magic
bfd sections, but, that's just the same kind of implementation
detail to the rest of GDB, as the fact that we use ptrace to read memory from
a live inferior.  The main executable and shared library section's however,
serve as a "cache" or pure memory version of what the inferior
is *supposed* to be executing, and conceptually, it what that stratum below
the core or process layers manipulate.  If I set "set trust-readonly-sections" to
true, I expect those to be read from, but not the core file's read only
sections (if it contained any).

This leads me to the design of the patch below.  It adds a new global:

 * The target sections (of the current address space) of the current
   inferior.  */
 struct target_section_table *current_target_sections;

... that holds the sections of the main executable, and of the
loaded shared libraries.  Both the solib.c module and the exec.c target
take care of inserting and removing to/from this table.  Obviously, this
global has to be swapped somehow when we add support for
multiple inferiors/executables, but that is not the important
detail at this point.

As I alluded to a bit above, the core_ops.to_sections sections however,
are *not*  to be placed in this set of "pure memory" set of sections.
Instead, they're placed on a private per-core table, managed by
the corelow.c target.  Unfortunately, rs6000-nat.c hasn't been converted
to the solib.c framework, so that target needs to break the
encapsulation.  This will surely go away when the rs6000-nat.c target
is cleaned up.  Note that with this the "info files" still shows
the core sections, as before.  The only difference is that
the shared library sections will be shown by the exec target, just
like when doing live debugging.

Now, once we're convinced of the above, several changes can
be made: 

- First, all reads from pure bfd memory contents are served
through the section_table_xfer_memory_partial interface  This
replaced the old xfer_memory (which implemented the
deprecated_xfer_memory interface).  xfer_memory is eliminated in
the process.

- "trust-readonly-sections" becomes more reliable,
and behaves the same for all targets, in all ocasions, as it is
now made to always access the whole set of "current_target_sections"
of "pure memory".

- shared library sections are not lost anymore by
  update_current_target, or by "nosharedlibrary -> sharedlibrary".

- The old target_resize_to_sections needed to delve into
  all targets in the stack, plus the current_target, to do an
  ugly update of to_sections.  It no longer needs to do that, as
  to_sections are gone.

- Again, I've moved the whole handling of unmmaped overlay
  sections to memory_xfer_partial.  There used to be a bit of it in xfer_memory.
  It's now centralized, and, the memory reads are now always
  really dispatched to read directly from files --- previously, they could
  go to the core layer first (don't know if there's any target that
  mixes core debugging with overlays, but if there is, I believe
  this change is correct).

- The bfd-target.c is used by the frv target, by reading memory through
  get_target_memory_unsigned, and that ends up going to memory_xfer_partial.
  But, this is a bit broken --- if we're reading from an alternative, non-current
  bfd target, neither the overlay support, neither the dcache should apply.
  This is fixed by making get_target_memory request a
  TARGET_OBJECT_RAW_MEMORY, instead of the cooked TARGET_OBJECT_MEMORY.


Compared to the previous patch, I've in addition dropped the changes
to solib_add's interface --- it was only adding noise.  The target_ops
argument becomes unused, but that can be mechanically cleaned
up afterwards.

I've tested this on x86_64-linux, native and remote, without
regressions.

Opinions?  Comments?  All in all, I'm much happier with this now.

-- 
Pedro Alves

2009-05-24  Pedro Alves  <pedro@codesourcery.com>

	* target.c: Include "exec.h".
	(update_current_target): Don't inherit to_sections or
	to_sections_end.
	(target_get_section_table): New.
	(target_section_by_addr): Fetch the section table from the passed
	in target.
	(memory_xfer_partial): Handle unmapped overlay sections before
	anything else.  Get the overlay mapped address here.  Adjust to
	use section_table_xfer_memory_partial.
	(get_target_memory): Reques a TARGET_OBJECT_RAW_MEMORY object
	instead of TARGET_OBJECT_MEMORY.
	(current_target_sections_1): New global.
	(current_target_sections): New global.
	(target_resize_to_sections): Delete.
	(remove_target_sections): Adjust to remove target sections from
	`current_target_sections', and use resize_section_table.
	* target.h (struct target_ops) <to_sections, to_sections_end>:
	Remove fields.
	<to_get_section_table>: New method.
	(xfer_memory, print_section_info): Delete declarations.
	(struct target_section_table): New type.
	(current_target_sections): Declare.
	(target_get_section_table): Declare.
	(target_resize_to_sections): Delete declaration.
	* bfd-target.c (target_bfd_xfer_partial): Get the section table
	from to_data.
	(target_bfd_get_section_table): New.
	(target_bfd_xclose): Adjust.
	(target_bfd_reopen): Store the section table in the to_data field.
	* corelow.c (core_data): New.
	(core_close): Adjust to release core_data and its sections.
	(core_open): Allocate core_data, and build its target sections
	table.
	(deprecated_core_resize_section_table): New.
	(core_files_info): Pass core_data to print_section_info.
	(core_xfer_partial): Adjust to use
	section_table_xfer_memory_partial for TARGET_OBJECT_MEMORY xfers.
	(init_core_ops): Do not install a deprecated_xfer_memory callback
	anymore.
	* solib.c (update_solib_list): Append the shared library sections
	in the current target sections table.
	* exec.c (exec_close): Remove the exec_bfd's sections from the
	current target sections table.  Adjust to not use to_sections.
	(exec_file_attach): Adjust to not use to_sections.  Append
	exec_bfd's sections in the current target sections table.
	(resize_section_table): New.
	(concat_section_table): New.
	(section_table_xfer_memory): Adjust to implement the xfer_partial
	interface, and rename to...
	(section_table_xfer_memory_partial): ... this, replacing the
	current function of that same name.
	(exec_xfer_partial): New.
	(xfer_memory): Delete.
	(print_section_info): Replace the target_ops parameter by a
	target_section_table parameter.
	(exec_files_info, set_section_command, exec_set_section_address):
	Adjust to use the current target sections table.
	(init_exec_ops): Do not register a deprecated_xfer_memory
	callback.  Register a to_xfer_partial callback.
	* infrun.c (handle_inferior_event): Update comments around
	solib_add.
	* rs6000-nat.c (xcoff_relocate_core): Adjust to use
	deprecated_core_resize_section_table.
	* exec.h (resize_section_table): Declare.
	(section_table_xfer_memory_partial): Add const char * argument.
	(concat_section_table): Declare.
	(print_section_info): Declare here.
	* gdbcore.h (deprecated_core_resize_section_table): Declare.

---
 gdb/bfd-target.c |   37 ++++++++---
 gdb/corelow.c    |   56 +++++++++++-----
 gdb/exec.c       |  178 +++++++++++++++++++++++++----------------------------
 gdb/exec.h       |   23 ++++++
 gdb/gdbcore.h    |    2 
 gdb/infrun.c     |   18 -----
 gdb/rs6000-nat.c |    3 
 gdb/solib.c      |   21 +-----
 gdb/target.c     |  183 +++++++++++++++++++++++++------------------------------
 gdb/target.h     |   39 ++++++-----
 10 files changed, 290 insertions(+), 270 deletions(-)

Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/target.c	2009-05-24 00:14:23.000000000 +0100
@@ -41,6 +41,7 @@
 #include "target-descriptions.h"
 #include "gdbthread.h"
 #include "solib.h"
+#include "exec.h"
 
 static void target_info (char *, int);
 
@@ -491,8 +492,6 @@ update_current_target (void)
       INHERIT (to_has_registers, t);
       INHERIT (to_has_execution, t);
       INHERIT (to_has_thread_control, t);
-      INHERIT (to_sections, t);
-      INHERIT (to_sections_end, t);
       INHERIT (to_can_async_p, t);
       INHERIT (to_is_async_p, t);
       INHERIT (to_async, t);
@@ -1016,14 +1015,37 @@ done:
   return nbytes_read;
 }
 
+struct target_section_table *
+target_get_section_table (struct target_ops *target)
+{
+  struct target_ops *t;
+
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog, "target_get_section_table ()\n");
+
+  for (t = target; t != NULL; t = t->beneath)
+    if (t->to_get_section_table != NULL)
+      return (*t->to_get_section_table) (t);
+
+  /* Most targets will want to get at the target sections mapped into
+     the current address space of the current inferior.  Those that do
+     not want such fallback, will install a to_get_section_table
+     callback.  One example is bfd-target.c.  */
+  return current_target_sections;
+}
+
 /* Find a section containing ADDR.  */
+
 struct target_section *
-target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
+target_section_by_addr (struct target_ops *ops, CORE_ADDR addr)
 {
+  struct target_section_table *table = target_get_section_table (ops);
   struct target_section *secp;
-  for (secp = target->to_sections;
-       secp < target->to_sections_end;
-       secp++)
+
+  if (table == NULL)
+    return NULL;
+
+  for (secp = table->sections; secp < table->sections_end; secp++)
     {
       if (addr >= secp->addr && addr < secp->endaddr)
 	return secp;
@@ -1046,24 +1068,40 @@ memory_xfer_partial (struct target_ops *
   if (len == 0)
     return 0;
 
-  /* Try the executable file, if "trust-readonly-sections" is set.  */
+  /* For accesses to unmapped overlay sections, read directly from
+     files.  Must do this first, as MEMADDR may need adjustment.  */
+  if (readbuf != NULL && overlay_debugging)
+    {
+      struct obj_section *section = find_pc_overlay (memaddr);
+      if (pc_in_unmapped_range (memaddr, section))
+	{
+	  struct target_section_table *table
+	    = target_get_section_table (ops);
+	  const char *section_name = section->the_bfd_section->name;
+	  memaddr = overlay_mapped_address (memaddr, section);
+	  return section_table_xfer_memory_partial (readbuf, writebuf,
+						    memaddr, len,
+						    table->sections,
+						    table->sections_end,
+						    section_name);
+	}
+    }
+
+  /* Try the executable files, if "trust-readonly-sections" is set.  */
   if (readbuf != NULL && trust_readonly)
     {
       struct target_section *secp;
-
+      struct target_section_table *table
+	= target_get_section_table (ops);
       secp = target_section_by_addr (ops, memaddr);
       if (secp != NULL
 	  && (bfd_get_section_flags (secp->bfd, secp->the_bfd_section)
 	      & SEC_READONLY))
-	return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
-    }
-
-  /* Likewise for accesses to unmapped overlay sections.  */
-  if (readbuf != NULL && overlay_debugging)
-    {
-      struct obj_section *section = find_pc_overlay (memaddr);
-      if (pc_in_unmapped_range (memaddr, section))
-	return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
+	return section_table_xfer_memory_partial (readbuf, writebuf,
+						  memaddr, len,
+						  table->sections,
+						  table->sections_end,
+						  NULL);
     }
 
   /* Try GDB's internal data cache.  */
@@ -1688,7 +1726,11 @@ void
 get_target_memory (struct target_ops *ops, CORE_ADDR addr, gdb_byte *buf,
 		   LONGEST len)
 {
-  if (target_read (ops, TARGET_OBJECT_MEMORY, NULL, buf, addr, len)
+  /* This method is used to read from an alternate, non-current
+     target.  This read must bypass the overlay support (as symbols
+     don't match this target), and GDB's internal cache (wrong cache
+     for this target).  */
+  if (target_read (ops, TARGET_OBJECT_RAW_MEMORY, NULL, buf, addr, len)
       != len)
     memory_error (EIO, addr);
 }
@@ -2338,95 +2380,38 @@ return_minus_one (void)
   return -1;
 }
 
-/*
- * Resize the to_sections pointer.  Also make sure that anyone that
- * was holding on to an old value of it gets updated.
- * Returns the old size.
- */
+/* GDB currently only supports a single symbol/address space for the
+   whole debug session.  When that limitation is lifted, this global
+   goes away.  */
+static struct target_section_table current_target_sections_1;
+
+/* The target sections (of the current address space) of the current
+   inferior.  */
+struct target_section_table *current_target_sections = &current_target_sections_1;
 
-int
-target_resize_to_sections (struct target_ops *target, int num_added)
-{
-  struct target_ops **t;
-  struct target_section *old_value;
-  int old_count;
-
-  old_value = target->to_sections;
-
-  if (target->to_sections)
-    {
-      old_count = target->to_sections_end - target->to_sections;
-      target->to_sections = (struct target_section *)
-	xrealloc ((char *) target->to_sections,
-		  (sizeof (struct target_section)) * (num_added + old_count));
-    }
-  else
-    {
-      old_count = 0;
-      target->to_sections = (struct target_section *)
-	xmalloc ((sizeof (struct target_section)) * num_added);
-    }
-  target->to_sections_end = target->to_sections + (num_added + old_count);
+/* Remove all target sections taken from ABFD.  */
 
-  /* Check to see if anyone else was pointing to this structure.
-     If old_value was null, then no one was. */
-
-  if (old_value)
-    {
-      for (t = target_structs; t < target_structs + target_struct_size;
-	   ++t)
-	{
-	  if ((*t)->to_sections == old_value)
-	    {
-	      (*t)->to_sections = target->to_sections;
-	      (*t)->to_sections_end = target->to_sections_end;
-	    }
-	}
-      /* There is a flattened view of the target stack in current_target,
-	 so its to_sections pointer might also need updating. */
-      if (current_target.to_sections == old_value)
-	{
-	  current_target.to_sections = target->to_sections;
-	  current_target.to_sections_end = target->to_sections_end;
-	}
-    }
-
-  return old_count;
-
-}
-
-/* Remove all target sections taken from ABFD.
-
-   Scan the current target stack for targets whose section tables
-   refer to sections from BFD, and remove those sections.  We use this
-   when we notice that the inferior has unloaded a shared object, for
-   example.  */
 void
 remove_target_sections (bfd *abfd)
 {
-  struct target_ops **t;
-
-  for (t = target_structs; t < target_structs + target_struct_size; t++)
-    {
-      struct target_section *src, *dest;
-
-      dest = (*t)->to_sections;
-      for (src = (*t)->to_sections; src < (*t)->to_sections_end; src++)
-	if (src->bfd != abfd)
-	  {
-	    /* Keep this section.  */
-	    if (dest < src) *dest = *src;
-	    dest++;
-	  }
-
-      /* If we've dropped any sections, resize the section table.  */
-      if (dest < src)
-	target_resize_to_sections (*t, dest - src);
-    }
-}
+  struct target_section *src, *dest;
 
+  struct target_section_table *table = current_target_sections;
 
+  dest = table->sections;
+  for (src = table->sections; src < table->sections_end; src++)
+    if (src->bfd != abfd)
+      {
+	/* Keep this section.  */
+	if (dest < src)
+	  *dest = *src;
+	dest++;
+      }
 
+  /* If we've dropped any sections, resize the section table.  */
+  if (dest < src)
+    resize_section_table (table, dest - src);
+}
 
 /* Find a single runnable target in the stack and return it.  If for
    some reason there is more than one, return NULL.  */
Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/target.h	2009-05-24 02:07:36.000000000 +0100
@@ -30,6 +30,7 @@ struct mem_attrib;
 struct target_ops;
 struct bp_target_info;
 struct regcache;
+struct target_section_table;
 
 /* This include file defines the interface between the main part
    of the debugger, and the part which is target-specific, or
@@ -420,10 +421,8 @@ struct target_ops
     int to_has_execution;
     int to_has_thread_control;	/* control thread execution */
     int to_attach_no_wait;
-    struct target_section
-     *to_sections;
-    struct target_section
-     *to_sections_end;
+
+    struct target_section_table *(*to_get_section_table) (struct target_ops *);
     /* ASYNC target controls */
     int (*to_can_async_p) (void);
     int (*to_is_async_p) (void);
@@ -668,9 +667,6 @@ extern int target_read_memory (CORE_ADDR
 extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr,
 				int len);
 
-extern int xfer_memory (CORE_ADDR, gdb_byte *, int, int,
-			struct mem_attrib *, struct target_ops *);
-
 /* Fetches the target's memory map.  If one is found it is sorted
    and returned, after some consistency checking.  Otherwise, NULL
    is returned.  */
@@ -733,10 +729,6 @@ extern int inferior_has_vforked (ptid_t 
 
 extern int inferior_has_execd (ptid_t pid, char **execd_pathname);
 
-/* From exec.c */
-
-extern void print_section_info (struct target_ops *, bfd *);
-
 /* Print a line about the current target.  */
 
 #define	target_files_info()	\
@@ -1208,10 +1200,30 @@ struct target_section
     bfd *bfd;			/* BFD file pointer */
   };
 
+/* Holds an array of target sections.  Defined by [START..END[.  */
+
+struct target_section_table
+{
+  struct target_section *sections;
+  struct target_section *sections_end;
+};
+
+/* The current set of target sections matching the sections mapped
+   into the current inferior's address space.  */
+extern struct target_section_table *current_target_sections;
+
+extern void remove_target_sections (bfd *abfd);
+
 /* Return the "section" containing the specified address.  */
 struct target_section *target_section_by_addr (struct target_ops *target,
 					       CORE_ADDR addr);
 
+/* Return the target section table this target (or the targets
+   beneath) currently manipulate.  */
+
+extern struct target_section_table *target_get_section_table
+  (struct target_ops *target);
+
 /* From mem-break.c */
 
 extern int memory_remove_breakpoint (struct bp_target_info *);
@@ -1242,11 +1254,6 @@ extern struct target_ops *find_core_targ
 
 extern struct target_ops *find_target_beneath (struct target_ops *);
 
-extern int target_resize_to_sections (struct target_ops *target,
-				      int num_added);
-
-extern void remove_target_sections (bfd *abfd);
-
 /* Read OS data object of type TYPE from the target, and return it in
    XML format.  The result is NUL-terminated and returned as a string,
    allocated using xmalloc.  If an error occurs or the transfer is
Index: src/gdb/bfd-target.c
===================================================================
--- src.orig/gdb/bfd-target.c	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/bfd-target.c	2009-05-23 23:46:15.000000000 +0100
@@ -32,35 +32,52 @@ target_bfd_xfer_partial (struct target_o
   switch (object)
     {
     case TARGET_OBJECT_MEMORY:
-      return section_table_xfer_memory_partial (readbuf, writebuf, offset, len,
-						ops->to_sections,
-						ops->to_sections_end);
+      {
+	struct target_section_table *table = ops->to_data;
+	return section_table_xfer_memory_partial (readbuf, writebuf, offset, len,
+						  table->sections,
+						  table->sections_end,
+						  NULL);
+      }
     default:
       return -1;
     }
 }
 
+struct target_section_table *
+target_bfd_get_section_table (struct target_ops *ops)
+{
+  return ops->to_data;
+}
+
 static void
 target_bfd_xclose (struct target_ops *t, int quitting)
 {
-  bfd_close (t->to_data);
-  xfree (t->to_sections);
+  struct target_section_table *table = t->to_data;
+  if (table->sections)
+    bfd_close (table->sections->bfd);
+  xfree (table->sections);
+  xfree (table);
   xfree (t);
 }
 
 struct target_ops *
 target_bfd_reopen (struct bfd *bfd)
 {
-  struct target_ops *t = XZALLOC (struct target_ops);
+  struct target_ops *t;
+  struct target_section_table *table;
+
+  table = XZALLOC (struct target_section_table);
+  build_section_table (bfd, &table->sections, &table->sections_end);
+
+  t = XZALLOC (struct target_ops);
   t->to_shortname = "bfd";
   t->to_longname = _("BFD backed target");
   t->to_doc = _("You should never see this");
+  t->to_get_section_table = target_bfd_get_section_table;
   t->to_xfer_partial = target_bfd_xfer_partial;
   t->to_xclose = target_bfd_xclose;
-  t->to_data = bfd;
+  t->to_data = table;
 
-  build_section_table (bfd,
-		       &t->to_sections,
-		       &t->to_sections_end);
   return t;
 }
Index: src/gdb/corelow.c
===================================================================
--- src.orig/gdb/corelow.c	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/corelow.c	2009-05-24 02:15:24.000000000 +0100
@@ -67,6 +67,14 @@ static struct core_fns *core_vec = NULL;
 
 struct gdbarch *core_gdbarch = NULL;
 
+/* Per-core data.  Currently, only the section table.  Note that these
+   target sections are *not* mapped in the current address spaces' set
+   of target sections --- those should come only from pure executable
+   or shared library bfds.  The core bfd sections are an
+   implementation detail of the core target, just like ptrace is for
+   unix child targets.  */
+struct target_section_table *core_data;
+
 static void core_files_info (struct target_ops *);
 
 static struct core_fns *sniff_core_bfd (bfd *);
@@ -203,18 +211,16 @@ core_close (int quitting)
          comments in clear_solib in solib.c. */
       clear_solib ();
 
+      xfree (core_data->sections);
+      xfree (core_data);
+      core_data = NULL;
+
       name = bfd_get_filename (core_bfd);
       if (!bfd_close (core_bfd))
 	warning (_("cannot close \"%s\": %s"),
 		 name, bfd_errmsg (bfd_get_error ()));
       xfree (name);
       core_bfd = NULL;
-      if (core_ops.to_sections)
-	{
-	  xfree (core_ops.to_sections);
-	  core_ops.to_sections = NULL;
-	  core_ops.to_sections_end = NULL;
-	}
     }
   core_vec = NULL;
   core_gdbarch = NULL;
@@ -347,9 +353,11 @@ core_open (char *filename, int from_tty)
 
   validate_files ();
 
+  core_data = XZALLOC (struct target_section_table);
+
   /* Find the data section */
-  if (build_section_table (core_bfd, &core_ops.to_sections,
-			   &core_ops.to_sections_end))
+  if (build_section_table (core_bfd,
+			   &core_data->sections, &core_data->sections_end))
     error (_("\"%s\": Can't find sections: %s"),
 	   bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
 
@@ -434,6 +442,23 @@ core_detach (struct target_ops *ops, cha
     printf_filtered (_("No core file now.\n"));
 }
 
+#ifdef DEPRECATED_IBM6000_TARGET
+
+/* Resize the core memory's section table, by NUM_ADDED.  Returns a
+   pointer into the first new slot.  This will not be necessary when
+   the rs6000 target is converted to use the standard solib
+   framework.  */
+
+struct target_section *
+deprecated_core_resize_section_table (int num_added)
+{
+  int old_count;
+
+  old_count = resize_section_table (core_data, num_added);
+  return core_data->sections + old_count;
+}
+
+#endif
 
 /* Try to retrieve registers from a section in core_bfd, and supply
    them to core_vec->core_read_registers, as the register set numbered
@@ -562,7 +587,7 @@ get_core_registers (struct target_ops *o
 static void
 core_files_info (struct target_ops *t)
 {
-  print_section_info (t, core_bfd);
+  print_section_info (core_data, core_bfd);
 }
 
 static LONGEST
@@ -573,13 +598,11 @@ core_xfer_partial (struct target_ops *op
   switch (object)
     {
     case TARGET_OBJECT_MEMORY:
-      if (readbuf)
-	return (*ops->deprecated_xfer_memory) (offset, readbuf,
-					       len, 0/*read*/, NULL, ops);
-      if (writebuf)
-	return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
-					       len, 1/*write*/, NULL, ops);
-      return -1;
+      return section_table_xfer_memory_partial (readbuf, writebuf,
+						offset, len,
+						core_data->sections,
+						core_data->sections_end,
+						NULL);
 
     case TARGET_OBJECT_AUXV:
       if (readbuf)
@@ -738,7 +761,6 @@ init_core_ops (void)
   core_ops.to_detach = core_detach;
   core_ops.to_fetch_registers = get_core_registers;
   core_ops.to_xfer_partial = core_xfer_partial;
-  core_ops.deprecated_xfer_memory = xfer_memory;
   core_ops.to_files_info = core_files_info;
   core_ops.to_insert_breakpoint = ignore;
   core_ops.to_remove_breakpoint = ignore;
Index: src/gdb/solib.c
===================================================================
--- src.orig/gdb/solib.c	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/solib.c	2009-05-24 00:24:08.000000000 +0100
@@ -661,21 +661,12 @@ update_solib_list (int from_tty, struct 
 			"Error while mapping shared library sections:\n",
 			RETURN_MASK_ALL);
 
-	  /* If requested, add the shared object's sections to the TARGET's
-	     section table.  Do this immediately after mapping the object so
-	     that later nodes in the list can query this object, as is needed
-	     in solib-osf.c.  */
-	  if (target)
-	    {
-	      int count = (i->sections_end - i->sections);
-	      if (count > 0)
-		{
-		  int space = target_resize_to_sections (target, count);
-		  memcpy (target->to_sections + space,
-			  i->sections,
-			  count * sizeof (i->sections[0]));
-		}
-	    }
+	  /* Add the shared object's sections to the current set of
+	     file section tables.  Do this immediately after mapping
+	     the object so that later nodes in the list can query this
+	     object, as is needed in solib-osf.c.  */
+	  concat_section_table (current_target_sections,
+				i->sections, i->sections_end);
 
 	  /* Notify any observer that the shared object has been
              loaded now that we've added it to GDB's tables.  */
Index: src/gdb/exec.c
===================================================================
--- src.orig/gdb/exec.c	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/exec.c	2009-05-23 23:46:15.000000000 +0100
@@ -132,6 +132,8 @@ exec_close (int quitting)
     {
       char *name = bfd_get_filename (exec_bfd);
 
+      remove_target_sections (exec_bfd);
+
       if (!bfd_close (exec_bfd))
 	warning (_("cannot close \"%s\": %s"),
 		 name, bfd_errmsg (bfd_get_error ()));
@@ -139,13 +141,6 @@ exec_close (int quitting)
       exec_bfd = NULL;
       exec_bfd_mtime = 0;
     }
-
-  if (exec_ops.to_sections)
-    {
-      xfree (exec_ops.to_sections);
-      exec_ops.to_sections = NULL;
-      exec_ops.to_sections_end = NULL;
-    }
 }
 
 void
@@ -195,6 +190,7 @@ exec_file_attach (char *filename, int fr
       struct cleanup *cleanups;
       char *scratch_pathname;
       int scratch_chan;
+      struct target_section *sections = NULL, *sections_end = NULL;
 
       scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
 		   write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
@@ -254,8 +250,7 @@ exec_file_attach (char *filename, int fr
 	}
 #endif /* DEPRECATED_IBM6000_TARGET */
 
-      if (build_section_table (exec_bfd, &exec_ops.to_sections,
-			       &exec_ops.to_sections_end))
+      if (build_section_table (exec_bfd, &sections, &sections_end))
 	{
 	  /* Make sure to close exec_bfd, or else "run" might try to use
 	     it.  */
@@ -264,6 +259,11 @@ exec_file_attach (char *filename, int fr
 		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
 	}
 
+      /* Add the executable's sections to the current address spaces'
+	 list of sections.  */
+      concat_section_table (current_target_sections, sections, sections_end);
+      xfree (sections);
+
       exec_bfd_mtime = bfd_get_mtime (exec_bfd);
 
       validate_files ();
@@ -370,6 +370,25 @@ add_to_section_table (bfd *abfd, struct 
   (*table_pp)++;
 }
 
+int
+resize_section_table (struct target_section_table *table, int num_added)
+{
+  struct target_section *old_value;
+  int old_count;
+  int new_count;
+
+  old_value = table->sections;
+  old_count = table->sections_end - table->sections;
+
+  new_count = num_added + old_count;
+
+  table->sections
+    = xrealloc (table->sections, sizeof (struct target_section) * new_count);
+  table->sections_end = table->sections + new_count;
+
+  return old_count;
+}
+
 /* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
    Returns 0 if OK, 1 on error.  */
 
@@ -390,6 +409,24 @@ build_section_table (struct bfd *some_bf
   /* We could realloc the table, but it probably loses for most files.  */
   return 0;
 }
+
+void
+concat_section_table (struct target_section_table *table,
+		      struct target_section *sections,
+		      struct target_section *sections_end)
+{
+  int count;
+
+  count = sections_end - sections;
+
+  if (count > 0)
+    {
+      int space = resize_section_table (table, count);
+      memcpy (table->sections + space,
+	      sections, count * sizeof (sections[0]));
+    }
+}
+
 
 static void
 bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
@@ -467,22 +504,22 @@ map_vmap (bfd *abfd, bfd *arch)
    < 0:  We cannot handle this address, but if somebody
    else handles (-N) bytes, we can start from there.  */
 
-static int
-section_table_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr,
-			   int len, int write,
-			   struct target_section *sections,
-			   struct target_section *sections_end,
-			   const char *section_name)
+int
+section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
+				   ULONGEST offset, LONGEST len,
+				   struct target_section *sections,
+				   struct target_section *sections_end,
+				   const char *section_name)
 {
   int res;
   struct target_section *p;
-  CORE_ADDR nextsectaddr, memend;
+  ULONGEST memaddr = offset;
+  ULONGEST memend;
 
   if (len <= 0)
     internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 
   memend = memaddr + len;
-  nextsectaddr = memend;
 
   for (p = sections; p < sections_end; p++)
     {
@@ -493,13 +530,13 @@ section_table_xfer_memory (CORE_ADDR mem
 	  if (memend <= p->endaddr)
 	    {
 	      /* Entire transfer is within this section.  */
-	      if (write)
+	      if (writebuf)
 		res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
-						myaddr, memaddr - p->addr,
+						writebuf, memaddr - p->addr,
 						len);
 	      else
 		res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
-						myaddr, memaddr - p->addr,
+						readbuf, memaddr - p->addr,
 						len);
 	      return (res != 0) ? len : 0;
 	    }
@@ -512,90 +549,43 @@ section_table_xfer_memory (CORE_ADDR mem
 	    {
 	      /* This section overlaps the transfer.  Just do half.  */
 	      len = p->endaddr - memaddr;
-	      if (write)
+	      if (writebuf)
 		res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
-						myaddr, memaddr - p->addr,
+						writebuf, memaddr - p->addr,
 						len);
 	      else
 		res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
-						myaddr, memaddr - p->addr,
+						readbuf, memaddr - p->addr,
 						len);
 	      return (res != 0) ? len : 0;
 	    }
         }
-      else
-	nextsectaddr = min (nextsectaddr, p->addr);
     }
 
-  if (nextsectaddr >= memend)
-    return 0;			/* We can't help */
-  else
-    return -(nextsectaddr - memaddr);	/* Next boundary where we can help */
+  return 0;			/* We can't help */
 }
 
-int
-section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
-				   ULONGEST offset, LONGEST len,
-				   struct target_section *sections,
-				   struct target_section *sections_end)
-{
-  if (readbuf != NULL)
-    return section_table_xfer_memory (offset, readbuf, len, 0,
-				      sections, sections_end, NULL);
+static LONGEST
+exec_xfer_partial (struct target_ops *ops, enum target_object object,
+		   const char *annex, gdb_byte *readbuf,
+		   const gdb_byte *writebuf,
+		   ULONGEST offset, LONGEST len)
+{
+  struct target_section_table *table = target_get_section_table (ops);
+
+  if (object == TARGET_OBJECT_MEMORY)
+    return section_table_xfer_memory_partial (readbuf, writebuf,
+					      offset, len,
+					      table->sections,
+					      table->sections_end,
+					      NULL);
   else
-    return section_table_xfer_memory (offset, (gdb_byte *) writebuf, len, 1,
-				      sections, sections_end, NULL);
-}
-
-/* Read or write the exec file.
-
-   Args are address within a BFD file, address within gdb address-space,
-   length, and a flag indicating whether to read or write.
-
-   Result is a length:
-
-   0:    We cannot handle this address and length.
-   > 0:  We have handled N bytes starting at this address.
-   (If N == length, we did it all.)  We might be able
-   to handle more bytes beyond this length, but no
-   promises.
-   < 0:  We cannot handle this address, but if somebody
-   else handles (-N) bytes, we can start from there.
-
-   The same routine is used to handle both core and exec files;
-   we just tail-call it with more arguments to select between them.  */
-
-int
-xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
-	     struct mem_attrib *attrib, struct target_ops *target)
-{
-  int res;
-  const char *section_name = NULL;
-
-  if (len <= 0)
-    internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
-
-  if (overlay_debugging)
-    {
-      struct obj_section *section = find_pc_overlay (memaddr);
-
-      if (section != NULL)
-	{
-	  if (pc_in_unmapped_range (memaddr, section))
-	    memaddr = overlay_mapped_address (memaddr, section);
-	  section_name = section->the_bfd_section->name;
-	}
-    }
-
-  return section_table_xfer_memory (memaddr, myaddr, len, write,
-				    target->to_sections,
-				    target->to_sections_end,
-				    section_name);
+    return -1;
 }
 
 
 void
-print_section_info (struct target_ops *t, bfd *abfd)
+print_section_info (struct target_section_table *t, bfd *abfd)
 {
   struct target_section *p;
   /* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64.  */
@@ -607,7 +597,7 @@ print_section_info (struct target_ops *t
   if (abfd == exec_bfd)
     printf_filtered (_("\tEntry point: %s\n"),
                      paddress (bfd_get_start_address (abfd)));
-  for (p = t->to_sections; p < t->to_sections_end; p++)
+  for (p = t->sections; p < t->sections_end; p++)
     {
       printf_filtered ("\t%s", hex_string_custom (p->addr, wid));
       printf_filtered (" - %s", hex_string_custom (p->endaddr, wid));
@@ -631,7 +621,7 @@ print_section_info (struct target_ops *t
 static void
 exec_files_info (struct target_ops *t)
 {
-  print_section_info (t, exec_bfd);
+  print_section_info (current_target_sections, exec_bfd);
 
   if (vmap)
     {
@@ -667,6 +657,7 @@ set_section_command (char *args, int fro
   unsigned long secaddr;
   char secprint[100];
   long offset;
+  struct target_section_table *table;
 
   if (args == 0)
     error (_("Must specify section name and its virtual address"));
@@ -678,7 +669,8 @@ set_section_command (char *args, int fro
   /* Parse out new virtual address */
   secaddr = parse_and_eval_address (args);
 
-  for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++)
+  table = current_target_sections;
+  for (p = table->sections; p < table->sections_end; p++)
     {
       if (!strncmp (secname, bfd_section_name (exec_bfd, p->the_bfd_section), seclen)
 	  && bfd_section_name (exec_bfd, p->the_bfd_section)[seclen] == '\0')
@@ -705,8 +697,10 @@ void
 exec_set_section_address (const char *filename, int index, CORE_ADDR address)
 {
   struct target_section *p;
+  struct target_section_table *table;
 
-  for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++)
+  table = current_target_sections;
+  for (p = table->sections; p < table->sections_end; p++)
     {
       if (strcmp (filename, p->bfd->filename) == 0
 	  && index == p->the_bfd_section->index)
@@ -754,7 +748,7 @@ Specify the filename of the executable f
   exec_ops.to_open = exec_open;
   exec_ops.to_close = exec_close;
   exec_ops.to_attach = find_default_attach;
-  exec_ops.deprecated_xfer_memory = xfer_memory;
+  exec_ops.to_xfer_partial = exec_xfer_partial;
   exec_ops.to_files_info = exec_files_info;
   exec_ops.to_insert_breakpoint = ignore;
   exec_ops.to_remove_breakpoint = ignore;
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/infrun.c	2009-05-23 23:39:22.000000000 +0100
@@ -2308,15 +2308,6 @@ handle_inferior_event (struct execution_
 	     operations such as address => section name and hence
 	     require the table to contain all sections (including
 	     those found in shared libraries).  */
-	  /* NOTE: cagney/2003-11-25: Pass current_target and not
-	     exec_ops to SOLIB_ADD.  This is because current GDB is
-	     only tooled to propagate section_table changes out from
-	     the "current_target" (see target_resize_to_sections), and
-	     not up from the exec stratum.  This, of course, isn't
-	     right.  "infrun.c" should only interact with the
-	     exec/process stratum, instead relying on the target stack
-	     to propagate relevant changes (stop, section table
-	     changed, ...) up to other layers.  */
 #ifdef SOLIB_ADD
 	  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
 #else
@@ -3293,15 +3284,6 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (
 	     operations such as address => section name and hence
 	     require the table to contain all sections (including
 	     those found in shared libraries).  */
-	  /* NOTE: cagney/2003-11-25: Pass current_target and not
-	     exec_ops to SOLIB_ADD.  This is because current GDB is
-	     only tooled to propagate section_table changes out from
-	     the "current_target" (see target_resize_to_sections), and
-	     not up from the exec stratum.  This, of course, isn't
-	     right.  "infrun.c" should only interact with the
-	     exec/process stratum, instead relying on the target stack
-	     to propagate relevant changes (stop, section table
-	     changed, ...) up to other layers.  */
 #ifdef SOLIB_ADD
 	  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
 #else
Index: src/gdb/rs6000-nat.c
===================================================================
--- src.orig/gdb/rs6000-nat.c	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/rs6000-nat.c	2009-05-24 00:13:21.000000000 +0100
@@ -1160,8 +1160,7 @@ xcoff_relocate_core (struct target_ops *
 	{
 	  struct target_section *stp;
 
-	  target_resize_to_sections (target, 2);
-	  stp = target->to_sections_end - 2;
+	  stp = deprecated_core_resize_section_table (2);
 
 	  stp->bfd = vp->bfd;
 	  stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text");
Index: src/gdb/exec.h
===================================================================
--- src.orig/gdb/exec.h	2009-05-23 23:00:21.000000000 +0100
+++ src/gdb/exec.h	2009-05-24 00:22:54.000000000 +0100
@@ -34,6 +34,11 @@ extern struct target_ops exec_ops;
 extern int build_section_table (struct bfd *, struct target_section **,
 				struct target_section **);
 
+/* Resize the section table held by TABLE, by NUM_ADDED.  Returns the
+   old size.  */
+
+extern int resize_section_table (struct target_section_table *, int);
+
 /* Request to transfer up to LEN 8-bit bytes of the target sections
    defined by SECTIONS and SECTIONS_END.  The OFFSET specifies the
    starting address.
@@ -50,9 +55,25 @@ extern int build_section_table (struct b
 extern int section_table_xfer_memory_partial (gdb_byte *, const gdb_byte *,
 					      ULONGEST, LONGEST,
 					      struct target_section *,
-					      struct target_section *);
+					      struct target_section *,
+					      const char *);
 
 /* Set the loaded address of a section.  */
 extern void exec_set_section_address (const char *, int, CORE_ADDR);
 
+/* Append the sections array defined by [SECTIONS..SECTIONS_END[ to
+   TABLE.  TABLE's memory is reallocated to fit in the new
+   sections.  */
+extern void concat_section_table (struct target_section_table *table,
+				  struct target_section *sections,
+				  struct target_section *sections_end);
+
+/* Prints info about all sections defined in the TABLE.  ABFD is
+   special cased --- it's filename is omitted; if it is the executable
+   file, its entry point is printed.  */
+
+extern void print_section_info (struct target_section_table *table,
+				bfd *abfd);
+
+
 #endif
Index: src/gdb/gdbcore.h
===================================================================
--- src.orig/gdb/gdbcore.h	2009-05-24 00:12:07.000000000 +0100
+++ src/gdb/gdbcore.h	2009-05-24 00:13:07.000000000 +0100
@@ -189,4 +189,6 @@ extern void deprecated_add_core_fns (str
 extern int default_core_sniffer (struct core_fns *cf, bfd * abfd);
 extern int default_check_format (bfd * abfd);
 
+struct target_section *deprecated_core_resize_section_table (int num_added);
+
 #endif /* !defined (GDBCORE_H) */


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