mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 11:39:35 +00:00
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:
parent
e37b32c433
commit
5616adf655
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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); }
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user