Fix a few symbols that are not actually ABS.

The symbols _end, end, _etext, etext, _edata, edata and __ehdr_start
refer to positions in the file and are therefore not absolute. Making
them absolute was on unfortunate cargo cult of what bfd was doing.

Changing the symbols allows for pc relocations to them to be resolved,
which should fix the wine build.

llvm-svn: 293385
This commit is contained in:
Rafael Espindola 2017-01-28 17:48:21 +00:00
parent 2b156edf56
commit 78493a259d
5 changed files with 75 additions and 45 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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

11
lld/test/ELF/end-abs.s Normal file
View File

@ -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 - .