summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2015-10-05 19:30:12 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2015-10-05 19:30:12 +0000
commitae24400424ab8005e3ddc656ba629c11282fa41b (patch)
treedc539223d95c2bd3218040efb5ff40d0f1bfc42a
parent9dbb5586b52206d63b60fdec8ff13c6263809fb6 (diff)
downloadbcm5719-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.cpp17
-rw-r--r--lld/ELF/Target.cpp15
-rw-r--r--lld/ELF/Target.h6
-rw-r--r--lld/ELF/Writer.cpp33
-rw-r--r--lld/test/elf2/relative-dynamic-reloc.s40
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
OpenPOWER on IntegriCloud