/* Work with executable files, for GDB.
- Copyright (C) 1988-2020 Free Software Foundation, Inc.
+ Copyright (C) 1988-2021 Free Software Foundation, Inc.
This file is part of GDB.
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
- struct target_section_table *get_section_table () override;
void files_info () override;
bool has_memory () override;
- char *make_corefile_notes (bfd *, int *) override;
+ gdb::unique_xmalloc_ptr<char> make_corefile_notes (bfd *, int *) override;
int find_memory_regions (find_memory_region_ftype func, void *data) override;
};
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. */
-
-void
-exec_close (void)
-{
- if (exec_bfd)
- {
- bfd *abfd = exec_bfd;
-
- gdb_bfd_unref (abfd);
-
- /* 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 (&exec_bfd);
-
- xfree (exec_filename);
- exec_filename = NULL;
- }
-}
-
/* This is the target_close implementation. Clears all target
sections and closes all executable bfds from all program spaces. */
void
exec_target::close ()
{
- scoped_restore_current_program_space restore_pspace;
-
for (struct program_space *ss : program_spaces)
{
- set_current_program_space (ss);
- clear_section_table (current_target_sections);
- exec_close ();
+ ss->clear_target_sections ();
+ ss->exec_close ();
}
}
reopen_exec_file ();
current_exec_file = get_exec_file (0);
- const bfd_build_id *exec_file_build_id = build_id_bfd_get (exec_bfd);
+ const bfd_build_id *exec_file_build_id
+ = build_id_bfd_get (current_program_space->exec_bfd ());
if (exec_file_build_id != nullptr)
{
/* Prepend the target prefix, to force gdb_bfd_open to open the
void
exec_file_attach (const char *filename, int from_tty)
{
- /* First, acquire a reference to the current exec_bfd. We release
+ /* First, acquire a reference to the exec_bfd. We release
this at the end of the function; but acquiring it now lets the
BFD cache return it if this call refers to the same file. */
- gdb_bfd_ref_ptr exec_bfd_holder = gdb_bfd_ref_ptr::new_reference (exec_bfd);
+ gdb_bfd_ref_ptr exec_bfd_holder
+ = gdb_bfd_ref_ptr::new_reference (current_program_space->exec_bfd ());
/* Remove any previous exec file. */
- exec_close ();
+ current_program_space->exec_close ();
/* Now open and digest the file the user requested, if any. */
if (!filename)
{
if (from_tty)
- printf_unfiltered (_("No executable file now.\n"));
+ printf_unfiltered (_("No executable file now.\n"));
set_gdbarch_from_file (NULL);
}
FOPEN_RUB, scratch_chan);
else
temp = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
- exec_bfd = temp.release ();
+ current_program_space->set_exec_bfd (std::move (temp));
- if (!exec_bfd)
+ if (!current_program_space->exec_bfd ())
{
error (_("\"%ps\": could not open as an executable file: %s."),
styled_string (file_name_style.style (), scratch_pathname),
/* gdb_realpath_keepfile resolves symlinks on the local
filesystem and so cannot be used for "target:" files. */
- gdb_assert (exec_filename == NULL);
+ gdb_assert (current_program_space->exec_filename == nullptr);
if (load_via_target)
- exec_filename = xstrdup (bfd_get_filename (exec_bfd));
+ current_program_space->exec_filename
+ = (make_unique_xstrdup
+ (bfd_get_filename (current_program_space->exec_bfd ())));
else
- exec_filename = gdb_realpath_keepfile (scratch_pathname).release ();
+ current_program_space->exec_filename
+ = gdb_realpath_keepfile (scratch_pathname);
- if (!bfd_check_format_matches (exec_bfd, bfd_object, &matching))
+ if (!bfd_check_format_matches (current_program_space->exec_bfd (),
+ bfd_object, &matching))
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close ();
+ current_program_space->exec_close ();
error (_("\"%ps\": not in executable format: %s"),
styled_string (file_name_style.style (), scratch_pathname),
gdb_bfd_errmsg (bfd_get_error (), matching).c_str ());
}
- target_section_table sections = build_section_table (exec_bfd);
+ target_section_table sections
+ = build_section_table (current_program_space->exec_bfd ());
- exec_bfd_mtime = bfd_get_mtime (exec_bfd);
+ current_program_space->ebfd_mtime
+ = bfd_get_mtime (current_program_space->exec_bfd ());
validate_files ();
- set_gdbarch_from_file (exec_bfd);
+ set_gdbarch_from_file (current_program_space->exec_bfd ());
/* Add the executable's sections to the current address spaces'
list of sections. This possibly pushes the exec_ops
target. */
- add_target_sections (&exec_bfd, sections);
+ current_program_space->add_target_sections (¤t_program_space->ebfd,
+ sections);
/* Tell display code (if any) about the changed file name. */
if (deprecated_exec_file_display_hook)
if (args)
{
/* Scan through the args and pick up the first non option arg
- as the filename. */
+ as the filename. */
gdb_argv built_argv (args);
char **argv = built_argv.get ();
for (; (*argv != NULL) && (**argv == '-'); argv++)
- {;
- }
+ {;
+ }
if (*argv == NULL)
- error (_("No executable file name was specified"));
+ error (_("No executable file name was specified"));
gdb::unique_xmalloc_ptr<char> filename (tilde_expand (*argv));
exec_file_attach (filename.get (), from_tty);
}
\f
-/* See exec.h. */
-
-void
-clear_section_table (struct target_section_table *table)
-{
- table->sections.clear ();
-}
-
/* Builds a section table, given args BFD, TABLE. */
target_section_table
if (!(aflag & SEC_ALLOC))
continue;
- table.sections.emplace_back ();
- target_section § = table.sections.back ();
- sect.owner = NULL;
- sect.the_bfd_section = asect;
- sect.addr = bfd_section_vma (asect);
- sect.endaddr = sect.addr + bfd_section_size (asect);
+ table.emplace_back (bfd_section_vma (asect),
+ bfd_section_vma (asect) + bfd_section_size (asect),
+ asect);
}
return table;
current set of target sections. */
void
-add_target_sections (void *owner,
- const target_section_table §ions)
+program_space::add_target_sections (void *owner,
+ const target_section_table §ions)
{
- struct target_section_table *table = current_target_sections;
-
- if (!sections.sections.empty ())
+ if (!sections.empty ())
{
- for (const target_section &s : sections.sections)
+ for (const target_section &s : sections)
{
- table->sections.push_back (s);
- table->sections.back ().owner = owner;
+ m_target_sections.push_back (s);
+ m_target_sections.back ().owner = owner;
}
scoped_restore_current_pspace_and_thread restore_pspace_thread;
- program_space *curr_pspace = current_program_space;
/* If these are the first file sections we can provide memory
from, push the file_stratum target. Must do this in all
inferiors sharing the program space. */
for (inferior *inf : all_inferiors ())
{
- if (inf->pspace != curr_pspace)
+ if (inf->pspace != this)
continue;
if (inf->target_is_pushed (&exec_ops))
continue;
switch_to_inferior_no_thread (inf);
- push_target (&exec_ops);
+ inf->push_target (&exec_ops);
}
}
}
/* Add the sections of OBJFILE to the current set of target sections. */
void
-add_target_sections_of_objfile (struct objfile *objfile)
+program_space::add_target_sections (struct objfile *objfile)
{
- struct target_section_table *table = current_target_sections;
struct obj_section *osect;
gdb_assert (objfile != nullptr);
if (bfd_section_size (osect->the_bfd_section) == 0)
continue;
- table->sections.emplace_back ();
- target_section &ts = table->sections.back ();
- ts.addr = obj_section_addr (osect);
- ts.endaddr = obj_section_endaddr (osect);
- ts.the_bfd_section = osect->the_bfd_section;
- ts.owner = (void *) objfile;
+ m_target_sections.emplace_back (osect->addr (), osect->endaddr (),
+ osect->the_bfd_section, (void *) objfile);
}
}
OWNER must be the same value passed to add_target_sections. */
void
-remove_target_sections (void *owner)
+program_space::remove_target_sections (void *owner)
{
- struct target_section_table *table = current_target_sections;
-
gdb_assert (owner != NULL);
- auto it = std::remove_if (table->sections.begin (),
- table->sections.end (),
+ auto it = std::remove_if (m_target_sections.begin (),
+ m_target_sections.end (),
[&] (target_section §)
{
return sect.owner == owner;
});
- table->sections.erase (it, table->sections.end ());
+ m_target_sections.erase (it, m_target_sections.end ());
/* If we don't have any more sections to read memory from,
remove the file_stratum target from the stack of each
inferior sharing the program space. */
- if (table->sections.empty ())
+ if (m_target_sections.empty ())
{
scoped_restore_current_pspace_and_thread restore_pspace_thread;
- program_space *curr_pspace = current_program_space;
for (inferior *inf : all_inferiors ())
{
- if (inf->pspace != curr_pspace)
- continue;
-
- if (!inf->pspace->target_sections.sections.empty ())
+ if (inf->pspace != this)
continue;
switch_to_inferior_no_thread (inf);
- unpush_target (&exec_ops);
+ inf->unpush_target (&exec_ops);
}
}
}
void
exec_on_vfork ()
{
- if (!current_program_space->target_sections.sections.empty ())
- push_target (&exec_ops);
+ if (!current_program_space->target_sections ().empty ())
+ current_inferior ()->push_target (&exec_ops);
}
\f
/* It's unduly pedantic to refuse to look at the executable for
read-only pieces; so do the equivalent of readonly regions aka
QTro packet. */
- if (exec_bfd != NULL)
+ if (current_program_space->exec_bfd () != NULL)
{
asection *s;
bfd_size_type size;
bfd_vma vma;
- for (s = exec_bfd->sections; s; s = s->next)
+ for (s = current_program_space->exec_bfd ()->sections; s; s = s->next)
{
if ((s->flags & SEC_LOAD) == 0
|| (s->flags & SEC_READONLY) == 0)
if (amt > len)
amt = len;
- amt = bfd_get_section_contents (exec_bfd, s,
+ amt = bfd_get_section_contents (current_program_space->exec_bfd (), s,
readbuf, offset - vma, amt);
if (amt == 0)
{
std::vector<mem_range> memory;
- for (const target_section &p : sections.sections)
+ for (const target_section &p : sections)
{
if ((bfd_section_flags (p.the_bfd_section) & SEC_READONLY) == 0)
continue;
section_table_read_available_memory (gdb_byte *readbuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
- target_section_table *table = target_get_section_table (&exec_ops);
+ const target_section_table *table
+ = target_get_section_table (current_inferior ()->top_target ());
std::vector<mem_range> available_memory
= section_table_available_memory (offset, len, *table);
gdb_assert (len != 0);
- for (const target_section &p : sections.sections)
+ for (const target_section &p : sections)
{
struct bfd_section *asect = p.the_bfd_section;
bfd *abfd = asect->owner;
if (match_cb != nullptr && !match_cb (&p))
continue; /* not the section we need. */
if (memaddr >= p.addr)
- {
+ {
if (memend <= p.endaddr)
{
/* Entire transfer is within this section. */
else
return TARGET_XFER_EOF;
}
- }
+ }
}
return TARGET_XFER_EOF; /* We can't help. */
}
-struct target_section_table *
-exec_target::get_section_table ()
-{
- return current_target_sections;
-}
-
enum target_xfer_status
exec_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
- struct target_section_table *table = get_section_table ();
+ const target_section_table *table = target_get_section_table (this);
if (object == TARGET_OBJECT_MEMORY)
return section_table_xfer_memory_partial (readbuf, writebuf,
\f
void
-print_section_info (struct target_section_table *t, bfd *abfd)
+print_section_info (const target_section_table *t, bfd *abfd)
{
struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
/* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64. */
bfd_get_filename (abfd)));
wrap_here (" ");
printf_filtered (_("file type %s.\n"), bfd_get_target (abfd));
- if (abfd == exec_bfd)
+ if (abfd == current_program_space->exec_bfd ())
{
/* gcc-3.4 does not like the initialization in
<p == t->sections_end>. */
bfd_vma entry_point;
bool found = false;
- for (const target_section &p : t->sections)
+ for (const target_section &p : *t)
{
struct bfd_section *psect = p.the_bfd_section;
printf_filtered (_("\tEntry point: %s\n"),
paddress (gdbarch, entry_point));
}
- for (const target_section &p : t->sections)
+ for (const target_section &p : *t)
{
struct bfd_section *psect = p.the_bfd_section;
bfd *pbfd = psect->owner;
void
exec_target::files_info ()
{
- if (exec_bfd)
- print_section_info (current_target_sections, exec_bfd);
+ if (current_program_space->exec_bfd ())
+ print_section_info (¤t_program_space->target_sections (),
+ current_program_space->exec_bfd ());
else
puts_filtered (_("\t<no file loaded>\n"));
}
set_section_command (const char *args, int from_tty)
{
const char *secname;
- unsigned seclen;
- 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"));
/* Parse out section name. */
for (secname = args; !isspace (*args); args++);
- seclen = args - secname;
+ unsigned seclen = args - secname;
/* Parse out new virtual address. */
- secaddr = parse_and_eval_address (args);
+ CORE_ADDR secaddr = parse_and_eval_address (args);
- table = current_target_sections;
- for (target_section &p : table->sections)
+ for (target_section &p : current_program_space->target_sections ())
{
if (!strncmp (secname, bfd_section_name (p.the_bfd_section), seclen)
&& bfd_section_name (p.the_bfd_section)[seclen] == '\0')
{
- offset = secaddr - p.addr;
+ long offset = secaddr - p.addr;
p.addr += offset;
p.endaddr += offset;
if (from_tty)
return;
}
}
- if (seclen >= sizeof (secprint))
- seclen = sizeof (secprint) - 1;
- strncpy (secprint, secname, seclen);
- secprint[seclen] = '\0';
- error (_("Section %s not found"), secprint);
+
+ std::string secprint (secname, seclen);
+ error (_("Section %s not found"), secprint.c_str ());
}
/* If we can find a section in FILENAME with BFD index INDEX, adjust
void
exec_set_section_address (const char *filename, int index, CORE_ADDR address)
{
- struct target_section_table *table;
-
- table = current_target_sections;
- for (target_section &p : table->sections)
+ for (target_section &p : current_program_space->target_sections ())
{
if (filename_cmp (filename,
bfd_get_filename (p.the_bfd_section->owner)) == 0
{
/* We can provide memory if we have any file/target sections to read
from. */
- return !current_target_sections->sections.empty ();
+ return !current_program_space->target_sections ().empty ();
}
-char *
+gdb::unique_xmalloc_ptr<char>
exec_target::make_corefile_notes (bfd *obfd, int *note_size)
{
error (_("Can't create a corefile"));