This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] x86-64: Treat PC32 relocation with branch as PLT32
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: Cary Coutant <ccoutant at gmail dot com>
- Cc: Florian Weimer <fweimer at redhat dot com>, Binutils <binutils at sourceware dot org>
- Date: Tue, 6 Feb 2018 10:42:12 -0800
- Subject: Re: [PATCH] x86-64: Treat PC32 relocation with branch as PLT32
- Authentication-results: sourceware.org; auth=none
- References: <20180206133536.10841-1-hjl.tools@gmail.com> <ef5667a1-40a7-9f3f-27a7-4487aba3b8e1@redhat.com> <CAJimCsHv+3Cc6_CWeAMe-A-zB=Zpaaa4rWrYSr09UhopFnf2Mw@mail.gmail.com>
On Tue, Feb 6, 2018 at 10:15 AM, Cary Coutant <ccoutant@gmail.com> wrote:
>> How is this safe, considering that R_X86_64_PC32 is also used for jump
>> tables and the like?
>
> Agreed.
>
> If it's a branch instruction that could be treated as PLT32, the
> compiler should emit a PLT32 reloc. We already reduce PLT32 to PC32 in
> the linker when the symbol is fully resolved, so the effect is the
> same, but without the danger of accidentally changing a non-branch.
>
Here is a patch to generate PLT32 reloc in assembler. No compiler change
is needed.
--
H.J.
From dd1f094bd81560d6c7d8c8b1a6fce7a18ee1feee Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Tue, 6 Feb 2018 05:23:04 -0800
Subject: [PATCH] x86-64: Generate branch with PLT32 relocation
Since there is no need to prepare for PLT branch on x86-64, generate
R_X86_64_PLT32, instead of R_X86_64_PC32, if possible, which can be
used as a marker for 32-bit PC-relative branches.
bfd/
PR ld/22791
* elf64-x86-64.c (is_32bit_relative_branch): Removed.
(elf_x86_64_relocate_section): Check PIC relocations in PIE.
Remove is_32bit_relative_branch usage. Disallow PC32 reloc
against protected function in shared object.
gas/
* config/tc-i386.c (need_plt32_p): New function.
(output_jump): Generate BFD_RELOC_X86_64_PLT32 if possible.
(md_estimate_size_before_relax): Likewise.
* testsuite/gas/i386/reloc64.d: Updated.
* testsuite/gas/i386/x86-64-jump.d: Likewise.
* testsuite/gas/i386/x86-64-mpx-branch-1.d: Likewise.
* testsuite/gas/i386/x86-64-mpx-branch-2.d: Likewise.
* testsuite/gas/i386/x86-64-relax-2.d: Likewise.
* testsuite/gas/i386/x86-64-relax-3.d: Likewise.
* testsuite/gas/i386/ilp32/reloc64.d: Likewise.
* testsuite/gas/i386/ilp32/x86-64-branch.d: Likewise.
ld/
PR ld/22791
* testsuite/ld-x86-64/x86-64.exp: Run PR ld/22791 tests.
* testsuite/ld-x86-64/pr22791-1.err: New file.
* testsuite/ld-x86-64/pr22791-1a.c: Likewise.
* testsuite/ld-x86-64/pr22791-1b.s: Likewise.
* testsuite/ld-x86-64/pr22791-2.rd: Likewise.
* testsuite/ld-x86-64/pr22791-2a.c: Likewise.
* testsuite/ld-x86-64/pr22791-2b.c: Likewise.
* testsuite/ld-x86-64/pr22791-2c.c: Likewise.
---
bfd/elf64-x86-64.c | 45 +++++++---------------
gas/config/tc-i386.c | 57 +++++++++++++++++++++++++++-
gas/testsuite/gas/i386/ilp32/reloc64.d | 2 +-
gas/testsuite/gas/i386/ilp32/x86-64-branch.d | 6 +--
gas/testsuite/gas/i386/reloc64.d | 2 +-
gas/testsuite/gas/i386/x86-64-jump.d | 4 +-
gas/testsuite/gas/i386/x86-64-mpx-branch-1.d | 6 +--
gas/testsuite/gas/i386/x86-64-mpx-branch-2.d | 6 +--
gas/testsuite/gas/i386/x86-64-relax-2.d | 4 +-
gas/testsuite/gas/i386/x86-64-relax-3.d | 2 +-
ld/testsuite/ld-x86-64/pr22791-1.err | 2 +
ld/testsuite/ld-x86-64/pr22791-1a.c | 4 ++
ld/testsuite/ld-x86-64/pr22791-1b.s | 6 +++
ld/testsuite/ld-x86-64/pr22791-2.rd | 6 +++
ld/testsuite/ld-x86-64/pr22791-2a.c | 7 ++++
ld/testsuite/ld-x86-64/pr22791-2b.c | 7 ++++
ld/testsuite/ld-x86-64/pr22791-2c.c | 8 ++++
ld/testsuite/ld-x86-64/x86-64.exp | 47 +++++++++++++++++++++++
18 files changed, 172 insertions(+), 49 deletions(-)
create mode 100644 ld/testsuite/ld-x86-64/pr22791-1.err
create mode 100644 ld/testsuite/ld-x86-64/pr22791-1a.c
create mode 100644 ld/testsuite/ld-x86-64/pr22791-1b.s
create mode 100644 ld/testsuite/ld-x86-64/pr22791-2.rd
create mode 100644 ld/testsuite/ld-x86-64/pr22791-2a.c
create mode 100644 ld/testsuite/ld-x86-64/pr22791-2b.c
create mode 100644 ld/testsuite/ld-x86-64/pr22791-2c.c
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index aad9b85296..aa6a47121b 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2307,24 +2307,6 @@ elf_x86_64_tpoff (struct bfd_link_info *info, bfd_vma address)
return address - static_tls_size - htab->tls_sec->vma;
}
-/* Is the instruction before OFFSET in CONTENTS a 32bit relative
- branch? */
-
-static bfd_boolean
-is_32bit_relative_branch (bfd_byte *contents, bfd_vma offset)
-{
- /* Opcode Instruction
- 0xe8 call
- 0xe9 jump
- 0x0f 0x8x conditional jump */
- return ((offset > 0
- && (contents [offset - 1] == 0xe8
- || contents [offset - 1] == 0xe9))
- || (offset > 1
- && contents [offset - 2] == 0x0f
- && (contents [offset - 1] & 0xf0) == 0x80));
-}
-
/* Relocate an x86_64 ELF section. */
static bfd_boolean
@@ -3023,14 +3005,18 @@ do_ifunc_pointer:
case R_X86_64_PC32:
case R_X86_64_PC32_BND:
/* Don't complain about -fPIC if the symbol is undefined when
- building executable unless it is unresolved weak symbol or
- -z nocopyreloc is used. */
+ building executable unless it is unresolved weak symbol,
+ references a dynamic definition in PIE or -z nocopyreloc
+ is used. */
if ((input_section->flags & SEC_ALLOC) != 0
&& (input_section->flags & SEC_READONLY) != 0
&& h != NULL
&& ((bfd_link_executable (info)
&& ((h->root.type == bfd_link_hash_undefweak
&& !resolved_to_zero)
+ || (bfd_link_pie (info)
+ && !h->def_regular
+ && h->def_dynamic)
|| ((info->nocopyreloc
|| (eh->def_protected
&& elf_has_no_copy_on_protected (h->root.u.def.section->owner)))
@@ -3039,26 +3025,21 @@ do_ifunc_pointer:
|| bfd_link_dll (info)))
{
bfd_boolean fail = FALSE;
- bfd_boolean branch
- = ((r_type == R_X86_64_PC32
- || r_type == R_X86_64_PC32_BND)
- && is_32bit_relative_branch (contents, rel->r_offset));
-
if (SYMBOL_REFERENCES_LOCAL_P (info, h))
{
/* Symbol is referenced locally. Make sure it is
- defined locally or for a branch. */
- fail = (!(h->def_regular || ELF_COMMON_DEF_P (h))
- && !branch);
+ defined locally. */
+ fail = !(h->def_regular || ELF_COMMON_DEF_P (h));
}
else if (!(bfd_link_pie (info)
&& (h->needs_copy || eh->needs_copy)))
{
/* Symbol doesn't need copy reloc and isn't referenced
- locally. We only allow branch to symbol with
- non-default visibility. */
- fail = (!branch
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT);
+ locally. Address of protected function may not be
+ reachable at run-time. */
+ fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED
+ && h->type == STT_FUNC));
}
if (fail)
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 32a8b31d30..357e561bfe 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -7023,12 +7023,54 @@ output_branch (void)
frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p);
}
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+/* Return TRUE iff PLT32 relocation should be used for branching to
+ symbol S. */
+
+static bfd_boolean
+need_plt32_p (symbolS *s)
+{
+ /* PLT32 relocation is ELF only. */
+ if (!IS_ELF)
+ return FALSE;
+
+ /* Since there is no need to prepare for PLT branch on x86-64, we
+ can generate R_X86_64_PLT32, instead of R_X86_64_PC32, which can
+ be used as a marker for 32-bit PC-relative branches. */
+ if (!object_64bit)
+ return FALSE;
+
+ /* Global symbol with hidden or internal visibilities doesn't need
+ PLT32 relocation. */
+ switch (ELF_ST_VISIBILITY (S_GET_OTHER (s)))
+ {
+ default:
+ break;
+ case STV_INTERNAL:
+ case STV_HIDDEN:
+ return FALSE;
+ }
+
+ /* Weak or undefined symbol need PLT32 relocation. */
+ if (S_IS_WEAK (s) || !S_IS_DEFINED (s))
+ return TRUE;
+
+ /* Non-global symbol doesn't need PLT32 relocation. */
+ if (! S_IS_EXTERNAL (s))
+ return FALSE;
+
+ /* Other global symbols need PLT32 relocation. */
+ return TRUE;
+}
+#endif
+
static void
output_jump (void)
{
char *p;
int size;
fixS *fixP;
+ bfd_reloc_code_real_type jump_reloc = i.reloc[0];
if (i.tm.opcode_modifier.jumpbyte)
{
@@ -7096,8 +7138,17 @@ output_jump (void)
abort ();
}
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ if (size == 4
+ && jump_reloc == NO_RELOC
+ && need_plt32_p (i.op[0].disps->X_add_symbol))
+ jump_reloc = BFD_RELOC_X86_64_PLT32;
+#endif
+
+ jump_reloc = reloc (size, 1, 1, jump_reloc);
+
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
- i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
+ i.op[0].disps, 1, jump_reloc);
/* All jumps handled here are signed, but don't use a signed limit
check for 32 and 16 bit jumps as we want to allow wrap around at
@@ -9315,6 +9366,10 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
reloc_type = (enum bfd_reloc_code_real) fragP->fr_var;
else if (size == 2)
reloc_type = BFD_RELOC_16_PCREL;
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ else if (need_plt32_p (fragP->fr_symbol))
+ reloc_type = BFD_RELOC_X86_64_PLT32;
+#endif
else
reloc_type = BFD_RELOC_32_PCREL;
diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.d b/gas/testsuite/gas/i386/ilp32/reloc64.d
index 53083f31d2..f6bc628448 100644
--- a/gas/testsuite/gas/i386/ilp32/reloc64.d
+++ b/gas/testsuite/gas/i386/ilp32/reloc64.d
@@ -16,7 +16,7 @@ Disassembly of section \.text:
.*[ ]+R_X86_64_PC8[ ]+xtrn\+0x0*1
.*[ ]+R_X86_64_PC32[ ]+xtrn-0x0*4
.*[ ]+R_X86_64_PC32[ ]+xtrn-0x0*4
-.*[ ]+R_X86_64_PC32[ ]+xtrn-0x0*4
+.*[ ]+R_X86_64_PLT32[ ]+xtrn-0x0*4
.*[ ]+R_X86_64_PC8[ ]+xtrn-0x0*1
.*[ ]+R_X86_64_GOT32[ ]+xtrn
.*[ ]+R_X86_64_GOT32[ ]+xtrn
diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-branch.d b/gas/testsuite/gas/i386/ilp32/x86-64-branch.d
index 915dbf3f1c..45ab6178b9 100644
--- a/gas/testsuite/gas/i386/ilp32/x86-64-branch.d
+++ b/gas/testsuite/gas/i386/ilp32/x86-64-branch.d
@@ -20,9 +20,9 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 66 ff 20 data16 jmpq \*\(%rax\)
[ ]*[a-f0-9]+: e8 00 00 00 00 callq 0x1f 1b: R_X86_64_PC32 \*ABS\*\+0x10003c
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 0x24 20: R_X86_64_PC32 \*ABS\*\+0x10003c
-[ ]*[a-f0-9]+: 66 e8 00 00 00 00 data16 callq 0x2a 26: R_X86_64_PC32 foo-0x4
-[ ]*[a-f0-9]+: 66 e9 00 00 00 00 data16 jmpq 0x30 2c: R_X86_64_PC32 foo-0x4
-[ ]*[a-f0-9]+: 66 0f 82 00 00 00 00 data16 jb 0x37 33: R_X86_64_PC32 foo-0x4
+[ ]*[a-f0-9]+: 66 e8 00 00 00 00 data16 callq 0x2a 26: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: 66 e9 00 00 00 00 data16 jmpq 0x30 2c: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: 66 0f 82 00 00 00 00 data16 jb 0x37 33: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: ff d0 callq \*%rax
[ ]*[a-f0-9]+: ff d0 callq \*%rax
[ ]*[a-f0-9]+: 66 ff d0 data16 callq \*%rax
diff --git a/gas/testsuite/gas/i386/reloc64.d b/gas/testsuite/gas/i386/reloc64.d
index a7fd3d6a3d..4cf884dc7b 100644
--- a/gas/testsuite/gas/i386/reloc64.d
+++ b/gas/testsuite/gas/i386/reloc64.d
@@ -18,7 +18,7 @@ Disassembly of section \.text:
.*[ ]+R_X86_64_PC8[ ]+xtrn\+0x0*1
.*[ ]+R_X86_64_PC32[ ]+xtrn-0x0*4
.*[ ]+R_X86_64_PC32[ ]+xtrn-0x0*4
-.*[ ]+R_X86_64_PC32[ ]+xtrn-0x0*4
+.*[ ]+R_X86_64_PLT32[ ]+xtrn-0x0*4
.*[ ]+R_X86_64_PC8[ ]+xtrn-0x0*1
.*[ ]+R_X86_64_GOT64[ ]+xtrn
.*[ ]+R_X86_64_GOT32[ ]+xtrn
diff --git a/gas/testsuite/gas/i386/x86-64-jump.d b/gas/testsuite/gas/i386/x86-64-jump.d
index edb34e6aa8..9f7b4b4848 100644
--- a/gas/testsuite/gas/i386/x86-64-jump.d
+++ b/gas/testsuite/gas/i386/x86-64-jump.d
@@ -8,7 +8,7 @@ Disassembly of section .text:
0+ <.text>:
[ ]*[a-f0-9]+: eb fe jmp (0x0|0 <.text>)
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 0x7 3: R_X86_64_PC32 xxx-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 0x7 3: R_X86_64_PLT32 xxx-0x4
[ ]*[a-f0-9]+: ff 24 25 00 00 00 00 jmpq \*0x0 a: R_X86_64_32S xxx
[ ]*[a-f0-9]+: ff e7 jmpq \*%rdi
[ ]*[a-f0-9]+: ff 27 jmpq \*\(%rdi\)
@@ -17,7 +17,7 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: ff 2c 25 00 00 00 00 ljmp \*0x0 24: R_X86_64_32S xxx
[ ]*[a-f0-9]+: 66 ff 2c 25 00 00 00 00 ljmpw \*0x0 2c: R_X86_64_32S xxx
[ ]*[a-f0-9]+: e8 cb ff ff ff callq 0x0
-[ ]*[a-f0-9]+: e8 00 00 00 00 callq 0x3a 36: R_X86_64_PC32 xxx-0x4
+[ ]*[a-f0-9]+: e8 00 00 00 00 callq 0x3a 36: R_X86_64_PLT32 xxx-0x4
[ ]*[a-f0-9]+: ff 14 25 00 00 00 00 callq \*0x0 3d: R_X86_64_32S xxx
[ ]*[a-f0-9]+: ff d7 callq \*%rdi
[ ]*[a-f0-9]+: ff 17 callq \*\(%rdi\)
diff --git a/gas/testsuite/gas/i386/x86-64-mpx-branch-1.d b/gas/testsuite/gas/i386/x86-64-mpx-branch-1.d
index c07002911c..d44841e745 100644
--- a/gas/testsuite/gas/i386/x86-64-mpx-branch-1.d
+++ b/gas/testsuite/gas/i386/x86-64-mpx-branch-1.d
@@ -20,9 +20,9 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 24 <foo2>
0+24 <foo2>:
-[ ]*[a-f0-9]+: f2 e9 00 00 00 00 bnd jmpq 2a <foo2\+0x6> 26: R_X86_64_PC32 foo-0x4
-[ ]*[a-f0-9]+: f2 0f 82 00 00 00 00 bnd jb 31 <foo2\+0xd> 2d: R_X86_64_PC32 foo-0x4
-[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 37 <foo2\+0x13> 33: R_X86_64_PC32 foo-0x4
+[ ]*[a-f0-9]+: f2 e9 00 00 00 00 bnd jmpq 2a <foo2\+0x6> 26: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: f2 0f 82 00 00 00 00 bnd jb 31 <foo2\+0xd> 2d: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 37 <foo2\+0x13> 33: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: f2 e9 00 00 00 00 bnd jmpq 3d <foo2\+0x19> 39: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: f2 0f 82 00 00 00 00 bnd jb 44 <foo2\+0x20> 40: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 4a <foo2\+0x26> 46: R_X86_64_PLT32 foo-0x4
diff --git a/gas/testsuite/gas/i386/x86-64-mpx-branch-2.d b/gas/testsuite/gas/i386/x86-64-mpx-branch-2.d
index 5bb6a57c1e..514c34363e 100644
--- a/gas/testsuite/gas/i386/x86-64-mpx-branch-2.d
+++ b/gas/testsuite/gas/i386/x86-64-mpx-branch-2.d
@@ -20,9 +20,9 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 24 <foo2>
0+24 <foo2>:
-[ ]*[a-f0-9]+: f2 e9 00 00 00 00 bnd jmpq 2a <foo2\+0x6> 26: R_X86_64_PC32 foo-0x4
-[ ]*[a-f0-9]+: f2 0f 82 00 00 00 00 bnd jb 31 <foo2\+0xd> 2d: R_X86_64_PC32 foo-0x4
-[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 37 <foo2\+0x13> 33: R_X86_64_PC32 foo-0x4
+[ ]*[a-f0-9]+: f2 e9 00 00 00 00 bnd jmpq 2a <foo2\+0x6> 26: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: f2 0f 82 00 00 00 00 bnd jb 31 <foo2\+0xd> 2d: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 37 <foo2\+0x13> 33: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: f2 e9 00 00 00 00 bnd jmpq 3d <foo2\+0x19> 39: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: f2 0f 82 00 00 00 00 bnd jb 44 <foo2\+0x20> 40: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: f2 e8 00 00 00 00 bnd callq 4a <foo2\+0x26> 46: R_X86_64_PLT32 foo-0x4
diff --git a/gas/testsuite/gas/i386/x86-64-relax-2.d b/gas/testsuite/gas/i386/x86-64-relax-2.d
index c124102982..a65d4b2132 100644
--- a/gas/testsuite/gas/i386/x86-64-relax-2.d
+++ b/gas/testsuite/gas/i386/x86-64-relax-2.d
@@ -10,9 +10,9 @@ Disassembly of section .text:
0+ <foo>:
[ ]*[a-f0-9]+: eb 24 jmp 26 <local>
[ ]*[a-f0-9]+: eb 1e jmp 22 <hidden_def>
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 9 <foo\+0x9> 5: R_X86_64_PC32 global_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 9 <foo\+0x9> 5: R_X86_64_PLT32 global_def-0x4
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq e <foo\+0xe> a: R_X86_64_PLT32 global_def-0x4
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 13 <foo\+0x13> f: R_X86_64_PC32 weak_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 13 <foo\+0x13> f: R_X86_64_PLT32 weak_def-0x4
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 18 <foo\+0x18> 14: R_X86_64_PC32 weak_hidden_undef-0x4
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1d <foo\+0x1d> 19: R_X86_64_PC32 weak_hidden_def-0x4
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 22 <hidden_def> 1e: R_X86_64_PC32 hidden_undef-0x4
diff --git a/gas/testsuite/gas/i386/x86-64-relax-3.d b/gas/testsuite/gas/i386/x86-64-relax-3.d
index 98fd28dd11..b87a19ce53 100644
--- a/gas/testsuite/gas/i386/x86-64-relax-3.d
+++ b/gas/testsuite/gas/i386/x86-64-relax-3.d
@@ -11,7 +11,7 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: eb 1b jmp 1f <hidden_def>
[ ]*[a-f0-9]+: eb 1b jmp 21 <global_def>
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq b <foo\+0xb> 7: R_X86_64_PLT32 global_def-0x4
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 10 <foo\+0x10> c: R_X86_64_PC32 weak_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 10 <foo\+0x10> c: R_X86_64_PLT32 weak_def-0x4
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 15 <foo\+0x15> 11: R_X86_64_PC32 weak_hidden_undef-0x4
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1a <foo\+0x1a> 16: R_X86_64_PC32 weak_hidden_def-0x4
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1f <hidden_def> 1b: R_X86_64_PC32 hidden_undef-0x4
diff --git a/ld/testsuite/ld-x86-64/pr22791-1.err b/ld/testsuite/ld-x86-64/pr22791-1.err
new file mode 100644
index 0000000000..5500fa55ce
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22791-1.err
@@ -0,0 +1,2 @@
+.*relocation R_X86_64_PC32 against symbol `foo' can not be used when making a PIE object; recompile with -fPIC
+#...
diff --git a/ld/testsuite/ld-x86-64/pr22791-1a.c b/ld/testsuite/ld-x86-64/pr22791-1a.c
new file mode 100644
index 0000000000..cd0130cacd
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22791-1a.c
@@ -0,0 +1,4 @@
+void
+foo (void)
+{
+}
diff --git a/ld/testsuite/ld-x86-64/pr22791-1b.s b/ld/testsuite/ld-x86-64/pr22791-1b.s
new file mode 100644
index 0000000000..9751db49aa
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22791-1b.s
@@ -0,0 +1,6 @@
+ .text
+ .globl main
+ .type main, @function
+main:
+ movl foo(%rip), %eax
+ .size main, .-main
diff --git a/ld/testsuite/ld-x86-64/pr22791-2.rd b/ld/testsuite/ld-x86-64/pr22791-2.rd
new file mode 100644
index 0000000000..70deb30d84
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22791-2.rd
@@ -0,0 +1,6 @@
+#failif
+#...
+.*\(TEXTREL\).*
+#...
+[0-9a-f ]+R_X86_64_NONE.*
+#...
diff --git a/ld/testsuite/ld-x86-64/pr22791-2a.c b/ld/testsuite/ld-x86-64/pr22791-2a.c
new file mode 100644
index 0000000000..8b23ec8f2b
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22791-2a.c
@@ -0,0 +1,7 @@
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
diff --git a/ld/testsuite/ld-x86-64/pr22791-2b.c b/ld/testsuite/ld-x86-64/pr22791-2b.c
new file mode 100644
index 0000000000..79ef27c085
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22791-2b.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+bar (void)
+{
+ puts ("PASS");
+}
diff --git a/ld/testsuite/ld-x86-64/pr22791-2c.c b/ld/testsuite/ld-x86-64/pr22791-2c.c
new file mode 100644
index 0000000000..f1cb6b492b
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22791-2c.c
@@ -0,0 +1,8 @@
+extern void foo (void);
+
+int
+main (void)
+{
+ foo ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index af3afcc2c7..8dac1c4dfa 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1152,6 +1152,44 @@ if { [isnative] && [which $CC] != 0 } {
{readelf -lW pr22393-3b.rd}} \
"pr22393-3-static" \
] \
+ [list \
+ "Build pr22791-1.so" \
+ "-shared" \
+ "-fPIC" \
+ { pr22791-1a.c } \
+ {} \
+ "pr22791-1.so" \
+ ] \
+ [list \
+ "Build pr22791-1" \
+ "-pie -Wl,--no-as-needed tmpdir/pr22791-1.so" \
+ "$NOPIE_CFLAGS" \
+ { pr22791-1b.s } \
+ {{error_output "pr22791-1.err"}} \
+ "pr22791-1" \
+ ] \
+ [list \
+ "Build pr22791-2a.o" \
+ "" \
+ "-fno-PIC $NOPIE_CFLAGS" \
+ { pr22791-2a.c } \
+ ] \
+ [list \
+ "Build pr22791-2.so" \
+ "-shared tmpdir/pr22791-2a.o" \
+ "-fPIC" \
+ { pr22791-2b.c } \
+ {{readelf -drW pr22791-2.rd}} \
+ "pr22791-2.so" \
+ ] \
+ [list \
+ "Build pr22791-2" \
+ "-pie -Wl,--no-as-needed tmpdir/pr22791-2.so" \
+ "$NOPIE_CFLAGS" \
+ { pr22791-2c.c } \
+ {{readelf -drW pr22791-2.rd}} \
+ "pr22791-2" \
+ ] \
]
if {[istarget "x86_64-*-linux*-gnux32"]} {
@@ -1477,6 +1515,15 @@ if { [isnative] && [which $CC] != 0 } {
"pr22393-3-static" \
"pass.out" \
] \
+ [list \
+ "Run pr22791-2" \
+ "-pie -Wl,--no-as-needed tmpdir/pr22791-2.so" \
+ "" \
+ { pr22791-2c.c } \
+ "pr22791-2" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
]
# Run-time tests which require working ifunc attribute support.
--
2.14.3