This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch 3/3 ppc64] the fix
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 4 Apr 2011 13:15:20 +0200
- Subject: [patch 3/3 ppc64] the fix
Hi,
the fix.
Thanks,
Jan
gdb/
2011-04-04 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix convert_code_addr_to_desc_addr for ppc64 files after eu-strip.
* arch-utils.c (default_elf_synthetic_msyms_prep): New function.
* arch-utils.h (default_elf_synthetic_msyms_prep): New declaration.
* elfread.c (elf_symfile_read): New variables gdbarch, synth_abfd.
Call gdbarch_elf_synthetic_msyms_prep when appropriate. Set
synth_abfd. Pass SYNTH_ABFD to bfd_get_synthetic_symtab.
* gdbarch.c: Regenerated.
* gdbarch.h: Regenerated.
* gdbarch.sh (elf_synthetic_msyms_prep): New method.
* ppc-sysv-tdep.c <HAVE_ELF> (ppc64_sysv_translate_debuginfo_syms)
<HAVE_ELF> (ppc64_sysv_elf_synthetic_msyms_prep)
<!HAVE_ELF> (ppc64_sysv_elf_synthetic_msyms_prep): New functions.
* ppc-tdep.h (ppc64_sysv_elf_synthetic_msyms_prep): New declaration.
* rs6000-tdep.c (rs6000_gdbarch_init): Install it on ppc64.
* symfile.c (build_section_addr_info_from_bfd): Set also
saved_sectindex.
(symbol_file_add_separate): Set sap->separate_debug_objfile_backlink.
* symfile.h (struct section_addr_info): New field
separate_debug_objfile_backlink.
(struct other_sections): New field saved_sectindex.
gdb/testsuite/
2011-04-04 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix convert_code_addr_to_desc_addr for ppc64 files after eu-strip.
* gdb.base/eu-strip-infcall.c: New file.
* gdb.base/eu-strip-infcall.exp: New file.
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -786,6 +786,17 @@ default_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
gdbarch_breakpoint_from_pc (gdbarch, pcptr, kindptr);
}
+int
+default_elf_synthetic_msyms_prep (struct section_addr_info *addrs,
+ struct objfile *objfile,
+ asymbol **symbol_table, long symcount,
+ asymbol **dyn_symbol_table,
+ long dynsymcount)
+{
+ /* Symbols have not been reassociated. */
+ return 0;
+}
+
/* */
/* -Wmissing-prototypes */
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -167,4 +167,11 @@ extern void default_remote_breakpoint_from_pc (struct gdbarch *,
extern const char *default_auto_charset (void);
extern const char *default_auto_wide_charset (void);
+extern int default_elf_synthetic_msyms_prep (struct section_addr_info *addrs,
+ struct objfile *objfile,
+ asymbol **symbol_table,
+ long symcount,
+ asymbol **dyn_symbol_table,
+ long dynsymcount);
+
#endif
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1231,7 +1231,8 @@ static void
elf_symfile_read (struct objfile *objfile, int symfile_flags,
struct section_addr_info *addrs)
{
- bfd *abfd = objfile->obfd;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ bfd *synth_abfd, *abfd = objfile->obfd;
struct elfinfo ei;
struct cleanup *back_to;
long symcount = 0, dynsymcount = 0, synthcount, storage_needed;
@@ -1302,9 +1303,21 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags,
elf_rel_plt_read (objfile, dyn_symbol_table);
}
+ /* This OBJFILE - if it is a separate debug info file - may not have enough
+ information for bfd_get_synthetic_symtab. Associate OBJFILE's ELF
+ symbols with backlinked BFD. */
+
+ if (addrs && addrs->separate_debug_objfile_backlink
+ && gdbarch_elf_synthetic_msyms_prep (gdbarch, addrs, objfile,
+ symbol_table, symcount,
+ dyn_symbol_table, dynsymcount))
+ synth_abfd = addrs->separate_debug_objfile_backlink->obfd;
+ else
+ synth_abfd = abfd;
+
/* Add synthetic symbols - for instance, names for any PLT entries. */
- synthcount = bfd_get_synthetic_symtab (abfd, symcount, symbol_table,
+ synthcount = bfd_get_synthetic_symtab (synth_abfd, symcount, symbol_table,
dynsymcount, dyn_symbol_table,
&synthsyms);
if (synthcount > 0)
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -815,6 +815,13 @@ v:const char *:solib_symbols_extension:::::::pstring (gdbarch->solib_symbols_ext
# is, absolute paths include a drive name, and the backslash is
# considered a directory separator.
v:int:has_dos_based_file_system:::0:0::0
+
+# Separate debug info OBJFILE may not have enough information for
+# bfd_get_synthetic_symtab. Associate OBJFILE's ELF symbols with backlinked
+# BFD which is described by ADDRS. Adjust the ELF symbols. SYMBOL_TABLE
+# array has SYMCOUNT entries, DYN_SYMBOL_TABLE has DYNSYMCOUNT entries.
+# Return true if the ELF symbols have been reassociated, false otherwise.
+f:int:elf_synthetic_msyms_prep:struct section_addr_info *addrs, struct objfile *objfile, asymbol **symbol_table, long symcount, asymbol **dyn_symbol_table, long dynsymcount:addrs, objfile, symbol_table, symcount, dyn_symbol_table, dynsymcount:default_elf_synthetic_msyms_prep:default_elf_synthetic_msyms_prep::0
EOF
}
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -1971,3 +1971,116 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
return RETURN_VALUE_STRUCT_CONVENTION;
}
+#ifdef HAVE_ELF
+
+/* Relocate ASYM_COUNT of ASYMS to a new BFD. Mapping of ASYMS's BFD sections
+ to the new BFD sections is in SYM_TO_NEW_ABFD_SECT. SYM_TO_NEW_ABFD_SECT
+ size is bfd_count_sections (asyms[0]->the_bfd). All ASYMS have the same
+ THE_BFD. */
+
+static void
+ppc64_sysv_translate_debuginfo_syms (asymbol **asyms, long asym_count,
+ asection **sym_to_new_abfd_sect)
+{
+ for (; asym_count-- > 0; asyms++)
+ {
+ asymbol *asym = *asyms;
+ asection *new_asect = sym_to_new_abfd_sect[asym->section->index];
+
+ if (new_asect == NULL)
+ continue;
+
+ asym->section = new_asect;
+ asym->the_bfd = new_asect->owner;
+ }
+}
+
+/* An implementation for gdbarch_elf_synthetic_msyms_prep_p.
+
+ Contrary to binutils --strip-debug/--only-keep-debug the strip command from
+ elfutils (eu-strip) moves even the .symtab section into the .debug file.
+
+ bfd_get_synthetic_symtab on ppc64 for each function descriptor ELF symbol
+ 'name' creates a new BSF_SYNTHETIC ELF symbol '.name' with its code
+ address. But with eu-strip files bfd_get_synthetic_symtab fails to read
+ the code address from .opd while it reads the .symtab section from
+ a separate debug info file as the .opd section is SHT_NOBITS there.
+
+ This function patches the SECTION and THE_BFD fields of separate debug info
+ ELF symbols to associate them with the backlinked original BFD file where
+ the .opd section content is valid.
+
+ Note the confusion (unrelated) partial/full symbols (typically from DWARF)
+ are named 'name' but they refer to their code address (and not their
+ address of a function descriptor). This dot/non-dot naming convention does
+ not match the dot/non-dot convention of minimal/ELF symbols. */
+
+int
+ppc64_sysv_elf_synthetic_msyms_prep (struct section_addr_info *addrs,
+ struct objfile *objfile,
+ asymbol **symbol_table, long symcount,
+ asymbol **dyn_symbol_table,
+ long dynsymcount)
+{
+ struct objfile *backlink = addrs->separate_debug_objfile_backlink;
+ int i;
+ asection *asect, **asectp;
+
+ /* Table of BACKLINK->obfd sections indexed by their asect->index. */
+ asection **backlink_sect_table;
+
+ /* Map sections in ABFD to their matching sections from BACKLINK->obfd.
+ If no such section exists the element is NULL. */
+ asection **abfd_to_backlink_sect;
+
+ /* Fill in backlink_sect_table. */
+ backlink_sect_table = alloca (sizeof (*backlink_sect_table)
+ * backlink->num_sections);
+ asectp = backlink_sect_table;
+ for (asect = backlink->obfd->sections; asect; asect = asect->next)
+ *asectp++ = asect;
+
+ /* Fill in abfd_to_backlink_sect. */
+ abfd_to_backlink_sect = alloca (sizeof (*abfd_to_backlink_sect)
+ * objfile->num_sections);
+ memset (abfd_to_backlink_sect, 0, (sizeof (*abfd_to_backlink_sect)
+ * objfile->num_sections));
+ for (i = 0; i < addrs->num_sections && addrs->other[i].name != 0; i++)
+ {
+ struct other_sections *addrs_sect = &addrs->other[i];
+
+ gdb_assert (addrs_sect->saved_sectindex < backlink->num_sections);
+
+ if (addrs_sect->sectindex != -1)
+ {
+ gdb_assert (addrs_sect->sectindex < objfile->num_sections);
+ abfd_to_backlink_sect[addrs_sect->sectindex]
+ = backlink_sect_table[addrs_sect->saved_sectindex];
+ }
+ }
+
+ ppc64_sysv_translate_debuginfo_syms (symbol_table, symcount,
+ abfd_to_backlink_sect);
+ ppc64_sysv_translate_debuginfo_syms (dyn_symbol_table, dynsymcount,
+ abfd_to_backlink_sect);
+
+ /* Symbols have been reassociated. */
+ return 1;
+}
+
+#else /* !HAVE_ELF */
+
+/* An no-operation implementation for gdbarch_elf_synthetic_msyms_prep_p. */
+
+int
+ppc64_sysv_elf_synthetic_msyms_prep (struct section_addr_info *addrs,
+ struct objfile *objfile,
+ asymbol **symbol_table, long symcount,
+ asymbol **dyn_symbol_table,
+ long dynsymcount)
+{
+ /* Symbols have not been reassociated. */
+ return 0;
+}
+
+#endif /* !HAVE_ELF */
--- a/gdb/ppc-tdep.h
+++ b/gdb/ppc-tdep.h
@@ -60,6 +60,7 @@ enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarc
struct regcache *regcache,
gdb_byte *readbuf,
const gdb_byte *writebuf);
+gdbarch_elf_synthetic_msyms_prep_ftype ppc64_sysv_elf_synthetic_msyms_prep;
/* From rs6000-tdep.c... */
int altivec_register_p (struct gdbarch *gdbarch, int regno);
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -4099,6 +4099,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
+ if (wordsize == 8)
+ set_gdbarch_elf_synthetic_msyms_prep (gdbarch,
+ ppc64_sysv_elf_synthetic_msyms_prep);
+
/* Hook in ABI-specific overrides, if they have been registered. */
info.target_desc = tdesc;
info.tdep_info = (void *) tdesc_data;
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -336,6 +336,7 @@ build_section_addr_info_from_bfd (bfd *abfd)
sap->other[i].addr = bfd_get_section_vma (abfd, sec);
sap->other[i].name = xstrdup (bfd_get_section_name (abfd, sec));
sap->other[i].sectindex = sec->index;
+ sap->other[i].saved_sectindex = sap->other[i].sectindex;
i++;
}
return sap;
@@ -1186,6 +1187,7 @@ symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile)
because sections of BFD may not match sections of OBJFILE and because
vma may have been modified by tools such as prelink. */
sap = build_section_addr_info_from_objfile (objfile);
+ sap->separate_debug_objfile_backlink = objfile;
my_cleanup = make_cleanup_free_section_addr_info (sap);
new_objfile = symbol_file_add_with_addrs_or_offsets
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -80,6 +80,11 @@ struct section_addr_info
/* The number of sections for which address information is
available. */
size_t num_sections;
+
+ /* If this array was created for adding a separate debug info file this
+ pointer contains the stripped binary file link. */
+ struct objfile *separate_debug_objfile_backlink;
+
/* Sections whose names are file format dependent. */
struct other_sections
{
@@ -88,6 +93,10 @@ struct section_addr_info
/* SECTINDEX must be valid for associated BFD or set to -1. */
int sectindex;
+
+ /* Copy of SECTINDEX from the original BFD this struct was created for.
+ SECTINDEX may get for example remapped for a different BFD later. */
+ int saved_sectindex;
} other[1];
};
--- /dev/null
+++ b/gdb/testsuite/gdb.base/eu-strip-infcall.c
@@ -0,0 +1,34 @@
+/* Copyright 2011 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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, see <http://www.gnu.org/licenses/>. */
+
+int
+func (void)
+{
+ return 1;
+}
+
+int
+callfunc (int (*funcp) (void))
+{
+ return funcp () * 2;
+}
+
+int
+main (void)
+{
+ return callfunc (func);
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/eu-strip-infcall.exp
@@ -0,0 +1,41 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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, see <http://www.gnu.org/licenses/>.
+
+# This testfile requires eu-strip - elfutils strip command. It moves even the
+# .symtab section into the separate debug info file. The tested feature is
+# passing a function descriptor as a function address, the FAIL was
+# reproducible only on ppc64 ELF platforms.
+
+set testfile eu-strip-infcall
+set binfile ${objdir}/${subdir}/${testfile}
+
+if {[build_executable ${testfile}.exp $testfile] == -1} {
+ return -1
+}
+
+set test "eu-strip"
+set status [remote_exec build "eu-strip -f ${binfile}.debug $binfile"]
+if {[lindex $status 0] != 0} {
+ untested ${testfile}.exp
+ return 0
+}
+
+clean_restart $testfile
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_test "p callfunc (func)" " = 2" "infcall"