summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Symbols.h28
-rw-r--r--lld/ELF/Writer.cpp73
-rw-r--r--lld/test/ELF/edata-etext.s6
-rw-r--r--lld/test/ELF/ehdr_start.s2
-rw-r--r--lld/test/ELF/end-abs.s11
5 files changed, 75 insertions, 45 deletions
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 7acb89ad071..ee5293cfee3 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -352,19 +352,19 @@ public:
// DefinedRegular symbols.
template <class ELFT> struct ElfSym {
// The content for __ehdr_start symbol.
- static DefinedRegular<ELFT> *EhdrStart;
+ static DefinedSynthetic *EhdrStart;
// The content for _etext and etext symbols.
- static DefinedRegular<ELFT> *Etext;
- static DefinedRegular<ELFT> *Etext2;
+ static DefinedSynthetic *Etext;
+ static DefinedSynthetic *Etext2;
// The content for _edata and edata symbols.
- static DefinedRegular<ELFT> *Edata;
- static DefinedRegular<ELFT> *Edata2;
+ static DefinedSynthetic *Edata;
+ static DefinedSynthetic *Edata2;
// The content for _end and end symbols.
- static DefinedRegular<ELFT> *End;
- static DefinedRegular<ELFT> *End2;
+ static DefinedSynthetic *End;
+ static DefinedSynthetic *End2;
// The content for _gp_disp/__gnu_local_gp symbols for MIPS target.
static DefinedRegular<ELFT> *MipsGpDisp;
@@ -372,13 +372,13 @@ template <class ELFT> struct ElfSym {
static DefinedRegular<ELFT> *MipsGp;
};
-template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::EhdrStart;
-template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext;
-template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext2;
-template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata;
-template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata2;
-template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End;
-template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End2;
+template <class ELFT> DefinedSynthetic *ElfSym<ELFT>::EhdrStart;
+template <class ELFT> DefinedSynthetic *ElfSym<ELFT>::Etext;
+template <class ELFT> DefinedSynthetic *ElfSym<ELFT>::Etext2;
+template <class ELFT> DefinedSynthetic *ElfSym<ELFT>::Edata;
+template <class ELFT> DefinedSynthetic *ElfSym<ELFT>::Edata2;
+template <class ELFT> DefinedSynthetic *ElfSym<ELFT>::End;
+template <class ELFT> DefinedSynthetic *ElfSym<ELFT>::End2;
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsGpDisp;
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsLocalGp;
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsGp;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 0715bf04d6d..cee6eb729fd 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -68,7 +68,7 @@ private:
void setPhdrs();
void fixHeaders();
void fixSectionAlignments();
- void fixAbsoluteSymbols();
+ void fixPredefinedSymbols();
void openFile();
void writeHeader();
void writeSections();
@@ -208,7 +208,7 @@ template <class ELFT> void Writer<ELFT>::run() {
assignFileOffsetsBinary();
setPhdrs();
- fixAbsoluteSymbols();
+ fixPredefinedSymbols();
}
// It does not make sense try to open the file if we have error already.
@@ -648,12 +648,14 @@ void PhdrEntry::add(OutputSectionBase *Sec) {
}
template <class ELFT>
-static void addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec,
- typename ELFT::uint Val,
- uint8_t StOther = STV_HIDDEN) {
+static DefinedSynthetic *
+addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec,
+ typename ELFT::uint Val, uint8_t StOther = STV_HIDDEN) {
if (SymbolBody *S = Symtab<ELFT>::X->find(Name))
if (!S->isInCurrentDSO())
- Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther);
+ return cast<DefinedSynthetic>(
+ Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther)->body());
+ return nullptr;
}
template <class ELFT>
@@ -750,14 +752,16 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
if (ScriptConfig->HasSections)
return;
- ElfSym<ELFT>::EhdrStart = Symtab<ELFT>::X->addIgnored("__ehdr_start");
+ // __ehdr_start is the location of program headers.
+ ElfSym<ELFT>::EhdrStart =
+ addOptionalSynthetic<ELFT>("__ehdr_start", Out<ELFT>::ProgramHeaders, 0);
- auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym1,
- DefinedRegular<ELFT> *&Sym2) {
- Sym1 = Symtab<ELFT>::X->addIgnored(S, STV_DEFAULT);
+ auto Define = [this](StringRef S, DefinedSynthetic *&Sym1,
+ DefinedSynthetic *&Sym2) {
+ Sym1 = addOptionalSynthetic<ELFT>(S, nullptr, 0, STV_DEFAULT);
assert(S.startswith("_"));
S = S.substr(1);
- Sym2 = Symtab<ELFT>::X->addIgnored(S, STV_DEFAULT);
+ Sym2 = addOptionalSynthetic<ELFT>(S, nullptr, 0, STV_DEFAULT);
};
Define("_end", ElfSym<ELFT>::End, ElfSym<ELFT>::End2);
@@ -1056,6 +1060,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
sortSections();
+ // This is a bit of a hack. A value of 0 means undef, so we set it
+ // to 1 t make __ehdr_start defined. The section number is not
+ // particularly relevant.
+ Out<ELFT>::ProgramHeaders->SectionIndex = 1;
+
unsigned I = 1;
for (OutputSectionBase *Sec : OutputSections) {
Sec->SectionIndex = I++;
@@ -1548,34 +1557,44 @@ static uint16_t getELFType() {
}
// This function is called after we have assigned address and size
-// to each section. This function fixes some predefined absolute
+// to each section. This function fixes some predefined
// symbol values that depend on section address and size.
-template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
- // __ehdr_start is the location of program headers.
- if (ElfSym<ELFT>::EhdrStart)
- ElfSym<ELFT>::EhdrStart->Value = Out<ELFT>::ProgramHeaders->Addr;
-
- auto Set = [](DefinedRegular<ELFT> *S1, DefinedRegular<ELFT> *S2, uintX_t V) {
- if (S1)
- S1->Value = V;
- if (S2)
- S2->Value = V;
+template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() {
+ auto Set = [](DefinedSynthetic *S1, DefinedSynthetic *S2,
+ OutputSectionBase *Sec, uint64_t Value) {
+ if (S1) {
+ S1->Section = Sec;
+ S1->Value = Value;
+ }
+ if (S2) {
+ S2->Section = Sec;
+ S2->Value = Value;
+ }
};
// _etext is the first location after the last read-only loadable segment.
// _edata is the first location after the last read-write loadable segment.
// _end is the first location after the uninitialized data region.
+ PhdrEntry *Last = nullptr;
+ PhdrEntry *LastRO = nullptr;
+ PhdrEntry *LastRW = nullptr;
for (PhdrEntry &P : Phdrs) {
if (P.p_type != PT_LOAD)
continue;
- Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, P.p_vaddr + P.p_memsz);
-
- uintX_t Val = P.p_vaddr + P.p_filesz;
+ Last = &P;
if (P.p_flags & PF_W)
- Set(ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2, Val);
+ LastRW = &P;
else
- Set(ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2, Val);
+ LastRO = &P;
}
+ if (Last)
+ Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, Last->First, Last->p_memsz);
+ if (LastRO)
+ Set(ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2, LastRO->First,
+ LastRO->p_filesz);
+ if (LastRW)
+ Set(ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2, LastRW->First,
+ LastRW->p_filesz);
// Setup MIPS _gp_disp/__gnu_local_gp symbols which should
// be equal to the _gp symbol's value.
diff --git a/lld/test/ELF/edata-etext.s b/lld/test/ELF/edata-etext.s
index 7723adf94e2..3b0ba49ad1a 100644
--- a/lld/test/ELF/edata-etext.s
+++ b/lld/test/ELF/edata-etext.s
@@ -18,9 +18,9 @@
# CHECK-NEXT: 3 .bss 00000006 0000000000202004 BSS
# CHECK: SYMBOL TABLE:
# CHECK-NEXT: 0000000000000000 *UND* 00000000
-# CHECK-NEXT: 0000000000202002 *ABS* 00000000 _edata
-# CHECK-NEXT: 000000000020200a *ABS* 00000000 _end
-# CHECK-NEXT: 0000000000201001 *ABS* 00000000 _etext
+# CHECK-NEXT: 0000000000202002 .data 00000000 _edata
+# CHECK-NEXT: 000000000020200a .data 00000000 _end
+# CHECK-NEXT: 0000000000201001 .text 00000000 _etext
# CHECK-NEXT: 0000000000201000 .text 00000000 _start
# RUN: ld.lld -r %t.o -o %t2
diff --git a/lld/test/ELF/ehdr_start.s b/lld/test/ELF/ehdr_start.s
index 9172feca5e9..67d23cf7164 100644
--- a/lld/test/ELF/ehdr_start.s
+++ b/lld/test/ELF/ehdr_start.s
@@ -3,7 +3,7 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: ld.lld %t.o -o %t
# RUN: llvm-objdump -t %t | FileCheck %s
-# CHECK: 0000000000200040 *ABS* 00000000 .hidden __ehdr_start
+# CHECK: 0000000000200040 .text 00000000 .hidden __ehdr_start
.text
.global _start, __ehdr_start
diff --git a/lld/test/ELF/end-abs.s b/lld/test/ELF/end-abs.s
new file mode 100644
index 00000000000..2199ce23ad0
--- /dev/null
+++ b/lld/test/ELF/end-abs.s
@@ -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 -r %t | FileCheck %s
+
+# CHECK: Relocations [
+# CHECK-NEXT: ]
+
+.global _start
+_start:
+.long _end - .
OpenPOWER on IntegriCloud