This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 02/11] Fix breakpoints in ifunc after inferior resolved it (@got.plt symbol creation)
- From: Pedro Alves <palves at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 9 Mar 2018 21:16:03 +0000
- Subject: [PATCH 02/11] Fix breakpoints in ifunc after inferior resolved it (@got.plt symbol creation)
- Authentication-results: sourceware.org; auth=none
- References: <20180309211612.12941-1-palves@redhat.com>
Setting a breakpoint on an ifunc symbol after the ifunc has already
been resolved by the inferior should result in creating a breakpoint
location at the ifunc target. However, that's not what happens today:
(gdb) n
53 i = gnu_ifunc (1); /* break-at-call */
(gdb)
54 assert (i == 2);
(gdb) b gnu_ifunc
Breakpoint 2 at gnu-indirect-function resolver at 0x7ffff7bd36ee
(gdb) info breakpoints
Num Type Disp Enb Address What
2 STT_GNU_IFUNC resolver keep y 0x00007ffff7bd36ee <gnu_ifunc+4>
The problem is that elf_gnu_ifunc_resolve_by_got never manages to
revolve an ifunc target. The reason is that GDB never actually
creates the internal got.plt symbols:
(gdb) p 'gnu_ifunc@got.plt'
No symbol "gnu_ifunc@got.plt" in current context.
and this is because GDB expects that rela.plt has relocations for
.plt, while it actually has relocations for .got.plt:
Relocation section [10] '.rela.plt' for section [22] '.got.plt' at offset 0x570 contains 2 entries:
Offset Type Value Addend Name
0x0000000000601018 X86_64_JUMP_SLOT 000000000000000000 +0 __assert_fail
0x0000000000601020 X86_64_JUMP_SLOT 000000000000000000 +0 gnu_ifunc
With that addressed, we now get:
(gdb) p 'gnu_ifunc@got.plt'
$1 = (<text from jump slot in .got.plt, no debug info>) 0x400753 <final>
And setting a breakpoint on the ifunc finds the ifunc target:
(gdb) b gnu_ifunc
Breakpoint 2 at 0x400753
(gdb) info breakpoints
Num Type Disp Enb Address What
2 breakpoint keep y 0x0000000000400753 <final>
gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <palves@redhat.com>
* elfread.c (elf_rel_plt_read): Look for relocation for .got.plt,
not .plt.
---
gdb/elfread.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 103b2144c3a..454b77e9bdc 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -535,8 +535,7 @@ elf_rel_plt_read (minimal_symbol_reader &reader,
{
bfd *obfd = objfile->obfd;
const struct elf_backend_data *bed = get_elf_backend_data (obfd);
- asection *plt, *relplt, *got_plt;
- int plt_elf_idx;
+ asection *relplt, *got_plt;
bfd_size_type reloc_count, reloc;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
@@ -545,11 +544,6 @@ elf_rel_plt_read (minimal_symbol_reader &reader,
if (objfile->separate_debug_objfile_backlink)
return;
- plt = bfd_get_section_by_name (obfd, ".plt");
- if (plt == NULL)
- return;
- plt_elf_idx = elf_section_data (plt)->this_idx;
-
got_plt = bfd_get_section_by_name (obfd, ".got.plt");
if (got_plt == NULL)
{
@@ -559,9 +553,11 @@ elf_rel_plt_read (minimal_symbol_reader &reader,
return;
}
+ int got_plt_elf_idx = elf_section_data (got_plt)->this_idx;
+
/* This search algorithm is from _bfd_elf_canonicalize_dynamic_reloc. */
for (relplt = obfd->sections; relplt != NULL; relplt = relplt->next)
- if (elf_section_data (relplt)->this_hdr.sh_info == plt_elf_idx
+ if (elf_section_data (relplt)->this_hdr.sh_info == got_plt_elf_idx
&& (elf_section_data (relplt)->this_hdr.sh_type == SHT_REL
|| elf_section_data (relplt)->this_hdr.sh_type == SHT_RELA))
break;
--
2.14.3