/* GDB routines for manipulating objfiles.
- Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* This file contains support routines for creating, manipulating, and
destroying objfile structures. */
#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 "breakpoint.h"
#include "block.h"
#include "dictionary.h"
+#include "source.h"
+#include "addrmap.h"
+#include "arch-utils.h"
+#include "exec.h"
/* Prototypes for local functions */
objfile_p_char is a char * to get it through
bfd_map_over_sections; we cast it back to its proper type. */
-#ifndef TARGET_KEEP_SECTION
-#define TARGET_KEEP_SECTION(ASECT) 0
-#endif
-
/* 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
aflag = bfd_get_section_flags (abfd, asect);
- if (!(aflag & SEC_ALLOC) && !(TARGET_KEEP_SECTION (asect)))
+ if (!(aflag & SEC_ALLOC))
return;
if (0 == bfd_section_size (abfd, asect))
return;
- section.offset = 0;
section.objfile = objfile;
section.the_bfd_section = asect;
section.ovly_mapped = 0;
- section.addr = bfd_section_vma (abfd, asect);
- section.endaddr = section.addr + bfd_section_size (abfd, asect);
obstack_grow (&objfile->objfile_obstack, (char *) §ion, sizeof (section));
- objfile->sections_end = (struct obj_section *) (((unsigned long) objfile->sections_end) + 1);
+ objfile->sections_end
+ = (struct obj_section *) (((size_t) objfile->sections_end) + 1);
}
/* Builds a section table for OBJFILE.
waste some memory. */
objfile->sections_end = 0;
- bfd_map_over_sections (objfile->obfd, add_to_objfile_sections, (char *) objfile);
- objfile->sections = (struct obj_section *)
- obstack_finish (&objfile->objfile_obstack);
- objfile->sections_end = objfile->sections + (unsigned long) objfile->sections_end;
+ 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);
}
{
objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
memset (objfile, 0, sizeof (struct objfile));
- objfile->md = NULL;
objfile->psymbol_cache = bcache_xmalloc ();
objfile->macro_cache = bcache_xmalloc ();
/* We could use obstack_specify_allocation here instead, but
objfile->obfd = abfd;
if (objfile->name != NULL)
{
- xmfree (objfile->md, objfile->name);
+ xfree (objfile->name);
}
if (abfd != NULL)
{
- objfile->name = mstrsave (objfile->md, bfd_get_filename (abfd));
+ /* 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. */
if (build_objfile_section_table (objfile))
{
- error ("Can't find the file sections in `%s': %s",
+ error (_("Can't find the file sections in `%s': %s"),
objfile->name, bfd_errmsg (bfd_get_error ()));
}
}
else
{
- objfile->name = mstrsave (objfile->md, "<<anonymous objfile>>");
+ objfile->name = xstrdup ("<<anonymous objfile>>");
}
/* Initialize the section indexes for this objfile, so that we can
return (objfile);
}
+/* Retrieve the gdbarch associated with OBJFILE. */
+struct gdbarch *
+get_objfile_arch (struct objfile *objfile)
+{
+ return objfile->gdbarch;
+}
+
/* Initialize entry point information for this objfile. */
void
the startup file because it contains the entry point. */
objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
}
+ 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);
else
{
/* Examination of non-executable.o files. Short-circuit this stuff. */
objfile->ei.entry_point = INVALID_ENTRY_POINT;
}
- objfile->ei.deprecated_entry_file_lowpc = INVALID_ENTRY_LOWPC;
- objfile->ei.deprecated_entry_file_highpc = INVALID_ENTRY_HIGHPC;
- objfile->ei.entry_func_lowpc = INVALID_ENTRY_LOWPC;
- objfile->ei.entry_func_highpc = INVALID_ENTRY_HIGHPC;
- objfile->ei.main_func_lowpc = INVALID_ENTRY_LOWPC;
- objfile->ei.main_func_highpc = INVALID_ENTRY_HIGHPC;
}
/* Get current entry point address. */
= &objfile->msymbols[objfile->minimal_symbol_count];
memset (m, 0, sizeof (*m));
- DEPRECATED_SYMBOL_NAME (m) = NULL;
- SYMBOL_VALUE_ADDRESS (m) = 0;
- MSYMBOL_INFO (m) = NULL;
- MSYMBOL_SIZE (m) = 0;
+ /* Don't rely on these enumeration values being 0's. */
MSYMBOL_TYPE (m) = mst_unknown;
SYMBOL_INIT_LANGUAGE_SPECIFIC (m, language_unknown);
}
}
internal_error (__FILE__, __LINE__,
- "put_objfile_before: before objfile not in list");
+ _("put_objfile_before: before objfile not in list"));
}
/* Put OBJFILE at the front of the list. */
}
internal_error (__FILE__, __LINE__,
- "unlink_objfile: objfile already unlinked");
+ _("unlink_objfile: objfile already unlinked"));
}
objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL;
}
+ /* Remove any references to this objfile in the global value
+ lists. */
+ preserve_values (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
(*objfile->sf->sym_finish) (objfile);
}
- /* We always close the bfd. */
+ /* Discard any data modules have associated with the objfile. */
+ objfile_free_data (objfile);
+
+ /* We always close the bfd, unless the OBJF_KEEPBFD flag is set. */
- if (objfile->obfd != NULL)
+ if (objfile->obfd != NULL && !(objfile->flags & OBJF_KEEPBFD))
{
char *name = bfd_get_filename (objfile->obfd);
if (!bfd_close (objfile->obfd))
- warning ("cannot close \"%s\": %s",
+ warning (_("cannot close \"%s\": %s"),
name, bfd_errmsg (bfd_get_error ()));
xfree (name);
}
is unknown, but we play it safe for now and keep each action until
it is shown to be no longer needed. */
- /* I *think* all our callers call clear_symtab_users. If so, no need
- to call this here. */
+ /* Not all our callers call clear_symtab_users (objfile_purge_solibs,
+ for example), so we need to call this here. */
clear_pc_function_cache ();
+ /* Clear globals which might have pointed into a removed objfile.
+ FIXME: It's not clear which of these are supposed to persist
+ between expressions and which ought to be reset each time. */
+ expression_context_block = NULL;
+ innermost_block = NULL;
+
+ /* Check to see if the current_source_symtab belongs to this objfile,
+ and if so, call clear_current_source_symtab_and_line. */
+
+ {
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ struct symtab *s;
+
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ {
+ if (s == cursal.symtab)
+ clear_current_source_symtab_and_line ();
+ }
+ }
+
/* The last thing we do is free the objfile struct itself. */
- objfile_free_data (objfile);
if (objfile->name != NULL)
{
- xmfree (objfile->md, objfile->name);
+ xfree (objfile->name);
}
if (objfile->global_psymbols.list)
- xmfree (objfile->md, objfile->global_psymbols.list);
+ xfree (objfile->global_psymbols.list);
if (objfile->static_psymbols.list)
- xmfree (objfile->md, objfile->static_psymbols.list);
+ xfree (objfile->static_psymbols.list);
/* Free the obstacks for non-reusable objfiles */
bcache_xfree (objfile->psymbol_cache);
bcache_xfree (objfile->macro_cache);
if (objfile->demangled_names_hash)
htab_delete (objfile->demangled_names_hash);
obstack_free (&objfile->objfile_obstack, 0);
- xmfree (objfile->md, objfile);
+ xfree (objfile);
objfile = NULL;
}
void
objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
{
+ struct obj_section *s;
struct section_offsets *delta =
((struct section_offsets *)
alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)));
b = BLOCKVECTOR_BLOCK (bv, i);
BLOCK_START (b) += ANOFFSET (delta, s->block_line_section);
BLOCK_END (b) += ANOFFSET (delta, s->block_line_section);
+ if (BLOCKVECTOR_MAP (bv))
+ addrmap_relocate (BLOCKVECTOR_MAP (bv),
+ ANOFFSET (delta, s->block_line_section));
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
But I'm leaving out that test, on the theory that
they can't possibly pass the tests below. */
if ((SYMBOL_CLASS (sym) == LOC_LABEL
- || SYMBOL_CLASS (sym) == LOC_STATIC
- || SYMBOL_CLASS (sym) == LOC_INDIRECT)
+ || SYMBOL_CLASS (sym) == LOC_STATIC)
&& SYMBOL_SECTION (sym) >= 0)
{
SYMBOL_VALUE_ADDRESS (sym) +=
ANOFFSET (delta, SYMBOL_SECTION (sym));
}
-#ifdef MIPS_EFI_SYMBOL_NAME
- /* Relocate Extra Function Info for ecoff. */
-
- else if (SYMBOL_CLASS (sym) == LOC_CONST
- && SYMBOL_DOMAIN (sym) == LABEL_DOMAIN
- && strcmp (DEPRECATED_SYMBOL_NAME (sym), MIPS_EFI_SYMBOL_NAME) == 0)
- ecoff_relocate_efi (sym, ANOFFSET (delta,
- s->block_line_section));
-#endif
}
}
}
objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
}
- {
- struct obj_section *s;
- bfd *abfd;
-
- abfd = objfile->obfd;
-
- ALL_OBJFILE_OSECTIONS (objfile, s)
- {
- int idx = s->the_bfd_section->index;
-
- s->addr += ANOFFSET (delta, idx);
- s->endaddr += ANOFFSET (delta, idx);
- }
- }
-
- if (objfile->ei.entry_func_lowpc != INVALID_ENTRY_LOWPC)
+ /* Update the table in exec_ops, used to read memory. */
+ ALL_OBJFILE_OSECTIONS (objfile, s)
{
- objfile->ei.entry_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
- objfile->ei.entry_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
- }
+ int idx = s->the_bfd_section->index;
- if (objfile->ei.deprecated_entry_file_lowpc != INVALID_ENTRY_LOWPC)
- {
- objfile->ei.deprecated_entry_file_lowpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
- objfile->ei.deprecated_entry_file_highpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
- }
-
- if (objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC)
- {
- objfile->ei.main_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
- objfile->ei.main_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
+ exec_set_section_address (bfd_get_filename (objfile->obfd), idx,
+ obj_section_addr (s));
}
/* Relocate breakpoints as necessary, after things are relocated. */
return 0;
}
-/* Returns a section whose range includes PC and SECTION, or NULL if
- none found. Note the distinction between the return type, struct
- obj_section (which is defined in gdb), and the input type "struct
- bfd_section" (which is a bfd-defined data type). The obj_section
- contains a pointer to the "struct bfd_section". */
+/* Returns a section whose range includes PC or NULL if none found. */
struct obj_section *
-find_pc_sect_section (CORE_ADDR pc, struct bfd_section *section)
+find_pc_section (CORE_ADDR pc)
{
struct obj_section *s;
struct objfile *objfile;
+ /* Check for mapped overlay section first. */
+ s = find_pc_mapped_section (pc);
+ if (s)
+ return s;
+
ALL_OBJSECTIONS (objfile, s)
- if ((section == 0 || section == s->the_bfd_section) &&
- s->addr <= pc && pc < s->endaddr)
- return (s);
+ if (obj_section_addr (s) <= pc && pc < obj_section_endaddr (s))
+ return s;
- return (NULL);
-}
-
-/* Returns a section whose range includes PC or NULL if none found.
- Backward compatibility, no section. */
-
-struct obj_section *
-find_pc_section (CORE_ADDR pc)
-{
- return find_pc_sect_section (pc, find_pc_mapped_section (pc));
+ return NULL;
}
&& strcmp (s->the_bfd_section->name, ".plt") == 0);
return (retval);
}
-
-/* Return nonzero if NAME is in the import list of OBJFILE. Else
- return zero. */
-
-int
-is_in_import_list (char *name, struct objfile *objfile)
-{
- int i;
-
- if (!objfile || !name || !*name)
- return 0;
-
- for (i = 0; i < objfile->import_list_size; i++)
- if (objfile->import_list[i] && DEPRECATED_STREQ (name, objfile->import_list[i]))
- return 1;
- return 0;
-}
\f
/* Keep a registry of per-objfile data-pointers required by other GDB
struct objfile_data
{
unsigned index;
+ void (*cleanup) (struct objfile *, void *);
};
struct objfile_data_registration
static struct objfile_data_registry objfile_data_registry = { NULL, 0 };
const struct objfile_data *
-register_objfile_data (void)
+register_objfile_data_with_cleanup (void (*cleanup) (struct objfile *, void *))
{
struct objfile_data_registration **curr;
(*curr)->next = NULL;
(*curr)->data = XMALLOC (struct objfile_data);
(*curr)->data->index = objfile_data_registry.num_registrations++;
+ (*curr)->data->cleanup = cleanup;
return (*curr)->data;
}
+const struct objfile_data *
+register_objfile_data (void)
+{
+ return register_objfile_data_with_cleanup (NULL);
+}
+
static void
objfile_alloc_data (struct objfile *objfile)
{
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);
+
+ for (registration = objfile_data_registry.registrations, i = 0;
+ i < objfile->num_data;
+ registration = registration->next, i++)
+ if (objfile->data[i] != NULL && registration->data->cleanup)
+ registration->data->cleanup (objfile, objfile->data[i]);
+
memset (objfile->data, 0, objfile->num_data * sizeof (void *));
}