diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-10-05 19:30:12 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-10-05 19:30:12 +0000 |
commit | ae24400424ab8005e3ddc656ba629c11282fa41b (patch) | |
tree | dc539223d95c2bd3218040efb5ff40d0f1bfc42a | |
parent | 9dbb5586b52206d63b60fdec8ff13c6263809fb6 (diff) | |
download | bcm5719-llvm-ae24400424ab8005e3ddc656ba629c11282fa41b.tar.gz bcm5719-llvm-ae24400424ab8005e3ddc656ba629c11282fa41b.zip |
Create R_X86_64_RELATIVE when needed.
The dynamic relocation code needs refactoring, but it is probably better
to do it with this test passing.
llvm-svn: 249340
-rw-r--r-- | lld/ELF/OutputSections.cpp | 17 | ||||
-rw-r--r-- | lld/ELF/Target.cpp | 15 | ||||
-rw-r--r-- | lld/ELF/Target.h | 6 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 33 | ||||
-rw-r--r-- | lld/test/elf2/relative-dynamic-reloc.s | 40 |
5 files changed, 92 insertions, 19 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 8992811bfad..28e157aa90e 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -104,16 +104,23 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { uint32_t SymIndex = RI.getSymbol(IsMips64EL); const SymbolBody *Body = C.getFile()->getSymbolBody(SymIndex); uint32_t Type = RI.getType(IsMips64EL); - if (Target->relocNeedsGot(Type, *Body)) { + if (Body && Target->relocNeedsGot(Type, *Body)) { P->r_offset = GotSec.getEntryAddr(*Body); P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Target->getGotReloc(), IsMips64EL); } else { P->r_offset = RI.r_offset + C.getOutputSectionOff() + Out->getVA(); - P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type, IsMips64EL); - if (IsRela) - static_cast<Elf_Rela *>(P)->r_addend = - static_cast<const Elf_Rela &>(RI).r_addend; + if (Body && Body->isShared()) { + P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type, + IsMips64EL); + if (IsRela) + static_cast<Elf_Rela *>(P)->r_addend = + static_cast<const Elf_Rela &>(RI).r_addend; + } else { + P->setSymbolAndType(0, Target->getRelativeReloc(), IsMips64EL); + if (IsRela) + static_cast<Elf_Rela *>(P)->r_addend = P->r_offset; + } } } } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index c4108373d2e..4748bce5283 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -30,6 +30,8 @@ TargetInfo::~TargetInfo() {} bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; } +bool TargetInfo::isRelRelative(uint32_t Type) const { return true; } + X86TargetInfo::X86TargetInfo() { PCRelReloc = R_386_PC32; GotReloc = R_386_GLOB_DAT; @@ -87,6 +89,7 @@ X86_64TargetInfo::X86_64TargetInfo() { PCRelReloc = R_X86_64_PC32; GotReloc = R_X86_64_GLOB_DAT; GotRefReloc = R_X86_64_PC32; + RelativeReloc = R_X86_64_RELATIVE; } void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, @@ -140,6 +143,18 @@ bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { } } +bool X86_64TargetInfo::isRelRelative(uint32_t Type) const { + switch (Type) { + default: + return false; + case R_X86_64_PC64: + case R_X86_64_PC32: + case R_X86_64_PC16: + case R_X86_64_PC8: + return true; + } +} + void X86_64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, uint64_t GotVA) const { diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index a5d6a48b523..6888c349812 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -23,9 +23,11 @@ public: llvm::StringRef getDefaultEntry() const { return DefaultEntry; } unsigned getPCRelReloc() const { return PCRelReloc; } unsigned getGotReloc() const { return GotReloc; } - unsigned getGotRefReloc() const { return GotRefReloc; }; + unsigned getGotRefReloc() const { return GotRefReloc; } + unsigned getRelativeReloc() const { return RelativeReloc; } virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const = 0; + virtual bool isRelRelative(uint32_t Type) const; virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0; virtual bool relocPointsToGot(uint32_t Type) const; virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0; @@ -39,6 +41,7 @@ protected: unsigned PCRelReloc; unsigned GotRefReloc; unsigned GotReloc; + unsigned RelativeReloc; llvm::StringRef DefaultEntry = "_start"; }; @@ -65,6 +68,7 @@ public: void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA, uint64_t GotVA) const override; + bool isRelRelative(uint32_t Type) const override; }; class PPC64TargetInfo final : public TargetInfo { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 30f02eeb5af..66fd48988c4 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -217,22 +217,29 @@ void Writer<ELFT>::scanRelocs( for (const RelType &RI : Rels) { uint32_t SymIndex = RI.getSymbol(IsMips64EL); SymbolBody *Body = File.getSymbolBody(SymIndex); - if (!Body) - continue; uint32_t Type = RI.getType(IsMips64EL); - if (Target->relocNeedsPlt(Type, *Body)) { - if (Body->isInPlt()) + if (Body) { + if (Target->relocNeedsPlt(Type, *Body)) { + if (Body->isInPlt()) + continue; + PltSec.addEntry(Body); + } + if (Target->relocNeedsGot(Type, *Body)) { + if (Body->isInGot()) + continue; + GotSec.addEntry(Body); + Body->setUsedInDynamicReloc(); + RelaDynSec.addReloc({C, RI}); continue; - PltSec.addEntry(Body); - } - if (Target->relocNeedsGot(Type, *Body)) { - if (Body->isInGot()) + } + if (Body->isShared()) { + Body->setUsedInDynamicReloc(); + RelaDynSec.addReloc({C, RI}); continue; - GotSec.addEntry(Body); - } else if (!isa<SharedSymbol<ELFT>>(Body)) - continue; - Body->setUsedInDynamicReloc(); - RelaDynSec.addReloc({C, RI}); + } + } + if (Config->Shared && !Target->isRelRelative(Type)) + RelaDynSec.addReloc({C, RI}); } } diff --git a/lld/test/elf2/relative-dynamic-reloc.s b/lld/test/elf2/relative-dynamic-reloc.s new file mode 100644 index 00000000000..d1e6e66778b --- /dev/null +++ b/lld/test/elf2/relative-dynamic-reloc.s @@ -0,0 +1,40 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: ld.lld2 -shared %t.o -o %t.so +// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s + +// Test that we create R_X86_64_RELATIVE relocations but don't put any +// symbols in the dynamic symbol table. + +// CHECK: Relocations [ +// CHECK-NEXT: Section ({{.*}}) .rela.dyn { +// CHECK-NEXT: [[FOO_ADDR:.*]] R_X86_64_RELATIVE - [[FOO_ADDR]] +// CHECK-NEXT: [[BAR_ADDR:.*]] R_X86_64_RELATIVE - [[BAR_ADDR]] +// CHECK-NEXT: } +// CHECK-NEXT: ] + +// CHECK: Symbols [ +// CHECK: Name: foo +// CHECK-NEXT: Value: [[FOO_ADDR]] +// CHECK: Name: bar +// CHECK-NEXT: Value: [[BAR_ADDR]] +// CHECK: ] + +// CHECK: DynamicSymbols [ +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: @ (0) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Undefined +// CHECK-NEXT: } +// CHECK-NEXT: ] + +foo: + .quad foo + + .hidden bar + .global bar +bar: + .quad bar |