/* Read ELF (Executable and Linking Format) object files for GDB.
Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support.
#include "complaints.h"
#include "demangle.h"
#include "psympriv.h"
+#include "filenames.h"
extern void _initialize_elfread (void);
+/* Forward declarations. */
+static const struct sym_fns elf_sym_fns_gdb_index;
+static const struct sym_fns elf_sym_fns_lazy_psyms;
+
/* The struct elfinfo is available only during ELF symbol table and
psymtab reading. It is destroyed at the completion of psymtab-reading.
It's local to elf_symfile_read. */
FIXME: The section names should not be hardwired strings (what
should they be? I don't think most object file formats have enough
- section flags to specify what kind of debug section it is
+ section flags to specify what kind of debug section it is.
-kingdon). */
static void
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- if (ms_type == mst_text || ms_type == mst_file_text)
+ if (ms_type == mst_text || ms_type == mst_file_text
+ || ms_type == mst_text_gnu_ifunc)
address = gdbarch_smash_text_address (gdbarch, address);
return prim_record_minimal_symbol_full (name, name_len, copy_name, address,
char *filesymname = "";
struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
int stripped = (bfd_get_symcount (objfile->obfd) == 0);
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
for (i = 0; i < number_of_symbols; i++)
{
if (sym->name == NULL || *sym->name == '\0')
{
/* Skip names that don't exist (shouldn't happen), or names
- that are null strings (may happen). */
+ that are null strings (may happen). */
continue;
}
of the corresponding entry in the procedure linkage table,
plus the desired section offset.
If its value is zero then the dynamic linker has to resolve
- the symbol. We are unable to find any meaningful address
+ the symbol. We are unable to find any meaningful address
for this symbol in the executable file, so we skip it. */
symaddr = sym->value;
if (symaddr == 0)
/* Select global/local/weak symbols. Note that bfd puts abs
symbols in their own section, so all symbols we are
- interested in will have a section. */
- /* Bfd symbols are section relative. */
+ interested in will have a section. */
+ /* Bfd symbols are section relative. */
symaddr = sym->value + sym->section->vma;
/* Relocate all non-absolute and non-TLS symbols by the
section offset. */
}
/* For non-absolute symbols, use the type of the section
they are relative to, to intuit text/data. Bfd provides
- no way of figuring this out for absolute symbols. */
+ no way of figuring this out for absolute symbols. */
if (sym->section == &bfd_abs_section)
{
/* This is a hack to get the minimal symbol type
}
/* If it is an Irix dynamic symbol, skip section name
- symbols, relocate all others by section offset. */
+ symbols, relocate all others by section offset. */
if (ms_type != mst_abs)
{
if (sym->name[0] == '.')
{
if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
{
- ms_type = mst_text;
+ if (sym->flags & BSF_GNU_INDIRECT_FUNCTION)
+ ms_type = mst_text_gnu_ifunc;
+ else
+ ms_type = mst_text;
}
else if ((sym->name[0] == '.' && sym->name[1] == 'L')
|| ((sym->flags & BSF_LOCAL)
/* Named Local variable in a Data section.
Check its name for stabs-in-elf. */
int special_local_sect;
+
if (strcmp ("Bbss.bss", sym->name) == 0)
special_local_sect = SECT_OFF_BSS (objfile);
else if (strcmp ("Ddata.data", sym->name) == 0)
need to allocate max_index aadditional
elements. */
size = (sizeof (struct stab_section_info)
- + (sizeof (CORE_ADDR)
- * max_index));
+ + (sizeof (CORE_ADDR) * max_index));
sectinfo = (struct stab_section_info *)
xmalloc (size);
+ make_cleanup (xfree, sectinfo);
memset (sectinfo, 0, size);
sectinfo->num_sections = max_index;
if (filesym == NULL)
{
complaint (&symfile_complaints,
- _("elf/stab section information %s without a preceding file symbol"),
+ _("elf/stab section information %s "
+ "without a preceding file symbol"),
sym->name);
}
else
}
if (sectinfo->sections[special_local_sect] != 0)
complaint (&symfile_complaints,
- _("duplicated elf/stab section information for %s"),
+ _("duplicated elf/stab section "
+ "information for %s"),
sectinfo->filename);
/* BFD symbols are section relative. */
symaddr = sym->value + sym->section->vma;
hob with actions like finding what function the PC
is in. Ignore them if they aren't text, data, or bss. */
/* ms_type = mst_unknown; */
- continue; /* Skip this symbol. */
+ continue; /* Skip this symbol. */
}
msym = record_minimal_symbol
(sym->name, strlen (sym->name), copy_names, symaddr,
}
}
}
+ do_cleanups (back_to);
}
struct build_id
warning (_("File \"%s\" has no build-id, file skipped"), filename);
else if (found->size != check->size
|| memcmp (found->data, check->data, found->size) != 0)
- warning (_("File \"%s\" has a different build-id, file skipped"), filename);
+ warning (_("File \"%s\" has a different build-id, file skipped"),
+ filename);
else
retval = 1;
build_id_name = build_id_to_debug_filename (build_id);
xfree (build_id);
/* Prevent looping on a stripped .debug file. */
- if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0)
+ if (build_id_name != NULL
+ && filename_cmp (build_id_name, objfile->name) == 0)
{
warning (_("\"%s\": separate debug info file has no debug info"),
build_id_name);
memset ((char *) &ei, 0, sizeof (ei));
- /* Allocate struct to keep track of the symfile */
+ /* Allocate struct to keep track of the symfile. */
objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *)
xmalloc (sizeof (struct dbx_symfile_info));
- memset ((char *) objfile->deprecated_sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+ memset ((char *) objfile->deprecated_sym_stab_info,
+ 0, sizeof (struct dbx_symfile_info));
make_cleanup (free_elfinfo, (void *) objfile);
- /* Process the normal ELF symbol table first. This may write some
- chain of info into the dbx_symfile_info in objfile->deprecated_sym_stab_info,
- which can later be used by elfstab_offset_sections. */
+ /* Process the normal ELF symbol table first. This may write some
+ chain of info into the dbx_symfile_info in
+ objfile->deprecated_sym_stab_info, which can later be used by
+ elfstab_offset_sections. */
storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
if (storage_needed < 0)
- error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
+ error (_("Can't read symbols from %s: %s"),
+ bfd_get_filename (objfile->obfd),
bfd_errmsg (bfd_get_error ()));
if (storage_needed > 0)
symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
if (symcount < 0)
- error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
+ error (_("Can't read symbols from %s: %s"),
+ bfd_get_filename (objfile->obfd),
bfd_errmsg (bfd_get_error ()));
elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0);
if (storage_needed > 0)
{
- dyn_symbol_table = (asymbol **) xmalloc (storage_needed);
- make_cleanup (xfree, dyn_symbol_table);
+ /* Memory gets permanently referenced from ABFD after
+ bfd_get_synthetic_symtab so it must not get freed before ABFD gets.
+ It happens only in the case when elf_slurp_reloc_table sees
+ asection->relocation NULL. Determining which section is asection is
+ done by _bfd_elf_get_synthetic_symtab which is all a bfd
+ implementation detail, though. */
+
+ dyn_symbol_table = bfd_alloc (abfd, storage_needed);
dynsymcount = bfd_canonicalize_dynamic_symtab (objfile->obfd,
dyn_symbol_table);
if (dynsymcount < 0)
- error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
+ error (_("Can't read symbols from %s: %s"),
+ bfd_get_filename (objfile->obfd),
bfd_errmsg (bfd_get_error ()));
elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0);
for (i = 0; i < synthcount; i++)
synth_symbol_table[i] = synthsyms + i;
make_cleanup (xfree, synth_symbol_table);
- elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table, 1);
+ elf_symtab_read (objfile, ST_SYNTHETIC, synthcount,
+ synth_symbol_table, 1);
}
/* Install any minimal symbols that have been collected as the current
do_cleanups (back_to);
/* Now process debugging information, which is contained in
- special ELF sections. */
+ special ELF sections. */
- /* We first have to find them... */
+ /* We first have to find them... */
bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei);
/* ELF debugging information is inserted into the psymtab in the
and .debug_info (DWARF2) sections then .mdebug is inserted first
(searched last) and DWARF2 is inserted last (searched first). If
we don't do this then the XCOFF info is found first - for code in
- an included file XCOFF info is useless. */
+ an included file XCOFF info is useless. */
if (ei.mdebugsect)
{
str_sect->filepos,
bfd_section_size (abfd, str_sect));
}
+
if (dwarf2_has_info (objfile))
{
- /* DWARF 2 sections */
- dwarf2_build_psymtabs (objfile);
+ if (dwarf2_initialize_objfile (objfile))
+ objfile->sf = &elf_sym_fns_gdb_index;
+ else
+ {
+ /* It is ok to do this even if the stabs reader made some
+ partial symbols, because OBJF_PSYMTABS_READ has not been
+ set, and so our lazy reader function will still be called
+ when needed. */
+ objfile->sf = &elf_sym_fns_lazy_psyms;
+ }
}
-
- /* If the file has its own symbol tables it has no separate debug info.
- `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS.
- `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'. */
- if (!objfile_has_partial_symbols (objfile))
+ /* If the file has its own symbol tables it has no separate debug
+ info. `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to
+ SYMTABS/PSYMTABS. `.gnu_debuglink' may no longer be present with
+ `.note.gnu.build-id'. */
+ else if (!objfile_has_partial_symbols (objfile))
{
char *debugfile;
if (debugfile)
{
bfd *abfd = symfile_bfd_open (debugfile);
+
symbol_file_add_separate (abfd, symfile_flags, objfile);
xfree (debugfile);
}
}
}
+/* Callback to lazily read psymtabs. */
+
+static void
+read_psyms (struct objfile *objfile)
+{
+ if (dwarf2_has_info (objfile))
+ dwarf2_build_psymtabs (objfile);
+}
+
/* This cleans up the objfile's deprecated_sym_stab_info pointer, and
the chain of stab_section_info's, that might be dangling from
it. */
file is specified (not just adding some symbols from another file, e.g. a
shared library).
- We reinitialize buildsym, since we may be reading stabs from an ELF file. */
+ We reinitialize buildsym, since we may be reading stabs from an ELF
+ file. */
static void
elf_new_init (struct objfile *ignore)
/* Perform any local cleanups required when we are done with a particular
objfile. I.E, we are in the process of discarding all symbol information
for an objfile, freeing up all memory held for it, and unlinking the
- objfile struct from the global list of known objfiles. */
+ objfile struct from the global list of known objfiles. */
static void
elf_symfile_finish (struct objfile *objfile)
a pointer to "private data" which we can fill with goodies.
For now at least, we have nothing in particular to do, so this function is
- just a stub. */
+ just a stub. */
static void
elf_symfile_init (struct objfile *objfile)
void
elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst)
{
- char *filename = pst->filename;
+ const char *filename = pst->filename;
struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
struct stab_section_info *maybe = dbx->stab_section_info;
struct stab_section_info *questionable = 0;
int i;
- char *p;
/* The ELF symbol info doesn't include path names, so strip the path
(if any) from the psymtab filename. */
- while (0 != (p = strchr (filename, '/')))
- filename = p + 1;
+ filename = lbasename (filename);
/* FIXME: This linear search could speed up significantly
if it was chained in the right order to match how we search it,
- and if we unchained when we found a match. */
+ and if we unchained when we found a match. */
for (; maybe; maybe = maybe->next)
{
if (filename[0] == maybe->filename[0]
- && strcmp (filename, maybe->filename) == 0)
+ && filename_cmp (filename, maybe->filename) == 0)
{
/* We found a match. But there might be several source files
(from different directories) with the same name. */
if (maybe == 0 && questionable != 0)
{
complaint (&symfile_complaints,
- _("elf/stab section information questionable for %s"), filename);
+ _("elf/stab section information questionable for %s"),
+ filename);
maybe = questionable;
}
\f
/* Register that we are able to handle ELF object file formats. */
-static struct sym_fns elf_sym_fns =
+static const struct sym_fns elf_sym_fns =
+{
+ bfd_target_elf_flavour,
+ elf_new_init, /* init anything gbl to entire symtab */
+ elf_symfile_init, /* read initial info, setup for sym_read() */
+ elf_symfile_read, /* read a symbol file into symtab */
+ NULL, /* sym_read_psymbols */
+ elf_symfile_finish, /* finished with file, cleanup */
+ default_symfile_offsets, /* Translate ext. to int. relocation */
+ elf_symfile_segments, /* Get segment information from a file. */
+ NULL,
+ default_symfile_relocate, /* Relocate a debug section. */
+ &psym_functions
+};
+
+/* The same as elf_sym_fns, but not registered and lazily reads
+ psymbols. */
+
+static const struct sym_fns elf_sym_fns_lazy_psyms =
+{
+ bfd_target_elf_flavour,
+ elf_new_init, /* init anything gbl to entire symtab */
+ elf_symfile_init, /* read initial info, setup for sym_read() */
+ elf_symfile_read, /* read a symbol file into symtab */
+ read_psyms, /* sym_read_psymbols */
+ elf_symfile_finish, /* finished with file, cleanup */
+ default_symfile_offsets, /* Translate ext. to int. relocation */
+ elf_symfile_segments, /* Get segment information from a file. */
+ NULL,
+ default_symfile_relocate, /* Relocate a debug section. */
+ &psym_functions
+};
+
+/* The same as elf_sym_fns, but not registered and uses the
+ DWARF-specific GNU index rather than psymtab. */
+static const struct sym_fns elf_sym_fns_gdb_index =
{
bfd_target_elf_flavour,
- elf_new_init, /* sym_new_init: init anything gbl to entire symtab */
- elf_symfile_init, /* sym_init: read initial info, setup for sym_read() */
- elf_symfile_read, /* sym_read: read a symbol file into symtab */
- elf_symfile_finish, /* sym_finish: finished with file, cleanup */
- default_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
- elf_symfile_segments, /* sym_segments: Get segment information from
- a file. */
- NULL, /* sym_read_linetable */
- default_symfile_relocate, /* sym_relocate: Relocate a debug section. */
- &psym_functions,
- NULL /* next: pointer to next struct sym_fns */
+ elf_new_init, /* init anything gbl to entire symab */
+ elf_symfile_init, /* read initial info, setup for sym_red() */
+ elf_symfile_read, /* read a symbol file into symtab */
+ NULL, /* sym_read_psymbols */
+ elf_symfile_finish, /* finished with file, cleanup */
+ default_symfile_offsets, /* Translate ext. to int. relocatin */
+ elf_symfile_segments, /* Get segment information from a file. */
+ NULL,
+ default_symfile_relocate, /* Relocate a debug section. */
+ &dwarf2_gdb_index_functions
};
void