diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-05-05 19:41:49 +0000 | 
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-05-05 19:41:49 +0000 | 
| commit | 66434562e7cdb4671821cbe50ec8c15fe5fff078 (patch) | |
| tree | f22f73e817e8a48ef70e84d26c618001f504a9a8 | |
| parent | 188a7c5f9e3ed9a40740bc0f878fb3b2908c1863 (diff) | |
| download | bcm5719-llvm-66434562e7cdb4671821cbe50ec8c15fe5fff078.tar.gz bcm5719-llvm-66434562e7cdb4671821cbe50ec8c15fe5fff078.zip  | |
Fix copy relocations in pie.
We were creating the copy relocations just fine, but then thinking that
the .bss position could be preempted and creating a dynamic relocation
to it, which would crash at runtime since that memory is read only.
llvm-svn: 268668
| -rw-r--r-- | lld/ELF/Symbols.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 7 | ||||
| -rw-r--r-- | lld/test/ELF/Inputs/copy-rel-pie.s | 9 | ||||
| -rw-r--r-- | lld/test/ELF/copy-rel-pie.s | 44 | ||||
| -rw-r--r-- | lld/test/ELF/mips-got-and-copy.s | 18 | ||||
| -rw-r--r-- | lld/test/ELF/relro.s | 2 | 
6 files changed, 72 insertions, 14 deletions
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 2768f1865a2..798e8c6d17a 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -113,9 +113,11 @@ bool SymbolBody::isPreemptible() const {    if (isLocal())      return false; -  // Shared symbols resolve to the definition in the DSO. +  // Shared symbols resolve to the definition in the DSO. The exceptions are +  // symbols with copy relocations (which resolve to .bss) or preempt plt +  // entries (which resolve to that plt entry).    if (isShared()) -    return true; +    return !NeedsCopyOrPltAddr;    // That's all that can be preempted in a non-DSO.    if (!Config->Shared) diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 6937dd59f88..dfb99d4b8b4 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -606,13 +606,10 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {      if (Offset == (uintX_t)-1)        continue; +    bool Preemptible = Body.isPreemptible();      Expr = adjustExpr(Body, IsWrite, Expr, Type);      if (HasError)        continue; -    bool Preemptible = Body.isPreemptible(); -    if (auto *B = dyn_cast<SharedSymbol<ELFT>>(&Body)) -      if (B->needsCopy()) -        Preemptible = false;      // This relocation does not require got entry, but it is relative to got and      // needs it to be created. Here we request for that. @@ -711,7 +708,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {        continue;      } -    if (Preemptible) { +    if (Body.isPreemptible()) {        // We don't know anything about the finaly symbol. Just ask the dynamic        // linker to handle the relocation for us.        AddDyn({Target->getDynRel(Type), C.OutSec, Offset, false, &Body, Addend}); diff --git a/lld/test/ELF/Inputs/copy-rel-pie.s b/lld/test/ELF/Inputs/copy-rel-pie.s new file mode 100644 index 00000000000..6cd681fcecb --- /dev/null +++ b/lld/test/ELF/Inputs/copy-rel-pie.s @@ -0,0 +1,9 @@ +.global foo +.type foo, @object +.size foo, 4 +foo: +.long 0 + +.global bar +.type bar, @function +bar: diff --git a/lld/test/ELF/copy-rel-pie.s b/lld/test/ELF/copy-rel-pie.s new file mode 100644 index 00000000000..be7d5acaeba --- /dev/null +++ b/lld/test/ELF/copy-rel-pie.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux +// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux +// RUN: ld.lld %t2.o -o %t2.so -shared +// RUN: ld.lld %t.o %t2.so -o %t.exe -pie +// RUN: llvm-readobj -s -r %t.exe | FileCheck %s +// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s + +.global _start +_start: +        call bar +        call foo + +// CHECK:      Name: .plt +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT:   SHF_ALLOC +// CHECK-NEXT:   SHF_EXECINSTR +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x1010 + +// CHECK:      Name: .bss +// CHECK-NEXT: Type: SHT_NOBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT:   SHF_ALLOC +// CHECK-NEXT:   SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x3020 + +// CHECK:      Relocations [ +// CHECK-NEXT:   Section (4) .rela.dyn { +// CHECK-NEXT:     0x3020 R_X86_64_COPY foo 0x0 +// CHECK-NEXT:   } +// CHECK-NEXT:   Section (5) .rela.plt { +// CHECK-NEXT:     0x3018 R_X86_64_JUMP_SLOT bar 0x0 +// CHECK-NEXT:   } +// CHECK-NEXT: ] + +// (0x1010 + 0x10) - 0x1005 = 27 +// 0x3020          - 0x100a = 8214 + +// DISASM:      Disassembly of section .text: +// DISASM-NEXT: _start: +// DISASM-NEXT:     1000:       e8 1b 00 00 00  callq   27 +// DISASM-NEXT:     1005:       e8 16 20 00 00  callq   8214 <foo> diff --git a/lld/test/ELF/mips-got-and-copy.s b/lld/test/ELF/mips-got-and-copy.s index 8501bd623e6..846bc245bc0 100644 --- a/lld/test/ELF/mips-got-and-copy.s +++ b/lld/test/ELF/mips-got-and-copy.s @@ -23,15 +23,21 @@  # CHECK-NEXT:   Reserved entries [  # CHECK:        ]  # CHECK-NEXT:   Local entries [ -# CHECK-NEXT:   ] -# CHECK-NEXT:   Global entries [  # CHECK-NEXT:     Entry { -# CHECK:            Section: .bss -# CHECK-NEXT:       Name: data0 +# CHECK-NEXT:       Address: 0x30008 +# CHECK-NEXT:       Access: -32744 +# CHECK-NEXT:       Initial: 0x40010  # CHECK-NEXT:     } +# CHECK-NEXT:   ] +# CHECK-NEXT:   Global entries [  # CHECK-NEXT:     Entry { -# CHECK:            Section: .bss -# CHECK-NEXT:       Name: data1 +# CHECK-NEXT:       Address: 0x3000C +# CHECK-NEXT:       Access: -32740 +# CHECK-NEXT:       Initial: 0x40010 +# CHECK-NEXT:       Value: 0x40010 +# CHECK-NEXT:       Type: Object (0x1) +# CHECK-NEXT:       Section: .bss (0xC) +# CHECK-NEXT:       Name: data1@ (7)  # CHECK-NEXT:     }  # CHECK-NEXT:   ]  # CHECK-NEXT:   Number of TLS and multi-GOT entries: 0 diff --git a/lld/test/ELF/relro.s b/lld/test/ELF/relro.s index 692d6b271cf..d3554874000 100644 --- a/lld/test/ELF/relro.s +++ b/lld/test/ELF/relro.s @@ -232,7 +232,7 @@  .global _start  _start:    .long bar -  jmp *bar@GOTPCREL(%rip) +  jmp *bar2@GOTPCREL(%rip)  .section .data,"aw"  .quad 0  | 

