/* Read ELF (Executable and Linking Format) object files for GDB.
- Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support.
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. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "bfd.h"
#include "gdb_string.h"
#include "elf-bfd.h"
+#include "elf/common.h"
+#include "elf/internal.h"
#include "elf/mips.h"
#include "symtab.h"
#include "symfile.h"
struct elfinfo
{
- file_ptr dboffset; /* Offset to dwarf debug section */
- unsigned int dbsize; /* Size of dwarf debug section */
- file_ptr lnoffset; /* Offset to dwarf line number section */
- unsigned int lnsize; /* Size of dwarf line number section */
asection *stabsect; /* Section pointer for .stab section */
asection *stabindexsect; /* Section pointer for .stab.index section */
asection *mdebugsect; /* Section pointer for .mdebug section */
static void free_elfinfo (void *);
+/* Locate the segments in ABFD. */
+
+static struct symfile_segment_data *
+elf_symfile_segments (bfd *abfd)
+{
+ Elf_Internal_Phdr *phdrs, **segments;
+ long phdrs_size;
+ int num_phdrs, num_segments, num_sections, i;
+ asection *sect;
+ struct symfile_segment_data *data;
+
+ phdrs_size = bfd_get_elf_phdr_upper_bound (abfd);
+ if (phdrs_size == -1)
+ return NULL;
+
+ phdrs = alloca (phdrs_size);
+ num_phdrs = bfd_get_elf_phdrs (abfd, phdrs);
+ if (num_phdrs == -1)
+ return NULL;
+
+ num_segments = 0;
+ segments = alloca (sizeof (Elf_Internal_Phdr *) * num_phdrs);
+ for (i = 0; i < num_phdrs; i++)
+ if (phdrs[i].p_type == PT_LOAD)
+ segments[num_segments++] = &phdrs[i];
+
+ if (num_segments == 0)
+ return NULL;
+
+ data = XZALLOC (struct symfile_segment_data);
+ data->num_segments = num_segments;
+ data->segment_bases = XCALLOC (num_segments, CORE_ADDR);
+ data->segment_sizes = XCALLOC (num_segments, CORE_ADDR);
+
+ for (i = 0; i < num_segments; i++)
+ {
+ data->segment_bases[i] = segments[i]->p_vaddr;
+ data->segment_sizes[i] = segments[i]->p_memsz;
+ }
+
+ num_sections = bfd_count_sections (abfd);
+ data->segment_info = XCALLOC (num_sections, int);
+
+ for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+ {
+ int j;
+ CORE_ADDR vma;
+
+ if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+ continue;
+
+ vma = bfd_get_section_vma (abfd, sect);
+
+ for (j = 0; j < num_segments; j++)
+ if (segments[j]->p_memsz > 0
+ && vma >= segments[j]->p_vaddr
+ && vma < segments[j]->p_vaddr + segments[j]->p_memsz)
+ {
+ data->segment_info[i] = j + 1;
+ break;
+ }
+
+ if (bfd_get_section_size (sect) > 0 && j == num_segments)
+ warning (_("Loadable segment \"%s\" outside of ELF segments"),
+ bfd_section_name (abfd, sect));
+ }
+
+ return data;
+}
+
/* We are called once per section from elf_symfile_read. We
need to examine each section we are passed, check to see
if it is something we are interested in processing, and
struct elfinfo *ei;
ei = (struct elfinfo *) eip;
- if (strcmp (sectp->name, ".debug") == 0)
- {
- ei->dboffset = sectp->filepos;
- ei->dbsize = bfd_get_section_size (sectp);
- }
- else if (strcmp (sectp->name, ".line") == 0)
- {
- ei->lnoffset = sectp->filepos;
- ei->lnsize = bfd_get_section_size (sectp);
- }
- else if (strcmp (sectp->name, ".stab") == 0)
+ if (strcmp (sectp->name, ".stab") == 0)
{
ei->stabsect = sectp;
}
asection *bfd_section, struct objfile *objfile)
{
if (ms_type == mst_text || ms_type == mst_file_text)
- address = SMASH_TEXT_ADDRESS (address);
+ address = gdbarch_smash_text_address (current_gdbarch, address);
return prim_record_minimal_symbol_and_info
(name, address, ms_type, NULL, bfd_section->index, bfd_section, objfile);
struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
int stripped = (bfd_get_symcount (objfile->obfd) == 0);
- if (1)
+ for (i = 0; i < number_of_symbols; i++)
{
- for (i = 0; i < number_of_symbols; i++)
+ sym = symbol_table[i];
+ if (sym->name == NULL || *sym->name == '\0')
{
- sym = symbol_table[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). */
- continue;
- }
+ /* Skip names that don't exist (shouldn't happen), or names
+ that are null strings (may happen). */
+ continue;
+ }
- offset = ANOFFSET (objfile->section_offsets, sym->section->index);
- if (dynamic
- && sym->section == &bfd_und_section
- && (sym->flags & BSF_FUNCTION))
- {
- struct minimal_symbol *msym;
-
- /* Symbol is a reference to a function defined in
- a shared library.
- If its value is non zero then it is usually the address
- 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
- for this symbol in the executable file, so we skip it. */
- symaddr = sym->value;
- if (symaddr == 0)
- continue;
- symaddr += offset;
- msym = record_minimal_symbol
- ((char *) sym->name, symaddr,
- mst_solib_trampoline, sym->section, objfile);
+ /* Skip "special" symbols, e.g. ARM mapping symbols. These are
+ symbols which do not correspond to objects in the symbol table,
+ but have some other target-specific meaning. */
+ if (bfd_is_target_special_symbol (objfile->obfd, sym))
+ continue;
+
+ offset = ANOFFSET (objfile->section_offsets, sym->section->index);
+ if (dynamic
+ && sym->section == &bfd_und_section
+ && (sym->flags & BSF_FUNCTION))
+ {
+ struct minimal_symbol *msym;
+
+ /* Symbol is a reference to a function defined in
+ a shared library.
+ If its value is non zero then it is usually the address
+ 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
+ for this symbol in the executable file, so we skip it. */
+ symaddr = sym->value;
+ if (symaddr == 0)
+ continue;
+ symaddr += offset;
+ msym = record_minimal_symbol
+ ((char *) sym->name, symaddr,
+ mst_solib_trampoline, sym->section, objfile);
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
- if (msym != NULL)
- msym->filename = filesymname;
+ if (msym != NULL)
+ msym->filename = filesymname;
#endif
- continue;
- }
+ continue;
+ }
- /* If it is a nonstripped executable, do not enter dynamic
- symbols, as the dynamic symbol table is usually a subset
- of the main symbol table. */
- if (dynamic && !stripped)
- continue;
- if (sym->flags & BSF_FILE)
+ /* If it is a nonstripped executable, do not enter dynamic
+ symbols, as the dynamic symbol table is usually a subset
+ of the main symbol table. */
+ if (dynamic && !stripped)
+ continue;
+ if (sym->flags & BSF_FILE)
+ {
+ /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
+ Chain any old one onto the objfile; remember new sym. */
+ if (sectinfo != NULL)
{
- /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
- Chain any old one onto the objfile; remember new sym. */
- if (sectinfo != NULL)
- {
- sectinfo->next = dbx->stab_section_info;
- dbx->stab_section_info = sectinfo;
- sectinfo = NULL;
- }
- filesym = sym;
+ sectinfo->next = dbx->stab_section_info;
+ dbx->stab_section_info = sectinfo;
+ sectinfo = NULL;
+ }
+ filesym = sym;
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
- filesymname =
- obsavestring ((char *) filesym->name, strlen (filesym->name),
- &objfile->objfile_obstack);
+ filesymname =
+ obsavestring ((char *) filesym->name, strlen (filesym->name),
+ &objfile->objfile_obstack);
#endif
+ }
+ else if (sym->flags & BSF_SECTION_SYM)
+ continue;
+ else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+ {
+ struct minimal_symbol *msym;
+
+ /* 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. */
+ symaddr = sym->value + sym->section->vma;
+ /* Relocate all non-absolute symbols by the section offset. */
+ if (sym->section != &bfd_abs_section)
+ {
+ symaddr += offset;
}
- else if (sym->flags & BSF_SECTION_SYM)
- continue;
- else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+ /* 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. */
+ if (sym->section == &bfd_abs_section)
{
- struct minimal_symbol *msym;
-
- /* 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. */
- symaddr = sym->value + sym->section->vma;
- /* Relocate all non-absolute symbols by the section offset. */
- if (sym->section != &bfd_abs_section)
+ /* This is a hack to get the minimal symbol type
+ right for Irix 5, which has absolute addresses
+ with special section indices for dynamic symbols. */
+ unsigned short shndx =
+ ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;
+
+ switch (shndx)
+ {
+ case SHN_MIPS_TEXT:
+ ms_type = mst_text;
+ break;
+ case SHN_MIPS_DATA:
+ ms_type = mst_data;
+ break;
+ case SHN_MIPS_ACOMMON:
+ ms_type = mst_bss;
+ break;
+ default:
+ ms_type = mst_abs;
+ }
+
+ /* If it is an Irix dynamic symbol, skip section name
+ symbols, relocate all others by section offset. */
+ if (ms_type != mst_abs)
{
+ if (sym->name[0] == '.')
+ continue;
symaddr += 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. */
- if (sym->section == &bfd_abs_section)
+ }
+ else if (sym->section->flags & SEC_CODE)
+ {
+ if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
{
- /* This is a hack to get the minimal symbol type
- right for Irix 5, which has absolute addresses
- with special section indices for dynamic symbols. */
- unsigned short shndx =
- ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;
-
- switch (shndx)
- {
- case SHN_MIPS_TEXT:
- ms_type = mst_text;
- break;
- case SHN_MIPS_DATA:
- ms_type = mst_data;
- break;
- case SHN_MIPS_ACOMMON:
- ms_type = mst_bss;
- break;
- default:
- ms_type = mst_abs;
- }
-
- /* If it is an Irix dynamic symbol, skip section name
- symbols, relocate all others by section offset. */
- if (ms_type != mst_abs)
- {
- if (sym->name[0] == '.')
- continue;
- symaddr += offset;
- }
+ ms_type = mst_text;
}
- else if (sym->section->flags & SEC_CODE)
+ else if ((sym->name[0] == '.' && sym->name[1] == 'L')
+ || ((sym->flags & BSF_LOCAL)
+ && sym->name[0] == '$'
+ && sym->name[1] == 'L'))
+ /* Looks like a compiler-generated label. Skip
+ it. The assembler should be skipping these (to
+ keep executables small), but apparently with
+ gcc on the (deleted) delta m88k SVR4, it loses.
+ So to have us check too should be harmless (but
+ I encourage people to fix this in the assembler
+ instead of adding checks here). */
+ continue;
+ else
+ {
+ ms_type = mst_file_text;
+ }
+ }
+ else if (sym->section->flags & SEC_ALLOC)
+ {
+ if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
{
- if (sym->flags & BSF_GLOBAL)
+ if (sym->section->flags & SEC_LOAD)
{
- ms_type = mst_text;
+ ms_type = mst_data;
}
- else if ((sym->name[0] == '.' && sym->name[1] == 'L')
- || ((sym->flags & BSF_LOCAL)
- && sym->name[0] == '$'
- && sym->name[1] == 'L'))
- /* Looks like a compiler-generated label. Skip
- it. The assembler should be skipping these (to
- keep executables small), but apparently with
- gcc on the (deleted) delta m88k SVR4, it loses.
- So to have us check too should be harmless (but
- I encourage people to fix this in the assembler
- instead of adding checks here). */
- continue;
else
{
- ms_type = mst_file_text;
+ ms_type = mst_bss;
}
}
- else if (sym->section->flags & SEC_ALLOC)
+ else if (sym->flags & BSF_LOCAL)
{
- if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
- {
- if (sym->section->flags & SEC_LOAD)
- {
- ms_type = mst_data;
- }
- else
- {
- ms_type = mst_bss;
- }
- }
- else if (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)
+ special_local_sect = SECT_OFF_DATA (objfile);
+ else if (strcmp ("Drodata.rodata", sym->name) == 0)
+ special_local_sect = SECT_OFF_RODATA (objfile);
+ else
+ special_local_sect = -1;
+ if (special_local_sect >= 0)
{
- /* 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)
- special_local_sect = SECT_OFF_DATA (objfile);
- else if (strcmp ("Drodata.rodata", sym->name) == 0)
- special_local_sect = SECT_OFF_RODATA (objfile);
- else
- special_local_sect = -1;
- if (special_local_sect >= 0)
+ /* Found a special local symbol. Allocate a
+ sectinfo, if needed, and fill it in. */
+ if (sectinfo == NULL)
{
- /* Found a special local symbol. Allocate a
- sectinfo, if needed, and fill it in. */
- if (sectinfo == NULL)
+ int max_index;
+ size_t size;
+
+ max_index
+ = max (SECT_OFF_BSS (objfile),
+ max (SECT_OFF_DATA (objfile),
+ SECT_OFF_RODATA (objfile)));
+
+ /* max_index is the largest index we'll
+ use into this array, so we must
+ allocate max_index+1 elements for it.
+ However, 'struct stab_section_info'
+ already includes one element, so we
+ need to allocate max_index aadditional
+ elements. */
+ size = (sizeof (struct stab_section_info)
+ + (sizeof (CORE_ADDR)
+ * max_index));
+ sectinfo = (struct stab_section_info *)
+ xmalloc (size);
+ memset (sectinfo, 0, size);
+ sectinfo->num_sections = max_index;
+ if (filesym == NULL)
{
- int max_index;
- size_t size;
-
- max_index
- = max (SECT_OFF_BSS (objfile),
- max (SECT_OFF_DATA (objfile),
- SECT_OFF_RODATA (objfile)));
-
- /* max_index is the largest index we'll
- use into this array, so we must
- allocate max_index+1 elements for it.
- However, 'struct stab_section_info'
- already includes one element, so we
- need to allocate max_index aadditional
- elements. */
- size = (sizeof (struct stab_section_info)
- + (sizeof (CORE_ADDR)
- * max_index));
- sectinfo = (struct stab_section_info *)
- xmalloc (size);
- 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"),
- sym->name);
- }
- else
- {
- sectinfo->filename =
- (char *) filesym->name;
- }
+ complaint (&symfile_complaints,
+ _("elf/stab section information %s without a preceding file symbol"),
+ sym->name);
+ }
+ else
+ {
+ sectinfo->filename =
+ (char *) filesym->name;
}
- if (sectinfo->sections[special_local_sect] != 0)
- complaint (&symfile_complaints,
- _("duplicated elf/stab section information for %s"),
- sectinfo->filename);
- /* BFD symbols are section relative. */
- symaddr = sym->value + sym->section->vma;
- /* Relocate non-absolute symbols by the
- section offset. */
- if (sym->section != &bfd_abs_section)
- symaddr += offset;
- sectinfo->sections[special_local_sect] = symaddr;
- /* The special local symbols don't go in the
- minimal symbol table, so ignore this one. */
- continue;
- }
- /* Not a special stabs-in-elf symbol, do regular
- symbol processing. */
- if (sym->section->flags & SEC_LOAD)
- {
- ms_type = mst_file_data;
- }
- else
- {
- ms_type = mst_file_bss;
}
+ if (sectinfo->sections[special_local_sect] != 0)
+ complaint (&symfile_complaints,
+ _("duplicated elf/stab section information for %s"),
+ sectinfo->filename);
+ /* BFD symbols are section relative. */
+ symaddr = sym->value + sym->section->vma;
+ /* Relocate non-absolute symbols by the
+ section offset. */
+ if (sym->section != &bfd_abs_section)
+ symaddr += offset;
+ sectinfo->sections[special_local_sect] = symaddr;
+ /* The special local symbols don't go in the
+ minimal symbol table, so ignore this one. */
+ continue;
+ }
+ /* Not a special stabs-in-elf symbol, do regular
+ symbol processing. */
+ if (sym->section->flags & SEC_LOAD)
+ {
+ ms_type = mst_file_data;
}
else
{
- ms_type = mst_unknown;
+ ms_type = mst_file_bss;
}
}
else
{
- /* FIXME: Solaris2 shared libraries include lots of
- odd "absolute" and "undefined" symbols, that play
- 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. */
+ ms_type = mst_unknown;
}
- msym = record_minimal_symbol
- ((char *) sym->name, symaddr,
- ms_type, sym->section, objfile);
- if (msym)
- {
- /* Pass symbol size field in via BFD. FIXME!!! */
- unsigned long size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
- MSYMBOL_SIZE(msym) = size;
- }
+ }
+ else
+ {
+ /* FIXME: Solaris2 shared libraries include lots of
+ odd "absolute" and "undefined" symbols, that play
+ 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. */
+ }
+ msym = record_minimal_symbol
+ ((char *) sym->name, symaddr,
+ ms_type, sym->section, objfile);
+ if (msym)
+ {
+ /* Pass symbol size field in via BFD. FIXME!!! */
+ unsigned long size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+ MSYMBOL_SIZE(msym) = size;
+ }
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
- if (msym != NULL)
- msym->filename = filesymname;
+ if (msym != NULL)
+ msym->filename = filesymname;
#endif
- ELF_MAKE_MSYMBOL_SPECIAL (sym, msym);
- }
+ gdbarch_elf_make_msymbol_special (current_gdbarch, sym, msym);
}
}
}
We look for sections with specific names, to tell us what debug
format to look for: FIXME!!!
- dwarf_build_psymtabs() builds psymtabs for DWARF symbols;
elfstab_build_psymtabs() handles STABS symbols;
mdebug_build_psymtabs() handles ECOFF debugging information.
make_cleanup (xfree, synthsyms);
synth_symbol_table = xmalloc (sizeof (asymbol *) * synthcount);
for (i = 0; i < synthcount; i++)
- {
- synth_symbol_table[i] = synthsyms + i;
- /* Synthetic symbols are not, strictly speaking, either local
- or global. But we can treat them as global symbols, since
- they are effectively dynamic symbols. */
- synth_symbol_table[i]->flags |= BSF_GLOBAL;
- }
+ synth_symbol_table[i] = synthsyms + i;
make_cleanup (xfree, synth_symbol_table);
elf_symtab_read (objfile, 0, synthcount, synth_symbol_table);
}
/* DWARF 2 sections */
dwarf2_build_psymtabs (objfile, mainline);
}
- else if (ei.dboffset && ei.lnoffset)
- {
- /* DWARF sections */
- dwarf_build_psymtabs (objfile,
- mainline,
- ei.dboffset, ei.dbsize,
- ei.lnoffset, ei.lnsize);
- }
/* FIXME: kettenis/20030504: This still needs to be integrated with
dwarf2read.c in a better way. */
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 /* next: pointer to next struct sym_fns */
};