From patchwork Wed Aug 31 11:49:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Arnez X-Patchwork-Id: 15114 Received: (qmail 36439 invoked by alias); 31 Aug 2016 11:50:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 36428 invoked by uid 89); 31 Aug 2016 11:50:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.1 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW, RCVD_IN_SEMBACKSCATTER autolearn=no version=3.3.2 spammy=8606, distinction, s390x, H*Ad:U*uweigand X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 31 Aug 2016 11:50:06 +0000 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u7VBhnUm120878 for ; Wed, 31 Aug 2016 07:50:04 -0400 Received: from e06smtp15.uk.ibm.com (e06smtp15.uk.ibm.com [195.75.94.111]) by mx0a-001b2d01.pphosted.com with ESMTP id 255mksn937-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 31 Aug 2016 07:50:04 -0400 Received: from localhost by e06smtp15.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 31 Aug 2016 12:50:01 +0100 Received: from d06dlp01.portsmouth.uk.ibm.com (9.149.20.13) by e06smtp15.uk.ibm.com (192.168.101.145) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 31 Aug 2016 12:49:59 +0100 X-IBM-Helo: d06dlp01.portsmouth.uk.ibm.com X-IBM-MailFrom: arnez@linux.vnet.ibm.com X-IBM-RcptTo: gdb-patches@sourceware.org Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 5BAE817D8063 for ; Wed, 31 Aug 2016 12:51:48 +0100 (BST) Received: from d06av06.portsmouth.uk.ibm.com (d06av06.portsmouth.uk.ibm.com [9.149.37.217]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u7VBnxpY65011782 for ; Wed, 31 Aug 2016 11:49:59 GMT Received: from d06av06.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u7VBnvPP029908 for ; Wed, 31 Aug 2016 07:49:58 -0400 Received: from oc1027705133.ibm.com (dyn-9-152-212-133.boeblingen.de.ibm.com [9.152.212.133]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u7VBnvq0029886 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 31 Aug 2016 07:49:57 -0400 From: Andreas Arnez To: gdb-patches@sourceware.org Cc: Ulrich Weigand Subject: [PATCH] Pass HWCAP to ifunc resolver Date: Wed, 31 Aug 2016 13:49:57 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16083111-0020-0000-0000-0000023B13B6 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16083111-0021-0000-0000-00003DD8B09C Message-Id: X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-08-31_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1608310149 X-IsSubscribed: yes On various GNU Elf architectures, including AArch64, ARM, s390/s390x, ppc32/64, and sparc32/64, the dynamic loader passes HWCAP as a parameter to each ifunc resolver. Currently there is an open glibc Bugzilla that requests this to be generalized to all architectures: https://sourceware.org/bugzilla/show_bug.cgi?id=19766 And various ifunc resolvers already rely on receiving HWCAP. Currently GDB always calls an ifunc resolver without any arguments; thus the resolver may receive garbage, and based on that, the resolver may decide to return a function that is not suited for the given platform. This patch always passes HWCAP to ifunc resolvers, even on systems where the dynamic loader currently behaves otherwise. The rationale is that (1) the dynamic loader may get adjusted on those systems as well in the future; (2) passing an unused argument should not cause a problem with existing resolvers; and (3) the logic is much simpler without such a distinction. gdb/ChangeLog: * elfread.c (auxv.h): New include. (elf_gnu_ifunc_resolve_addr): Pass HWCAP to ifunc resolver. gdb/testsuite/ChangeLog: * 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. --- gdb/elfread.c | 13 ++++++++++--- gdb/testsuite/gdb.base/gnu-ifunc-lib.c | 4 +++- gdb/testsuite/gdb.base/gnu-ifunc.c | 4 ++++ gdb/testsuite/gdb.base/gnu-ifunc.exp | 15 +++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) 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/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 . */ 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 .*"