diff options
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/elfread.c | 13 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/gnu-ifunc-lib.c | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/gnu-ifunc.c | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/gnu-ifunc.exp | 15 |
6 files changed, 46 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e7cc712..b585914 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2016-09-09 Andreas Arnez <arnez@linux.vnet.ibm.com> + + * elfread.c (auxv.h): New include. + (elf_gnu_ifunc_resolve_addr): Pass HWCAP to ifunc resolver. + 2016-09-08 Tom Tromey <tom@tromey.com> * remote.c (remote_notif_stop_ack, remote_wait_as) diff --git a/gdb/elfread.c b/gdb/elfread.c index e90466b..84355cf 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -46,6 +46,7 @@ #include "gdb_bfd.h" #include "build-id.h" #include "location.h" +#include "auxv.h" extern void _initialize_elfread (void); @@ -860,6 +861,8 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) CORE_ADDR start_at_pc, address; struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; struct value *function, *address_val; + CORE_ADDR hwcap = 0; + struct value *hwcap_val; /* Try first any non-intrusive methods without an inferior call. */ @@ -875,10 +878,14 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) function = allocate_value (func_func_type); set_value_address (function, pc); - /* STT_GNU_IFUNC resolver functions have no parameters. FUNCTION is the - function entry address. ADDRESS may be a function descriptor. */ + /* STT_GNU_IFUNC resolver functions usually receive the HWCAP vector as + parameter. FUNCTION is the function entry address. ADDRESS may be a + function descriptor. */ - address_val = call_function_by_hand (function, 0, NULL); + target_auxv_search (¤t_target, AT_HWCAP, &hwcap); + hwcap_val = value_from_longest (builtin_type (gdbarch) + ->builtin_unsigned_long, hwcap); + address_val = call_function_by_hand (function, 1, &hwcap_val); address = value_as_address (address_val); address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, ¤t_target); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 958ec27..783e30f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2016-09-09 Andreas Arnez <arnez@linux.vnet.ibm.com> + + * gdb.base/gnu-ifunc-lib.c (resolver_hwcap): New external + variable declaration. + (gnu_ifunc): Add parameter hwcap. Store it in resolver_hwcap. + * gdb.base/gnu-ifunc.c (resolver_hwcap): New global variable. + * gdb.base/gnu-ifunc.exp: Add test to verify that the resolver + received HWCAP as its argument. + 2016-09-06 Pedro Alves <palves@redhat.com> * gdb.base/new-ui-pending-input.c: New file. diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-lib.c b/gdb/testsuite/gdb.base/gnu-ifunc-lib.c index 8a55f60..0c0aeef 100644 --- a/gdb/testsuite/gdb.base/gnu-ifunc-lib.c +++ b/gdb/testsuite/gdb.base/gnu-ifunc-lib.c @@ -16,6 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ extern volatile int gnu_ifunc_initialized; +extern volatile unsigned long resolver_hwcap; extern int init_stub (int arg); extern int final (int arg); @@ -24,8 +25,9 @@ typedef int (*final_t) (int arg); asm (".type gnu_ifunc, %gnu_indirect_function"); final_t -gnu_ifunc (void) +gnu_ifunc (unsigned long hwcap) { + resolver_hwcap = hwcap; if (! gnu_ifunc_initialized) return init_stub; else diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.c b/gdb/testsuite/gdb.base/gnu-ifunc.c index c68866e..77dea30 100644 --- a/gdb/testsuite/gdb.base/gnu-ifunc.c +++ b/gdb/testsuite/gdb.base/gnu-ifunc.c @@ -35,6 +35,10 @@ final (int arg) volatile int gnu_ifunc_initialized; +/* This stores the argument received by the ifunc resolver. */ + +volatile unsigned long resolver_hwcap = -1; + static void gnu_ifunc_pre (void) { diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.exp b/gdb/testsuite/gdb.base/gnu-ifunc.exp index 097e48a9..3b2775b 100644 --- a/gdb/testsuite/gdb.base/gnu-ifunc.exp +++ b/gdb/testsuite/gdb.base/gnu-ifunc.exp @@ -76,6 +76,21 @@ gdb_continue_to_breakpoint "break-at-call" ".*break-at-call.*" gdb_test "p gnu_ifunc (3)" " = 4" +# Test that the resolver received its argument. + +set actual_hwcap "0x0" +set test "info auxv" +gdb_test_multiple $test $test { + -re "\r\n\\d+\\s+AT_HWCAP\[^\r\n\]+($hex)\r\n.*$gdb_prompt $" { + set actual_hwcap $expect_out(1,string) + } + -re ".*$gdb_prompt $" { + pass "$test (no HWCAP)" + } +} + +gdb_test "p/x resolver_hwcap" "= $actual_hwcap" "resolver received HWCAP" + # Test GDB will skip the gnu_ifunc resolver on first call. gdb_test "step" "\r\nfinal .*" |