From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by sourceware.org (Postfix) with ESMTPS id 7A4A4382FE4E for ; Tue, 31 May 2022 22:47:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7A4A4382FE4E Received: by mail-pj1-x102a.google.com with SMTP id e24so304571pjt.0 for ; Tue, 31 May 2022 15:47:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=NyVVyqgKkCjoBIXbY7dahNhFlJA8ptWhzEG2UBMGqRo=; b=qmKst9a6Jttu8aMzfv3LYWAr67ybWodoaAQ2yfi8ek2uVz5zmr2IiimT5YmyUkuCQ7 cc4TlPHpWU9G2lxWHxapMy2IbK4nJuIjSJDnRFn+/xuHzZOvcmS5bB6E27WHtysYGYIj KVF3kDD/WAiANeSmON8CNGzehJgvgpYtbJPlNQsAS4TnJkkC0Xtb87K6XPGnJvhdlaua qfxcefUDzWQreNVyNB7CC2tq3Q9jT6Bn1/gZQiKddXxeSNae+9Sg0XDcbD2S3OFmh2n0 ZS8uLwLz0BjmWPLNf+wPFCzm2M9aTB9MbvarQkMnUnENNkGeIMzKOElixEMJETodXchQ ATDg== X-Gm-Message-State: AOAM530Wx/Ol3ScSAVSOqRWTUdmsRq0u0w1+pDuo7fxzHDvZsA/3h3SP WFX+DgQbJY4swEWIsV1R2FtVDahERWs= X-Google-Smtp-Source: ABdhPJw2rZFXK0Gd4T+SGvmnttq/BNw5V0vixwJf/ApjizXou3YajrK8h/02lr4XdAqdfEpXVhyahQ== X-Received: by 2002:a17:90b:214b:b0:1e2:d777:934f with SMTP id kt11-20020a17090b214b00b001e2d777934fmr16791898pjb.193.1654037257588; Tue, 31 May 2022 15:47:37 -0700 (PDT) Received: from gnu-tgl-3.localdomain ([172.58.88.122]) by smtp.gmail.com with ESMTPSA id w6-20020aa78586000000b0050dc76281fdsm1986499pfn.215.2022.05.31.15.47.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 May 2022 15:47:37 -0700 (PDT) Received: from gnu-tgl-3.. (localhost [IPv6:::1]) by gnu-tgl-3.localdomain (Postfix) with ESMTP id 1E0F1C0322 for ; Tue, 31 May 2022 15:47:34 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Subject: [PATCH] x86: Properly handle IFUNC function pointer reference Date: Tue, 31 May 2022 15:47:34 -0700 Message-Id: <20220531224734.634761-1-hjl.tools@gmail.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3028.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 May 2022 22:47:41 -0000 Update commit 68c4956b1401de70173848a6bdf620cb42fa9358 Author: H.J. Lu Date: Tue Apr 26 09:08:54 2022 -0700 x86: Properly handle function pointer reference to properly handle IFUNC function pointer reference. Since IFUNC symbol value is only known at run-time, set pointer_equality_needed for IFUNC function pointer reference in PDE so that it will be resolved to its PLT entry directly. bfd/ PR ld/29216 * elf32-i386.c (elf_i386_scan_relocs): Set pointer_equality_needed for IFUNC function pointer reference in PDE. * elf64-x86-64.c (elf_x86_64_scan_relocs): Likewise. ld/ PR ld/29216 * testsuite/ld-ifunc/ifunc.exp: Run PR ld/29216 test. * testsuite/ld-ifunc/pr29216.c: New file. --- bfd/elf32-i386.c | 8 ++++- bfd/elf64-x86-64.c | 8 ++++- ld/testsuite/ld-ifunc/ifunc.exp | 9 +++++ ld/testsuite/ld-ifunc/pr29216.c | 62 +++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 ld/testsuite/ld-ifunc/pr29216.c diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index b034154fb97..3bc710096aa 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1778,7 +1778,13 @@ elf_i386_scan_relocs (bfd *abfd, if (r_type == R_386_32 && (sec->flags & SEC_READONLY) == 0) func_pointer_ref = true; - else + + /* IFUNC symbol needs pointer equality in PDE so that + function pointer reference will be resolved to its + PLT entry directly. */ + if (!func_pointer_ref + || (bfd_link_pde (info) + && h->type == STT_GNU_IFUNC)) h->pointer_equality_needed = 1; } diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 6d69d6141ee..eac5e83d7f1 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2221,7 +2221,13 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, && (r_type == R_X86_64_32 || r_type == R_X86_64_32S)))) func_pointer_ref = true; - else + + /* IFUNC symbol needs pointer equality in PDE so that + function pointer reference will be resolved to its + PLT entry directly. */ + if (!func_pointer_ref + || (bfd_link_pde (info) + && h->type == STT_GNU_IFUNC)) h->pointer_equality_needed = 1; } diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp index 1cd8d388b26..fdb65d01f9f 100644 --- a/ld/testsuite/ld-ifunc/ifunc.exp +++ b/ld/testsuite/ld-ifunc/ifunc.exp @@ -714,6 +714,15 @@ run_ld_link_exec_tests [list \ "pr18841cn" \ "pr18841.out" \ ] \ + [list \ + "Run pr29216" \ + "$NOPIE_LDFLAGS" \ + "" \ + { pr29216.c } \ + "pr29216" \ + "pass.out" \ + "-fPIC" \ + ] \ ] # The pr23169 testcase is not valid. In general, you can't call ifunc diff --git a/ld/testsuite/ld-ifunc/pr29216.c b/ld/testsuite/ld-ifunc/pr29216.c new file mode 100644 index 00000000000..5019c723c2b --- /dev/null +++ b/ld/testsuite/ld-ifunc/pr29216.c @@ -0,0 +1,62 @@ +#include + +static int +one (void) +{ + return -30; +} + +int foo (void) __attribute__ ((ifunc ("resolve_foo"))); + +void * +resolve_foo (void) +{ + return (void *) one; +} + +typedef int (*foo_p) (void); + +foo_p foo_ptr = foo; + +foo_p +__attribute__ ((noinline)) +get_foo_p (void) +{ + return foo_ptr; +} + +foo_p +__attribute__ ((noinline)) +get_foo (void) +{ + return foo; +} + +int +main (void) +{ + foo_p p; + + p = get_foo (); + if (p != foo) + __builtin_abort (); + if ((*p) () != -30) + __builtin_abort (); + + p = get_foo_p (); + if (p != foo) + __builtin_abort (); + if ((*p) () != -30) + __builtin_abort (); + + if (foo_ptr != foo) + __builtin_abort (); + if ((*foo_ptr) () != -30) + __builtin_abort (); + if (foo () != -30) + __builtin_abort (); + + printf ("PASS\n"); + + return 0; +} -- 2.36.1