Index: gdb/objfiles.c |
diff --git a/gdb/objfiles.c b/gdb/objfiles.c |
index f5e5c75b86f4f64acdc91eb6c8d3c90ab27a150c..2960ff9b00fa4ba0d368a922d249989169538376 100644 |
--- a/gdb/objfiles.c |
+++ b/gdb/objfiles.c |
@@ -1,6 +1,6 @@ |
/* GDB routines for manipulating objfiles. |
- Copyright (C) 1992-2004, 2007-2012 Free Software Foundation, Inc. |
+ Copyright (C) 1992-2013 Free Software Foundation, Inc. |
Contributed by Cygnus Support, using pieces from other GDB modules. |
@@ -30,16 +30,15 @@ |
#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 <string.h> |
#include "hashtab.h" |
#include "breakpoint.h" |
@@ -53,22 +52,31 @@ |
#include "complaints.h" |
#include "psymtab.h" |
#include "solist.h" |
+#include "gdb_bfd.h" |
+#include "btrace.h" |
-/* Prototypes for local functions */ |
+/* Keep a registry of per-objfile data-pointers required by other GDB |
+ modules. */ |
-static void objfile_alloc_data (struct objfile *objfile); |
-static void objfile_free_data (struct objfile *objfile); |
+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; |
+ |
+ /* Nonzero if object files have been added since the section map |
+ was last updated. */ |
+ int new_objfiles_available; |
+ |
+ /* Nonzero if the section map MUST be updated before use. */ |
+ int section_map_dirty; |
+ |
+ /* Nonzero if section map updates should be inhibited if possible. */ |
+ int inhibit_updates; |
}; |
/* Per-program-space data key. */ |
@@ -77,14 +85,10 @@ static const struct program_space_data *objfiles_pspace_data; |
static void |
objfiles_pspace_data_cleanup (struct program_space *pspace, void *arg) |
{ |
- struct objfile_pspace_info *info; |
+ struct objfile_pspace_info *info = arg; |
- info = program_space_data (pspace, objfiles_pspace_data); |
- if (info != NULL) |
- { |
- xfree (info->sections); |
- xfree (info); |
- } |
+ xfree (info->sections); |
+ xfree (info); |
} |
/* Get the current svr4 data. If none is found yet, add it now. This |
@@ -105,56 +109,140 @@ get_objfile_pspace_data (struct program_space *pspace) |
return info; |
} |
+ |
+ |
+/* Per-BFD data key. */ |
+ |
+static const struct bfd_data *objfiles_bfd_data; |
+ |
+/* 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. */ |
+ |
+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 = bfd_data (abfd, objfiles_bfd_data); |
+ |
+ if (storage == NULL) |
+ { |
+ /* 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); |
+ |
+ /* 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. */ |
+ |
+static void |
+free_objfile_per_bfd_storage (struct objfile_per_bfd_storage *storage) |
+{ |
+ 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); |
+} |
+ |
+/* A wrapper for free_objfile_per_bfd_storage that can be passed as a |
+ cleanup function to the BFD registry. */ |
+ |
+static void |
+objfile_bfd_data_free (struct bfd *unused, void *d) |
+{ |
+ free_objfile_per_bfd_storage (d); |
+} |
+ |
+/* See objfiles.h. */ |
+ |
+void |
+set_objfile_per_bfd (struct objfile *objfile) |
+{ |
+ objfile->per_bfd = get_objfile_bfd_data (objfile, objfile->obfd); |
+} |
+ |
+ |
+ |
/* 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_get_section_flags (abfd, 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, 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 |
@@ -162,6 +250,11 @@ build_objfile_section_table (struct objfile *objfile) |
into the list of all known objfiles, and return a pointer to the |
new objfile struct. |
+ 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. */ |
@@ -176,14 +269,13 @@ build_objfile_section_table (struct objfile *objfile) |
things in a consistent state even if abfd is NULL. */ |
struct objfile * |
-allocate_objfile (bfd *abfd, int flags) |
+allocate_objfile (bfd *abfd, const char *name, int flags) |
{ |
struct objfile *objfile; |
+ 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); |
@@ -191,27 +283,40 @@ allocate_objfile (bfd *abfd, int flags) |
objfile_alloc_data (objfile); |
+ if (name == NULL) |
+ { |
+ gdb_assert (abfd == NULL); |
+ gdb_assert ((flags & OBJF_NOT_FILENAME) != 0); |
+ expanded_name = xstrdup ("<<anonymous objfile>>"); |
+ } |
+ else if ((flags & OBJF_NOT_FILENAME) != 0) |
+ expanded_name = xstrdup (name); |
+ else |
+ expanded_name = gdb_abspath (name); |
+ objfile->original_name = obstack_copy0 (&objfile->objfile_obstack, |
+ expanded_name, |
+ strlen (expanded_name)); |
+ xfree (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. */ |
+ |
/* 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); |
+ objfile->obfd = abfd; |
+ gdb_bfd_ref (abfd); |
if (abfd != 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); |
} |
- else |
- { |
- objfile->name = xstrdup ("<<anonymous 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 |
@@ -241,7 +346,7 @@ allocate_objfile (bfd *abfd, int flags) |
objfile->flags |= flags; |
/* Rebuild section map next time we need it. */ |
- get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1; |
+ get_objfile_pspace_data (objfile->pspace)->new_objfiles_available = 1; |
return objfile; |
} |
@@ -250,38 +355,7 @@ allocate_objfile (bfd *abfd, int flags) |
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) |
-{ |
- /* 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 |
@@ -290,26 +364,11 @@ init_entry_point_info (struct objfile *objfile) |
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) |
return 0; |
- gdbarch = get_objfile_arch (symfile_objfile); |
- |
- entry_point = symfile_objfile->ei.entry_point; |
+ *entry_p = 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); |
- |
- /* 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; |
} |
@@ -390,26 +449,6 @@ put_objfile_before (struct objfile *objfile, struct objfile *before_this) |
_("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)) |
- { |
- 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; |
- } |
- } |
-} |
- |
/* Unlink OBJFILE from the list of known objfiles, if it is found in the |
list. |
@@ -452,6 +491,9 @@ add_separate_debug_objfile (struct objfile *objfile, struct 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; |
@@ -478,25 +520,14 @@ free_objfile_separate_debug (struct objfile *objfile) |
} |
} |
-/* 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 |
- |
- 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. */ |
+/* Destroy an objfile and all the symtabs and psymtabs under it. */ |
void |
free_objfile (struct objfile *objfile) |
{ |
+ /* First notify observers that this objfile is about to be freed. */ |
+ observer_notify_free_objfile (objfile); |
+ |
/* Free all separate debug objfiles. */ |
free_objfile_separate_debug (objfile); |
@@ -539,6 +570,9 @@ free_objfile (struct objfile *objfile) |
the symbol file data. */ |
forget_cached_source_info_for_objfile (objfile); |
+ breakpoint_free_objfile (objfile); |
+ btrace_free_objfile (objfile); |
+ |
/* First do any symbol file specific actions required when we are |
finished with a particular symbol file. Note that if the objfile |
is using reusable symbol information (via mmalloc) then each of |
@@ -555,7 +589,10 @@ free_objfile (struct objfile *objfile) |
still may reference objfile->obfd. */ |
objfile_free_data (objfile); |
- gdb_bfd_unref (objfile->obfd); |
+ if (objfile->obfd) |
+ gdb_bfd_unref (objfile->obfd); |
+ else |
+ free_objfile_per_bfd_storage (objfile->per_bfd); |
/* Remove it from the chain of all objfiles. */ |
@@ -564,9 +601,6 @@ free_objfile (struct objfile *objfile) |
if (objfile == symfile_objfile) |
symfile_objfile = NULL; |
- if (objfile == rt_common_objfile) |
- rt_common_objfile = NULL; |
- |
/* Before the symbol table code was redone to make it easier to |
selectively load and remove information particular to a specific |
linkage unit, gdb used to do these things whenever the monolithic |
@@ -594,24 +628,18 @@ free_objfile (struct objfile *objfile) |
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); |
/* 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; |
+ /* The last thing we do is free the objfile struct itself. */ |
xfree (objfile); |
} |
@@ -673,7 +701,7 @@ relocate_one_symbol (struct symbol *sym, struct objfile *objfile, |
static int |
objfile_relocate1 (struct objfile *objfile, |
- struct section_offsets *new_offsets) |
+ const struct section_offsets *new_offsets) |
{ |
struct obj_section *s; |
struct section_offsets *delta = |
@@ -773,7 +801,11 @@ objfile_relocate1 (struct objfile *objfile, |
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); |
+ { |
+ 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)); |
} |
@@ -786,12 +818,12 @@ objfile_relocate1 (struct objfile *objfile, |
} |
/* 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. */ |
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)); |
@@ -816,7 +848,8 @@ objfile_relocate1 (struct objfile *objfile, |
files. */ |
void |
-objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) |
+objfile_relocate (struct objfile *objfile, |
+ const struct section_offsets *new_offsets) |
{ |
struct objfile *debug_objfile; |
int changed = 0; |
@@ -840,7 +873,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) |
addr_info_make_relative (objfile_addrs, debug_objfile->obfd); |
gdb_assert (debug_objfile->num_sections |
- == bfd_count_sections (debug_objfile->obfd)); |
+ == 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); |
@@ -857,6 +890,45 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) |
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) |
+{ |
+ struct section_offsets *new_offsets = |
+ ((struct section_offsets *) |
+ alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections))); |
+ int i; |
+ |
+ for (i = 0; i < objfile->num_sections; ++i) |
+ new_offsets->offsets[i] = 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) |
+{ |
+ 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)) |
+ changed |= objfile_rebase1 (debug_objfile, slide); |
+ |
+ /* Relocate breakpoints as necessary, after things are relocated. */ |
+ if (changed) |
+ breakpoint_re_set (); |
+} |
/* Return non-zero if OBJFILE has partial symbols. */ |
@@ -1171,9 +1243,6 @@ filter_overlapping_sections (struct obj_section **map, int map_size) |
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; |
@@ -1186,10 +1255,10 @@ filter_overlapping_sections (struct obj_section **map, int map_size) |
" (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 (abfd1, bfds1), objfile_name (objf1), |
paddress (gdbarch, sect1_addr), |
paddress (gdbarch, sect1_endaddr), |
- bfd_section_name (abfd2, bfds2), objf2->name, |
+ bfd_section_name (abfd2, bfds2), objfile_name (objf2), |
paddress (gdbarch, sect2_addr), |
paddress (gdbarch, sect2_endaddr)); |
} |
@@ -1214,11 +1283,14 @@ static void |
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); |
@@ -1288,7 +1360,9 @@ find_pc_section (CORE_ADDR pc) |
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, |
@@ -1296,7 +1370,8 @@ find_pc_section (CORE_ADDR pc) |
/* 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 |
@@ -1318,12 +1393,10 @@ find_pc_section (CORE_ADDR pc) |
} |
-/* 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, char *name) |
{ |
struct obj_section *s; |
int retval = 0; |
@@ -1332,197 +1405,66 @@ in_plt_section (CORE_ADDR pc, char *name) |
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); |
} |
-/* 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; |
-} |
- |
-const struct objfile_data * |
-register_objfile_data (void) |
-{ |
- return register_objfile_data_with_cleanup (NULL, NULL); |
-} |
+/* Set section_map_dirty so section map will be rebuilt next time it |
+ is used. Called by reread_symbols. */ |
-static void |
-objfile_alloc_data (struct objfile *objfile) |
+void |
+objfiles_changed (void) |
{ |
- gdb_assert (objfile->data == NULL); |
- objfile->num_data = objfile_data_registry.num_registrations; |
- objfile->data = XCALLOC (objfile->num_data, void *); |
+ /* Rebuild section map next time we need it. */ |
+ get_objfile_pspace_data (current_program_space)->section_map_dirty = 1; |
} |
-static void |
-objfile_free_data (struct objfile *objfile) |
-{ |
- gdb_assert (objfile->data != NULL); |
- clear_objfile_data (objfile); |
- xfree (objfile->data); |
- objfile->data = NULL; |
-} |
+/* See comments in objfiles.h. */ |
void |
-clear_objfile_data (struct objfile *objfile) |
+inhibit_section_map_updates (struct program_space *pspace) |
{ |
- struct objfile_data_registration *registration; |
- int i; |
- |
- 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 *)); |
+ get_objfile_pspace_data (pspace)->inhibit_updates = 1; |
} |
-void |
-set_objfile_data (struct objfile *objfile, const struct objfile_data *data, |
- void *value) |
-{ |
- gdb_assert (data->index < objfile->num_data); |
- objfile->data[data->index] = value; |
-} |
+/* See comments in objfiles.h. */ |
-void * |
-objfile_data (struct objfile *objfile, const struct objfile_data *data) |
+void |
+resume_section_map_updates (struct program_space *pspace) |
{ |
- gdb_assert (data->index < objfile->num_data); |
- return objfile->data[data->index]; |
+ get_objfile_pspace_data (pspace)->inhibit_updates = 0; |
} |
-/* Set objfiles_changed_p so section map will be rebuilt next time it |
- is used. Called by reread_symbols. */ |
+/* See comments in objfiles.h. */ |
void |
-objfiles_changed (void) |
+resume_section_map_updates_cleanup (void *arg) |
{ |
- /* Rebuild section map next time we need it. */ |
- get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1; |
+ resume_section_map_updates (arg); |
} |
-/* Close ABFD, and warn if that fails. */ |
+/* Return 1 if ADDR maps into one of the sections of OBJFILE and 0 |
+ otherwise. */ |
int |
-gdb_bfd_close_or_warn (struct bfd *abfd) |
-{ |
- 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 ())); |
- |
- return ret; |
-} |
- |
-/* Add reference to ABFD. Returns ABFD. */ |
-struct bfd * |
-gdb_bfd_ref (struct bfd *abfd) |
+is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile) |
{ |
- int *p_refcount; |
- |
- if (abfd == NULL) |
- return NULL; |
+ struct obj_section *osect; |
- p_refcount = bfd_usrdata (abfd); |
+ if (objfile == NULL) |
+ return 0; |
- if (p_refcount != NULL) |
+ ALL_OBJFILE_OSECTIONS (objfile, osect) |
{ |
- *p_refcount += 1; |
- return abfd; |
- } |
- |
- 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) |
-{ |
- int *p_refcount; |
- char *name; |
- |
- if (abfd == NULL) |
- return; |
- |
- p_refcount = bfd_usrdata (abfd); |
- |
- /* 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); |
- |
- *p_refcount -= 1; |
- if (*p_refcount > 0) |
- return; |
- |
- xfree (p_refcount); |
- bfd_usrdata (abfd) = NULL; /* Paranoia. */ |
+ if (section_is_overlay (osect) && !section_is_mapped (osect)) |
+ continue; |
- name = bfd_get_filename (abfd); |
- gdb_bfd_close_or_warn (abfd); |
- xfree (name); |
+ if (obj_section_addr (osect) <= addr |
+ && addr < obj_section_endaddr (osect)) |
+ return 1; |
+ } |
+ return 0; |
} |
/* The default implementation for the "iterate_over_objfiles_in_search_order" |
@@ -1550,6 +1492,17 @@ default_iterate_over_objfiles_in_search_order |
} |
} |
+/* Return canonical name for OBJFILE. */ |
+ |
+const char * |
+objfile_name (const struct objfile *objfile) |
+{ |
+ if (objfile->obfd != NULL) |
+ return bfd_get_filename (objfile->obfd); |
+ |
+ return objfile->original_name; |
+} |
+ |
/* Provide a prototype to silence -Wmissing-prototypes. */ |
extern initialize_file_ftype _initialize_objfiles; |
@@ -1557,5 +1510,9 @@ void |
_initialize_objfiles (void) |
{ |
objfiles_pspace_data |
- = register_program_space_data_with_cleanup (objfiles_pspace_data_cleanup); |
+ = register_program_space_data_with_cleanup (NULL, |
+ objfiles_pspace_data_cleanup); |
+ |
+ objfiles_bfd_data = register_bfd_data_with_cleanup (NULL, |
+ objfile_bfd_data_free); |
} |