From 70a65b6fdde671ba81d93b87098b719ccf7bfb42 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 19 Jan 2019 18:45:04 +0000 Subject: Vendor import of lld release_80 branch r351543: https://llvm.org/svn/llvm-project/lld/branches/release_80@351543 --- ELF/Arch/X86_64.cpp | 41 +++++++++++---- ELF/Config.h | 1 + ELF/Driver.cpp | 1 + ELF/Options.td | 3 ++ ELF/Relocations.cpp | 2 +- ELF/Thunks.cpp | 10 ++-- docs/ld.lld.1 | 2 + test/ELF/aarch64-gnu-ifunc-address-pie.s | 44 ++++++++++++++++ test/ELF/arm-force-pi-thunk.s | 87 +++++++++++++++++++++++++++++++ test/ELF/tls-opt-x86_64-noplt.s | 88 ++++++++++++++++++++++++++++++++ 10 files changed, 263 insertions(+), 16 deletions(-) create mode 100644 test/ELF/aarch64-gnu-ifunc-address-pie.s create mode 100644 test/ELF/arm-force-pi-thunk.s create mode 100644 test/ELF/tls-opt-x86_64-noplt.s diff --git a/ELF/Arch/X86_64.cpp b/ELF/Arch/X86_64.cpp index 06314155dcc9..a000eeb079d9 100644 --- a/ELF/Arch/X86_64.cpp +++ b/ELF/Arch/X86_64.cpp @@ -264,15 +264,6 @@ void X86_64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, template void X86_64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - // Convert - // leaq bar@tlsld(%rip), %rdi - // callq __tls_get_addr@PLT - // leaq bar@dtpoff(%rax), %rcx - // to - // .word 0x6666 - // .byte 0x66 - // mov %fs:0,%rax - // leaq bar@tpoff(%rax), %rcx if (Type == R_X86_64_DTPOFF64) { write64le(Loc, Val); return; @@ -287,7 +278,37 @@ void X86_64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, 0x66, // .byte 0x66 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); + + if (Loc[4] == 0xe8) { + // Convert + // leaq bar@tlsld(%rip), %rdi # 48 8d 3d + // callq __tls_get_addr@PLT # e8 + // leaq bar@dtpoff(%rax), %rcx + // to + // .word 0x6666 + // .byte 0x66 + // mov %fs:0,%rax + // leaq bar@tpoff(%rax), %rcx + memcpy(Loc - 3, Inst, sizeof(Inst)); + return; + } + + if (Loc[4] == 0xff && Loc[5] == 0x15) { + // Convert + // leaq x@tlsld(%rip),%rdi # 48 8d 3d + // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 + // to + // .long 0x66666666 + // movq %fs:0,%rax + // See "Table 11.9: LD -> LE Code Transition (LP64)" in + // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + Loc[-3] = 0x66; + memcpy(Loc - 2, Inst, sizeof(Inst)); + return; + } + + error(getErrorLocation(Loc - 3) + + "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD"); } template diff --git a/ELF/Config.h b/ELF/Config.h index 8fb760e592eb..60555f188fed 100644 --- a/ELF/Config.h +++ b/ELF/Config.h @@ -159,6 +159,7 @@ struct Configuration { bool OFormatBinary; bool Omagic; bool OptRemarksWithHotness; + bool PicThunk; bool Pie; bool PrintGcSections; bool PrintIcfSections; diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index 13b6119e2dc9..2e2036310fb2 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -1006,6 +1006,7 @@ static void setConfigs(opt::InputArgList &Args) { Config->Endianness = Config->IsLE ? endianness::little : endianness::big; Config->IsMips64EL = (K == ELF64LEKind && M == EM_MIPS); Config->Pic = Config->Pie || Config->Shared; + Config->PicThunk = Args.hasArg(OPT_pic_veneer, Config->Pic); Config->Wordsize = Config->Is64 ? 8 : 4; // ELF defines two different ways to store relocation addends as shown below: diff --git a/ELF/Options.td b/ELF/Options.td index e43a21b923d3..bc203193661b 100644 --- a/ELF/Options.td +++ b/ELF/Options.td @@ -255,6 +255,9 @@ defm use_android_relr_tags: B<"use-android-relr-tags", "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*", "Use SHT_RELR / DT_RELR* tags (default)">; +def pic_veneer: F<"pic-veneer">, + HelpText<"Always generate position independent thunks (veneers)">; + defm pie: B<"pie", "Create a position independent executable", "Do not create a position independent executable (default)">; diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 812468896f0d..9ffe8a9cc72e 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -356,7 +356,7 @@ static bool needsGot(RelExpr Expr) { static bool isRelExpr(RelExpr Expr) { return isRelExprOneOf(Expr); + R_AARCH64_PLT_PAGE_PC, R_RELAX_GOT_PC>(Expr); } // Returns true if a given relocation can be computed at link-time. diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp index 95b57dc0db42..7a31d36b0e90 100644 --- a/ELF/Thunks.cpp +++ b/ELF/Thunks.cpp @@ -722,7 +722,7 @@ Thunk::~Thunk() = default; static Thunk *addThunkAArch64(RelType Type, Symbol &S) { if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) fatal("unrecognized relocation type"); - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); } @@ -739,7 +739,7 @@ static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) { case R_ARM_JUMP24: case R_ARM_CALL: case R_ARM_THM_CALL: - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); } @@ -794,13 +794,13 @@ static Thunk *addThunkArm(RelType Reloc, Symbol &S) { case R_ARM_PLT32: case R_ARM_JUMP24: case R_ARM_CALL: - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); } @@ -820,7 +820,7 @@ static Thunk *addThunkPPC64(RelType Type, Symbol &S) { if (S.isInPlt()) return make(S); - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); diff --git a/docs/ld.lld.1 b/docs/ld.lld.1 index d1ce4a3517f4..889d5feabe4d 100644 --- a/docs/ld.lld.1 +++ b/docs/ld.lld.1 @@ -311,6 +311,8 @@ Write optimization remarks in YAML format to .Ar file . .It Fl -opt-remarks-with-hotness Include hotness information in the optimization remarks file. +.It Fl -pic-veneer +Always generate position independent thunks. .It Fl -pie Create a position independent executable. .It Fl -print-gc-sections diff --git a/test/ELF/aarch64-gnu-ifunc-address-pie.s b/test/ELF/aarch64-gnu-ifunc-address-pie.s new file mode 100644 index 000000000000..3db9070dbd07 --- /dev/null +++ b/test/ELF/aarch64-gnu-ifunc-address-pie.s @@ -0,0 +1,44 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o +# RUN: ld.lld -pie %t.o -o %tout +# RUN: llvm-objdump -D %tout | FileCheck %s +# RUN: llvm-readobj -r %tout | FileCheck %s -check-prefix=CHECK-RELOCS + +# Test that when we take the address of a preemptible ifunc using -fpie, we can +# handle the case when the ifunc is in the same translation unit as the address +# taker. In this case the compiler knows that ifunc is not defined in a shared +# library so it can use a non got generating relative reference. +.text +.globl myfunc +.type myfunc,@gnu_indirect_function +myfunc: + ret + +.text +.globl main +.type main,@function +main: + adrp x8, myfunc + add x8, x8, :lo12: myfunc + ret + +# CHECK: 0000000000010000 myfunc: +# CHECK-NEXT: 10000: c0 03 5f d6 ret +# CHECK: 0000000000010004 main: +# CHECK-NEXT: 10004: 08 00 00 90 adrp x8, #0 +# x8 = 0x10000 +# CHECK-NEXT: 10008: 08 41 00 91 add x8, x8, #16 +# x8 = 0x10010 = .plt for myfunc +# CHECK-NEXT: 1000c: c0 03 5f d6 ret +# CHECK-NEXT: Disassembly of section .plt: +# CHECK-NEXT: 0000000000010010 .plt: +# CHECK-NEXT: 10010: 90 00 00 90 adrp x16, #65536 +# CHECK-NEXT: 10014: 11 02 40 f9 ldr x17, [x16] +# CHECK-NEXT: 10018: 10 02 00 91 add x16, x16, #0 +# CHECK-NEXT: 1001c: 20 02 1f d6 br x17 + +# CHECK-RELOCS: Relocations [ +# CHECK-RELOCS-NEXT: Section {{.*}} .rela.plt { +# CHECK-RELOCS-NEXT: 0x20000 R_AARCH64_IRELATIVE - 0x10000 +# CHECK-RELOCS-NEXT: } +# CHECK-RELOCS-NEXT: ] diff --git a/test/ELF/arm-force-pi-thunk.s b/test/ELF/arm-force-pi-thunk.s new file mode 100644 index 000000000000..2c88de0424ee --- /dev/null +++ b/test/ELF/arm-force-pi-thunk.s @@ -0,0 +1,87 @@ +// REQUIRES: arm +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: . = SIZEOF_HEADERS; \ +// RUN: .text_low : { *(.text_low) *(.text_low2) } \ +// RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \ +// RUN: } " > %t.script +// RUN: ld.lld --pic-veneer --script %t.script %t -o %t2 2>&1 +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s + +// Test that we can force generation of position independent thunks even when +// inputs are not pic. + + .syntax unified + .section .text_low, "ax", %progbits + .thumb + .globl _start +_start: bx lr + .globl low_target + .type low_target, %function +low_target: + bl high_target + bl high_target2 + + .section .text_low2, "ax", %progbits + .thumb + .globl low_target2 + .type low_target2, %function +low_target2: + bl high_target + bl high_target2 + +// CHECK: Disassembly of section .text_low: +// CHECK-NEXT: _start: +// CHECK-NEXT: 94: 70 47 bx lr +// CHECK: low_target: +// CHECK-NEXT: 96: 00 f0 03 f8 bl #6 +// CHECK-NEXT: 9a: 00 f0 07 f8 bl #14 +// CHECK-NEXT: 9e: d4 d4 bmi #-88 +// CHECK: __ThumbV7PILongThunk_high_target: +// CHECK-NEXT: a0: 4f f6 55 7c movw r12, #65365 +// CHECK-NEXT: a4: c0 f2 ff 1c movt r12, #511 +// CHECK-NEXT: a8: fc 44 add r12, pc +// CHECK-NEXT: aa: 60 47 bx r12 +// CHECK: __ThumbV7PILongThunk_high_target2: +// CHECK-NEXT: ac: 4f f6 69 7c movw r12, #65385 +// CHECK-NEXT: b0: c0 f2 ff 1c movt r12, #511 +// CHECK-NEXT: b4: fc 44 add r12, pc +// CHECK-NEXT: b6: 60 47 bx r12 +// CHECK: low_target2: +// CHECK-NEXT: b8: ff f7 f2 ff bl #-28 +// CHECK-NEXT: bc: ff f7 f6 ff bl #-20 + + + .section .text_high, "ax", %progbits + .thumb + .globl high_target + .type high_target, %function +high_target: + bl low_target + bl low_target2 + + .section .text_high2, "ax", %progbits + .thumb + .globl high_target2 + .type high_target2, %function +high_target2: + bl low_target + bl low_target2 + +// CHECK: Disassembly of section .text_high: +// CHECK-NEXT: high_target: +// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4 +// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12 +// CHECK: __ThumbV7PILongThunk_low_target: +// CHECK-NEXT: 2000008: 40 f2 83 0c movw r12, #131 +// CHECK-NEXT: 200000c: cf f6 00 6c movt r12, #65024 +// CHECK-NEXT: 2000010: fc 44 add r12, pc +// CHECK-NEXT: 2000012: 60 47 bx r12 +// CHECK: __ThumbV7PILongThunk_low_target2: +// CHECK-NEXT: 2000014: 40 f2 99 0c movw r12, #153 +// CHECK-NEXT: 2000018: cf f6 00 6c movt r12, #65024 +// CHECK-NEXT: 200001c: fc 44 add r12, pc +// CHECK-NEXT: 200001e: 60 47 bx r12 +// CHECK: high_target2: +// CHECK-NEXT: 2000020: ff f7 f2 ff bl #-28 +// CHECK-NEXT: 2000024: ff f7 f6 ff bl #-20 diff --git a/test/ELF/tls-opt-x86_64-noplt.s b/test/ELF/tls-opt-x86_64-noplt.s new file mode 100644 index 000000000000..69ec49871210 --- /dev/null +++ b/test/ELF/tls-opt-x86_64-noplt.s @@ -0,0 +1,88 @@ +// REQUIRES: x86 + +// Checks whether the TLS optimizations match the cases in Chapter 11 of +// https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o +// RUN: ld.lld -shared %tso.o -o %t.so +// RUN: ld.lld %t.o %t.so -o %t1 +// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOC %s +// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s + +// RELOC: Relocations [ +// RELOC-NEXT: Section {{.*}} .rela.dyn { +// RELOC-NEXT: 0x2020C0 R_X86_64_TPOFF64 tlsshared0 0x0 +// RELOC-NEXT: 0x2020C8 R_X86_64_TPOFF64 tlsshared1 0x0 +// RELOC-NEXT: } +// RELOC-NEXT: ] + +// DISASM: _start: + +// Table 11.5: GD -> IE Code Transition (LP64) +// DISASM-NEXT: 201000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201009: 48 03 05 b0 10 00 00 addq 4272(%rip), %rax +// DISASM-NEXT: 201010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201019: 48 03 05 a8 10 00 00 addq 4264(%rip), %rax + +// Table 11.7: GD -> LE Code Transition (LP64) +// DISASM-NEXT: 201020: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201029: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax +// DISASM-NEXT: 201030: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201039: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax + + +// Table 11.9: LD -> LE Code Transition (LP64) +// DISASM-NEXT: 201040: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 20104d: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax + +.type tls0,@object +.section .tbss,"awT",@nobits +.globl tls0 +.align 4 +tls0: + .long 0 + .size tls0, 4 + +.type tls1,@object +.globl tls1 +.align 4 +tls1: + .long 0 + .size tls1, 4 + +.section .text +.globl _start +_start: + // Table 11.5: GD -> IE Code Transition (LP64) + .byte 0x66 + leaq tlsshared0@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + .byte 0x66 + leaq tlsshared1@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + // Table 11.7: GD -> LE Code Transition (LP64) + .byte 0x66 + leaq tls0@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + .byte 0x66 + leaq tls1@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + // Table 11.9: LD -> LE Code Transition (LP64) + leaq tls0@tlsld(%rip),%rdi + call *__tls_get_addr@GOTPCREL(%rip) + + leaq tls1@tlsld(%rip),%rdi + call *__tls_get_addr@GOTPCREL(%rip) -- cgit v1.2.3