From 4b7d1f7fb496267f5ffb08effd1e18a3424eb9d8 Mon Sep 17 00:00:00 2001 From: Will Newton Date: Mon, 16 Dec 2013 17:45:45 +0000 Subject: [PATCH] gdb/elfread.c: Enable ifunc support on ARM. There are two failures in the gnu-ifunc.exp test on ARM. These are due to the failure to resolve the correct target function when attempting to breakpoint a GNU ifunc resolved function: (gdb) break gnu_ifunc Breakpoint 4 at gnu-indirect-function resolver at 0x2aacb5a2 when gnu_ifunc has been resolved this should actually be: (gdb) break gnu_ifunc Breakpoint 4 at 0x868c There are two reasons for this. The first is that ARM does not have a separate .got.plt section so looking this up will always fail. The second is that the Thumb bit needs to be stripped from the address to allow it to be reliably compared when inserting into the ifunc cache. Tested with no regressions on arm-linux-gnueabihf and x86_64-unknown-linux-gnu. gdb/ChangeLog: 2014-02-10 Will Newton * elfread.c (elf_rel_plt_read): Look for a .got section if looking up .got.plt fails. (elf_gnu_ifunc_resolve_by_got): Call gdbarch_addr_bits_remove on address passed to elf_gnu_ifunc_record_cache. (elf_gnu_ifunc_resolve_addr): Likewise. (elf_gnu_ifunc_resolver_return_stop): Likewise. --- gdb/ChangeLog | 9 +++++++++ gdb/elfread.c | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a53c04bd939..4487b6ba5b6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2014-02-10 Will Newton + + * elfread.c (elf_rel_plt_read): Look for a .got section if + looking up .got.plt fails. + (elf_gnu_ifunc_resolve_by_got): Call gdbarch_addr_bits_remove + on address passed to elf_gnu_ifunc_record_cache. + (elf_gnu_ifunc_resolve_addr): Likewise. + (elf_gnu_ifunc_resolver_return_stop): Likewise. + 2014-02-10 Jose E. Marchesi * sparc-tdep.c (sparc_in_function_epilogue_p): New function. diff --git a/gdb/elfread.c b/gdb/elfread.c index d43a1f74ffd..a610012f519 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -646,7 +646,12 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) got_plt = bfd_get_section_by_name (obfd, ".got.plt"); if (got_plt == NULL) - return; + { + /* For platforms where there is no separate .got.plt. */ + got_plt = bfd_get_section_by_name (obfd, ".got"); + if (got_plt == NULL) + return; + } /* This search algorithm is from _bfd_elf_canonicalize_dynamic_reloc. */ for (relplt = obfd->sections; relplt != NULL; relplt = relplt->next) @@ -899,6 +904,7 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) addr = extract_typed_address (buf, ptr_type); addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target); + addr = gdbarch_addr_bits_remove (gdbarch, addr); if (addr_p) *addr_p = addr; @@ -962,6 +968,7 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) address = value_as_address (address_val); address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, ¤t_target); + address = gdbarch_addr_bits_remove (gdbarch, address); if (name_at_pc) elf_gnu_ifunc_record_cache (name_at_pc, address); @@ -1070,6 +1077,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch, resolved_address, ¤t_target); + resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc); gdb_assert (current_program_space == b->pspace || b->pspace == NULL); elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc); -- 2.30.2