[lld] r287090 - [ELF] Add Section() to expression object
Eugene Leviant via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 16 01:49:39 PST 2016
Author: evgeny777
Date: Wed Nov 16 03:49:39 2016
New Revision: 287090
URL: http://llvm.org/viewvc/llvm-project?rev=287090&view=rev
Log:
[ELF] Add Section() to expression object
This allows making symbols containing ADDR(section) synthetic,
and defining synthetic symbols outside SECTIONS block.
Differential revision: https://reviews.llvm.org/D25441
Modified:
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/LinkerScript.h
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/test/ELF/linkerscript/symbols-synthetic.s
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=287090&r1=287089&r2=287090&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Nov 16 03:49:39 2016
@@ -75,9 +75,17 @@ template <class ELFT> static void addReg
}
template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
+ // If we have SECTIONS block then output sections haven't been created yet.
+ const OutputSectionBase *Sec =
+ ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section();
Symbol *Sym = Symtab<ELFT>::X->addSynthetic(
- Cmd->Name, nullptr, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
+ Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
Cmd->Sym = Sym->body();
+
+ // If we already know section then we can calculate symbol value immediately.
+ if (Sec)
+ cast<DefinedSynthetic<ELFT>>(Cmd->Sym)->Value =
+ Cmd->Expression(0) - Sec->Addr;
}
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
@@ -373,14 +381,14 @@ void LinkerScript<ELFT>::createSections(
// is an offset from beginning of section and regular
// symbols whose value is absolute.
template <class ELFT>
-static void assignSectionSymbol(SymbolAssignment *Cmd, OutputSectionBase *Sec,
+static void assignSectionSymbol(SymbolAssignment *Cmd,
typename ELFT::uint Value) {
if (!Cmd->Sym)
return;
if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
- Body->Section = Sec;
- Body->Value = Cmd->Expression(Value) - Sec->Addr;
+ Body->Section = Cmd->Expression.Section();
+ Body->Value = Cmd->Expression(Value) - Body->Section->Addr;
return;
}
auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
@@ -452,7 +460,7 @@ template <class ELFT> void LinkerScript<
CurOutSec->Size = Dot - CurOutSec->Addr;
return;
}
- assignSectionSymbol<ELFT>(AssignCmd, CurOutSec, Dot);
+ assignSectionSymbol<ELFT>(AssignCmd, Dot);
return;
}
@@ -667,8 +675,7 @@ void LinkerScript<ELFT>::assignAddresses
if (Cmd->Name == ".") {
Dot = Cmd->Expression(Dot);
} else if (Cmd->Sym) {
- assignSectionSymbol<ELFT>(
- Cmd, CurOutSec ? CurOutSec : (*OutputSections)[0], Dot);
+ assignSectionSymbol<ELFT>(Cmd, Dot);
}
continue;
}
@@ -849,39 +856,14 @@ template <class ELFT> bool LinkerScript<
}
template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) {
- for (OutputSectionBase *Sec : *OutputSections)
- if (Sec->getName() == Name)
- return Sec->Addr;
- error("undefined section " + Name);
- return 0;
-}
-
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionLMA(StringRef Name) {
- for (OutputSectionBase *Sec : *OutputSections)
- if (Sec->getName() == Name)
- return Sec->getLMA();
- error("undefined section " + Name);
- return 0;
-}
-
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {
- for (OutputSectionBase *Sec : *OutputSections)
- if (Sec->getName() == Name)
- return Sec->Size;
- error("undefined section " + Name);
- return 0;
-}
+const OutputSectionBase *LinkerScript<ELFT>::getOutputSection(StringRef Name) {
+ static OutputSectionBase FakeSec("", 0, 0);
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionAlign(StringRef Name) {
for (OutputSectionBase *Sec : *OutputSections)
if (Sec->getName() == Name)
- return Sec->Addralign;
+ return Sec;
error("undefined section " + Name);
- return 0;
+ return &FakeSec;
}
template <class ELFT> uint64_t LinkerScript<ELFT>::getHeaderSize() {
@@ -905,6 +887,26 @@ template <class ELFT> bool LinkerScript<
return DR && !DR->Section;
}
+// Gets section symbol belongs to. Symbol "." doesn't belong to any
+// specific section but isn't absolute at the same time, so we try
+// to find suitable section for it as well.
+template <class ELFT>
+const OutputSectionBase *LinkerScript<ELFT>::getSymbolSection(StringRef S) {
+ SymbolBody *Sym = Symtab<ELFT>::X->find(S);
+ if (!Sym) {
+ if (OutputSections->empty())
+ return nullptr;
+ return CurOutSec ? CurOutSec : (*OutputSections)[0];
+ }
+
+ if (auto *DR = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym))
+ return DR->Section ? DR->Section->OutSec : nullptr;
+ if (auto *DS = dyn_cast_or_null<DefinedSynthetic<ELFT>>(Sym))
+ return DS->Section;
+
+ return nullptr;
+}
+
// Returns indices of ELF headers containing specific section, identified
// by Name. Each index is a zero based number of ELF header listed within
// PHDRS {} script block.
@@ -1511,7 +1513,11 @@ static Expr combine(StringRef Op, Expr L
}
if (Op == "+")
return {[=](uint64_t Dot) { return L(Dot) + R(Dot); },
- [=]() { return L.IsAbsolute() && R.IsAbsolute(); }};
+ [=]() { return L.IsAbsolute() && R.IsAbsolute(); },
+ [=]() {
+ const OutputSectionBase *S = L.Section();
+ return S ? S : R.Section();
+ }};
if (Op == "-")
return [=](uint64_t Dot) { return L(Dot) - R(Dot); };
if (Op == "<<")
@@ -1650,12 +1656,16 @@ Expr ScriptParser::readPrimary() {
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
if (Tok == "ADDR") {
StringRef Name = readParenLiteral();
- return
- [=](uint64_t Dot) { return ScriptBase->getOutputSectionAddress(Name); };
+ return {
+ [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Addr; },
+ [=]() { return false; },
+ [=]() { return ScriptBase->getOutputSection(Name); }};
}
if (Tok == "LOADADDR") {
StringRef Name = readParenLiteral();
- return [=](uint64_t Dot) { return ScriptBase->getOutputSectionLMA(Name); };
+ return [=](uint64_t Dot) {
+ return ScriptBase->getOutputSection(Name)->getLMA();
+ };
}
if (Tok == "ASSERT")
return readAssert();
@@ -1708,12 +1718,14 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "SIZEOF") {
StringRef Name = readParenLiteral();
- return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); };
+ return
+ [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Size; };
}
if (Tok == "ALIGNOF") {
StringRef Name = readParenLiteral();
- return
- [=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); };
+ return [=](uint64_t Dot) {
+ return ScriptBase->getOutputSection(Name)->Addralign;
+ };
}
if (Tok == "SIZEOF_HEADERS")
return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); };
@@ -1727,7 +1739,8 @@ Expr ScriptParser::readPrimary() {
if (Tok != "." && !isValidCIdentifier(Tok))
setError("malformed number: " + Tok);
return {[=](uint64_t Dot) { return getSymbolValue(Tok, Dot); },
- [=]() { return isAbsolute(Tok); }};
+ [=]() { return isAbsolute(Tok); },
+ [=]() { return ScriptBase->getSymbolSection(Tok); }};
}
Expr ScriptParser::readTernary(Expr Cond) {
Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=287090&r1=287089&r2=287090&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed Nov 16 03:49:39 2016
@@ -43,12 +43,19 @@ class InputSectionData;
struct Expr {
std::function<uint64_t(uint64_t)> Val;
std::function<bool()> IsAbsolute;
+
+ // If expression is section-relative the function below is used
+ // to get the output section pointer.
+ std::function<const OutputSectionBase *()> Section;
+
uint64_t operator()(uint64_t Dot) const { return Val(Dot); }
operator bool() const { return (bool)Val; }
- Expr(std::function<uint64_t(uint64_t)> Val, std::function<bool()> IsAbsolute)
- : Val(Val), IsAbsolute(IsAbsolute) {}
- template <typename T> Expr(T V) : Expr(V, []() { return true; }) {}
+ Expr(std::function<uint64_t(uint64_t)> Val, std::function<bool()> IsAbsolute,
+ std::function<const OutputSectionBase *()> Section)
+ : Val(Val), IsAbsolute(IsAbsolute), Section(Section) {}
+ template <typename T>
+ Expr(T V) : Expr(V, []() { return true; }, []() { return nullptr; }) {}
Expr() : Expr(nullptr) {}
};
@@ -182,14 +189,12 @@ protected:
~LinkerScriptBase() = default;
public:
- virtual uint64_t getOutputSectionAddress(StringRef Name) = 0;
- virtual uint64_t getOutputSectionSize(StringRef Name) = 0;
- virtual uint64_t getOutputSectionAlign(StringRef Name) = 0;
- virtual uint64_t getOutputSectionLMA(StringRef Name) = 0;
virtual uint64_t getHeaderSize() = 0;
virtual uint64_t getSymbolValue(StringRef S) = 0;
virtual bool isDefined(StringRef S) = 0;
virtual bool isAbsolute(StringRef S) = 0;
+ virtual const OutputSectionBase *getSymbolSection(StringRef S) = 0;
+ virtual const OutputSectionBase *getOutputSection(StringRef S) = 0;
};
// ScriptConfiguration holds linker script parse results.
@@ -234,14 +239,12 @@ public:
void placeOrphanSections();
void assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs);
bool hasPhdrsCommands();
- uint64_t getOutputSectionAddress(StringRef Name) override;
- uint64_t getOutputSectionSize(StringRef Name) override;
- uint64_t getOutputSectionAlign(StringRef Name) override;
- uint64_t getOutputSectionLMA(StringRef Name) override;
uint64_t getHeaderSize() override;
uint64_t getSymbolValue(StringRef S) override;
bool isDefined(StringRef S) override;
bool isAbsolute(StringRef S) override;
+ const OutputSectionBase *getSymbolSection(StringRef S) override;
+ const OutputSectionBase *getOutputSection(StringRef S) override;
std::vector<OutputSectionBase *> *OutputSections;
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=287090&r1=287089&r2=287090&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Nov 16 03:49:39 2016
@@ -423,7 +423,8 @@ Symbol *SymbolTable<ELFT>::addRegular(St
}
template <typename ELFT>
-Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N, OutputSectionBase *Section,
+Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
+ const OutputSectionBase *Section,
uintX_t Value, uint8_t StOther) {
Symbol *S;
bool WasInserted;
Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=287090&r1=287089&r2=287090&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Wed Nov 16 03:49:39 2016
@@ -64,8 +64,8 @@ public:
Symbol *addRegular(StringRef Name, const Elf_Sym &Sym,
InputSectionBase<ELFT> *Section, InputFile *File);
- Symbol *addSynthetic(StringRef N, OutputSectionBase *Section, uintX_t Value,
- uint8_t StOther);
+ Symbol *addSynthetic(StringRef N, const OutputSectionBase *Section,
+ uintX_t Value, uint8_t StOther);
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=287090&r1=287089&r2=287090&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Wed Nov 16 03:49:39 2016
@@ -216,7 +216,7 @@ Undefined::Undefined(uint32_t NameOffset
template <typename ELFT>
DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
- OutputSectionBase *Section)
+ const OutputSectionBase *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=287090&r1=287089&r2=287090&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Wed Nov 16 03:49:39 2016
@@ -244,7 +244,8 @@ InputSectionBase<ELFT> *DefinedRegular<E
template <class ELFT> class DefinedSynthetic : public Defined {
public:
typedef typename ELFT::uint uintX_t;
- DefinedSynthetic(StringRef N, uintX_t Value, OutputSectionBase *Section);
+ DefinedSynthetic(StringRef N, uintX_t Value,
+ const OutputSectionBase *Section);
static bool classof(const SymbolBody *S) {
return S->kind() == SymbolBody::DefinedSyntheticKind;
Modified: lld/trunk/test/ELF/linkerscript/symbols-synthetic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/symbols-synthetic.s?rev=287090&r1=287089&r2=287090&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/symbols-synthetic.s (original)
+++ lld/trunk/test/ELF/linkerscript/symbols-synthetic.s Wed Nov 16 03:49:39 2016
@@ -42,6 +42,21 @@
# RUN: }" > %t.script
# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
+# Check that we can specify synthetic symbols without defining SECTIONS.
+# RUN: echo "PROVIDE_HIDDEN(_begin_sec = _start); \
+# RUN: PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text));" > %t.script
+# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=NO-SEC %s
+
+# Check that we can do the same as above inside SECTIONS block.
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x11000; \
+# RUN: .text : { *(.text) } \
+# RUN: PROVIDE_HIDDEN(_begin_sec = ADDR(.text)); \
+# RUN: PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text)); }" > %t.script
+# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=IN-SEC %s
+
# SIMPLE: 0000000000000128 .foo 00000000 .hidden _end_sec
# SIMPLE-NEXT: 0000000000000120 .foo 00000000 _begin_sec
# SIMPLE-NEXT: 0000000000000128 *ABS* 00000000 _end_sec_abs
@@ -59,6 +74,12 @@
# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end
# SIMPLE-NEXT: 0000000000001020 *ABS* 00000000 __eh_frame_hdr_end2
+# NO-SEC: 0000000000011000 .text 00000000 .hidden _begin_sec
+# NO-SEC-NEXT: 0000000000011001 .text 00000000 .hidden _end_sec
+
+# IN-SEC: 0000000000011000 .text 00000000 .hidden _begin_sec
+# IN-SEC-NEXT: 0000000000011001 .text 00000000 .hidden _end_sec
+
.global _start
_start:
nop
More information about the llvm-commits
mailing list