mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 01:50:24 +08:00
* 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.
This commit is contained in:
@ -1,3 +1,83 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
2009-06-03 Ulrich Weigand <uweigand@de.ibm.com>
|
2009-06-03 Ulrich Weigand <uweigand@de.ibm.com>
|
||||||
|
|
||||||
* value.h (struct internalvar): Remove.
|
* value.h (struct internalvar): Remove.
|
||||||
|
@ -32,35 +32,52 @@ target_bfd_xfer_partial (struct target_ops *ops,
|
|||||||
switch (object)
|
switch (object)
|
||||||
{
|
{
|
||||||
case TARGET_OBJECT_MEMORY:
|
case TARGET_OBJECT_MEMORY:
|
||||||
return section_table_xfer_memory_partial (readbuf, writebuf, offset, len,
|
{
|
||||||
ops->to_sections,
|
struct target_section_table *table = ops->to_data;
|
||||||
ops->to_sections_end);
|
return section_table_xfer_memory_partial (readbuf, writebuf, offset, len,
|
||||||
|
table->sections,
|
||||||
|
table->sections_end,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct target_section_table *
|
||||||
|
target_bfd_get_section_table (struct target_ops *ops)
|
||||||
|
{
|
||||||
|
return ops->to_data;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
target_bfd_xclose (struct target_ops *t, int quitting)
|
target_bfd_xclose (struct target_ops *t, int quitting)
|
||||||
{
|
{
|
||||||
bfd_close (t->to_data);
|
struct target_section_table *table = t->to_data;
|
||||||
xfree (t->to_sections);
|
if (table->sections)
|
||||||
|
bfd_close (table->sections->bfd);
|
||||||
|
xfree (table->sections);
|
||||||
|
xfree (table);
|
||||||
xfree (t);
|
xfree (t);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct target_ops *
|
struct target_ops *
|
||||||
target_bfd_reopen (struct bfd *bfd)
|
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_shortname = "bfd";
|
||||||
t->to_longname = _("BFD backed target");
|
t->to_longname = _("BFD backed target");
|
||||||
t->to_doc = _("You should never see this");
|
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_xfer_partial = target_bfd_xfer_partial;
|
||||||
t->to_xclose = target_bfd_xclose;
|
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;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,14 @@ static struct core_fns *core_vec = NULL;
|
|||||||
|
|
||||||
struct gdbarch *core_gdbarch = 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 void core_files_info (struct target_ops *);
|
||||||
|
|
||||||
static struct core_fns *sniff_core_bfd (bfd *);
|
static struct core_fns *sniff_core_bfd (bfd *);
|
||||||
@ -203,18 +211,16 @@ core_close (int quitting)
|
|||||||
comments in clear_solib in solib.c. */
|
comments in clear_solib in solib.c. */
|
||||||
clear_solib ();
|
clear_solib ();
|
||||||
|
|
||||||
|
xfree (core_data->sections);
|
||||||
|
xfree (core_data);
|
||||||
|
core_data = NULL;
|
||||||
|
|
||||||
name = bfd_get_filename (core_bfd);
|
name = bfd_get_filename (core_bfd);
|
||||||
if (!bfd_close (core_bfd))
|
if (!bfd_close (core_bfd))
|
||||||
warning (_("cannot close \"%s\": %s"),
|
warning (_("cannot close \"%s\": %s"),
|
||||||
name, bfd_errmsg (bfd_get_error ()));
|
name, bfd_errmsg (bfd_get_error ()));
|
||||||
xfree (name);
|
xfree (name);
|
||||||
core_bfd = NULL;
|
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_vec = NULL;
|
||||||
core_gdbarch = NULL;
|
core_gdbarch = NULL;
|
||||||
@ -347,9 +353,11 @@ core_open (char *filename, int from_tty)
|
|||||||
|
|
||||||
validate_files ();
|
validate_files ();
|
||||||
|
|
||||||
|
core_data = XZALLOC (struct target_section_table);
|
||||||
|
|
||||||
/* Find the data section */
|
/* Find the data section */
|
||||||
if (build_section_table (core_bfd, &core_ops.to_sections,
|
if (build_section_table (core_bfd,
|
||||||
&core_ops.to_sections_end))
|
&core_data->sections, &core_data->sections_end))
|
||||||
error (_("\"%s\": Can't find sections: %s"),
|
error (_("\"%s\": Can't find sections: %s"),
|
||||||
bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
|
bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
|
||||||
|
|
||||||
@ -434,6 +442,23 @@ core_detach (struct target_ops *ops, char *args, int from_tty)
|
|||||||
printf_filtered (_("No core file now.\n"));
|
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
|
/* Try to retrieve registers from a section in core_bfd, and supply
|
||||||
them to core_vec->core_read_registers, as the register set numbered
|
them to core_vec->core_read_registers, as the register set numbered
|
||||||
@ -562,7 +587,7 @@ get_core_registers (struct target_ops *ops,
|
|||||||
static void
|
static void
|
||||||
core_files_info (struct target_ops *t)
|
core_files_info (struct target_ops *t)
|
||||||
{
|
{
|
||||||
print_section_info (t, core_bfd);
|
print_section_info (core_data, core_bfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LONGEST
|
static LONGEST
|
||||||
@ -573,13 +598,11 @@ core_xfer_partial (struct target_ops *ops, enum target_object object,
|
|||||||
switch (object)
|
switch (object)
|
||||||
{
|
{
|
||||||
case TARGET_OBJECT_MEMORY:
|
case TARGET_OBJECT_MEMORY:
|
||||||
if (readbuf)
|
return section_table_xfer_memory_partial (readbuf, writebuf,
|
||||||
return (*ops->deprecated_xfer_memory) (offset, readbuf,
|
offset, len,
|
||||||
len, 0/*read*/, NULL, ops);
|
core_data->sections,
|
||||||
if (writebuf)
|
core_data->sections_end,
|
||||||
return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
|
NULL);
|
||||||
len, 1/*write*/, NULL, ops);
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case TARGET_OBJECT_AUXV:
|
case TARGET_OBJECT_AUXV:
|
||||||
if (readbuf)
|
if (readbuf)
|
||||||
@ -738,7 +761,6 @@ init_core_ops (void)
|
|||||||
core_ops.to_detach = core_detach;
|
core_ops.to_detach = core_detach;
|
||||||
core_ops.to_fetch_registers = get_core_registers;
|
core_ops.to_fetch_registers = get_core_registers;
|
||||||
core_ops.to_xfer_partial = core_xfer_partial;
|
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_files_info = core_files_info;
|
||||||
core_ops.to_insert_breakpoint = ignore;
|
core_ops.to_insert_breakpoint = ignore;
|
||||||
core_ops.to_remove_breakpoint = ignore;
|
core_ops.to_remove_breakpoint = ignore;
|
||||||
|
286
gdb/exec.c
286
gdb/exec.c
@ -71,6 +71,16 @@ struct target_ops exec_ops;
|
|||||||
bfd *exec_bfd = NULL;
|
bfd *exec_bfd = NULL;
|
||||||
long exec_bfd_mtime = 0;
|
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. */
|
/* Whether to open exec and core files read-only or read-write. */
|
||||||
|
|
||||||
int write_files = 0;
|
int write_files = 0;
|
||||||
@ -92,6 +102,31 @@ exec_open (char *args, int from_tty)
|
|||||||
exec_file_attach (args, 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
|
static void
|
||||||
exec_close (int quitting)
|
exec_close (int quitting)
|
||||||
{
|
{
|
||||||
@ -128,31 +163,20 @@ exec_close (int quitting)
|
|||||||
|
|
||||||
vmap = NULL;
|
vmap = NULL;
|
||||||
|
|
||||||
if (exec_bfd)
|
/* Delete all target sections. */
|
||||||
{
|
resize_section_table
|
||||||
char *name = bfd_get_filename (exec_bfd);
|
(current_target_sections,
|
||||||
|
-resize_section_table (current_target_sections, 0));
|
||||||
|
|
||||||
if (!bfd_close (exec_bfd))
|
/* Remove exec file. */
|
||||||
warning (_("cannot close \"%s\": %s"),
|
exec_close_1 ();
|
||||||
name, bfd_errmsg (bfd_get_error ()));
|
|
||||||
xfree (name);
|
|
||||||
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
|
void
|
||||||
exec_file_clear (int from_tty)
|
exec_file_clear (int from_tty)
|
||||||
{
|
{
|
||||||
/* Remove exec file. */
|
/* Remove exec file. */
|
||||||
unpush_target (&exec_ops);
|
exec_close_1 ();
|
||||||
|
|
||||||
if (from_tty)
|
if (from_tty)
|
||||||
printf_unfiltered (_("No executable file now.\n"));
|
printf_unfiltered (_("No executable file now.\n"));
|
||||||
@ -179,7 +203,7 @@ void
|
|||||||
exec_file_attach (char *filename, int from_tty)
|
exec_file_attach (char *filename, int from_tty)
|
||||||
{
|
{
|
||||||
/* Remove any previous exec file. */
|
/* Remove any previous exec file. */
|
||||||
unpush_target (&exec_ops);
|
exec_close_1 ();
|
||||||
|
|
||||||
/* Now open and digest the file the user requested, if any. */
|
/* Now open and digest the file the user requested, if any. */
|
||||||
|
|
||||||
@ -195,6 +219,7 @@ exec_file_attach (char *filename, int from_tty)
|
|||||||
struct cleanup *cleanups;
|
struct cleanup *cleanups;
|
||||||
char *scratch_pathname;
|
char *scratch_pathname;
|
||||||
int scratch_chan;
|
int scratch_chan;
|
||||||
|
struct target_section *sections = NULL, *sections_end = NULL;
|
||||||
|
|
||||||
scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
|
scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
|
||||||
write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
|
write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
|
||||||
@ -233,7 +258,7 @@ exec_file_attach (char *filename, int from_tty)
|
|||||||
{
|
{
|
||||||
/* Make sure to close exec_bfd, or else "run" might try to use
|
/* Make sure to close exec_bfd, or else "run" might try to use
|
||||||
it. */
|
it. */
|
||||||
exec_close (0);
|
exec_close_1 ();
|
||||||
error (_("\"%s\": not in executable format: %s"),
|
error (_("\"%s\": not in executable format: %s"),
|
||||||
scratch_pathname, bfd_errmsg (bfd_get_error ()));
|
scratch_pathname, bfd_errmsg (bfd_get_error ()));
|
||||||
}
|
}
|
||||||
@ -248,18 +273,17 @@ exec_file_attach (char *filename, int from_tty)
|
|||||||
{
|
{
|
||||||
/* Make sure to close exec_bfd, or else "run" might try to use
|
/* Make sure to close exec_bfd, or else "run" might try to use
|
||||||
it. */
|
it. */
|
||||||
exec_close (0);
|
exec_close_1 ();
|
||||||
error (_("\"%s\": can't find the file sections: %s"),
|
error (_("\"%s\": can't find the file sections: %s"),
|
||||||
scratch_pathname, bfd_errmsg (bfd_get_error ()));
|
scratch_pathname, bfd_errmsg (bfd_get_error ()));
|
||||||
}
|
}
|
||||||
#endif /* DEPRECATED_IBM6000_TARGET */
|
#endif /* DEPRECATED_IBM6000_TARGET */
|
||||||
|
|
||||||
if (build_section_table (exec_bfd, &exec_ops.to_sections,
|
if (build_section_table (exec_bfd, §ions, §ions_end))
|
||||||
&exec_ops.to_sections_end))
|
|
||||||
{
|
{
|
||||||
/* Make sure to close exec_bfd, or else "run" might try to use
|
/* Make sure to close exec_bfd, or else "run" might try to use
|
||||||
it. */
|
it. */
|
||||||
exec_close (0);
|
exec_close_1 ();
|
||||||
error (_("\"%s\": can't find the file sections: %s"),
|
error (_("\"%s\": can't find the file sections: %s"),
|
||||||
scratch_pathname, bfd_errmsg (bfd_get_error ()));
|
scratch_pathname, bfd_errmsg (bfd_get_error ()));
|
||||||
}
|
}
|
||||||
@ -270,7 +294,10 @@ exec_file_attach (char *filename, int from_tty)
|
|||||||
|
|
||||||
set_gdbarch_from_file (exec_bfd);
|
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. */
|
/* Tell display code (if any) about the changed file name. */
|
||||||
if (deprecated_exec_file_display_hook)
|
if (deprecated_exec_file_display_hook)
|
||||||
@ -370,6 +397,33 @@ add_to_section_table (bfd *abfd, struct bfd_section *asect,
|
|||||||
(*table_pp)++;
|
(*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.
|
/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
|
||||||
Returns 0 if OK, 1 on error. */
|
Returns 0 if OK, 1 on error. */
|
||||||
|
|
||||||
@ -390,6 +444,65 @@ build_section_table (struct bfd *some_bfd, struct target_section **start,
|
|||||||
/* We could realloc the table, but it probably loses for most files. */
|
/* We could realloc the table, but it probably loses for most files. */
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
|
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
|
< 0: We cannot handle this address, but if somebody
|
||||||
else handles (-N) bytes, we can start from there. */
|
else handles (-N) bytes, we can start from there. */
|
||||||
|
|
||||||
static int
|
int
|
||||||
section_table_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr,
|
section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
|
||||||
int len, int write,
|
ULONGEST offset, LONGEST len,
|
||||||
struct target_section *sections,
|
struct target_section *sections,
|
||||||
struct target_section *sections_end,
|
struct target_section *sections_end,
|
||||||
const char *section_name)
|
const char *section_name)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct target_section *p;
|
struct target_section *p;
|
||||||
CORE_ADDR nextsectaddr, memend;
|
ULONGEST memaddr = offset;
|
||||||
|
ULONGEST memend = memaddr + len;
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
|
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
|
||||||
|
|
||||||
memend = memaddr + len;
|
|
||||||
nextsectaddr = memend;
|
|
||||||
|
|
||||||
for (p = sections; p < sections_end; p++)
|
for (p = sections; p < sections_end; p++)
|
||||||
{
|
{
|
||||||
@ -493,13 +605,13 @@ section_table_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr,
|
|||||||
if (memend <= p->endaddr)
|
if (memend <= p->endaddr)
|
||||||
{
|
{
|
||||||
/* Entire transfer is within this section. */
|
/* Entire transfer is within this section. */
|
||||||
if (write)
|
if (writebuf)
|
||||||
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
|
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
|
||||||
myaddr, memaddr - p->addr,
|
writebuf, memaddr - p->addr,
|
||||||
len);
|
len);
|
||||||
else
|
else
|
||||||
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
|
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
|
||||||
myaddr, memaddr - p->addr,
|
readbuf, memaddr - p->addr,
|
||||||
len);
|
len);
|
||||||
return (res != 0) ? len : 0;
|
return (res != 0) ? len : 0;
|
||||||
}
|
}
|
||||||
@ -512,90 +624,49 @@ section_table_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr,
|
|||||||
{
|
{
|
||||||
/* This section overlaps the transfer. Just do half. */
|
/* This section overlaps the transfer. Just do half. */
|
||||||
len = p->endaddr - memaddr;
|
len = p->endaddr - memaddr;
|
||||||
if (write)
|
if (writebuf)
|
||||||
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
|
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
|
||||||
myaddr, memaddr - p->addr,
|
writebuf, memaddr - p->addr,
|
||||||
len);
|
len);
|
||||||
else
|
else
|
||||||
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
|
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
|
||||||
myaddr, memaddr - p->addr,
|
readbuf, memaddr - p->addr,
|
||||||
len);
|
len);
|
||||||
return (res != 0) ? len : 0;
|
return (res != 0) ? len : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
nextsectaddr = min (nextsectaddr, p->addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextsectaddr >= memend)
|
return 0; /* We can't help */
|
||||||
return 0; /* We can't help */
|
|
||||||
else
|
|
||||||
return -(nextsectaddr - memaddr); /* Next boundary where we can help */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
struct target_section_table *
|
||||||
section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
|
exec_get_section_table (struct target_ops *ops)
|
||||||
ULONGEST offset, LONGEST len,
|
|
||||||
struct target_section *sections,
|
|
||||||
struct target_section *sections_end)
|
|
||||||
{
|
{
|
||||||
if (readbuf != NULL)
|
return current_target_sections;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read or write the exec file.
|
static LONGEST
|
||||||
|
exec_xfer_partial (struct target_ops *ops, enum target_object object,
|
||||||
Args are address within a BFD file, address within gdb address-space,
|
const char *annex, gdb_byte *readbuf,
|
||||||
length, and a flag indicating whether to read or write.
|
const gdb_byte *writebuf,
|
||||||
|
ULONGEST offset, LONGEST len)
|
||||||
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;
|
struct target_section_table *table = target_get_section_table (ops);
|
||||||
const char *section_name = NULL;
|
|
||||||
|
|
||||||
if (len <= 0)
|
if (object == TARGET_OBJECT_MEMORY)
|
||||||
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
|
return section_table_xfer_memory_partial (readbuf, writebuf,
|
||||||
|
offset, len,
|
||||||
if (overlay_debugging)
|
table->sections,
|
||||||
{
|
table->sections_end,
|
||||||
struct obj_section *section = find_pc_overlay (memaddr);
|
NULL);
|
||||||
|
else
|
||||||
if (section != NULL)
|
return -1;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
print_section_info (struct target_ops *t, bfd *abfd)
|
print_section_info (struct target_section_table *t, bfd *abfd)
|
||||||
{
|
{
|
||||||
struct target_section *p;
|
struct target_section *p;
|
||||||
/* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64. */
|
/* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64. */
|
||||||
@ -607,7 +678,7 @@ print_section_info (struct target_ops *t, bfd *abfd)
|
|||||||
if (abfd == exec_bfd)
|
if (abfd == exec_bfd)
|
||||||
printf_filtered (_("\tEntry point: %s\n"),
|
printf_filtered (_("\tEntry point: %s\n"),
|
||||||
paddress (bfd_get_start_address (abfd)));
|
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 ("\t%s", hex_string_custom (p->addr, wid));
|
||||||
printf_filtered (" - %s", hex_string_custom (p->endaddr, wid));
|
printf_filtered (" - %s", hex_string_custom (p->endaddr, wid));
|
||||||
@ -631,7 +702,7 @@ print_section_info (struct target_ops *t, bfd *abfd)
|
|||||||
static void
|
static void
|
||||||
exec_files_info (struct target_ops *t)
|
exec_files_info (struct target_ops *t)
|
||||||
{
|
{
|
||||||
print_section_info (t, exec_bfd);
|
print_section_info (current_target_sections, exec_bfd);
|
||||||
|
|
||||||
if (vmap)
|
if (vmap)
|
||||||
{
|
{
|
||||||
@ -667,6 +738,7 @@ set_section_command (char *args, int from_tty)
|
|||||||
unsigned long secaddr;
|
unsigned long secaddr;
|
||||||
char secprint[100];
|
char secprint[100];
|
||||||
long offset;
|
long offset;
|
||||||
|
struct target_section_table *table;
|
||||||
|
|
||||||
if (args == 0)
|
if (args == 0)
|
||||||
error (_("Must specify section name and its virtual address"));
|
error (_("Must specify section name and its virtual address"));
|
||||||
@ -678,7 +750,8 @@ set_section_command (char *args, int from_tty)
|
|||||||
/* Parse out new virtual address */
|
/* Parse out new virtual address */
|
||||||
secaddr = parse_and_eval_address (args);
|
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)
|
if (!strncmp (secname, bfd_section_name (exec_bfd, p->the_bfd_section), seclen)
|
||||||
&& bfd_section_name (exec_bfd, p->the_bfd_section)[seclen] == '\0')
|
&& 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)
|
exec_set_section_address (const char *filename, int index, CORE_ADDR address)
|
||||||
{
|
{
|
||||||
struct target_section *p;
|
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
|
if (strcmp (filename, p->bfd->filename) == 0
|
||||||
&& index == p->the_bfd_section->index)
|
&& index == p->the_bfd_section->index)
|
||||||
@ -754,7 +829,8 @@ Specify the filename of the executable file.";
|
|||||||
exec_ops.to_open = exec_open;
|
exec_ops.to_open = exec_open;
|
||||||
exec_ops.to_close = exec_close;
|
exec_ops.to_close = exec_close;
|
||||||
exec_ops.to_attach = find_default_attach;
|
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_files_info = exec_files_info;
|
||||||
exec_ops.to_insert_breakpoint = ignore;
|
exec_ops.to_insert_breakpoint = ignore;
|
||||||
exec_ops.to_remove_breakpoint = ignore;
|
exec_ops.to_remove_breakpoint = ignore;
|
||||||
|
26
gdb/exec.h
26
gdb/exec.h
@ -34,6 +34,11 @@ extern struct target_ops exec_ops;
|
|||||||
extern int build_section_table (struct bfd *, struct target_section **,
|
extern int build_section_table (struct bfd *, struct target_section **,
|
||||||
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
|
/* Request to transfer up to LEN 8-bit bytes of the target sections
|
||||||
defined by SECTIONS and SECTIONS_END. The OFFSET specifies the
|
defined by SECTIONS and SECTIONS_END. The OFFSET specifies the
|
||||||
starting address.
|
starting address.
|
||||||
@ -50,9 +55,28 @@ extern int build_section_table (struct bfd *, struct target_section **,
|
|||||||
extern int section_table_xfer_memory_partial (gdb_byte *, const gdb_byte *,
|
extern int section_table_xfer_memory_partial (gdb_byte *, const gdb_byte *,
|
||||||
ULONGEST, LONGEST,
|
ULONGEST, LONGEST,
|
||||||
struct target_section *,
|
struct target_section *,
|
||||||
struct target_section *);
|
struct target_section *,
|
||||||
|
const char *);
|
||||||
|
|
||||||
/* Set the loaded address of a section. */
|
/* Set the loaded address of a section. */
|
||||||
extern void exec_set_section_address (const char *, int, CORE_ADDR);
|
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
|
#endif
|
||||||
|
@ -189,4 +189,6 @@ extern void deprecated_add_core_fns (struct core_fns *cf);
|
|||||||
extern int default_core_sniffer (struct core_fns *cf, bfd * abfd);
|
extern int default_core_sniffer (struct core_fns *cf, bfd * abfd);
|
||||||
extern int default_check_format (bfd * abfd);
|
extern int default_check_format (bfd * abfd);
|
||||||
|
|
||||||
|
struct target_section *deprecated_core_resize_section_table (int num_added);
|
||||||
|
|
||||||
#endif /* !defined (GDBCORE_H) */
|
#endif /* !defined (GDBCORE_H) */
|
||||||
|
18
gdb/infrun.c
18
gdb/infrun.c
@ -2448,15 +2448,6 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||||||
operations such as address => section name and hence
|
operations such as address => section name and hence
|
||||||
require the table to contain all sections (including
|
require the table to contain all sections (including
|
||||||
those found in shared libraries). */
|
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
|
#ifdef SOLIB_ADD
|
||||||
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
|
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
|
||||||
#else
|
#else
|
||||||
@ -3446,15 +3437,6 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||||||
operations such as address => section name and hence
|
operations such as address => section name and hence
|
||||||
require the table to contain all sections (including
|
require the table to contain all sections (including
|
||||||
those found in shared libraries). */
|
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
|
#ifdef SOLIB_ADD
|
||||||
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
|
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
|
||||||
#else
|
#else
|
||||||
|
@ -1160,8 +1160,7 @@ xcoff_relocate_core (struct target_ops *target)
|
|||||||
{
|
{
|
||||||
struct target_section *stp;
|
struct target_section *stp;
|
||||||
|
|
||||||
target_resize_to_sections (target, 2);
|
stp = deprecated_core_resize_section_table (2);
|
||||||
stp = target->to_sections_end - 2;
|
|
||||||
|
|
||||||
stp->bfd = vp->bfd;
|
stp->bfd = vp->bfd;
|
||||||
stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text");
|
stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text");
|
||||||
|
20
gdb/solib.c
20
gdb/solib.c
@ -661,21 +661,11 @@ update_solib_list (int from_tty, struct target_ops *target)
|
|||||||
"Error while mapping shared library sections:\n",
|
"Error while mapping shared library sections:\n",
|
||||||
RETURN_MASK_ALL);
|
RETURN_MASK_ALL);
|
||||||
|
|
||||||
/* If requested, add the shared object's sections to the TARGET's
|
/* Add the shared object's sections to the current set of
|
||||||
section table. Do this immediately after mapping the object so
|
file section tables. Do this immediately after mapping
|
||||||
that later nodes in the list can query this object, as is needed
|
the object so that later nodes in the list can query this
|
||||||
in solib-osf.c. */
|
object, as is needed in solib-osf.c. */
|
||||||
if (target)
|
add_target_sections (i->sections, i->sections_end);
|
||||||
{
|
|
||||||
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]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify any observer that the shared object has been
|
/* Notify any observer that the shared object has been
|
||||||
loaded now that we've added it to GDB's tables. */
|
loaded now that we've added it to GDB's tables. */
|
||||||
|
163
gdb/target.c
163
gdb/target.c
@ -41,6 +41,7 @@
|
|||||||
#include "target-descriptions.h"
|
#include "target-descriptions.h"
|
||||||
#include "gdbthread.h"
|
#include "gdbthread.h"
|
||||||
#include "solib.h"
|
#include "solib.h"
|
||||||
|
#include "exec.h"
|
||||||
|
|
||||||
static void target_info (char *, int);
|
static void target_info (char *, int);
|
||||||
|
|
||||||
@ -491,8 +492,6 @@ update_current_target (void)
|
|||||||
INHERIT (to_has_registers, t);
|
INHERIT (to_has_registers, t);
|
||||||
INHERIT (to_has_execution, t);
|
INHERIT (to_has_execution, t);
|
||||||
INHERIT (to_has_thread_control, t);
|
INHERIT (to_has_thread_control, t);
|
||||||
INHERIT (to_sections, t);
|
|
||||||
INHERIT (to_sections_end, t);
|
|
||||||
INHERIT (to_can_async_p, t);
|
INHERIT (to_can_async_p, t);
|
||||||
INHERIT (to_is_async_p, t);
|
INHERIT (to_is_async_p, t);
|
||||||
INHERIT (to_async, t);
|
INHERIT (to_async, t);
|
||||||
@ -1016,14 +1015,33 @@ done:
|
|||||||
return nbytes_read;
|
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. */
|
/* Find a section containing ADDR. */
|
||||||
|
|
||||||
struct target_section *
|
struct target_section *
|
||||||
target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
|
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;
|
struct target_section *secp;
|
||||||
for (secp = target->to_sections;
|
|
||||||
secp < target->to_sections_end;
|
if (table == NULL)
|
||||||
secp++)
|
return NULL;
|
||||||
|
|
||||||
|
for (secp = table->sections; secp < table->sections_end; secp++)
|
||||||
{
|
{
|
||||||
if (addr >= secp->addr && addr < secp->endaddr)
|
if (addr >= secp->addr && addr < secp->endaddr)
|
||||||
return secp;
|
return secp;
|
||||||
@ -1046,24 +1064,43 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
return 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)
|
if (readbuf != NULL && trust_readonly)
|
||||||
{
|
{
|
||||||
struct target_section *secp;
|
struct target_section *secp;
|
||||||
|
struct target_section_table *table;
|
||||||
|
|
||||||
secp = target_section_by_addr (ops, memaddr);
|
secp = target_section_by_addr (ops, memaddr);
|
||||||
if (secp != NULL
|
if (secp != NULL
|
||||||
&& (bfd_get_section_flags (secp->bfd, secp->the_bfd_section)
|
&& (bfd_get_section_flags (secp->bfd, secp->the_bfd_section)
|
||||||
& SEC_READONLY))
|
& SEC_READONLY))
|
||||||
return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
|
{
|
||||||
}
|
table = target_get_section_table (ops);
|
||||||
|
return section_table_xfer_memory_partial (readbuf, writebuf,
|
||||||
/* Likewise for accesses to unmapped overlay sections. */
|
memaddr, len,
|
||||||
if (readbuf != NULL && overlay_debugging)
|
table->sections,
|
||||||
{
|
table->sections_end,
|
||||||
struct obj_section *section = find_pc_overlay (memaddr);
|
NULL);
|
||||||
if (pc_in_unmapped_range (memaddr, section))
|
}
|
||||||
return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try GDB's internal data cache. */
|
/* Try GDB's internal data cache. */
|
||||||
@ -1688,7 +1725,11 @@ void
|
|||||||
get_target_memory (struct target_ops *ops, CORE_ADDR addr, gdb_byte *buf,
|
get_target_memory (struct target_ops *ops, CORE_ADDR addr, gdb_byte *buf,
|
||||||
LONGEST len)
|
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)
|
!= len)
|
||||||
memory_error (EIO, addr);
|
memory_error (EIO, addr);
|
||||||
}
|
}
|
||||||
@ -2338,96 +2379,6 @@ return_minus_one (void)
|
|||||||
return -1;
|
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
|
/* Find a single runnable target in the stack and return it. If for
|
||||||
some reason there is more than one, return NULL. */
|
some reason there is more than one, return NULL. */
|
||||||
|
|
||||||
|
32
gdb/target.h
32
gdb/target.h
@ -30,6 +30,7 @@ struct mem_attrib;
|
|||||||
struct target_ops;
|
struct target_ops;
|
||||||
struct bp_target_info;
|
struct bp_target_info;
|
||||||
struct regcache;
|
struct regcache;
|
||||||
|
struct target_section_table;
|
||||||
|
|
||||||
/* This include file defines the interface between the main part
|
/* This include file defines the interface between the main part
|
||||||
of the debugger, and the part which is target-specific, or
|
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);
|
void (*to_rcmd) (char *command, struct ui_file *output);
|
||||||
char *(*to_pid_to_exec_file) (int pid);
|
char *(*to_pid_to_exec_file) (int pid);
|
||||||
void (*to_log_command) (const char *);
|
void (*to_log_command) (const char *);
|
||||||
|
struct target_section_table *(*to_get_section_table) (struct target_ops *);
|
||||||
enum strata to_stratum;
|
enum strata to_stratum;
|
||||||
int to_has_all_memory;
|
int to_has_all_memory;
|
||||||
int to_has_memory;
|
int to_has_memory;
|
||||||
@ -420,10 +422,6 @@ struct target_ops
|
|||||||
int to_has_execution;
|
int to_has_execution;
|
||||||
int to_has_thread_control; /* control thread execution */
|
int to_has_thread_control; /* control thread execution */
|
||||||
int to_attach_no_wait;
|
int to_attach_no_wait;
|
||||||
struct target_section
|
|
||||||
*to_sections;
|
|
||||||
struct target_section
|
|
||||||
*to_sections_end;
|
|
||||||
/* ASYNC target controls */
|
/* ASYNC target controls */
|
||||||
int (*to_can_async_p) (void);
|
int (*to_can_async_p) (void);
|
||||||
int (*to_is_async_p) (void);
|
int (*to_is_async_p) (void);
|
||||||
@ -668,9 +666,6 @@ extern int target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len);
|
|||||||
extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr,
|
extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr,
|
||||||
int len);
|
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
|
/* Fetches the target's memory map. If one is found it is sorted
|
||||||
and returned, after some consistency checking. Otherwise, NULL
|
and returned, after some consistency checking. Otherwise, NULL
|
||||||
is returned. */
|
is returned. */
|
||||||
@ -733,10 +728,6 @@ extern int inferior_has_vforked (ptid_t pid, ptid_t *child_pid);
|
|||||||
|
|
||||||
extern int inferior_has_execd (ptid_t pid, char **execd_pathname);
|
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. */
|
/* Print a line about the current target. */
|
||||||
|
|
||||||
#define target_files_info() \
|
#define target_files_info() \
|
||||||
@ -1208,10 +1199,24 @@ struct target_section
|
|||||||
bfd *bfd; /* BFD file pointer */
|
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. */
|
/* Return the "section" containing the specified address. */
|
||||||
struct target_section *target_section_by_addr (struct target_ops *target,
|
struct target_section *target_section_by_addr (struct target_ops *target,
|
||||||
CORE_ADDR addr);
|
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 */
|
/* From mem-break.c */
|
||||||
|
|
||||||
extern int memory_remove_breakpoint (struct bp_target_info *);
|
extern int memory_remove_breakpoint (struct bp_target_info *);
|
||||||
@ -1242,11 +1247,6 @@ extern struct target_ops *find_core_target (void);
|
|||||||
|
|
||||||
extern struct target_ops *find_target_beneath (struct target_ops *);
|
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
|
/* 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,
|
XML format. The result is NUL-terminated and returned as a string,
|
||||||
allocated using xmalloc. If an error occurs or the transfer is
|
allocated using xmalloc. If an error occurs or the transfer is
|
||||||
|
Reference in New Issue
Block a user