From f1e1c239e31b467e17f1648b1f524fc9ab5b431a Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 20 Aug 2019 20:51:32 +0000 Subject: Vendor import of stripped lld trunk r366426 (just before the release_90 branch point): https://llvm.org/svn/llvm-project/lld/trunk@366426 --- COFF/DLL.cpp | 703 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 404 insertions(+), 299 deletions(-) (limited to 'COFF/DLL.cpp') diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp index 599cc5892a16..40d1f463aa3f 100644 --- a/COFF/DLL.cpp +++ b/COFF/DLL.cpp @@ -1,9 +1,8 @@ //===- DLL.cpp ------------------------------------------------------------===// // -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -36,149 +35,167 @@ namespace { // Import table // A chunk for the import descriptor table. -class HintNameChunk : public Chunk { +class HintNameChunk : public NonSectionChunk { public: - HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {} + HintNameChunk(StringRef n, uint16_t h) : name(n), hint(h) {} size_t getSize() const override { // Starts with 2 byte Hint field, followed by a null-terminated string, // ends with 0 or 1 byte padding. - return alignTo(Name.size() + 3, 2); + return alignTo(name.size() + 3, 2); } - void writeTo(uint8_t *Buf) const override { - write16le(Buf + OutputSectionOff, Hint); - memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size()); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); + write16le(buf, hint); + memcpy(buf + 2, name.data(), name.size()); } private: - StringRef Name; - uint16_t Hint; + StringRef name; + uint16_t hint; }; // A chunk for the import descriptor table. -class LookupChunk : public Chunk { +class LookupChunk : public NonSectionChunk { public: - explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = Config->Wordsize; } - size_t getSize() const override { return Config->Wordsize; } + explicit LookupChunk(Chunk *c) : hintName(c) { + setAlignment(config->wordsize); + } + size_t getSize() const override { return config->wordsize; } - void writeTo(uint8_t *Buf) const override { - write32le(Buf + OutputSectionOff, HintName->getRVA()); + void writeTo(uint8_t *buf) const override { + if (config->is64()) + write64le(buf, hintName->getRVA()); + else + write32le(buf, hintName->getRVA()); } - Chunk *HintName; + Chunk *hintName; }; // A chunk for the import descriptor table. // This chunk represent import-by-ordinal symbols. // See Microsoft PE/COFF spec 7.1. Import Header for details. -class OrdinalOnlyChunk : public Chunk { +class OrdinalOnlyChunk : public NonSectionChunk { public: - explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { - Alignment = Config->Wordsize; + explicit OrdinalOnlyChunk(uint16_t v) : ordinal(v) { + setAlignment(config->wordsize); } - size_t getSize() const override { return Config->Wordsize; } + size_t getSize() const override { return config->wordsize; } - void writeTo(uint8_t *Buf) const override { + void writeTo(uint8_t *buf) const override { // An import-by-ordinal slot has MSB 1 to indicate that // this is import-by-ordinal (and not import-by-name). - if (Config->is64()) { - write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal); + if (config->is64()) { + write64le(buf, (1ULL << 63) | ordinal); } else { - write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal); + write32le(buf, (1ULL << 31) | ordinal); } } - uint16_t Ordinal; + uint16_t ordinal; }; // A chunk for the import descriptor table. -class ImportDirectoryChunk : public Chunk { +class ImportDirectoryChunk : public NonSectionChunk { public: - explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {} + explicit ImportDirectoryChunk(Chunk *n) : dllName(n) {} size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } - void writeTo(uint8_t *Buf) const override { - auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff); - E->ImportLookupTableRVA = LookupTab->getRVA(); - E->NameRVA = DLLName->getRVA(); - E->ImportAddressTableRVA = AddressTab->getRVA(); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); + + auto *e = (coff_import_directory_table_entry *)(buf); + e->ImportLookupTableRVA = lookupTab->getRVA(); + e->NameRVA = dllName->getRVA(); + e->ImportAddressTableRVA = addressTab->getRVA(); } - Chunk *DLLName; - Chunk *LookupTab; - Chunk *AddressTab; + Chunk *dllName; + Chunk *lookupTab; + Chunk *addressTab; }; // A chunk representing null terminator in the import table. // Contents of this chunk is always null bytes. -class NullChunk : public Chunk { +class NullChunk : public NonSectionChunk { public: - explicit NullChunk(size_t N) : Size(N) {} - bool hasData() const override { return false; } - size_t getSize() const override { return Size; } + explicit NullChunk(size_t n) : size(n) { hasData = false; } + size_t getSize() const override { return size; } + + void writeTo(uint8_t *buf) const override { + memset(buf, 0, size); + } private: - size_t Size; + size_t size; }; static std::vector> -binImports(const std::vector &Imports) { +binImports(const std::vector &imports) { // Group DLL-imported symbols by DLL name because that's how // symbols are layed out in the import descriptor table. - auto Less = [](const std::string &A, const std::string &B) { - return Config->DLLOrder[A] < Config->DLLOrder[B]; + auto less = [](const std::string &a, const std::string &b) { + return config->dllOrder[a] < config->dllOrder[b]; }; std::map, - bool(*)(const std::string &, const std::string &)> M(Less); - for (DefinedImportData *Sym : Imports) - M[Sym->getDLLName().lower()].push_back(Sym); + bool(*)(const std::string &, const std::string &)> m(less); + for (DefinedImportData *sym : imports) + m[sym->getDLLName().lower()].push_back(sym); - std::vector> V; - for (auto &KV : M) { + std::vector> v; + for (auto &kv : m) { // Sort symbols by name for each group. - std::vector &Syms = KV.second; - std::sort(Syms.begin(), Syms.end(), - [](DefinedImportData *A, DefinedImportData *B) { - return A->getName() < B->getName(); + std::vector &syms = kv.second; + std::sort(syms.begin(), syms.end(), + [](DefinedImportData *a, DefinedImportData *b) { + return a->getName() < b->getName(); }); - V.push_back(std::move(Syms)); + v.push_back(std::move(syms)); } - return V; + return v; } // Export table // See Microsoft PE/COFF spec 4.3 for details. // A chunk for the delay import descriptor table etnry. -class DelayDirectoryChunk : public Chunk { +class DelayDirectoryChunk : public NonSectionChunk { public: - explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {} + explicit DelayDirectoryChunk(Chunk *n) : dllName(n) {} size_t getSize() const override { return sizeof(delay_import_directory_table_entry); } - void writeTo(uint8_t *Buf) const override { - auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff); - E->Attributes = 1; - E->Name = DLLName->getRVA(); - E->ModuleHandle = ModuleHandle->getRVA(); - E->DelayImportAddressTable = AddressTab->getRVA(); - E->DelayImportNameTable = NameTab->getRVA(); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); + + auto *e = (delay_import_directory_table_entry *)(buf); + e->Attributes = 1; + e->Name = dllName->getRVA(); + e->ModuleHandle = moduleHandle->getRVA(); + e->DelayImportAddressTable = addressTab->getRVA(); + e->DelayImportNameTable = nameTab->getRVA(); } - Chunk *DLLName; - Chunk *ModuleHandle; - Chunk *AddressTab; - Chunk *NameTab; + Chunk *dllName; + Chunk *moduleHandle; + Chunk *addressTab; + Chunk *nameTab; }; // Initial contents for delay-loaded functions. // This code calls __delayLoadHelper2 function to resolve a symbol // and then overwrites its jump table slot with the result // for subsequent function calls. -static const uint8_t ThunkX64[] = { +static const uint8_t thunkX64[] = { + 0x48, 0x8D, 0x05, 0, 0, 0, 0, // lea rax, [__imp_] + 0xE9, 0, 0, 0, 0, // jmp __tailMerge_ +}; + +static const uint8_t tailMergeX64[] = { 0x51, // push rcx 0x52, // push rdx 0x41, 0x50, // push r8 @@ -188,7 +205,7 @@ static const uint8_t ThunkX64[] = { 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3 - 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_] + 0x48, 0x8B, 0xD0, // mov rdx, rax 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...] 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp] @@ -203,10 +220,15 @@ static const uint8_t ThunkX64[] = { 0xFF, 0xE0, // jmp rax }; -static const uint8_t ThunkX86[] = { +static const uint8_t thunkX86[] = { + 0xB8, 0, 0, 0, 0, // mov eax, offset ___imp__ + 0xE9, 0, 0, 0, 0, // jmp __tailMerge_ +}; + +static const uint8_t tailMergeX86[] = { 0x51, // push ecx 0x52, // push edx - 0x68, 0, 0, 0, 0, // push offset ___imp__ + 0x50, // push eax 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR__dll 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8 0x5A, // pop edx @@ -214,9 +236,13 @@ static const uint8_t ThunkX86[] = { 0xFF, 0xE0, // jmp eax }; -static const uint8_t ThunkARM[] = { +static const uint8_t thunkARM[] = { 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_ 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_ + 0x00, 0xf0, 0x00, 0xb8, // b.w __tailMerge_ +}; + +static const uint8_t tailMergeARM[] = { 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr} 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7} @@ -230,9 +256,13 @@ static const uint8_t ThunkARM[] = { 0x60, 0x47, // bx ip }; -static const uint8_t ThunkARM64[] = { +static const uint8_t thunkARM64[] = { 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_ 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_ + 0x00, 0x00, 0x00, 0x14, // b __tailMerge_ +}; + +static const uint8_t tailMergeARM64[] = { 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]! 0xfd, 0x03, 0x00, 0x91, // mov x29, sp 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16] @@ -261,370 +291,445 @@ static const uint8_t ThunkARM64[] = { }; // A chunk for the delay import thunk. -class ThunkChunkX64 : public Chunk { +class ThunkChunkX64 : public NonSectionChunk { +public: + ThunkChunkX64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {} + + size_t getSize() const override { return sizeof(thunkX64); } + + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkX64, sizeof(thunkX64)); + write32le(buf + 3, imp->getRVA() - rva - 7); + write32le(buf + 8, tailMerge->getRVA() - rva - 12); + } + + Defined *imp = nullptr; + Chunk *tailMerge = nullptr; +}; + +class TailMergeChunkX64 : public NonSectionChunk { +public: + TailMergeChunkX64(Chunk *d, Defined *h) : desc(d), helper(h) {} + + size_t getSize() const override { return sizeof(tailMergeX64); } + + void writeTo(uint8_t *buf) const override { + memcpy(buf, tailMergeX64, sizeof(tailMergeX64)); + write32le(buf + 39, desc->getRVA() - rva - 43); + write32le(buf + 44, helper->getRVA() - rva - 48); + } + + Chunk *desc = nullptr; + Defined *helper = nullptr; +}; + +class ThunkChunkX86 : public NonSectionChunk { +public: + ThunkChunkX86(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {} + + size_t getSize() const override { return sizeof(thunkX86); } + + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkX86, sizeof(thunkX86)); + write32le(buf + 1, imp->getRVA() + config->imageBase); + write32le(buf + 6, tailMerge->getRVA() - rva - 10); + } + + void getBaserels(std::vector *res) override { + res->emplace_back(rva + 1); + } + + Defined *imp = nullptr; + Chunk *tailMerge = nullptr; +}; + +class TailMergeChunkX86 : public NonSectionChunk { public: - ThunkChunkX64(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + TailMergeChunkX86(Chunk *d, Defined *h) : desc(d), helper(h) {} - size_t getSize() const override { return sizeof(ThunkX64); } + size_t getSize() const override { return sizeof(tailMergeX86); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64)); - write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40); - write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47); - write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52); + void writeTo(uint8_t *buf) const override { + memcpy(buf, tailMergeX86, sizeof(tailMergeX86)); + write32le(buf + 4, desc->getRVA() + config->imageBase); + write32le(buf + 9, helper->getRVA() - rva - 13); } - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + void getBaserels(std::vector *res) override { + res->emplace_back(rva + 4); + } + + Chunk *desc = nullptr; + Defined *helper = nullptr; }; -class ThunkChunkX86 : public Chunk { +class ThunkChunkARM : public NonSectionChunk { public: - ThunkChunkX86(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + ThunkChunkARM(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {} - size_t getSize() const override { return sizeof(ThunkX86); } + size_t getSize() const override { return sizeof(thunkARM); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86)); - write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase); - write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase); - write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17); + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkARM, sizeof(thunkARM)); + applyMOV32T(buf + 0, imp->getRVA() + config->imageBase); + applyBranch24T(buf + 8, tailMerge->getRVA() - rva - 12); } - void getBaserels(std::vector *Res) override { - Res->emplace_back(RVA + 3); - Res->emplace_back(RVA + 8); + void getBaserels(std::vector *res) override { + res->emplace_back(rva + 0, IMAGE_REL_BASED_ARM_MOV32T); } - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + Defined *imp = nullptr; + Chunk *tailMerge = nullptr; }; -class ThunkChunkARM : public Chunk { +class TailMergeChunkARM : public NonSectionChunk { public: - ThunkChunkARM(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + TailMergeChunkARM(Chunk *d, Defined *h) : desc(d), helper(h) {} - size_t getSize() const override { return sizeof(ThunkARM); } + size_t getSize() const override { return sizeof(tailMergeARM); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM)); - applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase); - applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase); - applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34); + void writeTo(uint8_t *buf) const override { + memcpy(buf, tailMergeARM, sizeof(tailMergeARM)); + applyMOV32T(buf + 14, desc->getRVA() + config->imageBase); + applyBranch24T(buf + 22, helper->getRVA() - rva - 26); } - void getBaserels(std::vector *Res) override { - Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T); - Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T); + void getBaserels(std::vector *res) override { + res->emplace_back(rva + 14, IMAGE_REL_BASED_ARM_MOV32T); } - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + Chunk *desc = nullptr; + Defined *helper = nullptr; }; -class ThunkChunkARM64 : public Chunk { +class ThunkChunkARM64 : public NonSectionChunk { public: - ThunkChunkARM64(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + ThunkChunkARM64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {} - size_t getSize() const override { return sizeof(ThunkARM64); } + size_t getSize() const override { return sizeof(thunkARM64); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkARM64, sizeof(ThunkARM64)); - applyArm64Addr(Buf + OutputSectionOff + 0, Imp->getRVA(), RVA + 0, 12); - applyArm64Imm(Buf + OutputSectionOff + 4, Imp->getRVA() & 0xfff, 0); - applyArm64Addr(Buf + OutputSectionOff + 52, Desc->getRVA(), RVA + 52, 12); - applyArm64Imm(Buf + OutputSectionOff + 56, Desc->getRVA() & 0xfff, 0); - applyArm64Branch26(Buf + OutputSectionOff + 60, - Helper->getRVA() - RVA - 60); + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkARM64, sizeof(thunkARM64)); + applyArm64Addr(buf + 0, imp->getRVA(), rva + 0, 12); + applyArm64Imm(buf + 4, imp->getRVA() & 0xfff, 0); + applyArm64Branch26(buf + 8, tailMerge->getRVA() - rva - 8); } - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + Defined *imp = nullptr; + Chunk *tailMerge = nullptr; +}; + +class TailMergeChunkARM64 : public NonSectionChunk { +public: + TailMergeChunkARM64(Chunk *d, Defined *h) : desc(d), helper(h) {} + + size_t getSize() const override { return sizeof(tailMergeARM64); } + + void writeTo(uint8_t *buf) const override { + memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64)); + applyArm64Addr(buf + 44, desc->getRVA(), rva + 44, 12); + applyArm64Imm(buf + 48, desc->getRVA() & 0xfff, 0); + applyArm64Branch26(buf + 52, helper->getRVA() - rva - 52); + } + + Chunk *desc = nullptr; + Defined *helper = nullptr; }; // A chunk for the import descriptor table. -class DelayAddressChunk : public Chunk { +class DelayAddressChunk : public NonSectionChunk { public: - explicit DelayAddressChunk(Chunk *C) : Thunk(C) { - Alignment = Config->Wordsize; + explicit DelayAddressChunk(Chunk *c) : thunk(c) { + setAlignment(config->wordsize); } - size_t getSize() const override { return Config->Wordsize; } + size_t getSize() const override { return config->wordsize; } - void writeTo(uint8_t *Buf) const override { - if (Config->is64()) { - write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); + void writeTo(uint8_t *buf) const override { + if (config->is64()) { + write64le(buf, thunk->getRVA() + config->imageBase); } else { - uint32_t Bit = 0; + uint32_t bit = 0; // Pointer to thumb code must have the LSB set, so adjust it. - if (Config->Machine == ARMNT) - Bit = 1; - write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit); + if (config->machine == ARMNT) + bit = 1; + write32le(buf, (thunk->getRVA() + config->imageBase) | bit); } } - void getBaserels(std::vector *Res) override { - Res->emplace_back(RVA); + void getBaserels(std::vector *res) override { + res->emplace_back(rva); } - Chunk *Thunk; + Chunk *thunk; }; // Export table // Read Microsoft PE/COFF spec 5.3 for details. // A chunk for the export descriptor table. -class ExportDirectoryChunk : public Chunk { +class ExportDirectoryChunk : public NonSectionChunk { public: - ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O) - : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N), - OrdinalTab(O) {} + ExportDirectoryChunk(int i, int j, Chunk *d, Chunk *a, Chunk *n, Chunk *o) + : maxOrdinal(i), nameTabSize(j), dllName(d), addressTab(a), nameTab(n), + ordinalTab(o) {} size_t getSize() const override { return sizeof(export_directory_table_entry); } - void writeTo(uint8_t *Buf) const override { - auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff); - E->NameRVA = DLLName->getRVA(); - E->OrdinalBase = 0; - E->AddressTableEntries = MaxOrdinal + 1; - E->NumberOfNamePointers = NameTabSize; - E->ExportAddressTableRVA = AddressTab->getRVA(); - E->NamePointerRVA = NameTab->getRVA(); - E->OrdinalTableRVA = OrdinalTab->getRVA(); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); + + auto *e = (export_directory_table_entry *)(buf); + e->NameRVA = dllName->getRVA(); + e->OrdinalBase = 0; + e->AddressTableEntries = maxOrdinal + 1; + e->NumberOfNamePointers = nameTabSize; + e->ExportAddressTableRVA = addressTab->getRVA(); + e->NamePointerRVA = nameTab->getRVA(); + e->OrdinalTableRVA = ordinalTab->getRVA(); } - uint16_t MaxOrdinal; - uint16_t NameTabSize; - Chunk *DLLName; - Chunk *AddressTab; - Chunk *NameTab; - Chunk *OrdinalTab; + uint16_t maxOrdinal; + uint16_t nameTabSize; + Chunk *dllName; + Chunk *addressTab; + Chunk *nameTab; + Chunk *ordinalTab; }; -class AddressTableChunk : public Chunk { +class AddressTableChunk : public NonSectionChunk { public: - explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {} - size_t getSize() const override { return Size * 4; } + explicit AddressTableChunk(size_t maxOrdinal) : size(maxOrdinal + 1) {} + size_t getSize() const override { return size * 4; } - void writeTo(uint8_t *Buf) const override { - memset(Buf + OutputSectionOff, 0, getSize()); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); - for (const Export &E : Config->Exports) { - uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4; - uint32_t Bit = 0; + for (const Export &e : config->exports) { + uint8_t *p = buf + e.ordinal * 4; + uint32_t bit = 0; // Pointer to thumb code must have the LSB set, so adjust it. - if (Config->Machine == ARMNT && !E.Data) - Bit = 1; - if (E.ForwardChunk) { - write32le(P, E.ForwardChunk->getRVA() | Bit); + if (config->machine == ARMNT && !e.data) + bit = 1; + if (e.forwardChunk) { + write32le(p, e.forwardChunk->getRVA() | bit); } else { - write32le(P, cast(E.Sym)->getRVA() | Bit); + write32le(p, cast(e.sym)->getRVA() | bit); } } } private: - size_t Size; + size_t size; }; -class NamePointersChunk : public Chunk { +class NamePointersChunk : public NonSectionChunk { public: - explicit NamePointersChunk(std::vector &V) : Chunks(V) {} - size_t getSize() const override { return Chunks.size() * 4; } - - void writeTo(uint8_t *Buf) const override { - uint8_t *P = Buf + OutputSectionOff; - for (Chunk *C : Chunks) { - write32le(P, C->getRVA()); - P += 4; + explicit NamePointersChunk(std::vector &v) : chunks(v) {} + size_t getSize() const override { return chunks.size() * 4; } + + void writeTo(uint8_t *buf) const override { + for (Chunk *c : chunks) { + write32le(buf, c->getRVA()); + buf += 4; } } private: - std::vector Chunks; + std::vector chunks; }; -class ExportOrdinalChunk : public Chunk { +class ExportOrdinalChunk : public NonSectionChunk { public: - explicit ExportOrdinalChunk(size_t I) : Size(I) {} - size_t getSize() const override { return Size * 2; } + explicit ExportOrdinalChunk(size_t i) : size(i) {} + size_t getSize() const override { return size * 2; } - void writeTo(uint8_t *Buf) const override { - uint8_t *P = Buf + OutputSectionOff; - for (Export &E : Config->Exports) { - if (E.Noname) + void writeTo(uint8_t *buf) const override { + for (Export &e : config->exports) { + if (e.noname) continue; - write16le(P, E.Ordinal); - P += 2; + write16le(buf, e.ordinal); + buf += 2; } } private: - size_t Size; + size_t size; }; } // anonymous namespace void IdataContents::create() { - std::vector> V = binImports(Imports); + std::vector> v = binImports(imports); // Create .idata contents for each DLL. - for (std::vector &Syms : V) { + for (std::vector &syms : v) { // Create lookup and address tables. If they have external names, - // we need to create HintName chunks to store the names. + // we need to create hintName chunks to store the names. // If they don't (if they are import-by-ordinals), we store only // ordinal values to the table. - size_t Base = Lookups.size(); - for (DefinedImportData *S : Syms) { - uint16_t Ord = S->getOrdinal(); - if (S->getExternalName().empty()) { - Lookups.push_back(make(Ord)); - Addresses.push_back(make(Ord)); + size_t base = lookups.size(); + for (DefinedImportData *s : syms) { + uint16_t ord = s->getOrdinal(); + if (s->getExternalName().empty()) { + lookups.push_back(make(ord)); + addresses.push_back(make(ord)); continue; } - auto *C = make(S->getExternalName(), Ord); - Lookups.push_back(make(C)); - Addresses.push_back(make(C)); - Hints.push_back(C); + auto *c = make(s->getExternalName(), ord); + lookups.push_back(make(c)); + addresses.push_back(make(c)); + hints.push_back(c); } // Terminate with null values. - Lookups.push_back(make(Config->Wordsize)); - Addresses.push_back(make(Config->Wordsize)); + lookups.push_back(make(config->wordsize)); + addresses.push_back(make(config->wordsize)); - for (int I = 0, E = Syms.size(); I < E; ++I) - Syms[I]->setLocation(Addresses[Base + I]); + for (int i = 0, e = syms.size(); i < e; ++i) + syms[i]->setLocation(addresses[base + i]); // Create the import table header. - DLLNames.push_back(make(Syms[0]->getDLLName())); - auto *Dir = make(DLLNames.back()); - Dir->LookupTab = Lookups[Base]; - Dir->AddressTab = Addresses[Base]; - Dirs.push_back(Dir); + dllNames.push_back(make(syms[0]->getDLLName())); + auto *dir = make(dllNames.back()); + dir->lookupTab = lookups[base]; + dir->addressTab = addresses[base]; + dirs.push_back(dir); } // Add null terminator. - Dirs.push_back(make(sizeof(ImportDirectoryTableEntry))); + dirs.push_back(make(sizeof(ImportDirectoryTableEntry))); } std::vector DelayLoadContents::getChunks() { - std::vector V; - V.insert(V.end(), Dirs.begin(), Dirs.end()); - V.insert(V.end(), Names.begin(), Names.end()); - V.insert(V.end(), HintNames.begin(), HintNames.end()); - V.insert(V.end(), DLLNames.begin(), DLLNames.end()); - return V; + std::vector v; + v.insert(v.end(), dirs.begin(), dirs.end()); + v.insert(v.end(), names.begin(), names.end()); + v.insert(v.end(), hintNames.begin(), hintNames.end()); + v.insert(v.end(), dllNames.begin(), dllNames.end()); + return v; } std::vector DelayLoadContents::getDataChunks() { - std::vector V; - V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end()); - V.insert(V.end(), Addresses.begin(), Addresses.end()); - return V; + std::vector v; + v.insert(v.end(), moduleHandles.begin(), moduleHandles.end()); + v.insert(v.end(), addresses.begin(), addresses.end()); + return v; } uint64_t DelayLoadContents::getDirSize() { - return Dirs.size() * sizeof(delay_import_directory_table_entry); + return dirs.size() * sizeof(delay_import_directory_table_entry); } -void DelayLoadContents::create(Defined *H) { - Helper = H; - std::vector> V = binImports(Imports); +void DelayLoadContents::create(Defined *h) { + helper = h; + std::vector> v = binImports(imports); // Create .didat contents for each DLL. - for (std::vector &Syms : V) { + for (std::vector &syms : v) { // Create the delay import table header. - DLLNames.push_back(make(Syms[0]->getDLLName())); - auto *Dir = make(DLLNames.back()); - - size_t Base = Addresses.size(); - for (DefinedImportData *S : Syms) { - Chunk *T = newThunkChunk(S, Dir); - auto *A = make(T); - Addresses.push_back(A); - Thunks.push_back(T); - StringRef ExtName = S->getExternalName(); - if (ExtName.empty()) { - Names.push_back(make(S->getOrdinal())); + dllNames.push_back(make(syms[0]->getDLLName())); + auto *dir = make(dllNames.back()); + + size_t base = addresses.size(); + Chunk *tm = newTailMergeChunk(dir); + for (DefinedImportData *s : syms) { + Chunk *t = newThunkChunk(s, tm); + auto *a = make(t); + addresses.push_back(a); + thunks.push_back(t); + StringRef extName = s->getExternalName(); + if (extName.empty()) { + names.push_back(make(s->getOrdinal())); } else { - auto *C = make(ExtName, 0); - Names.push_back(make(C)); - HintNames.push_back(C); + auto *c = make(extName, 0); + names.push_back(make(c)); + hintNames.push_back(c); } } + thunks.push_back(tm); // Terminate with null values. - Addresses.push_back(make(8)); - Names.push_back(make(8)); + addresses.push_back(make(8)); + names.push_back(make(8)); - for (int I = 0, E = Syms.size(); I < E; ++I) - Syms[I]->setLocation(Addresses[Base + I]); - auto *MH = make(8); - MH->Alignment = 8; - ModuleHandles.push_back(MH); + for (int i = 0, e = syms.size(); i < e; ++i) + syms[i]->setLocation(addresses[base + i]); + auto *mh = make(8); + mh->setAlignment(8); + moduleHandles.push_back(mh); // Fill the delay import table header fields. - Dir->ModuleHandle = MH; - Dir->AddressTab = Addresses[Base]; - Dir->NameTab = Names[Base]; - Dirs.push_back(Dir); + dir->moduleHandle = mh; + dir->addressTab = addresses[base]; + dir->nameTab = names[base]; + dirs.push_back(dir); } // Add null terminator. - Dirs.push_back(make(sizeof(delay_import_directory_table_entry))); + dirs.push_back(make(sizeof(delay_import_directory_table_entry))); +} + +Chunk *DelayLoadContents::newTailMergeChunk(Chunk *dir) { + switch (config->machine) { + case AMD64: + return make(dir, helper); + case I386: + return make(dir, helper); + case ARMNT: + return make(dir, helper); + case ARM64: + return make(dir, helper); + default: + llvm_unreachable("unsupported machine type"); + } } -Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { - switch (Config->Machine) { +Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *s, + Chunk *tailMerge) { + switch (config->machine) { case AMD64: - return make(S, Dir, Helper); + return make(s, tailMerge); case I386: - return make(S, Dir, Helper); + return make(s, tailMerge); case ARMNT: - return make(S, Dir, Helper); + return make(s, tailMerge); case ARM64: - return make(S, Dir, Helper); + return make(s, tailMerge); default: llvm_unreachable("unsupported machine type"); } } EdataContents::EdataContents() { - uint16_t MaxOrdinal = 0; - for (Export &E : Config->Exports) - MaxOrdinal = std::max(MaxOrdinal, E.Ordinal); - - auto *DLLName = make(sys::path::filename(Config->OutputFile)); - auto *AddressTab = make(MaxOrdinal); - std::vector Names; - for (Export &E : Config->Exports) - if (!E.Noname) - Names.push_back(make(E.ExportName)); - - std::vector Forwards; - for (Export &E : Config->Exports) { - if (E.ForwardTo.empty()) + uint16_t maxOrdinal = 0; + for (Export &e : config->exports) + maxOrdinal = std::max(maxOrdinal, e.ordinal); + + auto *dllName = make(sys::path::filename(config->outputFile)); + auto *addressTab = make(maxOrdinal); + std::vector names; + for (Export &e : config->exports) + if (!e.noname) + names.push_back(make(e.exportName)); + + std::vector forwards; + for (Export &e : config->exports) { + if (e.forwardTo.empty()) continue; - E.ForwardChunk = make(E.ForwardTo); - Forwards.push_back(E.ForwardChunk); - } - - auto *NameTab = make(Names); - auto *OrdinalTab = make(Names.size()); - auto *Dir = make(MaxOrdinal, Names.size(), DLLName, - AddressTab, NameTab, OrdinalTab); - Chunks.push_back(Dir); - Chunks.push_back(DLLName); - Chunks.push_back(AddressTab); - Chunks.push_back(NameTab); - Chunks.push_back(OrdinalTab); - Chunks.insert(Chunks.end(), Names.begin(), Names.end()); - Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end()); + e.forwardChunk = make(e.forwardTo); + forwards.push_back(e.forwardChunk); + } + + auto *nameTab = make(names); + auto *ordinalTab = make(names.size()); + auto *dir = make(maxOrdinal, names.size(), dllName, + addressTab, nameTab, ordinalTab); + chunks.push_back(dir); + chunks.push_back(dllName); + chunks.push_back(addressTab); + chunks.push_back(nameTab); + chunks.push_back(ordinalTab); + chunks.insert(chunks.end(), names.begin(), names.end()); + chunks.insert(chunks.end(), forwards.begin(), forwards.end()); } } // namespace coff -- cgit v1.2.3