Remove DefinedSynthetic.

With this we have a single section hierarchy. It is a bit less code,
but the main advantage will be in a future patch being able to handle

foo = symbol_in_obj;

in a linker script. Currently that fails since we try to find the
output section of symbol_in_obj.  With this we should be able to just
return an InputSection from the expression.

llvm-svn: 297313
This commit is contained in:
Rafael Espindola 2017-03-08 22:36:28 +00:00
parent e37b32c433
commit 5616adf655
13 changed files with 209 additions and 248 deletions

View File

@ -55,10 +55,11 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
uint32_t Link, uint32_t Info,
uint32_t Alignment, ArrayRef<uint8_t> Data,
StringRef Name, Kind SectionKind)
: File(File), Data(Data), Name(Name), SectionKind(SectionKind),
Live(!Config->GcSections || !(Flags & SHF_ALLOC)), Assigned(false),
Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info),
Repl(this) {
: SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info,
Link),
File(File), Data(Data), Repl(this) {
Live = !Config->GcSections || !(Flags & SHF_ALLOC);
Assigned = false;
NumRelocations = 0;
AreRelocsRela = false;
@ -98,15 +99,20 @@ uint64_t InputSectionBase::getOffsetInFile() const {
return SecStart - FileStart;
}
uint64_t InputSectionBase::getOffset(uint64_t Offset) const {
uint64_t SectionBase::getOffset(uint64_t Offset) const {
switch (kind()) {
case Output: {
auto *OS = cast<OutputSection>(this);
// For output sections we treat offset -1 as the end of the section.
return Offset == uint64_t(-1) ? OS->Size : Offset;
}
case Regular:
return cast<InputSection>(this)->OutSecOff + Offset;
case Synthetic:
case Synthetic: {
auto *IS = cast<InputSection>(this);
// For synthetic sections we treat offset -1 as the end of the section.
// The same approach is used for synthetic symbols (DefinedSynthetic).
return cast<InputSection>(this)->OutSecOff +
(Offset == uint64_t(-1) ? getSize() : Offset);
return IS->OutSecOff + (Offset == uint64_t(-1) ? IS->getSize() : Offset);
}
case EHFrame:
// The file crtbeginT.o has relocations pointing to the start of an empty
// .eh_frame that is known to be the first in the link. It does that to
@ -121,12 +127,14 @@ uint64_t InputSectionBase::getOffset(uint64_t Offset) const {
llvm_unreachable("invalid section kind");
}
OutputSection *InputSectionBase::getOutputSection() const {
OutputSection *SectionBase::getOutputSection() {
if (auto *IS = dyn_cast<InputSection>(this))
return IS->OutSec;
if (auto *MS = dyn_cast<MergeInputSection>(this))
return MS->MergeSec ? MS->MergeSec->OutSec : nullptr;
if (auto *EH = dyn_cast<EhInputSection>(this))
return EH->EHSec->OutSec;
return OutSec;
return cast<OutputSection>(this);
}
// Uncompress section contents. Note that this function is called
@ -150,7 +158,7 @@ template <class ELFT> void InputSectionBase::uncompress() {
Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size);
}
uint64_t InputSectionBase::getOffset(const DefinedRegular &Sym) const {
uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const {
return getOffset(Sym.Value);
}
@ -199,9 +207,13 @@ InputSection::InputSection(elf::ObjectFile<ELFT> *F,
const typename ELFT::Shdr *Header, StringRef Name)
: InputSectionBase(F, Header, Name, InputSectionBase::Regular) {}
bool InputSection::classof(const InputSectionBase *S) {
return S->kind() == InputSectionBase::Regular ||
S->kind() == InputSectionBase::Synthetic;
bool InputSection::classof(const SectionBase *S) {
return S->kind() == SectionBase::Regular ||
S->kind() == SectionBase::Synthetic;
}
bool InputSectionBase::classof(const SectionBase *S) {
return S->kind() != Output;
}
template <class ELFT> InputSectionBase *InputSection::getRelocatedSection() {
@ -248,14 +260,14 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
// avoid having to parse and recreate .eh_frame, we just replace any
// relocation in it pointing to discarded sections with R_*_NONE, which
// hopefully creates a frame that is ignored at runtime.
InputSectionBase *Section = cast<DefinedRegular>(Body).Section;
SectionBase *Section = cast<DefinedRegular>(Body).Section;
if (Section == &InputSection::Discarded) {
P->setSymbolAndType(0, 0, false);
continue;
}
if (Config->isRela()) {
P->r_addend += Body.getVA<ELFT>() - Section->OutSec->Addr;
P->r_addend += Body.getVA<ELFT>() - Section->getOutputSection()->Addr;
} else if (Config->Relocatable) {
const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset;
RelocatedSection->Relocations.push_back(
@ -587,7 +599,7 @@ EhInputSection::EhInputSection(elf::ObjectFile<ELFT> *F,
this->Live = true;
}
bool EhInputSection::classof(const InputSectionBase *S) {
bool EhInputSection::classof(const SectionBase *S) {
return S->kind() == InputSectionBase::EHFrame;
}
@ -710,7 +722,7 @@ void MergeInputSection::splitIntoPieces() {
this->getSectionPiece(Off)->Live = true;
}
bool MergeInputSection::classof(const InputSectionBase *S) {
bool MergeInputSection::classof(const SectionBase *S) {
return S->kind() == InputSectionBase::Merge;
}

View File

@ -34,21 +34,23 @@ class MergeSyntheticSection;
template <class ELFT> class ObjectFile;
class OutputSection;
// This corresponds to a section of an input file.
class InputSectionBase {
// This is the base class of all sections that lld handles. Some are sections in
// input files, some are sections in the produced output file and some exist
// just as a convenience for implementing special ways of combining some
// sections.
class SectionBase {
public:
enum Kind { Regular, EHFrame, Merge, Synthetic, };
enum Kind { Regular, EHFrame, Merge, Synthetic, Output };
Kind kind() const { return (Kind)SectionKind; }
// The file this section is from.
InputFile *File;
ArrayRef<uint8_t> Data;
StringRef Name;
unsigned SectionKind : 3;
// The next two bit fields are only used by InputSectionBase, but we
// put them here so the struct packs better.
// The garbage collector sets sections' Live bits.
// If GC is disabled, all sections are considered live by default.
unsigned Live : 1; // for garbage collection
@ -63,12 +65,48 @@ public:
uint32_t Link;
uint32_t Info;
OutputSection *getOutputSection();
const OutputSection *getOutputSection() const {
return const_cast<SectionBase *>(this)->getOutputSection();
}
// Translate an offset in the input section to an offset in the output
// section.
uint64_t getOffset(uint64_t Offset) const;
uint64_t getOffset(const DefinedRegular &Sym) const;
protected:
SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags,
uint64_t Entsize, uint64_t Alignment, uint32_t Type,
uint32_t Info, uint32_t Link)
: Name(Name), SectionKind(SectionKind), Alignment(Alignment),
Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info) {
Live = false;
Assigned = false;
}
};
// This corresponds to a section of an input file.
class InputSectionBase : public SectionBase {
public:
static bool classof(const SectionBase *S);
// The file this section is from.
InputFile *File;
ArrayRef<uint8_t> Data;
uint64_t getOffsetInFile() const;
static InputSectionBase Discarded;
InputSectionBase()
: SectionKind(Regular), Live(false), Assigned(false), Repl(this) {
: SectionBase(Regular, "", /*Flags*/ 0, /*Entsize*/ 0, /*Alignment*/ 0,
/*Type*/ 0,
/*Info*/ 0, /*Link*/ 0),
Repl(this) {
Live = false;
Assigned = false;
NumRelocations = 0;
AreRelocsRela = false;
}
@ -113,20 +151,13 @@ public:
// Returns the size of this section (even if this is a common or BSS.)
size_t getSize() const;
OutputSection *getOutputSection() const;
template <class ELFT> ObjectFile<ELFT> *getFile() const;
template <class ELFT> llvm::object::ELFFile<ELFT> getObj() const {
return getFile<ELFT>()->getObj();
}
uint64_t getOffset(const DefinedRegular &Sym) const;
template <class ELFT> InputSectionBase *getLinkOrderDep() const;
// Translate an offset in the input section to an offset in the output
// section.
uint64_t getOffset(uint64_t Offset) const;
template <class ELFT> void uncompress();
@ -165,7 +196,7 @@ public:
template <class ELFT>
MergeInputSection(ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header,
StringRef Name);
static bool classof(const InputSectionBase *S);
static bool classof(const SectionBase *S);
void splitIntoPieces();
// Mark the piece at a given offset live. Used by GC.
@ -237,7 +268,7 @@ public:
template <class ELFT>
EhInputSection(ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header,
StringRef Name);
static bool classof(const InputSectionBase *S);
static bool classof(const SectionBase *S);
template <class ELFT> void split();
template <class ELFT, class RelTy> void split(ArrayRef<RelTy> Rels);
@ -267,7 +298,7 @@ public:
// to. The writer sets a value.
uint64_t OutSecOff = 0;
static bool classof(const InputSectionBase *S);
static bool classof(const SectionBase *S);
template <class ELFT> InputSectionBase *getRelocatedSection();

View File

@ -63,21 +63,10 @@ template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) {
Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false,
/*File*/ nullptr);
Sym->Binding = STB_GLOBAL;
OutputSection *Sec =
Cmd->Expression.IsAbsolute() ? nullptr : Cmd->Expression.Section();
replaceBody<DefinedRegular>(Sym, Cmd->Name, /*IsLocal=*/false, Visibility,
STT_NOTYPE, 0, 0, nullptr, nullptr);
return Sym->body();
}
template <class ELFT> static SymbolBody *addSynthetic(SymbolAssignment *Cmd) {
Symbol *Sym;
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
const OutputSection *Sec =
ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section();
std::tie(Sym, std::ignore) = Symtab<ELFT>::X->insert(
Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false,
/*File*/ nullptr);
Sym->Binding = STB_GLOBAL;
replaceBody<DefinedSynthetic>(Sym, Cmd->Name, 0, Sec);
STT_NOTYPE, 0, 0, Sec, nullptr);
return Sym->body();
}
@ -119,18 +108,14 @@ void LinkerScript<ELFT>::assignSymbol(SymbolAssignment *Cmd, bool InSec) {
if (!Cmd->Sym)
return;
if (auto *Body = dyn_cast<DefinedSynthetic>(Cmd->Sym)) {
Body->Section = Cmd->Expression.Section();
if (Body->Section) {
uint64_t VA = 0;
if (Body->Section->Flags & SHF_ALLOC)
VA = Body->Section->Addr;
Body->Value = Cmd->Expression(Dot) - VA;
}
return;
auto *Sym = cast<DefinedRegular>(Cmd->Sym);
Sym->Value = Cmd->Expression(Dot);
if (!Cmd->Expression.IsAbsolute()) {
Sym->Section = Cmd->Expression.Section();
if (auto *Sec = dyn_cast_or_null<OutputSection>(Sym->Section))
if (Sec->Flags & SHF_ALLOC)
Sym->Value -= Sec->Addr;
}
cast<DefinedRegular>(Cmd->Sym)->Value = Cmd->Expression(Dot);
}
template <class ELFT>
@ -144,12 +129,7 @@ void LinkerScript<ELFT>::addSymbol(SymbolAssignment *Cmd) {
if (Cmd->Provide && (!B || B->isDefined()))
return;
// Otherwise, create a new symbol if one does not exist or an
// undefined one does exist.
if (Cmd->Expression.IsAbsolute())
Cmd->Sym = addRegular<ELFT>(Cmd);
else
Cmd->Sym = addSynthetic<ELFT>(Cmd);
Cmd->Sym = addRegular<ELFT>(Cmd);
// If there are sections, then let the value be assigned later in
// `assignAddresses`.
@ -321,6 +301,19 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
template <class ELFT>
void LinkerScript<ELFT>::processCommands(OutputSectionFactory &Factory) {
// A symbol can be assigned before any section is mentioned in the linker
// script. In an DSO, the symbol values are addresses, so the only important
// section values are:
// * SHN_UNDEF
// * SHN_ABS
// * Any value meaning a regular section.
// To handle that, create a dummy aether section that fills the void before
// the linker scripts switches to another section. It has an index of one
// which will map to whatever the first actual section is.
Aether = make<OutputSection>("", 0, SHF_ALLOC);
Aether->SectionIndex = 1;
CurOutSec = Aether;
for (unsigned I = 0; I < Opt.Commands.size(); ++I) {
auto Iter = Opt.Commands.begin() + I;
const std::unique_ptr<BaseCommand> &Base1 = *Iter;
@ -385,6 +378,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory &Factory) {
Factory.addInputSec<ELFT>(S, Cmd->Name);
}
}
CurOutSec = nullptr;
}
// Add sections that didn't match any sections command.
@ -772,18 +766,6 @@ template <class ELFT>
void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = 0;
// A symbol can be assigned before any section is mentioned in the linker
// script. In an DSO, the symbol values are addresses, so the only important
// section values are:
// * SHN_UNDEF
// * SHN_ABS
// * Any value meaning a regular section.
// To handle that, create a dummy aether section that fills the void before
// the linker scripts switches to another section. It has an index of one
// which will map to whatever the first actual section is.
auto *Aether = make<OutputSection>("", 0, SHF_ALLOC);
Aether->SectionIndex = 1;
switchTo(Aether);
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
@ -924,8 +906,8 @@ template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() {
}
template <class ELFT>
const OutputSection *LinkerScript<ELFT>::getOutputSection(const Twine &Loc,
StringRef Name) {
OutputSection *LinkerScript<ELFT>::getOutputSection(const Twine &Loc,
StringRef Name) {
static OutputSection FakeSec("", 0, 0);
for (OutputSection *Sec : *OutputSections)
@ -976,7 +958,7 @@ template <class ELFT> bool LinkerScript<ELFT>::isAbsolute(StringRef S) {
// 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 OutputSection *LinkerScript<ELFT>::getSymbolSection(StringRef S) {
OutputSection *LinkerScript<ELFT>::getSymbolSection(StringRef S) {
if (SymbolBody *Sym = Symtab<ELFT>::X->find(S))
return Sym->getOutputSection<ELFT>();
return CurOutSec;
@ -1634,7 +1616,7 @@ Expr ScriptParser::readExpr() {
static Expr combine(StringRef Op, Expr L, Expr R) {
auto IsAbs = [=] { return L.IsAbsolute() && R.IsAbsolute(); };
auto GetOutSec = [=] {
const OutputSection *S = L.Section();
OutputSection *S = L.Section();
return S ? S : R.Section();
};

View File

@ -47,13 +47,13 @@ struct Expr {
// If expression is section-relative the function below is used
// to get the output section pointer.
std::function<const OutputSection *()> Section;
std::function<OutputSection *()> 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,
std::function<const OutputSection *()> Section)
std::function<OutputSection *()> Section)
: Val(Val), IsAbsolute(IsAbsolute), Section(Section) {}
template <typename T>
Expr(T V) : Expr(V, [] { return true; }, [] { return nullptr; }) {}
@ -207,15 +207,15 @@ struct MemoryRegion {
class LinkerScriptBase {
protected:
~LinkerScriptBase() = default;
OutputSection *Aether;
public:
virtual uint64_t getHeaderSize() = 0;
virtual uint64_t getSymbolValue(const Twine &Loc, StringRef S) = 0;
virtual bool isDefined(StringRef S) = 0;
virtual bool isAbsolute(StringRef S) = 0;
virtual const OutputSection *getSymbolSection(StringRef S) = 0;
virtual const OutputSection *getOutputSection(const Twine &Loc,
StringRef S) = 0;
virtual OutputSection *getSymbolSection(StringRef S) = 0;
virtual OutputSection *getOutputSection(const Twine &Loc, StringRef S) = 0;
virtual uint64_t getOutputSectionSize(StringRef S) = 0;
};
@ -268,8 +268,8 @@ public:
uint64_t getSymbolValue(const Twine &Loc, StringRef S) override;
bool isDefined(StringRef S) override;
bool isAbsolute(StringRef S) override;
const OutputSection *getSymbolSection(StringRef S) override;
const OutputSection *getOutputSection(const Twine &Loc, StringRef S) override;
OutputSection *getSymbolSection(StringRef S) override;
OutputSection *getOutputSection(const Twine &Loc, StringRef S) override;
uint64_t getOutputSectionSize(StringRef S) override;
std::vector<OutputSection *> *OutputSections;

View File

@ -78,7 +78,7 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
typename ELFT::uint Offset = D->Value;
if (D->isSection())
Offset += getAddend<ELFT>(Sec, Rel);
Fn({D->Section->Repl, Offset});
Fn({cast<InputSectionBase>(D->Section)->Repl, Offset});
} else if (auto *U = dyn_cast<Undefined>(&B)) {
for (InputSectionBase *Sec : CNamedSections.lookup(U->getName()))
Fn({Sec, 0});
@ -223,7 +223,7 @@ template <class ELFT> void elf::markLive() {
auto MarkSymbol = [&](const SymbolBody *Sym) {
if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym))
Enqueue({D->Section, D->Value});
Enqueue({cast<InputSectionBase>(D->Section), D->Value});
};
// Add GC root symbols.

View File

@ -67,7 +67,9 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) {
}
OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
: Name(Name), Flags(Flags), Alignment(1), Type(Type) {}
: SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
/*Info*/ 0,
/*Link*/ 0) {}
template <typename ELFT>
static bool compareByFilePosition(InputSection *A, InputSection *B) {

View File

@ -11,6 +11,7 @@
#define LLD_ELF_OUTPUT_SECTIONS_H
#include "Config.h"
#include "InputSection.h"
#include "Relocations.h"
#include "lld/Core/LLVM.h"
@ -37,10 +38,14 @@ class DefinedRegular;
// It is composed of multiple InputSections.
// The writer creates multiple OutputSections and assign them unique,
// non-overlapping file offsets and VAs.
class OutputSection final {
class OutputSection final : public SectionBase {
public:
OutputSection(StringRef Name, uint32_t Type, uint64_t Flags);
static bool classof(const SectionBase *S) {
return S->kind() == SectionBase::Output;
}
uint64_t getLMA() const { return Addr + LMAOffset; }
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
@ -65,20 +70,12 @@ public:
// formula: Off = Off_first + VA - VA_first.
OutputSection *FirstInPtLoad = nullptr;
StringRef Name;
// The following fields correspond to Elf_Shdr members.
uint64_t Size = 0;
uint64_t Entsize = 0;
uint64_t Offset = 0;
uint64_t Flags = 0;
uint64_t LMAOffset = 0;
uint64_t Addr = 0;
uint32_t Alignment = 0;
uint32_t ShName = 0;
uint32_t Type = 0;
uint32_t Info = 0;
uint32_t Link = 0;
void addSection(InputSectionBase *C);
void sort(std::function<int(InputSectionBase *S)> Order);

View File

@ -369,7 +369,8 @@ static void reportDuplicate(SymbolBody *Existing, InputSectionBase *ErrSec,
return;
}
std::string OldLoc = D->Section->template getLocation<ELFT>(D->Value);
std::string OldLoc =
cast<InputSectionBase>(D->Section)->template getLocation<ELFT>(D->Value);
std::string NewLoc = ErrSec->getLocation<ELFT>(ErrOffset);
print(NewLoc + ": duplicate symbol '" + toString(*Existing) + "'");
@ -377,10 +378,10 @@ static void reportDuplicate(SymbolBody *Existing, InputSectionBase *ErrSec,
}
template <typename ELFT>
Symbol *
SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
uint64_t Value, uint64_t Size, uint8_t Binding,
InputSectionBase *Section, InputFile *File) {
Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther,
uint8_t Type, uint64_t Value,
uint64_t Size, uint8_t Binding,
SectionBase *Section, InputFile *File) {
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther),
@ -391,24 +392,8 @@ SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type,
Value, Size, Section, File);
else if (Cmp == 0)
reportDuplicate<ELFT>(S->body(), Section, Value);
return S;
}
template <typename ELFT>
Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
const OutputSection *Section,
uint64_t Value, uint8_t StOther) {
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(N, STT_NOTYPE, getVisibility(StOther),
/*CanOmitFromDynSym*/ false, nullptr);
int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, STB_GLOBAL,
/*IsAbsolute*/ false, /*Value*/ 0);
if (Cmp > 0)
replaceBody<DefinedSynthetic>(S, N, Value, Section);
else if (Cmp == 0)
reportDuplicate(S->body(), nullptr);
reportDuplicate<ELFT>(S->body(),
dyn_cast_or_null<InputSectionBase>(Section), Value);
return S;
}

View File

@ -58,10 +58,7 @@ public:
Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
uint64_t Value, uint64_t Size, uint8_t Binding,
InputSectionBase *Section, InputFile *File);
Symbol *addSynthetic(StringRef N, const OutputSection *Section,
uint64_t Value, uint8_t StOther);
SectionBase *Section, InputFile *File);
void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
const typename ELFT::Verdef *Verdef);

View File

@ -28,14 +28,12 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
InputSectionBase *DefinedRegular::NullInputSection;
DefinedSynthetic *ElfSym::Etext;
DefinedSynthetic *ElfSym::Etext2;
DefinedSynthetic *ElfSym::Edata;
DefinedSynthetic *ElfSym::Edata2;
DefinedSynthetic *ElfSym::End;
DefinedSynthetic *ElfSym::End2;
DefinedRegular *ElfSym::Etext;
DefinedRegular *ElfSym::Etext2;
DefinedRegular *ElfSym::Edata;
DefinedRegular *ElfSym::Edata2;
DefinedRegular *ElfSym::End;
DefinedRegular *ElfSym::End2;
DefinedRegular *ElfSym::MipsGpDisp;
DefinedRegular *ElfSym::MipsLocalGp;
DefinedRegular *ElfSym::MipsGp;
@ -43,18 +41,11 @@ DefinedRegular *ElfSym::MipsGp;
template <class ELFT>
static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) {
switch (Body.kind()) {
case SymbolBody::DefinedSyntheticKind: {
auto &D = cast<DefinedSynthetic>(Body);
const OutputSection *Sec = D.Section;
if (!Sec)
return D.Value;
if (D.Value == uint64_t(-1))
return Sec->Addr + Sec->Size;
return Sec->Addr + D.Value;
}
case SymbolBody::DefinedRegularKind: {
auto &D = cast<DefinedRegular>(Body);
InputSectionBase *IS = D.Section;
SectionBase *IS = D.Section;
if (auto *ISB = dyn_cast_or_null<InputSectionBase>(IS))
IS = ISB->Repl;
// According to the ELF spec reference to a local symbol from outside
// the group are not allowed. Unfortunately .eh_frame breaks that rule
@ -207,8 +198,7 @@ template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
return 0;
}
template <class ELFT>
const OutputSection *SymbolBody::getOutputSection() const {
template <class ELFT> OutputSection *SymbolBody::getOutputSection() const {
if (auto *S = dyn_cast<DefinedRegular>(this)) {
if (S->Section)
return S->Section->getOutputSection();
@ -227,8 +217,6 @@ const OutputSection *SymbolBody::getOutputSection() const {
return nullptr;
}
if (auto *S = dyn_cast<DefinedSynthetic>(this))
return S->Section;
return nullptr;
}
@ -279,7 +267,11 @@ template <class ELFT> bool DefinedRegular::isMipsPIC() const {
if (!Section || !isFunc())
return false;
return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC ||
(Section->getFile<ELFT>()->getObj().getHeader()->e_flags &
(cast<InputSectionBase>(Section)
->template getFile<ELFT>()
->getObj()
.getHeader()
->e_flags &
EF_MIPS_PIC);
}
@ -419,14 +411,10 @@ template uint32_t SymbolBody::template getSize<ELF32BE>() const;
template uint64_t SymbolBody::template getSize<ELF64LE>() const;
template uint64_t SymbolBody::template getSize<ELF64BE>() const;
template const OutputSection *
SymbolBody::template getOutputSection<ELF32LE>() const;
template const OutputSection *
SymbolBody::template getOutputSection<ELF32BE>() const;
template const OutputSection *
SymbolBody::template getOutputSection<ELF64LE>() const;
template const OutputSection *
SymbolBody::template getOutputSection<ELF64BE>() const;
template OutputSection *SymbolBody::template getOutputSection<ELF32LE>() const;
template OutputSection *SymbolBody::template getOutputSection<ELF32BE>() const;
template OutputSection *SymbolBody::template getOutputSection<ELF64LE>() const;
template OutputSection *SymbolBody::template getOutputSection<ELF64BE>() const;
template bool DefinedRegular::template isMipsPIC<ELF32LE>() const;
template bool DefinedRegular::template isMipsPIC<ELF32BE>() const;

View File

@ -43,8 +43,7 @@ public:
DefinedRegularKind = DefinedFirst,
SharedKind,
DefinedCommonKind,
DefinedSyntheticKind,
DefinedLast = DefinedSyntheticKind,
DefinedLast = DefinedCommonKind,
UndefinedKind,
LazyArchiveKind,
LazyObjectKind,
@ -84,7 +83,7 @@ public:
template <class ELFT> typename ELFT::uint getGotPltVA() const;
template <class ELFT> typename ELFT::uint getPltVA() const;
template <class ELFT> typename ELFT::uint getSize() const;
template <class ELFT> const OutputSection *getOutputSection() const;
template <class ELFT> OutputSection *getOutputSection() const;
// The file from which this symbol was created.
InputFile *File = nullptr;
@ -177,11 +176,10 @@ public:
class DefinedRegular : public Defined {
public:
DefinedRegular(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type,
uint64_t Value, uint64_t Size, InputSectionBase *Section,
uint64_t Value, uint64_t Size, SectionBase *Section,
InputFile *File)
: Defined(SymbolBody::DefinedRegularKind, Name, IsLocal, StOther, Type),
Value(Value), Size(Size),
Section(Section ? Section->Repl : NullInputSection) {
Value(Value), Size(Size), Section(Section) {
this->File = File;
}
@ -194,37 +192,7 @@ public:
uint64_t Value;
uint64_t Size;
// The input section this symbol belongs to. Notice that this is
// a reference to a pointer. We are using two levels of indirections
// because of ICF. If ICF decides two sections need to be merged, it
// manipulates this Section pointers so that they point to the same
// section. This is a bit tricky, so be careful to not be confused.
// If this is null, the symbol is an absolute symbol.
InputSectionBase *&Section;
private:
static InputSectionBase *NullInputSection;
};
// DefinedSynthetic is a class to represent linker-generated ELF symbols.
// 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.
class DefinedSynthetic : public Defined {
public:
DefinedSynthetic(StringRef Name, uint64_t Value, const OutputSection *Section)
: Defined(SymbolBody::DefinedSyntheticKind, Name, /*IsLocal=*/false,
llvm::ELF::STV_HIDDEN, 0 /* Type */),
Value(Value), Section(Section) {}
static bool classof(const SymbolBody *S) {
return S->kind() == SymbolBody::DefinedSyntheticKind;
}
uint64_t Value;
const OutputSection *Section;
SectionBase *Section;
};
class Undefined : public SymbolBody {
@ -334,16 +302,16 @@ public:
// DefinedRegular symbols.
struct ElfSym {
// The content for _etext and etext symbols.
static DefinedSynthetic *Etext;
static DefinedSynthetic *Etext2;
static DefinedRegular *Etext;
static DefinedRegular *Etext2;
// The content for _edata and edata symbols.
static DefinedSynthetic *Edata;
static DefinedSynthetic *Edata2;
static DefinedRegular *Edata;
static DefinedRegular *Edata2;
// The content for _end and end symbols.
static DefinedSynthetic *End;
static DefinedSynthetic *End2;
static DefinedRegular *End;
static DefinedRegular *End2;
// The content for _gp_disp/__gnu_local_gp symbols for MIPS target.
static DefinedRegular *MipsGpDisp;
@ -395,8 +363,8 @@ struct Symbol {
// This field is used to store the Symbol's SymbolBody. This instantiation of
// AlignedCharArrayUnion gives us a struct with a char array field that is
// large and aligned enough to store any derived class of SymbolBody.
llvm::AlignedCharArrayUnion<DefinedCommon, DefinedRegular, DefinedSynthetic,
Undefined, SharedSymbol, LazyArchive, LazyObject>
llvm::AlignedCharArrayUnion<DefinedCommon, DefinedRegular, Undefined,
SharedSymbol, LazyArchive, LazyObject>
Body;
SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); }

View File

@ -460,7 +460,8 @@ bool EhFrameSection<ELFT>::isFdeLive(EhSectionPiece &Piece,
auto *D = dyn_cast<DefinedRegular>(&B);
if (!D || !D->Section)
return false;
InputSectionBase *Target = D->Section->Repl;
auto *Target =
cast<InputSectionBase>(cast<InputSectionBase>(D->Section)->Repl);
return Target && Target->Live;
}
@ -1357,8 +1358,8 @@ size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) {
// This is used for -r, so we have to handle multiple section
// symbols being combined.
if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION)
return cast<DefinedRegular>(Body)->Section->OutSec ==
cast<DefinedRegular>(E.Symbol)->Section->OutSec;
return cast<DefinedRegular>(Body)->Section->getOutputSection() ==
cast<DefinedRegular>(E.Symbol)->Section->getOutputSection();
return false;
});
if (I == Symbols.end())

View File

@ -453,7 +453,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
}
template <class ELFT>
static bool shouldKeepInSymtab(InputSectionBase *Sec, StringRef SymName,
static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,
const SymbolBody &B) {
if (B.isFile() || B.isSection())
return false;
@ -485,12 +485,17 @@ template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
if (auto *D = dyn_cast<DefinedRegular>(&B)) {
// Always include absolute symbols.
if (!D->Section)
SectionBase *Sec = D->Section;
if (!Sec)
return true;
// Exclude symbols pointing to garbage-collected sections.
if (!D->Section->Live)
return false;
if (auto *S = dyn_cast<MergeInputSection>(D->Section))
if (auto *IS = dyn_cast<InputSectionBase>(Sec)) {
Sec = IS->Repl;
IS = cast<InputSectionBase>(Sec);
// Exclude symbols pointing to garbage-collected sections.
if (!IS->Live)
return false;
}
if (auto *S = dyn_cast<MergeInputSection>(Sec))
if (!S->getSectionPiece(D->Value)->Live)
return false;
}
@ -515,7 +520,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
if (!includeInSymtab<ELFT>(*B))
continue;
InputSectionBase *Sec = DR->Section;
SectionBase *Sec = DR->Section;
if (!shouldKeepInSymtab<ELFT>(Sec, B->getName(), *B))
continue;
In<ELFT>::SymTab->addSymbol(B);
@ -733,35 +738,27 @@ void PhdrEntry::add(OutputSection *Sec) {
}
template <class ELFT>
static DefinedSynthetic *addOptionalSynthetic(StringRef Name,
OutputSection *Sec, uint64_t Val,
uint8_t StOther = STV_HIDDEN) {
if (SymbolBody *S = Symtab<ELFT>::X->find(Name))
if (!S->isInCurrentDSO())
return cast<DefinedSynthetic>(
Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther)->body());
return nullptr;
}
template <class ELFT>
static Symbol *addRegular(StringRef Name, InputSectionBase *Sec,
uint64_t Value) {
static Symbol *addRegular(StringRef Name, SectionBase *Sec, uint64_t Value,
uint8_t StOther = STV_HIDDEN,
uint8_t Binding = STB_WEAK) {
// The linker generated symbols are added as STB_WEAK to allow user defined
// ones to override them.
return Symtab<ELFT>::X->addRegular(Name, STV_HIDDEN, STT_NOTYPE, Value,
/*Size=*/0, STB_WEAK, Sec,
return Symtab<ELFT>::X->addRegular(Name, StOther, STT_NOTYPE, Value,
/*Size=*/0, Binding, Sec,
/*File=*/nullptr);
}
template <class ELFT>
static Symbol *addOptionalRegular(StringRef Name, InputSectionBase *IS,
uint64_t Value) {
static DefinedRegular *
addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val,
uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) {
SymbolBody *S = Symtab<ELFT>::X->find(Name);
if (!S)
return nullptr;
if (S->isInCurrentDSO())
return S->symbol();
return addRegular<ELFT>(Name, IS, Value);
return nullptr;
return cast<DefinedRegular>(
addRegular<ELFT>(Name, Sec, Val, StOther, Binding)->body());
}
// The beginning and the ending of .rel[a].plt section are marked
@ -774,10 +771,10 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
if (In<ELFT>::DynSymTab)
return;
StringRef S = Config->isRela() ? "__rela_iplt_start" : "__rel_iplt_start";
addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0);
addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
S = Config->isRela() ? "__rela_iplt_end" : "__rel_iplt_end";
addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1);
addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
}
// The linker is expected to define some symbols depending on
@ -837,14 +834,13 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
return;
// __ehdr_start is the location of ELF file headers.
addOptionalSynthetic<ELFT>("__ehdr_start", Out::ElfHeader, 0);
addOptionalRegular<ELFT>("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);
auto Define = [](StringRef S, DefinedSynthetic *&Sym1,
DefinedSynthetic *&Sym2) {
Sym1 = addOptionalSynthetic<ELFT>(S, nullptr, 0, STV_DEFAULT);
auto Define = [](StringRef S, DefinedRegular *&Sym1, DefinedRegular *&Sym2) {
Sym1 = addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT);
assert(S.startswith("_"));
S = S.substr(1);
Sym2 = addOptionalSynthetic<ELFT>(S, nullptr, 0, STV_DEFAULT);
Sym2 = addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT);
};
Define("_end", ElfSym::End, ElfSym::End2);
@ -880,7 +876,7 @@ static void sortBySymbolsOrder(ArrayRef<OutputSection *> OutputSections) {
SymbolOrder.insert({S, Priority++});
// Build a map from sections to their priorities.
DenseMap<InputSectionBase *, int> SectionOrder;
DenseMap<SectionBase *, int> SectionOrder;
for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
for (SymbolBody *Body : File->getSymbols()) {
auto *D = dyn_cast<DefinedRegular>(Body);
@ -1208,8 +1204,10 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
auto Define = [&](StringRef Start, StringRef End, OutputSection *OS) {
// These symbols resolve to the image base if the section does not exist.
// A special value -1 indicates end of the section.
addOptionalSynthetic<ELFT>(Start, OS, 0);
addOptionalSynthetic<ELFT>(End, OS, OS ? -1 : 0);
if (!OS && Config->pic())
OS = Out::ElfHeader;
addOptionalRegular<ELFT>(Start, OS, 0);
addOptionalRegular<ELFT>(End, OS, OS ? -1 : 0);
};
Define("__preinit_array_start", "__preinit_array_end", Out::PreinitArray);
@ -1230,8 +1228,8 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
StringRef S = Sec->Name;
if (!isValidCIdentifier(S))
return;
addOptionalSynthetic<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
addOptionalSynthetic<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
}
template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
@ -1638,7 +1636,7 @@ static uint16_t getELFType() {
// to each section. This function fixes some predefined
// symbol values that depend on section address and size.
template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() {
auto Set = [](DefinedSynthetic *S1, DefinedSynthetic *S2, OutputSection *Sec,
auto Set = [](DefinedRegular *S1, DefinedRegular *S2, OutputSection *Sec,
uint64_t Value) {
if (S1) {
S1->Section = Sec;