X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fobjfiles.c;h=cacdabae3b7352e4cd2898608a87c221af49bf4f;hb=d903301282bd777b82a395fc21dda695dc67f84d;hp=6082155c5e502c551d0268d11867f0222265d9a8;hpb=2f6e5d7e9d6a416093702b75a536e8fed5c30d03;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 6082155c5e..cacdabae3b 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -1,7 +1,7 @@ /* GDB routines for manipulating objfiles. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc. + 2002, 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -52,6 +52,8 @@ #include "exec.h" #include "observer.h" #include "complaints.h" +#include "psymtab.h" +#include "solist.h" /* Prototypes for local functions */ @@ -196,10 +198,10 @@ allocate_objfile (bfd *abfd, int flags) { struct objfile *objfile; - objfile = (struct objfile *) xmalloc (sizeof (struct objfile)); - memset (objfile, 0, sizeof (struct objfile)); + objfile = (struct objfile *) xzalloc (sizeof (struct objfile)); objfile->psymbol_cache = bcache_xmalloc (); objfile->macro_cache = bcache_xmalloc (); + objfile->filename_cache = bcache_xmalloc (); /* We could use obstack_specify_allocation here instead, but gdb_obstack.h specifies the alloc/dealloc functions. */ obstack_init (&objfile->objfile_obstack); @@ -295,29 +297,34 @@ init_entry_point_info (struct objfile *objfile) /* 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); + { + /* 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 = INVALID_ENTRY_POINT; + objfile->ei.entry_point_p = 0; } } -/* Get current entry point address. */ +/* If there is a valid and known entry point, function fills *ENTRY_P with it + and returns non-zero; otherwise it returns zero. */ -CORE_ADDR -entry_point_address (void) +int +entry_point_address_query (CORE_ADDR *entry_p) { struct gdbarch *gdbarch; CORE_ADDR entry_point; - if (symfile_objfile == NULL) + if (symfile_objfile == NULL || !symfile_objfile->ei.entry_point_p) return 0; gdbarch = get_objfile_arch (symfile_objfile); @@ -333,7 +340,21 @@ entry_point_address (void) symbol table. */ entry_point = gdbarch_addr_bits_remove (gdbarch, entry_point); - return entry_point; + *entry_p = entry_point; + return 1; +} + +/* Get current entry point address. Call error if it is not known. */ + +CORE_ADDR +entry_point_address (void) +{ + CORE_ADDR retval; + + if (!entry_point_address_query (&retval)) + error (_("Entry point address is not known.")); + + return retval; } /* Create the terminating entry of OBJFILE's minimal symbol table. @@ -359,6 +380,45 @@ terminate_minimal_symbol_table (struct objfile *objfile) } } +/* 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) +{ + 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) + { + gdb_assert (res != NULL); + if (res->separate_debug_objfile_link) + return res->separate_debug_objfile_link; + } + 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 @@ -436,6 +496,41 @@ unlink_objfile (struct objfile *objfile) _("unlink_objfile: objfile already unlinked")); } +/* Add OBJFILE as a separate debug objfile of PARENT. */ + +void +add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent) +{ + gdb_assert (objfile && parent); + + /* Must not be already in a list. */ + gdb_assert (objfile->separate_debug_objfile_backlink == NULL); + gdb_assert (objfile->separate_debug_objfile_link == NULL); + + objfile->separate_debug_objfile_backlink = parent; + objfile->separate_debug_objfile_link = parent->separate_debug_objfile; + parent->separate_debug_objfile = objfile; + + /* 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); +} + +/* Free all separate debug objfile of OBJFILE, but don't free OBJFILE + itself. */ + +void +free_objfile_separate_debug (struct objfile *objfile) +{ + struct objfile *child; + + for (child = objfile->separate_debug_objfile; child;) + { + struct objfile *next_child = child->separate_debug_objfile_link; + free_objfile (child); + 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 @@ -456,16 +551,38 @@ unlink_objfile (struct objfile *objfile) void free_objfile (struct objfile *objfile) { - if (objfile->separate_debug_objfile) - { - free_objfile (objfile->separate_debug_objfile); - } - + /* Free all separate debug objfiles. */ + free_objfile_separate_debug (objfile); + if (objfile->separate_debug_objfile_backlink) { /* We freed the separate debug file, make sure the base objfile doesn't reference it. */ - objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL; + struct objfile *child; + + child = objfile->separate_debug_objfile_backlink->separate_debug_objfile; + + if (child == objfile) + { + /* OBJFILE is the first child. */ + objfile->separate_debug_objfile_backlink->separate_debug_objfile = + objfile->separate_debug_objfile_link; + } + else + { + /* Find OBJFILE in the list. */ + while (1) + { + if (child->separate_debug_objfile_link == objfile) + { + child->separate_debug_objfile_link = + objfile->separate_debug_objfile_link; + break; + } + child = child->separate_debug_objfile_link; + gdb_assert (child); + } + } } /* Remove any references to this objfile in the global value @@ -543,6 +660,7 @@ free_objfile (struct objfile *objfile) /* Free the obstacks for non-reusable objfiles */ bcache_xfree (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); @@ -571,6 +689,11 @@ void free_all_objfiles (void) { struct objfile *objfile, *temp; + struct so_list *so; + + /* Any objfile referencewould become stale. */ + for (so = master_so_list (); so; so = so->next) + gdb_assert (so->objfile == NULL); ALL_OBJFILES_SAFE (objfile, temp) { @@ -580,9 +703,11 @@ free_all_objfiles (void) } /* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS - entries in new_offsets. */ -void -objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) + entries in new_offsets. SEPARATE_DEBUG_OBJFILE is not touched here. + Return non-zero iff any change happened. */ + +static int +objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets) { struct obj_section *s; struct section_offsets *delta = @@ -600,7 +725,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) something_changed = 1; } if (!something_changed) - return; + return 0; } /* OK, get all the symtabs. */ @@ -660,38 +785,12 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) } } - { - struct partial_symtab *p; + if (objfile->psymtabs_addrmap) + addrmap_relocate (objfile->psymtabs_addrmap, + ANOFFSET (delta, SECT_OFF_TEXT (objfile))); - ALL_OBJFILE_PSYMTABS (objfile, p) - { - p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile)); - p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile)); - } - } - - { - struct partial_symbol **psym; - - for (psym = objfile->global_psymbols.list; - psym < objfile->global_psymbols.next; - psym++) - { - fixup_psymbol_section (*psym, objfile); - if (SYMBOL_SECTION (*psym) >= 0) - SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta, - SYMBOL_SECTION (*psym)); - } - for (psym = objfile->static_psymbols.list; - psym < objfile->static_psymbols.next; - psym++) - { - fixup_psymbol_section (*psym, objfile); - if (SYMBOL_SECTION (*psym) >= 0) - SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta, - SYMBOL_SECTION (*psym)); - } - } + if (objfile->sf) + objfile->sf->qf->relocate (objfile, new_offsets, delta); { struct minimal_symbol *msym; @@ -703,7 +802,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) to be out of order. */ msymbols_sort (objfile); - if (objfile->ei.entry_point != ~(CORE_ADDR) 0) + if (objfile->ei.entry_point_p) { /* Relocate ei.entry_point with its section offset, use SECT_OFF_TEXT only as a fallback. */ @@ -733,8 +832,61 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) obj_section_addr (s)); } + /* Data changed. */ + return 1; +} + +/* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS + entries in new_offsets. Process also OBJFILE's SEPARATE_DEBUG_OBJFILEs. + + The number and ordering of sections does differ between the two objfiles. + Only their names match. Also the file offsets will differ (objfile being + possibly prelinked but separate_debug_objfile is probably not prelinked) but + the in-memory absolute address as specified by NEW_OFFSETS must match both + files. */ + +void +objfile_relocate (struct objfile *objfile, 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)) + { + struct section_addr_info *objfile_addrs; + struct section_offsets *new_debug_offsets; + int new_debug_num_sections; + struct cleanup *my_cleanups; + + objfile_addrs = build_section_addr_info_from_objfile (objfile); + my_cleanups = make_cleanup (xfree, objfile_addrs); + + /* 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); + + gdb_assert (debug_objfile->num_sections + == bfd_count_sections (debug_objfile->obfd)); + new_debug_offsets = xmalloc (SIZEOF_N_SECTION_OFFSETS + (debug_objfile->num_sections)); + make_cleanup (xfree, new_debug_offsets); + relative_addr_info_to_section_offsets (new_debug_offsets, + debug_objfile->num_sections, + objfile_addrs); + + changed |= objfile_relocate1 (debug_objfile, new_debug_offsets); + + do_cleanups (my_cleanups); + } + /* Relocate breakpoints as necessary, after things are relocated. */ - breakpoint_re_set (); + if (changed) + breakpoint_re_set (); } /* Return non-zero if OBJFILE has partial symbols. */ @@ -742,7 +894,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) int objfile_has_partial_symbols (struct objfile *objfile) { - return objfile->psymtabs != NULL; + return objfile->sf ? objfile->sf->qf->has_symbols (objfile) : 0; } /* Return non-zero if OBJFILE has full symbols. */ @@ -754,25 +906,16 @@ objfile_has_full_symbols (struct objfile *objfile) } /* Return non-zero if OBJFILE has full or partial symbols, either directly - or throught its separate debug file. */ + or through a separate debug file. */ int objfile_has_symbols (struct objfile *objfile) { - struct objfile *separate_objfile; - - if (objfile_has_partial_symbols (objfile) - || objfile_has_full_symbols (objfile)) - return 1; - - separate_objfile = objfile->separate_debug_objfile; - if (separate_objfile == NULL) - return 0; - - if (objfile_has_partial_symbols (separate_objfile) - || objfile_has_full_symbols (separate_objfile)) - return 1; + struct objfile *o; + for (o = objfile; o; o = objfile_separate_debug_iterate (objfile, o)) + if (objfile_has_partial_symbols (o) || objfile_has_full_symbols (o)) + return 1; return 0; } @@ -1334,11 +1477,33 @@ 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); + + 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) { - int *p_refcount = bfd_usrdata (abfd); + int *p_refcount; + + if (abfd == NULL) + return NULL; + + p_refcount = bfd_usrdata (abfd); if (p_refcount != NULL) { @@ -1377,9 +1542,7 @@ gdb_bfd_unref (struct bfd *abfd) bfd_usrdata (abfd) = NULL; /* Paranoia. */ name = bfd_get_filename (abfd); - if (!bfd_close (abfd)) - warning (_("cannot close \"%s\": %s"), - name, bfd_errmsg (bfd_get_error ())); + gdb_bfd_close_or_warn (abfd); xfree (name); }