diff options
author | Pedro Alves <palves@redhat.com> | 2018-04-26 13:01:27 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2018-04-26 13:09:40 +0100 |
commit | bfa5bd2ab31a8abb23cb442d51fe6c3836028880 (patch) | |
tree | a1432300e4bc11c81a1b2251c897d1f42dddae36 /bfd/ChangeLog | |
parent | f50776aad58a1df6b8f7f2a7d25a3b10aa074f7b (diff) | |
download | gdb-bfa5bd2ab31a8abb23cb442d51fe6c3836028880.zip gdb-bfa5bd2ab31a8abb23cb442d51fe6c3836028880.tar.gz gdb-bfa5bd2ab31a8abb23cb442d51fe6c3836028880.tar.bz2 |
PPC64: always make synthetic .text symbols for GNU ifunc symbols
If you create an ifunc using GCC's __attribute__ ifunc, like:
extern int gnu_ifunc (int arg);
static int gnu_ifunc_target (int arg) { return 0; }
__typeof (gnu_ifunc) *gnu_ifunc_resolver (unsigned long hwcap) { return gnu_ifunc_target; }
__typeof (gnu_ifunc) gnu_ifunc __attribute__ ((ifunc ("gnu_ifunc_resolver")));
then you end up with two (function descriptor) symbols, one for the
ifunc itself, and another for the resolver:
(...)
12: 0000000000020060 104 FUNC GLOBAL DEFAULT 18 gnu_ifunc_resolver
(...)
16: 0000000000020060 104 GNU_IFUNC GLOBAL DEFAULT 18 gnu_ifunc
(...)
Both ifunc and resolver symbols have the same address/value, so
ppc64_elf_get_synthetic_symtab only creates a synthetic text symbol
for one of them. In the case above, it ends up being created for the
resolver, only:
(gdb) maint print msymbols
(...)
[ 7] t 0x980 .frame_dummy section .text
[ 8] T 0x9e4 .gnu_ifunc_resolver section .text
[ 9] T 0xa58 __glink_PLTresolve section .text
(...)
GDB needs to know when a program stepped into an ifunc resolver, so
that it can know whether to step past the resolver into the target
function without the user noticing. The way GDB does it is my
checking whether the current PC points to an ifunc symbol (since
resolver and ifunc have the same address by design).
The problem is then that ppc64_elf_get_synthetic_symtab never creates
the synchetic symbol for the ifunc, so GDB stops stepping at the
resolver (in a test added by the following patch):
(gdb) step
gnu_ifunc_resolver (hwcap=21) at gdb/testsuite/gdb.base/gnu-ifunc-lib.c:33
33 {
(gdb) FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=1: resolver_debug=1: final_debug=0: step
After this commit, we get:
[ 8] i 0x9e4 .gnu_ifunc section .text
[ 9] T 0x9e4 .gnu_ifunc_resolver section .text
And stepping an ifunc call takes to the final function:
(gdb) step
0x00000000100009e8 in .final ()
(gdb) PASS: gdb.base/gnu-ifunc.exp: resolver_attr=1: resolver_debug=1: final_debug=0: step
An alternative to touching bfd I considered was for GDB to check
whether there's an ifunc data symbol / function descriptor that points
to the current PC, whenever the program stops, but discarded it
because we'd have to do a linear scan over .opd over an over to find a
matching function descriptor for the current PC. At that point I
considered caching that info, but quickly dismissed it as then that
has no advantage (memory or performance) over just creating the
synthetic ifunc text symbol in the first place.
I ran the binutils and ld testsuites on PPC64 ELFv1 (machine gcc110 on
the GCC compile farm), and saw no regressions. This commit is part of
a GDB patch series that includes GDB tests that fail without this fix.
bfd/ChangeLog:
2018-04-26 Pedro Alves <palves@redhat.com>
* elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Don't consider
ifunc and non-ifunc symbols duplicates.
Diffstat (limited to 'bfd/ChangeLog')
-rw-r--r-- | bfd/ChangeLog | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 311e211..fcfd913 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2018-04-26 Pedro Alves <palves@redhat.com> + + * elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Don't consider + ifunc and non-ifunc symbols duplicates. + 2018-04-25 Christophe Lyon <christophe.lyon@st.com> Mickaël Guêné <mickael.guene@st.com> |