/* 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.
{
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);
/* 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);
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.
}
}
+/* 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
_("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
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
/* 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);
}
\f
/* 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 =
something_changed = 1;
}
if (!something_changed)
- return;
+ return 0;
}
/* OK, get all the symtabs. */
}
}
+ if (objfile->psymtabs_addrmap)
+ addrmap_relocate (objfile->psymtabs_addrmap,
+ ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
+
{
struct partial_symtab *p;
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. */
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 ();
}
\f
/* Return non-zero if OBJFILE has partial symbols. */
}
/* 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;
}