gdb/elfread.c: Enable ifunc support on ARM.
authorWill Newton <will.newton@linaro.org>
Mon, 16 Dec 2013 17:45:45 +0000 (17:45 +0000)
committerWill Newton <will.newton@linaro.org>
Mon, 10 Feb 2014 16:45:47 +0000 (16:45 +0000)
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  <will.newton@linaro.org>

* 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
gdb/elfread.c

index a53c04bd939890c97bde4956ac157a913de3a282..4487b6ba5b6d5fcfd39d576066d625a41a28cff4 100644 (file)
@@ -1,3 +1,12 @@
+2014-02-10  Will Newton  <will.newton@linaro.org>
+
+       * 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  <jose.marchesi@oracle.com>
 
        * sparc-tdep.c (sparc_in_function_epilogue_p): New function.
index d43a1f74ffd5dded921e8a83ae6f6063410e21c5..a610012f51919e0a0976951892d4e848cad7dd02 100644 (file)
@@ -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,
                                                 &current_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,
                                                &current_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,
                                                    &current_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);