summaryrefslogtreecommitdiff
path: root/ELF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-24 01:00:50 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-24 01:00:50 +0000
commit0d9ba4fe26725cacc7253fc3c72c4574f26bc099 (patch)
tree90c426d54188ca226b29aaf8a308bba364a73d1a /ELF
parenteb1ff93d02b5f17b6b409e83c6d9be585f4a04b3 (diff)
Notes
Diffstat (limited to 'ELF')
-rw-r--r--ELF/AArch64ErrataFix.cpp4
-rw-r--r--ELF/Arch/ARM.cpp12
-rw-r--r--ELF/Driver.cpp4
-rw-r--r--ELF/InputFiles.cpp114
-rw-r--r--ELF/InputFiles.h15
-rw-r--r--ELF/InputSection.cpp201
-rw-r--r--ELF/InputSection.h14
-rw-r--r--ELF/MarkLive.cpp4
-rw-r--r--ELF/Relocations.cpp112
-rw-r--r--ELF/ScriptParser.cpp2
-rw-r--r--ELF/SymbolTable.cpp100
-rw-r--r--ELF/SymbolTable.h10
-rw-r--r--ELF/Symbols.cpp16
-rw-r--r--ELF/Symbols.h27
-rw-r--r--ELF/SyntheticSections.cpp77
-rw-r--r--ELF/SyntheticSections.h9
-rw-r--r--ELF/Target.cpp2
-rw-r--r--ELF/Target.h4
-rw-r--r--ELF/Thunks.cpp32
-rw-r--r--ELF/Writer.cpp118
-rw-r--r--ELF/Writer.h2
21 files changed, 429 insertions, 450 deletions
diff --git a/ELF/AArch64ErrataFix.cpp b/ELF/AArch64ErrataFix.cpp
index 6cc68cc08e10c..9c0d536dea71e 100644
--- a/ELF/AArch64ErrataFix.cpp
+++ b/ELF/AArch64ErrataFix.cpp
@@ -400,8 +400,8 @@ lld::elf::Patch843419Section::Patch843419Section(InputSection *P, uint64_t Off)
this->Parent = P->getParent();
PatchSym = addSyntheticLocal(
Saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0,
- getSize(), this);
- addSyntheticLocal(Saver.save("$x"), STT_NOTYPE, 0, 0, this);
+ getSize(), *this);
+ addSyntheticLocal(Saver.save("$x"), STT_NOTYPE, 0, 0, *this);
}
uint64_t lld::elf::Patch843419Section::getLDSTAddr() const {
diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp
index 94a98e7679bdd..b9f551e4b3be8 100644
--- a/ELF/Arch/ARM.cpp
+++ b/ELF/Arch/ARM.cpp
@@ -37,8 +37,8 @@ public:
void writePltHeader(uint8_t *Buf) const override;
void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
int32_t Index, unsigned RelOff) const override;
- void addPltSymbols(InputSectionBase *IS, uint64_t Off) const override;
- void addPltHeaderSymbols(InputSectionBase *ISD) const override;
+ void addPltSymbols(InputSection &IS, uint64_t Off) const override;
+ void addPltHeaderSymbols(InputSection &ISD) const override;
bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
uint64_t BranchAddr, const Symbol &S) const override;
bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override;
@@ -184,7 +184,7 @@ void ARM::writeIgotPlt(uint8_t *Buf, const Symbol &S) const {
write32le(Buf, S.getVA());
}
-// Long form PLT Heade that does not have any restrictions on the displacement
+// Long form PLT Header that does not have any restrictions on the displacement
// of the .plt from the .plt.got.
static void writePltHeaderLong(uint8_t *Buf) {
const uint8_t PltData[] = {
@@ -232,8 +232,7 @@ void ARM::writePltHeader(uint8_t *Buf) const {
write32le(Buf + 28, TrapInstr);
}
-void ARM::addPltHeaderSymbols(InputSectionBase *ISD) const {
- auto *IS = cast<InputSection>(ISD);
+void ARM::addPltHeaderSymbols(InputSection &IS) const {
addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS);
addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS);
}
@@ -282,8 +281,7 @@ void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
write32le(Buf + 12, TrapInstr); // Pad to 16-byte boundary
}
-void ARM::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const {
- auto *IS = cast<InputSection>(ISD);
+void ARM::addPltSymbols(InputSection &IS, uint64_t Off) const {
addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS);
addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS);
}
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 2b6925031b07d..cc76fea2ad5e5 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -1056,7 +1056,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// We need to create some reserved symbols such as _end. Create them.
if (!Config->Relocatable)
- addReservedSymbols<ELFT>();
+ addReservedSymbols();
// Apply version scripts.
Symtab->scanVersionScript();
@@ -1111,7 +1111,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// before decompressAndMergeSections because the .comment section is a
// mergeable section.
if (!Config->Relocatable)
- InputSections.push_back(createCommentSection<ELFT>());
+ InputSections.push_back(createCommentSection());
// Do size optimizations: garbage collection, merging of SHF_MERGE sections
// and identical code folding.
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 1f68340c94289..f514870ca84ab 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -32,6 +32,7 @@
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
+using namespace llvm::sys;
using namespace llvm::sys::fs;
using namespace lld;
@@ -69,6 +70,50 @@ Optional<MemoryBufferRef> elf::readFile(StringRef Path) {
return MBRef;
}
+// Concatenates arguments to construct a string representing an error location.
+static std::string createFileLineMsg(StringRef Path, unsigned Line) {
+ std::string Filename = path::filename(Path);
+ std::string Lineno = ":" + std::to_string(Line);
+ if (Filename == Path)
+ return Filename + Lineno;
+ return Filename + Lineno + " (" + Path.str() + Lineno + ")";
+}
+
+template <class ELFT>
+static std::string getSrcMsgAux(ObjFile<ELFT> &File, const Symbol &Sym,
+ InputSectionBase &Sec, uint64_t Offset) {
+ // In DWARF, functions and variables are stored to different places.
+ // First, lookup a function for a given offset.
+ if (Optional<DILineInfo> Info = File.getDILineInfo(&Sec, Offset))
+ return createFileLineMsg(Info->FileName, Info->Line);
+
+ // If it failed, lookup again as a variable.
+ if (Optional<std::pair<std::string, unsigned>> FileLine =
+ File.getVariableLoc(Sym.getName()))
+ return createFileLineMsg(FileLine->first, FileLine->second);
+
+ // File.SourceFile contains STT_FILE symbol, and that is a last resort.
+ return File.SourceFile;
+}
+
+std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,
+ uint64_t Offset) {
+ if (kind() != ObjKind)
+ return "";
+ switch (Config->EKind) {
+ default:
+ llvm_unreachable("Invalid kind");
+ case ELF32LEKind:
+ return getSrcMsgAux(cast<ObjFile<ELF32LE>>(*this), Sym, Sec, Offset);
+ case ELF32BEKind:
+ return getSrcMsgAux(cast<ObjFile<ELF32BE>>(*this), Sym, Sec, Offset);
+ case ELF64LEKind:
+ return getSrcMsgAux(cast<ObjFile<ELF64LE>>(*this), Sym, Sec, Offset);
+ case ELF64BEKind:
+ return getSrcMsgAux(cast<ObjFile<ELF64BE>>(*this), Sym, Sec, Offset);
+ }
+}
+
template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(this));
const DWARFObject &Obj = Dwarf.getDWARFObj();
@@ -384,8 +429,8 @@ void ObjFile<ELFT>::initializeSections(
// have a SHF_LINK_ORDER dependency, this is identified by the sh_link.
if (Sec.sh_flags & SHF_LINK_ORDER) {
if (Sec.sh_link >= this->Sections.size())
- fatal(toString(this) + ": invalid sh_link index: " +
- Twine(Sec.sh_link));
+ fatal(toString(this) +
+ ": invalid sh_link index: " + Twine(Sec.sh_link));
this->Sections[Sec.sh_link]->DependentSections.push_back(
cast<InputSection>(this->Sections[I]));
}
@@ -454,11 +499,9 @@ InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
// Create a regular InputSection class that has the same contents
// as a given section.
-InputSectionBase *toRegularSection(MergeInputSection *Sec) {
- auto *Ret = make<InputSection>(Sec->Flags, Sec->Type, Sec->Alignment,
- Sec->Data, Sec->Name);
- Ret->File = Sec->File;
- return Ret;
+static InputSection *toRegularSection(MergeInputSection *Sec) {
+ return make<InputSection>(Sec->File, Sec->Flags, Sec->Type, Sec->Alignment,
+ Sec->Data, Sec->Name);
}
template <class ELFT>
@@ -471,13 +514,13 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
break;
ARMAttributeParser Attributes;
ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec));
- Attributes.Parse(Contents, /*isLittle*/Config->EKind == ELF32LEKind);
+ Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind);
updateSupportedARMFeatures(Attributes);
// FIXME: Retain the first attribute section we see. The eglibc ARM
// dynamic loaders require the presence of an attribute section for dlopen
// to work. In a full implementation we would merge all attribute sections.
if (InX::ARMAttributes == nullptr) {
- InX::ARMAttributes = make<InputSection>(this, &Sec, Name);
+ InX::ARMAttributes = make<InputSection>(*this, Sec, Name);
return InX::ARMAttributes;
}
return &InputSection::Discarded;
@@ -496,7 +539,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
// If -r is given, we do not interpret or apply relocation
// but just copy relocation sections to output.
if (Config->Relocatable)
- return make<InputSection>(this, &Sec, Name);
+ return make<InputSection>(*this, Sec, Name);
if (Target->FirstRelocation)
fatal(toString(this) +
@@ -534,7 +577,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
// However, if -emit-relocs is given, we need to leave them in the output.
// (Some post link analysis tools need this information.)
if (Config->EmitRelocs) {
- InputSection *RelocSec = make<InputSection>(this, &Sec, Name);
+ InputSection *RelocSec = make<InputSection>(*this, Sec, Name);
// We will not emit relocation section if target was discarded.
Target->DependentSections.push_back(RelocSec);
return RelocSec;
@@ -581,11 +624,11 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
// .eh_frame_hdr section for runtime. So we handle them with a special
// class. For relocatable outputs, they are just passed through.
if (Name == ".eh_frame" && !Config->Relocatable)
- return make<EhInputSection>(this, &Sec, Name);
+ return make<EhInputSection>(*this, Sec, Name);
if (shouldMerge(Sec))
- return make<MergeInputSection>(this, &Sec, Name);
- return make<InputSection>(this, &Sec, Name);
+ return make<MergeInputSection>(*this, Sec, Name);
+ return make<InputSection>(*this, Sec, Name);
}
template <class ELFT>
@@ -636,7 +679,7 @@ template <class ELFT> Symbol *ObjFile<ELFT>::createSymbol(const Elf_Sym *Sym) {
if (Value == 0 || Value >= UINT32_MAX)
fatal(toString(this) + ": common symbol '" + Name +
"' has invalid alignment: " + Twine(Value));
- return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, this);
+ return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, *this);
}
switch (Binding) {
@@ -648,8 +691,8 @@ template <class ELFT> Symbol *ObjFile<ELFT>::createSymbol(const Elf_Sym *Sym) {
if (Sec == &InputSection::Discarded)
return Symtab->addUndefined<ELFT>(Name, Binding, StOther, Type,
/*CanOmitFromDynSym=*/false, this);
- return Symtab->addRegular<ELFT>(Name, StOther, Type, Value, Size, Binding,
- Sec, this);
+ return Symtab->addRegular(Name, StOther, Type, Value, Size, Binding, Sec,
+ this);
}
}
@@ -660,7 +703,7 @@ ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File)
template <class ELFT> void ArchiveFile::parse() {
Symbols.reserve(File->getNumberOfSymbols());
for (const Archive::Symbol &Sym : File->symbols())
- Symbols.push_back(Symtab->addLazyArchive<ELFT>(Sym.getName(), this, Sym));
+ Symbols.push_back(Symtab->addLazyArchive<ELFT>(Sym.getName(), *this, Sym));
}
// Returns a buffer pointing to a member file containing a given symbol.
@@ -841,14 +884,14 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() {
error(toString(this) + ": alignment too large: " + Name);
if (!Hidden)
- Symtab->addShared(Name, this, Sym, Alignment, VersymIndex);
+ Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex);
// Also add the symbol with the versioned name to handle undefined symbols
// with explicit versions.
if (Ver) {
StringRef VerName = this->StringTable.data() + Ver->getAux()->vda_name;
Name = Saver.save(Name + "@" + VerName);
- Symtab->addShared(Name, this, Sym, Alignment, VersymIndex);
+ Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex);
}
}
}
@@ -925,7 +968,7 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {
template <class ELFT>
static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
const lto::InputFile::Symbol &ObjSym,
- BitcodeFile *F) {
+ BitcodeFile &F) {
StringRef NameRef = Saver.save(ObjSym.getName());
uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL;
@@ -936,11 +979,11 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
int C = ObjSym.getComdatIndex();
if (C != -1 && !KeptComdats[C])
return Symtab->addUndefined<ELFT>(NameRef, Binding, Visibility, Type,
- CanOmitFromDynSym, F);
+ CanOmitFromDynSym, &F);
if (ObjSym.isUndefined())
return Symtab->addUndefined<ELFT>(NameRef, Binding, Visibility, Type,
- CanOmitFromDynSym, F);
+ CanOmitFromDynSym, &F);
if (ObjSym.isCommon())
return Symtab->addCommon(NameRef, ObjSym.getCommonSize(),
@@ -958,7 +1001,7 @@ void BitcodeFile::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {
KeptComdats.push_back(ComdatGroups.insert(CachedHashStringRef(S)).second);
for (const lto::InputFile::Symbol &ObjSym : Obj->symbols())
- Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, this));
+ Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, *this));
}
static ELFKind getELFKind(MemoryBufferRef MB) {
@@ -981,10 +1024,10 @@ static ELFKind getELFKind(MemoryBufferRef MB) {
return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind;
}
-template <class ELFT> void BinaryFile::parse() {
+void BinaryFile::parse() {
ArrayRef<uint8_t> Data = toArrayRef(MB.getBuffer());
- auto *Section =
- make<InputSection>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 8, Data, ".data");
+ auto *Section = make<InputSection>(nullptr, SHF_ALLOC | SHF_WRITE,
+ SHT_PROGBITS, 8, Data, ".data");
Sections.push_back(Section);
// For each input file foo that is embedded to a result as a binary
@@ -996,12 +1039,12 @@ template <class ELFT> void BinaryFile::parse() {
if (!isAlnum(S[I]))
S[I] = '_';
- Symtab->addRegular<ELFT>(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT,
- 0, 0, STB_GLOBAL, Section, nullptr);
- Symtab->addRegular<ELFT>(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT,
- Data.size(), 0, STB_GLOBAL, Section, nullptr);
- Symtab->addRegular<ELFT>(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT,
- Data.size(), 0, STB_GLOBAL, nullptr, nullptr);
+ Symtab->addRegular(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT, 0, 0,
+ STB_GLOBAL, Section, nullptr);
+ Symtab->addRegular(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT,
+ Data.size(), 0, STB_GLOBAL, Section, nullptr);
+ Symtab->addRegular(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT,
+ Data.size(), 0, STB_GLOBAL, nullptr, nullptr);
}
static bool isBitcode(MemoryBufferRef MB) {
@@ -1145,8 +1188,3 @@ template class elf::SharedFile<ELF32LE>;
template class elf::SharedFile<ELF32BE>;
template class elf::SharedFile<ELF64LE>;
template class elf::SharedFile<ELF64BE>;
-
-template void BinaryFile::parse<ELF32LE>();
-template void BinaryFile::parse<ELF32BE>();
-template void BinaryFile::parse<ELF64LE>();
-template void BinaryFile::parse<ELF64BE>();
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 427f2fdea53ee..dda1de81570cc 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -72,6 +72,11 @@ public:
Kind kind() const { return FileKind; }
+ bool isElf() const {
+ Kind K = kind();
+ return K == ObjKind || K == SharedKind;
+ }
+
StringRef getName() const { return MB.getBufferIdentifier(); }
MemoryBufferRef MB;
@@ -104,6 +109,9 @@ public:
// Cache for toString(). Only toString() should use this member.
mutable std::string ToStringCache;
+ std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,
+ uint64_t Offset);
+
protected:
InputFile(Kind K, MemoryBufferRef M);
std::vector<InputSectionBase *> Sections;
@@ -121,10 +129,7 @@ public:
typedef typename ELFT::SymRange Elf_Sym_Range;
ELFFileBase(Kind K, MemoryBufferRef M);
- static bool classof(const InputFile *F) {
- Kind K = F->kind();
- return K == ObjKind || K == SharedKind;
- }
+ static bool classof(const InputFile *F) { return F->isElf(); }
llvm::object::ELFFile<ELFT> getObj() const {
return check(llvm::object::ELFFile<ELFT>::create(MB.getBuffer()));
@@ -325,7 +330,7 @@ class BinaryFile : public InputFile {
public:
explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {}
static bool classof(const InputFile *F) { return F->kind() == BinaryKind; }
- template <class ELFT> void parse();
+ void parse();
};
InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index 02cad56ca5088..93baefadce6e8 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -24,7 +24,6 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/xxhash.h"
#include <mutex>
@@ -73,11 +72,11 @@ DenseMap<SectionBase *, int> elf::buildSectionOrder() {
}
template <class ELFT>
-static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> *File,
- const typename ELFT::Shdr *Hdr) {
- if (!File || Hdr->sh_type == SHT_NOBITS)
- return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size);
- return check(File->getObj().getSectionContents(Hdr));
+static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> &File,
+ const typename ELFT::Shdr &Hdr) {
+ if (Hdr.sh_type == SHT_NOBITS)
+ return makeArrayRef<uint8_t>(nullptr, Hdr.sh_size);
+ return check(File.getObj().getSectionContents(&Hdr));
}
InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
@@ -88,6 +87,12 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
: SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info,
Link),
File(File), Data(Data) {
+ // In order to reduce memory allocation, we assume that mergeable
+ // sections are smaller than 4 GiB, which is not an unreasonable
+ // assumption as of 2017.
+ if (SectionKind == SectionBase::Merge && Data.size() > UINT32_MAX)
+ error(toString(this) + ": section too large");
+
NumRelocations = 0;
AreRelocsRela = false;
@@ -128,18 +133,18 @@ static uint64_t getType(uint64_t Type, StringRef Name) {
}
template <class ELFT>
-InputSectionBase::InputSectionBase(ObjFile<ELFT> *File,
- const typename ELFT::Shdr *Hdr,
+InputSectionBase::InputSectionBase(ObjFile<ELFT> &File,
+ const typename ELFT::Shdr &Hdr,
StringRef Name, Kind SectionKind)
- : InputSectionBase(File, getFlags(Hdr->sh_flags),
- getType(Hdr->sh_type, Name), Hdr->sh_entsize,
- Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign,
+ : InputSectionBase(&File, getFlags(Hdr.sh_flags),
+ getType(Hdr.sh_type, Name), Hdr.sh_entsize, Hdr.sh_link,
+ Hdr.sh_info, Hdr.sh_addralign,
getSectionContents(File, Hdr), Name, SectionKind) {
// We reject object files having insanely large alignments even though
// they are allowed by the spec. I think 4GB is a reasonable limitation.
// We might want to relax this in the future.
- if (Hdr->sh_addralign > UINT32_MAX)
- fatal(toString(File) + ": section sh_addralign is too large");
+ if (Hdr.sh_addralign > UINT32_MAX)
+ fatal(toString(&File) + ": section sh_addralign is too large");
}
size_t InputSectionBase::getSize() const {
@@ -211,8 +216,8 @@ void InputSectionBase::maybeUncompress() {
fatal(toString(this) +
": decompress failed: " + llvm::toString(std::move(E)));
- this->Data = makeArrayRef((uint8_t *)UncompressBuf.get(), Size);
- this->Flags &= ~(uint64_t)SHF_COMPRESSED;
+ Data = makeArrayRef((uint8_t *)UncompressBuf.get(), Size);
+ Flags &= ~(uint64_t)SHF_COMPRESSED;
}
InputSection *InputSectionBase::getLinkOrderDep() const {
@@ -257,40 +262,17 @@ std::string InputSectionBase::getLocation(uint64_t Offset) {
return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str();
}
-// Concatenates arguments to construct a string representing an error location.
-static std::string createFileLineMsg(StringRef Path, unsigned Line) {
- std::string Filename = path::filename(Path);
- std::string Lineno = ":" + std::to_string(Line);
- if (Filename == Path)
- return Filename + Lineno;
- return Filename + Lineno + " (" + Path.str() + Lineno + ")";
-}
-
// This function is intended to be used for constructing an error message.
// The returned message looks like this:
//
// foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42)
//
// Returns an empty string if there's no way to get line info.
-template <class ELFT>
std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) {
// Synthetic sections don't have input files.
- ObjFile<ELFT> *File = getFile<ELFT>();
if (!File)
return "";
-
- // In DWARF, functions and variables are stored to different places.
- // First, lookup a function for a given offset.
- if (Optional<DILineInfo> Info = File->getDILineInfo(this, Offset))
- return createFileLineMsg(Info->FileName, Info->Line);
-
- // If it failed, lookup again as a variable.
- if (Optional<std::pair<std::string, unsigned>> FileLine =
- File->getVariableLoc(Sym.getName()))
- return createFileLineMsg(FileLine->first, FileLine->second);
-
- // File->SourceFile contains STT_FILE symbol, and that is a last resort.
- return File->SourceFile;
+ return File->getSrcMsg(Sym, *this, Offset);
}
// Returns a filename string along with an optional section name. This
@@ -323,16 +305,17 @@ std::string InputSectionBase::getObjMsg(uint64_t Off) {
.str();
}
-InputSection InputSection::Discarded(0, 0, 0, ArrayRef<uint8_t>(), "");
+InputSection InputSection::Discarded(nullptr, 0, 0, 0, ArrayRef<uint8_t>(), "");
-InputSection::InputSection(uint64_t Flags, uint32_t Type, uint32_t Alignment,
- ArrayRef<uint8_t> Data, StringRef Name, Kind K)
- : InputSectionBase(nullptr, Flags, Type,
+InputSection::InputSection(InputFile *F, uint64_t Flags, uint32_t Type,
+ uint32_t Alignment, ArrayRef<uint8_t> Data,
+ StringRef Name, Kind K)
+ : InputSectionBase(F, Flags, Type,
/*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Alignment, Data,
Name, K) {}
template <class ELFT>
-InputSection::InputSection(ObjFile<ELFT> *F, const typename ELFT::Shdr *Header,
+InputSection::InputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,
StringRef Name)
: InputSectionBase(F, Header, Name, InputSectionBase::Regular) {}
@@ -357,15 +340,15 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) {
// Adjust section numbers because section numbers in an input object
// files are different in the output.
- ArrayRef<InputSectionBase *> Sections = this->File->getSections();
+ ArrayRef<InputSectionBase *> Sections = File->getSections();
for (uint32_t Idx : From.slice(1))
*To++ = Sections[Idx]->getOutputSection()->SectionIndex;
}
InputSectionBase *InputSection::getRelocatedSection() {
- assert(this->Type == SHT_RELA || this->Type == SHT_REL);
- ArrayRef<InputSectionBase *> Sections = this->File->getSections();
- return Sections[this->Info];
+ assert(Type == SHT_RELA || Type == SHT_REL);
+ ArrayRef<InputSectionBase *> Sections = File->getSections();
+ return Sections[Info];
}
// This is used for -r and --emit-relocs. We can't use memcpy to copy
@@ -377,7 +360,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
for (const RelTy &Rel : Rels) {
RelType Type = Rel.getType(Config->IsMips64EL);
- Symbol &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel);
+ Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel);
auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf);
Buf += sizeof(RelTy);
@@ -679,7 +662,7 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
if (!RelTy::IsRela)
Addend += Target->getImplicitAddend(BufLoc, Type);
- Symbol &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel);
+ Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel);
RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc);
if (Expr == R_NONE)
continue;
@@ -691,7 +674,7 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
if (Config->EMachine == EM_386 && Type == R_386_GOTPC)
continue;
- error(this->getLocation<ELFT>(Offset) + ": has non-ABS relocation " +
+ error(getLocation<ELFT>(Offset) + ": has non-ABS relocation " +
toString(Type) + " against symbol '" + toString(Sym) + "'");
return;
}
@@ -765,7 +748,7 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
}
template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
- if (this->Type == SHT_NOBITS)
+ if (Type == SHT_NOBITS)
return;
if (auto *S = dyn_cast<SyntheticSection>(this)) {
@@ -775,19 +758,17 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
// If -r or --emit-relocs is given, then an InputSection
// may be a relocation section.
- if (this->Type == SHT_RELA) {
- copyRelocations<ELFT>(Buf + OutSecOff,
- this->template getDataAs<typename ELFT::Rela>());
+ if (Type == SHT_RELA) {
+ copyRelocations<ELFT>(Buf + OutSecOff, getDataAs<typename ELFT::Rela>());
return;
}
- if (this->Type == SHT_REL) {
- copyRelocations<ELFT>(Buf + OutSecOff,
- this->template getDataAs<typename ELFT::Rel>());
+ if (Type == SHT_REL) {
+ copyRelocations<ELFT>(Buf + OutSecOff, getDataAs<typename ELFT::Rel>());
return;
}
// If -r is given, we may have a SHT_GROUP section.
- if (this->Type == SHT_GROUP) {
+ if (Type == SHT_GROUP) {
copyShtGroup<ELFT>(Buf + OutSecOff);
return;
}
@@ -796,18 +777,18 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
// and then apply relocations.
memcpy(Buf + OutSecOff, Data.data(), Data.size());
uint8_t *BufEnd = Buf + OutSecOff + Data.size();
- this->relocate<ELFT>(Buf, BufEnd);
+ relocate<ELFT>(Buf, BufEnd);
}
void InputSection::replace(InputSection *Other) {
- this->Alignment = std::max(this->Alignment, Other->Alignment);
- Other->Repl = this->Repl;
+ Alignment = std::max(Alignment, Other->Alignment);
+ Other->Repl = Repl;
Other->Live = false;
}
template <class ELFT>
-EhInputSection::EhInputSection(ObjFile<ELFT> *F,
- const typename ELFT::Shdr *Header,
+EhInputSection::EhInputSection(ObjFile<ELFT> &F,
+ const typename ELFT::Shdr &Header,
StringRef Name)
: InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) {}
@@ -838,22 +819,21 @@ static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels,
// This function splits an input section into records and returns them.
template <class ELFT> void EhInputSection::split() {
// Early exit if already split.
- if (!this->Pieces.empty())
+ if (!Pieces.empty())
return;
- if (this->AreRelocsRela)
- split<ELFT>(this->relas<ELFT>());
+ if (AreRelocsRela)
+ split<ELFT>(relas<ELFT>());
else
- split<ELFT>(this->rels<ELFT>());
+ split<ELFT>(rels<ELFT>());
}
template <class ELFT, class RelTy>
void EhInputSection::split(ArrayRef<RelTy> Rels) {
- ArrayRef<uint8_t> Data = this->Data;
unsigned RelI = 0;
for (size_t Off = 0, End = Data.size(); Off != End;) {
size_t Size = readEhRecordSize(this, Off);
- this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI));
+ Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI));
// The empty record is the end marker.
if (Size == 4)
break;
@@ -882,7 +862,7 @@ SyntheticSection *MergeInputSection::getParent() const {
// null-terminated strings.
void MergeInputSection::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) {
size_t Off = 0;
- bool IsAlloc = this->Flags & SHF_ALLOC;
+ bool IsAlloc = Flags & SHF_ALLOC;
StringRef S = toStringRef(Data);
while (!S.empty()) {
@@ -903,7 +883,7 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data,
size_t EntSize) {
size_t Size = Data.size();
assert((Size % EntSize) == 0);
- bool IsAlloc = this->Flags & SHF_ALLOC;
+ bool IsAlloc = Flags & SHF_ALLOC;
for (size_t I = 0; I != Size; I += EntSize)
Pieces.emplace_back(I, xxHash64(toStringRef(Data.slice(I, EntSize))),
@@ -911,16 +891,16 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data,
}
template <class ELFT>
-MergeInputSection::MergeInputSection(ObjFile<ELFT> *F,
- const typename ELFT::Shdr *Header,
+MergeInputSection::MergeInputSection(ObjFile<ELFT> &F,
+ const typename ELFT::Shdr &Header,
StringRef Name)
- : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {
- // In order to reduce memory allocation, we assume that mergeable
- // sections are smaller than 4 GiB, which is not an unreasonable
- // assumption as of 2017.
- if (Data.size() > UINT32_MAX)
- error(toString(this) + ": section too large");
-}
+ : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {}
+
+MergeInputSection::MergeInputSection(uint64_t Flags, uint32_t Type,
+ uint64_t Entsize, ArrayRef<uint8_t> Data,
+ StringRef Name)
+ : InputSectionBase(nullptr, Flags, Type, Entsize, /*Link*/ 0, /*Info*/ 0,
+ /*Alignment*/ Entsize, Data, Name, SectionBase::Merge) {}
// This function is called after we obtain a complete list of input sections
// that need to be linked. This is responsible to split section contents
@@ -931,14 +911,14 @@ MergeInputSection::MergeInputSection(ObjFile<ELFT> *F,
void MergeInputSection::splitIntoPieces() {
assert(Pieces.empty());
- if (this->Flags & SHF_STRINGS)
+ if (Flags & SHF_STRINGS)
splitStrings(Data, Entsize);
else
splitNonStrings(Data, Entsize);
- if (Config->GcSections && (this->Flags & SHF_ALLOC))
+ if (Config->GcSections && (Flags & SHF_ALLOC))
for (uint64_t Off : LiveOffsets)
- this->getSectionPiece(Off)->Live = true;
+ getSectionPiece(Off)->Live = true;
}
// Do binary search to get a section piece at a given input offset.
@@ -993,7 +973,7 @@ uint64_t MergeInputSection::getOffset(uint64_t Offset) const {
// If Offset is not at beginning of a section piece, it is not in the map.
// In that case we need to search from the original section piece vector.
- const SectionPiece &Piece = *this->getSectionPiece(Offset);
+ const SectionPiece &Piece = *getSectionPiece(Offset);
if (!Piece.Live)
return 0;
@@ -1001,13 +981,13 @@ uint64_t MergeInputSection::getOffset(uint64_t Offset) const {
return Piece.OutputOff + Addend;
}
-template InputSection::InputSection(ObjFile<ELF32LE> *, const ELF32LE::Shdr *,
+template InputSection::InputSection(ObjFile<ELF32LE> &, const ELF32LE::Shdr &,
StringRef);
-template InputSection::InputSection(ObjFile<ELF32BE> *, const ELF32BE::Shdr *,
+template InputSection::InputSection(ObjFile<ELF32BE> &, const ELF32BE::Shdr &,
StringRef);
-template InputSection::InputSection(ObjFile<ELF64LE> *, const ELF64LE::Shdr *,
+template InputSection::InputSection(ObjFile<ELF64LE> &, const ELF64LE::Shdr &,
StringRef);
-template InputSection::InputSection(ObjFile<ELF64BE> *, const ELF64BE::Shdr *,
+template InputSection::InputSection(ObjFile<ELF64BE> &, const ELF64BE::Shdr &,
StringRef);
template std::string InputSectionBase::getLocation<ELF32LE>(uint64_t);
@@ -1015,37 +995,28 @@ template std::string InputSectionBase::getLocation<ELF32BE>(uint64_t);
template std::string InputSectionBase::getLocation<ELF64LE>(uint64_t);
template std::string InputSectionBase::getLocation<ELF64BE>(uint64_t);
-template std::string InputSectionBase::getSrcMsg<ELF32LE>(const Symbol &,
- uint64_t);
-template std::string InputSectionBase::getSrcMsg<ELF32BE>(const Symbol &,
- uint64_t);
-template std::string InputSectionBase::getSrcMsg<ELF64LE>(const Symbol &,
- uint64_t);
-template std::string InputSectionBase::getSrcMsg<ELF64BE>(const Symbol &,
- uint64_t);
-
template void InputSection::writeTo<ELF32LE>(uint8_t *);
template void InputSection::writeTo<ELF32BE>(uint8_t *);
template void InputSection::writeTo<ELF64LE>(uint8_t *);
template void InputSection::writeTo<ELF64BE>(uint8_t *);
-template MergeInputSection::MergeInputSection(ObjFile<ELF32LE> *,
- const ELF32LE::Shdr *, StringRef);
-template MergeInputSection::MergeInputSection(ObjFile<ELF32BE> *,
- const ELF32BE::Shdr *, StringRef);
-template MergeInputSection::MergeInputSection(ObjFile<ELF64LE> *,
- const ELF64LE::Shdr *, StringRef);
-template MergeInputSection::MergeInputSection(ObjFile<ELF64BE> *,
- const ELF64BE::Shdr *, StringRef);
-
-template EhInputSection::EhInputSection(ObjFile<ELF32LE> *,
- const ELF32LE::Shdr *, StringRef);
-template EhInputSection::EhInputSection(ObjFile<ELF32BE> *,
- const ELF32BE::Shdr *, StringRef);
-template EhInputSection::EhInputSection(ObjFile<ELF64LE> *,
- const ELF64LE::Shdr *, StringRef);
-template EhInputSection::EhInputSection(ObjFile<ELF64BE> *,
- const ELF64BE::Shdr *, StringRef);
+template MergeInputSection::MergeInputSection(ObjFile<ELF32LE> &,
+ const ELF32LE::Shdr &, StringRef);
+template MergeInputSection::MergeInputSection(ObjFile<ELF32BE> &,
+ const ELF32BE::Shdr &, StringRef);
+template MergeInputSection::MergeInputSection(ObjFile<ELF64LE> &,
+ const ELF64LE::Shdr &, StringRef);
+template MergeInputSection::MergeInputSection(ObjFile<ELF64BE> &,
+ const ELF64BE::Shdr &, StringRef);
+
+template EhInputSection::EhInputSection(ObjFile<ELF32LE> &,
+ const ELF32LE::Shdr &, StringRef);
+template EhInputSection::EhInputSection(ObjFile<ELF32BE> &,
+ const ELF32BE::Shdr &, StringRef);
+template EhInputSection::EhInputSection(ObjFile<ELF64LE> &,
+ const ELF64LE::Shdr &, StringRef);
+template EhInputSection::EhInputSection(ObjFile<ELF64BE> &,
+ const ELF64BE::Shdr &, StringRef);
template void EhInputSection::split<ELF32LE>();
template void EhInputSection::split<ELF32BE>();
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index dfd78a8fb4588..8c114ae719481 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -93,7 +93,7 @@ protected:
class InputSectionBase : public SectionBase {
public:
template <class ELFT>
- InputSectionBase(ObjFile<ELFT> *File, const typename ELFT::Shdr *Header,
+ InputSectionBase(ObjFile<ELFT> &File, const typename ELFT::Shdr &Header,
StringRef Name, Kind SectionKind);
InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Type,
@@ -168,7 +168,6 @@ public:
// Returns a source location string. Used to construct an error message.
template <class ELFT> std::string getLocation(uint64_t Offset);
- template <class ELFT>
std::string getSrcMsg(const Symbol &Sym, uint64_t Offset);
std::string getObjMsg(uint64_t Offset);
@@ -216,8 +215,11 @@ static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big");
class MergeInputSection : public InputSectionBase {
public:
template <class ELFT>
- MergeInputSection(ObjFile<ELFT> *F, const typename ELFT::Shdr *Header,
+ MergeInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,
StringRef Name);
+ MergeInputSection(uint64_t Flags, uint32_t Type, uint64_t Entsize,
+ ArrayRef<uint8_t> Data, StringRef Name);
+
static bool classof(const SectionBase *S) { return S->kind() == Merge; }
void splitIntoPieces();
@@ -279,7 +281,7 @@ struct EhSectionPiece {
class EhInputSection : public InputSectionBase {
public:
template <class ELFT>
- EhInputSection(ObjFile<ELFT> *F, const typename ELFT::Shdr *Header,
+ EhInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,
StringRef Name);
static bool classof(const SectionBase *S) { return S->kind() == EHFrame; }
template <class ELFT> void split();
@@ -298,10 +300,10 @@ public:
// .eh_frame. It also includes the synthetic sections themselves.
class InputSection : public InputSectionBase {
public:
- InputSection(uint64_t Flags, uint32_t Type, uint32_t Alignment,
+ InputSection(InputFile *F, uint64_t Flags, uint32_t Type, uint32_t Alignment,
ArrayRef<uint8_t> Data, StringRef Name, Kind K = Regular);
template <class ELFT>
- InputSection(ObjFile<ELFT> *F, const typename ELFT::Shdr *Header,
+ InputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,
StringRef Name);
// Write this section to a mmap'ed file, assuming Buf is pointing to
diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp
index 36f994f204903..88f558c7a3c6e 100644
--- a/ELF/MarkLive.cpp
+++ b/ELF/MarkLive.cpp
@@ -68,7 +68,7 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
B.Used = true;
if (auto *SS = dyn_cast<SharedSymbol>(&B))
if (!SS->isWeak())
- SS->getFile<ELFT>()->IsNeeded = true;
+ SS->getFile<ELFT>().IsNeeded = true;
if (auto *D = dyn_cast<Defined>(&B)) {
auto *RelSec = dyn_cast_or_null<InputSectionBase>(D->Section);
@@ -246,7 +246,7 @@ template <class ELFT> static void doGcSections() {
// that point to .eh_frames. Otherwise, the garbage collector would drop
// all of them. We also want to preserve personality routines and LSDA
// referenced by .eh_frame sections, so we scan them for that here.
- if (auto *EH = dyn_cast_or_null<EhInputSection>(Sec)) {
+ if (auto *EH = dyn_cast<EhInputSection>(Sec)) {
EH->Live = true;
scanEhFrameSection<ELFT>(*EH, Enqueue);
}
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index 96e409578f5c2..94ea3e1557c48 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -70,12 +70,11 @@ using namespace lld::elf;
// >>> defined in /home/alice/src/foo.o
// >>> referenced by bar.c:12 (/home/alice/src/bar.c:12)
// >>> /home/alice/src/bar.o:(.text+0x1)
-template <class ELFT>
static std::string getLocation(InputSectionBase &S, const Symbol &Sym,
uint64_t Off) {
std::string Msg =
"\n>>> defined in " + toString(Sym.File) + "\n>>> referenced by ";
- std::string Src = S.getSrcMsg<ELFT>(Sym, Off);
+ std::string Src = S.getSrcMsg(Sym, Off);
if (!Src.empty())
Msg += Src + "\n>>> ";
return Msg + S.getObjMsg(Off);
@@ -365,7 +364,6 @@ static bool isRelExpr(RelExpr Expr) {
//
// If this function returns false, that means we need to emit a
// dynamic relocation so that the relocation will be fixed at load-time.
-template <class ELFT>
static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
InputSectionBase &S, uint64_t RelOff) {
// These expressions always compute a constant
@@ -410,7 +408,7 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
return true;
error("relocation " + toString(Type) + " cannot refer to absolute symbol: " +
- toString(Sym) + getLocation<ELFT>(S, Sym, RelOff));
+ toString(Sym) + getLocation(S, Sym, RelOff));
return true;
}
@@ -443,8 +441,8 @@ template <class ELFT> static bool isReadOnly(SharedSymbol *SS) {
typedef typename ELFT::Phdr Elf_Phdr;
// Determine if the symbol is read-only by scanning the DSO's program headers.
- const SharedFile<ELFT> *File = SS->getFile<ELFT>();
- for (const Elf_Phdr &Phdr : check(File->getObj().program_headers()))
+ const SharedFile<ELFT> &File = SS->getFile<ELFT>();
+ for (const Elf_Phdr &Phdr : check(File.getObj().program_headers()))
if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) &&
!(Phdr.p_flags & ELF::PF_W) && SS->Value >= Phdr.p_vaddr &&
SS->Value < Phdr.p_vaddr + Phdr.p_memsz)
@@ -461,14 +459,14 @@ template <class ELFT>
static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) {
typedef typename ELFT::Sym Elf_Sym;
- SharedFile<ELFT> *File = SS->getFile<ELFT>();
+ SharedFile<ELFT> &File = SS->getFile<ELFT>();
std::vector<SharedSymbol *> Ret;
- for (const Elf_Sym &S : File->getGlobalELFSyms()) {
+ for (const Elf_Sym &S : File.getGlobalELFSyms()) {
if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS ||
S.st_value != SS->Value)
continue;
- StringRef Name = check(S.getName(File->getStringTable()));
+ StringRef Name = check(S.getName(File.getStringTable()));
Symbol *Sym = Symtab->find(Name);
if (auto *Alias = dyn_cast_or_null<SharedSymbol>(Sym))
Ret.push_back(Alias);
@@ -554,22 +552,57 @@ static void errorOrWarn(const Twine &Msg) {
warn(Msg);
}
+// Returns PLT relocation expression.
+//
+// This handles a non PIC program call to function in a shared library. In
+// an ideal world, we could just report an error saying the relocation can
+// overflow at runtime. In the real world with glibc, crt1.o has a
+// R_X86_64_PC32 pointing to libc.so.
+//
+// The general idea on how to handle such cases is to create a PLT entry and
+// use that as the function value.
+//
+// For the static linking part, we just return a plt expr and everything
+// else will use the the PLT entry as the address.
+//
+// The remaining problem is making sure pointer equality still works. We
+// need the help of the dynamic linker for that. We let it know that we have
+// a direct reference to a so symbol by creating an undefined symbol with a
+// non zero st_value. Seeing that, the dynamic linker resolves the symbol to
+// the value of the symbol we created. This is true even for got entries, so
+// pointer equality is maintained. To avoid an infinite loop, the only entry
+// that points to the real function is a dedicated got entry used by the
+// plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
+// R_386_JMP_SLOT, etc).
+static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) {
+ Sym.NeedsPltAddr = true;
+ Sym.IsPreemptible = false;
+ IsConstant = true;
+ return toPlt(Expr);
+}
+
template <class ELFT>
static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
- InputSectionBase &S, uint64_t RelOff) {
+ InputSectionBase &S, uint64_t RelOff,
+ bool &IsConstant) {
// We can create any dynamic relocation if a section is simply writable.
if (S.Flags & SHF_WRITE)
return Expr;
// Or, if we are allowed to create dynamic relocations against
- // read-only sections (i.e. unless "-z notext" is given),
+ // read-only sections (i.e. when "-z notext" is given),
// we can create a dynamic relocation as we want, too.
- if (!Config->ZText)
+ if (!Config->ZText) {
+ // We use PLT for relocations that may overflow in runtime,
+ // see comment for getPltExpr().
+ if (Sym.isFunc() && !Target->isPicRel(Type))
+ return getPltExpr(Sym, Expr, IsConstant);
return Expr;
+ }
// If a relocation can be applied at link-time, we don't need to
// create a dynamic relocation in the first place.
- if (isStaticLinkTimeConstant<ELFT>(Expr, Type, Sym, S, RelOff))
+ if (IsConstant)
return Expr;
// If we got here we know that this relocation would require the dynamic
@@ -579,6 +612,7 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
// non preemptible 0.
if (Sym.isUndefWeak()) {
Sym.IsPreemptible = false;
+ IsConstant = true;
return Expr;
}
@@ -589,13 +623,13 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
"can't create dynamic relocation " + toString(Type) + " against " +
(Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) +
" in readonly segment; recompile object files with -fPIC" +
- getLocation<ELFT>(S, Sym, RelOff));
+ getLocation(S, Sym, RelOff));
return Expr;
}
if (Sym.getVisibility() != STV_DEFAULT) {
error("cannot preempt symbol: " + toString(Sym) +
- getLocation<ELFT>(S, Sym, RelOff));
+ getLocation(S, Sym, RelOff));
return Expr;
}
@@ -607,38 +641,16 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
error("unresolvable relocation " + toString(Type) +
" against symbol '" + toString(*B) +
"'; recompile with -fPIC or remove '-z nocopyreloc'" +
- getLocation<ELFT>(S, Sym, RelOff));
+ getLocation(S, Sym, RelOff));
addCopyRelSymbol<ELFT>(B);
}
+ IsConstant = true;
return Expr;
}
- if (Sym.isFunc()) {
- // This handles a non PIC program call to function in a shared library. In
- // an ideal world, we could just report an error saying the relocation can
- // overflow at runtime. In the real world with glibc, crt1.o has a
- // R_X86_64_PC32 pointing to libc.so.
- //
- // The general idea on how to handle such cases is to create a PLT entry and
- // use that as the function value.
- //
- // For the static linking part, we just return a plt expr and everything
- // else will use the the PLT entry as the address.
- //
- // The remaining problem is making sure pointer equality still works. We
- // need the help of the dynamic linker for that. We let it know that we have
- // a direct reference to a so symbol by creating an undefined symbol with a
- // non zero st_value. Seeing that, the dynamic linker resolves the symbol to
- // the value of the symbol we created. This is true even for got entries, so
- // pointer equality is maintained. To avoid an infinite loop, the only entry
- // that points to the real function is a dedicated got entry used by the
- // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
- // R_386_JMP_SLOT, etc).
- Sym.NeedsPltAddr = true;
- Sym.IsPreemptible = false;
- return toPlt(Expr);
- }
+ if (Sym.isFunc())
+ return getPltExpr(Sym, Expr, IsConstant);
errorOrWarn("symbol '" + toString(Sym) + "' defined in " +
toString(Sym.File) + " has no type");
@@ -708,7 +720,6 @@ static int64_t computeAddend(const RelTy &Rel, const RelTy *End,
// Report an undefined symbol if necessary.
// Returns true if this function printed out an error message.
-template <class ELFT>
static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec,
uint64_t Offset) {
if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll)
@@ -725,7 +736,7 @@ static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec,
std::string Msg =
"undefined symbol: " + toString(Sym) + "\n>>> referenced by ";
- std::string Src = Sec.getSrcMsg<ELFT>(Sym, Offset);
+ std::string Src = Sec.getSrcMsg(Sym, Offset);
if (!Src.empty())
Msg += Src + "\n>>> ";
Msg += Sec.getObjMsg(Offset);
@@ -846,7 +857,7 @@ template <class ELFT> static void addGotEntry(Symbol &Sym, bool Preemptible) {
//
// This is ugly -- the difference between REL and RELA should be
// handled in a better way. It's a TODO.
- if (!Config->IsRela)
+ if (!Config->IsRela && !Preemptible)
InX::Got->Relocations.push_back({R_ABS, Target->GotRel, Off, 0, &Sym});
}
@@ -885,7 +896,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
continue;
// Skip if the target symbol is an erroneous undefined symbol.
- if (maybeReportUndefined<ELFT>(Sym, Sec, Rel.r_offset))
+ if (maybeReportUndefined(Sym, Sec, Rel.r_offset))
continue;
RelExpr Expr =
@@ -923,7 +934,10 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
else if (!Preemptible)
Expr = fromPlt(Expr);
- Expr = adjustExpr<ELFT>(Sym, Expr, Type, Sec, Rel.r_offset);
+ bool IsConstant =
+ isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Rel.r_offset);
+
+ Expr = adjustExpr<ELFT>(Sym, Expr, Type, Sec, Rel.r_offset, IsConstant);
if (errorCount())
continue;
@@ -980,7 +994,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
errorOrWarn(
"relocation " + toString(Type) +
" cannot be used against shared object; recompile with -fPIC" +
- getLocation<ELFT>(Sec, Sym, Offset));
+ getLocation(Sec, Sym, Offset));
InX::RelaDyn->addReloc(
{Target->getDynRel(Type), &Sec, Offset, false, &Sym, Addend});
@@ -1005,10 +1019,6 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
continue;
}
- // If the relocation points to something in the file, we can process it.
- bool IsConstant =
- isStaticLinkTimeConstant<ELFT>(Expr, Type, Sym, Sec, Rel.r_offset);
-
// The size is not going to change, so we fold it in here.
if (Expr == R_SIZE)
Addend += Sym.getSize();
diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp
index d56500ae7dd8f..c1176ccfa8d56 100644
--- a/ELF/ScriptParser.cpp
+++ b/ELF/ScriptParser.cpp
@@ -151,6 +151,8 @@ static ExprValue add(ExprValue A, ExprValue B) {
}
static ExprValue sub(ExprValue A, ExprValue B) {
+ if (!A.isAbsolute() && !B.isAbsolute())
+ return A.getValue() - B.getValue();
return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc};
}
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 12509c9a17575..b6bf219988632 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -44,8 +44,8 @@ static InputFile *getFirstElf() {
// All input object files must be for the same architecture
// (e.g. it does not make sense to link x86 object files with
// MIPS object files.) This function checks for that error.
-template <class ELFT> static bool isCompatible(InputFile *F) {
- if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F))
+static bool isCompatible(InputFile *F) {
+ if (!F->isElf() && !isa<BitcodeFile>(F))
return true;
if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) {
@@ -64,13 +64,13 @@ template <class ELFT> static bool isCompatible(InputFile *F) {
// Add symbols in File to the symbol table.
template <class ELFT> void SymbolTable::addFile(InputFile *File) {
- if (!isCompatible<ELFT>(File))
+ if (!isCompatible(File))
return;
// Binary file
if (auto *F = dyn_cast<BinaryFile>(File)) {
BinaryFiles.push_back(F);
- F->parse<ELFT>();
+ F->parse();
return;
}
@@ -135,11 +135,10 @@ template <class ELFT> void SymbolTable::addCombinedLTOObject() {
}
}
-template <class ELFT>
Defined *SymbolTable::addAbsolute(StringRef Name, uint8_t Visibility,
uint8_t Binding) {
- Symbol *Sym = addRegular<ELFT>(Name, Visibility, STT_NOTYPE, 0, 0, Binding,
- nullptr, nullptr);
+ Symbol *Sym =
+ addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr);
return cast<Defined>(Sym);
}
@@ -306,7 +305,7 @@ Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding,
if (Binding != STB_WEAK) {
if (auto *SS = dyn_cast<SharedSymbol>(S))
if (!Config->GcSections)
- SS->getFile<ELFT>()->IsNeeded = true;
+ SS->getFile<ELFT>().IsNeeded = true;
}
if (auto *L = dyn_cast<Lazy>(S)) {
// An undefined weak will not fetch archive members. See comment on Lazy in
@@ -377,19 +376,19 @@ static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
uint8_t Binding, uint8_t StOther, uint8_t Type,
- InputFile *File) {
+ InputFile &File) {
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther),
- /*CanOmitFromDynSym*/ false, File);
+ /*CanOmitFromDynSym*/ false, &File);
int Cmp = compareDefined(S, WasInserted, Binding, N);
if (Cmp > 0) {
auto *Bss = make<BssSection>("COMMON", Size, Alignment);
- Bss->File = File;
+ Bss->File = &File;
Bss->Live = !Config->GcSections;
InputSections.push_back(Bss);
- replaceSymbol<Defined>(S, File, N, Binding, StOther, Type, 0, Size, Bss);
+ replaceSymbol<Defined>(S, &File, N, Binding, StOther, Type, 0, Size, Bss);
} else if (Cmp == 0) {
auto *D = cast<Defined>(S);
auto *Bss = dyn_cast_or_null<BssSection>(D->Section);
@@ -405,7 +404,7 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
Bss->Alignment = std::max(Bss->Alignment, Alignment);
if (Size > Bss->Size) {
- D->File = Bss->File = File;
+ D->File = Bss->File = &File;
D->Size = Bss->Size = Size;
}
}
@@ -424,9 +423,8 @@ static void reportDuplicate(Symbol *Sym, InputFile *NewFile) {
toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
}
-template <class ELFT>
static void reportDuplicate(Symbol *Sym, InputSectionBase *ErrSec,
- typename ELFT::uint ErrOffset) {
+ uint64_t ErrOffset) {
Defined *D = cast<Defined>(Sym);
if (!D->Section || !ErrSec) {
reportDuplicate(Sym, ErrSec ? ErrSec->File : nullptr);
@@ -441,9 +439,9 @@ static void reportDuplicate(Symbol *Sym, InputSectionBase *ErrSec,
// >>> defined at baz.c:563
// >>> baz.o in archive libbaz.a
auto *Sec1 = cast<InputSectionBase>(D->Section);
- std::string Src1 = Sec1->getSrcMsg<ELFT>(*Sym, D->Value);
+ std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value);
std::string Obj1 = Sec1->getObjMsg(D->Value);
- std::string Src2 = ErrSec->getSrcMsg<ELFT>(*Sym, ErrOffset);
+ std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset);
std::string Obj2 = ErrSec->getObjMsg(ErrOffset);
std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at ";
@@ -456,7 +454,6 @@ static void reportDuplicate(Symbol *Sym, InputSectionBase *ErrSec,
warnOrError(Msg);
}
-template <typename ELFT>
Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
uint64_t Value, uint64_t Size, uint8_t Binding,
SectionBase *Section, InputFile *File) {
@@ -470,13 +467,12 @@ Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
replaceSymbol<Defined>(S, File, Name, Binding, StOther, Type, Value, Size,
Section);
else if (Cmp == 0)
- reportDuplicate<ELFT>(S, dyn_cast_or_null<InputSectionBase>(Section),
- Value);
+ reportDuplicate(S, dyn_cast_or_null<InputSectionBase>(Section), Value);
return S;
}
template <typename ELFT>
-void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
+void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> &File,
const typename ELFT::Sym &Sym, uint32_t Alignment,
uint32_t VerdefIndex) {
// DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
@@ -485,7 +481,7 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT,
- /*CanOmitFromDynSym*/ true, File);
+ /*CanOmitFromDynSym*/ true, &File);
// Make sure we preempt DSO symbols with default visibility.
if (Sym.getVisibility() == STV_DEFAULT)
S->ExportDynamic = true;
@@ -501,24 +497,24 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
if (!WasInserted) {
S->Binding = Binding;
if (!S->isWeak() && !Config->GcSections)
- File->IsNeeded = true;
+ File.IsNeeded = true;
}
}
}
Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding,
uint8_t StOther, uint8_t Type,
- bool CanOmitFromDynSym, BitcodeFile *F) {
+ bool CanOmitFromDynSym, BitcodeFile &F) {
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) =
- insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F);
+ insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, &F);
int Cmp = compareDefinedNonCommon(S, WasInserted, Binding,
/*IsAbs*/ false, /*Value*/ 0, Name);
if (Cmp > 0)
- replaceSymbol<Defined>(S, F, Name, Binding, StOther, Type, 0, 0, nullptr);
+ replaceSymbol<Defined>(S, &F, Name, Binding, StOther, Type, 0, 0, nullptr);
else if (Cmp == 0)
- reportDuplicate(S, F);
+ reportDuplicate(S, &F);
return S;
}
@@ -532,7 +528,7 @@ Symbol *SymbolTable::find(StringRef Name) {
}
template <class ELFT>
-Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile *F,
+Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &F,
const object::Archive::Symbol Sym) {
Symbol *S;
bool WasInserted;
@@ -551,9 +547,9 @@ Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile *F,
S->Binding = STB_WEAK;
return S;
}
- std::pair<MemoryBufferRef, uint64_t> MBInfo = F->getMember(&Sym);
+ std::pair<MemoryBufferRef, uint64_t> MBInfo = F.getMember(&Sym);
if (!MBInfo.first.getBuffer().empty())
- addFile<ELFT>(createObjectFile(MBInfo.first, F->getName(), MBInfo.second));
+ addFile<ELFT>(createObjectFile(MBInfo.first, F.getName(), MBInfo.second));
return S;
}
@@ -563,7 +559,7 @@ void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) {
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
if (WasInserted) {
- replaceSymbol<LazyObject>(S, &Obj, Name, Symbol::UnknownType);
+ replaceSymbol<LazyObject>(S, Obj, Name, Symbol::UnknownType);
return;
}
if (!S->isUndefined())
@@ -571,7 +567,7 @@ void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) {
// See comment for addLazyArchive above.
if (S->isWeak())
- replaceSymbol<LazyObject>(S, &Obj, Name, S->Type);
+ replaceSymbol<LazyObject>(S, Obj, Name, S->Type);
else if (InputFile *F = Obj.fetch())
addFile<ELFT>(F);
}
@@ -582,7 +578,7 @@ template <class ELFT> void SymbolTable::fetchIfLazy(StringRef Name) {
// Mark the symbol not to be eliminated by LTO
// even if it is a bitcode symbol.
B->IsUsedInRegularObj = true;
- if (auto *L = dyn_cast_or_null<Lazy>(B))
+ if (auto *L = dyn_cast<Lazy>(B))
if (InputFile *File = L->fetch())
addFile<ELFT>(File);
}
@@ -797,39 +793,17 @@ template void SymbolTable::addCombinedLTOObject<ELF32BE>();
template void SymbolTable::addCombinedLTOObject<ELF64LE>();
template void SymbolTable::addCombinedLTOObject<ELF64BE>();
-template Symbol *SymbolTable::addRegular<ELF32LE>(StringRef, uint8_t, uint8_t,
- uint64_t, uint64_t, uint8_t,
- SectionBase *, InputFile *);
-template Symbol *SymbolTable::addRegular<ELF32BE>(StringRef, uint8_t, uint8_t,
- uint64_t, uint64_t, uint8_t,
- SectionBase *, InputFile *);
-template Symbol *SymbolTable::addRegular<ELF64LE>(StringRef, uint8_t, uint8_t,
- uint64_t, uint64_t, uint8_t,
- SectionBase *, InputFile *);
-template Symbol *SymbolTable::addRegular<ELF64BE>(StringRef, uint8_t, uint8_t,
- uint64_t, uint64_t, uint8_t,
- SectionBase *, InputFile *);
-
-template Defined *SymbolTable::addAbsolute<ELF32LE>(StringRef, uint8_t,
- uint8_t);
-template Defined *SymbolTable::addAbsolute<ELF32BE>(StringRef, uint8_t,
- uint8_t);
-template Defined *SymbolTable::addAbsolute<ELF64LE>(StringRef, uint8_t,
- uint8_t);
-template Defined *SymbolTable::addAbsolute<ELF64BE>(StringRef, uint8_t,
- uint8_t);
-
template Symbol *
-SymbolTable::addLazyArchive<ELF32LE>(StringRef, ArchiveFile *,
+SymbolTable::addLazyArchive<ELF32LE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
template Symbol *
-SymbolTable::addLazyArchive<ELF32BE>(StringRef, ArchiveFile *,
+SymbolTable::addLazyArchive<ELF32BE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
template Symbol *
-SymbolTable::addLazyArchive<ELF64LE>(StringRef, ArchiveFile *,
+SymbolTable::addLazyArchive<ELF64LE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
template Symbol *
-SymbolTable::addLazyArchive<ELF64BE>(StringRef, ArchiveFile *,
+SymbolTable::addLazyArchive<ELF64BE>(StringRef, ArchiveFile &,
const object::Archive::Symbol);
template void SymbolTable::addLazyObject<ELF32LE>(StringRef, LazyObjFile &);
@@ -837,16 +811,16 @@ template void SymbolTable::addLazyObject<ELF32BE>(StringRef, LazyObjFile &);
template void SymbolTable::addLazyObject<ELF64LE>(StringRef, LazyObjFile &);
template void SymbolTable::addLazyObject<ELF64BE>(StringRef, LazyObjFile &);
-template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile<ELF32LE> *,
+template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile<ELF32LE> &,
const typename ELF32LE::Sym &,
uint32_t Alignment, uint32_t);
-template void SymbolTable::addShared<ELF32BE>(StringRef, SharedFile<ELF32BE> *,
+template void SymbolTable::addShared<ELF32BE>(StringRef, SharedFile<ELF32BE> &,
const typename ELF32BE::Sym &,
uint32_t Alignment, uint32_t);
-template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> *,
+template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> &,
const typename ELF64LE::Sym &,
uint32_t Alignment, uint32_t);
-template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> *,
+template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> &,
const typename ELF64BE::Sym &,
uint32_t Alignment, uint32_t);
diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h
index 738311c089db7..e7341b05baf51 100644
--- a/ELF/SymbolTable.h
+++ b/ELF/SymbolTable.h
@@ -42,7 +42,6 @@ public:
ArrayRef<Symbol *> getSymbols() const { return SymVector; }
- template <class ELFT>
Defined *addAbsolute(StringRef Name,
uint8_t Visibility = llvm::ELF::STV_HIDDEN,
uint8_t Binding = llvm::ELF::STB_GLOBAL);
@@ -51,28 +50,27 @@ public:
template <class ELFT>
Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther,
uint8_t Type, bool CanOmitFromDynSym, InputFile *File);
- template <class ELFT>
Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
uint64_t Value, uint64_t Size, uint8_t Binding,
SectionBase *Section, InputFile *File);
template <class ELFT>
- void addShared(StringRef Name, SharedFile<ELFT> *F,
+ void addShared(StringRef Name, SharedFile<ELFT> &F,
const typename ELFT::Sym &Sym, uint32_t Alignment,
uint32_t VerdefIndex);
template <class ELFT>
- Symbol *addLazyArchive(StringRef Name, ArchiveFile *F,
+ Symbol *addLazyArchive(StringRef Name, ArchiveFile &F,
const llvm::object::Archive::Symbol S);
template <class ELFT> void addLazyObject(StringRef Name, LazyObjFile &Obj);
Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther,
- uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *File);
+ uint8_t Type, bool CanOmitFromDynSym, BitcodeFile &File);
Symbol *addCommon(StringRef Name, uint64_t Size, uint32_t Alignment,
uint8_t Binding, uint8_t StOther, uint8_t Type,
- InputFile *File);
+ InputFile &File);
std::pair<Symbol *, bool> insert(StringRef Name);
std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type,
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index ab42fcd51a81b..13a91aab80bb7 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -116,12 +116,6 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
llvm_unreachable("invalid symbol kind");
}
-// Returns true if this is a weak undefined symbol.
-bool Symbol::isUndefWeak() const {
- // See comment on Lazy in Symbols.h for the details.
- return isWeak() && (isUndefined() || isLazy());
-}
-
uint64_t Symbol::getVA(int64_t Addend) const {
uint64_t OutVA = getSymVA(*this, Addend);
return OutVA + Addend;
@@ -224,21 +218,21 @@ InputFile *Lazy::fetch() {
return cast<LazyObject>(this)->fetch();
}
-ArchiveFile *LazyArchive::getFile() { return cast<ArchiveFile>(File); }
+ArchiveFile &LazyArchive::getFile() { return *cast<ArchiveFile>(File); }
InputFile *LazyArchive::fetch() {
- std::pair<MemoryBufferRef, uint64_t> MBInfo = getFile()->getMember(&Sym);
+ std::pair<MemoryBufferRef, uint64_t> MBInfo = getFile().getMember(&Sym);
// getMember returns an empty buffer if the member was already
// read from the library.
if (MBInfo.first.getBuffer().empty())
return nullptr;
- return createObjectFile(MBInfo.first, getFile()->getName(), MBInfo.second);
+ return createObjectFile(MBInfo.first, getFile().getName(), MBInfo.second);
}
-LazyObjFile *LazyObject::getFile() { return cast<LazyObjFile>(File); }
+LazyObjFile &LazyObject::getFile() { return *cast<LazyObjFile>(File); }
-InputFile *LazyObject::fetch() { return getFile()->fetch(); }
+InputFile *LazyObject::fetch() { return getFile().fetch(); }
uint8_t Symbol::computeBinding() const {
if (Config->Relocatable)
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index f4bb245f955d1..9b7207383345a 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -102,7 +102,10 @@ public:
// True is this is an undefined weak symbol. This only works once
// all input files have been added.
- bool isUndefWeak() const;
+ bool isUndefWeak() const {
+ // See comment on Lazy the details.
+ return isWeak() && (isUndefined() || isLazy());
+ }
StringRef getName() const { return Name; }
uint8_t getVisibility() const { return StOther & 0x3; }
@@ -208,14 +211,14 @@ class SharedSymbol : public Symbol {
public:
static bool classof(const Symbol *S) { return S->kind() == SharedKind; }
- SharedSymbol(InputFile *File, StringRef Name, uint8_t Binding,
+ SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding,
uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size,
uint32_t Alignment, uint32_t VerdefIndex)
- : Symbol(SharedKind, File, Name, Binding, StOther, Type), Value(Value),
+ : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value),
Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) {
// GNU ifunc is a mechanism to allow user-supplied functions to
// resolve PLT slot values at load-time. This is contrary to the
- // regualr symbol resolution scheme in which symbols are resolved just
+ // regular symbol resolution scheme in which symbols are resolved just
// by name. Using this hook, you can program how symbols are solved
// for you program. For example, you can make "memcpy" to be resolved
// to a SSE-enabled version of memcpy only when a machine running the
@@ -233,8 +236,8 @@ public:
this->Type = llvm::ELF::STT_FUNC;
}
- template <class ELFT> SharedFile<ELFT> *getFile() const {
- return cast<SharedFile<ELFT>>(File);
+ template <class ELFT> SharedFile<ELFT> &getFile() const {
+ return *cast<SharedFile<ELFT>>(File);
}
// If not null, there is a copy relocation to this section.
@@ -267,8 +270,8 @@ public:
InputFile *fetch();
protected:
- Lazy(Kind K, InputFile *File, StringRef Name, uint8_t Type)
- : Symbol(K, File, Name, llvm::ELF::STB_GLOBAL, llvm::ELF::STV_DEFAULT,
+ Lazy(Kind K, InputFile &File, StringRef Name, uint8_t Type)
+ : Symbol(K, &File, Name, llvm::ELF::STB_GLOBAL, llvm::ELF::STV_DEFAULT,
Type) {}
};
@@ -278,13 +281,13 @@ protected:
// symbol.
class LazyArchive : public Lazy {
public:
- LazyArchive(InputFile *File, const llvm::object::Archive::Symbol S,
+ LazyArchive(InputFile &File, const llvm::object::Archive::Symbol S,
uint8_t Type)
: Lazy(LazyArchiveKind, File, S.getName(), Type), Sym(S) {}
static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; }
- ArchiveFile *getFile();
+ ArchiveFile &getFile();
InputFile *fetch();
private:
@@ -295,12 +298,12 @@ private:
// --start-lib and --end-lib options.
class LazyObject : public Lazy {
public:
- LazyObject(InputFile *File, StringRef Name, uint8_t Type)
+ LazyObject(InputFile &File, StringRef Name, uint8_t Type)
: Lazy(LazyObjectKind, File, Name, Type) {}
static bool classof(const Symbol *S) { return S->kind() == LazyObjectKind; }
- LazyObjFile *getFile();
+ LazyObjFile &getFile();
InputFile *fetch();
};
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index b408e653dfa04..a5e291b79a4db 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -81,17 +81,9 @@ static ArrayRef<uint8_t> getVersion() {
// With this feature, you can identify LLD-generated binaries easily
// by "readelf --string-dump .comment <file>".
// The returned object is a mergeable string section.
-template <class ELFT> MergeInputSection *elf::createCommentSection() {
- typename ELFT::Shdr Hdr = {};
- Hdr.sh_flags = SHF_MERGE | SHF_STRINGS;
- Hdr.sh_type = SHT_PROGBITS;
- Hdr.sh_entsize = 1;
- Hdr.sh_addralign = 1;
-
- auto *Ret =
- make<MergeInputSection>((ObjFile<ELFT> *)nullptr, &Hdr, ".comment");
- Ret->Data = getVersion();
- return Ret;
+MergeInputSection *elf::createCommentSection() {
+ return make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1,
+ getVersion(), ".comment");
}
// .MIPS.abiflags section.
@@ -268,16 +260,16 @@ InputSection *elf::createInterpSection() {
StringRef S = Saver.save(Config->DynamicLinker);
ArrayRef<uint8_t> Contents = {(const uint8_t *)S.data(), S.size() + 1};
- auto *Sec =
- make<InputSection>(SHF_ALLOC, SHT_PROGBITS, 1, Contents, ".interp");
+ auto *Sec = make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, Contents,
+ ".interp");
Sec->Live = true;
return Sec;
}
Symbol *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
- uint64_t Size, InputSectionBase *Section) {
- auto *S = make<Defined>(Section->File, Name, STB_LOCAL, STV_DEFAULT, Type,
- Value, Size, Section);
+ uint64_t Size, InputSectionBase &Section) {
+ auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type,
+ Value, Size, &Section);
if (InX::SymTab)
InX::SymTab->addSymbol(S);
return S;
@@ -1893,10 +1885,10 @@ size_t PltSection::getSize() const {
void PltSection::addSymbols() {
// The PLT may have symbols defined for the Header, the IPLT has no header
if (HeaderSize != 0)
- Target->addPltHeaderSymbols(this);
+ Target->addPltHeaderSymbols(*this);
size_t Off = HeaderSize;
for (size_t I = 0; I < Entries.size(); ++I) {
- Target->addPltSymbols(this, Off);
+ Target->addPltSymbols(*this, Off);
Off += Target->PltEntrySize;
}
}
@@ -2299,8 +2291,8 @@ VersionNeedSection<ELFT>::VersionNeedSection()
template <class ELFT>
void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
- SharedFile<ELFT> *File = SS->getFile<ELFT>();
- const typename ELFT::Verdef *Ver = File->Verdefs[SS->VerdefIndex];
+ SharedFile<ELFT> &File = SS->getFile<ELFT>();
+ const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];
if (!Ver) {
SS->VersionId = VER_NDX_GLOBAL;
return;
@@ -2309,14 +2301,14 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
// If we don't already know that we need an Elf_Verneed for this DSO, prepare
// to create one by adding it to our needed list and creating a dynstr entry
// for the soname.
- if (File->VerdefMap.empty())
- Needed.push_back({File, InX::DynStrTab->addString(File->SoName)});
- typename SharedFile<ELFT>::NeededVer &NV = File->VerdefMap[Ver];
+ if (File.VerdefMap.empty())
+ Needed.push_back({&File, InX::DynStrTab->addString(File.SoName)});
+ typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver];
// If we don't already know that we need an Elf_Vernaux for this Elf_Verdef,
// prepare to create one by allocating a version identifier and creating a
// dynstr entry for the version name.
if (NV.Index == 0) {
- NV.StrTab = InX::DynStrTab->addString(File->getStringTable().data() +
+ NV.StrTab = InX::DynStrTab->addString(File.getStringTable().data() +
Ver->getAux()->vda_name);
NV.Index = NextIndex++;
}
@@ -2561,31 +2553,25 @@ ARMExidxSentinelSection::ARMExidxSentinelSection()
// The sentinel must have the PREL31 value of an address higher than any
// address described by any other table entry.
void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
- // The Sections are sorted in order of ascending PREL31 address with the
- // sentinel last. We need to find the InputSection that precedes the
- // sentinel.
- OutputSection *C = getParent();
- InputSection *Highest = nullptr;
- unsigned Skip = 1;
- for (const BaseCommand *Base : llvm::reverse(C->SectionCommands)) {
- if (!isa<InputSectionDescription>(Base))
- continue;
- auto L = cast<InputSectionDescription>(Base);
- if (Skip >= L->Sections.size()) {
- Skip -= L->Sections.size();
- continue;
- }
- Highest = L->Sections[L->Sections.size() - Skip - 1];
- break;
- }
assert(Highest);
- InputSection *LS = Highest->getLinkOrderDep();
- uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize());
+ uint64_t S =
+ Highest->getParent()->Addr + Highest->getOffset(Highest->getSize());
uint64_t P = getVA();
Target->relocateOne(Buf, R_ARM_PREL31, S - P);
write32le(Buf + 4, 1);
}
+// The sentinel has to be removed if there are no other .ARM.exidx entries.
+bool ARMExidxSentinelSection::empty() const {
+ OutputSection *OS = getParent();
+ for (auto *B : OS->SectionCommands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(B))
+ for (auto *S : ISD->Sections)
+ if (!isa<ARMExidxSentinelSection>(S))
+ return false;
+ return true;
+}
+
ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
Config->Wordsize, ".text.thunk") {
@@ -2655,11 +2641,6 @@ template void PltSection::addEntry<ELF32BE>(Symbol &Sym);
template void PltSection::addEntry<ELF64LE>(Symbol &Sym);
template void PltSection::addEntry<ELF64BE>(Symbol &Sym);
-template MergeInputSection *elf::createCommentSection<ELF32LE>();
-template MergeInputSection *elf::createCommentSection<ELF32BE>();
-template MergeInputSection *elf::createCommentSection<ELF64LE>();
-template MergeInputSection *elf::createCommentSection<ELF64BE>();
-
template class elf::MipsAbiFlagsSection<ELF32LE>;
template class elf::MipsAbiFlagsSection<ELF32BE>;
template class elf::MipsAbiFlagsSection<ELF64LE>;
diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h
index 5aaf479f3e35e..a990590513bb9 100644
--- a/ELF/SyntheticSections.h
+++ b/ELF/SyntheticSections.h
@@ -36,7 +36,7 @@ class SyntheticSection : public InputSection {
public:
SyntheticSection(uint64_t Flags, uint32_t Type, uint32_t Alignment,
StringRef Name)
- : InputSection(Flags, Type, Alignment, {}, Name,
+ : InputSection(nullptr, Flags, Type, Alignment, {}, Name,
InputSectionBase::Synthetic) {
this->Live = true;
}
@@ -785,6 +785,9 @@ public:
ARMExidxSentinelSection();
size_t getSize() const override { return 8; }
void writeTo(uint8_t *Buf) override;
+ bool empty() const override;
+
+ InputSection *Highest = 0;
};
// A container for one or more linker generated thunks. Instances of these
@@ -809,12 +812,12 @@ private:
};
InputSection *createInterpSection();
-template <class ELFT> MergeInputSection *createCommentSection();
+MergeInputSection *createCommentSection();
void decompressSections();
void mergeSections();
Symbol *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
- uint64_t Size, InputSectionBase *Section);
+ uint64_t Size, InputSectionBase &Section);
// Linker generated sections which can be used as inputs.
struct InX {
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index ddd408906d14f..b528fd583c1ae 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -89,7 +89,7 @@ TargetInfo *elf::getTarget() {
template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) {
for (InputSectionBase *D : InputSections) {
- auto *IS = dyn_cast_or_null<InputSection>(D);
+ auto *IS = dyn_cast<InputSection>(D);
if (!IS || !IS->getParent())
continue;
diff --git a/ELF/Target.h b/ELF/Target.h
index 2902dbc99149c..1f58adba18178 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -40,8 +40,8 @@ public:
virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {}
- virtual void addPltHeaderSymbols(InputSectionBase *IS) const {}
- virtual void addPltSymbols(InputSectionBase *IS, uint64_t Off) const {}
+ virtual void addPltHeaderSymbols(InputSection &IS) const {}
+ virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {}
// Returns true if a relocation only uses the low bits of a value such that
// all those bits are in in the same page. For example, if the relocation
diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp
index 91ca3b9b5bc2c..b0bbf6da705a5 100644
--- a/ELF/Thunks.cpp
+++ b/ELF/Thunks.cpp
@@ -164,9 +164,9 @@ void AArch64ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {
ThunkSym = addSyntheticLocal(
Saver.save("__AArch64AbsLongThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), &IS);
- addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, &IS);
- addSyntheticLocal("$d", STT_NOTYPE, Offset + 8, 0, &IS);
+ Offset, size(), IS);
+ addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
+ addSyntheticLocal("$d", STT_NOTYPE, Offset + 8, 0, IS);
}
// This Thunk has a maximum range of 4Gb, this is sufficient for all programs
@@ -192,8 +192,8 @@ void AArch64ADRPThunk::addSymbols(ThunkSection &IS)
{
ThunkSym = addSyntheticLocal(
Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), &IS);
- addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, &IS);
+ Offset, size(), IS);
+ addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
}
// ARM Target Thunks
@@ -217,8 +217,8 @@ void ARMV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) {
ThunkSym = addSyntheticLocal(
Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), &IS);
- addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
+ Offset, size(), IS);
+ addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
}
bool ARMV7ABSLongThunk::isCompatibleWith(RelType Type) const {
@@ -241,8 +241,8 @@ void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {
ThunkSym = addSyntheticLocal(
Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
- Offset | 0x1, size(), &IS);
- addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
+ Offset | 0x1, size(), IS);
+ addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
}
bool ThumbV7ABSLongThunk::isCompatibleWith(RelType Type) const {
@@ -268,8 +268,8 @@ void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
void ARMV7PILongThunk::addSymbols(ThunkSection &IS) {
ThunkSym = addSyntheticLocal(
Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,
- Offset, size(), &IS);
- addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
+ Offset, size(), IS);
+ addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
}
bool ARMV7PILongThunk::isCompatibleWith(RelType Type) const {
@@ -295,8 +295,8 @@ void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {
ThunkSym = addSyntheticLocal(
Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), STT_FUNC,
- Offset | 0x1, size(), &IS);
- addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
+ Offset | 0x1, size(), IS);
+ addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
}
bool ThumbV7PILongThunk::isCompatibleWith(RelType Type) const {
@@ -318,7 +318,7 @@ void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
void MipsThunk::addSymbols(ThunkSection &IS) {
ThunkSym =
addSyntheticLocal(Saver.save("__LA25Thunk_" + Destination.getName()),
- STT_FUNC, Offset, size(), &IS);
+ STT_FUNC, Offset, size(), IS);
}
InputSection *MipsThunk::getTargetInputSection() const {
@@ -342,7 +342,7 @@ void MicroMipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
void MicroMipsThunk::addSymbols(ThunkSection &IS) {
ThunkSym =
addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
- STT_FUNC, Offset, size(), &IS);
+ STT_FUNC, Offset, size(), IS);
ThunkSym->StOther |= STO_MIPS_MICROMIPS;
}
@@ -367,7 +367,7 @@ void MicroMipsR6Thunk::writeTo(uint8_t *Buf, ThunkSection &) const {
void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) {
ThunkSym =
addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
- STT_FUNC, Offset, size(), &IS);
+ STT_FUNC, Offset, size(), IS);
ThunkSym->StOther |= STO_MIPS_MICROMIPS;
}
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index c7a3cae49ae65..15f3821047560 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -54,7 +54,6 @@ private:
void resolveShfLinkOrder();
void sortInputSections();
void finalizeSections();
- void addPredefinedSections();
void setReservedSymbolSections();
std::vector<PhdrEntry *> createPhdrs();
@@ -157,35 +156,34 @@ template <class ELFT> static void combineEhFrameSections() {
V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
}
-template <class ELFT>
static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec,
uint64_t Val, uint8_t StOther = STV_HIDDEN,
uint8_t Binding = STB_GLOBAL) {
Symbol *S = Symtab->find(Name);
if (!S || S->isDefined())
return nullptr;
- Symbol *Sym = Symtab->addRegular<ELFT>(Name, StOther, STT_NOTYPE, Val,
- /*Size=*/0, Binding, Sec,
- /*File=*/nullptr);
+ Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val,
+ /*Size=*/0, Binding, Sec,
+ /*File=*/nullptr);
return cast<Defined>(Sym);
}
// The linker is expected to define some symbols depending on
// the linking result. This function defines such symbols.
-template <class ELFT> void elf::addReservedSymbols() {
+void elf::addReservedSymbols() {
if (Config->EMachine == EM_MIPS) {
// Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
// so that it points to an absolute address which by default is relative
// to GOT. Default offset is 0x7ff0.
// See "Global Data Symbols" in Chapter 6 in the following document:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- ElfSym::MipsGp = Symtab->addAbsolute<ELFT>("_gp", STV_HIDDEN, STB_GLOBAL);
+ ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL);
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
// start of function and 'gp' pointer into GOT.
if (Symtab->find("_gp_disp"))
ElfSym::MipsGpDisp =
- Symtab->addAbsolute<ELFT>("_gp_disp", STV_HIDDEN, STB_GLOBAL);
+ Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL);
// The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
// pointer. This symbol is used in the code generated by .cpload pseudo-op
@@ -193,10 +191,10 @@ template <class ELFT> void elf::addReservedSymbols() {
// https://sourceware.org/ml/binutils/2004-12/msg00094.html
if (Symtab->find("__gnu_local_gp"))
ElfSym::MipsLocalGp =
- Symtab->addAbsolute<ELFT>("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
+ Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
}
- ElfSym::GlobalOffsetTable = addOptionalRegular<ELFT>(
+ ElfSym::GlobalOffsetTable = addOptionalRegular(
"_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff);
// __ehdr_start is the location of ELF file headers. Note that we define
@@ -210,14 +208,14 @@ template <class ELFT> void elf::addReservedSymbols() {
// different in different DSOs, so we chose the start address of the DSO.
for (const char *Name :
{"__ehdr_start", "__executable_start", "__dso_handle"})
- addOptionalRegular<ELFT>(Name, Out::ElfHeader, 0, STV_HIDDEN);
+ addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN);
// If linker script do layout we do not need to create any standart symbols.
if (Script->HasSectionsCommand)
return;
auto Add = [](StringRef S, int64_t Pos) {
- return addOptionalRegular<ELFT>(S, Out::ElfHeader, Pos, STV_DEFAULT);
+ return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT);
};
ElfSym::Bss = Add("__bss_start", 0);
@@ -390,6 +388,11 @@ template <class ELFT> static void createSyntheticSections() {
Add(InX::ShStrTab);
if (InX::StrTab)
Add(InX::StrTab);
+
+ if (Config->EMachine == EM_ARM && !Config->Relocatable)
+ // Add a sentinel to terminate .ARM.exidx. It helps an unwinder
+ // to find the exact address range of the last entry.
+ Add(make<ARMExidxSentinelSection>());
}
// The main function of the writer.
@@ -830,10 +833,10 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
if (!Config->Static)
return;
StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
- addOptionalRegular<ELFT>(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
+ addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
- addOptionalRegular<ELFT>(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
+ addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
}
template <class ELFT>
@@ -1145,10 +1148,10 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
}
static bool compareByFilePosition(InputSection *A, InputSection *B) {
- // Synthetic doesn't have link order dependecy, stable_sort will keep it last
+ // Synthetic, i. e. a sentinel section, should go last.
if (A->kind() == InputSectionBase::Synthetic ||
B->kind() == InputSectionBase::Synthetic)
- return false;
+ return A->kind() != InputSectionBase::Synthetic;
InputSection *LA = A->getLinkOrderDep();
InputSection *LB = B->getLinkOrderDep();
OutputSection *AOut = LA->getParent();
@@ -1231,23 +1234,37 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
}
std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
- if (Config->MergeArmExidx && !Config->Relocatable &&
- Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX) {
- // The EHABI for the Arm Architecture permits consecutive identical
- // table entries to be merged. We use a simple implementation that
- // removes a .ARM.exidx Input Section if it can be merged into the
- // previous one. This does not require any rewriting of InputSection
- // contents but misses opportunities for fine grained deduplication where
- // only a subset of the InputSection contents can be merged.
- int Cur = 1;
- int Prev = 0;
- int N = Sections.size();
- while (Cur < N) {
- if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
- Sections[Cur] = nullptr;
- else
- Prev = Cur;
- ++Cur;
+ if (!Config->Relocatable && Config->EMachine == EM_ARM &&
+ Sec->Type == SHT_ARM_EXIDX) {
+
+ if (!Sections.empty() && isa<ARMExidxSentinelSection>(Sections.back())) {
+ assert(Sections.size() >= 2 &&
+ "We should create a sentinel section only if there are "
+ "alive regular exidx sections.");
+ // The last executable section is required to fill the sentinel.
+ // Remember it here so that we don't have to find it again.
+ auto *Sentinel = cast<ARMExidxSentinelSection>(Sections.back());
+ Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
+ }
+
+ if (Config->MergeArmExidx) {
+ // The EHABI for the Arm Architecture permits consecutive identical
+ // table entries to be merged. We use a simple implementation that
+ // removes a .ARM.exidx Input Section if it can be merged into the
+ // previous one. This does not require any rewriting of InputSection
+ // contents but misses opportunities for fine grained deduplication
+ // where only a subset of the InputSection contents can be merged.
+ int Cur = 1;
+ int Prev = 0;
+ // The last one is a sentinel entry which should not be removed.
+ int N = Sections.size() - 1;
+ while (Cur < N) {
+ if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
+ Sections[Cur] = nullptr;
+ else
+ Prev = Cur;
+ ++Cur;
+ }
}
}
@@ -1367,9 +1384,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Even the author of gold doesn't remember why gold behaves that way.
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
if (InX::DynSymTab)
- Symtab->addRegular<ELFT>("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/,
- /*Size=*/0, STB_WEAK, InX::Dynamic,
- /*File=*/nullptr);
+ Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/,
+ /*Size=*/0, STB_WEAK, InX::Dynamic,
+ /*File=*/nullptr);
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
@@ -1413,7 +1430,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (errorCount())
return;
- addPredefinedSections();
removeUnusedSyntheticSections();
sortSections();
@@ -1510,17 +1526,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
[](SyntheticSection *SS) { SS->postThunkContents(); });
}
-template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
- // ARM ABI requires .ARM.exidx to be terminated by some piece of data.
- // We have the terminater synthetic section class. Add that at the end.
- OutputSection *Cmd = findSection(".ARM.exidx");
- if (!Cmd || !Cmd->Live || Config->Relocatable)
- return;
-
- auto *Sentinel = make<ARMExidxSentinelSection>();
- Cmd->addSection(Sentinel);
-}
-
// The linker is expected to define SECNAME_start and SECNAME_end
// symbols for a few sections. This function defines them.
template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
@@ -1528,13 +1533,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
// These symbols resolve to the image base if the section does not exist.
// A special value -1 indicates end of the section.
if (OS) {
- addOptionalRegular<ELFT>(Start, OS, 0);
- addOptionalRegular<ELFT>(End, OS, -1);
+ addOptionalRegular(Start, OS, 0);
+ addOptionalRegular(End, OS, -1);
} else {
if (Config->Pic)
OS = Out::ElfHeader;
- addOptionalRegular<ELFT>(Start, OS, 0);
- addOptionalRegular<ELFT>(End, OS, 0);
+ addOptionalRegular(Start, OS, 0);
+ addOptionalRegular(End, OS, 0);
}
};
@@ -1556,8 +1561,8 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
StringRef S = Sec->Name;
if (!isValidCIdentifier(S))
return;
- addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
- addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
+ addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
+ addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
}
static bool needsPtLoad(OutputSection *Sec) {
@@ -2057,8 +2062,3 @@ template void elf::writeResult<ELF32LE>();
template void elf::writeResult<ELF32BE>();
template void elf::writeResult<ELF64LE>();
template void elf::writeResult<ELF64BE>();
-
-template void elf::addReservedSymbols<ELF32LE>();
-template void elf::addReservedSymbols<ELF32BE>();
-template void elf::addReservedSymbols<ELF64LE>();
-template void elf::addReservedSymbols<ELF64BE>();
diff --git a/ELF/Writer.h b/ELF/Writer.h
index 32d3c23047ddd..d247068bab232 100644
--- a/ELF/Writer.h
+++ b/ELF/Writer.h
@@ -46,7 +46,7 @@ struct PhdrEntry {
bool HasLMA = false;
};
-template <class ELFT> void addReservedSymbols();
+void addReservedSymbols();
llvm::StringRef getOutputSectionName(InputSectionBase *S);
template <class ELFT> uint32_t calcMipsEFlags();