aboutsummaryrefslogtreecommitdiffstats
path: root/ELF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-01-06 20:07:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-01-06 20:07:13 +0000
commitfba2c04f31e119eacf142fcbbaabd5a9e63a39ed (patch)
tree59eba88ea527759edb2c98d294ae369f95f57e33 /ELF
parent5a5c549fe9a3fef595297bd21d36bed8409dc37d (diff)
downloadsrc-fba2c04f31e119eacf142fcbbaabd5a9e63a39ed.tar.gz
src-fba2c04f31e119eacf142fcbbaabd5a9e63a39ed.zip
Vendor import of lld trunk r256945:vendor/lld/lld-trunk-r256945
Notes
Notes: svn path=/vendor/lld/dist/; revision=293258 svn path=/vendor/lld/lld-trunk-r256945/; revision=293259; tag=vendor/lld/lld-trunk-r256945
Diffstat (limited to 'ELF')
-rw-r--r--ELF/Config.h5
-rw-r--r--ELF/Driver.cpp28
-rw-r--r--ELF/Driver.h1
-rw-r--r--ELF/InputFiles.cpp112
-rw-r--r--ELF/InputFiles.h15
-rw-r--r--ELF/InputSection.h8
-rw-r--r--ELF/MarkLive.cpp6
-rw-r--r--ELF/OutputSections.cpp31
-rw-r--r--ELF/SymbolTable.cpp56
-rw-r--r--ELF/SymbolTable.h9
-rw-r--r--ELF/Symbols.cpp3
-rw-r--r--ELF/Symbols.h6
-rw-r--r--ELF/Target.cpp2
-rw-r--r--ELF/Writer.cpp45
14 files changed, 158 insertions, 169 deletions
diff --git a/ELF/Config.h b/ELF/Config.h
index 7b820f18b8c7..c279b99b43c1 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -30,6 +30,10 @@ enum ELFKind {
ELF64BEKind
};
+// This struct contains the global configuration for the linker.
+// Most fields are direct mapping from the command line options
+// and such fields have the same name as the corresponding options.
+// Most fields are initialized by the driver.
struct Configuration {
SymbolBody *EntrySym = nullptr;
SymbolBody *MipsGpDisp = nullptr;
@@ -76,6 +80,7 @@ struct Configuration {
unsigned Optimize = 0;
};
+// The only instance of Configuration struct.
extern Configuration *Config;
} // namespace elf2
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 6d881373b303..2a3ecfa61586 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -57,6 +57,24 @@ static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) {
error("Unknown emulation: " + S);
}
+// Returns slices of MB by parsing MB as an archive file.
+// Each slice consists of a member file in the archive.
+static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB) {
+ ErrorOr<std::unique_ptr<Archive>> FileOrErr = Archive::create(MB);
+ error(FileOrErr, "Failed to parse archive");
+ std::unique_ptr<Archive> File = std::move(*FileOrErr);
+
+ std::vector<MemoryBufferRef> V;
+ for (const ErrorOr<Archive::Child> &C : File->children()) {
+ error(C, "Could not get the child of the archive " + File->getFileName());
+ ErrorOr<MemoryBufferRef> MbOrErr = C->getMemoryBufferRef();
+ error(MbOrErr, "Could not get the buffer for a child of the archive " +
+ File->getFileName());
+ V.push_back(*MbOrErr);
+ }
+ return V;
+}
+
// Opens and parses a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
void LinkerDriver::addFile(StringRef Path) {
@@ -75,19 +93,17 @@ void LinkerDriver::addFile(StringRef Path) {
return;
case file_magic::archive:
if (WholeArchive) {
- auto File = make_unique<ArchiveFile>(MBRef);
- for (MemoryBufferRef &MB : File->getMembers())
- Files.push_back(createELFFile<ObjectFile>(MB));
- OwningArchives.emplace_back(std::move(File));
+ for (MemoryBufferRef MB : getArchiveMembers(MBRef))
+ Files.push_back(createObjectFile(MB));
return;
}
Files.push_back(make_unique<ArchiveFile>(MBRef));
return;
case file_magic::elf_shared_object:
- Files.push_back(createELFFile<SharedFile>(MBRef));
+ Files.push_back(createSharedFile(MBRef));
return;
default:
- Files.push_back(createELFFile<ObjectFile>(MBRef));
+ Files.push_back(createObjectFile(MBRef));
}
}
diff --git a/ELF/Driver.h b/ELF/Driver.h
index 2641155104dc..bfae2b3f4dfa 100644
--- a/ELF/Driver.h
+++ b/ELF/Driver.h
@@ -38,7 +38,6 @@ private:
llvm::BumpPtrAllocator Alloc;
bool WholeArchive = false;
std::vector<std::unique_ptr<InputFile>> Files;
- std::vector<std::unique_ptr<ArchiveFile>> OwningArchives;
std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
};
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index e0827a3ee43d..d9df6abbf233 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -37,10 +37,9 @@ ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef M)
template <class ELFT>
ELFKind ELFFileBase<ELFT>::getELFKind() {
- using llvm::support::little;
- if (ELFT::Is64Bits)
- return ELFT::TargetEndianness == little ? ELF64LEKind : ELF64BEKind;
- return ELFT::TargetEndianness == little ? ELF32LEKind : ELF32BEKind;
+ if (ELFT::TargetEndianness == support::little)
+ return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind;
+ return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind;
}
template <class ELFT>
@@ -63,8 +62,7 @@ template <class ELFT>
uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
uint32_t I = Sym.st_shndx;
if (I == ELF::SHN_XINDEX)
- return this->ELFObj.getExtendedSymbolTableIndex(&Sym, this->Symtab,
- SymtabSHNDX);
+ return ELFObj.getExtendedSymbolTableIndex(&Sym, Symtab, SymtabSHNDX);
if (I >= ELF::SHN_LORESERVE || I == ELF::SHN_ABS)
return 0;
return I;
@@ -74,7 +72,7 @@ template <class ELFT> void ELFFileBase<ELFT>::initStringTable() {
if (!Symtab)
return;
ErrorOr<StringRef> StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab);
- error(StringTableOrErr.getError());
+ error(StringTableOrErr);
StringTable = *StringTableOrErr;
}
@@ -108,9 +106,9 @@ ObjectFile<ELFT>::getLocalSymbol(uintX_t SymIndex) {
}
template <class ELFT>
-void elf2::ObjectFile<ELFT>::parse(DenseSet<StringRef> &Comdats) {
+void ObjectFile<ELFT>::parse(DenseSet<StringRef> &ComdatGroups) {
// Read section and symbol tables.
- initializeSections(Comdats);
+ initializeSections(ComdatGroups);
initializeSymbols();
}
@@ -139,7 +137,7 @@ ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
const ELFFile<ELFT> &Obj = this->ELFObj;
ErrorOr<ArrayRef<GroupEntryType>> EntriesOrErr =
Obj.template getSectionContentsAsArray<GroupEntryType>(&Sec);
- error(EntriesOrErr.getError());
+ error(EntriesOrErr);
ArrayRef<GroupEntryType> Entries = *EntriesOrErr;
if (Entries.empty() || Entries[0] != GRP_COMDAT)
error("Unsupported SHT_GROUP format");
@@ -174,7 +172,7 @@ static bool shouldMerge(const typename ELFFile<ELFT>::Elf_Shdr &Sec) {
}
template <class ELFT>
-void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) {
+void ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &ComdatGroups) {
uint64_t Size = this->ELFObj.getNumSections();
Sections.resize(Size);
unsigned I = -1;
@@ -187,7 +185,7 @@ void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) {
switch (Sec.sh_type) {
case SHT_GROUP:
Sections[I] = &InputSection<ELFT>::Discarded;
- if (Comdats.insert(getShtGroupSignature(Sec)).second)
+ if (ComdatGroups.insert(getShtGroupSignature(Sec)).second)
continue;
for (GroupEntryType E : getShtGroupEntries(Sec)) {
uint32_t SecIndex = E;
@@ -235,7 +233,7 @@ void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) {
}
template <class ELFT> InputSectionBase<ELFT> *
-elf2::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
+ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
ErrorOr<StringRef> NameOrErr = this->ELFObj.getSectionName(&Sec);
error(NameOrErr);
StringRef Name = *NameOrErr;
@@ -250,29 +248,29 @@ elf2::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
// A MIPS object file has a special section that contains register
// usage info, which needs to be handled by the linker specially.
if (Config->EMachine == EM_MIPS && Name == ".reginfo") {
- MipsReginfo = new (this->Alloc) MipsReginfoInputSection<ELFT>(this, &Sec);
+ MipsReginfo = new (Alloc) MipsReginfoInputSection<ELFT>(this, &Sec);
return MipsReginfo;
}
if (Name == ".eh_frame")
- return new (this->EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec);
+ return new (EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec);
if (shouldMerge<ELFT>(Sec))
- return new (this->MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec);
- return new (this->Alloc) InputSection<ELFT>(this, &Sec);
+ return new (MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec);
+ return new (Alloc) InputSection<ELFT>(this, &Sec);
}
-template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
+template <class ELFT> void ObjectFile<ELFT>::initializeSymbols() {
this->initStringTable();
Elf_Sym_Range Syms = this->getNonLocalSymbols();
uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
- this->SymbolBodies.reserve(NumSymbols);
+ SymbolBodies.reserve(NumSymbols);
for (const Elf_Sym &Sym : Syms)
- this->SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
+ SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
}
template <class ELFT>
InputSectionBase<ELFT> *
-elf2::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
+ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
uint32_t Index = this->getSectionIndex(Sym);
if (Index == 0)
return nullptr;
@@ -282,19 +280,19 @@ elf2::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
}
template <class ELFT>
-SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
+SymbolBody *ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
const Elf_Sym *Sym) {
ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
- error(NameOrErr.getError());
+ error(NameOrErr);
StringRef Name = *NameOrErr;
switch (Sym->st_shndx) {
case SHN_UNDEF:
- return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
+ return new (Alloc) UndefinedElf<ELFT>(Name, *Sym);
case SHN_COMMON:
- return new (this->Alloc) DefinedCommon(
- Name, Sym->st_size, Sym->st_value,
- Sym->getBinding() == llvm::ELF::STB_WEAK, Sym->getVisibility());
+ return new (Alloc) DefinedCommon(Name, Sym->st_size, Sym->st_value,
+ Sym->getBinding() == llvm::ELF::STB_WEAK,
+ Sym->getVisibility());
}
switch (Sym->getBinding()) {
@@ -305,20 +303,16 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
case STB_GNU_UNIQUE: {
InputSectionBase<ELFT> *Sec = getSection(*Sym);
if (Sec == &InputSection<ELFT>::Discarded)
- return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
- return new (this->Alloc) DefinedRegular<ELFT>(Name, *Sym, Sec);
+ return new (Alloc) UndefinedElf<ELFT>(Name, *Sym);
+ return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, Sec);
}
}
}
-static std::unique_ptr<Archive> openArchive(MemoryBufferRef MB) {
- ErrorOr<std::unique_ptr<Archive>> ArchiveOrErr = Archive::create(MB);
- error(ArchiveOrErr, "Failed to parse archive");
- return std::move(*ArchiveOrErr);
-}
-
void ArchiveFile::parse() {
- File = openArchive(MB);
+ ErrorOr<std::unique_ptr<Archive>> FileOrErr = Archive::create(MB);
+ error(FileOrErr, "Failed to parse archive");
+ File = std::move(*FileOrErr);
// Allocate a buffer for Lazy objects.
size_t NumSyms = File->getNumberOfSymbols();
@@ -345,28 +339,9 @@ MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
return *RefOrErr;
}
-std::vector<MemoryBufferRef> ArchiveFile::getMembers() {
- File = openArchive(MB);
-
- std::vector<MemoryBufferRef> Result;
- for (auto &ChildOrErr : File->children()) {
- error(ChildOrErr,
- "Could not get the child of the archive " + File->getFileName());
- const Archive::Child Child(*ChildOrErr);
- ErrorOr<MemoryBufferRef> MbOrErr = Child.getMemoryBufferRef();
- if (!MbOrErr)
- error(MbOrErr, "Could not get the buffer for a child of the archive " +
- File->getFileName());
- Result.push_back(MbOrErr.get());
- }
- return Result;
-}
-
template <class ELFT>
SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
- : ELFFileBase<ELFT>(Base::SharedKind, M) {
- AsNeeded = Config->AsNeeded;
-}
+ : ELFFileBase<ELFT>(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {}
template <class ELFT>
const typename ELFFile<ELFT>::Elf_Shdr *
@@ -379,6 +354,8 @@ SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const {
return *Ret;
}
+// Partially parse the shared object file so that we can call
+// getSoName on this object.
template <class ELFT> void SharedFile<ELFT>::parseSoName() {
typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
@@ -405,7 +382,7 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
}
this->initStringTable();
- this->SoName = this->getName();
+ SoName = this->getName();
if (!DynamicSec)
return;
@@ -418,13 +395,14 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
uintX_t Val = Dyn.getVal();
if (Val >= this->StringTable.size())
error("Invalid DT_SONAME entry");
- this->SoName = StringRef(this->StringTable.data() + Val);
+ SoName = StringRef(this->StringTable.data() + Val);
return;
}
}
}
-template <class ELFT> void SharedFile<ELFT>::parse() {
+// Fully parse the shared object file. This must be called after parseSoName().
+template <class ELFT> void SharedFile<ELFT>::parseRest() {
Elf_Sym_Range Syms = this->getNonLocalSymbols();
uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
SymbolBodies.reserve(NumSymbols);
@@ -456,7 +434,7 @@ static std::unique_ptr<InputFile> createELFFileAux(MemoryBufferRef MB) {
}
template <template <class> class T>
-std::unique_ptr<InputFile> lld::elf2::createELFFile(MemoryBufferRef MB) {
+static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) {
std::pair<unsigned char, unsigned char> Type = getElfArchType(MB.getBuffer());
if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
error("Invalid data encoding: " + MB.getBufferIdentifier());
@@ -474,6 +452,14 @@ std::unique_ptr<InputFile> lld::elf2::createELFFile(MemoryBufferRef MB) {
error("Invalid file class: " + MB.getBufferIdentifier());
}
+std::unique_ptr<InputFile> elf2::createObjectFile(MemoryBufferRef MB) {
+ return createELFFile<ObjectFile>(MB);
+}
+
+std::unique_ptr<InputFile> elf2::createSharedFile(MemoryBufferRef MB) {
+ return createELFFile<SharedFile>(MB);
+}
+
template class elf2::ELFFileBase<ELF32LE>;
template class elf2::ELFFileBase<ELF32BE>;
template class elf2::ELFFileBase<ELF64LE>;
@@ -488,9 +474,3 @@ template class elf2::SharedFile<ELF32LE>;
template class elf2::SharedFile<ELF32BE>;
template class elf2::SharedFile<ELF64LE>;
template class elf2::SharedFile<ELF64BE>;
-
-template std::unique_ptr<InputFile>
-elf2::createELFFile<ObjectFile>(MemoryBufferRef);
-
-template std::unique_ptr<InputFile>
-elf2::createELFFile<SharedFile>(MemoryBufferRef);
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 4e529c558cf5..9c54a9328f80 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -101,10 +101,10 @@ public:
return F->kind() == Base::ObjectKind;
}
- ArrayRef<SymbolBody *> getSymbols() { return this->SymbolBodies; }
+ ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
explicit ObjectFile(MemoryBufferRef M);
- void parse(llvm::DenseSet<StringRef> &Comdats);
+ void parse(llvm::DenseSet<StringRef> &ComdatGroups);
ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
@@ -113,7 +113,7 @@ public:
uint32_t FirstNonLocal = this->Symtab->sh_info;
if (SymbolIndex < FirstNonLocal)
return nullptr;
- return this->SymbolBodies[SymbolIndex - FirstNonLocal];
+ return SymbolBodies[SymbolIndex - FirstNonLocal];
}
Elf_Sym_Range getLocalSymbols();
@@ -127,7 +127,7 @@ public:
uint32_t getMipsGp0() const;
private:
- void initializeSections(llvm::DenseSet<StringRef> &Comdats);
+ void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);
void initializeSymbols();
InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
@@ -159,7 +159,6 @@ public:
MemoryBufferRef getMember(const Archive::Symbol *Sym);
llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
- std::vector<MemoryBufferRef> getMembers();
private:
std::unique_ptr<Archive> File;
@@ -194,7 +193,7 @@ public:
explicit SharedFile(MemoryBufferRef M);
void parseSoName();
- void parse();
+ void parseRest();
// Used for --as-needed
bool AsNeeded = false;
@@ -202,8 +201,8 @@ public:
bool isNeeded() const { return !AsNeeded || IsUsed; }
};
-template <template <class> class T>
-std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB);
+std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB);
+std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB);
} // namespace elf2
} // namespace lld
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index d4dc9864ae91..24491a2e17c0 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -93,6 +93,10 @@ InputSectionBase<ELFT>
InputSectionBase<ELFT>::Discarded(nullptr, nullptr,
InputSectionBase<ELFT>::Regular);
+// Usually sections are copied to the output as atomic chunks of data,
+// but some special types of sections are split into small pieces of data
+// and each piece is copied to a different place in the output.
+// This class represents such special sections.
template <class ELFT> class SplitInputSection : public InputSectionBase<ELFT> {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
@@ -100,7 +104,11 @@ template <class ELFT> class SplitInputSection : public InputSectionBase<ELFT> {
public:
SplitInputSection(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
typename InputSectionBase<ELFT>::Kind SectionKind);
+
+ // For each piece of data, we maintain the offsets in the input section and
+ // in the output section. The latter may be -1 if it is not assigned yet.
std::vector<std::pair<uintX_t, uintX_t>> Offsets;
+
std::pair<std::pair<uintX_t, uintX_t> *, uintX_t>
getRangeAndSize(uintX_t Offset);
};
diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp
index 1ad9b01af4e8..b719b1a09c25 100644
--- a/ELF/MarkLive.cpp
+++ b/ELF/MarkLive.cpp
@@ -16,7 +16,7 @@
// by default. Starting with GC-root symbols or sections, markLive function
// defined in this file visits all reachable sections to set their Live
// bits. Writer will then ignore sections whose Live bits are off, so that
-// such sections are removed from output.
+// such sections are not included into output.
//
//===----------------------------------------------------------------------===//
@@ -37,7 +37,7 @@ using namespace llvm::object;
using namespace lld;
using namespace lld::elf2;
-// Calls Fn for each section that Sec refers to.
+// Calls Fn for each section that Sec refers to via relocations.
template <class ELFT>
static void forEachSuccessor(InputSection<ELFT> *Sec,
std::function<void(InputSectionBase<ELFT> *)> Fn) {
@@ -104,7 +104,7 @@ template <class ELFT> void lld::elf2::markLive(SymbolTable<ELFT> *Symtab) {
MarkSymbol(Symtab->find(S));
// Preserve externally-visible symbols if the symbols defined by this
- // file could override other ELF file's symbols at runtime.
+ // file can interrupt other ELF file's symbols at runtime.
if (Config->Shared || Config->ExportDynamic) {
for (const std::pair<StringRef, Symbol *> &P : Symtab->getSymbols()) {
SymbolBody *B = P.second->Body;
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 8bdc2b0e5c4f..30ec83f4d3b1 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -239,14 +239,13 @@ bool RelocationSection<ELFT>::applyTlsDynamicReloc(SymbolBody *Body,
}
template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
- const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
for (const DynamicReloc<ELFT> &Rel : Relocs) {
auto *P = reinterpret_cast<Elf_Rel *>(Buf);
- Buf += EntrySize;
+ Buf += IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
// Skip placeholder for global dynamic TLS relocation pair. It was already
// handled by the previous relocation.
- if (!Rel.C || !Rel.RI)
+ if (!Rel.C)
continue;
InputSectionBase<ELFT> &C = *Rel.C;
@@ -262,16 +261,16 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
continue;
bool NeedsCopy = Body && Target->needsCopyRel(Type, *Body);
bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body);
- bool CanBePreempted = canBePreempted(Body, NeedsGot);
+ bool CBP = canBePreempted(Body, NeedsGot);
bool LazyReloc = Body && Target->supportsLazyRelocations() &&
Target->relocNeedsPlt(Type, *Body);
bool IsDynRelative = Type == Target->getRelativeReloc();
- unsigned Sym = CanBePreempted ? Body->DynamicSymbolTableIndex : 0;
+ unsigned Sym = CBP ? Body->DynamicSymbolTableIndex : 0;
unsigned Reloc;
- if (!CanBePreempted && Body && isGnuIFunc<ELFT>(*Body))
+ if (!CBP && Body && isGnuIFunc<ELFT>(*Body))
Reloc = Target->getIRelativeReloc();
- else if (!CanBePreempted || IsDynRelative)
+ else if (!CBP || IsDynRelative)
Reloc = Target->getRelativeReloc();
else if (LazyReloc)
Reloc = Target->getPltReloc();
@@ -289,7 +288,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
else if (NeedsCopy)
P->r_offset = Out<ELFT>::Bss->getVA() +
- dyn_cast<SharedSymbol<ELFT>>(Body)->OffsetInBSS;
+ cast<SharedSymbol<ELFT>>(Body)->OffsetInBss;
else
P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
@@ -300,7 +299,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
uintX_t Addend;
if (NeedsCopy)
Addend = 0;
- else if (CanBePreempted || IsDynRelative)
+ else if (CBP || IsDynRelative)
Addend = OrigAddend;
else if (Body)
Addend = getSymVA<ELFT>(*Body) + OrigAddend;
@@ -640,6 +639,9 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
if (DtFlags1)
++NumEntries; // DT_FLAGS_1
+ if (!Config->Entry.empty())
+ ++NumEntries; // DT_DEBUG
+
if (Config->EMachine == EM_MIPS) {
++NumEntries; // DT_MIPS_RLD_VERSION
++NumEntries; // DT_MIPS_FLAGS
@@ -738,6 +740,8 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
WriteVal(DT_FLAGS, DtFlags);
if (DtFlags1)
WriteVal(DT_FLAGS_1, DtFlags1);
+ if (!Config->Entry.empty())
+ WriteVal(DT_DEBUG, 0);
// See "Dynamic Section" in Chapter 5 in the following document
// for detailed description:
@@ -799,11 +803,11 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
return SC->OutSec->getVA() + SC->getOffset(DR.Sym);
}
case SymbolBody::DefinedCommonKind:
- return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBSS;
+ return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBss;
case SymbolBody::SharedKind: {
auto &SS = cast<SharedSymbol<ELFT>>(S);
if (SS.NeedsCopy)
- return Out<ELFT>::Bss->getVA() + SS.OffsetInBSS;
+ return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
return 0;
}
case SymbolBody::UndefinedElfKind:
@@ -1119,9 +1123,9 @@ void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
ArrayRef<uint8_t> D = S->getSectionData();
StringRef Data((const char *)D.data(), D.size());
uintX_t EntSize = S->getSectionHdr()->sh_entsize;
- uintX_t Offset = 0;
if (this->Header.sh_flags & SHF_STRINGS) {
+ uintX_t Offset = 0;
while (!Data.empty()) {
size_t End = findNull(Data, EntSize);
if (End == StringRef::npos)
@@ -1139,8 +1143,7 @@ void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
for (unsigned I = 0, N = Data.size(); I != N; I += EntSize) {
StringRef Entry = Data.substr(I, EntSize);
size_t OutputOffset = Builder.add(Entry);
- S->Offsets.push_back(std::make_pair(Offset, OutputOffset));
- Offset += EntSize;
+ S->Offsets.push_back(std::make_pair(I, OutputOffset));
}
}
}
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index e022ecd2e90d..74951bad410f 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// Symbol table is a bag of all known symbols. We put all symbols of
-// all input files to the symbol table. The symbol Table is basically
+// all input files to the symbol table. The symbol table is basically
// a hash table with the logic to resolve symbol name conflicts using
// the symbol types.
//
@@ -28,6 +28,9 @@ using namespace lld::elf2;
template <class ELFT> SymbolTable<ELFT>::SymbolTable() {}
+// 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 void checkCompatibility(InputFile *FileP) {
auto *F = dyn_cast<ELFFileBase<ELFT>>(FileP);
@@ -42,6 +45,7 @@ static void checkCompatibility(InputFile *FileP) {
error(A + " is incompatible with " + B);
}
+// Add symbols in File to the symbol table.
template <class ELFT>
void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
InputFile *FileP = File.get();
@@ -64,7 +68,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
return;
SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
- F->parse();
+ F->parseRest();
for (SharedSymbol<ELFT> &B : F->getSharedSymbols())
resolve(&B);
return;
@@ -73,7 +77,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
// .o file
auto *F = cast<ObjectFile<ELFT>>(FileP);
ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
- F->parse(Comdats);
+ F->parse(ComdatGroups);
for (SymbolBody *B : F->getSymbols())
resolve(B);
}
@@ -109,6 +113,9 @@ void SymbolTable<ELFT>::addSynthetic(StringRef Name,
resolve(Sym);
}
+// Add Name as an "ignored" symbol. An ignored symbol is a regular
+// linker-synthesized defined symbol, but it is not recorded to the output
+// file's symbol table. Such symbols are useful for some linker-defined symbols.
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {
auto *Sym = new (Alloc)
@@ -117,18 +124,10 @@ SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {
return Sym;
}
-template <class ELFT> bool SymbolTable<ELFT>::isUndefined(StringRef Name) {
- if (SymbolBody *Sym = find(Name))
- return Sym->isUndefined();
- return false;
-}
-
// Returns a file from which symbol B was created.
-// If B does not belong to any file in ObjectFiles, returns a nullptr.
+// If B does not belong to any file, returns a nullptr.
template <class ELFT>
-ELFFileBase<ELFT> *
-elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles,
- const SymbolBody *B) {
+ELFFileBase<ELFT> *SymbolTable<ELFT>::findFile(SymbolBody *B) {
for (const std::unique_ptr<ObjectFile<ELFT>> &F : ObjectFiles) {
ArrayRef<SymbolBody *> Syms = F->getSymbols();
if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
@@ -139,8 +138,8 @@ elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles,
template <class ELFT>
std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
- ELFFileBase<ELFT> *OldFile = findFile<ELFT>(ObjectFiles, Old);
- ELFFileBase<ELFT> *NewFile = findFile<ELFT>(ObjectFiles, New);
+ ELFFileBase<ELFT> *OldFile = findFile(Old);
+ ELFFileBase<ELFT> *NewFile = findFile(New);
StringRef Sym = Old->getName();
StringRef F1 = OldFile ? OldFile->getName() : "(internal)";
@@ -173,15 +172,15 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
// compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
// equivalent (conflicting), or more preferable, respectively.
- int comp = Existing->compare<ELFT>(New);
- if (comp == 0) {
+ int Comp = Existing->compare<ELFT>(New);
+ if (Comp == 0) {
std::string S = "duplicate symbol: " + conflictMsg(Existing, New);
if (!Config->AllowMultipleDefinition)
error(S);
warning(S);
return;
}
- if (comp < 0)
+ if (Comp < 0)
Sym->Body = New;
}
@@ -248,20 +247,7 @@ template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
Sym->setUsedInDynamicReloc();
}
-template class lld::elf2::SymbolTable<ELF32LE>;
-template class lld::elf2::SymbolTable<ELF32BE>;
-template class lld::elf2::SymbolTable<ELF64LE>;
-template class lld::elf2::SymbolTable<ELF64BE>;
-
-template ELFFileBase<ELF32LE> *
-lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF32LE>>>,
- const SymbolBody *);
-template ELFFileBase<ELF32BE> *
-lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF32BE>>>,
- const SymbolBody *);
-template ELFFileBase<ELF64LE> *
-lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF64LE>>>,
- const SymbolBody *);
-template ELFFileBase<ELF64BE> *
-lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF64BE>>>,
- const SymbolBody *);
+template class elf2::SymbolTable<ELF32LE>;
+template class elf2::SymbolTable<ELF32BE>;
+template class elf2::SymbolTable<ELF64LE>;
+template class elf2::SymbolTable<ELF64BE>;
diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h
index aa905e027d48..4f8f5afa420a 100644
--- a/ELF/SymbolTable.h
+++ b/ELF/SymbolTable.h
@@ -55,9 +55,9 @@ public:
void addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,
typename llvm::object::ELFFile<ELFT>::uintX_t Value);
SymbolBody *addIgnored(StringRef Name);
- bool isUndefined(StringRef Name);
void scanShlibUndefined();
SymbolBody *find(StringRef Name);
+ ELFFileBase<ELFT> *findFile(SymbolBody *B);
private:
Symbol *insert(SymbolBody *New);
@@ -78,7 +78,7 @@ private:
llvm::MapVector<StringRef, Symbol *> Symtab;
llvm::BumpPtrAllocator Alloc;
- llvm::DenseSet<StringRef> Comdats;
+ llvm::DenseSet<StringRef> ComdatGroups;
// The writer needs to infer the machine type from the object files.
std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
@@ -87,11 +87,6 @@ private:
llvm::DenseSet<StringRef> IncludedSoNames;
};
-template <class ELFT>
-ELFFileBase<ELFT> *
-findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles,
- const SymbolBody *B);
-
} // namespace elf2
} // namespace lld
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index f8d585242a86..4af1b88e79ad 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -115,8 +115,7 @@ std::unique_ptr<InputFile> Lazy::getMember() {
// read from the library.
if (MBRef.getBuffer().empty())
return std::unique_ptr<InputFile>(nullptr);
-
- return createELFFile<ObjectFile>(MBRef);
+ return createObjectFile(MBRef);
}
template <class ELFT> static void doInitSymbols() {
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index 8556452dbb13..16a3b338b3cd 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -173,7 +173,7 @@ public:
// The output offset of this common symbol in the output bss. Computed by the
// writer.
- uint64_t OffsetInBSS;
+ uint64_t OffsetInBss;
// The maximum alignment we have seen for this symbol.
uint64_t MaxAlignment;
@@ -262,9 +262,9 @@ public:
SharedFile<ELFT> *File;
// True if the linker has to generate a copy relocation for this shared
- // symbol. OffsetInBSS is significant only when NeedsCopy is true.
+ // symbol. OffsetInBss is significant only when NeedsCopy is true.
bool NeedsCopy = false;
- uintX_t OffsetInBSS = 0;
+ uintX_t OffsetInBss = 0;
};
// This class represents a symbol defined in an archive file. It is
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index 8d848d040c61..8d54c93570fa 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -320,7 +320,7 @@ void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
// separate procedure linkage tables.
if (Config->Shared) {
const uint8_t V[] = {
- 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx
+ 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx)
0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx)
0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop
};
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index bdcb720a8a48..2437a435657c 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -69,7 +69,7 @@ private:
}
int getPhdrsNum() const;
- OutputSection<ELFT> *getBSS();
+ OutputSection<ELFT> *getBss();
void addCommonSymbols(std::vector<DefinedCommon *> &Syms);
void addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms);
@@ -330,18 +330,17 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S,
}
template <class ELFT>
-static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) {
+static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
if (Config->Shared && !Config->NoUndefined)
return;
- ELFFileBase<ELFT> *SymFile = findFile<ELFT>(S.getObjectFiles(), &Sym);
- std::string Message = "undefined symbol: " + Sym.getName().str();
- if (SymFile)
- Message += " in " + SymFile->getName().str();
+ std::string Msg = "undefined symbol: " + Sym->getName().str();
+ if (ELFFileBase<ELFT> *File = Symtab.findFile(Sym))
+ Msg += " in " + File->getName().str();
if (Config->NoInhibitExec)
- warning(Message);
+ warning(Msg);
else
- error(Message);
+ error(Msg);
}
// Local symbols are not in the linker's symbol table. This function scans
@@ -466,7 +465,7 @@ static bool compareOutputSections(OutputSectionBase<ELFT> *A,
return false;
}
-template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBSS() {
+template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBss() {
if (!Out<ELFT>::Bss) {
Out<ELFT>::Bss =
new OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
@@ -480,8 +479,6 @@ template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBSS() {
// This function adds them to end of BSS section.
template <class ELFT>
void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
-
if (Syms.empty())
return;
@@ -491,11 +488,11 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
return A->MaxAlignment > B->MaxAlignment;
});
- uintX_t Off = getBSS()->getSize();
+ uintX_t Off = getBss()->getSize();
for (DefinedCommon *C : Syms) {
uintX_t Align = C->MaxAlignment;
Off = RoundUpToAlignment(Off, Align);
- C->OffsetInBSS = Off;
+ C->OffsetInBss = Off;
Off += C->Size;
}
@@ -507,7 +504,7 @@ template <class ELFT>
void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) {
if (Syms.empty())
return;
- uintX_t Off = getBSS()->getSize();
+ uintX_t Off = getBss()->getSize();
for (SharedSymbol<ELFT> *C : Syms) {
const Elf_Sym &Sym = C->Sym;
const Elf_Shdr *Sec = C->File->getSection(Sym);
@@ -518,7 +515,7 @@ void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) {
uintX_t Align = 1 << TrailingZeros;
Out<ELFT>::Bss->updateAlign(Align);
Off = RoundUpToAlignment(Off, Align);
- C->OffsetInBSS = Off;
+ C->OffsetInBss = Off;
Off += Sym.st_size;
}
Out<ELFT>::Bss->setSize(Off);
@@ -803,7 +800,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
SymbolBody *Body = P.second->Body;
if (auto *U = dyn_cast<Undefined>(Body))
if (!U->isWeak() && !U->canKeepUndefined())
- reportUndefined<ELFT>(Symtab, *Body);
+ reportUndefined<ELFT>(Symtab, Body);
if (auto *C = dyn_cast<DefinedCommon>(Body))
CommonSymbols.push_back(C);
@@ -958,10 +955,12 @@ void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
StringSaver Saver(Alloc);
StringRef Start = Saver.save("__start_" + S);
StringRef Stop = Saver.save("__stop_" + S);
- if (Symtab.isUndefined(Start))
- Symtab.addSynthetic(Start, *Sec, 0);
- if (Symtab.isUndefined(Stop))
- Symtab.addSynthetic(Stop, *Sec, Sec->getSize());
+ if (SymbolBody *B = Symtab.find(Start))
+ if (B->isUndefined())
+ Symtab.addSynthetic(Start, *Sec, 0);
+ if (SymbolBody *B = Symtab.find(Stop))
+ if (B->isUndefined())
+ Symtab.addSynthetic(Stop, *Sec, Sec->getSize());
}
template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) {
@@ -1016,7 +1015,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
Elf_Phdr GnuRelroPhdr = {};
Elf_Phdr TlsPhdr{};
bool RelroAligned = false;
- uintX_t ThreadBSSOffset = 0;
+ uintX_t ThreadBssOffset = 0;
// Create phdrs as we assign VAs and file offsets to all output sections.
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
Elf_Phdr *PH = &Phdrs[PhdrIdx];
@@ -1042,11 +1041,11 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
if (Sec->getType() != SHT_NOBITS)
VA = RoundUpToAlignment(VA, Sec->getAlign());
- uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign());
+ uintX_t TVA = RoundUpToAlignment(VA + ThreadBssOffset, Sec->getAlign());
Sec->setVA(TVA);
TlsPhdr.p_memsz += Sec->getSize();
if (Sec->getType() == SHT_NOBITS) {
- ThreadBSSOffset = TVA - VA + Sec->getSize();
+ ThreadBssOffset = TVA - VA + Sec->getSize();
} else {
TlsPhdr.p_filesz += Sec->getSize();
VA += Sec->getSize();