[lld] r268350 - ELF: Forbid all relative relocations to absolute symbols in PIC, except for weak undefined.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Mon May 2 18:21:09 PDT 2016
Author: pcc
Date: Mon May 2 20:21:08 2016
New Revision: 268350
URL: http://llvm.org/viewvc/llvm-project?rev=268350&view=rev
Log:
ELF: Forbid all relative relocations to absolute symbols in PIC, except for weak undefined.
Weak undefined symbols resolve to the image base. This is a little strange,
but it allows us to link function calls to such symbols. Normally such a
call will be guarded with a comparison, which will load a zero from the GOT.
There's one example of such a function call in crti.o in Linux's CRT.
As part of this change, I also needed to make the synthetic start and end
symbols image base relative in the case where their sections were empty,
so that PC-relative references to those symbols would continue to work.
Differential Revision: http://reviews.llvm.org/D19844
Added:
lld/trunk/test/ELF/relocation-relative-absolute.s
lld/trunk/test/ELF/relocation-relative-synthetic.s
lld/trunk/test/ELF/relocation-relative-weak.s
Modified:
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=268350&r1=268349&r2=268350&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon May 2 20:21:08 2016
@@ -1496,7 +1496,7 @@ const OutputSectionBase<ELFT> *
SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
switch (Sym->kind()) {
case SymbolBody::DefinedSyntheticKind:
- return &cast<DefinedSynthetic<ELFT>>(Sym)->Section;
+ return cast<DefinedSynthetic<ELFT>>(Sym)->Section;
case SymbolBody::DefinedRegularKind: {
auto &D = cast<DefinedRegular<ELFT>>(*Sym);
if (D.Section)
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=268350&r1=268349&r2=268350&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Mon May 2 20:21:08 2016
@@ -388,7 +388,7 @@ Symbol *SymbolTable<ELFT>::addRegular(St
template <typename ELFT>
Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
- OutputSectionBase<ELFT> &Section,
+ OutputSectionBase<ELFT> *Section,
uintX_t Value) {
Symbol *S;
bool WasInserted;
Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=268350&r1=268349&r2=268350&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Mon May 2 20:21:08 2016
@@ -64,7 +64,7 @@ public:
Symbol *addRegular(StringRef Name, const Elf_Sym &Sym,
InputSectionBase<ELFT> *Section);
Symbol *addRegular(StringRef Name, uint8_t Binding, uint8_t StOther);
- Symbol *addSynthetic(StringRef N, OutputSectionBase<ELFT> &Section,
+ Symbol *addSynthetic(StringRef N, OutputSectionBase<ELFT> *Section,
uintX_t Value);
void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
const typename ELFT::Verdef *Verdef);
Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=268350&r1=268349&r2=268350&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Mon May 2 20:21:08 2016
@@ -36,9 +36,12 @@ static typename ELFT::uint getSymVA(cons
switch (Body.kind()) {
case SymbolBody::DefinedSyntheticKind: {
auto &D = cast<DefinedSynthetic<ELFT>>(Body);
+ const OutputSectionBase<ELFT> *Sec = D.Section;
+ if (!Sec)
+ return D.Value;
if (D.Value == DefinedSynthetic<ELFT>::SectionEnd)
- return D.Section.getVA() + D.Section.getSize();
- return D.Section.getVA() + D.Value;
+ return Sec->getVA() + Sec->getSize();
+ return Sec->getVA() + D.Value;
}
case SymbolBody::DefinedRegularKind: {
auto &D = cast<DefinedRegular<ELFT>>(Body);
@@ -208,7 +211,7 @@ Undefined::Undefined(uint32_t NameOffset
template <typename ELFT>
DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
- OutputSectionBase<ELFT> &Section)
+ OutputSectionBase<ELFT> *Section)
: Defined(SymbolBody::DefinedSyntheticKind, N, STV_HIDDEN, 0 /* Type */),
Value(Value), Section(Section) {}
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=268350&r1=268349&r2=268350&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Mon May 2 20:21:08 2016
@@ -237,11 +237,12 @@ InputSectionBase<ELFT> *DefinedRegular<E
// The difference from the regular symbol is that DefinedSynthetic symbols
// don't belong to any input files or sections. Thus, its constructor
// takes an output section to calculate output VA, etc.
+// If Section is null, this symbol is relative to the image base.
template <class ELFT> class DefinedSynthetic : public Defined {
public:
typedef typename ELFT::uint uintX_t;
DefinedSynthetic(StringRef N, uintX_t Value,
- OutputSectionBase<ELFT> &Section);
+ OutputSectionBase<ELFT> *Section);
static bool classof(const SymbolBody *S) {
return S->kind() == SymbolBody::DefinedSyntheticKind;
@@ -252,7 +253,7 @@ public:
static const uintX_t SectionEnd = uintX_t(-1);
uintX_t Value;
- const OutputSectionBase<ELFT> &Section;
+ const OutputSectionBase<ELFT> *Section;
};
class Undefined : public SymbolBody {
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=268350&r1=268349&r2=268350&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon May 2 20:21:08 2016
@@ -454,6 +454,20 @@ static bool isRelRelative(RelExpr E, uin
if (!AbsVal && RelE)
return true;
+ // Relative relocation to an absolute value. This is normally unrepresentable,
+ // but if the relocation refers to a weak undefined symbol, we allow it to
+ // resolve to the image base. This is a little strange, but it allows us to
+ // link function calls to such symbols. Normally such a call will be guarded
+ // with a comparison, which will load a zero from the GOT.
+ if (AbsVal && RelE) {
+ if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
+ return true;
+ StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
+ error("relocation " + S + " cannot refer to absolute symbol " +
+ Body.getName());
+ return true;
+ }
+
return Target->usesOnlyLowPageBits(Type);
}
@@ -1067,7 +1081,7 @@ bool Writer<ELFT>::isDiscarded(InputSect
template <class ELFT>
static Symbol *addOptionalSynthetic(SymbolTable<ELFT> &Table, StringRef Name,
- OutputSectionBase<ELFT> &Sec,
+ OutputSectionBase<ELFT> *Sec,
typename ELFT::uint Val) {
if (!Table.find(Name))
return nullptr;
@@ -1084,10 +1098,10 @@ template <class ELFT> void Writer<ELFT>:
if (isOutputDynamic() || !Out<ELFT>::RelaPlt)
return;
StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
- addOptionalSynthetic(Symtab, S, *Out<ELFT>::RelaPlt, 0);
+ addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt, 0);
S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";
- addOptionalSynthetic(Symtab, S, *Out<ELFT>::RelaPlt,
+ addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt,
DefinedSynthetic<ELFT>::SectionEnd);
}
@@ -1189,18 +1203,18 @@ template <class ELFT> void Writer<ELFT>:
// so that it points to an absolute address which is relative to GOT.
// See "Global Data Symbols" in Chapter 6 in the following document:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- Symtab.addSynthetic("_gp", *Out<ELFT>::Got, MipsGPOffset);
+ Symtab.addSynthetic("_gp", Out<ELFT>::Got, MipsGPOffset);
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
// start of function and 'gp' pointer into GOT.
ElfSym<ELFT>::MipsGpDisp =
- addOptionalSynthetic(Symtab, "_gp_disp", *Out<ELFT>::Got, MipsGPOffset)
+ addOptionalSynthetic(Symtab, "_gp_disp", Out<ELFT>::Got, MipsGPOffset)
->body();
// The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
// pointer. This symbol is used in the code generated by .cpload pseudo-op
// in case of using -mno-shared option.
// https://sourceware.org/ml/binutils/2004-12/msg00094.html
- addOptionalSynthetic(Symtab, "__gnu_local_gp", *Out<ELFT>::Got,
+ addOptionalSynthetic(Symtab, "__gnu_local_gp", Out<ELFT>::Got,
MipsGPOffset);
}
@@ -1327,7 +1341,7 @@ template <class ELFT> void Writer<ELFT>:
// Even the author of gold doesn't remember why gold behaves that way.
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
if (isOutputDynamic())
- Symtab.addSynthetic("_DYNAMIC", *Out<ELFT>::Dynamic, 0);
+ Symtab.addSynthetic("_DYNAMIC", Out<ELFT>::Dynamic, 0);
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
@@ -1487,11 +1501,13 @@ template <class ELFT> void Writer<ELFT>:
auto Define = [&](StringRef Start, StringRef End,
OutputSectionBase<ELFT> *OS) {
if (OS) {
- this->Symtab.addSynthetic(Start, *OS, 0);
- this->Symtab.addSynthetic(End, *OS, DefinedSynthetic<ELFT>::SectionEnd);
+ this->Symtab.addSynthetic(Start, OS, 0);
+ this->Symtab.addSynthetic(End, OS, DefinedSynthetic<ELFT>::SectionEnd);
} else {
- this->Symtab.addIgnored(Start);
- this->Symtab.addIgnored(End);
+ addOptionalSynthetic(this->Symtab, Start,
+ (OutputSectionBase<ELFT> *)nullptr, 0);
+ addOptionalSynthetic(this->Symtab, End,
+ (OutputSectionBase<ELFT> *)nullptr, 0);
}
};
@@ -1518,10 +1534,10 @@ void Writer<ELFT>::addStartStopSymbols(O
StringRef Stop = Saver.save("__stop_" + S);
if (SymbolBody *B = Symtab.find(Start))
if (B->isUndefined())
- Symtab.addSynthetic(Start, *Sec, 0);
+ Symtab.addSynthetic(Start, Sec, 0);
if (SymbolBody *B = Symtab.find(Stop))
if (B->isUndefined())
- Symtab.addSynthetic(Stop, *Sec, DefinedSynthetic<ELFT>::SectionEnd);
+ Symtab.addSynthetic(Stop, Sec, DefinedSynthetic<ELFT>::SectionEnd);
}
template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) {
Added: lld/trunk/test/ELF/relocation-relative-absolute.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocation-relative-absolute.s?rev=268350&view=auto
==============================================================================
--- lld/trunk/test/ELF/relocation-relative-absolute.s (added)
+++ lld/trunk/test/ELF/relocation-relative-absolute.s Mon May 2 20:21:08 2016
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s
+
+.globl _start
+_start:
+
+# CHECK: relocation R_X86_64_PLT32 cannot refer to absolute symbol answer
+call answer at PLT
+
+.globl answer
+answer = 42
Added: lld/trunk/test/ELF/relocation-relative-synthetic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocation-relative-synthetic.s?rev=268350&view=auto
==============================================================================
--- lld/trunk/test/ELF/relocation-relative-synthetic.s (added)
+++ lld/trunk/test/ELF/relocation-relative-synthetic.s Mon May 2 20:21:08 2016
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t -pie
+# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
+
+# CHECK: Dynamic Relocations {
+# CHECK-NEXT: }
+
+.globl _start
+_start:
+call __init_array_start at PLT
Added: lld/trunk/test/ELF/relocation-relative-weak.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocation-relative-weak.s?rev=268350&view=auto
==============================================================================
--- lld/trunk/test/ELF/relocation-relative-weak.s (added)
+++ lld/trunk/test/ELF/relocation-relative-weak.s Mon May 2 20:21:08 2016
@@ -0,0 +1,14 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t -pie
+# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
+
+# CHECK: Dynamic Relocations {
+# CHECK-NEXT: }
+
+.globl _start
+_start:
+
+.globl w
+.weak w
+call w at PLT
More information about the llvm-commits
mailing list