svn commit: r320965 - in vendor/lld/dist: COFF ELF lib/ReaderWriter/MachO test test/COFF test/COFF/Inputs test/ELF test/ELF/Inputs test/ELF/invalid test/ELF/invalid/Inputs test/ELF/linkerscript tes...
Dimitry Andric
dim at FreeBSD.org
Thu Jul 13 19:26:10 UTC 2017
Author: dim
Date: Thu Jul 13 19:26:06 2017
New Revision: 320965
URL: https://svnweb.freebsd.org/changeset/base/320965
Log:
Vendor import of lld trunk r307894:
https://llvm.org/svn/llvm-project/lld/trunk@307894
Added:
vendor/lld/dist/test/COFF/Inputs/library-arm64.lib (contents, props changed)
vendor/lld/dist/test/COFF/Inputs/pdb-diff-cl.pdb (contents, props changed)
vendor/lld/dist/test/COFF/Inputs/pdb-diff.cpp (contents, props changed)
vendor/lld/dist/test/COFF/Inputs/pdb-diff.obj (contents, props changed)
vendor/lld/dist/test/COFF/Inputs/pdb-scopes-a.yaml
vendor/lld/dist/test/COFF/Inputs/pdb-scopes-b.yaml
vendor/lld/dist/test/COFF/arm64-magic.yaml
vendor/lld/dist/test/COFF/arm64-relocs-imports.test
vendor/lld/dist/test/COFF/pdb-diff.test
vendor/lld/dist/test/COFF/pdb-invalid-func-type.yaml
vendor/lld/dist/test/COFF/pdb-linker-module.test
vendor/lld/dist/test/COFF/pdb-scopes.test
vendor/lld/dist/test/ELF/Inputs/gnu-ifunc-dso.s (contents, props changed)
vendor/lld/dist/test/ELF/Inputs/symver-archive1.s (contents, props changed)
vendor/lld/dist/test/ELF/Inputs/symver-archive2.s (contents, props changed)
vendor/lld/dist/test/ELF/Inputs/version-script-no-warn2.s (contents, props changed)
vendor/lld/dist/test/ELF/Inputs/version-script-weak.s (contents, props changed)
vendor/lld/dist/test/ELF/Inputs/wrap-dynamic-undef.s (contents, props changed)
vendor/lld/dist/test/ELF/duplicated-synthetic-sym.s (contents, props changed)
vendor/lld/dist/test/ELF/gnu-ifunc-dso.s (contents, props changed)
vendor/lld/dist/test/ELF/invalid/invalid-debug-relocations.test
vendor/lld/dist/test/ELF/linkerscript/non-alloc-segment.s (contents, props changed)
vendor/lld/dist/test/ELF/linkerscript/unused-synthetic.s (contents, props changed)
vendor/lld/dist/test/ELF/symver-archive.s (contents, props changed)
vendor/lld/dist/test/ELF/version-script-no-warn2.s (contents, props changed)
vendor/lld/dist/test/ELF/version-script-symver2.s (contents, props changed)
vendor/lld/dist/test/ELF/version-script-undef-version.s (contents, props changed)
vendor/lld/dist/test/ELF/version-script-weak.s (contents, props changed)
vendor/lld/dist/test/ELF/wrap-dynamic-undef.s (contents, props changed)
Deleted:
vendor/lld/dist/test/ELF/invalid/Inputs/invalid-relocation-x64.elf
Modified:
vendor/lld/dist/COFF/Chunks.cpp
vendor/lld/dist/COFF/Chunks.h
vendor/lld/dist/COFF/Config.h
vendor/lld/dist/COFF/Driver.cpp
vendor/lld/dist/COFF/DriverUtils.cpp
vendor/lld/dist/COFF/Error.cpp
vendor/lld/dist/COFF/Error.h
vendor/lld/dist/COFF/InputFiles.cpp
vendor/lld/dist/COFF/PDB.cpp
vendor/lld/dist/COFF/PDB.h
vendor/lld/dist/COFF/Symbols.cpp
vendor/lld/dist/COFF/Writer.cpp
vendor/lld/dist/ELF/Config.h
vendor/lld/dist/ELF/Driver.cpp
vendor/lld/dist/ELF/Error.cpp
vendor/lld/dist/ELF/Error.h
vendor/lld/dist/ELF/Filesystem.cpp
vendor/lld/dist/ELF/GdbIndex.h
vendor/lld/dist/ELF/InputFiles.cpp
vendor/lld/dist/ELF/InputSection.cpp
vendor/lld/dist/ELF/LinkerScript.cpp
vendor/lld/dist/ELF/LinkerScript.h
vendor/lld/dist/ELF/OutputSections.cpp
vendor/lld/dist/ELF/OutputSections.h
vendor/lld/dist/ELF/Relocations.cpp
vendor/lld/dist/ELF/Relocations.h
vendor/lld/dist/ELF/ScriptParser.cpp
vendor/lld/dist/ELF/SymbolTable.cpp
vendor/lld/dist/ELF/Symbols.cpp
vendor/lld/dist/ELF/Symbols.h
vendor/lld/dist/ELF/SyntheticSections.cpp
vendor/lld/dist/ELF/SyntheticSections.h
vendor/lld/dist/ELF/Thunks.cpp
vendor/lld/dist/ELF/Thunks.h
vendor/lld/dist/ELF/Writer.cpp
vendor/lld/dist/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
vendor/lld/dist/test/COFF/combined-resources.test
vendor/lld/dist/test/COFF/pdb-comdat.test
vendor/lld/dist/test/COFF/pdb-lib.s
vendor/lld/dist/test/COFF/pdb-none.test
vendor/lld/dist/test/COFF/pdb-source-lines.test
vendor/lld/dist/test/COFF/pdb-symbol-types.yaml
vendor/lld/dist/test/COFF/pdb.test
vendor/lld/dist/test/ELF/arm-mov-relocs.s
vendor/lld/dist/test/ELF/copy-in-shared.s
vendor/lld/dist/test/ELF/defsym.s
vendor/lld/dist/test/ELF/invalid/invalid-relocation-x64.test
vendor/lld/dist/test/ELF/linkerscript/locationcountererr2.s
vendor/lld/dist/test/ELF/linkerscript/out-of-order.s
vendor/lld/dist/test/ELF/lto/defsym.ll
vendor/lld/dist/test/ELF/lto/wrap-1.ll
vendor/lld/dist/test/ELF/lto/wrap-2.ll
vendor/lld/dist/test/ELF/version-script-symver.s
vendor/lld/dist/test/ELF/wrap.s
vendor/lld/dist/test/lit.cfg
Modified: vendor/lld/dist/COFF/Chunks.cpp
==============================================================================
--- vendor/lld/dist/COFF/Chunks.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Chunks.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -52,6 +52,7 @@ static void add16(uint8_t *P, int16_t V) { write16le(P
static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
+static void or32(uint8_t *P, uint32_t V) { write32le(P, read32le(P) | V); }
static void applySecRel(const SectionChunk *Sec, uint8_t *Off,
OutputSection *OS, uint64_t S) {
@@ -166,6 +167,41 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t
}
}
+static void applyArm64Addr(uint8_t *Off, uint64_t Imm) {
+ uint32_t ImmLo = (Imm & 0x3) << 29;
+ uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;
+ uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);
+ write32le(Off, (read32le(Off) & ~Mask) | ImmLo | ImmHi);
+}
+
+// Update the immediate field in a AARCH64 ldr, str, and add instruction.
+static void applyArm64Imm(uint8_t *Off, uint64_t Imm) {
+ uint32_t Orig = read32le(Off);
+ Imm += (Orig >> 10) & 0xFFF;
+ Orig &= ~(0xFFF << 10);
+ write32le(Off, Orig | ((Imm & 0xFFF) << 10));
+}
+
+static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) {
+ int Size = read32le(Off) >> 30;
+ Imm >>= Size;
+ applyArm64Imm(Off, Imm);
+}
+
+void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS,
+ uint64_t S, uint64_t P) const {
+ switch (Type) {
+ case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, (S >> 12) - (P >> 12)); break;
+ case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff); break;
+ case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break;
+ case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break;
+ case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break;
+ case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break;
+ default:
+ fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
+ }
+}
+
void SectionChunk::writeTo(uint8_t *Buf) const {
if (!hasData())
return;
@@ -210,6 +246,9 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
case ARMNT:
applyRelARM(Off, Rel.Type, OS, S, P);
break;
+ case ARM64:
+ applyRelARM64(Off, Rel.Type, OS, S, P);
+ break;
default:
llvm_unreachable("unknown machine type");
}
@@ -236,6 +275,10 @@ static uint8_t getBaserelType(const coff_relocation &R
if (Rel.Type == IMAGE_REL_ARM_MOV32T)
return IMAGE_REL_BASED_ARM_MOV32T;
return IMAGE_REL_BASED_ABSOLUTE;
+ case ARM64:
+ if (Rel.Type == IMAGE_REL_ARM64_ADDR64)
+ return IMAGE_REL_BASED_DIR64;
+ return IMAGE_REL_BASED_ABSOLUTE;
default:
llvm_unreachable("unknown machine type");
}
@@ -343,6 +386,14 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const
memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM));
// Fix mov.w and mov.t operands.
applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase);
+}
+
+void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const {
+ int64_t PageOff = (ImpSymbol->getRVA() >> 12) - (RVA >> 12);
+ int64_t Off = ImpSymbol->getRVA() & 0xfff;
+ memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64));
+ applyArm64Addr(Buf + OutputSectionOff, PageOff);
+ applyArm64Ldr(Buf + OutputSectionOff + 4, Off);
}
void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {
Modified: vendor/lld/dist/COFF/Chunks.h
==============================================================================
--- vendor/lld/dist/COFF/Chunks.h Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Chunks.h Thu Jul 13 19:26:06 2017 (r320965)
@@ -151,6 +151,8 @@ class SectionChunk : public Chunk { (public)
uint64_t P) const;
void applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
uint64_t P) const;
+ void applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
+ uint64_t P) const;
// Called if the garbage collector decides to not include this chunk
// in a final output. It's supposed to print out a log message to stdout.
@@ -264,6 +266,12 @@ static const uint8_t ImportThunkARM[] = {
0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]
};
+static const uint8_t ImportThunkARM64[] = {
+ 0x10, 0x00, 0x00, 0x90, // adrp x16, #0
+ 0x10, 0x02, 0x40, 0xf9, // ldr x16, [x16]
+ 0x00, 0x02, 0x1f, 0xd6, // br x16
+};
+
// Windows-specific.
// A chunk for DLL import jump table entry. In a final output, it's
// contents will be a JMP instruction to some __imp_ symbol.
@@ -293,6 +301,16 @@ class ImportThunkChunkARM : public Chunk { (public)
explicit ImportThunkChunkARM(Defined *S) : ImpSymbol(S) {}
size_t getSize() const override { return sizeof(ImportThunkARM); }
void getBaserels(std::vector<Baserel> *Res) override;
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ Defined *ImpSymbol;
+};
+
+class ImportThunkChunkARM64 : public Chunk {
+public:
+ explicit ImportThunkChunkARM64(Defined *S) : ImpSymbol(S) {}
+ size_t getSize() const override { return sizeof(ImportThunkARM64); }
void writeTo(uint8_t *Buf) const override;
private:
Modified: vendor/lld/dist/COFF/Config.h
==============================================================================
--- vendor/lld/dist/COFF/Config.h Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Config.h Thu Jul 13 19:26:06 2017 (r320965)
@@ -31,6 +31,7 @@ class SymbolBody;
// Short aliases.
static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
+static const auto ARM64 = llvm::COFF::IMAGE_FILE_MACHINE_ARM64;
static const auto ARMNT = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
@@ -73,7 +74,7 @@ enum class DebugType {
// Global configuration.
struct Configuration {
enum ManifestKind { SideBySide, Embed, No };
- bool is64() { return Machine == AMD64; }
+ bool is64() { return Machine == AMD64 || Machine == ARM64; }
llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN;
bool Verbose = false;
@@ -91,6 +92,7 @@ struct Configuration {
bool WriteSymtab = true;
unsigned DebugTypes = static_cast<unsigned>(DebugType::None);
llvm::SmallString<128> PDBPath;
+ std::vector<llvm::StringRef> Argv;
// Symbols in this set are considered as live by the garbage collector.
std::set<SymbolBody *> GCRoot;
Modified: vendor/lld/dist/COFF/Driver.cpp
==============================================================================
--- vendor/lld/dist/COFF/Driver.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Driver.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -55,8 +55,8 @@ std::vector<SpecificAllocBase *> SpecificAllocBase::In
bool link(ArrayRef<const char *> Args, raw_ostream &Diag) {
ErrorCount = 0;
ErrorOS = &Diag;
- Argv0 = Args[0];
Config = make<Configuration>();
+ Config->Argv = {Args.begin(), Args.end()};
Config->ColorDiagnostics =
(ErrorOS == &llvm::errs() && Process::StandardErrHasColors());
Driver = make<LinkerDriver>();
Modified: vendor/lld/dist/COFF/DriverUtils.cpp
==============================================================================
--- vendor/lld/dist/COFF/DriverUtils.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/DriverUtils.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -85,6 +85,7 @@ MachineTypes getMachineType(StringRef S) {
.Cases("x64", "amd64", AMD64)
.Cases("x86", "i386", I386)
.Case("arm", ARMNT)
+ .Case("arm64", ARM64)
.Default(IMAGE_FILE_MACHINE_UNKNOWN);
if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
return MT;
@@ -95,6 +96,8 @@ StringRef machineToStr(MachineTypes MT) {
switch (MT) {
case ARMNT:
return "arm";
+ case ARM64:
+ return "arm64";
case AMD64:
return "x64";
case I386:
@@ -378,13 +381,11 @@ static std::string createManifestXml() {
static std::unique_ptr<MemoryBuffer>
createMemoryBufferForManifestRes(size_t ManifestSize) {
- size_t ResSize = alignTo(object::WIN_RES_MAGIC_SIZE +
- object::WIN_RES_NULL_ENTRY_SIZE +
- sizeof(object::WinResHeaderPrefix) +
- sizeof(object::WinResIDs) +
- sizeof(object::WinResHeaderSuffix) +
- ManifestSize,
- object::WIN_RES_DATA_ALIGNMENT);
+ size_t ResSize = alignTo(
+ object::WIN_RES_MAGIC_SIZE + object::WIN_RES_NULL_ENTRY_SIZE +
+ sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) +
+ sizeof(object::WinResHeaderSuffix) + ManifestSize,
+ object::WIN_RES_DATA_ALIGNMENT);
return MemoryBuffer::getNewMemBuffer(ResSize);
}
Modified: vendor/lld/dist/COFF/Error.cpp
==============================================================================
--- vendor/lld/dist/COFF/Error.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Error.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -29,7 +29,6 @@ namespace lld {
static std::mutex Mu;
namespace coff {
-StringRef Argv0;
uint64_t ErrorCount;
raw_ostream *ErrorOS;
@@ -45,7 +44,7 @@ static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
}
static void print(StringRef S, raw_ostream::Colors C) {
- *ErrorOS << Argv0 + ": ";
+ *ErrorOS << Config->Argv[0] << ": ";
if (Config->ColorDiagnostics) {
ErrorOS->changeColor(C, true);
*ErrorOS << S;
@@ -58,7 +57,7 @@ static void print(StringRef S, raw_ostream::Colors C)
void log(const Twine &Msg) {
if (Config->Verbose) {
std::lock_guard<std::mutex> Lock(Mu);
- outs() << Argv0 << ": " << Msg << "\n";
+ outs() << Config->Argv[0] << ": " << Msg << "\n";
outs().flush();
}
}
Modified: vendor/lld/dist/COFF/Error.h
==============================================================================
--- vendor/lld/dist/COFF/Error.h Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Error.h Thu Jul 13 19:26:06 2017 (r320965)
@@ -18,7 +18,6 @@ namespace coff {
extern uint64_t ErrorCount;
extern llvm::raw_ostream *ErrorOS;
-extern llvm::StringRef Argv0;
void log(const Twine &Msg);
void message(const Twine &Msg);
Modified: vendor/lld/dist/COFF/InputFiles.cpp
==============================================================================
--- vendor/lld/dist/COFF/InputFiles.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/InputFiles.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -380,6 +380,8 @@ MachineTypes BitcodeFile::getMachineType() {
return I386;
case Triple::arm:
return ARMNT;
+ case Triple::aarch64:
+ return ARM64;
default:
return IMAGE_FILE_MACHINE_UNKNOWN;
}
Modified: vendor/lld/dist/COFF/PDB.cpp
==============================================================================
--- vendor/lld/dist/COFF/PDB.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/PDB.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -18,19 +18,20 @@
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
-#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
@@ -124,26 +125,25 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<Typ
return true;
}
-static bool remapTypesInSymbolRecord(ObjectFile *File,
+static void remapTypesInSymbolRecord(ObjectFile *File,
MutableArrayRef<uint8_t> Contents,
ArrayRef<TypeIndex> TypeIndexMap,
ArrayRef<TiReference> TypeRefs) {
for (const TiReference &Ref : TypeRefs) {
unsigned ByteSize = Ref.Count * sizeof(TypeIndex);
- if (Contents.size() < Ref.Offset + ByteSize) {
- log("ignoring short symbol record");
- return false;
- }
+ if (Contents.size() < Ref.Offset + ByteSize)
+ fatal("symbol record too short");
MutableArrayRef<TypeIndex> TIs(
reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count);
- for (TypeIndex &TI : TIs)
+ for (TypeIndex &TI : TIs) {
if (!remapTypeIndex(TI, TypeIndexMap)) {
+ TI = TypeIndex(SimpleTypeKind::NotTranslated);
log("ignoring symbol record in " + File->getName() +
" with bad type index 0x" + utohexstr(TI.getIndex()));
- return false;
+ continue;
}
+ }
}
- return true;
}
/// MSVC translates S_PROC_ID_END to S_END.
@@ -176,6 +176,70 @@ static MutableArrayRef<uint8_t> copySymbolForPdb(const
return NewData;
}
+/// Return true if this symbol opens a scope. This implies that the symbol has
+/// "parent" and "end" fields, which contain the offset of the S_END or
+/// S_INLINESITE_END record.
+static bool symbolOpensScope(SymbolKind Kind) {
+ switch (Kind) {
+ case SymbolKind::S_GPROC32:
+ case SymbolKind::S_LPROC32:
+ case SymbolKind::S_LPROC32_ID:
+ case SymbolKind::S_GPROC32_ID:
+ case SymbolKind::S_BLOCK32:
+ case SymbolKind::S_SEPCODE:
+ case SymbolKind::S_THUNK32:
+ case SymbolKind::S_INLINESITE:
+ case SymbolKind::S_INLINESITE2:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool symbolEndsScope(SymbolKind Kind) {
+ switch (Kind) {
+ case SymbolKind::S_END:
+ case SymbolKind::S_PROC_ID_END:
+ case SymbolKind::S_INLINESITE_END:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+struct ScopeRecord {
+ ulittle32_t PtrParent;
+ ulittle32_t PtrEnd;
+};
+
+struct SymbolScope {
+ ScopeRecord *OpeningRecord;
+ uint32_t ScopeOffset;
+};
+
+static void scopeStackOpen(SmallVectorImpl<SymbolScope> &Stack,
+ uint32_t CurOffset, CVSymbol &Sym) {
+ assert(symbolOpensScope(Sym.kind()));
+ SymbolScope S;
+ S.ScopeOffset = CurOffset;
+ S.OpeningRecord = const_cast<ScopeRecord *>(
+ reinterpret_cast<const ScopeRecord *>(Sym.content().data()));
+ S.OpeningRecord->PtrParent = Stack.empty() ? 0 : Stack.back().ScopeOffset;
+ Stack.push_back(S);
+}
+
+static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack,
+ uint32_t CurOffset, ObjectFile *File) {
+ if (Stack.empty()) {
+ warn("symbol scopes are not balanced in " + File->getName());
+ return;
+ }
+ SymbolScope S = Stack.pop_back_val();
+ S.OpeningRecord->PtrEnd = CurOffset;
+}
+
static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
ArrayRef<TypeIndex> TypeIndexMap,
BinaryStreamRef SymData) {
@@ -184,6 +248,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc
CVSymbolArray Syms;
BinaryStreamReader Reader(SymData);
ExitOnErr(Reader.readArray(Syms, Reader.getLength()));
+ SmallVector<SymbolScope, 4> Scopes;
for (const CVSymbol &Sym : Syms) {
// Discover type index references in the record. Skip it if we don't know
// where they are.
@@ -199,14 +264,17 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc
// Re-map all the type index references.
MutableArrayRef<uint8_t> Contents =
NewData.drop_front(sizeof(RecordPrefix));
- if (!remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs))
- continue;
+ remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs);
- // FIXME: Fill in "Parent" and "End" fields by maintaining a stack of
- // scopes.
+ // Fill in "Parent" and "End" fields by maintaining a stack of scopes.
+ CVSymbol NewSym(Sym.kind(), NewData);
+ if (symbolOpensScope(Sym.kind()))
+ scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(), NewSym);
+ else if (symbolEndsScope(Sym.kind()))
+ scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File);
// Add the symbol to the module.
- File->ModuleDBI->addSymbol(CVSymbol(Sym.kind(), NewData));
+ File->ModuleDBI->addSymbol(NewSym);
}
}
@@ -246,7 +314,9 @@ static void addObjectsToPDB(BumpPtrAllocator &Alloc, S
bool InArchive = !File->ParentName.empty();
SmallString<128> Path = InArchive ? File->ParentName : File->getName();
sys::fs::make_absolute(Path);
+ sys::path::native(Path, llvm::sys::path::Style::windows);
StringRef Name = InArchive ? File->getName() : StringRef(Path);
+
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
File->ModuleDBI->setObjFileName(Path);
@@ -325,9 +395,52 @@ static void addObjectsToPDB(BumpPtrAllocator &Alloc, S
addTypeInfo(Builder.getIpiBuilder(), IDTable);
}
+static void addLinkerModuleSymbols(StringRef Path,
+ pdb::DbiModuleDescriptorBuilder &Mod,
+ BumpPtrAllocator &Allocator) {
+ codeview::SymbolSerializer Serializer(Allocator, CodeViewContainer::Pdb);
+ codeview::ObjNameSym ONS(SymbolRecordKind::ObjNameSym);
+ codeview::Compile3Sym CS(SymbolRecordKind::Compile3Sym);
+ codeview::EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym);
+
+ ONS.Name = "* Linker *";
+ ONS.Signature = 0;
+
+ CS.Machine = Config->is64() ? CPUType::X64 : CPUType::Intel80386;
+ CS.Flags = CompileSym3Flags::None;
+ CS.VersionBackendBuild = 0;
+ CS.VersionBackendMajor = 0;
+ CS.VersionBackendMinor = 0;
+ CS.VersionBackendQFE = 0;
+ CS.VersionFrontendBuild = 0;
+ CS.VersionFrontendMajor = 0;
+ CS.VersionFrontendMinor = 0;
+ CS.VersionFrontendQFE = 0;
+ CS.Version = "LLVM Linker";
+ CS.setLanguage(SourceLanguage::Link);
+
+ ArrayRef<StringRef> Args = makeArrayRef(Config->Argv).drop_front();
+ std::string ArgStr = llvm::join(Args, " ");
+ EBS.Fields.push_back("cwd");
+ SmallString<64> cwd;
+ llvm::sys::fs::current_path(cwd);
+ EBS.Fields.push_back(cwd);
+ EBS.Fields.push_back("exe");
+ EBS.Fields.push_back(Config->Argv[0]);
+ EBS.Fields.push_back("pdb");
+ EBS.Fields.push_back(Path);
+ EBS.Fields.push_back("cmd");
+ EBS.Fields.push_back(ArgStr);
+ Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
+ ONS, Allocator, CodeViewContainer::Pdb));
+ Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
+ CS, Allocator, CodeViewContainer::Pdb));
+ Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
+ EBS, Allocator, CodeViewContainer::Pdb));
+}
+
// Creates a PDB file.
-void coff::createPDB(StringRef Path, SymbolTable *Symtab,
- ArrayRef<uint8_t> SectionTable,
+void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo *DI) {
BumpPtrAllocator Alloc;
pdb::PDBFileBuilder Builder(Alloc);
@@ -342,22 +455,37 @@ void coff::createPDB(StringRef Path, SymbolTable *Symt
auto &InfoBuilder = Builder.getInfoBuilder();
InfoBuilder.setAge(DI ? DI->PDB70.Age : 0);
+ llvm::SmallString<128> NativePath(Config->PDBPath.begin(),
+ Config->PDBPath.end());
+ llvm::sys::fs::make_absolute(NativePath);
+ llvm::sys::path::native(NativePath, llvm::sys::path::Style::windows);
+
pdb::PDB_UniqueId uuid{};
if (DI)
memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid));
InfoBuilder.setGuid(uuid);
- // Should be the current time, but set 0 for reproducibilty.
- InfoBuilder.setSignature(0);
+ InfoBuilder.setSignature(time(nullptr));
InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
- // Add an empty DPI stream.
+ // Add an empty DBI stream.
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
- DbiBuilder.setVersionHeader(pdb::PdbDbiV110);
+ DbiBuilder.setVersionHeader(pdb::PdbDbiV70);
+ ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
+ // It's not entirely clear what this is, but the * Linker * module uses it.
+ uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath);
+
TypeTableBuilder TypeTable(BAlloc);
TypeTableBuilder IDTable(BAlloc);
addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable);
+ // Add public and symbol records stream.
+
+ // For now we don't actually write any thing useful to the publics stream, but
+ // the act of "getting" it also creates it lazily so that we write an empty
+ // stream.
+ (void)Builder.getPublicsBuilder();
+
// Add Section Contributions.
addSectionContribs(Symtab, DbiBuilder);
@@ -369,12 +497,14 @@ void coff::createPDB(StringRef Path, SymbolTable *Symt
pdb::DbiStreamBuilder::createSectionMap(Sections);
DbiBuilder.setSectionMap(SectionMap);
- ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));
+ auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));
+ LinkerModule.setPdbFilePathNI(PdbFilePathNI);
+ addLinkerModuleSymbols(NativePath, LinkerModule, Alloc);
// Add COFF section header stream.
ExitOnErr(
DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));
// Write to a file.
- ExitOnErr(Builder.commit(Path));
+ ExitOnErr(Builder.commit(Config->PDBPath));
}
Modified: vendor/lld/dist/COFF/PDB.h
==============================================================================
--- vendor/lld/dist/COFF/PDB.h Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/PDB.h Thu Jul 13 19:26:06 2017 (r320965)
@@ -23,8 +23,7 @@ namespace lld {
namespace coff {
class SymbolTable;
-void createPDB(llvm::StringRef Path, SymbolTable *Symtab,
- llvm::ArrayRef<uint8_t> SectionTable,
+void createPDB(SymbolTable *Symtab, llvm::ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo *DI);
}
}
Modified: vendor/lld/dist/COFF/Symbols.cpp
==============================================================================
--- vendor/lld/dist/COFF/Symbols.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Symbols.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -68,6 +68,8 @@ static Chunk *makeImportThunk(DefinedImportData *S, ui
return make<ImportThunkChunkX64>(S);
if (Machine == I386)
return make<ImportThunkChunkX86>(S);
+ if (Machine == ARM64)
+ return make<ImportThunkChunkARM64>(S);
assert(Machine == ARMNT);
return make<ImportThunkChunkARM>(S);
}
Modified: vendor/lld/dist/COFF/Writer.cpp
==============================================================================
--- vendor/lld/dist/COFF/Writer.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/COFF/Writer.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -239,7 +239,7 @@ void Writer::run() {
const llvm::codeview::DebugInfo *DI = nullptr;
if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV))
DI = BuildId->DI;
- createPDB(Config->PDBPath, Symtab, SectionTable, DI);
+ createPDB(Symtab, SectionTable, DI);
}
writeMapFile(OutputSections);
Modified: vendor/lld/dist/ELF/Config.h
==============================================================================
--- vendor/lld/dist/ELF/Config.h Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/Config.h Thu Jul 13 19:26:06 2017 (r320965)
@@ -97,6 +97,7 @@ struct Configuration {
llvm::StringRef ThinLTOCacheDir;
std::string Rpath;
std::vector<VersionDefinition> VersionDefinitions;
+ std::vector<llvm::StringRef> Argv;
std::vector<llvm::StringRef> AuxiliaryList;
std::vector<llvm::StringRef> SearchPaths;
std::vector<llvm::StringRef> SymbolOrderingFile;
Modified: vendor/lld/dist/ELF/Driver.cpp
==============================================================================
--- vendor/lld/dist/ELF/Driver.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/Driver.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -74,13 +74,13 @@ bool elf::link(ArrayRef<const char *> Args, bool CanEx
raw_ostream &Error) {
ErrorCount = 0;
ErrorOS = &Error;
- Argv0 = Args[0];
InputSections.clear();
Tar = nullptr;
Config = make<Configuration>();
Driver = make<LinkerDriver>();
Script = make<LinkerScript>();
+ Config->Argv = {Args.begin(), Args.end()};
Driver->main(Args, CanExitEarly);
freeArena();
Modified: vendor/lld/dist/ELF/Error.cpp
==============================================================================
--- vendor/lld/dist/ELF/Error.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/Error.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -27,7 +27,6 @@ using namespace lld::elf;
uint64_t elf::ErrorCount;
raw_ostream *elf::ErrorOS;
-StringRef elf::Argv0;
// The functions defined in this file can be called from multiple threads,
// but outs() or errs() are not thread-safe. We protect them using a mutex.
@@ -46,7 +45,7 @@ static void newline(const Twine &Msg) {
}
static void print(StringRef S, raw_ostream::Colors C) {
- *ErrorOS << Argv0 + ": ";
+ *ErrorOS << Config->Argv[0] << ": ";
if (Config->ColorDiagnostics) {
ErrorOS->changeColor(C, true);
*ErrorOS << S;
@@ -59,7 +58,7 @@ static void print(StringRef S, raw_ostream::Colors C)
void elf::log(const Twine &Msg) {
if (Config->Verbose) {
std::lock_guard<std::mutex> Lock(Mu);
- outs() << Argv0 << ": " << Msg << "\n";
+ outs() << Config->Argv[0] << ": " << Msg << "\n";
outs().flush();
}
}
Modified: vendor/lld/dist/ELF/Error.h
==============================================================================
--- vendor/lld/dist/ELF/Error.h Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/Error.h Thu Jul 13 19:26:06 2017 (r320965)
@@ -37,7 +37,6 @@ namespace elf {
extern uint64_t ErrorCount;
extern llvm::raw_ostream *ErrorOS;
-extern llvm::StringRef Argv0;
void log(const Twine &Msg);
void message(const Twine &Msg);
Modified: vendor/lld/dist/ELF/Filesystem.cpp
==============================================================================
--- vendor/lld/dist/ELF/Filesystem.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/Filesystem.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -38,7 +38,8 @@ using namespace lld::elf;
// This function spawns a background thread to call unlink.
// The calling thread returns almost immediately.
void elf::unlinkAsync(StringRef Path) {
- if (!Config->Threads || !sys::fs::exists(Config->OutputFile))
+ if (!Config->Threads || !sys::fs::exists(Config->OutputFile) ||
+ !sys::fs::is_regular_file(Config->OutputFile))
return;
// First, rename Path to avoid race condition. We cannot remove
Modified: vendor/lld/dist/ELF/GdbIndex.h
==============================================================================
--- vendor/lld/dist/ELF/GdbIndex.h Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/GdbIndex.h Thu Jul 13 19:26:06 2017 (r320965)
@@ -45,6 +45,7 @@ struct NameTypeEntry {
// debug information performed. That information futher used
// for filling gdb index section areas.
struct GdbIndexChunk {
+ InputSection *DebugInfoSec;
std::vector<AddressEntry> AddressArea;
std::vector<CompilationUnitEntry> CompilationUnits;
std::vector<NameTypeEntry> NamesAndTypes;
Modified: vendor/lld/dist/ELF/InputFiles.cpp
==============================================================================
--- vendor/lld/dist/ELF/InputFiles.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/InputFiles.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -45,13 +45,10 @@ namespace {
// LLVM DWARF parser will not be able to parse .debug_line correctly, unless
// we assign each section some unique address. This callback method assigns
// each section an address equal to its offset in ELF object file.
-class ObjectInfo : public LoadedObjectInfo {
+class ObjectInfo : public LoadedObjectInfoHelper<ObjectInfo> {
public:
uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override {
return static_cast<const ELFSectionRef &>(Sec).getOffset();
- }
- std::unique_ptr<LoadedObjectInfo> clone() const override {
- return std::unique_ptr<LoadedObjectInfo>();
}
};
}
Modified: vendor/lld/dist/ELF/InputSection.cpp
==============================================================================
--- vendor/lld/dist/ELF/InputSection.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/InputSection.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -276,7 +276,9 @@ template <class ELFT> std::string InputSectionBase::ge
template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) {
// Synthetic sections don't have input files.
elf::ObjectFile<ELFT> *File = getFile<ELFT>();
- std::string Filename = File ? File->getName() : "(internal)";
+ if (!File)
+ return ("(internal):(" + Name + "+0x" + utohexstr(Off) + ")").str();
+ std::string Filename = File->getName();
std::string Archive;
if (!File->ArchiveName.empty())
@@ -466,7 +468,7 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint
static uint64_t getARMStaticBase(const SymbolBody &Body) {
OutputSection *OS = Body.getOutputSection();
if (!OS || !OS->FirstInPtLoad)
- fatal("SBREL relocation to " + Body.getName() + " without static base\n");
+ fatal("SBREL relocation to " + Body.getName() + " without static base");
return OS->FirstInPtLoad->Addr;
}
Modified: vendor/lld/dist/ELF/LinkerScript.cpp
==============================================================================
--- vendor/lld/dist/ELF/LinkerScript.cpp Thu Jul 13 19:26:02 2017 (r320964)
+++ vendor/lld/dist/ELF/LinkerScript.cpp Thu Jul 13 19:26:06 2017 (r320965)
@@ -111,17 +111,13 @@ LinkerScript::getOrCreateOutputSectionCommand(StringRe
void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {
uint64_t Val = E().getValue();
- if (Val < Dot) {
- if (InSec)
- error(Loc + ": unable to move location counter backward for: " +
- CurOutSec->Name);
- else
- error(Loc + ": unable to move location counter backward");
- }
+ if (Val < Dot && InSec)
+ error(Loc + ": unable to move location counter backward for: " +
+ CurAddressState->OutSec->Name);
Dot = Val;
// Update to location counter means update to section size.
if (InSec)
- CurOutSec->Size = Dot - CurOutSec->Addr;
+ CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr;
}
// Sets value of a symbol. Two kinds of symbols are processed: synthetic
@@ -373,7 +369,13 @@ void LinkerScript::processCommands(OutputSectionFactor
// which will map to whatever the first actual section is.
Aether = make<OutputSection>("", 0, SHF_ALLOC);
Aether->SectionIndex = 1;
- CurOutSec = Aether;
+ auto State = make_unique<AddressState>(Opt);
+ // CurAddressState captures the local AddressState and makes it accessible
+ // deliberately. This is needed as there are some cases where we cannot just
+ // thread the current state through to a lambda function created by the
+ // script parser.
+ CurAddressState = State.get();
+ CurAddressState->OutSec = Aether;
Dot = 0;
for (size_t I = 0; I < Opt.Commands.size(); ++I) {
@@ -435,7 +437,7 @@ void LinkerScript::processCommands(OutputSectionFactor
}
}
}
- CurOutSec = nullptr;
+ CurAddressState = nullptr;
}
void LinkerScript::fabricateDefaultCommands() {
@@ -481,20 +483,31 @@ void LinkerScript::fabricateDefaultCommands() {
// Add sections that didn't match any sections command.
void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
+ unsigned NumCommands = Opt.Commands.size();
for (InputSectionBase *S : InputSections) {
if (!S->Live || S->Parent)
continue;
StringRef Name = getOutputSectionName(S->Name);
- auto I = std::find_if(
- Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) {
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- return Cmd->Name == Name;
- return false;
- });
- if (I == Opt.Commands.end()) {
+ auto End = Opt.Commands.begin() + NumCommands;
+ auto I = std::find_if(Opt.Commands.begin(), End, [&](BaseCommand *Base) {
+ if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
+ return Cmd->Name == Name;
+ return false;
+ });
+ OutputSectionCommand *Cmd;
+ if (I == End) {
Factory.addInputSec(S, Name);
+ OutputSection *Sec = S->getOutputSection();
+ assert(Sec->SectionIndex == INT_MAX);
+ OutputSectionCommand *&CmdRef = SecToCommand[Sec];
+ if (!CmdRef) {
+ CmdRef = createOutputSectionCommand(Sec->Name, "<internal>");
+ CmdRef->Sec = Sec;
+ Opt.Commands.push_back(CmdRef);
+ }
+ Cmd = CmdRef;
} else {
- auto *Cmd = cast<OutputSectionCommand>(*I);
+ Cmd = cast<OutputSectionCommand>(*I);
Factory.addInputSec(S, Name, Cmd->Sec);
if (OutputSection *Sec = Cmd->Sec) {
SecToCommand[Sec] = Cmd;
@@ -502,21 +515,22 @@ void LinkerScript::addOrphanSections(OutputSectionFact
assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index);
Sec->SectionIndex = Index;
}
- auto *ISD = make<InputSectionDescription>("");
- ISD->Sections.push_back(cast<InputSection>(S));
- Cmd->Commands.push_back(ISD);
}
+ auto *ISD = make<InputSectionDescription>("");
+ ISD->Sections.push_back(cast<InputSection>(S));
+ Cmd->Commands.push_back(ISD);
}
}
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;
+ bool IsTbss = (CurAddressState->OutSec->Flags & SHF_TLS) &&
+ CurAddressState->OutSec->Type == SHT_NOBITS;
+ uint64_t Start = IsTbss ? Dot + CurAddressState->ThreadBssOffset : Dot;
Start = alignTo(Start, Align);
uint64_t End = Start + Size;
if (IsTbss)
- ThreadBssOffset = End - Dot;
+ CurAddressState->ThreadBssOffset = End - Dot;
else
Dot = End;
return End;
@@ -524,40 +538,43 @@ uint64_t LinkerScript::advance(uint64_t Size, unsigned
void LinkerScript::output(InputSection *S) {
uint64_t Pos = advance(S->getSize(), S->Alignment);
- S->OutSecOff = Pos - S->getSize() - CurOutSec->Addr;
+ S->OutSecOff = Pos - S->getSize() - CurAddressState->OutSec->Addr;
// Update output section size after adding each section. This is so that
// SIZEOF works correctly in the case below:
// .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
- CurOutSec->Size = Pos - CurOutSec->Addr;
+ CurAddressState->OutSec->Size = Pos - CurAddressState->OutSec->Addr;
// If there is a memory region associated with this input section, then
// place the section in that region and update the region index.
- if (CurMemRegion) {
- CurMemRegion->Offset += CurOutSec->Size;
- uint64_t CurSize = CurMemRegion->Offset - CurMemRegion->Origin;
- if (CurSize > CurMemRegion->Length) {
- uint64_t OverflowAmt = CurSize - CurMemRegion->Length;
- error("section '" + CurOutSec->Name + "' will not fit in region '" +
- CurMemRegion->Name + "': overflowed by " + Twine(OverflowAmt) +
- " bytes");
+ if (CurAddressState->MemRegion) {
+ uint64_t &CurOffset =
+ CurAddressState->MemRegionOffset[CurAddressState->MemRegion];
+ CurOffset += CurAddressState->OutSec->Size;
+ uint64_t CurSize = CurOffset - CurAddressState->MemRegion->Origin;
+ if (CurSize > CurAddressState->MemRegion->Length) {
+ uint64_t OverflowAmt = CurSize - CurAddressState->MemRegion->Length;
+ error("section '" + CurAddressState->OutSec->Name +
+ "' will not fit in region '" + CurAddressState->MemRegion->Name +
+ "': overflowed by " + Twine(OverflowAmt) + " bytes");
}
}
}
void LinkerScript::switchTo(OutputSection *Sec) {
- if (CurOutSec == Sec)
+ if (CurAddressState->OutSec == Sec)
return;
- CurOutSec = Sec;
- CurOutSec->Addr = advance(0, CurOutSec->Alignment);
+ CurAddressState->OutSec = Sec;
+ CurAddressState->OutSec->Addr =
+ advance(0, CurAddressState->OutSec->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
// section is the same as the preceding output section in the same region
// https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
- if (LMAOffset)
- CurOutSec->LMAOffset = LMAOffset();
+ if (CurAddressState->LMAOffset)
+ CurAddressState->OutSec->LMAOffset = CurAddressState->LMAOffset();
}
void LinkerScript::process(BaseCommand &Base) {
@@ -569,9 +586,9 @@ void LinkerScript::process(BaseCommand &Base) {
// Handle BYTE(), SHORT(), LONG(), or QUAD().
if (auto *Cmd = dyn_cast<BytesDataCommand>(&Base)) {
- Cmd->Offset = Dot - CurOutSec->Addr;
+ Cmd->Offset = Dot - CurAddressState->OutSec->Addr;
Dot += Cmd->Size;
- CurOutSec->Size = Dot - CurOutSec->Addr;
+ CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr;
return;
}
@@ -596,7 +613,7 @@ void LinkerScript::process(BaseCommand &Base) {
if (!Sec->Live)
continue;
- assert(CurOutSec == Sec->getParent());
+ assert(CurAddressState->OutSec == Sec->getParent());
output(Sec);
}
}
@@ -649,17 +666,17 @@ void LinkerScript::assignOffsets(OutputSectionCommand
if (Cmd->LMAExpr) {
uint64_t D = Dot;
- LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; };
+ CurAddressState->LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; };
}
- CurMemRegion = Cmd->MemRegion;
- if (CurMemRegion)
- Dot = CurMemRegion->Offset;
+ CurAddressState->MemRegion = Cmd->MemRegion;
+ if (CurAddressState->MemRegion)
+ Dot = CurAddressState->MemRegionOffset[CurAddressState->MemRegion];
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)
+ if (CurAddressState->OutSec->Flags & SHF_COMPRESSED)
return;
for (BaseCommand *C : Cmd->Commands)
@@ -746,30 +763,20 @@ void LinkerScript::adjustSectionsAfterSorting() {
if (!Cmd)
continue;
- if (Cmd->Phdrs.empty())
- Cmd->Phdrs = DefPhdrs;
- else
+ if (Cmd->Phdrs.empty()) {
+ OutputSection *Sec = Cmd->Sec;
+ // To match the bfd linker script behaviour, only propagate program
+ // headers to sections that are allocated.
+ if (Sec && (Sec->Flags & SHF_ALLOC))
+ Cmd->Phdrs = DefPhdrs;
+ } else {
DefPhdrs = Cmd->Phdrs;
+ }
}
removeEmptyCommands();
}
-void LinkerScript::createOrphanCommands() {
- for (OutputSection *Sec : OutputSections) {
- if (Sec->SectionIndex != INT_MAX)
- continue;
- OutputSectionCommand *Cmd =
- createOutputSectionCommand(Sec->Name, "<internal>");
- Cmd->Sec = Sec;
- SecToCommand[Sec] = Cmd;
- auto *ISD = make<InputSectionDescription>("");
- ISD->Sections = Sec->Sections;
- Cmd->Commands.push_back(ISD);
- Opt.Commands.push_back(Cmd);
- }
-}
-
void LinkerScript::processNonSectionCommands() {
for (BaseCommand *Base : Opt.Commands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base))
@@ -779,22 +786,25 @@ void LinkerScript::processNonSectionCommands() {
}
}
-static bool
-allocateHeaders(std::vector<PhdrEntry> &Phdrs,
- ArrayRef<OutputSectionCommand *> OutputSectionCommands,
- uint64_t Min) {
- auto FirstPTLoad =
- std::find_if(Phdrs.begin(), Phdrs.end(),
- [](const PhdrEntry &E) { return E.p_type == PT_LOAD; });
+void LinkerScript::allocateHeaders(std::vector<PhdrEntry> &Phdrs) {
+ uint64_t Min = std::numeric_limits<uint64_t>::max();
+ for (OutputSectionCommand *Cmd : OutputSectionCommands) {
+ OutputSection *Sec = Cmd->Sec;
+ if (Sec->Flags & SHF_ALLOC)
+ Min = std::min<uint64_t>(Min, Sec->Addr);
+ }
+
+ auto FirstPTLoad = llvm::find_if(
+ Phdrs, [](const PhdrEntry &E) { return E.p_type == PT_LOAD; });
if (FirstPTLoad == Phdrs.end())
- return false;
+ return;
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;
+ return;
}
assert(FirstPTLoad->First == Out::ElfHeader);
@@ -817,17 +827,28 @@ allocateHeaders(std::vector<PhdrEntry> &Phdrs,
Phdrs.erase(FirstPTLoad);
}
- auto PhdrI = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) {
- return E.p_type == PT_PHDR;
- });
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-vendor
mailing list