/* GDB routines for manipulating objfiles.
- Copyright (C) 1992-2004, 2007-2012 Free Software Foundation, Inc.
+ Copyright (C) 1992-2020 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
#include "gdb-stabs.h"
#include "target.h"
#include "bcache.h"
-#include "mdebugread.h"
#include "expression.h"
#include "parser-defs.h"
-#include "gdb_assert.h"
#include <sys/types.h>
-#include "gdb_stat.h"
+#include <sys/stat.h>
#include <fcntl.h>
#include "gdb_obstack.h"
-#include "gdb_string.h"
#include "hashtab.h"
#include "breakpoint.h"
#include "addrmap.h"
#include "arch-utils.h"
#include "exec.h"
-#include "observer.h"
+#include "observable.h"
#include "complaints.h"
#include "psymtab.h"
#include "solist.h"
+#include "gdb_bfd.h"
+#include "btrace.h"
+#include "gdbsupport/pathstuff.h"
-/* Prototypes for local functions */
+#include <algorithm>
+#include <vector>
-static void objfile_alloc_data (struct objfile *objfile);
-static void objfile_free_data (struct objfile *objfile);
+/* Keep a registry of per-objfile data-pointers required by other GDB
+ modules. */
+
+DEFINE_REGISTRY (objfile, REGISTRY_ACCESS_FIELD)
/* Externally visible variables that are owned by this module.
See declarations in objfile.h for more info. */
-struct objfile *rt_common_objfile; /* For runtime common symbols */
-
struct objfile_pspace_info
{
- int objfiles_changed_p;
- struct obj_section **sections;
- int num_sections;
+ objfile_pspace_info () = default;
+ ~objfile_pspace_info ();
+
+ struct obj_section **sections = nullptr;
+ int num_sections = 0;
+
+ /* Nonzero if object files have been added since the section map
+ was last updated. */
+ int new_objfiles_available = 0;
+
+ /* Nonzero if the section map MUST be updated before use. */
+ int section_map_dirty = 0;
+
+ /* Nonzero if section map updates should be inhibited if possible. */
+ int inhibit_updates = 0;
};
/* Per-program-space data key. */
-static const struct program_space_data *objfiles_pspace_data;
+static const struct program_space_key<objfile_pspace_info>
+ objfiles_pspace_data;
-static void
-objfiles_pspace_data_cleanup (struct program_space *pspace, void *arg)
+objfile_pspace_info::~objfile_pspace_info ()
{
- struct objfile_pspace_info *info;
-
- info = program_space_data (pspace, objfiles_pspace_data);
- if (info != NULL)
- {
- xfree (info->sections);
- xfree (info);
- }
+ xfree (sections);
}
/* Get the current svr4 data. If none is found yet, add it now. This
{
struct objfile_pspace_info *info;
- info = program_space_data (pspace, objfiles_pspace_data);
+ info = objfiles_pspace_data.get (pspace);
if (info == NULL)
+ info = objfiles_pspace_data.emplace (pspace);
+
+ return info;
+}
+
+\f
+
+/* Per-BFD data key. */
+
+static const struct bfd_key<objfile_per_bfd_storage> objfiles_bfd_data;
+
+objfile_per_bfd_storage::~objfile_per_bfd_storage ()
+{
+}
+
+/* Create the per-BFD storage object for OBJFILE. If ABFD is not
+ NULL, and it already has a per-BFD storage object, use that.
+ Otherwise, allocate a new per-BFD storage object. Note that it is
+ not safe to call this multiple times for a given OBJFILE -- it can
+ only be called when allocating or re-initializing OBJFILE. */
+
+static struct objfile_per_bfd_storage *
+get_objfile_bfd_data (struct objfile *objfile, struct bfd *abfd)
+{
+ struct objfile_per_bfd_storage *storage = NULL;
+
+ if (abfd != NULL)
+ storage = objfiles_bfd_data.get (abfd);
+
+ if (storage == NULL)
{
- info = XZALLOC (struct objfile_pspace_info);
- set_program_space_data (pspace, objfiles_pspace_data, info);
+ storage = new objfile_per_bfd_storage;
+ /* If the object requires gdb to do relocations, we simply fall
+ back to not sharing data across users. These cases are rare
+ enough that this seems reasonable. */
+ if (abfd != NULL && !gdb_bfd_requires_relocations (abfd))
+ objfiles_bfd_data.set (abfd, storage);
+
+ /* Look up the gdbarch associated with the BFD. */
+ if (abfd != NULL)
+ storage->gdbarch = gdbarch_from_bfd (abfd);
}
- return info;
+ return storage;
+}
+
+/* See objfiles.h. */
+
+void
+set_objfile_per_bfd (struct objfile *objfile)
+{
+ objfile->per_bfd = get_objfile_bfd_data (objfile, objfile->obfd);
+}
+
+/* Set the objfile's per-BFD notion of the "main" name and
+ language. */
+
+void
+set_objfile_main_name (struct objfile *objfile,
+ const char *name, enum language lang)
+{
+ if (objfile->per_bfd->name_of_main == NULL
+ || strcmp (objfile->per_bfd->name_of_main, name) != 0)
+ objfile->per_bfd->name_of_main
+ = obstack_strdup (&objfile->per_bfd->storage_obstack, name);
+ objfile->per_bfd->language_of_main = lang;
+}
+
+/* Helper structure to map blocks to static link properties in hash tables. */
+
+struct static_link_htab_entry
+{
+ const struct block *block;
+ const struct dynamic_prop *static_link;
+};
+
+/* Return a hash code for struct static_link_htab_entry *P. */
+
+static hashval_t
+static_link_htab_entry_hash (const void *p)
+{
+ const struct static_link_htab_entry *e
+ = (const struct static_link_htab_entry *) p;
+
+ return htab_hash_pointer (e->block);
+}
+
+/* Return whether P1 an P2 (pointers to struct static_link_htab_entry) are
+ mappings for the same block. */
+
+static int
+static_link_htab_entry_eq (const void *p1, const void *p2)
+{
+ const struct static_link_htab_entry *e1
+ = (const struct static_link_htab_entry *) p1;
+ const struct static_link_htab_entry *e2
+ = (const struct static_link_htab_entry *) p2;
+
+ return e1->block == e2->block;
+}
+
+/* Register STATIC_LINK as the static link for BLOCK, which is part of OBJFILE.
+ Must not be called more than once for each BLOCK. */
+
+void
+objfile_register_static_link (struct objfile *objfile,
+ const struct block *block,
+ const struct dynamic_prop *static_link)
+{
+ void **slot;
+ struct static_link_htab_entry lookup_entry;
+ struct static_link_htab_entry *entry;
+
+ if (objfile->static_links == NULL)
+ objfile->static_links.reset (htab_create_alloc
+ (1, &static_link_htab_entry_hash, static_link_htab_entry_eq, NULL,
+ xcalloc, xfree));
+
+ /* Create a slot for the mapping, make sure it's the first mapping for this
+ block and then create the mapping itself. */
+ lookup_entry.block = block;
+ slot = htab_find_slot (objfile->static_links.get (), &lookup_entry, INSERT);
+ gdb_assert (*slot == NULL);
+
+ entry = XOBNEW (&objfile->objfile_obstack, static_link_htab_entry);
+ entry->block = block;
+ entry->static_link = static_link;
+ *slot = (void *) entry;
+}
+
+/* Look for a static link for BLOCK, which is part of OBJFILE. Return NULL if
+ none was found. */
+
+const struct dynamic_prop *
+objfile_lookup_static_link (struct objfile *objfile,
+ const struct block *block)
+{
+ struct static_link_htab_entry *entry;
+ struct static_link_htab_entry lookup_entry;
+
+ if (objfile->static_links == NULL)
+ return NULL;
+ lookup_entry.block = block;
+ entry = ((struct static_link_htab_entry *)
+ htab_find (objfile->static_links.get (), &lookup_entry));
+ if (entry == NULL)
+ return NULL;
+
+ gdb_assert (entry->block == block);
+ return entry->static_link;
}
+\f
+
/* Called via bfd_map_over_sections to build up the section table that
the objfile references. The objfile contains pointers to the start
of the table (objfile->sections) and to the first location after
the end of the table (objfile->sections_end). */
+static void
+add_to_objfile_sections_full (struct bfd *abfd, struct bfd_section *asect,
+ struct objfile *objfile, int force)
+{
+ struct obj_section *section;
+
+ if (!force)
+ {
+ flagword aflag;
+
+ aflag = bfd_section_flags (asect);
+ if (!(aflag & SEC_ALLOC))
+ return;
+ }
+
+ section = &objfile->sections[gdb_bfd_section_index (abfd, asect)];
+ section->objfile = objfile;
+ section->the_bfd_section = asect;
+ section->ovly_mapped = 0;
+}
+
static void
add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect,
void *objfilep)
{
- struct objfile *objfile = (struct objfile *) objfilep;
- struct obj_section section;
- flagword aflag;
-
- aflag = bfd_get_section_flags (abfd, asect);
- if (!(aflag & SEC_ALLOC))
- return;
- if (bfd_section_size (abfd, asect) == 0)
- return;
-
- section.objfile = objfile;
- section.the_bfd_section = asect;
- section.ovly_mapped = 0;
- obstack_grow (&objfile->objfile_obstack,
- (char *) §ion, sizeof (section));
- objfile->sections_end
- = (struct obj_section *) (((size_t) objfile->sections_end) + 1);
+ add_to_objfile_sections_full (abfd, asect, (struct objfile *) objfilep, 0);
}
/* Builds a section table for OBJFILE.
- Note that while we are building the table, which goes into the
- objfile obstack, we hijack the sections_end pointer to instead hold
- a count of the number of sections. When bfd_map_over_sections
- returns, this count is used to compute the pointer to the end of
- the sections table, which then overwrites the count.
-
- Also note that the OFFSET and OVLY_MAPPED in each table entry
- are initialized to zero.
-
- Also note that if anything else writes to the objfile obstack while
- we are building the table, we're pretty much hosed. */
+ Note that the OFFSET and OVLY_MAPPED in each table entry are
+ initialized to zero. */
void
build_objfile_section_table (struct objfile *objfile)
{
- objfile->sections_end = 0;
+ int count = gdb_bfd_count_sections (objfile->obfd);
+
+ objfile->sections = OBSTACK_CALLOC (&objfile->objfile_obstack,
+ count,
+ struct obj_section);
+ objfile->sections_end = (objfile->sections + count);
bfd_map_over_sections (objfile->obfd,
add_to_objfile_sections, (void *) objfile);
- objfile->sections = obstack_finish (&objfile->objfile_obstack);
- objfile->sections_end = objfile->sections + (size_t) objfile->sections_end;
+
+ /* See gdb_bfd_section_index. */
+ add_to_objfile_sections_full (objfile->obfd, bfd_com_section_ptr, objfile, 1);
+ add_to_objfile_sections_full (objfile->obfd, bfd_und_section_ptr, objfile, 1);
+ add_to_objfile_sections_full (objfile->obfd, bfd_abs_section_ptr, objfile, 1);
+ add_to_objfile_sections_full (objfile->obfd, bfd_ind_section_ptr, objfile, 1);
}
-/* Given a pointer to an initialized bfd (ABFD) and some flag bits
- allocate a new objfile struct, fill it in as best we can, link it
- into the list of all known objfiles, and return a pointer to the
- new objfile struct.
+/* Given a pointer to an initialized bfd (ABFD) and some flag bits,
+ initialize the new objfile as best we can and link it into the list
+ of all known objfiles.
+
+ NAME should contain original non-canonicalized filename or other
+ identifier as entered by user. If there is no better source use
+ bfd_get_filename (ABFD). NAME may be NULL only if ABFD is NULL.
+ NAME content is copied into returned objfile.
The FLAGS word contains various bits (OBJF_*) that can be taken as
requests for specific operations. Other bits like OBJF_SHARED are
simply copied through to the new objfile flags member. */
-/* NOTE: carlton/2003-02-04: This function is called with args NULL, 0
- by jv-lang.c, to create an artificial objfile used to hold
- information about dynamically-loaded Java classes. Unfortunately,
- that branch of this function doesn't get tested very frequently, so
- it's prone to breakage. (E.g. at one time the name was set to NULL
- in that situation, which broke a loop over all names in the dynamic
- library loader.) If you change this function, please try to leave
- things in a consistent state even if abfd is NULL. */
-
-struct objfile *
-allocate_objfile (bfd *abfd, int flags)
+objfile::objfile (bfd *abfd, const char *name, objfile_flags flags_)
+ : flags (flags_),
+ pspace (current_program_space),
+ partial_symtabs (new psymtab_storage ()),
+ obfd (abfd)
{
- struct objfile *objfile;
+ const char *expanded_name;
- objfile = (struct objfile *) xzalloc (sizeof (struct objfile));
- objfile->psymbol_cache = psymbol_bcache_init ();
- objfile->macro_cache = bcache_xmalloc (NULL, NULL);
- objfile->filename_cache = bcache_xmalloc (NULL, NULL);
/* We could use obstack_specify_allocation here instead, but
gdb_obstack.h specifies the alloc/dealloc functions. */
- obstack_init (&objfile->objfile_obstack);
- terminate_minimal_symbol_table (objfile);
+ obstack_init (&objfile_obstack);
- objfile_alloc_data (objfile);
+ objfile_alloc_data (this);
- /* Update the per-objfile information that comes from the bfd, ensuring
- that any data that is reference is saved in the per-objfile data
- region. */
-
- objfile->obfd = gdb_bfd_ref (abfd);
- if (abfd != NULL)
+ gdb::unique_xmalloc_ptr<char> name_holder;
+ if (name == NULL)
{
- /* Look up the gdbarch associated with the BFD. */
- objfile->gdbarch = gdbarch_from_bfd (abfd);
-
- objfile->name = xstrdup (bfd_get_filename (abfd));
- objfile->mtime = bfd_get_mtime (abfd);
-
- /* Build section table. */
- build_objfile_section_table (objfile);
+ gdb_assert (abfd == NULL);
+ gdb_assert ((flags & OBJF_NOT_FILENAME) != 0);
+ expanded_name = "<<anonymous objfile>>";
}
+ else if ((flags & OBJF_NOT_FILENAME) != 0
+ || is_target_filename (name))
+ expanded_name = name;
else
{
- objfile->name = xstrdup ("<<anonymous objfile>>");
+ name_holder = gdb_abspath (name);
+ expanded_name = name_holder.get ();
}
+ original_name = obstack_strdup (&objfile_obstack, expanded_name);
- objfile->pspace = current_program_space;
-
- /* Initialize the section indexes for this objfile, so that we can
- later detect if they are used w/o being properly assigned to. */
-
- objfile->sect_index_text = -1;
- objfile->sect_index_data = -1;
- objfile->sect_index_bss = -1;
- objfile->sect_index_rodata = -1;
-
- /* Add this file onto the tail of the linked list of other such files. */
+ /* Update the per-objfile information that comes from the bfd, ensuring
+ that any data that is reference is saved in the per-objfile data
+ region. */
- objfile->next = NULL;
- if (object_files == NULL)
- object_files = objfile;
- else
+ gdb_bfd_ref (abfd);
+ if (abfd != NULL)
{
- struct objfile *last_one;
+ mtime = bfd_get_mtime (abfd);
- for (last_one = object_files;
- last_one->next;
- last_one = last_one->next);
- last_one->next = objfile;
+ /* Build section table. */
+ build_objfile_section_table (this);
}
- /* Save passed in flag bits. */
- objfile->flags |= flags;
-
- /* Rebuild section map next time we need it. */
- get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1;
-
- return objfile;
+ per_bfd = get_objfile_bfd_data (this, abfd);
}
/* Retrieve the gdbarch associated with OBJFILE. */
-struct gdbarch *
-get_objfile_arch (struct objfile *objfile)
-{
- return objfile->gdbarch;
-}
-/* Initialize entry point information for this objfile. */
-
-void
-init_entry_point_info (struct objfile *objfile)
+struct gdbarch *
+get_objfile_arch (const struct objfile *objfile)
{
- /* Save startup file's range of PC addresses to help blockframe.c
- decide where the bottom of the stack is. */
-
- if (bfd_get_file_flags (objfile->obfd) & EXEC_P)
- {
- /* Executable file -- record its entry point so we'll recognize
- the startup file because it contains the entry point. */
- objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
- objfile->ei.entry_point_p = 1;
- }
- else if (bfd_get_file_flags (objfile->obfd) & DYNAMIC
- && bfd_get_start_address (objfile->obfd) != 0)
- {
- /* Some shared libraries may have entry points set and be
- runnable. There's no clear way to indicate this, so just check
- for values other than zero. */
- objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
- objfile->ei.entry_point_p = 1;
- }
- else
- {
- /* Examination of non-executable.o files. Short-circuit this stuff. */
- objfile->ei.entry_point_p = 0;
- }
+ return objfile->per_bfd->gdbarch;
}
/* If there is a valid and known entry point, function fills *ENTRY_P with it
int
entry_point_address_query (CORE_ADDR *entry_p)
{
- struct gdbarch *gdbarch;
- CORE_ADDR entry_point;
-
- if (symfile_objfile == NULL || !symfile_objfile->ei.entry_point_p)
+ if (symfile_objfile == NULL || !symfile_objfile->per_bfd->ei.entry_point_p)
return 0;
- gdbarch = get_objfile_arch (symfile_objfile);
-
- entry_point = symfile_objfile->ei.entry_point;
-
- /* Make certain that the address points at real code, and not a
- function descriptor. */
- entry_point = gdbarch_convert_from_func_ptr_addr (gdbarch, entry_point,
- ¤t_target);
+ int idx = symfile_objfile->per_bfd->ei.the_bfd_section_index;
+ *entry_p = (symfile_objfile->per_bfd->ei.entry_point
+ + symfile_objfile->section_offsets[idx]);
- /* Remove any ISA markers, so that this matches entries in the
- symbol table. */
- entry_point = gdbarch_addr_bits_remove (gdbarch, entry_point);
-
- *entry_p = entry_point;
return 1;
}
return retval;
}
-/* Iterator on PARENT and every separate debug objfile of PARENT.
- The usage pattern is:
- for (objfile = parent;
- objfile;
- objfile = objfile_separate_debug_iterate (parent, objfile))
- ...
-*/
-
-struct objfile *
-objfile_separate_debug_iterate (const struct objfile *parent,
- const struct objfile *objfile)
+separate_debug_iterator &
+separate_debug_iterator::operator++ ()
{
+ gdb_assert (m_objfile != nullptr);
+
struct objfile *res;
/* If any, return the first child. */
- res = objfile->separate_debug_objfile;
- if (res)
- return res;
-
- /* Common case where there is no separate debug objfile. */
- if (objfile == parent)
- return NULL;
-
- /* Return the brother if any. Note that we don't iterate on brothers of
- the parents. */
- res = objfile->separate_debug_objfile_link;
- if (res)
- return res;
-
- for (res = objfile->separate_debug_objfile_backlink;
- res != parent;
- res = res->separate_debug_objfile_backlink)
+ res = m_objfile->separate_debug_objfile;
+ if (res != nullptr)
{
- gdb_assert (res != NULL);
- if (res->separate_debug_objfile_link)
- return res->separate_debug_objfile_link;
+ m_objfile = res;
+ return *this;
}
- return NULL;
-}
-/* Put one object file before a specified on in the global list.
- This can be used to make sure an object file is destroyed before
- another when using ALL_OBJFILES_SAFE to free all objfiles. */
-void
-put_objfile_before (struct objfile *objfile, struct objfile *before_this)
-{
- struct objfile **objp;
-
- unlink_objfile (objfile);
-
- for (objp = &object_files; *objp != NULL; objp = &((*objp)->next))
+ /* Common case where there is no separate debug objfile. */
+ if (m_objfile == m_parent)
{
- if (*objp == before_this)
- {
- objfile->next = *objp;
- *objp = objfile;
- return;
- }
+ m_objfile = nullptr;
+ return *this;
}
-
- internal_error (__FILE__, __LINE__,
- _("put_objfile_before: before objfile not in list"));
-}
-
-/* Put OBJFILE at the front of the list. */
-void
-objfile_to_front (struct objfile *objfile)
-{
- struct objfile **objp;
- for (objp = &object_files; *objp != NULL; objp = &((*objp)->next))
+ /* Return the brother if any. Note that we don't iterate on brothers of
+ the parents. */
+ res = m_objfile->separate_debug_objfile_link;
+ if (res != nullptr)
{
- if (*objp == objfile)
- {
- /* Unhook it from where it is. */
- *objp = objfile->next;
- /* Put it in the front. */
- objfile->next = object_files;
- object_files = objfile;
- break;
- }
+ m_objfile = res;
+ return *this;
}
-}
-
-/* Unlink OBJFILE from the list of known objfiles, if it is found in the
- list.
-
- It is not a bug, or error, to call this function if OBJFILE is not known
- to be in the current list. This is done in the case of mapped objfiles,
- for example, just to ensure that the mapped objfile doesn't appear twice
- in the list. Since the list is threaded, linking in a mapped objfile
- twice would create a circular list.
- If OBJFILE turns out to be in the list, we zap it's NEXT pointer after
- unlinking it, just to ensure that we have completely severed any linkages
- between the OBJFILE and the list. */
-
-void
-unlink_objfile (struct objfile *objfile)
-{
- struct objfile **objpp;
-
- for (objpp = &object_files; *objpp != NULL; objpp = &((*objpp)->next))
+ for (res = m_objfile->separate_debug_objfile_backlink;
+ res != m_parent;
+ res = res->separate_debug_objfile_backlink)
{
- if (*objpp == objfile)
+ gdb_assert (res != nullptr);
+ if (res->separate_debug_objfile_link != nullptr)
{
- *objpp = (*objpp)->next;
- objfile->next = NULL;
- return;
+ m_objfile = res->separate_debug_objfile_link;
+ return *this;
}
}
-
- internal_error (__FILE__, __LINE__,
- _("unlink_objfile: objfile already unlinked"));
+ m_objfile = nullptr;
+ return *this;
}
/* Add OBJFILE as a separate debug objfile of PARENT. */
-void
+static void
add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent)
{
gdb_assert (objfile && parent);
/* Must not be already in a list. */
gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
gdb_assert (objfile->separate_debug_objfile_link == NULL);
+ gdb_assert (objfile->separate_debug_objfile == NULL);
+ gdb_assert (parent->separate_debug_objfile_backlink == NULL);
+ gdb_assert (parent->separate_debug_objfile_link == NULL);
objfile->separate_debug_objfile_backlink = parent;
objfile->separate_debug_objfile_link = parent->separate_debug_objfile;
parent->separate_debug_objfile = objfile;
+}
+
+/* See objfiles.h. */
+
+objfile *
+objfile::make (bfd *bfd_, const char *name_, objfile_flags flags_,
+ objfile *parent)
+{
+ objfile *result = new objfile (bfd_, name_, flags_);
+ if (parent != nullptr)
+ add_separate_debug_objfile (result, parent);
+
+ /* Using std::make_shared might be a bit nicer here, but that would
+ require making the constructor public. */
+ current_program_space->add_objfile (std::shared_ptr<objfile> (result),
+ parent);
- /* Put the separate debug object before the normal one, this is so that
- usage of the ALL_OBJFILES_SAFE macro will stay safe. */
- put_objfile_before (objfile, parent);
+ /* Rebuild section map next time we need it. */
+ get_objfile_pspace_data (current_program_space)->new_objfiles_available = 1;
+
+ return result;
+}
+
+/* See objfiles.h. */
+
+void
+objfile::unlink ()
+{
+ current_program_space->remove_objfile (this);
}
/* Free all separate debug objfile of OBJFILE, but don't free OBJFILE
for (child = objfile->separate_debug_objfile; child;)
{
struct objfile *next_child = child->separate_debug_objfile_link;
- free_objfile (child);
+ child->unlink ();
child = next_child;
}
}
-/* Destroy an objfile and all the symtabs and psymtabs under it. Note
- that as much as possible is allocated on the objfile_obstack
- so that the memory can be efficiently freed.
-
- Things which we do NOT free because they are not in malloc'd memory
- or not in memory specific to the objfile include:
-
- objfile -> sf
+/* Destroy an objfile and all the symtabs and psymtabs under it. */
- FIXME: If the objfile is using reusable symbol information (via mmalloc),
- then we need to take into account the fact that more than one process
- may be using the symbol information at the same time (when mmalloc is
- extended to support cooperative locking). When more than one process
- is using the mapped symbol info, we need to be more careful about when
- we free objects in the reusable area. */
-
-void
-free_objfile (struct objfile *objfile)
+objfile::~objfile ()
{
+ /* First notify observers that this objfile is about to be freed. */
+ gdb::observers::free_objfile.notify (this);
+
/* Free all separate debug objfiles. */
- free_objfile_separate_debug (objfile);
+ free_objfile_separate_debug (this);
- if (objfile->separate_debug_objfile_backlink)
+ if (separate_debug_objfile_backlink)
{
/* We freed the separate debug file, make sure the base objfile
doesn't reference it. */
struct objfile *child;
- child = objfile->separate_debug_objfile_backlink->separate_debug_objfile;
+ child = separate_debug_objfile_backlink->separate_debug_objfile;
- if (child == objfile)
+ if (child == this)
{
- /* OBJFILE is the first child. */
- objfile->separate_debug_objfile_backlink->separate_debug_objfile =
- objfile->separate_debug_objfile_link;
+ /* THIS is the first child. */
+ separate_debug_objfile_backlink->separate_debug_objfile =
+ separate_debug_objfile_link;
}
else
{
- /* Find OBJFILE in the list. */
+ /* Find THIS in the list. */
while (1)
{
- if (child->separate_debug_objfile_link == objfile)
+ if (child->separate_debug_objfile_link == this)
{
child->separate_debug_objfile_link =
- objfile->separate_debug_objfile_link;
+ separate_debug_objfile_link;
break;
}
child = child->separate_debug_objfile_link;
}
}
}
-
+
/* Remove any references to this objfile in the global value
lists. */
- preserve_values (objfile);
+ preserve_values (this);
/* It still may reference data modules have associated with the objfile and
the symbol file data. */
- forget_cached_source_info_for_objfile (objfile);
+ forget_cached_source_info_for_objfile (this);
+
+ breakpoint_free_objfile (this);
+ btrace_free_objfile (this);
/* First do any symbol file specific actions required when we are
finished with a particular symbol file. Note that if the objfile
freeing things which are valid only during this particular gdb
execution, or leaving them to be reused during the next one. */
- if (objfile->sf != NULL)
- {
- (*objfile->sf->sym_finish) (objfile);
- }
+ if (sf != NULL)
+ (*sf->sym_finish) (this);
/* Discard any data modules have associated with the objfile. The function
- still may reference objfile->obfd. */
- objfile_free_data (objfile);
-
- gdb_bfd_unref (objfile->obfd);
+ still may reference obfd. */
+ objfile_free_data (this);
- /* Remove it from the chain of all objfiles. */
-
- unlink_objfile (objfile);
-
- if (objfile == symfile_objfile)
- symfile_objfile = NULL;
-
- if (objfile == rt_common_objfile)
- rt_common_objfile = NULL;
+ if (obfd)
+ gdb_bfd_unref (obfd);
+ else
+ delete per_bfd;
/* Before the symbol table code was redone to make it easier to
selectively load and remove information particular to a specific
for example), so we need to call this here. */
clear_pc_function_cache ();
- /* Clear globals which might have pointed into a removed objfile.
- FIXME: It's not clear which of these are supposed to persist
- between expressions and which ought to be reset each time. */
- expression_context_block = NULL;
- innermost_block = NULL;
-
/* Check to see if the current_source_symtab belongs to this objfile,
and if so, call clear_current_source_symtab_and_line. */
{
struct symtab_and_line cursal = get_current_source_symtab_and_line ();
- if (cursal.symtab && cursal.symtab->objfile == objfile)
+ if (cursal.symtab && SYMTAB_OBJFILE (cursal.symtab) == this)
clear_current_source_symtab_and_line ();
}
- /* The last thing we do is free the objfile struct itself. */
-
- xfree (objfile->name);
- if (objfile->global_psymbols.list)
- xfree (objfile->global_psymbols.list);
- if (objfile->static_psymbols.list)
- xfree (objfile->static_psymbols.list);
/* Free the obstacks for non-reusable objfiles. */
- psymbol_bcache_free (objfile->psymbol_cache);
- bcache_xfree (objfile->macro_cache);
- bcache_xfree (objfile->filename_cache);
- if (objfile->demangled_names_hash)
- htab_delete (objfile->demangled_names_hash);
- obstack_free (&objfile->objfile_obstack, 0);
+ obstack_free (&objfile_obstack, 0);
/* Rebuild section map next time we need it. */
- get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1;
-
- xfree (objfile);
-}
-
-static void
-do_free_objfile_cleanup (void *obj)
-{
- free_objfile (obj);
+ get_objfile_pspace_data (pspace)->section_map_dirty = 1;
}
-struct cleanup *
-make_cleanup_free_objfile (struct objfile *obj)
-{
- return make_cleanup (do_free_objfile_cleanup, obj);
-}
-
-/* Free all the object files at once and clean up their users. */
-
-void
-free_all_objfiles (void)
-{
- struct objfile *objfile, *temp;
- struct so_list *so;
-
- /* Any objfile referencewould become stale. */
- for (so = master_so_list (); so; so = so->next)
- gdb_assert (so->objfile == NULL);
-
- ALL_OBJFILES_SAFE (objfile, temp)
- {
- free_objfile (objfile);
- }
- clear_symtab_users (0);
-}
\f
/* A helper function for objfile_relocate1 that relocates a single
symbol. */
static void
relocate_one_symbol (struct symbol *sym, struct objfile *objfile,
- struct section_offsets *delta)
+ const section_offsets &delta)
{
fixup_symbol_section (sym, objfile);
|| SYMBOL_CLASS (sym) == LOC_STATIC)
&& SYMBOL_SECTION (sym) >= 0)
{
- SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (delta, SYMBOL_SECTION (sym));
+ SET_SYMBOL_VALUE_ADDRESS (sym,
+ SYMBOL_VALUE_ADDRESS (sym)
+ + delta[SYMBOL_SECTION (sym)]);
}
}
static int
objfile_relocate1 (struct objfile *objfile,
- struct section_offsets *new_offsets)
+ const section_offsets &new_offsets)
{
- struct obj_section *s;
- struct section_offsets *delta =
- ((struct section_offsets *)
- alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)));
+ section_offsets delta (objfile->section_offsets.size ());
- int i;
int something_changed = 0;
- for (i = 0; i < objfile->num_sections; ++i)
+ for (int i = 0; i < objfile->section_offsets.size (); ++i)
{
- delta->offsets[i] =
- ANOFFSET (new_offsets, i) - ANOFFSET (objfile->section_offsets, i);
- if (ANOFFSET (delta, i) != 0)
+ delta[i] = new_offsets[i] - objfile->section_offsets[i];
+ if (delta[i] != 0)
something_changed = 1;
}
if (!something_changed)
/* OK, get all the symtabs. */
{
- struct symtab *s;
-
- ALL_OBJFILE_SYMTABS (objfile, s)
- {
- struct linetable *l;
- struct blockvector *bv;
- int i;
-
- /* First the line table. */
- l = LINETABLE (s);
- if (l)
- {
- for (i = 0; i < l->nitems; ++i)
- l->item[i].pc += ANOFFSET (delta, s->block_line_section);
- }
-
- /* Don't relocate a shared blockvector more than once. */
- if (!s->primary)
- continue;
-
- bv = BLOCKVECTOR (s);
- if (BLOCKVECTOR_MAP (bv))
- addrmap_relocate (BLOCKVECTOR_MAP (bv),
- ANOFFSET (delta, s->block_line_section));
-
- for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); ++i)
- {
- struct block *b;
- struct symbol *sym;
- struct dict_iterator iter;
-
- b = BLOCKVECTOR_BLOCK (bv, i);
- BLOCK_START (b) += ANOFFSET (delta, s->block_line_section);
- BLOCK_END (b) += ANOFFSET (delta, s->block_line_section);
+ for (compunit_symtab *cust : objfile->compunits ())
+ {
+ for (symtab *s : compunit_filetabs (cust))
+ {
+ struct linetable *l;
+
+ /* First the line table. */
+ l = SYMTAB_LINETABLE (s);
+ if (l)
+ {
+ for (int i = 0; i < l->nitems; ++i)
+ l->item[i].pc += delta[COMPUNIT_BLOCK_LINE_SECTION (cust)];
+ }
+ }
+ }
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- relocate_one_symbol (sym, objfile, delta);
- }
- }
- }
+ for (compunit_symtab *cust : objfile->compunits ())
+ {
+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (cust);
+ int block_line_section = COMPUNIT_BLOCK_LINE_SECTION (cust);
+
+ if (BLOCKVECTOR_MAP (bv))
+ addrmap_relocate (BLOCKVECTOR_MAP (bv), delta[block_line_section]);
+
+ for (int i = 0; i < BLOCKVECTOR_NBLOCKS (bv); ++i)
+ {
+ struct block *b;
+ struct symbol *sym;
+ struct mdict_iterator miter;
+
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ BLOCK_START (b) += delta[block_line_section];
+ BLOCK_END (b) += delta[block_line_section];
+
+ if (BLOCK_RANGES (b) != nullptr)
+ for (int j = 0; j < BLOCK_NRANGES (b); j++)
+ {
+ BLOCK_RANGE_START (b, j) += delta[block_line_section];
+ BLOCK_RANGE_END (b, j) += delta[block_line_section];
+ }
+
+ /* We only want to iterate over the local symbols, not any
+ symbols in included symtabs. */
+ ALL_DICT_SYMBOLS (BLOCK_MULTIDICT (b), miter, sym)
+ {
+ relocate_one_symbol (sym, objfile, delta);
+ }
+ }
+ }
}
+ /* This stores relocated addresses and so must be cleared. This
+ will cause it to be recreated on demand. */
+ objfile->psymbol_map.clear ();
+
/* Relocate isolated symbols. */
{
struct symbol *iter;
relocate_one_symbol (iter, objfile, delta);
}
- if (objfile->psymtabs_addrmap)
- addrmap_relocate (objfile->psymtabs_addrmap,
- ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
-
- if (objfile->sf)
- objfile->sf->qf->relocate (objfile, new_offsets, delta);
-
- {
- struct minimal_symbol *msym;
-
- ALL_OBJFILE_MSYMBOLS (objfile, msym)
- if (SYMBOL_SECTION (msym) >= 0)
- SYMBOL_VALUE_ADDRESS (msym) += ANOFFSET (delta, SYMBOL_SECTION (msym));
- }
- /* Relocating different sections by different amounts may cause the symbols
- to be out of order. */
- msymbols_sort (objfile);
-
- if (objfile->ei.entry_point_p)
- {
- /* Relocate ei.entry_point with its section offset, use SECT_OFF_TEXT
- only as a fallback. */
- struct obj_section *s;
- s = find_pc_section (objfile->ei.entry_point);
- if (s)
- objfile->ei.entry_point += ANOFFSET (delta, s->the_bfd_section->index);
- else
- objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
- }
-
{
int i;
- for (i = 0; i < objfile->num_sections; ++i)
- (objfile->section_offsets)->offsets[i] = ANOFFSET (new_offsets, i);
+ for (i = 0; i < objfile->section_offsets.size (); ++i)
+ objfile->section_offsets[i] = new_offsets[i];
}
/* Rebuild section map next time we need it. */
- get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1;
+ get_objfile_pspace_data (objfile->pspace)->section_map_dirty = 1;
/* Update the table in exec_ops, used to read memory. */
+ struct obj_section *s;
ALL_OBJFILE_OSECTIONS (objfile, s)
{
- int idx = s->the_bfd_section->index;
+ int idx = s - objfile->sections;
exec_set_section_address (bfd_get_filename (objfile->obfd), idx,
obj_section_addr (s));
files. */
void
-objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
+objfile_relocate (struct objfile *objfile,
+ const section_offsets &new_offsets)
{
- struct objfile *debug_objfile;
int changed = 0;
changed |= objfile_relocate1 (objfile, new_offsets);
- for (debug_objfile = objfile->separate_debug_objfile;
- debug_objfile;
- debug_objfile = objfile_separate_debug_iterate (objfile, debug_objfile))
+ for (::objfile *debug_objfile : objfile->separate_debug_objfiles ())
{
- struct section_addr_info *objfile_addrs;
- struct section_offsets *new_debug_offsets;
- struct cleanup *my_cleanups;
+ if (debug_objfile == objfile)
+ continue;
- objfile_addrs = build_section_addr_info_from_objfile (objfile);
- my_cleanups = make_cleanup (xfree, objfile_addrs);
+ section_addr_info objfile_addrs
+ = build_section_addr_info_from_objfile (objfile);
/* Here OBJFILE_ADDRS contain the correct absolute addresses, the
relative ones must be already created according to debug_objfile. */
- addr_info_make_relative (objfile_addrs, debug_objfile->obfd);
+ addr_info_make_relative (&objfile_addrs, debug_objfile->obfd);
- gdb_assert (debug_objfile->num_sections
- == bfd_count_sections (debug_objfile->obfd));
- new_debug_offsets =
- xmalloc (SIZEOF_N_SECTION_OFFSETS (debug_objfile->num_sections));
- make_cleanup (xfree, new_debug_offsets);
- relative_addr_info_to_section_offsets (new_debug_offsets,
- debug_objfile->num_sections,
- objfile_addrs);
+ gdb_assert (debug_objfile->section_offsets.size ()
+ == gdb_bfd_count_sections (debug_objfile->obfd));
+ section_offsets new_debug_offsets
+ (debug_objfile->section_offsets.size ());
+ relative_addr_info_to_section_offsets (new_debug_offsets, objfile_addrs);
changed |= objfile_relocate1 (debug_objfile, new_debug_offsets);
-
- do_cleanups (my_cleanups);
}
/* Relocate breakpoints as necessary, after things are relocated. */
if (changed)
breakpoint_re_set ();
}
+
+/* Rebase (add to the offsets) OBJFILE by SLIDE. SEPARATE_DEBUG_OBJFILE is
+ not touched here.
+ Return non-zero iff any change happened. */
+
+static int
+objfile_rebase1 (struct objfile *objfile, CORE_ADDR slide)
+{
+ section_offsets new_offsets (objfile->section_offsets.size (), slide);
+ return objfile_relocate1 (objfile, new_offsets);
+}
+
+/* Rebase (add to the offsets) OBJFILE by SLIDE. Process also OBJFILE's
+ SEPARATE_DEBUG_OBJFILEs. */
+
+void
+objfile_rebase (struct objfile *objfile, CORE_ADDR slide)
+{
+ int changed = 0;
+
+ for (::objfile *debug_objfile : objfile->separate_debug_objfiles ())
+ changed |= objfile_rebase1 (debug_objfile, slide);
+
+ /* Relocate breakpoints as necessary, after things are relocated. */
+ if (changed)
+ breakpoint_re_set ();
+}
\f
/* Return non-zero if OBJFILE has partial symbols. */
int
objfile_has_full_symbols (struct objfile *objfile)
{
- return objfile->symtabs != NULL;
+ return objfile->compunit_symtabs != NULL;
}
/* Return non-zero if OBJFILE has full or partial symbols, either directly
int
objfile_has_symbols (struct objfile *objfile)
{
- struct objfile *o;
-
- for (o = objfile; o; o = objfile_separate_debug_iterate (objfile, o))
+ for (::objfile *o : objfile->separate_debug_objfiles ())
if (objfile_has_partial_symbols (o) || objfile_has_full_symbols (o))
return 1;
return 0;
int
have_partial_symbols (void)
{
- struct objfile *ofp;
-
- ALL_OBJFILES (ofp)
- {
- if (objfile_has_partial_symbols (ofp))
- return 1;
- }
+ for (objfile *ofp : current_program_space->objfiles ())
+ {
+ if (objfile_has_partial_symbols (ofp))
+ return 1;
+ }
return 0;
}
int
have_full_symbols (void)
{
- struct objfile *ofp;
-
- ALL_OBJFILES (ofp)
- {
- if (objfile_has_full_symbols (ofp))
- return 1;
- }
+ for (objfile *ofp : current_program_space->objfiles ())
+ {
+ if (objfile_has_full_symbols (ofp))
+ return 1;
+ }
return 0;
}
void
objfile_purge_solibs (void)
{
- struct objfile *objf;
- struct objfile *temp;
-
- ALL_OBJFILES_SAFE (objf, temp)
- {
- /* We assume that the solib package has been purged already, or will
- be soon. */
+ for (objfile *objf : current_program_space->objfiles_safe ())
+ {
+ /* We assume that the solib package has been purged already, or will
+ be soon. */
- if (!(objf->flags & OBJF_USERLOADED) && (objf->flags & OBJF_SHARED))
- free_objfile (objf);
- }
+ if (!(objf->flags & OBJF_USERLOADED) && (objf->flags & OBJF_SHARED))
+ objf->unlink ();
+ }
}
int
have_minimal_symbols (void)
{
- struct objfile *ofp;
-
- ALL_OBJFILES (ofp)
- {
- if (ofp->minimal_symbol_count > 0)
- {
- return 1;
- }
- }
+ for (objfile *ofp : current_program_space->objfiles ())
+ {
+ if (ofp->per_bfd->minimal_symbol_count > 0)
+ {
+ return 1;
+ }
+ }
return 0;
}
/* Qsort comparison function. */
-static int
-qsort_cmp (const void *a, const void *b)
+static bool
+sort_cmp (const struct obj_section *sect1, const obj_section *sect2)
{
- const struct obj_section *sect1 = *(const struct obj_section **) a;
- const struct obj_section *sect2 = *(const struct obj_section **) b;
const CORE_ADDR sect1_addr = obj_section_addr (sect1);
const CORE_ADDR sect2_addr = obj_section_addr (sect2);
if (sect1_addr < sect2_addr)
- return -1;
+ return true;
else if (sect1_addr > sect2_addr)
- return 1;
+ return false;
else
{
/* Sections are at the same address. This could happen if
/* Case A. The ordering doesn't matter: separate debuginfo files
will be filtered out later. */
- return 0;
+ return false;
}
/* Case B. Maintain stable sort order, so bugs in GDB are easier to
triage. This section could be slow (since we iterate over all
- objfiles in each call to qsort_cmp), but this shouldn't happen
+ objfiles in each call to sort_cmp), but this shouldn't happen
very often (GDB is already in a confused state; one hopes this
doesn't happen at all). If you discover that significant time is
spent in the loops below, do 'set complaints 100' and examine the
resulting complaints. */
-
if (objfile1 == objfile2)
{
- /* Both sections came from the same objfile. We are really confused.
- Sort on sequence order of sections within the objfile. */
+ /* Both sections came from the same objfile. We are really
+ confused. Sort on sequence order of sections within the
+ objfile. The order of checks is important here, if we find a
+ match on SECT2 first then either SECT2 is before SECT1, or,
+ SECT2 == SECT1, in both cases we should return false. The
+ second case shouldn't occur during normal use, but std::sort
+ does check that '!(a < a)' when compiled in debug mode. */
const struct obj_section *osect;
ALL_OBJFILE_OSECTIONS (objfile1, osect)
- if (osect == sect1)
- return -1;
- else if (osect == sect2)
- return 1;
+ if (osect == sect2)
+ return false;
+ else if (osect == sect1)
+ return true;
/* We should have found one of the sections before getting here. */
gdb_assert_not_reached ("section not found");
{
/* Sort on sequence number of the objfile in the chain. */
- const struct objfile *objfile;
-
- ALL_OBJFILES (objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
if (objfile == objfile1)
- return -1;
+ return true;
else if (objfile == objfile2)
- return 1;
+ return false;
/* We should have found one of the objfiles before getting here. */
gdb_assert_not_reached ("objfile not found");
/* Unreachable. */
gdb_assert_not_reached ("unexpected code path");
- return 0;
+ return false;
}
/* Select "better" obj_section to keep. We prefer the one that came from
insert_section_p (const struct bfd *abfd,
const struct bfd_section *section)
{
- const bfd_vma lma = bfd_section_lma (abfd, section);
+ const bfd_vma lma = bfd_section_lma (section);
- if (overlay_debugging && lma != 0 && lma != bfd_section_vma (abfd, section)
+ if (overlay_debugging && lma != 0 && lma != bfd_section_vma (section)
&& (bfd_get_file_flags (abfd) & BFD_IN_MEMORY) == 0)
/* This is an overlay section. IN_MEMORY check is needed to avoid
discarding sections from the "system supplied DSO" (aka vdso)
on some Linux systems (e.g. Fedora 11). */
return 0;
- if ((bfd_get_section_flags (abfd, section) & SEC_THREAD_LOCAL) != 0)
+ if ((bfd_section_flags (section) & SEC_THREAD_LOCAL) != 0)
/* This is a TLS section. */
return 0;
struct objfile *const objf1 = sect1->objfile;
struct objfile *const objf2 = sect2->objfile;
- const struct bfd *const abfd1 = objf1->obfd;
- const struct bfd *const abfd2 = objf2->obfd;
-
const struct bfd_section *const bfds1 = sect1->the_bfd_section;
const struct bfd_section *const bfds2 = sect2->the_bfd_section;
struct gdbarch *const gdbarch = get_objfile_arch (objf1);
- complaint (&symfile_complaints,
- _("unexpected overlap between:\n"
+ complaint (_("unexpected overlap between:\n"
" (A) section `%s' from `%s' [%s, %s)\n"
" (B) section `%s' from `%s' [%s, %s).\n"
"Will ignore section B"),
- bfd_section_name (abfd1, bfds1), objf1->name,
+ bfd_section_name (bfds1), objfile_name (objf1),
paddress (gdbarch, sect1_addr),
paddress (gdbarch, sect1_endaddr),
- bfd_section_name (abfd2, bfds2), objf2->name,
+ bfd_section_name (bfds2), objfile_name (objf2),
paddress (gdbarch, sect2_addr),
paddress (gdbarch, sect2_endaddr));
}
update_section_map (struct program_space *pspace,
struct obj_section ***pmap, int *pmap_size)
{
+ struct objfile_pspace_info *pspace_info;
int alloc_size, map_size, i;
struct obj_section *s, **map;
- struct objfile *objfile;
- gdb_assert (get_objfile_pspace_data (pspace)->objfiles_changed_p != 0);
+ pspace_info = get_objfile_pspace_data (pspace);
+ gdb_assert (pspace_info->section_map_dirty != 0
+ || pspace_info->new_objfiles_available != 0);
map = *pmap;
xfree (map);
alloc_size = 0;
- ALL_PSPACE_OBJFILES (pspace, objfile)
+ for (objfile *objfile : pspace->objfiles ())
ALL_OBJFILE_OSECTIONS (objfile, s)
if (insert_section_p (objfile->obfd, s->the_bfd_section))
alloc_size += 1;
return;
}
- map = xmalloc (alloc_size * sizeof (*map));
+ map = XNEWVEC (struct obj_section *, alloc_size);
i = 0;
- ALL_PSPACE_OBJFILES (pspace, objfile)
+ for (objfile *objfile : pspace->objfiles ())
ALL_OBJFILE_OSECTIONS (objfile, s)
if (insert_section_p (objfile->obfd, s->the_bfd_section))
map[i++] = s;
- qsort (map, alloc_size, sizeof (*map), qsort_cmp);
+ std::sort (map, map + alloc_size, sort_cmp);
map_size = filter_debuginfo_sections(map, alloc_size);
map_size = filter_overlapping_sections(map, map_size);
if (map_size < alloc_size)
/* Some sections were eliminated. Trim excess space. */
- map = xrealloc (map, map_size * sizeof (*map));
+ map = XRESIZEVEC (struct obj_section *, map, map_size);
else
gdb_assert (alloc_size == map_size);
return s;
pspace_info = get_objfile_pspace_data (current_program_space);
- if (pspace_info->objfiles_changed_p != 0)
+ if (pspace_info->section_map_dirty
+ || (pspace_info->new_objfiles_available
+ && !pspace_info->inhibit_updates))
{
update_section_map (current_program_space,
&pspace_info->sections,
/* Don't need updates to section map until objfiles are added,
removed or relocated. */
- pspace_info->objfiles_changed_p = 0;
+ pspace_info->new_objfiles_available = 0;
+ pspace_info->section_map_dirty = 0;
}
/* The C standard (ISO/IEC 9899:TC2) requires the BASE argument to
}
-/* In SVR4, we recognize a trampoline by it's section name.
- That is, if the pc is in a section named ".plt" then we are in
- a trampoline. */
+/* Return non-zero if PC is in a section called NAME. */
int
-in_plt_section (CORE_ADDR pc, char *name)
+pc_in_section (CORE_ADDR pc, const char *name)
{
struct obj_section *s;
int retval = 0;
retval = (s != NULL
&& s->the_bfd_section->name != NULL
- && strcmp (s->the_bfd_section->name, ".plt") == 0);
+ && strcmp (s->the_bfd_section->name, name) == 0);
return (retval);
}
\f
-/* Keep a registry of per-objfile data-pointers required by other GDB
- modules. */
-
-struct objfile_data
-{
- unsigned index;
- void (*save) (struct objfile *, void *);
- void (*free) (struct objfile *, void *);
-};
-
-struct objfile_data_registration
-{
- struct objfile_data *data;
- struct objfile_data_registration *next;
-};
-
-struct objfile_data_registry
-{
- struct objfile_data_registration *registrations;
- unsigned num_registrations;
-};
-
-static struct objfile_data_registry objfile_data_registry = { NULL, 0 };
-
-const struct objfile_data *
-register_objfile_data_with_cleanup (void (*save) (struct objfile *, void *),
- void (*free) (struct objfile *, void *))
-{
- struct objfile_data_registration **curr;
-
- /* Append new registration. */
- for (curr = &objfile_data_registry.registrations;
- *curr != NULL; curr = &(*curr)->next);
-
- *curr = XMALLOC (struct objfile_data_registration);
- (*curr)->next = NULL;
- (*curr)->data = XMALLOC (struct objfile_data);
- (*curr)->data->index = objfile_data_registry.num_registrations++;
- (*curr)->data->save = save;
- (*curr)->data->free = free;
-
- return (*curr)->data;
-}
+/* Set section_map_dirty so section map will be rebuilt next time it
+ is used. Called by reread_symbols. */
-const struct objfile_data *
-register_objfile_data (void)
+void
+objfiles_changed (void)
{
- return register_objfile_data_with_cleanup (NULL, NULL);
+ /* Rebuild section map next time we need it. */
+ get_objfile_pspace_data (current_program_space)->section_map_dirty = 1;
}
-static void
-objfile_alloc_data (struct objfile *objfile)
-{
- gdb_assert (objfile->data == NULL);
- objfile->num_data = objfile_data_registry.num_registrations;
- objfile->data = XCALLOC (objfile->num_data, void *);
-}
+/* See comments in objfiles.h. */
-static void
-objfile_free_data (struct objfile *objfile)
+scoped_restore_tmpl<int>
+inhibit_section_map_updates (struct program_space *pspace)
{
- gdb_assert (objfile->data != NULL);
- clear_objfile_data (objfile);
- xfree (objfile->data);
- objfile->data = NULL;
+ return scoped_restore_tmpl<int>
+ (&get_objfile_pspace_data (pspace)->inhibit_updates, 1);
}
-void
-clear_objfile_data (struct objfile *objfile)
-{
- struct objfile_data_registration *registration;
- int i;
+/* Return 1 if ADDR maps into one of the sections of OBJFILE and 0
+ otherwise. */
- gdb_assert (objfile->data != NULL);
-
- /* Process all the save handlers. */
-
- for (registration = objfile_data_registry.registrations, i = 0;
- i < objfile->num_data;
- registration = registration->next, i++)
- if (objfile->data[i] != NULL && registration->data->save != NULL)
- registration->data->save (objfile, objfile->data[i]);
-
- /* Now process all the free handlers. */
-
- for (registration = objfile_data_registry.registrations, i = 0;
- i < objfile->num_data;
- registration = registration->next, i++)
- if (objfile->data[i] != NULL && registration->data->free != NULL)
- registration->data->free (objfile, objfile->data[i]);
-
- memset (objfile->data, 0, objfile->num_data * sizeof (void *));
-}
-
-void
-set_objfile_data (struct objfile *objfile, const struct objfile_data *data,
- void *value)
+int
+is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile)
{
- gdb_assert (data->index < objfile->num_data);
- objfile->data[data->index] = value;
-}
+ struct obj_section *osect;
-void *
-objfile_data (struct objfile *objfile, const struct objfile_data *data)
-{
- gdb_assert (data->index < objfile->num_data);
- return objfile->data[data->index];
-}
+ if (objfile == NULL)
+ return 0;
-/* Set objfiles_changed_p so section map will be rebuilt next time it
- is used. Called by reread_symbols. */
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+ {
+ if (section_is_overlay (osect) && !section_is_mapped (osect))
+ continue;
-void
-objfiles_changed (void)
-{
- /* Rebuild section map next time we need it. */
- get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1;
+ if (obj_section_addr (osect) <= addr
+ && addr < obj_section_endaddr (osect))
+ return 1;
+ }
+ return 0;
}
-/* Close ABFD, and warn if that fails. */
-
int
-gdb_bfd_close_or_warn (struct bfd *abfd)
+shared_objfile_contains_address_p (struct program_space *pspace,
+ CORE_ADDR address)
{
- int ret;
- char *name = bfd_get_filename (abfd);
-
- ret = bfd_close (abfd);
-
- if (!ret)
- warning (_("cannot close \"%s\": %s"),
- name, bfd_errmsg (bfd_get_error ()));
+ for (objfile *objfile : pspace->objfiles ())
+ {
+ if ((objfile->flags & OBJF_SHARED) != 0
+ && is_addr_in_objfile (address, objfile))
+ return 1;
+ }
- return ret;
+ return 0;
}
-/* Add reference to ABFD. Returns ABFD. */
-struct bfd *
-gdb_bfd_ref (struct bfd *abfd)
-{
- int *p_refcount;
+/* The default implementation for the "iterate_over_objfiles_in_search_order"
+ gdbarch method. It is equivalent to use the objfiles iterable,
+ searching the objfiles in the order they are stored internally,
+ ignoring CURRENT_OBJFILE.
- if (abfd == NULL)
- return NULL;
+ On most platforms, it should be close enough to doing the best
+ we can without some knowledge specific to the architecture. */
- p_refcount = bfd_usrdata (abfd);
+void
+default_iterate_over_objfiles_in_search_order
+ (struct gdbarch *gdbarch,
+ iterate_over_objfiles_in_search_order_cb_ftype *cb,
+ void *cb_data, struct objfile *current_objfile)
+{
+ int stop = 0;
- if (p_refcount != NULL)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- *p_refcount += 1;
- return abfd;
+ stop = cb (objfile, cb_data);
+ if (stop)
+ return;
}
-
- p_refcount = xmalloc (sizeof (*p_refcount));
- *p_refcount = 1;
- bfd_usrdata (abfd) = p_refcount;
-
- return abfd;
}
-/* Unreference and possibly close ABFD. */
-void
-gdb_bfd_unref (struct bfd *abfd)
+/* See objfiles.h. */
+
+const char *
+objfile_name (const struct objfile *objfile)
{
- int *p_refcount;
- char *name;
+ if (objfile->obfd != NULL)
+ return bfd_get_filename (objfile->obfd);
- if (abfd == NULL)
- return;
+ return objfile->original_name;
+}
- p_refcount = bfd_usrdata (abfd);
+/* See objfiles.h. */
- /* Valid range for p_refcount: a pointer to int counter, which has a
- value of 1 (single owner) or 2 (shared). */
- gdb_assert (*p_refcount == 1 || *p_refcount == 2);
+const char *
+objfile_filename (const struct objfile *objfile)
+{
+ if (objfile->obfd != NULL)
+ return bfd_get_filename (objfile->obfd);
- *p_refcount -= 1;
- if (*p_refcount > 0)
- return;
+ return NULL;
+}
- xfree (p_refcount);
- bfd_usrdata (abfd) = NULL; /* Paranoia. */
+/* See objfiles.h. */
- name = bfd_get_filename (abfd);
- gdb_bfd_close_or_warn (abfd);
- xfree (name);
+const char *
+objfile_debug_name (const struct objfile *objfile)
+{
+ return lbasename (objfile->original_name);
}
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_objfiles;
+/* See objfiles.h. */
-void
-_initialize_objfiles (void)
+const char *
+objfile_flavour_name (struct objfile *objfile)
{
- objfiles_pspace_data
- = register_program_space_data_with_cleanup (objfiles_pspace_data_cleanup);
+ if (objfile->obfd != NULL)
+ return bfd_flavour_name (bfd_get_flavour (objfile->obfd));
+ return NULL;
}