diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2018-02-13 07:34:22 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2018-02-13 07:34:36 -0800 |
commit | bd7ab16b4537788ad53521c45469a1bdae84ad4a (patch) | |
tree | 375430fcb7deb06890838718c27b204f405c5fae /gas | |
parent | 80c96350467f23a54546580b3e2b67a65ec65b66 (diff) | |
download | gdb-bd7ab16b4537788ad53521c45469a1bdae84ad4a.zip gdb-bd7ab16b4537788ad53521c45469a1bdae84ad4a.tar.gz gdb-bd7ab16b4537788ad53521c45469a1bdae84ad4a.tar.bz2 |
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.
To compile Linux kernel, this patch:
From: "H.J. Lu" <hjl.tools@gmail.com>
Subject: [PATCH] x86: Treat R_X86_64_PLT32 as R_X86_64_PC32
On i386, there are 2 types of PLTs, PIC and non-PIC. PIE and shared
objects must use PIC PLT. To use PIC PLT, you need to load
_GLOBAL_OFFSET_TABLE_ into EBX first. There is no need for that on
x86-64 since x86-64 uses PC-relative PLT.
On x86-64, for 32-bit PC-relative branches, we can generate PLT32
relocation, instead of PC32 relocation, which can also be used as
a marker for 32-bit PC-relative branches. Linker can always reduce
PLT32 relocation to PC32 if function is defined locally. Local
functions should use PC32 relocation. As far as Linux kernel is
concerned, R_X86_64_PLT32 can be treated the same as R_X86_64_PC32
since Linux kernel doesn't use PLT.
is needed. It is available on hjl/plt32/master branch at
https://github.com/hjl-tools/linux
bfd/
PR gas/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/
PR gas/22791
* 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 gas/22791
* testsuite/ld-x86-64/mpx1c.rd: Updated.
* 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.s: Likewise.
* testsuite/ld-x86-64/pr22791-2b.c: Likewise.
* testsuite/ld-x86-64/pr22791-2c.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run PR ld/22791 tests.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 15 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 49 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/ilp32/reloc64.d | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/ilp32/x86-64-branch.d | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/reloc64.d | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-jump.d | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-mpx-branch-1.d | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-mpx-branch-2.d | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-relax-2.d | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-relax-3.d | 8 |
10 files changed, 85 insertions, 23 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 97b3581..e66e8ce 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,18 @@ +2018-02-13 H.J. Lu <hongjiu.lu@intel.com> + + PR gas/22791 + * 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. + 2018-02-13 Maciej W. Rozycki <macro@mips.com> * testsuite/gas/mips/loongson-3a-2.d: Rename test. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 552c1b8..1a5be1b 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -7023,12 +7023,46 @@ 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; + + /* 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. NB: Symbol with + non-default visibilities are treated as normal global symbol + so that PLT32 relocation can be used as a marker for 32-bit + PC-relative branches. It is useful for linker relaxation. */ + 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 +7130,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 +9358,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 53083f3..f6bc628 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 915dbf3..45ab617 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 a7fd3d6..4cf884d 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 edb34e6..9f7b4b4 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 c070029..d44841e 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 5bb6a57..514c343 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 c124102..c9eba84 100644 --- a/gas/testsuite/gas/i386/x86-64-relax-2.d +++ b/gas/testsuite/gas/i386/x86-64-relax-2.d @@ -10,12 +10,12 @@ 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 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 +[ ]*[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_PLT32 weak_hidden_undef-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1d <foo\+0x1d> 19: R_X86_64_PLT32 weak_hidden_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 22 <hidden_def> 1e: R_X86_64_PLT32 hidden_undef-0x4 0+22 <hidden_def>: [ ]*[a-f0-9]+: c3 retq diff --git a/gas/testsuite/gas/i386/x86-64-relax-3.d b/gas/testsuite/gas/i386/x86-64-relax-3.d index 98fd28d..28ab5dd 100644 --- a/gas/testsuite/gas/i386/x86-64-relax-3.d +++ b/gas/testsuite/gas/i386/x86-64-relax-3.d @@ -11,10 +11,10 @@ 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 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 +[ ]*[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_PLT32 weak_hidden_undef-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1a <foo\+0x1a> 16: R_X86_64_PLT32 weak_hidden_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1f <hidden_def> 1b: R_X86_64_PLT32 hidden_undef-0x4 0+1f <hidden_def>: [ ]*[a-f0-9]+: c3 retq |