X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fobjfiles.c;h=31265c1653d944e32c9a618faf7e97b22e9a4056;hb=d0801dd8f22a3e739c6a7d126d45829df981794d;hp=f669e30d2f9a752341d07636e63c97560fe3c5bc;hpb=0e9f083f4cb94a9dc861f38ba151aac06efce2b8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/objfiles.c b/gdb/objfiles.c index f669e30d2f..31265c1653 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -1,6 +1,6 @@ /* GDB routines for manipulating objfiles. - Copyright (C) 1992-2013 Free Software Foundation, Inc. + Copyright (C) 1992-2019 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -33,12 +33,10 @@ #include "expression.h" #include "parser-defs.h" -#include "gdb_assert.h" #include -#include "gdb_stat.h" +#include #include #include "gdb_obstack.h" -#include #include "hashtab.h" #include "breakpoint.h" @@ -48,12 +46,16 @@ #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" + +#include +#include /* Keep a registry of per-objfile data-pointers required by other GDB modules. */ @@ -65,30 +67,30 @@ DEFINE_REGISTRY (objfile, REGISTRY_ACCESS_FIELD) struct objfile_pspace_info { - 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; + int new_objfiles_available = 0; /* Nonzero if the section map MUST be updated before use. */ - int section_map_dirty; + int section_map_dirty = 0; /* Nonzero if section map updates should be inhibited if possible. */ - int inhibit_updates; + int inhibit_updates = 0; }; /* Per-program-space data key. */ -static const struct program_space_data *objfiles_pspace_data; +static const struct program_space_key + 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 = arg; - - xfree (info->sections); - xfree (info); + xfree (sections); } /* Get the current svr4 data. If none is found yet, add it now. This @@ -99,12 +101,9 @@ get_objfile_pspace_data (struct program_space *pspace) { struct objfile_pspace_info *info; - info = program_space_data (pspace, objfiles_pspace_data); + info = objfiles_pspace_data.get (pspace); if (info == NULL) - { - info = XZALLOC (struct objfile_pspace_info); - set_program_space_data (pspace, objfiles_pspace_data, info); - } + info = objfiles_pspace_data.emplace (pspace); return info; } @@ -113,15 +112,17 @@ get_objfile_pspace_data (struct program_space *pspace) /* Per-BFD data key. */ -static const struct bfd_data *objfiles_bfd_data; +static const struct bfd_key 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. If ABFD is not - NULL, the object is allocated on the BFD; otherwise it is allocated - on OBJFILE's obstack. 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. */ + 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) @@ -129,61 +130,129 @@ get_objfile_bfd_data (struct objfile *objfile, struct bfd *abfd) struct objfile_per_bfd_storage *storage = NULL; if (abfd != NULL) - storage = bfd_data (abfd, objfiles_bfd_data); + storage = objfiles_bfd_data.get (abfd); if (storage == NULL) { + 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)) - { - storage = bfd_zalloc (abfd, sizeof (struct objfile_per_bfd_storage)); - set_bfd_data (abfd, objfiles_bfd_data, storage); - } - else - storage = OBSTACK_ZALLOC (&objfile->objfile_obstack, - struct objfile_per_bfd_storage); + objfiles_bfd_data.set (abfd, storage); /* Look up the gdbarch associated with the BFD. */ if (abfd != NULL) storage->gdbarch = gdbarch_from_bfd (abfd); - - obstack_init (&storage->storage_obstack); - storage->filename_cache = bcache_xmalloc (NULL, NULL); - storage->macro_cache = bcache_xmalloc (NULL, NULL); } return storage; } -/* Free STORAGE. */ +/* See objfiles.h. */ -static void -free_objfile_per_bfd_storage (struct objfile_per_bfd_storage *storage) +void +set_objfile_per_bfd (struct objfile *objfile) { - bcache_xfree (storage->filename_cache); - bcache_xfree (storage->macro_cache); - if (storage->demangled_names_hash) - htab_delete (storage->demangled_names_hash); - obstack_free (&storage->storage_obstack, 0); + objfile->per_bfd = get_objfile_bfd_data (objfile, objfile->obfd); } -/* A wrapper for free_objfile_per_bfd_storage that can be passed as a - cleanup function to the BFD registry. */ +/* Set the objfile's per-BFD notion of the "main" name and + language. */ -static void -objfile_bfd_data_free (struct bfd *unused, void *d) +void +set_objfile_main_name (struct objfile *objfile, + const char *name, enum language lang) { - free_objfile_per_bfd_storage (d); + 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; } -/* See objfiles.h. */ +/* 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 -set_objfile_per_bfd (struct objfile *objfile) +objfile_register_static_link (struct objfile *objfile, + const struct block *block, + const struct dynamic_prop *static_link) { - objfile->per_bfd = get_objfile_bfd_data (objfile, objfile->obfd); + 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; } @@ -203,7 +272,7 @@ add_to_objfile_sections_full (struct bfd *abfd, struct bfd_section *asect, { flagword aflag; - aflag = bfd_get_section_flags (abfd, asect); + aflag = bfd_section_flags (asect); if (!(aflag & SEC_ALLOC)) return; } @@ -218,7 +287,7 @@ static void add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect, void *objfilep) { - add_to_objfile_sections_full (abfd, asect, objfilep, 0); + add_to_objfile_sections_full (abfd, asect, (struct objfile *) objfilep, 0); } /* Builds a section table for OBJFILE. @@ -245,10 +314,9 @@ build_objfile_section_table (struct objfile *objfile) 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 @@ -259,90 +327,57 @@ build_objfile_section_table (struct objfile *objfile) 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, const char *name, 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 (); /* 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); + gdb::unique_xmalloc_ptr name_holder; if (name == NULL) { gdb_assert (abfd == NULL); gdb_assert ((flags & OBJF_NOT_FILENAME) != 0); - name = "<>"; + expanded_name = "<>"; + } + else if ((flags & OBJF_NOT_FILENAME) != 0 + || is_target_filename (name)) + expanded_name = name; + else + { + name_holder = gdb_abspath (name); + expanded_name = name_holder.get (); } - objfile->original_name = obstack_copy0 (&objfile->objfile_obstack, name, - strlen (name)); + original_name = obstack_strdup (&objfile_obstack, expanded_name); /* 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 = abfd; gdb_bfd_ref (abfd); if (abfd != NULL) { - objfile->mtime = bfd_get_mtime (abfd); + mtime = bfd_get_mtime (abfd); /* Build section table. */ - build_objfile_section_table (objfile); - } - - objfile->per_bfd = get_objfile_bfd_data (objfile, abfd); - 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. */ - - objfile->next = NULL; - if (object_files == NULL) - object_files = objfile; - else - { - struct objfile *last_one; - - for (last_one = object_files; - last_one->next; - last_one = last_one->next); - last_one->next = objfile; + 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)->new_objfiles_available = 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) +get_objfile_arch (const struct objfile *objfile) { return objfile->per_bfd->gdbarch; } @@ -353,10 +388,12 @@ get_objfile_arch (struct objfile *objfile) int entry_point_address_query (CORE_ADDR *entry_p) { - if (symfile_objfile == NULL || !symfile_objfile->ei.entry_point_p) + if (symfile_objfile == NULL || !symfile_objfile->per_bfd->ei.entry_point_p) return 0; - *entry_p = symfile_objfile->ei.entry_point; + *entry_p = (symfile_objfile->per_bfd->ei.entry_point + + ANOFFSET (symfile_objfile->section_offsets, + symfile_objfile->per_bfd->ei.the_bfd_section_index)); return 1; } @@ -374,125 +411,55 @@ entry_point_address (void) 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); @@ -507,10 +474,33 @@ add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent) 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); + + current_program_space->add_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); + delete this; } /* Free all separate debug objfile of OBJFILE, but don't free OBJFILE @@ -524,59 +514,44 @@ free_objfile_separate_debug (struct objfile *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. +/* Destroy an objfile and all the symtabs and psymtabs under it. */ - 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 - - 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. */ - observer_notify_free_objfile (objfile); + 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; @@ -584,17 +559,17 @@ free_objfile (struct objfile *objfile) } } } - + /* 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 (objfile); - btrace_free_objfile (objfile); + 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 @@ -603,26 +578,17 @@ free_objfile (struct objfile *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); + still may reference obfd. */ + objfile_free_data (this); - if (objfile->obfd) - gdb_bfd_unref (objfile->obfd); + if (obfd) + gdb_bfd_unref (obfd); else - free_objfile_per_bfd_storage (objfile->per_bfd); - - /* Remove it from the chain of all objfiles. */ - - unlink_objfile (objfile); - - if (objfile == symfile_objfile) - symfile_objfile = NULL; + delete per_bfd; /* Before the symbol table code was redone to make it easier to selectively load and remove information particular to a specific @@ -635,47 +601,21 @@ free_objfile (struct objfile *objfile) 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 (); } - 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); - 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)->section_map_dirty = 1; - - /* The last thing we do is free the objfile struct itself. */ - xfree (objfile); -} - -static void -do_free_objfile_cleanup (void *obj) -{ - free_objfile (obj); -} - -struct cleanup * -make_cleanup_free_objfile (struct objfile *obj) -{ - return make_cleanup (do_free_objfile_cleanup, obj); + get_objfile_pspace_data (pspace)->section_map_dirty = 1; } /* Free all the object files at once and clean up their users. */ @@ -683,17 +623,14 @@ make_cleanup_free_objfile (struct objfile *obj) void free_all_objfiles (void) { - struct objfile *objfile, *temp; struct so_list *so; - /* Any objfile referencewould become stale. */ + /* Any objfile reference would become stale. */ for (so = master_so_list (); so; so = so->next) gdb_assert (so->objfile == NULL); - ALL_OBJFILES_SAFE (objfile, temp) - { - free_objfile (objfile); - } + for (objfile *objfile : current_program_space->objfiles_safe ()) + objfile->unlink (); clear_symtab_users (0); } @@ -714,7 +651,9 @@ relocate_one_symbol (struct symbol *sym, struct objfile *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) + + ANOFFSET (delta, SYMBOL_SECTION (sym))); } } @@ -726,15 +665,13 @@ static int objfile_relocate1 (struct objfile *objfile, const struct section_offsets *new_offsets) { - struct obj_section *s; struct section_offsets *delta = ((struct section_offsets *) alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections))); - int i; int something_changed = 0; - for (i = 0; i < objfile->num_sections; ++i) + for (int i = 0; i < objfile->num_sections; ++i) { delta->offsets[i] = ANOFFSET (new_offsets, i) - ANOFFSET (objfile->section_offsets, i); @@ -746,51 +683,66 @@ objfile_relocate1 (struct objfile *objfile, /* 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 += ANOFFSET (delta, + COMPUNIT_BLOCK_LINE_SECTION + (cust)); + } + } + } - /* We only want to iterate over the local symbols, not any - symbols in included symtabs. */ - ALL_DICT_SYMBOLS (BLOCK_DICT (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), + ANOFFSET (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) += ANOFFSET (delta, block_line_section); + BLOCK_END (b) += ANOFFSET (delta, block_line_section); + + if (BLOCK_RANGES (b) != nullptr) + for (int j = 0; j < BLOCK_NRANGES (b); j++) + { + BLOCK_RANGE_START (b, j) + += ANOFFSET (delta, block_line_section); + BLOCK_RANGE_END (b, j) += ANOFFSET (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; @@ -799,40 +751,6 @@ objfile_relocate1 (struct objfile *objfile, 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) - { - int idx = gdb_bfd_section_index (objfile->obfd, s->the_bfd_section); - - objfile->ei.entry_point += ANOFFSET (delta, idx); - } - else - objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT (objfile)); - } - { int i; @@ -844,6 +762,7 @@ objfile_relocate1 (struct objfile *objfile, 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 - objfile->sections; @@ -852,11 +771,6 @@ objfile_relocate1 (struct objfile *objfile, obj_section_addr (s)); } - /* Relocating probes. */ - if (objfile->sf && objfile->sf->sym_probe_fns) - objfile->sf->sym_probe_fns->sym_relocate_probe (objfile, - new_offsets, delta); - /* Data changed. */ return 1; } @@ -874,39 +788,32 @@ void objfile_relocate (struct objfile *objfile, const struct 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 == gdb_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, + std::vector + new_debug_offsets (SIZEOF_N_SECTION_OFFSETS (debug_objfile->num_sections)); + relative_addr_info_to_section_offsets (new_debug_offsets.data (), debug_objfile->num_sections, objfile_addrs); - changed |= objfile_relocate1 (debug_objfile, new_debug_offsets); - - do_cleanups (my_cleanups); + changed |= objfile_relocate1 (debug_objfile, new_debug_offsets.data ()); } /* Relocate breakpoints as necessary, after things are relocated. */ @@ -938,14 +845,9 @@ objfile_rebase1 (struct objfile *objfile, CORE_ADDR slide) void objfile_rebase (struct objfile *objfile, CORE_ADDR slide) { - struct objfile *debug_objfile; int changed = 0; - changed |= objfile_rebase1 (objfile, slide); - - 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 ()) changed |= objfile_rebase1 (debug_objfile, slide); /* Relocate breakpoints as necessary, after things are relocated. */ @@ -977,7 +879,7 @@ objfile_has_partial_symbols (struct objfile *objfile) 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 @@ -986,9 +888,7 @@ objfile_has_full_symbols (struct objfile *objfile) 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; @@ -1002,13 +902,11 @@ objfile_has_symbols (struct objfile *objfile) 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; } @@ -1019,13 +917,11 @@ have_partial_symbols (void) 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; } @@ -1037,17 +933,14 @@ have_full_symbols (void) 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 (); + } } @@ -1058,32 +951,28 @@ objfile_purge_solibs (void) 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 @@ -1100,29 +989,33 @@ qsort_cmp (const void *a, const void *b) /* 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"); @@ -1131,13 +1024,11 @@ qsort_cmp (const void *a, const void *b) { /* 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"); @@ -1146,7 +1037,7 @@ qsort_cmp (const void *a, const void *b) /* 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 @@ -1176,15 +1067,15 @@ static int 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; @@ -1273,15 +1164,14 @@ filter_overlapping_sections (struct obj_section **map, int map_size) 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), objfile_name (objf1), + bfd_section_name (bfds1), objfile_name (objf1), paddress (gdbarch, sect1_addr), paddress (gdbarch, sect1_endaddr), - bfd_section_name (abfd2, bfds2), objfile_name (objf2), + bfd_section_name (bfds2), objfile_name (objf2), paddress (gdbarch, sect2_addr), paddress (gdbarch, sect2_endaddr)); } @@ -1309,7 +1199,6 @@ update_section_map (struct program_space *pspace, struct objfile_pspace_info *pspace_info; int alloc_size, map_size, i; struct obj_section *s, **map; - struct objfile *objfile; pspace_info = get_objfile_pspace_data (pspace); gdb_assert (pspace_info->section_map_dirty != 0 @@ -1319,7 +1208,7 @@ update_section_map (struct program_space *pspace, 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; @@ -1332,21 +1221,21 @@ update_section_map (struct program_space *pspace, 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); @@ -1419,7 +1308,7 @@ find_pc_section (CORE_ADDR pc) /* Return non-zero if PC is in a section called NAME. */ int -pc_in_section (CORE_ADDR pc, char *name) +pc_in_section (CORE_ADDR pc, const char *name) { struct obj_section *s; int retval = 0; @@ -1445,26 +1334,11 @@ objfiles_changed (void) /* See comments in objfiles.h. */ -void +scoped_restore_tmpl inhibit_section_map_updates (struct program_space *pspace) { - get_objfile_pspace_data (pspace)->inhibit_updates = 1; -} - -/* See comments in objfiles.h. */ - -void -resume_section_map_updates (struct program_space *pspace) -{ - get_objfile_pspace_data (pspace)->inhibit_updates = 0; -} - -/* See comments in objfiles.h. */ - -void -resume_section_map_updates_cleanup (void *arg) -{ - resume_section_map_updates (arg); + return scoped_restore_tmpl + (&get_objfile_pspace_data (pspace)->inhibit_updates, 1); } /* Return 1 if ADDR maps into one of the sections of OBJFILE and 0 @@ -1490,12 +1364,26 @@ is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile) return 0; } +int +shared_objfile_contains_address_p (struct program_space *pspace, + CORE_ADDR address) +{ + for (objfile *objfile : pspace->objfiles ()) + { + if ((objfile->flags & OBJF_SHARED) != 0 + && is_addr_in_objfile (address, objfile)) + return 1; + } + + return 0; +} + /* The default implementation for the "iterate_over_objfiles_in_search_order" - gdbarch method. It is equivalent to use the ALL_OBJFILES macro, + gdbarch method. It is equivalent to use the objfiles iterable, searching the objfiles in the order they are stored internally, ignoring CURRENT_OBJFILE. - On most platorms, it should be close enough to doing the best + On most platforms, it should be close enough to doing the best we can without some knowledge specific to the architecture. */ void @@ -1505,9 +1393,8 @@ default_iterate_over_objfiles_in_search_order void *cb_data, struct objfile *current_objfile) { int stop = 0; - struct objfile *objfile; - ALL_OBJFILES (objfile) + for (objfile *objfile : current_program_space->objfiles ()) { stop = cb (objfile, cb_data); if (stop) @@ -1515,7 +1402,7 @@ default_iterate_over_objfiles_in_search_order } } -/* Return canonical name for OBJFILE. */ +/* See objfiles.h. */ const char * objfile_name (const struct objfile *objfile) @@ -1526,16 +1413,31 @@ objfile_name (const struct objfile *objfile) return 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_filename (const struct objfile *objfile) { - objfiles_pspace_data - = register_program_space_data_with_cleanup (NULL, - objfiles_pspace_data_cleanup); + if (objfile->obfd != NULL) + return bfd_get_filename (objfile->obfd); - objfiles_bfd_data = register_bfd_data_with_cleanup (NULL, - objfile_bfd_data_free); + return NULL; +} + +/* See objfiles.h. */ + +const char * +objfile_debug_name (const struct objfile *objfile) +{ + return lbasename (objfile->original_name); +} + +/* See objfiles.h. */ + +const char * +objfile_flavour_name (struct objfile *objfile) +{ + if (objfile->obfd != NULL) + return bfd_flavour_name (bfd_get_flavour (objfile->obfd)); + return NULL; }