svn commit: r319148 - in vendor/lld/dist: COFF ELF test/COFF test/COFF/Inputs test/ELF test/ELF/Inputs test/ELF/linkerscript test/ELF/lto test/ELF/lto/Inputs
Dimitry Andric
dim at FreeBSD.org
Mon May 29 16:26:24 UTC 2017
Author: dim
Date: Mon May 29 16:26:20 2017
New Revision: 319148
URL: https://svnweb.freebsd.org/changeset/base/319148
Log:
Vendor import of lld trunk r304149:
https://llvm.org/svn/llvm-project/lld/trunk@304149
Added:
vendor/lld/dist/test/COFF/Inputs/delayimports-error.yaml
vendor/lld/dist/test/COFF/Inputs/oldname.yaml
vendor/lld/dist/test/COFF/delayimports-error.test
vendor/lld/dist/test/COFF/dllimport-gc.test
vendor/lld/dist/test/ELF/Inputs/rodynamic.s (contents, props changed)
vendor/lld/dist/test/ELF/gdb-index-dup-types.s (contents, props changed)
vendor/lld/dist/test/ELF/linkerscript/arm-lscript.s (contents, props changed)
vendor/lld/dist/test/ELF/lto/Inputs/relocation-model-pic.ll
vendor/lld/dist/test/ELF/lto/relocation-model.ll
vendor/lld/dist/test/ELF/relocatable-comdat.s (contents, props changed)
vendor/lld/dist/test/ELF/rodynamic.s (contents, props changed)
Modified:
vendor/lld/dist/COFF/ICF.cpp
vendor/lld/dist/COFF/InputFiles.cpp
vendor/lld/dist/COFF/InputFiles.h
vendor/lld/dist/COFF/MarkLive.cpp
vendor/lld/dist/COFF/PDB.cpp
vendor/lld/dist/COFF/Symbols.cpp
vendor/lld/dist/COFF/Symbols.h
vendor/lld/dist/COFF/Writer.cpp
vendor/lld/dist/ELF/Config.h
vendor/lld/dist/ELF/Driver.cpp
vendor/lld/dist/ELF/ICF.cpp
vendor/lld/dist/ELF/InputFiles.cpp
vendor/lld/dist/ELF/InputSection.cpp
vendor/lld/dist/ELF/InputSection.h
vendor/lld/dist/ELF/LTO.cpp
vendor/lld/dist/ELF/LinkerScript.cpp
vendor/lld/dist/ELF/LinkerScript.h
vendor/lld/dist/ELF/MapFile.cpp
vendor/lld/dist/ELF/Options.td
vendor/lld/dist/ELF/OutputSections.cpp
vendor/lld/dist/ELF/OutputSections.h
vendor/lld/dist/ELF/SyntheticSections.cpp
vendor/lld/dist/ELF/SyntheticSections.h
vendor/lld/dist/ELF/Writer.cpp
vendor/lld/dist/ELF/Writer.h
vendor/lld/dist/test/COFF/Inputs/import.yaml
vendor/lld/dist/test/ELF/amdgpu-globals.s
vendor/lld/dist/test/ELF/build-id.s
vendor/lld/dist/test/ELF/gc-sections.s
vendor/lld/dist/test/ELF/i386-tls-ie-shared.s
vendor/lld/dist/test/ELF/linkerscript/sections-constraint.s
vendor/lld/dist/test/ELF/relocation-size-shared.s
vendor/lld/dist/test/ELF/relocation-size.s
vendor/lld/dist/test/ELF/reproduce.s
vendor/lld/dist/test/ELF/section-layout.s
vendor/lld/dist/test/ELF/tls-i686.s
Modified: vendor/lld/dist/COFF/ICF.cpp
==============================================================================
--- vendor/lld/dist/COFF/ICF.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/ICF.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -56,7 +56,6 @@ private:
std::vector<SectionChunk *> Chunks;
int Cnt = 0;
- std::atomic<uint32_t> NextId = {1};
std::atomic<bool> Repeat = {false};
};
@@ -98,10 +97,10 @@ void ICF::segregate(size_t Begin, size_t
});
size_t Mid = Bound - Chunks.begin();
- // Split [Begin, End) into [Begin, Mid) and [Mid, End).
- uint32_t Id = NextId++;
+ // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an
+ // equivalence class ID because every group ends with a unique index.
for (size_t I = Begin; I < Mid; ++I)
- Chunks[I]->Class[(Cnt + 1) % 2] = Id;
+ Chunks[I]->Class[(Cnt + 1) % 2] = Mid;
// If we created a group, we need to iterate the main loop again.
if (Mid != End)
@@ -186,6 +185,7 @@ void ICF::forEachClass(std::function<voi
// call Fn sequentially.
if (Chunks.size() < 1024) {
forEachClassRange(0, Chunks.size(), Fn);
+ ++Cnt;
return;
}
@@ -193,9 +193,10 @@ void ICF::forEachClass(std::function<voi
size_t NumShards = 256;
size_t Step = Chunks.size() / NumShards;
for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
- forEachClassRange(I * Step, (I + 1) * Step, Fn);
+ size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
+ forEachClassRange(I * Step, End, Fn);
});
- forEachClassRange(Step * NumShards, Chunks.size(), Fn);
+ ++Cnt;
}
// Merge identical COMDAT sections.
@@ -203,22 +204,20 @@ void ICF::forEachClass(std::function<voi
// contents and relocations are all the same.
void ICF::run(const std::vector<Chunk *> &Vec) {
// Collect only mergeable sections and group by hash value.
+ uint32_t NextId = 1;
for (Chunk *C : Vec) {
- auto *SC = dyn_cast<SectionChunk>(C);
- if (!SC)
- continue;
-
- if (isEligible(SC)) {
- // Set MSB to 1 to avoid collisions with non-hash classs.
- SC->Class[0] = getHash(SC) | (1 << 31);
- Chunks.push_back(SC);
- } else {
- SC->Class[0] = NextId++;
+ if (auto *SC = dyn_cast<SectionChunk>(C)) {
+ if (isEligible(SC))
+ Chunks.push_back(SC);
+ else
+ SC->Class[0] = NextId++;
}
}
- if (Chunks.empty())
- return;
+ // Initially, we use hash values to partition sections.
+ for (SectionChunk *SC : Chunks)
+ // Set MSB to 1 to avoid collisions with non-hash classs.
+ SC->Class[0] = getHash(SC) | (1 << 31);
// From now on, sections in Chunks are ordered so that sections in
// the same group are consecutive in the vector.
@@ -229,14 +228,12 @@ void ICF::run(const std::vector<Chunk *>
// Compare static contents and assign unique IDs for each static content.
forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); });
- ++Cnt;
// Split groups by comparing relocations until convergence is obtained.
do {
Repeat = false;
forEachClass(
[&](size_t Begin, size_t End) { segregate(Begin, End, false); });
- ++Cnt;
} while (Repeat);
log("ICF needed " + Twine(Cnt) + " iterations");
Modified: vendor/lld/dist/COFF/InputFiles.cpp
==============================================================================
--- vendor/lld/dist/COFF/InputFiles.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/InputFiles.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -48,13 +48,11 @@ namespace coff {
/// alias to Target.
static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F,
SymbolBody *Source, SymbolBody *Target) {
- auto *U = dyn_cast<Undefined>(Source);
- if (!U)
- return;
- else if (!U->WeakAlias)
+ if (auto *U = dyn_cast<Undefined>(Source)) {
+ if (U->WeakAlias && U->WeakAlias != Target)
+ Symtab->reportDuplicate(Source->symbol(), F);
U->WeakAlias = Target;
- else if (U->WeakAlias != Target)
- Symtab->reportDuplicate(Source->symbol(), F);
+ }
}
ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
@@ -153,8 +151,10 @@ void ObjectFile::initializeSymbols() {
uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
SymbolBodies.reserve(NumSymbols);
SparseSymbolBodies.resize(NumSymbols);
+
SmallVector<std::pair<SymbolBody *, uint32_t>, 8> WeakAliases;
int32_t LastSectionNumber = 0;
+
for (uint32_t I = 0; I < NumSymbols; ++I) {
// Get a COFFSymbolRef object.
ErrorOr<COFFSymbolRef> SymOrErr = COFFObj->getSymbol(I);
@@ -185,9 +185,12 @@ void ObjectFile::initializeSymbols() {
I += Sym.getNumberOfAuxSymbols();
LastSectionNumber = Sym.getSectionNumber();
}
- for (auto WeakAlias : WeakAliases)
- checkAndSetWeakAlias(Symtab, this, WeakAlias.first,
- SparseSymbolBodies[WeakAlias.second]);
+
+ for (auto &KV : WeakAliases) {
+ SymbolBody *Sym = KV.first;
+ uint32_t Idx = KV.second;
+ checkAndSetWeakAlias(Symtab, this, Sym, SparseSymbolBodies[Idx]);
+ }
}
SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) {
Modified: vendor/lld/dist/COFF/InputFiles.h
==============================================================================
--- vendor/lld/dist/COFF/InputFiles.h Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/InputFiles.h Mon May 29 16:26:20 2017 (r319148)
@@ -10,6 +10,7 @@
#ifndef LLD_COFF_INPUT_FILES_H
#define LLD_COFF_INPUT_FILES_H
+#include "Config.h"
#include "lld/Core/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
@@ -161,7 +162,9 @@ private:
// for details about the format.
class ImportFile : public InputFile {
public:
- explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M) {}
+ explicit ImportFile(MemoryBufferRef M)
+ : InputFile(ImportKind, M), Live(!Config->DoGC) {}
+
static bool classof(const InputFile *F) { return F->kind() == ImportKind; }
DefinedImportData *ImpSym = nullptr;
@@ -176,6 +179,14 @@ public:
StringRef ExternalName;
const coff_import_header *Hdr;
Chunk *Location = nullptr;
+
+ // We want to eliminate dllimported symbols if no one actually refers them.
+ // This "Live" bit is used to keep track of which import library members
+ // are actually in use.
+ //
+ // If the Live bit is turned off by MarkLive, Writer will ignore dllimported
+ // symbols provided by this import library member.
+ bool Live;
};
// Used for LTO.
Modified: vendor/lld/dist/COFF/MarkLive.cpp
==============================================================================
--- vendor/lld/dist/COFF/MarkLive.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/MarkLive.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -37,19 +37,26 @@ void markLive(const std::vector<Chunk *>
Worklist.push_back(C);
};
+ auto AddSym = [&](SymbolBody *B) {
+ if (auto *Sym = dyn_cast<DefinedRegular>(B))
+ Enqueue(Sym->getChunk());
+ else if (auto *Sym = dyn_cast<DefinedImportData>(B))
+ Sym->File->Live = true;
+ else if (auto *Sym = dyn_cast<DefinedImportThunk>(B))
+ Sym->WrappedSym->File->Live = true;
+ };
+
// Add GC root chunks.
for (SymbolBody *B : Config->GCRoot)
- if (auto *D = dyn_cast<DefinedRegular>(B))
- Enqueue(D->getChunk());
+ AddSym(B);
while (!Worklist.empty()) {
SectionChunk *SC = Worklist.pop_back_val();
assert(SC->isLive() && "We mark as live when pushing onto the worklist!");
// Mark all symbols listed in the relocation table for this section.
- for (SymbolBody *S : SC->symbols())
- if (auto *D = dyn_cast<DefinedRegular>(S))
- Enqueue(D->getChunk());
+ for (SymbolBody *B : SC->symbols())
+ AddSym(B);
// Mark associative sections if any.
for (SectionChunk *C : SC->children())
Modified: vendor/lld/dist/COFF/PDB.cpp
==============================================================================
--- vendor/lld/dist/COFF/PDB.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/PDB.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -99,6 +99,12 @@ static void addTypeInfo(pdb::TpiStreamBu
static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
codeview::TypeTableBuilder &TypeTable,
codeview::TypeTableBuilder &IDTable) {
+ // Follow type servers. If the same type server is encountered more than
+ // once for this instance of `PDBTypeServerHandler` (for example if many
+ // object files reference the same TypeServer), the types from the
+ // TypeServer will only be visited once.
+ pdb::PDBTypeServerHandler Handler;
+
// Visit all .debug$T sections to add them to Builder.
for (ObjectFile *File : Symtab->ObjectFiles) {
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
@@ -109,16 +115,11 @@ static void mergeDebugT(SymbolTable *Sym
codeview::CVTypeArray Types;
BinaryStreamReader Reader(Stream);
SmallVector<TypeIndex, 128> SourceToDest;
- // Follow type servers. If the same type server is encountered more than
- // once for this instance of `PDBTypeServerHandler` (for example if many
- // object files reference the same TypeServer), the types from the
- // TypeServer will only be visited once.
- pdb::PDBTypeServerHandler Handler;
Handler.addSearchPath(llvm::sys::path::parent_path(File->getName()));
if (auto EC = Reader.readArray(Types, Reader.getLength()))
fatal(EC, "Reader::readArray failed");
- if (auto Err = codeview::mergeTypeStreams(IDTable, TypeTable, SourceToDest,
- &Handler, Types))
+ if (auto Err = codeview::mergeTypeAndIdRecords(
+ IDTable, TypeTable, SourceToDest, &Handler, Types))
fatal(Err, "codeview::mergeTypeStreams failed");
}
Modified: vendor/lld/dist/COFF/Symbols.cpp
==============================================================================
--- vendor/lld/dist/COFF/Symbols.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/Symbols.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -61,16 +61,19 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol
return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
}
+static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {
+ if (Machine == AMD64)
+ return make<ImportThunkChunkX64>(S);
+ if (Machine == I386)
+ return make<ImportThunkChunkX86>(S);
+ assert(Machine == ARMNT);
+ return make<ImportThunkChunkARM>(S);
+}
+
DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,
uint16_t Machine)
- : Defined(DefinedImportThunkKind, Name) {
- switch (Machine) {
- case AMD64: Data = make<ImportThunkChunkX64>(S); return;
- case I386: Data = make<ImportThunkChunkX86>(S); return;
- case ARMNT: Data = make<ImportThunkChunkARM>(S); return;
- default: llvm_unreachable("unknown machine type");
- }
-}
+ : Defined(DefinedImportThunkKind, Name), WrappedSym(S),
+ Data(makeImportThunk(S, Machine)) {}
Defined *Undefined::getWeakAlias() {
// A weak alias may be a weak alias to another symbol, so check recursively.
Modified: vendor/lld/dist/COFF/Symbols.h
==============================================================================
--- vendor/lld/dist/COFF/Symbols.h Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/Symbols.h Mon May 29 16:26:20 2017 (r319148)
@@ -300,7 +300,6 @@ public:
void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
-private:
ImportFile *File;
};
@@ -320,6 +319,8 @@ public:
uint64_t getRVA() { return Data->getRVA(); }
Chunk *getChunk() { return Data; }
+ DefinedImportData *WrappedSym;
+
private:
Chunk *Data;
};
Modified: vendor/lld/dist/COFF/Writer.cpp
==============================================================================
--- vendor/lld/dist/COFF/Writer.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/COFF/Writer.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -365,6 +365,9 @@ void Writer::createImportTables() {
// the same order as in the command line. (That affects DLL
// initialization order, and this ordering is MSVC-compatible.)
for (ImportFile *File : Symtab->ImportFiles) {
+ if (!File->Live)
+ continue;
+
std::string DLL = StringRef(File->DLLName).lower();
if (Config->DLLOrder.count(DLL) == 0)
Config->DLLOrder[DLL] = Config->DLLOrder.size();
@@ -372,19 +375,28 @@ void Writer::createImportTables() {
OutputSection *Text = createSection(".text");
for (ImportFile *File : Symtab->ImportFiles) {
+ if (!File->Live)
+ continue;
+
if (DefinedImportThunk *Thunk = File->ThunkSym)
Text->addChunk(Thunk->getChunk());
+
if (Config->DelayLoads.count(StringRef(File->DLLName).lower())) {
+ if (!File->ThunkSym)
+ fatal("cannot delay-load " + toString(File) +
+ " due to import of data: " + toString(*File->ImpSym));
DelayIdata.add(File->ImpSym);
} else {
Idata.add(File->ImpSym);
}
}
+
if (!Idata.empty()) {
OutputSection *Sec = createSection(".idata");
for (Chunk *C : Idata.getChunks())
Sec->addChunk(C);
}
+
if (!DelayIdata.empty()) {
Defined *Helper = cast<Defined>(Config->DelayLoadHelper);
DelayIdata.create(Helper);
@@ -437,6 +449,14 @@ Optional<coff_symbol16> Writer::createSy
if (!D->getChunk()->isLive())
return None;
+ if (auto *Sym = dyn_cast<DefinedImportData>(Def))
+ if (!Sym->File->Live)
+ return None;
+
+ if (auto *Sym = dyn_cast<DefinedImportThunk>(Def))
+ if (!Sym->WrappedSym->File->Live)
+ return None;
+
coff_symbol16 Sym;
StringRef Name = Def->getName();
if (Name.size() > COFF::NameSize) {
@@ -491,14 +511,17 @@ void Writer::createSymbolAndStringTable(
Sec->setStringTableOff(addEntryToStringTable(Name));
}
- for (lld::coff::ObjectFile *File : Symtab->ObjectFiles)
- for (SymbolBody *B : File->getSymbols())
- if (auto *D = dyn_cast<Defined>(B))
- if (!D->WrittenToSymtab) {
- D->WrittenToSymtab = true;
- if (Optional<coff_symbol16> Sym = createSymbol(D))
- OutputSymtab.push_back(*Sym);
- }
+ for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) {
+ for (SymbolBody *B : File->getSymbols()) {
+ auto *D = dyn_cast<Defined>(B);
+ if (!D || D->WrittenToSymtab)
+ continue;
+ D->WrittenToSymtab = true;
+
+ if (Optional<coff_symbol16> Sym = createSymbol(D))
+ OutputSymtab.push_back(*Sym);
+ }
+ }
OutputSection *LastSection = OutputSections.back();
// We position the symbol table to be adjacent to the end of the last section.
@@ -782,19 +805,15 @@ void Writer::writeBuildId() {
if (BuildId == nullptr)
return;
- MD5 Hash;
- MD5::MD5Result Res;
-
- Hash.update(ArrayRef<uint8_t>{Buffer->getBufferStart(),
- Buffer->getBufferEnd()});
- Hash.final(Res);
-
assert(BuildId->DI->Signature.CVSignature == OMF::Signature::PDB70 &&
"only PDB 7.0 is supported");
- assert(sizeof(Res) == sizeof(BuildId->DI->PDB70.Signature) &&
+ assert(sizeof(BuildId->DI->PDB70.Signature) == 16 &&
"signature size mismatch");
- memcpy(BuildId->DI->PDB70.Signature, Res.Bytes.data(),
- sizeof(codeview::PDB70DebugInfo::Signature));
+
+ // Compute an MD5 hash.
+ ArrayRef<uint8_t> Buf(Buffer->getBufferStart(), Buffer->getBufferEnd());
+ memcpy(BuildId->DI->PDB70.Signature, MD5::hash(Buf).data(), 16);
+
// TODO(compnerd) track the Age
BuildId->DI->PDB70.Age = 1;
}
Modified: vendor/lld/dist/ELF/Config.h
==============================================================================
--- vendor/lld/dist/ELF/Config.h Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/Config.h Mon May 29 16:26:20 2017 (r319148)
@@ -145,6 +145,7 @@ struct Configuration {
bool ZNow;
bool ZOrigin;
bool ZRelro;
+ bool ZRodynamic;
bool ZText;
bool ExitEarly;
bool ZWxneeded;
Modified: vendor/lld/dist/ELF/Driver.cpp
==============================================================================
--- vendor/lld/dist/ELF/Driver.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/Driver.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -572,10 +572,14 @@ static std::pair<bool, bool> getHashStyl
// -build-id=sha1 are actually tree hashes for performance reasons.
static std::pair<BuildIdKind, std::vector<uint8_t>>
getBuildId(opt::InputArgList &Args) {
- if (Args.hasArg(OPT_build_id))
+ auto *Arg = Args.getLastArg(OPT_build_id, OPT_build_id_eq);
+ if (!Arg)
+ return {BuildIdKind::None, {}};
+
+ if (Arg->getOption().getID() == OPT_build_id)
return {BuildIdKind::Fast, {}};
- StringRef S = getString(Args, OPT_build_id_eq, "none");
+ StringRef S = Arg->getValue();
if (S == "md5")
return {BuildIdKind::Md5, {}};
if (S == "sha1" || S == "tree")
@@ -688,6 +692,7 @@ void LinkerDriver::readConfigs(opt::Inpu
Config->ZNow = hasZOption(Args, "now");
Config->ZOrigin = hasZOption(Args, "origin");
Config->ZRelro = !hasZOption(Args, "norelro");
+ Config->ZRodynamic = hasZOption(Args, "rodynamic");
Config->ZStackSize = getZOptionValue(Args, "stack-size", 0);
Config->ZText = !hasZOption(Args, "notext");
Config->ZWxneeded = hasZOption(Args, "wxneeded");
Modified: vendor/lld/dist/ELF/ICF.cpp
==============================================================================
--- vendor/lld/dist/ELF/ICF.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/ICF.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -326,9 +326,9 @@ void ICF<ELFT>::forEachClass(std::functi
size_t NumShards = 256;
size_t Step = Sections.size() / NumShards;
parallelForEachN(0, NumShards, [&](size_t I) {
- forEachClassRange(I * Step, (I + 1) * Step, Fn);
+ size_t End = (I == NumShards - 1) ? Sections.size() : (I + 1) * Step;
+ forEachClassRange(I * Step, End, Fn);
});
- forEachClassRange(Step * NumShards, Sections.size(), Fn);
++Cnt;
}
Modified: vendor/lld/dist/ELF/InputFiles.cpp
==============================================================================
--- vendor/lld/dist/ELF/InputFiles.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/InputFiles.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -281,18 +281,20 @@ bool elf::ObjectFile<ELFT>::shouldMerge(
template <class ELFT>
void elf::ObjectFile<ELFT>::initializeSections(
DenseSet<CachedHashStringRef> &ComdatGroups) {
+ const ELFFile<ELFT> &Obj = this->getObj();
+
ArrayRef<Elf_Shdr> ObjSections =
check(this->getObj().sections(), toString(this));
- const ELFFile<ELFT> &Obj = this->getObj();
uint64_t Size = ObjSections.size();
this->Sections.resize(Size);
- unsigned I = -1;
+
StringRef SectionStringTable =
check(Obj.getSectionStringTable(ObjSections), toString(this));
- for (const Elf_Shdr &Sec : ObjSections) {
- ++I;
+
+ for (size_t I = 0, E = ObjSections.size(); I < E; I++) {
if (this->Sections[I] == &InputSection::Discarded)
continue;
+ const Elf_Shdr &Sec = ObjSections[I];
// SHF_EXCLUDE'ed sections are discarded by the linker. However,
// if -r is given, we'll let the final link discard such sections.
@@ -303,13 +305,22 @@ void elf::ObjectFile<ELFT>::initializeSe
}
switch (Sec.sh_type) {
- case SHT_GROUP:
- this->Sections[I] = &InputSection::Discarded;
- if (ComdatGroups
- .insert(
- CachedHashStringRef(getShtGroupSignature(ObjSections, Sec)))
- .second)
+ case SHT_GROUP: {
+ // We discard comdat sections usually. When -r we should not do that. We
+ // still do deduplication in this case to simplify implementation, because
+ // otherwise merging group sections together would requre additional
+ // regeneration of its contents.
+ bool New = ComdatGroups
+ .insert(CachedHashStringRef(
+ getShtGroupSignature(ObjSections, Sec)))
+ .second;
+ if (New && Config->Relocatable)
+ this->Sections[I] = createInputSection(Sec, SectionStringTable);
+ else
+ this->Sections[I] = &InputSection::Discarded;
+ if (New)
continue;
+
for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
if (SecIndex >= Size)
fatal(toString(this) +
@@ -317,6 +328,7 @@ void elf::ObjectFile<ELFT>::initializeSe
this->Sections[SecIndex] = &InputSection::Discarded;
}
break;
+ }
case SHT_SYMTAB:
this->initSymtab(ObjSections, &Sec);
break;
Modified: vendor/lld/dist/ELF/InputSection.cpp
==============================================================================
--- vendor/lld/dist/ELF/InputSection.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/InputSection.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -23,6 +23,7 @@
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Threading.h"
#include <mutex>
using namespace llvm;
@@ -172,7 +173,8 @@ void InputSectionBase::uncompress() {
if (Error E = Dec.decompress({OutputBuf, Size}))
fatal(toString(this) +
": decompress failed: " + llvm::toString(std::move(E)));
- Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size);
+ this->Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size);
+ this->Flags &= ~(uint64_t)SHF_COMPRESSED;
}
uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const {
@@ -293,6 +295,24 @@ bool InputSectionBase::classof(const Sec
return S->kind() != Output;
}
+void InputSection::copyShtGroup(uint8_t *Buf) {
+ assert(this->Type == SHT_GROUP);
+
+ ArrayRef<uint32_t> From = getDataAs<uint32_t>();
+ uint32_t *To = reinterpret_cast<uint32_t *>(Buf);
+
+ // First entry is a flag word, we leave it unchanged.
+ *To++ = From[0];
+
+ // Here we adjust indices of sections that belong to group as it
+ // might change during linking.
+ ArrayRef<InputSectionBase *> Sections = this->File->getSections();
+ for (uint32_t Val : From.slice(1)) {
+ uint32_t Index = read32(&Val, Config->Endianness);
+ write32(To++, Sections[Index]->OutSec->SectionIndex, Config->Endianness);
+ }
+}
+
InputSectionBase *InputSection::getRelocatedSection() {
assert(this->Type == SHT_RELA || this->Type == SHT_REL);
ArrayRef<InputSectionBase *> Sections = this->File->getSections();
@@ -678,6 +698,13 @@ template <class ELFT> void InputSection:
return;
}
+ // If -r is given, linker should keep SHT_GROUP sections. We should fixup
+ // them, see copyShtGroup().
+ if (this->Type == SHT_GROUP) {
+ copyShtGroup(Buf + OutSecOff);
+ return;
+ }
+
// Copy section contents from source object file to output file
// and then apply relocations.
memcpy(Buf + OutSecOff, Data.data(), Data.size());
@@ -866,7 +893,7 @@ const SectionPiece *MergeInputSection::g
// it is not just an addition to a base output offset.
uint64_t MergeInputSection::getOffset(uint64_t Offset) const {
// Initialize OffsetMap lazily.
- std::call_once(InitOffsetMap, [&] {
+ llvm::call_once(InitOffsetMap, [&] {
OffsetMap.reserve(Pieces.size());
for (const SectionPiece &Piece : Pieces)
OffsetMap[Piece.InputOff] = Piece.OutputOff;
Modified: vendor/lld/dist/ELF/InputSection.h
==============================================================================
--- vendor/lld/dist/ELF/InputSection.h Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/InputSection.h Mon May 29 16:26:20 2017 (r319148)
@@ -18,6 +18,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Support/Threading.h"
#include <mutex>
namespace lld {
@@ -248,7 +249,7 @@ private:
std::vector<uint32_t> Hashes;
mutable llvm::DenseMap<uint64_t, uint64_t> OffsetMap;
- mutable std::once_flag InitOffsetMap;
+ mutable llvm::once_flag InitOffsetMap;
llvm::DenseSet<uint64_t> LiveOffsets;
};
@@ -318,6 +319,8 @@ public:
private:
template <class ELFT, class RelTy>
void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
+
+ void copyShtGroup(uint8_t *Buf);
};
// The list of all input sections.
Modified: vendor/lld/dist/ELF/LTO.cpp
==============================================================================
--- vendor/lld/dist/ELF/LTO.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/LTO.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -73,7 +73,12 @@ static std::unique_ptr<lto::LTO> createL
Conf.Options = InitTargetOptionsFromCodeGenFlags();
Conf.Options.RelaxELFRelocations = true;
- Conf.RelocModel = Config->Pic ? Reloc::PIC_ : Reloc::Static;
+ if (Config->Relocatable)
+ Conf.RelocModel = None;
+ else if (Config->Pic)
+ Conf.RelocModel = Reloc::PIC_;
+ else
+ Conf.RelocModel = Reloc::Static;
Conf.CodeModel = GetCodeModelFromCMModel();
Conf.DisableVerify = Config->DisableVerify;
Conf.DiagHandler = diagnosticHandler;
Modified: vendor/lld/dist/ELF/LinkerScript.cpp
==============================================================================
--- vendor/lld/dist/ELF/LinkerScript.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/LinkerScript.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -20,6 +20,8 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
+#include "Target.h"
+#include "Threads.h"
#include "Writer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -198,6 +200,15 @@ bool OutputSectionCommand::classof(const
return C->Kind == OutputSectionKind;
}
+// Fill [Buf, Buf + Size) with Filler.
+// This is used for linker script "=fillexp" command.
+static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
+ size_t I = 0;
+ for (; I + 4 < Size; I += 4)
+ memcpy(Buf + I, &Filler, 4);
+ memcpy(Buf + I, &Filler, Size - I);
+}
+
bool InputSectionDescription::classof(const BaseCommand *C) {
return C->Kind == InputSectionKind;
}
@@ -263,16 +274,16 @@ static bool matchConstraints(ArrayRef<In
(!IsRW && Kind == ConstraintKind::ReadOnly);
}
-static void sortSections(InputSectionBase **Begin, InputSectionBase **End,
+static void sortSections(InputSection **Begin, InputSection **End,
SortSectionPolicy K) {
if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None)
std::stable_sort(Begin, End, getComparator(K));
}
// Compute and remember which sections the InputSectionDescription matches.
-std::vector<InputSectionBase *>
+std::vector<InputSection *>
LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {
- std::vector<InputSectionBase *> Ret;
+ std::vector<InputSection *> Ret;
// Collects all sections that satisfy constraints of Cmd.
for (const SectionPattern &Pat : Cmd->SectionPatterns) {
@@ -294,7 +305,7 @@ LinkerScript::computeInputSections(const
!Pat.SectionPat.match(Sec->Name))
continue;
- Ret.push_back(Sec);
+ Ret.push_back(cast<InputSection>(Sec));
Sec->Assigned = true;
}
@@ -309,8 +320,8 @@ LinkerScript::computeInputSections(const
// --sort-section is handled as an inner SORT command.
// 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
// 4. If no SORT command is given, sort according to --sort-section.
- InputSectionBase **Begin = Ret.data() + SizeBefore;
- InputSectionBase **End = Ret.data() + Ret.size();
+ InputSection **Begin = Ret.data() + SizeBefore;
+ InputSection **End = Ret.data() + Ret.size();
if (Pat.SortOuter != SortSectionPolicy::None) {
if (Pat.SortInner == SortSectionPolicy::Default)
sortSections(Begin, End, Config->SortSection);
@@ -493,7 +504,7 @@ void LinkerScript::addOrphanSections(Out
Sec->SectionIndex = Index;
}
auto *ISD = make<InputSectionDescription>("");
- ISD->Sections.push_back(S);
+ ISD->Sections.push_back(cast<InputSection>(S));
Cmd->Commands.push_back(ISD);
}
}
@@ -684,7 +695,6 @@ void LinkerScript::adjustSectionsBeforeS
// '.' is assigned to, but creating these section should not have any bad
// consequeces and gives us a section to put the symbol in.
uint64_t Flags = SHF_ALLOC;
- uint32_t Type = SHT_PROGBITS;
for (int I = 0, E = Opt.Commands.size(); I != E; ++I) {
auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]);
@@ -692,14 +702,13 @@ void LinkerScript::adjustSectionsBeforeS
continue;
if (OutputSection *Sec = Cmd->Sec) {
Flags = Sec->Flags;
- Type = Sec->Type;
continue;
}
if (isAllSectionDescription(*Cmd))
continue;
- auto *OutSec = make<OutputSection>(Cmd->Name, Type, Flags);
+ auto *OutSec = make<OutputSection>(Cmd->Name, SHT_PROGBITS, Flags);
OutSec->SectionIndex = I;
OutputSections->push_back(OutSec);
Cmd->Sec = OutSec;
@@ -875,20 +884,20 @@ void LinkerScript::synchronize() {
if (!Cmd)
continue;
ArrayRef<InputSection *> Sections = Cmd->Sec->Sections;
- std::vector<InputSectionBase **> ScriptSections;
- DenseSet<InputSectionBase *> ScriptSectionsSet;
+ std::vector<InputSection **> ScriptSections;
+ DenseSet<InputSection *> ScriptSectionsSet;
for (BaseCommand *Base : Cmd->Commands) {
auto *ISD = dyn_cast<InputSectionDescription>(Base);
if (!ISD)
continue;
- for (InputSectionBase *&IS : ISD->Sections) {
+ for (InputSection *&IS : ISD->Sections) {
if (IS->Live) {
ScriptSections.push_back(&IS);
ScriptSectionsSet.insert(IS);
}
}
}
- std::vector<InputSectionBase *> Missing;
+ std::vector<InputSection *> Missing;
for (InputSection *IS : Sections)
if (!ScriptSectionsSet.count(IS))
Missing.push_back(IS);
@@ -896,7 +905,7 @@ void LinkerScript::synchronize() {
auto ISD = make<InputSectionDescription>("");
ISD->Sections = Missing;
Cmd->Commands.push_back(ISD);
- for (InputSectionBase *&IS : ISD->Sections)
+ for (InputSection *&IS : ISD->Sections)
if (IS->Live)
ScriptSections.push_back(&IS);
}
@@ -1034,10 +1043,12 @@ OutputSectionCommand *LinkerScript::getC
return I->second;
}
-Optional<uint32_t> LinkerScript::getFiller(OutputSection *Sec) {
- if (OutputSectionCommand *Cmd = getCmd(Sec))
- return Cmd->Filler;
- return None;
+uint32_t OutputSectionCommand::getFiller() {
+ if (Filler)
+ return *Filler;
+ if (Sec->Flags & SHF_EXECINSTR)
+ return Target->TrapInstr;
+ return 0;
}
static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
@@ -1053,11 +1064,45 @@ static void writeInt(uint8_t *Buf, uint6
llvm_unreachable("unsupported Size argument");
}
-void LinkerScript::writeDataBytes(OutputSection *Sec, uint8_t *Buf) {
- if (OutputSectionCommand *Cmd = getCmd(Sec))
- for (BaseCommand *Base : Cmd->Commands)
- if (auto *Data = dyn_cast<BytesDataCommand>(Base))
- writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
+template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
+ Sec->Loc = Buf;
+
+ // We may have already rendered compressed content when using
+ // -compress-debug-sections option. Write it together with header.
+ if (!Sec->CompressedData.empty()) {
+ memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size());
+ memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(),
+ Sec->CompressedData.size());
+ return;
+ }
+
+ // Write leading padding.
+ ArrayRef<InputSection *> Sections = Sec->Sections;
+ uint32_t Filler = getFiller();
+ if (Filler)
+ fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler);
+
+ parallelForEachN(0, Sections.size(), [=](size_t I) {
+ InputSection *IS = Sections[I];
+ IS->writeTo<ELFT>(Buf);
+
+ // Fill gaps between sections.
+ if (Filler) {
+ uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
+ uint8_t *End;
+ if (I + 1 == Sections.size())
+ End = Buf + Sec->Size;
+ else
+ End = Buf + Sections[I + 1]->OutSecOff;
+ fill(Start, End - Start, Filler);
+ }
+ });
+
+ // Linker scripts may have BYTE()-family commands with which you
+ // can write arbitrary bytes to the output. Process them if any.
+ for (BaseCommand *Base : Commands)
+ if (auto *Data = dyn_cast<BytesDataCommand>(Base))
+ writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
}
bool LinkerScript::hasLMA(OutputSection *Sec) {
@@ -1104,3 +1149,8 @@ size_t LinkerScript::getPhdrIndex(const
error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");
return 0;
}
+
+template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf);
+template void OutputSectionCommand::writeTo<ELF32BE>(uint8_t *Buf);
+template void OutputSectionCommand::writeTo<ELF64LE>(uint8_t *Buf);
+template void OutputSectionCommand::writeTo<ELF64BE>(uint8_t *Buf);
Modified: vendor/lld/dist/ELF/LinkerScript.h
==============================================================================
--- vendor/lld/dist/ELF/LinkerScript.h Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/LinkerScript.h Mon May 29 16:26:20 2017 (r319148)
@@ -130,6 +130,9 @@ struct OutputSectionCommand : BaseComman
ConstraintKind Constraint = ConstraintKind::NoConstraint;
std::string Location;
std::string MemoryRegionName;
+
+ template <class ELFT> void writeTo(uint8_t *Buf);
+ uint32_t getFiller();
};
// This struct represents one section match pattern in SECTIONS() command.
@@ -157,7 +160,7 @@ struct InputSectionDescription : BaseCom
// will be associated with this InputSectionDescription.
std::vector<SectionPattern> SectionPatterns;
- std::vector<InputSectionBase *> Sections;
+ std::vector<InputSection *> Sections;
};
// Represents an ASSERT().
@@ -213,11 +216,10 @@ struct ScriptConfiguration {
class LinkerScript final {
llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
- OutputSectionCommand *getCmd(OutputSection *Sec) const;
void assignSymbol(SymbolAssignment *Cmd, bool InSec);
void setDot(Expr E, const Twine &Loc, bool InSec);
- std::vector<InputSectionBase *>
+ std::vector<InputSection *>
computeInputSections(const InputSectionDescription *);
std::vector<InputSectionBase *>
@@ -244,6 +246,7 @@ class LinkerScript final {
MemoryRegion *CurMemRegion = nullptr;
public:
+ OutputSectionCommand *getCmd(OutputSection *Sec) const;
bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
uint64_t getDot() { return Dot; }
OutputSection *getOutputSection(const Twine &Loc, StringRef S);
@@ -263,7 +266,6 @@ public:
std::vector<PhdrEntry> createPhdrs();
bool ignoreInterpSection();
- llvm::Optional<uint32_t> getFiller(OutputSection *Sec);
bool hasLMA(OutputSection *Sec);
bool shouldKeep(InputSectionBase *S);
void assignOffsets(OutputSectionCommand *Cmd);
@@ -272,7 +274,6 @@ public:
void synchronize();
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
- void writeDataBytes(OutputSection *Sec, uint8_t *Buf);
void addSymbol(SymbolAssignment *Cmd);
void processCommands(OutputSectionFactory &Factory);
Modified: vendor/lld/dist/ELF/MapFile.cpp
==============================================================================
--- vendor/lld/dist/ELF/MapFile.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/MapFile.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -132,12 +132,17 @@ void elf::writeMapFile(llvm::ArrayRef<Ba
OS << OSec->Name << '\n';
// Dump symbols for each input section.
- for (InputSection *IS : OSec->Sections) {
- writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(),
- IS->Alignment);
- OS << indent(1) << toString(IS) << '\n';
- for (DefinedRegular *Sym : SectionSyms[IS])
- OS << SymStr[Sym] << '\n';
+ for (BaseCommand *Base : Cmd->Commands) {
+ auto *ISD = dyn_cast<InputSectionDescription>(Base);
+ if (!ISD)
+ continue;
+ for (InputSection *IS : ISD->Sections) {
+ writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(),
+ IS->Alignment);
+ OS << indent(1) << toString(IS) << '\n';
+ for (DefinedRegular *Sym : SectionSyms[IS])
+ OS << SymStr[Sym] << '\n';
+ }
}
}
}
Modified: vendor/lld/dist/ELF/Options.td
==============================================================================
--- vendor/lld/dist/ELF/Options.td Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/Options.td Mon May 29 16:26:20 2017 (r319148)
@@ -313,6 +313,7 @@ def alias_o_output2 : Separate<["--"], "
def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>;
def alias_print_map_M: Flag<["-"], "M">, Alias<print_map>;
def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>;
+def alias_reproduce_eq: J<"reproduce=">, Alias<reproduce>;
def alias_retain_symbols_file: S<"retain-symbols-file">, Alias<retain_symbols_file>;
def alias_rpath_R: JoinedOrSeparate<["-"], "R">, Alias<rpath>;
def alias_rpath_rpath: J<"rpath=">, Alias<rpath>;
Modified: vendor/lld/dist/ELF/OutputSections.cpp
==============================================================================
--- vendor/lld/dist/ELF/OutputSections.cpp Mon May 29 16:26:16 2017 (r319147)
+++ vendor/lld/dist/ELF/OutputSections.cpp Mon May 29 16:26:20 2017 (r319148)
@@ -103,7 +103,7 @@ template <class ELFT> void OutputSection
// Write section contents to a temporary buffer and compress it.
std::vector<uint8_t> Buf(Size);
- writeTo<ELFT>(Buf.data());
+ Script->getCmd(this)->writeTo<ELFT>(Buf.data());
if (Error E = zlib::compress(toStringRef(Buf), CompressedData))
fatal("compress failed: " + llvm::toString(std::move(E)));
@@ -112,6 +112,19 @@ template <class ELFT> void OutputSection
Flags |= SHF_COMPRESSED;
}
+template <class ELFT> static void finalizeShtGroup(OutputSection *Sec) {
+ // sh_link field for SHT_GROUP sections should contain the section index of
+ // the symbol table.
+ Sec->Link = InX::SymTab->OutSec->SectionIndex;
+
+ // sh_link then contain index of an entry in symbol table section which
+ // provides signature of the section group.
+ elf::ObjectFile<ELFT> *Obj = Sec->Sections[0]->getFile<ELFT>();
+ assert(Config->Relocatable && Sec->Sections.size() == 1);
+ ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
+ Sec->Info = InX::SymTab->getSymbolIndex(Symbols[Sec->Sections[0]->Info - 1]);
+}
+
template <class ELFT> void OutputSection::finalize() {
if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) {
std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
@@ -126,6 +139,11 @@ template <class ELFT> void OutputSection
}
uint32_t Type = this->Type;
+ if (Type == SHT_GROUP) {
+ finalizeShtGroup<ELFT>(this);
+ return;
+ }
+
if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
return;
@@ -259,69 +277,6 @@ void OutputSection::sortCtorsDtors() {
std::stable_sort(Sections.begin(), Sections.end(), compCtors);
}
-// Fill [Buf, Buf + Size) with Filler.
-// This is used for linker script "=fillexp" command.
-static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
- size_t I = 0;
- for (; I + 4 < Size; I += 4)
- memcpy(Buf + I, &Filler, 4);
- memcpy(Buf + I, &Filler, Size - I);
-}
-
-uint32_t OutputSection::getFiller() {
- // Determine what to fill gaps between InputSections with, as specified by the
- // linker script. If nothing is specified and this is an executable section,
- // fall back to trap instructions to prevent bad diassembly and detect invalid
- // jumps to padding.
- if (Optional<uint32_t> Filler = Script->getFiller(this))
- return *Filler;
- if (Flags & SHF_EXECINSTR)
- return Target->TrapInstr;
- return 0;
-}
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-vendor
mailing list