aboutsummaryrefslogtreecommitdiff
path: root/gdb/elfread.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/elfread.c')
-rw-r--r--gdb/elfread.c262
1 files changed, 243 insertions, 19 deletions
diff --git a/gdb/elfread.c b/gdb/elfread.c
index a89e556c..7075f0f 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -43,8 +43,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "objfiles.h"
#include "buildsym.h"
+#include <sys/types.h> /* For off_t for gdb-stabs.h */
+#include "gdb-stabs.h"
+
#define STREQ(a,b) (strcmp((a),(b))==0)
+/* The struct elfinfo is available only during ELF symbol table and
+ psymtab reading. It is destroyed at the complation of psymtab-reading.
+ It's local to elf_symfile_read. */
+
struct elfinfo {
unsigned int dboffset; /* Offset to dwarf debug section */
unsigned int dbsize; /* Size of dwarf debug section */
@@ -54,6 +61,20 @@ struct elfinfo {
asection *stabindexsect; /* Section pointer for .stab.index section */
};
+/* Various things we might complain about... */
+
+struct complaint section_info_complaint =
+ {"elf/stab section information %s without a preceding file symbol", 0, 0};
+
+struct complaint section_info_dup_complaint =
+ {"duplicated elf/stab section information for %s", 0, 0};
+
+struct complaint stab_info_mismatch_complaint =
+ {"elf/stab section information missing for %s", 0, 0};
+
+struct complaint stab_info_questionable_complaint =
+ {"elf/stab section information questionable for %s", 0, 0};
+
static void
elf_symfile_init PARAMS ((struct objfile *));
@@ -61,7 +82,7 @@ static void
elf_new_init PARAMS ((struct objfile *));
static void
-elf_symfile_read PARAMS ((struct objfile *, CORE_ADDR, int));
+elf_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
static void
elf_symfile_finish PARAMS ((struct objfile *));
@@ -69,6 +90,12 @@ elf_symfile_finish PARAMS ((struct objfile *));
static void
elf_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *));
+static void
+free_elfinfo PARAMS ((PTR));
+
+static struct section_offsets *
+elf_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
#if 0
static void
record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
@@ -221,6 +248,12 @@ DESCRIPTION
or not (may be shared library for example), add all the global
function and data symbols to the minimal symbol table.
+ In stabs-in-ELF, as implemented by Sun, there are some local symbols
+ defined in the ELF symbol table, which can be used to locate
+ the beginnings of sections from each ".o" file that was linked to
+ form the executable objfile. We gather any such info and record it
+ in data structures hung off the objfile's private data.
+
*/
static void
@@ -234,9 +267,18 @@ elf_symtab_read (abfd, addr, objfile)
asymbol **symbol_table;
unsigned int number_of_symbols;
unsigned int i;
+ int index;
struct cleanup *back_to;
CORE_ADDR symaddr;
enum minimal_symbol_type ms_type;
+ /* If sectinfo is nonzero, it contains section info that should end up
+ filed in the objfile. */
+ struct stab_section_info *sectinfo = 0;
+ /* If filesym is nonzero, it points to a file symbol, but we haven't
+ seen any section info for it yet. */
+ asymbol *filesym = 0;
+ struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
+ objfile->sym_private;
storage_needed = get_symtab_upper_bound (abfd);
@@ -248,7 +290,7 @@ elf_symtab_read (abfd, addr, objfile)
for (i = 0; i < number_of_symbols; i++)
{
- sym = *symbol_table++;
+ sym = symbol_table[i];
/* Select global/weak symbols that are defined in a specific section.
Note that bfd now puts abs symbols in their own section, so
all symbols we are interested in will have a section. */
@@ -258,9 +300,8 @@ elf_symtab_read (abfd, addr, objfile)
symaddr = sym -> value;
/* Relocate all non-absolute symbols by base address. */
if (sym -> section != &bfd_abs_section)
- {
- symaddr += addr;
- }
+ symaddr += addr;
+
/* 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. */
@@ -285,6 +326,69 @@ elf_symtab_read (abfd, addr, objfile)
record_minimal_symbol_and_info ((char *) sym -> name,
symaddr, ms_type, sym->udata, objfile);
}
+
+ /* See if this is a debugging symbol that helps Solaris
+ stabs-in-elf debugging. */
+
+ else if (sym->flags & BSF_FILE)
+ {
+ /* Chain any old one onto the objfile; remember new sym. */
+ if (sectinfo)
+ {
+ sectinfo->next = dbx->stab_section_info;
+ dbx->stab_section_info = sectinfo;
+ sectinfo = 0;
+ }
+ filesym = sym;
+ }
+ else if ((sym->flags & BSF_LOCAL) &&
+ (sym->section) &&
+ (sym->section->flags & SEC_DATA) &&
+ (sym->name))
+ {
+ /* Named Local variable in a Data section. Check its name. */
+ index = -1;
+ switch (sym->name[1])
+ {
+ case 'b':
+ if (!strcmp ("Bbss.bss", sym->name))
+ index = SECT_OFF_BSS;
+ break;
+ case 'd':
+ if (!strcmp ("Ddata.data", sym->name))
+ index = SECT_OFF_DATA;
+ break;
+ case 'r':
+ if (!strcmp ("Drodata.rodata", sym->name))
+ index = SECT_OFF_RODATA;
+ break;
+ }
+ if (index > 0)
+ {
+ /* We have some new info. Allocate a sectinfo, if
+ needed, and fill it in. */
+ if (!sectinfo)
+ {
+ sectinfo = (struct stab_section_info *)
+ xmmalloc (objfile -> md,
+ sizeof (*sectinfo));
+ memset ((PTR) sectinfo, 0, sizeof (*sectinfo));
+ if (!filesym)
+ complain (&section_info_complaint, (char *)sym->name);
+ else
+ sectinfo->filename = (char *)filesym->name;
+ }
+ if (sectinfo->sections[index])
+ complain (&section_info_dup_complaint,
+ (char *)sectinfo->filename);
+
+ symaddr = sym -> value;
+ /* Relocate all non-absolute symbols by base address. */
+ if (sym -> section != &bfd_abs_section)
+ symaddr += addr;
+ sectinfo->sections[index] = symaddr;
+ }
+ }
}
do_cleanups (back_to);
}
@@ -294,8 +398,9 @@ elf_symtab_read (abfd, addr, objfile)
We have been initialized by a call to elf_symfile_init, which
currently does nothing.
- ADDR is the address relative to which the symbols in it are (e.g.
- the base address of the text segment).
+ SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
+ in each section. We simplify it down to a single offset for all
+ symbols. FIXME.
MAINLINE is true if we are reading the main symbol
table (as opposed to a shared lib or dynamically loaded file).
@@ -321,13 +426,14 @@ elf_symtab_read (abfd, addr, objfile)
capability even for files compiled without -g. */
static void
-elf_symfile_read (objfile, addr, mainline)
+elf_symfile_read (objfile, section_offsets, mainline)
struct objfile *objfile;
- CORE_ADDR addr;
+ struct section_offsets *section_offsets;
int mainline;
{
bfd *abfd = objfile->obfd;
struct elfinfo ei;
+ struct dbx_symfile_info *dbx;
struct cleanup *back_to;
asection *text_sect;
CORE_ADDR offset;
@@ -335,29 +441,32 @@ elf_symfile_read (objfile, addr, mainline)
init_minimal_symbol_collection ();
back_to = make_cleanup (discard_minimal_symbols, 0);
- /* Compute the amount to relocate all symbols by. The value passed in
- as ADDR is typically either the actual address of the text section,
- or a user specified address. By subtracting off the actual address
- of the text section, we can compute the relocation amount. */
+ memset ((char *) &ei, 0, sizeof (ei));
- text_sect = bfd_get_section_by_name (objfile -> obfd, ".text");
- offset = addr - bfd_section_vma (objfile -> obfd, text_sect);
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_private = (PTR)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+ memset ((char *) objfile->sym_private, 0, sizeof (struct dbx_symfile_info));
+ make_cleanup (free_elfinfo, (PTR) objfile);
- /* Process the normal ELF symbol table first. */
+ /* Process the normal ELF symbol table first. This may write some
+ chain of info into the dbx_symfile_info in objfile->sym_private,
+ which can later be used by elfstab_offset_sections. */
+ /* FIXME, should take a section_offsets param, not just an offset. */
+ offset = ANOFFSET (section_offsets, 0);
elf_symtab_read (abfd, offset, objfile);
/* Now process debugging information, which is contained in
special ELF sections. We first have to find them... */
- memset ((char *) &ei, 0, sizeof (ei));
bfd_map_over_sections (abfd, elf_locate_sections, (PTR) &ei);
if (ei.dboffset && ei.lnoffset)
{
/* DWARF sections */
dwarf_build_psymtabs (fileno ((FILE *)(abfd -> iostream)),
bfd_get_filename (abfd),
- offset, mainline,
+ section_offsets, mainline,
ei.dboffset, ei.dbsize,
ei.lnoffset, ei.lnsize, objfile);
}
@@ -376,7 +485,7 @@ elf_symfile_read (objfile, addr, mainline)
elf_sect = bfd_elf_find_section (abfd, ".stabstr");
if (elf_sect)
elfstab_build_psymtabs (objfile,
- addr, /* We really pass the text seg addr, not the offset, here. */
+ section_offsets,
mainline,
ei.stabsect->filepos, /* .stab offset */
bfd_get_section_size_before_reloc (ei.stabsect),/* .stab size */
@@ -399,6 +508,30 @@ elf_symfile_read (objfile, addr, mainline)
do_cleanups (back_to);
}
+/* This cleans up the objfile's sym_private pointer, and the chain of
+ stab_section_info's, that might be dangling from it. */
+
+static void
+free_elfinfo (objp)
+ PTR objp;
+{
+ struct objfile *objfile = (struct objfile *)objp;
+ struct dbx_symfile_info *dbxinfo = (struct dbx_symfile_info *)
+ objfile->sym_private;
+ struct stab_section_info *ssi, *nssi;
+
+ ssi = dbxinfo->stab_section_info;
+ while (ssi)
+ {
+ nssi = ssi->next;
+ mfree (objfile->md, ssi);
+ ssi = nssi;
+ }
+
+ dbxinfo->stab_section_info = 0; /* Just say No mo info about this. */
+}
+
+
/* Initialize anything that needs initializing when a completely new symbol
file is specified (not just adding some symbols from another file, e.g. a
shared library).
@@ -442,6 +575,96 @@ elf_symfile_init (ignore)
{
}
+/* ELF specific parsing routine for section offsets.
+
+ Plain and simple for now. */
+
+static
+struct section_offsets *
+elf_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+/* When handling an ELF file that contains Sun STABS debug info,
+ some of the debug info is relative to the particular chunk of the
+ section that was generated in its individual .o file. E.g.
+ offsets to static variables are relative to the start of the data
+ segment *for that module before linking*. This information is
+ painfully squirreled away in the ELF symbol table as local symbols
+ with wierd names. Go get 'em when needed. */
+
+void
+elfstab_offset_sections (objfile, pst)
+ struct objfile *objfile;
+ struct partial_symtab *pst;
+{
+ char *filename = pst->filename;
+ struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
+ objfile->sym_private;
+ 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;
+
+ /* 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. */
+ for (; maybe; maybe = maybe->next)
+ {
+ if (filename[0] == maybe->filename[0]
+ && !strcmp (filename, maybe->filename))
+ {
+ /* We found a match. But there might be several source files
+ (from different directories) with the same name. */
+ if (0 == maybe->found)
+ break;
+ questionable = maybe; /* Might use it later. */
+ }
+ }
+
+ if (maybe == 0 && questionable != 0)
+ {
+ complain (&stab_info_questionable_complaint, filename);
+ maybe = questionable;
+ }
+
+ if (maybe)
+ {
+ /* Found it! Allocate a new psymtab struct, and fill it in. */
+ maybe->found++;
+ pst->section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (pst->section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (pst->section_offsets, i) = maybe->sections[i];
+ return;
+ }
+
+ /* We were unable to find any offsets for this file. Complain. */
+ if (dbx->stab_section_info) /* If there *is* any info, */
+ complain (&stab_info_mismatch_complaint, filename);
+}
/* Register that we are able to handle ELF object file formats and DWARF
debugging formats.
@@ -467,6 +690,7 @@ static struct sym_fns elf_sym_fns =
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 */
+ elf_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
NULL /* next: pointer to next struct sym_fns */
};