aboutsummaryrefslogtreecommitdiff
path: root/ELF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-08 17:13:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-08 17:13:44 +0000
commitfbe69f787ace06f44b6cb1bd3cd45ac703a16a05 (patch)
tree71baf2dfe04008283f87b4c0ae75a2268033cd62 /ELF
parentd803cda42997f42649910309ac18170d2d6f2214 (diff)
downloadsrc-fbe69f787ace06f44b6cb1bd3cd45ac703a16a05.tar.gz
src-fbe69f787ace06f44b6cb1bd3cd45ac703a16a05.zip
Vendor import of lld trunk r302418:vendor/lld/lld-trunk-r302418
Notes
Notes: svn path=/vendor/lld/dist/; revision=317957 svn path=/vendor/lld/lld-trunk-r302418/; revision=317958; tag=vendor/lld/lld-trunk-r302418
Diffstat (limited to 'ELF')
-rw-r--r--ELF/Config.h2
-rw-r--r--ELF/Driver.cpp38
-rw-r--r--ELF/InputFiles.cpp21
-rw-r--r--ELF/InputFiles.h10
-rw-r--r--ELF/LinkerScript.cpp132
-rw-r--r--ELF/LinkerScript.h6
-rw-r--r--ELF/Options.td1
-rw-r--r--ELF/OutputSections.cpp24
-rw-r--r--ELF/Relocations.cpp16
-rw-r--r--ELF/SymbolTable.cpp9
-rw-r--r--ELF/Symbols.cpp7
-rw-r--r--ELF/SyntheticSections.cpp20
-rw-r--r--ELF/Target.cpp42
-rw-r--r--ELF/Target.h2
-rw-r--r--ELF/Writer.cpp89
-rw-r--r--ELF/Writer.h3
16 files changed, 197 insertions, 225 deletions
diff --git a/ELF/Config.h b/ELF/Config.h
index 1ace4aa26fdb..0321c84e7106 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -73,6 +73,7 @@ struct VersionDefinition {
// Most fields are initialized by the driver.
struct Configuration {
InputFile *FirstElf = nullptr;
+ bool HasStaticTlsModel = false;
uint8_t OSABI = 0;
llvm::CachePruningPolicy ThinLTOCachePolicy;
llvm::StringMap<uint64_t> SectionStartMap;
@@ -99,7 +100,6 @@ struct Configuration {
std::vector<SymbolVersion> VersionScriptLocals;
std::vector<uint8_t> BuildIdVector;
bool AllowMultipleDefinition;
- bool ArchiveWithoutSymbolsSeen = false;
bool AsNeeded = false;
bool Bsymbolic;
bool BsymbolicFunctions;
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 6a71eb3ee490..c2cfe3c4129e 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -123,13 +123,13 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {
// Returns slices of MB by parsing MB as an archive file.
// Each slice consists of a member file in the archive.
-std::vector<MemoryBufferRef>
-static getArchiveMembers(MemoryBufferRef MB) {
+std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
+ MemoryBufferRef MB) {
std::unique_ptr<Archive> File =
check(Archive::create(MB),
MB.getBufferIdentifier() + ": failed to parse archive");
- std::vector<MemoryBufferRef> V;
+ std::vector<std::pair<MemoryBufferRef, uint64_t>> V;
Error Err = Error::success();
for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {
Archive::Child C =
@@ -139,7 +139,7 @@ static getArchiveMembers(MemoryBufferRef MB) {
check(C.getMemoryBufferRef(),
MB.getBufferIdentifier() +
": could not get the buffer for a child of the archive");
- V.push_back(MBRef);
+ V.push_back(std::make_pair(MBRef, C.getChildOffset()));
}
if (Err)
fatal(MB.getBufferIdentifier() + ": Archive::children failed: " +
@@ -152,8 +152,7 @@ static getArchiveMembers(MemoryBufferRef MB) {
return V;
}
-// Opens and parses a file. Path has to be resolved already.
-// Newly created memory buffers are owned by this driver.
+// Opens a file and create a file object. Path has to be resolved already.
void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
using namespace sys::fs;
@@ -171,14 +170,31 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
case file_magic::unknown:
readLinkerScript(MBRef);
return;
- case file_magic::archive:
+ case file_magic::archive: {
+ // Handle -whole-archive.
if (InWholeArchive) {
- for (MemoryBufferRef MB : getArchiveMembers(MBRef))
- Files.push_back(createObjectFile(MB, Path));
+ for (const auto &P : getArchiveMembers(MBRef))
+ Files.push_back(createObjectFile(P.first, Path, P.second));
return;
}
- Files.push_back(make<ArchiveFile>(MBRef));
+
+ std::unique_ptr<Archive> File =
+ check(Archive::create(MBRef), Path + ": failed to parse archive");
+
+ // If an archive file has no symbol table, it is likely that a user
+ // is attempting LTO and using a default ar command that doesn't
+ // understand the LLVM bitcode file. It is a pretty common error, so
+ // we'll handle it as if it had a symbol table.
+ if (!File->hasSymbolTable()) {
+ for (const auto &P : getArchiveMembers(MBRef))
+ Files.push_back(make<LazyObjectFile>(P.first, Path, P.second));
+ return;
+ }
+
+ // Handle the regular case.
+ Files.push_back(make<ArchiveFile>(std::move(File)));
return;
+ }
case file_magic::elf_shared_object:
if (Config->Relocatable) {
error("attempted static link of dynamic object " + Path);
@@ -199,7 +215,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
return;
default:
if (InLib)
- Files.push_back(make<LazyObjectFile>(MBRef));
+ Files.push_back(make<LazyObjectFile>(MBRef, "", 0));
else
Files.push_back(createObjectFile(MBRef));
}
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 260a78ebbf8e..5f94fc9338a4 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -596,17 +596,13 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
}
}
-template <class ELFT> void ArchiveFile::parse() {
- File = check(Archive::create(MB),
- MB.getBufferIdentifier() + ": failed to parse archive");
+ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File)
+ : InputFile(ArchiveKind, File->getMemoryBufferRef()),
+ File(std::move(File)) {}
- // Read the symbol table to construct Lazy objects.
- for (const Archive::Symbol &Sym : File->symbols()) {
+template <class ELFT> void ArchiveFile::parse() {
+ for (const Archive::Symbol &Sym : File->symbols())
Symtab<ELFT>::X->addLazyArchive(this, Sym);
- }
-
- if (File->symbols().begin() == File->symbols().end())
- Config->ArchiveWithoutSymbolsSeen = true;
}
// Returns a buffer pointing to a member file containing a given symbol.
@@ -981,6 +977,13 @@ MemoryBufferRef LazyObjectFile::getBuffer() {
return MB;
}
+InputFile *LazyObjectFile::fetch() {
+ MemoryBufferRef MBRef = getBuffer();
+ if (MBRef.getBuffer().empty())
+ return nullptr;
+ return createObjectFile(MBRef, ArchiveName, OffsetInArchive);
+}
+
template <class ELFT> void LazyObjectFile::parse() {
for (StringRef Sym : getSymbols())
Symtab<ELFT>::X->addLazyObject(Sym, *this);
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index d0a45a4a98cf..6daf26649859 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -219,7 +219,11 @@ private:
// archive file semantics.
class LazyObjectFile : public InputFile {
public:
- explicit LazyObjectFile(MemoryBufferRef M) : InputFile(LazyObjectKind, M) {}
+ LazyObjectFile(MemoryBufferRef M, StringRef ArchiveName,
+ uint64_t OffsetInArchive)
+ : InputFile(LazyObjectKind, M), OffsetInArchive(OffsetInArchive) {
+ this->ArchiveName = ArchiveName;
+ }
static bool classof(const InputFile *F) {
return F->kind() == LazyObjectKind;
@@ -227,6 +231,7 @@ public:
template <class ELFT> void parse();
MemoryBufferRef getBuffer();
+ InputFile *fetch();
private:
std::vector<StringRef> getSymbols();
@@ -234,12 +239,13 @@ private:
std::vector<StringRef> getBitcodeSymbols();
bool Seen = false;
+ uint64_t OffsetInArchive;
};
// An ArchiveFile object represents a .a file.
class ArchiveFile : public InputFile {
public:
- explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
+ explicit ArchiveFile(std::unique_ptr<Archive> &&File);
static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
template <class ELFT> void parse();
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index 3f872c65897f..d7858e173c7b 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -406,27 +406,22 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
}
// Add input sections to an output section.
- unsigned Pos = 0;
- for (InputSectionBase *S : V) {
- // The actual offset will be computed during
- // assignAddresses. For now, use the index as a very crude
- // approximation so that it is at least easy for other code to
- // know the section order.
- cast<InputSection>(S)->OutSecOff = Pos++;
+ for (InputSectionBase *S : V)
Factory.addInputSec(S, Cmd->Name, Cmd->Sec);
+ if (OutputSection *Sec = Cmd->Sec) {
+ assert(Sec->SectionIndex == INT_MAX);
+ Sec->SectionIndex = I;
}
}
}
CurOutSec = nullptr;
}
-void LinkerScript::fabricateDefaultCommands(bool AllocateHeader) {
+void LinkerScript::fabricateDefaultCommands() {
std::vector<BaseCommand *> Commands;
// Define start address
- uint64_t StartAddr = Config->ImageBase;
- if (AllocateHeader)
- StartAddr += elf::getHeaderSize();
+ uint64_t StartAddr = Config->ImageBase + elf::getHeaderSize();
// The Sections with -T<section> have been sorted in order of ascending
// address. We must lower StartAddr if the lowest -T<section address> as
@@ -488,6 +483,11 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
} else {
auto *Cmd = cast<OutputSectionCommand>(*I);
Factory.addInputSec(S, Name, Cmd->Sec);
+ if (OutputSection *Sec = Cmd->Sec) {
+ unsigned Index = std::distance(Opt.Commands.begin(), I);
+ assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index);
+ Sec->SectionIndex = Index;
+ }
auto *ISD = make<InputSectionDescription>("");
ISD->Sections.push_back(S);
Cmd->Commands.push_back(ISD);
@@ -495,17 +495,22 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
}
}
-static bool isTbss(OutputSection *Sec) {
- return (Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS;
+uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) {
+ bool IsTbss = (CurOutSec->Flags & SHF_TLS) && CurOutSec->Type == SHT_NOBITS;
+ uint64_t Start = IsTbss ? Dot + ThreadBssOffset : Dot;
+ Start = alignTo(Start, Align);
+ uint64_t End = Start + Size;
+
+ if (IsTbss)
+ ThreadBssOffset = End - Dot;
+ else
+ Dot = End;
+ return End;
}
void LinkerScript::output(InputSection *S) {
- bool IsTbss = isTbss(CurOutSec);
-
- uint64_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot;
- Pos = alignTo(Pos, S->Alignment);
- S->OutSecOff = Pos - CurOutSec->Addr;
- Pos += S->getSize();
+ uint64_t Pos = advance(S->getSize(), S->Alignment);
+ S->OutSecOff = Pos - S->getSize() - CurOutSec->Addr;
// Update output section size after adding each section. This is so that
// SIZEOF works correctly in the case below:
@@ -524,11 +529,6 @@ void LinkerScript::output(InputSection *S) {
" bytes");
}
}
-
- if (IsTbss)
- ThreadBssOffset = Pos - Dot;
- else
- Dot = Pos;
}
void LinkerScript::switchTo(OutputSection *Sec) {
@@ -536,9 +536,7 @@ void LinkerScript::switchTo(OutputSection *Sec) {
return;
CurOutSec = Sec;
-
- Dot = alignTo(Dot, CurOutSec->Alignment);
- CurOutSec->Addr = isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot;
+ CurOutSec->Addr = advance(0, CurOutSec->Alignment);
// If neither AT nor AT> is specified for an allocatable section, the linker
// will set the LMA such that the difference between VMA and LMA for the
@@ -643,6 +641,11 @@ void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) {
Dot = CurMemRegion->Offset;
switchTo(Sec);
+ // We do not support custom layout for compressed debug sectons.
+ // At this point we already know their size and have compressed content.
+ if (CurOutSec->Flags & SHF_COMPRESSED)
+ return;
+
for (BaseCommand *C : Cmd->Commands)
process(*C);
}
@@ -678,8 +681,9 @@ void LinkerScript::adjustSectionsBeforeSorting() {
// consequeces and gives us a section to put the symbol in.
uint64_t Flags = SHF_ALLOC;
uint32_t Type = SHT_PROGBITS;
- for (BaseCommand *Base : Opt.Commands) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
+
+ for (int I = 0, E = Opt.Commands.size(); I != E; ++I) {
+ auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]);
if (!Cmd)
continue;
if (OutputSection *Sec = Cmd->Sec) {
@@ -692,6 +696,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
continue;
auto *OutSec = make<OutputSection>(Cmd->Name, Type, Flags);
+ OutSec->SectionIndex = I;
OutputSections->push_back(OutSec);
Cmd->Sec = OutSec;
}
@@ -894,6 +899,48 @@ void LinkerScript::synchronize() {
}
}
+static bool allocateHeaders(std::vector<PhdrEntry> &Phdrs,
+ ArrayRef<OutputSection *> OutputSections,
+ uint64_t Min) {
+ auto FirstPTLoad =
+ std::find_if(Phdrs.begin(), Phdrs.end(),
+ [](const PhdrEntry &E) { return E.p_type == PT_LOAD; });
+ if (FirstPTLoad == Phdrs.end())
+ return false;
+
+ uint64_t HeaderSize = getHeaderSize();
+ if (HeaderSize <= Min || Script->hasPhdrsCommands()) {
+ Min = alignDown(Min - HeaderSize, Config->MaxPageSize);
+ Out::ElfHeader->Addr = Min;
+ Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size;
+ return true;
+ }
+
+ assert(FirstPTLoad->First == Out::ElfHeader);
+ OutputSection *ActualFirst = nullptr;
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec->FirstInPtLoad == Out::ElfHeader) {
+ ActualFirst = Sec;
+ break;
+ }
+ }
+ if (ActualFirst) {
+ for (OutputSection *Sec : OutputSections)
+ if (Sec->FirstInPtLoad == Out::ElfHeader)
+ Sec->FirstInPtLoad = ActualFirst;
+ FirstPTLoad->First = ActualFirst;
+ } else {
+ Phdrs.erase(FirstPTLoad);
+ }
+
+ auto PhdrI = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) {
+ return E.p_type == PT_PHDR;
+ });
+ if (PhdrI != Phdrs.end())
+ Phdrs.erase(PhdrI);
+ return false;
+}
+
void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = 0;
@@ -994,12 +1041,17 @@ static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
llvm_unreachable("unsupported Size argument");
}
-void LinkerScript::writeDataBytes(StringRef Name, uint8_t *Buf) {
- int I = getSectionIndex(Name);
- if (I == INT_MAX)
+void LinkerScript::writeDataBytes(OutputSection *Sec, uint8_t *Buf) {
+ auto I = std::find_if(Opt.Commands.begin(), Opt.Commands.end(),
+ [=](BaseCommand *Base) {
+ if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
+ if (Cmd->Sec == Sec)
+ return true;
+ return false;
+ });
+ if (I == Opt.Commands.end())
return;
-
- auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]);
+ auto *Cmd = cast<OutputSectionCommand>(*I);
for (BaseCommand *Base : Cmd->Commands)
if (auto *Data = dyn_cast<BytesDataCommand>(Base))
writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
@@ -1013,18 +1065,6 @@ bool LinkerScript::hasLMA(StringRef Name) {
return false;
}
-// Returns the index of the given section name in linker script
-// SECTIONS commands. Sections are laid out as the same order as they
-// were in the script. If a given name did not appear in the script,
-// it returns INT_MAX, so that it will be laid out at end of file.
-int LinkerScript::getSectionIndex(StringRef Name) {
- for (int I = 0, E = Opt.Commands.size(); I != E; ++I)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]))
- if (Cmd->Name == Name)
- return I;
- return INT_MAX;
-}
-
ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
if (S == ".")
return {CurOutSec, Dot - CurOutSec->Addr};
diff --git a/ELF/LinkerScript.h b/ELF/LinkerScript.h
index dd96d335a660..7bcd21c87602 100644
--- a/ELF/LinkerScript.h
+++ b/ELF/LinkerScript.h
@@ -228,6 +228,7 @@ protected:
MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
void switchTo(OutputSection *Sec);
+ uint64_t advance(uint64_t Size, unsigned Align);
void output(InputSection *Sec);
void process(BaseCommand &Base);
@@ -252,7 +253,7 @@ public:
bool isDefined(StringRef S);
std::vector<OutputSection *> *OutputSections;
- void fabricateDefaultCommands(bool AllocateHeader);
+ void fabricateDefaultCommands();
void addOrphanSections(OutputSectionFactory &Factory);
void removeEmptyCommands();
void adjustSectionsBeforeSorting();
@@ -269,9 +270,8 @@ public:
void processNonSectionCommands();
void synchronize();
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
- int getSectionIndex(StringRef Name);
- void writeDataBytes(StringRef Name, uint8_t *Buf);
+ void writeDataBytes(OutputSection *Sec, uint8_t *Buf);
void addSymbol(SymbolAssignment *Cmd);
void processCommands(OutputSectionFactory &Factory);
diff --git a/ELF/Options.td b/ELF/Options.td
index 8863912c179c..65a0e72d2320 100644
--- a/ELF/Options.td
+++ b/ELF/Options.td
@@ -290,6 +290,7 @@ def alias_L__library_path: J<"library-path=">, Alias<L>;
def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>;
def alias_define_common_dc: F<"dc">, Alias<define_common>;
def alias_define_common_dp: F<"dp">, Alias<define_common>;
+def alias_defsym: S<"defsym">, Alias<defsym>;
def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>;
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 839f68f2da55..cb9c57657af3 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -68,7 +68,8 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) {
OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
: SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
/*Info*/ 0,
- /*Link*/ 0) {}
+ /*Link*/ 0),
+ SectionIndex(INT_MAX) {}
static bool compareByFilePosition(InputSection *A, InputSection *B) {
// Synthetic doesn't have link order dependecy, stable_sort will keep it last
@@ -139,12 +140,24 @@ template <class ELFT> void OutputSection::finalize() {
this->Info = S->OutSec->SectionIndex;
}
+static uint64_t updateOffset(uint64_t Off, InputSection *S) {
+ Off = alignTo(Off, S->Alignment);
+ S->OutSecOff = Off;
+ return Off + S->getSize();
+}
+
void OutputSection::addSection(InputSection *S) {
assert(S->Live);
Sections.push_back(S);
S->OutSec = this;
this->updateAlignment(S->Alignment);
+ // The actual offsets will be computed by assignAddresses. For now, use
+ // crude approximation so that it is at least easy for other code to know the
+ // section order. It is also used to calculate the output section size early
+ // for compressed debug sections.
+ this->Size = updateOffset(Size, S);
+
// If this section contains a table of fixed-size entries, sh_entsize
// holds the element size. Consequently, if this contains two or more
// input sections, all of them must have the same sh_entsize. However,
@@ -159,11 +172,8 @@ void OutputSection::addSection(InputSection *S) {
// and scan relocations to setup sections' offsets.
void OutputSection::assignOffsets() {
uint64_t Off = 0;
- for (InputSection *S : Sections) {
- Off = alignTo(Off, S->Alignment);
- S->OutSecOff = Off;
- Off += S->getSize();
- }
+ for (InputSection *S : Sections)
+ Off = updateOffset(Off, S);
this->Size = Off;
}
@@ -305,7 +315,7 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {
// Linker scripts may have BYTE()-family commands with which you
// can write arbitrary bytes to the output. Process them if any.
- Script->writeDataBytes(Name, Buf);
+ Script->writeDataBytes(this, Buf);
}
static uint64_t getOutFlags(InputSectionBase *S) {
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index baef0a2f2257..f5db931e9755 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -233,7 +233,7 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
}
// Local-Dynamic relocs can be relaxed to Local-Exec.
- if (Target->isTlsLocalDynamicRel(Type) && !Config->Shared) {
+ if (isRelExprOneOf<R_ABS, R_TLSLD, R_TLSLD_PC>(Expr) && !Config->Shared) {
C.Relocations.push_back(
{R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body});
return 1;
@@ -282,7 +282,8 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
// defined.
- if (Target->isTlsInitialExecRel(Type) && !Config->Shared && !IsPreemptible) {
+ if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_GOT_PAGE_PC>(Expr) &&
+ !Config->Shared && !IsPreemptible) {
C.Relocations.push_back(
{R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body});
return 1;
@@ -694,17 +695,6 @@ static void reportUndefined(SymbolBody &Sym, InputSectionBase &S,
warn(Msg);
} else {
error(Msg);
-
- if (Config->ArchiveWithoutSymbolsSeen) {
- message("At least one archive listed no symbols in its index."
- " This can happen when creating archives with a version"
- " of ar that does not understand the object files in"
- " the archive. For example, if you are using LLVM"
- " bitcode objects (such as created by -flto), you may"
- " need to use llvm-ar or GNU ar with a plugin.");
- // Reset to false so that we print the message only once.
- Config->ArchiveWithoutSymbolsSeen = false;
- }
}
}
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 30f1c3653f50..ed8a790c9599 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -540,13 +540,10 @@ void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) {
return;
// See comment for addLazyArchive above.
- if (S->isWeak()) {
+ if (S->isWeak())
replaceBody<LazyObject>(S, Name, Obj, S->body()->Type);
- } else {
- MemoryBufferRef MBRef = Obj.getBuffer();
- if (!MBRef.getBuffer().empty())
- addFile(createObjectFile(MBRef));
- }
+ else if (InputFile *F = Obj.fetch())
+ addFile(F);
}
// Process undefined (-u) flags by loading lazy symbols named by those flags.
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 01caa6daa5ac..2090b33e8cd6 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -327,12 +327,7 @@ InputFile *LazyArchive::fetch() {
return createObjectFile(MBInfo.first, file()->getName(), MBInfo.second);
}
-InputFile *LazyObject::fetch() {
- MemoryBufferRef MBRef = file()->getBuffer();
- if (MBRef.getBuffer().empty())
- return nullptr;
- return createObjectFile(MBRef);
-}
+InputFile *LazyObject::fetch() { return file()->fetch(); }
uint8_t Symbol::computeBinding() const {
if (Config->Relocatable)
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index a271d31048f5..9c585e41e9f0 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -1038,6 +1038,15 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() {
if (!Config->SoName.empty())
add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)});
+ if (!Config->Shared && !Config->Relocatable)
+ add({DT_DEBUG, (uint64_t)0});
+}
+
+// Add remaining entries to complete .dynamic contents.
+template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
+ if (this->Size)
+ return; // Already finalized.
+
// Set DT_FLAGS and DT_FLAGS_1.
uint32_t DtFlags = 0;
uint32_t DtFlags1 = 0;
@@ -1055,21 +1064,14 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() {
DtFlags |= DF_ORIGIN;
DtFlags1 |= DF_1_ORIGIN;
}
+ if (Config->HasStaticTlsModel)
+ DtFlags |= DF_STATIC_TLS;
if (DtFlags)
add({DT_FLAGS, DtFlags});
if (DtFlags1)
add({DT_FLAGS_1, DtFlags1});
- if (!Config->Shared && !Config->Relocatable)
- add({DT_DEBUG, (uint64_t)0});
-}
-
-// Add remaining entries to complete .dynamic contents.
-template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
- if (this->Size)
- return; // Already finalized.
-
this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
if (In<ELFT>::RelaDyn->OutSec->Size > 0) {
bool IsRela = Config->IsRela;
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index 921505ae4b61..4643c1a919aa 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -124,8 +124,6 @@ public:
int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
void writeGotPltHeader(uint8_t *Buf) const override;
uint32_t getDynRel(uint32_t Type) const override;
- bool isTlsLocalDynamicRel(uint32_t Type) const override;
- bool isTlsInitialExecRel(uint32_t Type) const override;
void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override;
void writePltHeader(uint8_t *Buf) const override;
@@ -147,8 +145,6 @@ public:
RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
const uint8_t *Loc) const override;
bool isPicRel(uint32_t Type) const override;
- bool isTlsLocalDynamicRel(uint32_t Type) const override;
- bool isTlsInitialExecRel(uint32_t Type) const override;
void writeGotPltHeader(uint8_t *Buf) const override;
void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
void writePltHeader(uint8_t *Buf) const override;
@@ -193,7 +189,6 @@ public:
RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
const uint8_t *Loc) const override;
bool isPicRel(uint32_t Type) const override;
- bool isTlsInitialExecRel(uint32_t Type) const override;
void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
void writePltHeader(uint8_t *Buf) const override;
void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
@@ -303,10 +298,6 @@ bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
return false;
}
-bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return false; }
-
-bool TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const { return false; }
-
void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
writeGotPlt(Buf, S);
}
@@ -360,6 +351,15 @@ X86TargetInfo::X86TargetInfo() {
RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S,
const uint8_t *Loc) const {
+ // There are 4 different TLS variable models with varying degrees of
+ // flexibility and performance. LocalExec and InitialExec models are fast but
+ // less-flexible models. They cannot be used for dlopen(). If they are in use,
+ // we set DF_STATIC_TLS in the ELF header so that the runtime can reject such
+ // DSOs.
+ if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 || Type == R_386_TLS_IE ||
+ Type == R_386_TLS_GOTIE)
+ Config->HasStaticTlsModel = true;
+
switch (Type) {
case R_386_8:
case R_386_16:
@@ -451,14 +451,6 @@ uint32_t X86TargetInfo::getDynRel(uint32_t Type) const {
return Type;
}
-bool X86TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const {
- return Type == R_386_TLS_LDO_32 || Type == R_386_TLS_LDM;
-}
-
-bool X86TargetInfo::isTlsInitialExecRel(uint32_t Type) const {
- return Type == R_386_TLS_IE || Type == R_386_TLS_GOTIE;
-}
-
void X86TargetInfo::writePltHeader(uint8_t *Buf) const {
if (Config->Pic) {
const uint8_t V[] = {
@@ -772,17 +764,6 @@ bool X86_64TargetInfo<ELFT>::isPicRel(uint32_t Type) const {
}
template <class ELFT>
-bool X86_64TargetInfo<ELFT>::isTlsInitialExecRel(uint32_t Type) const {
- return Type == R_X86_64_GOTTPOFF;
-}
-
-template <class ELFT>
-bool X86_64TargetInfo<ELFT>::isTlsLocalDynamicRel(uint32_t Type) const {
- return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_DTPOFF64 ||
- Type == R_X86_64_TLSLD;
-}
-
-template <class ELFT>
void X86_64TargetInfo<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
uint64_t Val) const {
// Convert
@@ -1383,11 +1364,6 @@ bool AArch64TargetInfo::usesOnlyLowPageBits(uint32_t Type) const {
}
}
-bool AArch64TargetInfo::isTlsInitialExecRel(uint32_t Type) const {
- return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
- Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
-}
-
bool AArch64TargetInfo::isPicRel(uint32_t Type) const {
return Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64;
}
diff --git a/ELF/Target.h b/ELF/Target.h
index 4b88626050b3..f4f366219d86 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -23,8 +23,6 @@ class SymbolBody;
class TargetInfo {
public:
- virtual bool isTlsInitialExecRel(uint32_t Type) const;
- virtual bool isTlsLocalDynamicRel(uint32_t Type) const;
virtual bool isPicRel(uint32_t Type) const { return true; }
virtual uint32_t getDynRel(uint32_t Type) const { return Type; }
virtual void writeGotPltHeader(uint8_t *Buf) const {}
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 3de2596af27c..7f00e37ce7b0 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -62,7 +62,6 @@ private:
void assignFileOffsets();
void assignFileOffsetsBinary();
void setPhdrs();
- void fixHeaders();
void fixSectionAlignments();
void fixPredefinedSymbols();
void openFile();
@@ -86,7 +85,6 @@ private:
uint64_t FileSize;
uint64_t SectionHeaderOff;
- bool AllocateHeader = true;
};
} // anonymous namespace
@@ -252,7 +250,7 @@ template <class ELFT> void Writer<ELFT>::run() {
} else {
if (!Script->Opt.HasSections) {
fixSectionAlignments();
- Script->fabricateDefaultCommands(AllocateHeader);
+ Script->fabricateDefaultCommands();
}
Script->synchronize();
Script->assignAddresses(Phdrs);
@@ -747,15 +745,12 @@ static bool compareSectionsNonScript(const OutputSection *A,
// Output section ordering is determined by this function.
template <class ELFT>
static bool compareSections(const OutputSection *A, const OutputSection *B) {
- // For now, put sections mentioned in a linker script first.
- int AIndex = Script->getSectionIndex(A->Name);
- int BIndex = Script->getSectionIndex(B->Name);
- bool AInScript = AIndex != INT_MAX;
- bool BInScript = BIndex != INT_MAX;
- if (AInScript != BInScript)
- return AInScript;
- // If both are in the script, use that order.
- if (AInScript)
+ // For now, put sections mentioned in a linker script
+ // first. Sections not on linker script will have a SectionIndex of
+ // INT_MAX.
+ int AIndex = A->SectionIndex;
+ int BIndex = B->SectionIndex;
+ if (AIndex != BIndex)
return AIndex < BIndex;
return compareSectionsNonScript<ELFT>(A, B);
@@ -1021,9 +1016,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
auto I = OutputSections.begin();
auto E = OutputSections.end();
auto NonScriptI =
- std::find_if(OutputSections.begin(), E, [](OutputSection *S) {
- return Script->getSectionIndex(S->Name) == INT_MAX;
- });
+ std::find_if(OutputSections.begin(), E,
+ [](OutputSection *S) { return S->SectionIndex == INT_MAX; });
while (NonScriptI != E) {
auto BestPos = std::max_element(
I, NonScriptI, [&](OutputSection *&A, OutputSection *&B) {
@@ -1176,7 +1170,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!Config->Relocatable && !Config->OFormatBinary) {
Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs();
addPtArmExid(Phdrs);
- fixHeaders();
+ Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
}
// Dynamic section must be the last one in this list and dynamic
@@ -1321,6 +1315,11 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
// Add the first PT_LOAD segment for regular output sections.
uint64_t Flags = computeFlags(PF_R);
PhdrEntry *Load = AddHdr(PT_LOAD, Flags);
+
+ // Add the headers. We will remove them if they don't fit.
+ Load->add(Out::ElfHeader);
+ Load->add(Out::ProgramHeaders);
+
for (OutputSection *Sec : OutputSections) {
if (!(Sec->Flags & SHF_ALLOC))
break;
@@ -1447,64 +1446,6 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
}
}
-bool elf::allocateHeaders(std::vector<PhdrEntry> &Phdrs,
- ArrayRef<OutputSection *> OutputSections,
- uint64_t Min) {
- auto FirstPTLoad =
- std::find_if(Phdrs.begin(), Phdrs.end(),
- [](const PhdrEntry &E) { return E.p_type == PT_LOAD; });
- if (FirstPTLoad == Phdrs.end())
- return false;
-
- uint64_t HeaderSize = getHeaderSize();
- if (HeaderSize > Min) {
- auto PhdrI =
- std::find_if(Phdrs.begin(), Phdrs.end(),
- [](const PhdrEntry &E) { return E.p_type == PT_PHDR; });
- if (PhdrI != Phdrs.end())
- Phdrs.erase(PhdrI);
- return false;
- }
- Min = alignDown(Min - HeaderSize, Config->MaxPageSize);
-
- if (!Script->Opt.HasSections)
- Config->ImageBase = Min = std::min(Min, Config->ImageBase);
-
- Out::ElfHeader->Addr = Min;
- Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size;
-
- if (Script->hasPhdrsCommands())
- return true;
-
- if (FirstPTLoad->First)
- for (OutputSection *Sec : OutputSections)
- if (Sec->FirstInPtLoad == FirstPTLoad->First)
- Sec->FirstInPtLoad = Out::ElfHeader;
- FirstPTLoad->First = Out::ElfHeader;
- if (!FirstPTLoad->Last)
- FirstPTLoad->Last = Out::ProgramHeaders;
- return true;
-}
-
-// We should set file offsets and VAs for elf header and program headers
-// sections. These are special, we do not include them into output sections
-// list, but have them to simplify the code.
-template <class ELFT> void Writer<ELFT>::fixHeaders() {
- Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
- // If the script has SECTIONS, assignAddresses will compute the values.
- if (Script->Opt.HasSections)
- return;
-
- // When -T<section> option is specified, lower the base to make room for those
- // sections.
- uint64_t Min = -1;
- if (!Config->SectionStartMap.empty())
- for (const auto &P : Config->SectionStartMap)
- Min = std::min(Min, P.second);
-
- AllocateHeader = allocateHeaders(Phdrs, OutputSections, Min);
-}
-
// Adjusts the file alignment for a given output section and returns
// its new file offset. The file offset must be the same with its
// virtual address (modulo the page size) so that the loader can load
diff --git a/ELF/Writer.h b/ELF/Writer.h
index a669e42ef205..8b965f7beddb 100644
--- a/ELF/Writer.h
+++ b/ELF/Writer.h
@@ -49,9 +49,6 @@ struct PhdrEntry {
llvm::StringRef getOutputSectionName(llvm::StringRef Name);
-bool allocateHeaders(std::vector<PhdrEntry> &, llvm::ArrayRef<OutputSection *>,
- uint64_t Min);
-
template <class ELFT> uint32_t getMipsEFlags();
uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,