* [RFC,v2] Yank out target_ops->to_sections
@ 2009-05-24 1:35 Pedro Alves
2009-05-26 23:30 ` Pedro Alves
0 siblings, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2009-05-24 1:35 UTC (permalink / raw)
To: gdb-patches
[ 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 = ¤t_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);
}
\f
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, §ions, §ions_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]));
+ }
+}
+
\f
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;
}
\f
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, ¤t_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, ¤t_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) */
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v2] Yank out target_ops->to_sections
2009-05-24 1:35 [RFC,v2] Yank out target_ops->to_sections Pedro Alves
@ 2009-05-26 23:30 ` Pedro Alves
2009-05-27 1:30 ` Doug Evans
2009-05-27 18:24 ` Ulrich Weigand
0 siblings, 2 replies; 11+ messages in thread
From: Pedro Alves @ 2009-05-26 23:30 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich Weigand
Hi Ulrich, all,
On Sunday 24 May 2009 02:35:20, Pedro Alves wrote:
> - 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).
It seems I don't have access to any target using an overlay manager. I
think Cell uses overlays? Ulrich, perhaps I could ask you the favour of
confirming that I'm not breaking anything overlay related? A genaral peek
over the patch would be much appreciated as well, of course.
> - 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.
ppc64-linux may also use bfd-target.c (ppc64_linux_convert_from_func_ptr_addr,
which I think was the whole point of this bfd-target.c), so I found myself
such a machine, and gave it a spin there. Surprisingly, I get this
consistently:
-FAIL: gdb.base/gcore.exp: corefile restored backtrace
+PASS: gdb.base/gcore.exp: corefile restored backtrace
@@ -24913,10 +24914,8 @@ backtrace
#6 0x00000000100006c4 in factorial_func (value=5) at ../../../src/gdb/testsuite/gdb.base/gcore.c:60
#7 0x00000000100006c4 in factorial_func (value=6) at ../../../src/gdb/testsuite/gdb.base/gcore.c:60
#8 0x0000000010000720 in main () at ../../../src/gdb/testsuite/gdb.base/gcore.c:68
-#9 0x0000008091073cd8 in .generic_start_main () from /lib64/tls/libc.so.6
-Backtrace stopped: frame did not save the PC
-(gdb) FAIL: gdb.base/gcore.exp: corefile restored backtrace
-testcase ../../../src/gdb/testsuite/gdb.base/gcore.exp completed in 3 seconds
+(gdb) PASS: gdb.base/gcore.exp: corefile restored backtrace
+testcase ../../../src/gdb/testsuite/gdb.base/gcore.exp completed in 2 seconds
Always fails without the patch, always passes with. No other changes in the
whole test run. I haven't exactly pinpointed the exact reason why this is
now passing, though.
Here's the patch again. Only change compared to the previous version is to
use an explicit xfree, instead of xrealloc (..., 0), because I found out
that libiberty's xrealloc still allocs when the 'size' argument is
0, instead of behaving like free (it is legal either way).
--
Pedro Alves
2009-05-27 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 | 186 +++++++++++++++++++++++++++----------------------------
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, 298 insertions(+), 270 deletions(-)
Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c 2009-05-24 22:46:23.000000000 +0100
+++ src/gdb/target.c 2009-05-25 16:04:38.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 = ¤t_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-24 22:46:23.000000000 +0100
+++ src/gdb/target.h 2009-05-25 16:04:38.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-24 22:46:23.000000000 +0100
+++ src/gdb/bfd-target.c 2009-05-24 23:22:52.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-24 22:46:23.000000000 +0100
+++ src/gdb/corelow.c 2009-05-25 16:04:38.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);
}
\f
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-24 22:46:23.000000000 +0100
+++ src/gdb/solib.c 2009-05-25 16:04:37.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-24 22:46:23.000000000 +0100
+++ src/gdb/exec.c 2009-05-25 16:05:01.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, §ions, §ions_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,33 @@ 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;
+
+ if (new_count)
+ {
+ table->sections
+ = xrealloc (table->sections, sizeof (struct target_section) * new_count);
+ table->sections_end = table->sections + new_count;
+ }
+ else
+ {
+ xfree (table->sections);
+ table->sections = table->sections_end = NULL;
+ }
+
+ return old_count;
+}
+
/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
Returns 0 if OK, 1 on error. */
@@ -390,6 +417,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]));
+ }
+}
+
\f
static void
bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
@@ -467,22 +512,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 +538,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 +557,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;
}
\f
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 +605,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 +629,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 +665,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 +677,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 +705,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 +756,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-24 22:46:23.000000000 +0100
+++ src/gdb/infrun.c 2009-05-25 16:04:45.000000000 +0100
@@ -2425,15 +2425,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, ¤t_target, auto_solib_add);
#else
@@ -3422,15 +3413,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, ¤t_target, auto_solib_add);
#else
Index: src/gdb/rs6000-nat.c
===================================================================
--- src.orig/gdb/rs6000-nat.c 2009-05-24 22:46:23.000000000 +0100
+++ src/gdb/rs6000-nat.c 2009-05-24 23:22:52.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-24 22:46:23.000000000 +0100
+++ src/gdb/exec.h 2009-05-25 16:04:37.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 22:46:23.000000000 +0100
+++ src/gdb/gdbcore.h 2009-05-25 16:04:37.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) */
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v2] Yank out target_ops->to_sections
2009-05-26 23:30 ` Pedro Alves
@ 2009-05-27 1:30 ` Doug Evans
2009-05-27 18:24 ` Ulrich Weigand
1 sibling, 0 replies; 11+ messages in thread
From: Doug Evans @ 2009-05-27 1:30 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, Ulrich Weigand
On Tue, May 26, 2009 at 4:30 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> It seems I don't have access to any target using an overlay manager.
m32r-elf + simulator?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v2] Yank out target_ops->to_sections
2009-05-26 23:30 ` Pedro Alves
2009-05-27 1:30 ` Doug Evans
@ 2009-05-27 18:24 ` Ulrich Weigand
2009-05-29 14:13 ` Pedro Alves
1 sibling, 1 reply; 11+ messages in thread
From: Ulrich Weigand @ 2009-05-27 18:24 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> On Sunday 24 May 2009 02:35:20, Pedro Alves wrote:
>
> > - 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).
>
> It seems I don't have access to any target using an overlay manager. I
> think Cell uses overlays? Ulrich, perhaps I could ask you the favour of
> confirming that I'm not breaking anything overlay related? A genaral peek
> over the patch would be much appreciated as well, of course.
Your changes to overlay support look good to me, and I've verified that the
patch introduces no regressions on spu-elf, including the overlay test cases.
In general, I like the idea of your patch, in particular the elimination of
sections from target_ops, and removal of xfer_memory.
I'm not quite sure what to think of the new current_target_sections variable,
in particular its interaction with target_get_section_table. Why do you need
a generic fallback to current_target_sections, instead of e.g. having exec_ops
implement a to_get_section_table method? How to you see this work in a
multi-inferior / multi-address-space setup?
Also, I'm not completely sure I understand the implications of the solib_add
change. The old method allowed callers to explicitly ask that the library
sections be *not* added to the section table, and several callers did that.
With your patch, sections are always added. Was it always an error to not
add sections? I'm not really sure why this feature was introduced ...
(Maybe as a follow-on, ...) Now that we have a struct target_section_table,
some of the interfaces that use two target_section pointers should be changed
to take a single target_section_table pointer, perhaps?
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v2] Yank out target_ops->to_sections
2009-05-27 18:24 ` Ulrich Weigand
@ 2009-05-29 14:13 ` Pedro Alves
2009-05-30 16:39 ` [RFC,v3] " Pedro Alves
2009-06-02 11:06 ` [RFC,v2] " Ulrich Weigand
0 siblings, 2 replies; 11+ messages in thread
From: Pedro Alves @ 2009-05-29 14:13 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich Weigand
On Wednesday 27 May 2009 19:24:06, Ulrich Weigand wrote:
> Your changes to overlay support look good to me, and I've verified that the
> patch introduces no regressions on spu-elf, including the overlay test cases.
Great. Thank you very much for testing and for the speedy review.
> In general, I like the idea of your patch, in particular the elimination of
> sections from target_ops, and removal of xfer_memory.
>
> I'm not quite sure what to think of the new current_target_sections variable,
> in particular its interaction with target_get_section_table. Why do you need
> a generic fallback to current_target_sections, instead of e.g. having exec_ops
> implement a to_get_section_table method?
The issue I had in mind is that currently, it is possible to debug
with process_stratum target pushed, without having the exec_ops
target pushed. In that case, nothing would reply to
a to_get_section_table request, and so "trust-readonly-sections"
would fail in those cases.
I've been thinking for a while that the exec_ops target
should be pushed whenever we have any kind of file loaded (main
executable or dynamic shared module) that we can read memory
from. It implements the file_stratum after all, and target.h says:
file_stratum, /* Executable files, etc */
^^^
Maybe rename it file_ops in the process, maybe.
A couple of patches ahead, I'll need to make to_have_memory,
to_have_registers, etc. methods, so that target_has_memory etc.,
returns a different result depending on the current inferior (or
current executable not inferior yet). I think that with that
in place, it wouldn't be hard to make file_stratum always be
pushed and get rid of dummy_ops, but I haven't tried it.
An example where exec_ops isn't used at all currently is DICOS.
In that case, there's no concept of a "main" executable. All
code comes from dynamically loaded modules the target reports. As
a consequence, there's no exec_ops target pushed, as the user
isn't expected to use the file command (as it doesn't make sense
to use it here).
There are a few cases where GDB reads memory from the target sections
when you don't have an inferior yet. E.g., when setting breakpoints
on functions (e.g., "break main") prologue skipping needs to read
memory. Since on DICOS I don't have an exec_ops target pushed,
I needed to hack remote.c's xfer_partial routine to defer to
(the now being eliminated) xfer_memory itself. I wouldn't need
that hack if there was a file_stratum layer pushed whenever GDB has
(any kind of) files to read from.
> How to you see this work in a
> multi-inferior / multi-address-space setup?
This is all up to discussion of course, but, currently,
I've got a new structure that holds among other things,
the target sections. Then, the current_target_sections_1 and
current_target_sections global this patch is introducing
go away, and instead we access the corresponing fields of
that new structure.
Here's a stripped down version of what I've got here currently:
/* A symbol space represents a symbolic view of an address space. It
holds all the data associated with a non-running-yet program (main
executable, main symbols), and when an inferior is running and is
bound to it, includes the list of its mapped in shared libraries.
In the traditional debugging scenario, there's a 1-1 correspondence
among symbol spaces, inferiors and address spaces, like so:
sspace1 (prog1) <--> inf1(pid1) <--> aspace1
In the case of debugging more than one traditional unix process or
program, we still have:
|-----------------+------------+---------|
| sspace1 (prog1) | inf1(pid1) | aspace1 |
|----------------------------------------|
| sspace2 (prog1) | no inf yet | aspace2 |
|-----------------+------------+---------|
| sspace3 (prog2) | inf2(pid2) | aspace3 |
|-----------------+------------+---------|
In the former example, if inf1 forks (and GDB wants to stay
attached to both processes), the new child will have its own symbol
space, and address spaces. Like so:
|-----------------+------------+---------|
| sspace1 (prog1) | inf1(pid1) | aspace1 |
|-----------------+------------+---------|
| sspace2 (prog1) | inf2(pid2) | aspace2 |
|-----------------+------------+---------|
However, had inf1 from the latter case vforked instead, it would
share the symbol and address spaces with its parent, until it execs
or exits, like so:
|-----------------+------------+---------|
| sspace1 (prog1) | inf1(pid1) | aspace1 |
| | inf2(pid2) | |
|-----------------+------------+---------|
When the vfork child execs, it is finally given new symbol and
address spaces.
|-----------------+------------+---------|
| sspace1 (prog1) | inf1(pid1) | aspace1 |
|-----------------+------------+---------|
| sspace2 (prog1) | inf2(pid2) | aspace2 |
|-----------------+------------+---------|
There are targets where the OS (if any) doesn't provide memory
management and VM protection, where all inferiors share the same
address space --- e.g. uClinux. This is modelled by having all
inferiors share the same address space, but, giving each its own
symbol space, like so:
|-----------------+------------+---------|
| sspace1 (prog1) | inf1(pid1) | |
|-----------------+------------+ |
| sspace2 (prog1) | inf2(pid2) | aspace1 |
|-----------------+------------+ |
| sspace3 (prog2) | inf3(pid3) | |
|-----------------+------------+---------|
The address sharing is important for run control (did we just hit a
known breakpoint that we need to step over?) and for the
breakpoints module (is this breakpoint a duplicate of this other
one, or do I need to insert a trap?).
Then, there are targets where all symbols look the same for all
inferiors, although each has its own address space, as e.g.,
Ericsson DICOS. There, the correct model would be:
|---------+------------+---------|
| | inf1(pid1) | aspace1 |
| +------------+---------|
| sspace | inf2(pid2) | aspace2 |
| +------------+---------|
| | inf3(pid3) | aspace3 |
|---------+------------+---------|
Although currently we don't model this, because the DICOS debug API
takes care of making GDB believe that breakpoints are "global".
That is, although each process does have its own private copy of
data symbols (just like a bunch of forks), to the breakpoints
module, all processes share a single address space, so all
breakpoints set at the same address are duplicates of each other,
even breakpoints set in the data space (e.g., call dummy
breakpoints placed on stack). DICOS is currently modelled by
having all inferiors share a symbol space and an address space. */
/* The symbol space structure. */
struct symbol_space
{
/* Pointer to next in linked list. */
struct symbol_space *next;
/* Unique ID number. */
int num;
/* The main executable loaded into this symbol space. This is
managed by the exec target. */
struct exec *exec;
/* The address space attached to this symbol space. More than one
symbol space may be bound to the same address space. */
struct address_space *aspace;
/* The object file that the main symbol table was loaded from
(e.g. the argument to the "symbol-file" or "file" command). */
struct objfile *symfile_objfile_1;
/* All known objfiles are kept in a linked list. This points to
the root of this list. */
struct objfile *objfiles;
/* The set of target sections matching the sections mapped into
this symbol space. Managed by both exec_ops and solib.c. */
struct target_section_table target_sections;
/* List of shared objects mapped into this space. Managed by
solib.c. */
struct so_list *so_list;
/* True if this was an auto-created sspace, e.g. created from
following a fork/exec; false, if this sspace was manually added
by the user, and should not be pruned automatically. */
int removable;
};
/* The object file that the main symbol table was loaded from (e.g. the
argument to the "symbol-file" or "file" command). */
#define symfile_objfile current_symbol_space->symfile_objfile_1
/* All known objfiles are kept in a linked list. This points to the
root of this list. */
#define object_files current_symbol_space->objfiles
/* The set of target sections matching the sections mapped into the
current symbol address space. */
#define current_target_sections (¤t_symbol_space->target_sections)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There still needs to be a global somewhere, there's no way around it,
but, it will be the "current_symbol_space", not the target sections.
This global is then switched whenever we need to switch context
--- switch thread, insert breakpoints, or by user command, to e.g.,
prepare to start a new inferior --- in a sense, this structure holds
the globals that currently form a "prototype" for an inferior.
> Also, I'm not completely sure I understand the implications of the solib_add
> change. The old method allowed callers to explicitly ask that the library
> sections be *not* added to the section table, and several callers did that.
> With your patch, sections are always added. Was it always an error to not
> add sections? I'm not really sure why this feature was introduced ...
I think that historically, it was the other way around. They were never
added in the beggining, and when shared libraries support for core
files was added to GDB, the corresponing targets that supported it
were adjusted to pass a target_ops pointer.
We've currently got more use for the target sections (trust-readonly-sections,
for once), so I think we should always add the sections. I've done a bit
of history digging. Looking at gdb 3.98's sources, and I see in solib.c:
/*
** Called by core_xfer_memory if the transfer form the core file failed.
** We try to satisfy the request from the text sections of the shared libs.
*/
int
solib_xfer_memory (memaddr, myaddr, len, write)
CORE_ADDR memaddr;
char *myaddr;
int len;
int write;
{
int res;
register struct so_list *so = 0;
while (so = find_solib(so))
{
res = xfer_memory (memaddr, myaddr, len, write,
so->so_bfd, so->so_sections, so->so_sections_end);
if (res)
return res;
}
return 0;
}
and in corelow.c:
static int
core_xfer_memory (memaddr, myaddr, len, write)
CORE_ADDR memaddr;
char *myaddr;
int len;
int write;
{
int res;
res = xfer_memory (memaddr, myaddr, len, write,
core_bfd, core_sections, core_sections_end);
#ifdef SOLIB_XFER_MEMORY
if (res == 0)
res = SOLIB_XFER_MEMORY (memaddr, myaddr, len, write);
#endif
return res;
}
The changelog mentions:
* Shared library/corefile changes from Peter Schauer:
core.c (core_close): Call CLEAR_SOLIB.
(core_open): Remove comment about "should deal with shared lib".
(core_xfer_memory): If we can't xfer the usual way, try the
shared libraries.
solib.c (so_list): New fields so_bfd and so_sections{,_end}.
(find_solib): Use solib_map_sections to get ld_text.
(solib_map_sections, solib_xfer_memory): New functions.
(clear_solib): Free so_sections and close so_bfd.
tm-sunos.h: Add solib_xfer_memory, solib_add.
Then on ChangeLog-9091, I see:
Tue Aug 13 16:17:56 1991 John Gilmore (gnu at cygint.cygnus.com)
...
* gdbcore.h: Move struct section_table.
* target.h: New home of struct section_table.
* solib.c (solib_add): New argument is the target_ops whose
section list is to be added to, if any. Reallocate the
sections in that target to add any that come from shared libs.
(throughout) so_sections renamed to sections.
(solib_xfer_memory): Deleted.
* tm-sunos.h (SOLIB_ADD): Add target argument.
(SOLIB_XFER_MEMORY): Delete.
... and from there on I would guess that a few target gained generic
shared library support after solaris, and just missed adding
the section tables to to_sections, probably because they didn't
have either proper core file support --- remember that when debugging a
process_stratum layer, usually to_has_all_memory is set,
and so unless "set trust-readonly-sections" is on, or overlay
support is needed, target sections aren't accessed --- or
the system didn't support partial cores (cores always included all memory).
Interestingly, by gdb 4.6, we have:
>ls *solib*
solib.c solib.h xcoffsolib.c xcoffsolib.h
... and we're still stuck with xcoffsolib.c. :-)
I took a look at all solib_add calls that don't pass a target
ops pointer:
solib.c: solib_add (args, from_tty, (struct target_ops *) 0, 1);
solib.c: solib_add (NULL, from_tty, NULL, auto_solib_add);
These two are the broken sharedlibrary_command and reload_shared_libraries
calls.
solib-frv.c: solib_add (0, 0, 0, 1);
This module is only used when remote debugging, there's no core
file support. Doesn't look like adding target sections would do
any harm, and it would make trust-readonly-sections work better.
solib-irix.c: solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
I can't see a native .mt file pulling this in. This shared library
support can't be being used with core inferiors, since
irix_solib_create_inferior_hook always wants to resume the target. Since
target sections were primarily a feature for core files, it doesn't
surprise me to see a NULL target being passed here (remember to_has_all_memory),
but I can't see a reason why not to --- it would make "set trust-readonly-sections"
work for shared library code on this target.
solib-osf.c: solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
Same here, although this one handles core files. It is mistifying then,
since when debugging core files, if the user tries to read memory from shared
libraries' .text sections must be failing on this target, unless the core files
on this system include all memory, of course.
solib-sunos.c: solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
Same as solib-irix.c. This one must be failing badly on core inferiors. A
configuration where that would be happening is
config/arm/nbsdaout.mh (NetBSD/arm).
windows-nat.c: solib_add (NULL, 0, NULL, auto_solib_add);
Up until not so long ago, there was no core file support on Windows/Cygwin.
Cygwin can now generate elf core dumps, and minidump support is being worked on
(Windows version of unix cores). Windows configurations use solib-target.c.
Again, I can't see why it wouldn't work to pass target sections here, since,
the solib.c model always relocates target sections before sos and their
sections are added to the generic lists.
> (Maybe as a follow-on, ...) Now that we have a struct target_section_table,
> some of the interfaces that use two target_section pointers should be changed
> to take a single target_section_table pointer, perhaps?
Sure, can't see why not.
--
Pedro Alves
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC,v3] Yank out target_ops->to_sections
2009-05-29 14:13 ` Pedro Alves
@ 2009-05-30 16:39 ` Pedro Alves
2009-06-02 11:10 ` Ulrich Weigand
2009-06-02 11:06 ` [RFC,v2] " Ulrich Weigand
1 sibling, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2009-05-30 16:39 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich Weigand
On Friday 29 May 2009 15:13:41, Pedro Alves wrote:
> On Wednesday 27 May 2009 19:24:06, Ulrich Weigand wrote:
> > In general, I like the idea of your patch, in particular the elimination of
> > sections from target_ops, and removal of xfer_memory.
> >
> > I'm not quite sure what to think of the new current_target_sections variable,
> > in particular its interaction with target_get_section_table. Why do you need
> > a generic fallback to current_target_sections, instead of e.g. having exec_ops
> > implement a to_get_section_table method?
>
> The issue I had in mind is that currently, it is possible to debug
> with process_stratum target pushed, without having the exec_ops
> target pushed. In that case, nothing would reply to
> a to_get_section_table request, and so "trust-readonly-sections"
> would fail in those cases.
>
> I've been thinking for a while that the exec_ops target
> should be pushed whenever we have any kind of file loaded (main
> executable or dynamic shared module) that we can read memory
> from. It implements the file_stratum after all, and target.h says:
>
> file_stratum, /* Executable files, etc */
> ^^^
I think I'm convinced this it is the best to do, design-wise.
This way, we'll still be able to read memory from shared library
sections if no main executable is loaded into GDB (e.g., gdb -c foo,
without specifying an executable needs this).
I've given it a try, and, it does look like a cleaner solution
long term to me. Even PIE executables blur the distintion of
what is specified as main executable vs what is reported by the
dynamic loader a bit more. Another interesting fact, is that
the "vmap" bits spread about in exec.c for xcoffsolib are quite
similar in spirit to this "set of target sections we can read file
read memory from". Find below an incremental patch that applies
on top of the v2 one I posted (the changes aren't that
many: push/unpush of exec_ops moved, plus that default of
target_get_section_table you pointed out goes away, replaced by
the exec_ops target returning the current set of target sections).
At the bottom there's the new v3 combined patch.
Please let me know what you think about this. Re-tested on x86_64-linux.
--
Pedro Alves
---
gdb/exec.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++-------------
gdb/exec.h | 7 +--
gdb/solib.c | 3 -
gdb/target.c | 39 -------------------
gdb/target.h | 6 --
5 files changed, 100 insertions(+), 75 deletions(-)
Index: src/gdb/exec.c
===================================================================
--- src.orig/gdb/exec.c 2009-05-30 17:09:35.000000000 +0100
+++ src/gdb/exec.c 2009-05-30 17:15:28.000000000 +0100
@@ -71,6 +71,15 @@ struct target_ops exec_ops;
bfd *exec_bfd = NULL;
long exec_bfd_mtime = 0;
+/* 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 set of target sections matching the sections mapped into the
+ current inferior's address space. */
+struct target_section_table *current_target_sections = ¤t_target_sections_1;
+
/* Whether to open exec and core files read-only or read-write. */
int write_files = 0;
@@ -93,6 +102,28 @@ exec_open (char *args, int from_tty)
}
static void
+exec_close_1 (void)
+{
+ if (exec_bfd)
+ {
+ bfd *abfd = exec_bfd;
+ char *name = bfd_get_filename (abfd);
+
+ if (!bfd_close (abfd))
+ warning (_("cannot close \"%s\": %s"),
+ name, bfd_errmsg (bfd_get_error ()));
+ xfree (name);
+
+ /* Removing target sections may close the exec_ops target.
+ Clear exec_bfd before doing so to prevent recursion. */
+ exec_bfd = NULL;
+ exec_bfd_mtime = 0;
+
+ remove_target_sections (abfd);
+ }
+}
+
+static void
exec_close (int quitting)
{
int need_symtab_cleanup = 0;
@@ -128,26 +159,20 @@ exec_close (int quitting)
vmap = NULL;
- if (exec_bfd)
- {
- char *name = bfd_get_filename (exec_bfd);
-
- remove_target_sections (exec_bfd);
+ /* Delete all target sections. */
+ resize_section_table
+ (current_target_sections,
+ -resize_section_table (current_target_sections, 0));
- if (!bfd_close (exec_bfd))
- warning (_("cannot close \"%s\": %s"),
- name, bfd_errmsg (bfd_get_error ()));
- xfree (name);
- exec_bfd = NULL;
- exec_bfd_mtime = 0;
- }
+ /* Remove exec file. */
+ exec_close_1 ();
}
void
exec_file_clear (int from_tty)
{
/* Remove exec file. */
- unpush_target (&exec_ops);
+ exec_close_1 ();
if (from_tty)
printf_unfiltered (_("No executable file now.\n"));
@@ -174,7 +199,7 @@ void
exec_file_attach (char *filename, int from_tty)
{
/* Remove any previous exec file. */
- unpush_target (&exec_ops);
+ exec_close_1 ();
/* Now open and digest the file the user requested, if any. */
@@ -229,7 +254,7 @@ exec_file_attach (char *filename, int fr
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": not in executable format: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
@@ -244,7 +269,7 @@ exec_file_attach (char *filename, int fr
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
@@ -254,23 +279,21 @@ exec_file_attach (char *filename, int fr
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": can't find the file sections: %s"),
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 ();
set_gdbarch_from_file (exec_bfd);
- push_target (&exec_ops);
+ /* Add the executable's sections to the current address spaces'
+ list of sections. */
+ add_target_sections (sections, sections_end);
+ xfree (sections);
/* Tell display code (if any) about the changed file name. */
if (deprecated_exec_file_display_hook)
@@ -419,11 +442,11 @@ build_section_table (struct bfd *some_bf
}
void
-concat_section_table (struct target_section_table *table,
- struct target_section *sections,
- struct target_section *sections_end)
+add_target_sections (struct target_section *sections,
+ struct target_section *sections_end)
{
int count;
+ struct target_section_table *table = current_target_sections;
count = sections_end - sections;
@@ -432,6 +455,44 @@ concat_section_table (struct target_sect
int space = resize_section_table (table, count);
memcpy (table->sections + space,
sections, count * sizeof (sections[0]));
+
+ /* If these are the first file sections we can provide memory
+ from, push the file_stratum target. */
+ if (space == 0)
+ push_target (&exec_ops);
+ }
+}
+
+/* Remove all target sections taken from ABFD. */
+
+void
+remove_target_sections (bfd *abfd)
+{
+ 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)
+ {
+ int old_count;
+
+ old_count = resize_section_table (table, dest - src);
+
+ /* If we don't have any more sections to read memory from,
+ remove the file_stratum target from the stack. */
+ if (old_count + (dest - src) == 0)
+ unpush_target (&exec_ops);
}
}
@@ -573,6 +634,12 @@ section_table_xfer_memory_partial (gdb_b
return 0; /* We can't help */
}
+struct target_section_table *
+exec_get_section_table (struct target_ops *ops)
+{
+ return current_target_sections;
+}
+
static LONGEST
exec_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
@@ -757,6 +824,7 @@ Specify the filename of the executable f
exec_ops.to_close = exec_close;
exec_ops.to_attach = find_default_attach;
exec_ops.to_xfer_partial = exec_xfer_partial;
+ exec_ops.to_get_section_table = exec_get_section_table;
exec_ops.to_files_info = exec_files_info;
exec_ops.to_insert_breakpoint = ignore;
exec_ops.to_remove_breakpoint = ignore;
Index: src/gdb/exec.h
===================================================================
--- src.orig/gdb/exec.h 2009-05-30 17:09:35.000000000 +0100
+++ src/gdb/exec.h 2009-05-30 17:09:37.000000000 +0100
@@ -61,12 +61,13 @@ extern int section_table_xfer_memory_par
/* Set the loaded address of a section. */
extern void exec_set_section_address (const char *, int, CORE_ADDR);
+extern void remove_target_sections (bfd *abfd);
+
/* 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);
+extern void add_target_sections (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
Index: src/gdb/solib.c
===================================================================
--- src.orig/gdb/solib.c 2009-05-30 17:09:35.000000000 +0100
+++ src/gdb/solib.c 2009-05-30 17:09:37.000000000 +0100
@@ -665,8 +665,7 @@ update_solib_list (int from_tty, struct
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);
+ add_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/target.c
===================================================================
--- src.orig/gdb/target.c 2009-05-30 17:09:35.000000000 +0100
+++ src/gdb/target.c 2009-05-30 17:12:52.000000000 +0100
@@ -1027,11 +1027,7 @@ target_get_section_table (struct target_
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;
+ return NULL;
}
/* Find a section containing ADDR. */
@@ -2380,39 +2376,6 @@ return_minus_one (void)
return -1;
}
-/* 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 = ¤t_target_sections_1;
-
-/* Remove all target sections taken from ABFD. */
-
-void
-remove_target_sections (bfd *abfd)
-{
- 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-30 17:09:35.000000000 +0100
+++ src/gdb/target.h 2009-05-30 17:12:05.000000000 +0100
@@ -1208,12 +1208,6 @@ struct target_section_table
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);
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
New combined patch below:
2009-05-30 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): Request a TARGET_OBJECT_RAW_MEMORY object
instead of TARGET_OBJECT_MEMORY.
(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.
(target_get_section_table): Declare.
(target_resize_to_sections): Delete declaration.
(remove_target_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): Add the shared library sections
to the current target sections table.
* exec.c (current_target_sections_1): New global.
(current_target_sections): New global.
(exec_close_1): New function, refactored from exec_close. Remove
the exec_bfd's sections from the current target sections table.
Adjust to not use to_sections.
(exec_close): Remove all target sections. Call exec_close_1.
(exec_file_clear): Use exec_close_1 instead of unpushing the
target.
(exec_file_attach): Likewise. Adjust to not use to_sections. Add
exec_bfd's sections to the current target sections table. Don't
push the exec_ops target here.
(resize_section_table): New.
(add_target_sections): New.
(remove_target_sections): Moved here.
(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_get_section_table): New.
(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 sections table.
(init_exec_ops): Do not register a deprecated_xfer_memory
callback. Register to_xfer_partial and to_get_section_table
callbacks.
* 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.
(remove_target_sections): Declare here.
(add_target_sections): Declare.
(print_section_info): Declare here.
* gdbcore.h (deprecated_core_resize_section_table): Declare.
Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c 2009-05-30 17:24:30.000000000 +0100
+++ src/gdb/target.c 2009-05-30 17:24:47.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,33 @@ 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);
+
+ return NULL;
+}
+
/* 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 +1064,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 +1722,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,96 +2376,6 @@ 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.
- */
-
-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);
-
- /* 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);
- }
-}
-
-
-
-
/* 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-30 17:24:30.000000000 +0100
+++ src/gdb/target.h 2009-05-30 17:24:47.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,24 @@ 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;
+};
+
/* 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 +1248,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-30 17:24:30.000000000 +0100
+++ src/gdb/bfd-target.c 2009-05-30 17:24:45.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-30 17:24:30.000000000 +0100
+++ src/gdb/corelow.c 2009-05-30 17:24:45.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);
}
\f
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-30 17:24:30.000000000 +0100
+++ src/gdb/solib.c 2009-05-30 17:24:47.000000000 +0100
@@ -661,21 +661,11 @@ 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. */
+ add_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-30 17:24:30.000000000 +0100
+++ src/gdb/exec.c 2009-05-30 17:24:47.000000000 +0100
@@ -71,6 +71,15 @@ struct target_ops exec_ops;
bfd *exec_bfd = NULL;
long exec_bfd_mtime = 0;
+/* 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 set of target sections matching the sections mapped into the
+ current inferior's address space. */
+struct target_section_table *current_target_sections = ¤t_target_sections_1;
+
/* Whether to open exec and core files read-only or read-write. */
int write_files = 0;
@@ -93,6 +102,28 @@ exec_open (char *args, int from_tty)
}
static void
+exec_close_1 (void)
+{
+ if (exec_bfd)
+ {
+ bfd *abfd = exec_bfd;
+ char *name = bfd_get_filename (abfd);
+
+ if (!bfd_close (abfd))
+ warning (_("cannot close \"%s\": %s"),
+ name, bfd_errmsg (bfd_get_error ()));
+ xfree (name);
+
+ /* Removing target sections may close the exec_ops target.
+ Clear exec_bfd before doing so to prevent recursion. */
+ exec_bfd = NULL;
+ exec_bfd_mtime = 0;
+
+ remove_target_sections (abfd);
+ }
+}
+
+static void
exec_close (int quitting)
{
int need_symtab_cleanup = 0;
@@ -128,31 +159,20 @@ exec_close (int quitting)
vmap = NULL;
- if (exec_bfd)
- {
- char *name = bfd_get_filename (exec_bfd);
-
- if (!bfd_close (exec_bfd))
- warning (_("cannot close \"%s\": %s"),
- name, bfd_errmsg (bfd_get_error ()));
- xfree (name);
- exec_bfd = NULL;
- exec_bfd_mtime = 0;
- }
+ /* Delete all target sections. */
+ resize_section_table
+ (current_target_sections,
+ -resize_section_table (current_target_sections, 0));
- if (exec_ops.to_sections)
- {
- xfree (exec_ops.to_sections);
- exec_ops.to_sections = NULL;
- exec_ops.to_sections_end = NULL;
- }
+ /* Remove exec file. */
+ exec_close_1 ();
}
void
exec_file_clear (int from_tty)
{
/* Remove exec file. */
- unpush_target (&exec_ops);
+ exec_close_1 ();
if (from_tty)
printf_unfiltered (_("No executable file now.\n"));
@@ -179,7 +199,7 @@ void
exec_file_attach (char *filename, int from_tty)
{
/* Remove any previous exec file. */
- unpush_target (&exec_ops);
+ exec_close_1 ();
/* Now open and digest the file the user requested, if any. */
@@ -195,6 +215,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,
@@ -233,7 +254,7 @@ exec_file_attach (char *filename, int fr
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": not in executable format: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
@@ -248,18 +269,17 @@ exec_file_attach (char *filename, int fr
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
#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, §ions, §ions_end))
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
@@ -270,7 +290,10 @@ exec_file_attach (char *filename, int fr
set_gdbarch_from_file (exec_bfd);
- push_target (&exec_ops);
+ /* Add the executable's sections to the current address spaces'
+ list of sections. */
+ add_target_sections (sections, sections_end);
+ xfree (sections);
/* Tell display code (if any) about the changed file name. */
if (deprecated_exec_file_display_hook)
@@ -370,6 +393,33 @@ 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;
+
+ if (new_count)
+ {
+ table->sections
+ = xrealloc (table->sections, sizeof (struct target_section) * new_count);
+ table->sections_end = table->sections + new_count;
+ }
+ else
+ {
+ xfree (table->sections);
+ table->sections = table->sections_end = NULL;
+ }
+
+ return old_count;
+}
+
/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
Returns 0 if OK, 1 on error. */
@@ -390,6 +440,62 @@ build_section_table (struct bfd *some_bf
/* We could realloc the table, but it probably loses for most files. */
return 0;
}
+
+void
+add_target_sections (struct target_section *sections,
+ struct target_section *sections_end)
+{
+ int count;
+ struct target_section_table *table = current_target_sections;
+
+ count = sections_end - sections;
+
+ if (count > 0)
+ {
+ int space = resize_section_table (table, count);
+ memcpy (table->sections + space,
+ sections, count * sizeof (sections[0]));
+
+ /* If these are the first file sections we can provide memory
+ from, push the file_stratum target. */
+ if (space == 0)
+ push_target (&exec_ops);
+ }
+}
+
+/* Remove all target sections taken from ABFD. */
+
+void
+remove_target_sections (bfd *abfd)
+{
+ 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)
+ {
+ int old_count;
+
+ old_count = resize_section_table (table, dest - src);
+
+ /* If we don't have any more sections to read memory from,
+ remove the file_stratum target from the stack. */
+ if (old_count + (dest - src) == 0)
+ unpush_target (&exec_ops);
+ }
+}
+
\f
static void
bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
@@ -467,22 +573,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 +599,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 +618,49 @@ 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)
+struct target_section_table *
+exec_get_section_table (struct target_ops *ops)
{
- if (readbuf != NULL)
- return section_table_xfer_memory (offset, readbuf, len, 0,
- sections, sections_end, NULL);
- else
- return section_table_xfer_memory (offset, (gdb_byte *) writebuf, len, 1,
- sections, sections_end, NULL);
+ return current_target_sections;
}
-/* 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)
+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)
{
- 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;
- }
- }
+ struct target_section_table *table = target_get_section_table (ops);
- return section_table_xfer_memory (memaddr, myaddr, len, write,
- target->to_sections,
- target->to_sections_end,
- section_name);
+ if (object == TARGET_OBJECT_MEMORY)
+ return section_table_xfer_memory_partial (readbuf, writebuf,
+ offset, len,
+ table->sections,
+ table->sections_end,
+ NULL);
+ else
+ return -1;
}
\f
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 +672,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 +696,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 +732,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 +744,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 +772,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 +823,8 @@ 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_get_section_table = exec_get_section_table;
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-30 17:24:31.000000000 +0100
+++ src/gdb/infrun.c 2009-05-30 17:24:45.000000000 +0100
@@ -2448,15 +2448,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, ¤t_target, auto_solib_add);
#else
@@ -3447,15 +3438,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, ¤t_target, auto_solib_add);
#else
Index: src/gdb/rs6000-nat.c
===================================================================
--- src.orig/gdb/rs6000-nat.c 2009-05-30 17:24:30.000000000 +0100
+++ src/gdb/rs6000-nat.c 2009-05-30 17:24:45.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-30 17:24:30.000000000 +0100
+++ src/gdb/exec.h 2009-05-30 17:24:47.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,26 @@ 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);
+extern void remove_target_sections (bfd *abfd);
+
+/* Append the sections array defined by [SECTIONS..SECTIONS_END[ to
+ TABLE. TABLE's memory is reallocated to fit in the new
+ sections. */
+extern void add_target_sections (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-30 17:24:30.000000000 +0100
+++ src/gdb/gdbcore.h 2009-05-30 17:24:45.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) */
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v2] Yank out target_ops->to_sections
2009-05-29 14:13 ` Pedro Alves
2009-05-30 16:39 ` [RFC,v3] " Pedro Alves
@ 2009-06-02 11:06 ` Ulrich Weigand
2009-06-03 16:26 ` Pedro Alves
1 sibling, 1 reply; 11+ messages in thread
From: Ulrich Weigand @ 2009-06-02 11:06 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> I've been thinking for a while that the exec_ops target
> should be pushed whenever we have any kind of file loaded (main
> executable or dynamic shared module) that we can read memory
> from. It implements the file_stratum after all, and target.h says:
>
> file_stratum, /* Executable files, etc */
> ^^^
I agree, and I like the approach in your v3 patch :-)
> Here's a stripped down version of what I've got here currently:
>
> /* A symbol space represents a symbolic view of an address space. It
> holds all the data associated with a non-running-yet program (main
> executable, main symbols), and when an inferior is running and is
> bound to it, includes the list of its mapped in shared libraries.
>
> In the traditional debugging scenario, there's a 1-1 correspondence
> among symbol spaces, inferiors and address spaces, like so:
>
> sspace1 (prog1) <--> inf1(pid1) <--> aspace1
Thanks for the detailed description! This makes sense to me.
> There still needs to be a global somewhere, there's no way around it,
> but, it will be the "current_symbol_space", not the target sections.
> This global is then switched whenever we need to switch context
> --- switch thread, insert breakpoints, or by user command, to e.g.,
> prepare to start a new inferior --- in a sense, this structure holds
> the globals that currently form a "prototype" for an inferior.
This is the one part I'm not sure I agree with. I would have hoped
we could actually get *rid* of all those globals, at least as far
as the GDB core is concerned. (There may be globals in the UI code
where it makes sense, to represent conceptually global settings at
the the UI level like the notion of the "selected frame". But all
of GDB's core should IMO be fully parameterized and not rely on
globals. I'd expect this could be achieved by passing "inferior"
or "thread" arguments to some of the central functions ...)
> > Also, I'm not completely sure I understand the implications of the solib_add
> > change. The old method allowed callers to explicitly ask that the library
> > sections be *not* added to the section table, and several callers did that.
> > With your patch, sections are always added. Was it always an error to not
> > add sections? I'm not really sure why this feature was introduced ...
>
> I think that historically, it was the other way around. They were never
> added in the beggining, and when shared libraries support for core
> files was added to GDB, the corresponing targets that supported it
> were adjusted to pass a target_ops pointer.
>
> We've currently got more use for the target sections (trust-readonly-sections,
> for once), so I think we should always add the sections. I've done a bit
> of history digging. Looking at gdb 3.98's sources, and I see in solib.c:
Thanks for doing this research! You've convinced me it should be fine
to unconditionally add solib target sections.
> solib-irix.c: solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
>
> I can't see a native .mt file pulling this in.
It's a target property:
mips*-sgi-irix5*)
# Target: MIPS SGI running Irix 5
gdb_target_obs="mips-tdep.o mips-irix-tdep.o solib.o solib-irix.o"
;;
mips*-sgi-irix6*)
# Target: MIPS SGI running Irix 6.x
gdb_target_obs="mips-tdep.o mips-irix-tdep.o solib.o solib-irix.o"
;;
> This shared library support can't be being used with core inferiors, since
> irix_solib_create_inferior_hook always wants to resume the target.
Hmm, good point.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v3] Yank out target_ops->to_sections
2009-05-30 16:39 ` [RFC,v3] " Pedro Alves
@ 2009-06-02 11:10 ` Ulrich Weigand
2009-06-03 18:57 ` Pedro Alves
0 siblings, 1 reply; 11+ messages in thread
From: Ulrich Weigand @ 2009-06-02 11:10 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> > I've been thinking for a while that the exec_ops target
> > should be pushed whenever we have any kind of file loaded (main
> > executable or dynamic shared module) that we can read memory
> > from. It implements the file_stratum after all, and target.h says:
> >
> > file_stratum, /* Executable files, etc */
> > ^^^
>
> I think I'm convinced this it is the best to do, design-wise.
> This way, we'll still be able to read memory from shared library
> sections if no main executable is loaded into GDB (e.g., gdb -c foo,
> without specifying an executable needs this).
>
> I've given it a try, and, it does look like a cleaner solution
> long term to me. Even PIE executables blur the distintion of
> what is specified as main executable vs what is reported by the
> dynamic loader a bit more. Another interesting fact, is that
> the "vmap" bits spread about in exec.c for xcoffsolib are quite
> similar in spirit to this "set of target sections we can read file
> read memory from". Find below an incremental patch that applies
> on top of the v2 one I posted (the changes aren't that
> many: push/unpush of exec_ops moved, plus that default of
> target_get_section_table you pointed out goes away, replaced by
> the exec_ops target returning the current set of target sections).
> At the bottom there's the new v3 combined patch.
>
> Please let me know what you think about this. Re-tested on x86_64-linux.
I think this makes sense. Your new combined patch looks good to me.
> Index: src/gdb/exec.c
> ===================================================================
> --- src.orig/gdb/exec.c 2009-05-30 17:24:30.000000000 +0100
> +++ src/gdb/exec.c 2009-05-30 17:24:47.000000000 +0100
> @@ -71,6 +71,15 @@ struct target_ops exec_ops;
> bfd *exec_bfd = NULL;
> long exec_bfd_mtime = 0;
>
> +/* 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 set of target sections matching the sections mapped into the
> + current inferior's address space. */
> +struct target_section_table *current_target_sections = ¤t_target_sections_1;
This can be "static" now, right?
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v2] Yank out target_ops->to_sections
2009-06-02 11:06 ` [RFC,v2] " Ulrich Weigand
@ 2009-06-03 16:26 ` Pedro Alves
2009-06-03 19:36 ` Ulrich Weigand
0 siblings, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2009-06-03 16:26 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich Weigand
On Tuesday 02 June 2009 12:05:43, Ulrich Weigand wrote:
> > There still needs to be a global somewhere, there's no way around it,
> > but, it will be the "current_symbol_space", not the target sections.
> > This global is then switched whenever we need to switch context
> > --- switch thread, insert breakpoints, or by user command, to e.g.,
> > prepare to start a new inferior --- in a sense, this structure holds
> > the globals that currently form a "prototype" for an inferior.
>
> This is the one part I'm not sure I agree with. I would have hoped
> we could actually get *rid* of all those globals, at least as far
> as the GDB core is concerned. (There may be globals in the UI code
> where it makes sense, to represent conceptually global settings at
> the the UI level like the notion of the "selected frame". But all
> of GDB's core should IMO be fully parameterized and not rely on
> globals.
> I'd expect this could be achieved by passing "inferior"
> or "thread" arguments to some of the central functions ...)
I don't think anyone disagrees with that. With my proposal, there will
be ways to get from a frame/thread/inferior/whatever to the corresponding
address/symbol space, and where possible we'll use those. However,
consider the case where you have more than one program
loaded (say, /bin/cat and /bin/echo), and haven't started execution in
either of those yet. There is no "inferior" or "thread" object yet
for any of them, and you can't distinguish with inferior_ptid
either (it's null_ptid in both cases). Currently, all this state
is spread around in globals all over (e.g., even exec_bfd can be
accessed in the most twisted code paths). But, it's the "prepare to
start a new inferior" part that ends up requiring the global. I'm
proposing to aggregate them somewhere, but we still need to have a
global storing a pointer to the "current context" somewhere. I agree
that ideally then this global should only be accessed at high
layers, close to the UI, and that we should only need to pass to each
major component what it really needs and handles, as arguments.
But, that really *has* to be a long term goal. Just getting rid
of a single one of those globals (by passing them in arguments) is
a *lot* of hair for practically 0 gain at this point. Since we do
have to aggregate and store these globals somewhere, I think that
I'm taking a good first step. IMO, it's much better to just switch
a pointer than to come up with the old "infrun.c|thread.c:context_switch"
mess. We can then *incrementally* clean up interfaces, as we'll
then have a clearly visible goal to achieve. Anyway, things
will surely get clearer a bit further down the line when I post
the main juicy bits for discussion.
--
Pedro Alves
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v3] Yank out target_ops->to_sections
2009-06-02 11:10 ` Ulrich Weigand
@ 2009-06-03 18:57 ` Pedro Alves
0 siblings, 0 replies; 11+ messages in thread
From: Pedro Alves @ 2009-06-03 18:57 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich Weigand
On Tuesday 02 June 2009 12:10:24, Ulrich Weigand wrote:
> I think this makes sense. Your new combined patch looks good to me.
Thank you very much for the review. Deeply appreciated.
> > Index: src/gdb/exec.c
> > ===================================================================
> > --- src.orig/gdb/exec.c 2009-05-30 17:24:30.000000000 +0100
> > +++ src/gdb/exec.c 2009-05-30 17:24:47.000000000 +0100
> > @@ -71,6 +71,15 @@ struct target_ops exec_ops;
> > bfd *exec_bfd = NULL;
> > long exec_bfd_mtime = 0;
> >
> > +/* 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 set of target sections matching the sections mapped into the
> > + current inferior's address space. */
> > +struct target_section_table *current_target_sections = ¤t_target_sections_1;
>
> This can be "static" now, right?
Indeed. I had a couple of other cases that could be made static. Fixed now,
and checked in, as below.
Thanks again!
--
Pedro Alves
2009-06-03 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): Request a TARGET_OBJECT_RAW_MEMORY object
instead of TARGET_OBJECT_MEMORY.
(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.
(target_get_section_table): Declare.
(target_resize_to_sections): Delete declaration.
(remove_target_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): Add the shared library sections
to the current target sections table.
* exec.c (current_target_sections_1): New global.
(current_target_sections): New global.
(exec_close_1): New function, refactored from exec_close. Remove
the exec_bfd's sections from the current target sections table.
Adjust to not use to_sections.
(exec_close): Remove all target sections. Call exec_close_1.
(exec_file_clear): Use exec_close_1 instead of unpushing the
target.
(exec_file_attach): Likewise. Adjust to not use to_sections. Add
exec_bfd's sections to the current target sections table. Don't
push the exec_ops target here.
(resize_section_table): New.
(add_target_sections): New.
(remove_target_sections): Moved here.
(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_get_section_table): New.
(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 sections table.
(init_exec_ops): Do not register a deprecated_xfer_memory
callback. Register to_xfer_partial and to_get_section_table
callbacks.
* 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.
(remove_target_sections): Declare here.
(add_target_sections): 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 | 286 ++++++++++++++++++++++++++++++++++---------------------
gdb/exec.h | 26 ++++-
gdb/gdbcore.h | 2
gdb/infrun.c | 18 ---
gdb/rs6000-nat.c | 3
gdb/solib.c | 20 ---
gdb/target.c | 163 ++++++++++---------------------
gdb/target.h | 32 +++---
10 files changed, 353 insertions(+), 290 deletions(-)
Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c 2009-06-03 19:34:02.000000000 +0100
+++ src/gdb/target.c 2009-06-03 19:42:33.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,33 @@ 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);
+
+ return NULL;
+}
+
/* Find a section containing ADDR. */
+
struct target_section *
target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
{
+ struct target_section_table *table = target_get_section_table (target);
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 +1064,43 @@ 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;
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);
+ {
+ table = target_get_section_table (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 +1725,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,96 +2379,6 @@ 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.
- */
-
-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);
-
- /* 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);
- }
-}
-
-
-
-
/* 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-06-03 19:34:03.000000000 +0100
+++ src/gdb/target.h 2009-06-03 19:42:33.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
@@ -412,6 +413,7 @@ struct target_ops
void (*to_rcmd) (char *command, struct ui_file *output);
char *(*to_pid_to_exec_file) (int pid);
void (*to_log_command) (const char *);
+ struct target_section_table *(*to_get_section_table) (struct target_ops *);
enum strata to_stratum;
int to_has_all_memory;
int to_has_memory;
@@ -420,10 +422,6 @@ 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;
/* ASYNC target controls */
int (*to_can_async_p) (void);
int (*to_is_async_p) (void);
@@ -668,9 +666,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 +728,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 +1199,24 @@ struct target_section
bfd *bfd; /* BFD file pointer */
};
+/* Holds an array of target sections. Defined by [SECTIONS..SECTIONS_END[. */
+
+struct target_section_table
+{
+ struct target_section *sections;
+ struct target_section *sections_end;
+};
+
/* 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 +1247,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-06-03 19:34:02.000000000 +0100
+++ src/gdb/bfd-target.c 2009-06-03 19:42:33.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;
}
}
+static 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-06-03 19:34:03.000000000 +0100
+++ src/gdb/corelow.c 2009-06-03 19:42:33.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. */
+static 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);
}
\f
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-06-03 19:34:03.000000000 +0100
+++ src/gdb/solib.c 2009-06-03 19:42:33.000000000 +0100
@@ -661,21 +661,11 @@ 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. */
+ add_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-06-03 19:34:02.000000000 +0100
+++ src/gdb/exec.c 2009-06-03 19:42:33.000000000 +0100
@@ -71,6 +71,16 @@ struct target_ops exec_ops;
bfd *exec_bfd = NULL;
long exec_bfd_mtime = 0;
+/* 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 set of target sections matching the sections mapped into the
+ current inferior's address space. */
+static struct target_section_table *current_target_sections
+ = ¤t_target_sections_1;
+
/* Whether to open exec and core files read-only or read-write. */
int write_files = 0;
@@ -92,6 +102,31 @@ exec_open (char *args, int from_tty)
exec_file_attach (args, from_tty);
}
+/* Close and clear exec_bfd. If we end up with no target sections to
+ read memory from, this unpushes the exec_ops target. */
+
+static void
+exec_close_1 (void)
+{
+ if (exec_bfd)
+ {
+ bfd *abfd = exec_bfd;
+ char *name = bfd_get_filename (abfd);
+
+ if (!bfd_close (abfd))
+ warning (_("cannot close \"%s\": %s"),
+ name, bfd_errmsg (bfd_get_error ()));
+ xfree (name);
+
+ /* Removing target sections may close the exec_ops target.
+ Clear exec_bfd before doing so to prevent recursion. */
+ exec_bfd = NULL;
+ exec_bfd_mtime = 0;
+
+ remove_target_sections (abfd);
+ }
+}
+
static void
exec_close (int quitting)
{
@@ -128,31 +163,20 @@ exec_close (int quitting)
vmap = NULL;
- if (exec_bfd)
- {
- char *name = bfd_get_filename (exec_bfd);
-
- if (!bfd_close (exec_bfd))
- warning (_("cannot close \"%s\": %s"),
- name, bfd_errmsg (bfd_get_error ()));
- xfree (name);
- exec_bfd = NULL;
- exec_bfd_mtime = 0;
- }
+ /* Delete all target sections. */
+ resize_section_table
+ (current_target_sections,
+ -resize_section_table (current_target_sections, 0));
- if (exec_ops.to_sections)
- {
- xfree (exec_ops.to_sections);
- exec_ops.to_sections = NULL;
- exec_ops.to_sections_end = NULL;
- }
+ /* Remove exec file. */
+ exec_close_1 ();
}
void
exec_file_clear (int from_tty)
{
/* Remove exec file. */
- unpush_target (&exec_ops);
+ exec_close_1 ();
if (from_tty)
printf_unfiltered (_("No executable file now.\n"));
@@ -179,7 +203,7 @@ void
exec_file_attach (char *filename, int from_tty)
{
/* Remove any previous exec file. */
- unpush_target (&exec_ops);
+ exec_close_1 ();
/* Now open and digest the file the user requested, if any. */
@@ -195,6 +219,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,
@@ -233,7 +258,7 @@ exec_file_attach (char *filename, int fr
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": not in executable format: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
@@ -248,18 +273,17 @@ exec_file_attach (char *filename, int fr
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
#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, §ions, §ions_end))
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close_1 ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
@@ -270,7 +294,10 @@ exec_file_attach (char *filename, int fr
set_gdbarch_from_file (exec_bfd);
- push_target (&exec_ops);
+ /* Add the executable's sections to the current address spaces'
+ list of sections. */
+ add_target_sections (sections, sections_end);
+ xfree (sections);
/* Tell display code (if any) about the changed file name. */
if (deprecated_exec_file_display_hook)
@@ -370,6 +397,33 @@ 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;
+
+ if (new_count)
+ {
+ table->sections = xrealloc (table->sections,
+ sizeof (struct target_section) * new_count);
+ table->sections_end = table->sections + new_count;
+ }
+ else
+ {
+ xfree (table->sections);
+ table->sections = table->sections_end = NULL;
+ }
+
+ return old_count;
+}
+
/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
Returns 0 if OK, 1 on error. */
@@ -390,6 +444,65 @@ build_section_table (struct bfd *some_bf
/* We could realloc the table, but it probably loses for most files. */
return 0;
}
+
+/* Add the sections array defined by [SECTIONS..SECTIONS_END[ to the
+ current set of target sections. */
+
+void
+add_target_sections (struct target_section *sections,
+ struct target_section *sections_end)
+{
+ int count;
+ struct target_section_table *table = current_target_sections;
+
+ count = sections_end - sections;
+
+ if (count > 0)
+ {
+ int space = resize_section_table (table, count);
+ memcpy (table->sections + space,
+ sections, count * sizeof (sections[0]));
+
+ /* If these are the first file sections we can provide memory
+ from, push the file_stratum target. */
+ if (space == 0)
+ push_target (&exec_ops);
+ }
+}
+
+/* Remove all target sections taken from ABFD. */
+
+void
+remove_target_sections (bfd *abfd)
+{
+ 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)
+ {
+ int old_count;
+
+ old_count = resize_section_table (table, dest - src);
+
+ /* If we don't have any more sections to read memory from,
+ remove the file_stratum target from the stack. */
+ if (old_count + (dest - src) == 0)
+ unpush_target (&exec_ops);
+ }
+}
+
\f
static void
bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
@@ -467,22 +580,21 @@ 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 = memaddr + len;
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 +605,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 +624,49 @@ 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)
+struct target_section_table *
+exec_get_section_table (struct target_ops *ops)
{
- if (readbuf != NULL)
- return section_table_xfer_memory (offset, readbuf, len, 0,
- sections, sections_end, NULL);
- else
- return section_table_xfer_memory (offset, (gdb_byte *) writebuf, len, 1,
- sections, sections_end, NULL);
+ return current_target_sections;
}
-/* 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)
+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)
{
- 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;
- }
- }
+ struct target_section_table *table = target_get_section_table (ops);
- return section_table_xfer_memory (memaddr, myaddr, len, write,
- target->to_sections,
- target->to_sections_end,
- section_name);
+ if (object == TARGET_OBJECT_MEMORY)
+ return section_table_xfer_memory_partial (readbuf, writebuf,
+ offset, len,
+ table->sections,
+ table->sections_end,
+ NULL);
+ else
+ return -1;
}
\f
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 +678,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 +702,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 +738,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 +750,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 +778,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 +829,8 @@ 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_get_section_table = exec_get_section_table;
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-06-03 19:34:47.000000000 +0100
+++ src/gdb/infrun.c 2009-06-03 19:42:33.000000000 +0100
@@ -2448,15 +2448,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, ¤t_target, auto_solib_add);
#else
@@ -3446,15 +3437,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, ¤t_target, auto_solib_add);
#else
Index: src/gdb/rs6000-nat.c
===================================================================
--- src.orig/gdb/rs6000-nat.c 2009-06-03 19:34:03.000000000 +0100
+++ src/gdb/rs6000-nat.c 2009-06-03 19:42:33.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-06-03 19:34:03.000000000 +0100
+++ src/gdb/exec.h 2009-06-03 19:42:33.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,28 @@ 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);
+/* Remove all target sections taken from ABFD. */
+
+extern void remove_target_sections (bfd *abfd);
+
+/* Add the sections array defined by [SECTIONS..SECTIONS_END[ to the
+ current set of target sections. */
+
+extern void add_target_sections (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-06-03 19:34:03.000000000 +0100
+++ src/gdb/gdbcore.h 2009-06-03 19:42:33.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) */
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC,v2] Yank out target_ops->to_sections
2009-06-03 16:26 ` Pedro Alves
@ 2009-06-03 19:36 ` Ulrich Weigand
0 siblings, 0 replies; 11+ messages in thread
From: Ulrich Weigand @ 2009-06-03 19:36 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> I don't think anyone disagrees with that. With my proposal, there will
> be ways to get from a frame/thread/inferior/whatever to the corresponding
> address/symbol space, and where possible we'll use those. However,
> consider the case where you have more than one program
> loaded (say, /bin/cat and /bin/echo), and haven't started execution in
> either of those yet. There is no "inferior" or "thread" object yet
> for any of them, and you can't distinguish with inferior_ptid=20
> either (it's null_ptid in both cases). Currently, all this state
> is spread around in globals all over (e.g., even exec_bfd can be
> accessed in the most twisted code paths). But, it's the "prepare to
> start a new inferior" part that ends up requiring the global.
Ah, I see.
> I'm proposing to aggregate them somewhere, but we still need to have a
> global storing a pointer to the "current context" somewhere. I agree
> that ideally then this global should only be accessed at high
> layers, close to the UI, and that we should only need to pass to each
> major component what it really needs and handles, as arguments.
> But, that really *has* to be a long term goal. Just getting rid
> of a single one of those globals (by passing them in arguments) is
> a *lot* of hair for practically 0 gain at this point. Since we do
> have to aggregate and store these globals somewhere, I think that
> I'm taking a good first step. IMO, it's much better to just switch
> a pointer than to come up with the old "infrun.c|thread.c:context_switch"
> mess. We can then *incrementally* clean up interfaces, as we'll
> then have a clearly visible goal to achieve. Anyway, things
> will surely get clearer a bit further down the line when I post
> the main juicy bits for discussion.
OK, thanks for the explanation ... Looking forward to your patches :-)
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2009-06-03 19:36 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-24 1:35 [RFC,v2] Yank out target_ops->to_sections Pedro Alves
2009-05-26 23:30 ` Pedro Alves
2009-05-27 1:30 ` Doug Evans
2009-05-27 18:24 ` Ulrich Weigand
2009-05-29 14:13 ` Pedro Alves
2009-05-30 16:39 ` [RFC,v3] " Pedro Alves
2009-06-02 11:10 ` Ulrich Weigand
2009-06-03 18:57 ` Pedro Alves
2009-06-02 11:06 ` [RFC,v2] " Ulrich Weigand
2009-06-03 16:26 ` Pedro Alves
2009-06-03 19:36 ` Ulrich Weigand
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox