Fix powerpc64-linux inferior function calls

Alan Modra
2005-09-28T07:34:27Z

This gives me a gdb that can make inferior calls on powerpc64-linux when
debugging code compiled by a gcc that doesn't provide dot-symbols.
ppc-sysv-tdep.c:convert_code_addr_to_desc_addr needs dot-symbols to find
the function descriptor corresponding to a given pc.

It's a band-aid really. I think the proper fix is to not convert
function pointers to function code addresses in gdb's expression
evaluator, which would keep the pointer to the descriptor. This of
course would mean that gdb's breakpoint and similar code expecting that
function symbols point to code would need adjusting. One benefit would
be that "p *func" would print me the descriptor, which is what I'd
expect for powerpc64.

PR 2016
* elfread.c (elf_symtab_process): Split out from..
(elf_symtab_read): ..here.
(elf_symfile_read): Read both static and dynamic symbols before
processing. Call bfd_get_synthetic_symtab.

Index: gdb/elfread.c
===================================================================
RCS file: /cvs/src/src/gdb/elfread.c,v
retrieving revision 1.50
diff -u -p -r1.50 elfread.c
--- gdb/elfread.c 21 Feb 2005 11:00:44 -0000 1.50
+++ gdb/elfread.c 28 Sep 2005 06:59:55 -0000
@@ -124,7 +124,63 @@ record_minimal_symbol (char *name, CORE_

SYNOPSIS

- void elf_symtab_read (struct objfile *objfile, int dynamic)
+ long elf_symtab_read (struct objfile *objfile, int dynamic, asymbol ***syms)
+
+ DESCRIPTION
+
+ Given an objfile and a flag that specifies whether to read static or
+ dynamic symbols, read the raw BFD symbols. Return the number of symbols
+ and an array of pointers to the symbols.
+
+ */
+
+long
+elf_symtab_read (struct objfile *objfile, int dynamic, asymbol ***syms)
+{
+ long storage_needed;
+ asymbol **symbol_table = NULL;
+ long number_of_symbols = 0;
+
+ if (dynamic)
+ storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd);
+ else
+ {
+ 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),
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ if (storage_needed > 0)
+ {
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ if (dynamic)
+ number_of_symbols = bfd_canonicalize_dynamic_symtab (objfile->obfd,
+ symbol_table);
+ else
+ number_of_symbols = bfd_canonicalize_symtab (objfile->obfd,
+ symbol_table);
+ if (number_of_symbols < 0)
+ error (_("Can't read symbols from %s: %s"),
+ bfd_get_filename (objfile->obfd),
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ *syms = symbol_table;
+ return number_of_symbols;
+}
+
+/*
+
+ LOCAL FUNCTION
+
+ elf_symtab_process -- process the symbol table of an ELF file
+
+ SYNOPSIS
+
+ void elf_symtab_process (struct objfile *objfile, int dynamic
+ long number_of_symbols, asymbol **symbol_table)

DESCRIPTION

@@ -140,15 +196,12 @@ record_minimal_symbol (char *name, CORE_

*/

-static void
-elf_symtab_read (struct objfile *objfile, int dynamic)
+void
+elf_symtab_process (struct objfile *objfile, int dynamic,
+ long number_of_symbols, asymbol **symbol_table)
{
- long storage_needed;
asymbol *sym;
- asymbol **symbol_table;
- long number_of_symbols;
long i;
- struct cleanup *back_to;
CORE_ADDR symaddr;
CORE_ADDR offset;
enum minimal_symbol_type ms_type;
@@ -165,292 +218,262 @@ elf_symtab_read (struct objfile *objfile
struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
int stripped = (bfd_get_symcount (objfile->obfd) == 0);

- if (dynamic)
+ for (i = 0; i < number_of_symbols; i++)
{
- storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd);
+ 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;
+ }

- /* Nothing to be done if there is no dynamic symtab. */
- if (storage_needed < 0)
- return;
- }
- else
- {
- 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),
- bfd_errmsg (bfd_get_error ()));
- }
- if (storage_needed > 0)
- {
- symbol_table = (asymbol **) xmalloc (storage_needed);
- back_to = make_cleanup (xfree, symbol_table);
- if (dynamic)
- number_of_symbols = bfd_canonicalize_dynamic_symtab (objfile->obfd,
- symbol_table);
- else
- number_of_symbols = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
- if (number_of_symbols < 0)
- error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
- bfd_errmsg (bfd_get_error ()));
+ 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;
+#endif
+ continue;
+ }

- for (i = 0; i < number_of_symbols; i++)
+ /* 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)
{
- sym = symbol_table[i];
- if (sym->name == NULL || *sym->name == '\0')
+ /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
+ Chain any old one onto the objfile; remember new sym. */
+ if (sectinfo != NULL)
{
- /* Skip names that don't exist (shouldn't happen), or names
- that are null strings (may happen). */
- continue;
+ 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);
+#endif
+ }
+ else if (sym->flags & BSF_SECTION_SYM)
+ continue;
+ else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+ {
+ struct minimal_symbol *msym;

- offset = ANOFFSET (objfile->section_offsets, sym->section->index);
- if (dynamic
- && sym->section == &bfd_und_section
- && (sym->flags & BSF_FUNCTION))
+ /* 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)
{
- 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;
-#endif
- 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)
+ /* 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)
{
- /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
- Chain any old one onto the objfile; remember new sym. */
- if (sectinfo != NULL)
+ /* 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)
{
- sectinfo->next = dbx->stab_section_info;
- dbx->stab_section_info = sectinfo;
- sectinfo = NULL;
+ 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;
}
- filesym = sym;
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
- 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)
+ /* 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)
{
- /* 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
{
- if (sym->flags & BSF_GLOBAL)
+ ms_type = mst_file_text;
+ }
+ }
+ else if (sym->section->flags & SEC_ALLOC)
+ {
+ if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
+ {
+ 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;
+ 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;
- }
+ 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;
}
- 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);
- }
+ ELF_MAKE_MSYMBOL_SPECIAL (sym, msym);
}
- do_cleanups (back_to);
}
}

@@ -493,6 +516,12 @@ elf_symfile_read (struct objfile *objfil
struct elfinfo ei;
struct cleanup *back_to;
CORE_ADDR offset;
+ asymbol **static_syms;
+ asymbol **dyn_syms;
+ asymbol *synthsyms;
+ long num_static_syms;
+ long num_dyn_syms;
+ long synth_count;

init_minimal_symbol_collection ();
back_to = make_cleanup_discard_minimal_symbols ();
@@ -509,11 +538,42 @@ elf_symfile_read (struct objfile *objfil
chain of info into the dbx_symfile_info in objfile->deprecated_sym_stab_info,
which can later be used by elfstab_offset_sections. */

- elf_symtab_read (objfile, 0);
+ num_static_syms = elf_symtab_read (objfile, 0, &static_syms);
+ make_cleanup (xfree, static_syms);

/* Add the dynamic symbols. */

- elf_symtab_read (objfile, 1);
+ num_dyn_syms = elf_symtab_read (objfile, 1, &dyn_syms);
+ make_cleanup (xfree, dyn_syms);
+
+ /* Also, for the sake of powerpc64-linux, regenerate dot-symbols.
+ On other targets, this introduces syms marking PLT entries. */
+
+ synth_count = bfd_get_synthetic_symtab (objfile->obfd,
+ num_static_syms, static_syms,
+ num_dyn_syms, dyn_syms,
+ &synthsyms);
+ if (synth_count > 0)
+ {
+ asymbol **symp;
+ void *new_syms;
+ long i;
+
+ new_syms = xmalloc ((num_static_syms + synth_count + 1)
+ * sizeof (*symp));
+ symp = new_syms;
+ memcpy (symp, static_syms, num_static_syms * sizeof (*symp));
+ symp += num_static_syms;
+ for (i = 0; i < synth_count; i++)
+ *symp++ = synthsyms + i;
+ *symp = 0;
+ static_syms = new_syms;
+ num_static_syms += synth_count;
+ make_cleanup (xfree, static_syms);
+ }
+
+ elf_symtab_process (objfile, 0, num_static_syms, static_syms);
+ elf_symtab_process (objfile, 1, num_dyn_syms, dyn_syms);

/* Install any minimal symbols that have been collected as the current
minimal symbols for this objfile. The debug readers below this point

--
Alan Modra
IBM OzLabs - Linux Technology Centre