X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fobjfiles.c;h=2e13421301386dd05096f14027b25b2b539585b1;hb=d445b2f6a4492b74f6fa5cb21d8b95ccf4f8edd9;hp=1cb1698e7a349370d997630d294ee9af157d32a9;hpb=50f8ea949d73101ef1dc3d68dfbb7e5e35d4e82a;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 1cb1698e7a..2e13421301 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -1,8 +1,6 @@ /* GDB routines for manipulating objfiles. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992-2013 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -32,7 +30,6 @@ #include "gdb-stabs.h" #include "target.h" #include "bcache.h" -#include "mdebugread.h" #include "expression.h" #include "parser-defs.h" @@ -55,11 +52,13 @@ #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. */ @@ -107,67 +106,131 @@ get_objfile_pspace_data (struct program_space *pspace) return info; } -/* Records whether any objfiles appeared or disappeared since we last updated - address to obj section map. */ + + +/* 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 (abfd != NULL) + { + 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); + + 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); + 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); +} -/* Locate all mappable sections of a BFD file. - objfile_p_char is a char * to get it through - bfd_map_over_sections; we cast it back to its proper type. */ + /* 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 *objfile_p_char) + void *objfilep) { - struct objfile *objfile = (struct objfile *) objfile_p_char; - struct obj_section section; - flagword aflag; - - aflag = bfd_get_section_flags (abfd, asect); - - if (!(aflag & SEC_ALLOC)) - return; - - if (0 == bfd_section_size (abfd, asect)) - 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. - Returns 0 if OK, 1 on error (in which case bfd_error contains the - error). - - Note that while we are building the table, which goes into the - psymbol 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 psymbol 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. */ -int +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; - return (0); + + /* 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 @@ -195,8 +258,6 @@ allocate_objfile (bfd *abfd, int flags) 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); @@ -208,28 +269,25 @@ allocate_objfile (bfd *abfd, int flags) 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->name = bfd_get_filename (abfd); objfile->mtime = bfd_get_mtime (abfd); /* Build section table. */ - - if (build_objfile_section_table (objfile)) - { - error (_("Can't find the file sections in `%s': %s"), - objfile->name, bfd_errmsg (bfd_get_error ())); - } + build_objfile_section_table (objfile); } else { - objfile->name = xstrdup ("<>"); + objfile->name = "<>"; } + 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 @@ -271,63 +329,17 @@ 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; - } -} - /* If there is a valid and known entry point, function fills *ENTRY_P with it and returns non-zero; otherwise it returns zero. */ 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; - - /* 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); + *entry_p = symfile_objfile->ei.entry_point; - /* 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; } @@ -344,29 +356,6 @@ entry_point_address (void) return retval; } -/* Create the terminating entry of OBJFILE's minimal symbol table. - If OBJFILE->msymbols is zero, allocate a single entry from - OBJFILE->objfile_obstack; otherwise, just initialize - OBJFILE->msymbols[OBJFILE->minimal_symbol_count]. */ -void -terminate_minimal_symbol_table (struct objfile *objfile) -{ - if (! objfile->msymbols) - objfile->msymbols = ((struct minimal_symbol *) - obstack_alloc (&objfile->objfile_obstack, - sizeof (objfile->msymbols[0]))); - - { - struct minimal_symbol *m - = &objfile->msymbols[objfile->minimal_symbol_count]; - - memset (m, 0, sizeof (*m)); - /* Don't rely on these enumeration values being 0's. */ - MSYMBOL_TYPE (m) = mst_unknown; - SYMBOL_SET_LANGUAGE (m, language_unknown); - } -} - /* Iterator on PARENT and every separate debug objfile of PARENT. The usage pattern is: for (objfile = parent; @@ -493,6 +482,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; @@ -580,6 +572,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 @@ -596,7 +591,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. */ @@ -637,15 +635,12 @@ free_objfile (struct objfile *objfile) /* 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); @@ -771,7 +766,9 @@ objfile_relocate1 (struct objfile *objfile, BLOCK_START (b) += ANOFFSET (delta, s->block_line_section); BLOCK_END (b) += ANOFFSET (delta, s->block_line_section); - ALL_BLOCK_SYMBOLS (b, iter, sym) + /* 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); } @@ -812,7 +809,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)); } @@ -830,12 +831,17 @@ objfile_relocate1 (struct objfile *objfile, /* 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)); } + /* 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,7 +880,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); @@ -891,6 +897,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. */ @@ -1205,9 +1250,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; @@ -1371,115 +1413,6 @@ in_plt_section (CORE_ADDR pc, char *name) } -/* 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); -} - -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 *); -} - -static void -objfile_free_data (struct objfile *objfile) -{ - gdb_assert (objfile->data != NULL); - clear_objfile_data (objfile); - xfree (objfile->data); - objfile->data = NULL; -} - -void -clear_objfile_data (struct objfile *objfile) -{ - 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 *)); -} - -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; -} - -void * -objfile_data (struct objfile *objfile, const struct objfile_data *data) -{ - gdb_assert (data->index < objfile->num_data); - return objfile->data[data->index]; -} - /* Set objfiles_changed_p so section map will be rebuilt next time it is used. Called by reread_symbols. */ @@ -1490,73 +1423,29 @@ objfiles_changed (void) get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1; } -/* Close ABFD, and warn if that fails. */ - -int -gdb_bfd_close_or_warn (struct bfd *abfd) -{ - int ret; - char *name = bfd_get_filename (abfd); - - ret = bfd_close (abfd); +/* The default implementation for the "iterate_over_objfiles_in_search_order" + gdbarch method. It is equivalent to use the ALL_OBJFILES macro, + searching the objfiles in the order they are stored internally, + ignoring CURRENT_OBJFILE. - if (!ret) - warning (_("cannot close \"%s\": %s"), - name, bfd_errmsg (bfd_get_error ())); + On most platorms, it should be close enough to doing the best + we can without some knowledge specific to the architecture. */ - return ret; -} - -/* Add reference to ABFD. Returns ABFD. */ -struct bfd * -gdb_bfd_ref (struct bfd *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 *p_refcount; - - if (abfd == NULL) - return NULL; - - p_refcount = bfd_usrdata (abfd); + int stop = 0; + struct objfile *objfile; - if (p_refcount != NULL) + ALL_OBJFILES (objfile) { - *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) -{ - 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. */ - - name = bfd_get_filename (abfd); - gdb_bfd_close_or_warn (abfd); - xfree (name); } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -1566,5 +1455,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); }