X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fobjfiles.c;h=d1e441b41891a7ead66aca4ac5d3c22f7136f29b;hb=b5cfddf53bc50bebe17c82cb8352b6fa08b27cdd;hp=03a49a935e9bcc9c2f251e348f61c33330e26a3b;hpb=65a97ab329d81a01b410d7b49ec41fd1b7652439;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 03a49a935e..d1e441b418 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. @@ -194,24 +194,16 @@ build_objfile_section_table (struct objfile *objfile) struct objfile * allocate_objfile (bfd *abfd, int flags) { - struct objfile *objfile = NULL; - struct objfile *last_one = NULL; - - /* If we don't support mapped symbol files, didn't ask for the file to be - mapped, or failed to open the mapped file for some reason, then revert - back to an unmapped objfile. */ + struct objfile *objfile; - if (objfile == NULL) - { - objfile = (struct objfile *) xmalloc (sizeof (struct objfile)); - memset (objfile, 0, sizeof (struct objfile)); - objfile->psymbol_cache = bcache_xmalloc (); - objfile->macro_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); - terminate_minimal_symbol_table (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); + terminate_minimal_symbol_table (objfile); objfile_alloc_data (objfile); @@ -266,6 +258,8 @@ allocate_objfile (bfd *abfd, int flags) object_files = objfile; else { + struct objfile *last_one; + for (last_one = object_files; last_one->next; last_one = last_one->next); @@ -301,29 +295,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); @@ -339,7 +338,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. @@ -365,6 +378,42 @@ 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; + + res = objfile->separate_debug_objfile; + if (res) + return res; + + res = objfile->separate_debug_objfile_link; + if (res) + return res; + + /* Common case where there is no separate debug objfile. */ + if (objfile == parent) + return NULL; + + 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 @@ -442,6 +491,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 @@ -462,16 +546,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 @@ -549,6 +655,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); @@ -586,9 +693,10 @@ 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. */ + +static void +objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets) { struct obj_section *s; struct section_offsets *delta = @@ -666,6 +774,10 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) } } + if (objfile->psymtabs_addrmap) + addrmap_relocate (objfile->psymtabs_addrmap, + ANOFFSET (delta, SECT_OFF_TEXT (objfile))); + { struct partial_symtab *p; @@ -709,7 +821,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. */ @@ -738,6 +850,54 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) exec_set_section_address (bfd_get_filename (objfile->obfd), idx, obj_section_addr (s)); } +} + +/* 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; + + 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); + + objfile_relocate1 (debug_objfile, new_debug_offsets); + + do_cleanups (my_cleanups); + } /* Relocate breakpoints as necessary, after things are relocated. */ breakpoint_re_set (); @@ -760,25 +920,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; }