aboutsummaryrefslogtreecommitdiffstats
path: root/COFF/DLL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'COFF/DLL.cpp')
-rw-r--r--COFF/DLL.cpp703
1 files changed, 404 insertions, 299 deletions
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<std::vector<DefinedImportData *>>
-binImports(const std::vector<DefinedImportData *> &Imports) {
+binImports(const std::vector<DefinedImportData *> &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<std::string, std::vector<DefinedImportData *>,
- 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<std::vector<DefinedImportData *>> V;
- for (auto &KV : M) {
+ std::vector<std::vector<DefinedImportData *>> v;
+ for (auto &kv : m) {
// Sort symbols by name for each group.
- std::vector<DefinedImportData *> &Syms = KV.second;
- std::sort(Syms.begin(), Syms.end(),
- [](DefinedImportData *A, DefinedImportData *B) {
- return A->getName() < B->getName();
+ std::vector<DefinedImportData *> &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_<FUNCNAME>]
+ 0xE9, 0, 0, 0, 0, // jmp __tailMerge_<lib>
+};
+
+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_<FUNCNAME>]
+ 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__<FUNCNAME>
+ 0xE9, 0, 0, 0, 0, // jmp __tailMerge_<lib>
+};
+
+static const uint8_t tailMergeX86[] = {
0x51, // push ecx
0x52, // push edx
- 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
+ 0x50, // push eax
0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_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_<FUNCNAME>
0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME>
+ 0x00, 0xf0, 0x00, 0xb8, // b.w __tailMerge_<lib>
+};
+
+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_<FUNCNAME>
0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_<FUNCNAME>
+ 0x00, 0x00, 0x00, 0x14, // b __tailMerge_<lib>
+};
+
+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<Baserel> *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<Baserel> *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<Baserel> *Res) override {
- Res->emplace_back(RVA + 3);
- Res->emplace_back(RVA + 8);
+ void getBaserels(std::vector<Baserel> *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<Baserel> *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<Baserel> *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<Baserel> *Res) override {
- Res->emplace_back(RVA);
+ void getBaserels(std::vector<Baserel> *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<Defined>(E.Sym)->getRVA() | Bit);
+ write32le(p, cast<Defined>(e.sym)->getRVA() | bit);
}
}
}
private:
- size_t Size;
+ size_t size;
};
-class NamePointersChunk : public Chunk {
+class NamePointersChunk : public NonSectionChunk {
public:
- explicit NamePointersChunk(std::vector<Chunk *> &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<Chunk *> &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<Chunk *> Chunks;
+ std::vector<Chunk *> 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<std::vector<DefinedImportData *>> V = binImports(Imports);
+ std::vector<std::vector<DefinedImportData *>> v = binImports(imports);
// Create .idata contents for each DLL.
- for (std::vector<DefinedImportData *> &Syms : V) {
+ for (std::vector<DefinedImportData *> &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<OrdinalOnlyChunk>(Ord));
- Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
+ size_t base = lookups.size();
+ for (DefinedImportData *s : syms) {
+ uint16_t ord = s->getOrdinal();
+ if (s->getExternalName().empty()) {
+ lookups.push_back(make<OrdinalOnlyChunk>(ord));
+ addresses.push_back(make<OrdinalOnlyChunk>(ord));
continue;
}
- auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
- Lookups.push_back(make<LookupChunk>(C));
- Addresses.push_back(make<LookupChunk>(C));
- Hints.push_back(C);
+ auto *c = make<HintNameChunk>(s->getExternalName(), ord);
+ lookups.push_back(make<LookupChunk>(c));
+ addresses.push_back(make<LookupChunk>(c));
+ hints.push_back(c);
}
// Terminate with null values.
- Lookups.push_back(make<NullChunk>(Config->Wordsize));
- Addresses.push_back(make<NullChunk>(Config->Wordsize));
+ lookups.push_back(make<NullChunk>(config->wordsize));
+ addresses.push_back(make<NullChunk>(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<StringChunk>(Syms[0]->getDLLName()));
- auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
- Dir->LookupTab = Lookups[Base];
- Dir->AddressTab = Addresses[Base];
- Dirs.push_back(Dir);
+ dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
+ auto *dir = make<ImportDirectoryChunk>(dllNames.back());
+ dir->lookupTab = lookups[base];
+ dir->addressTab = addresses[base];
+ dirs.push_back(dir);
}
// Add null terminator.
- Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
+ dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
}
std::vector<Chunk *> DelayLoadContents::getChunks() {
- std::vector<Chunk *> 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<Chunk *> 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<Chunk *> DelayLoadContents::getDataChunks() {
- std::vector<Chunk *> V;
- V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
- V.insert(V.end(), Addresses.begin(), Addresses.end());
- return V;
+ std::vector<Chunk *> 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<std::vector<DefinedImportData *>> V = binImports(Imports);
+void DelayLoadContents::create(Defined *h) {
+ helper = h;
+ std::vector<std::vector<DefinedImportData *>> v = binImports(imports);
// Create .didat contents for each DLL.
- for (std::vector<DefinedImportData *> &Syms : V) {
+ for (std::vector<DefinedImportData *> &syms : v) {
// Create the delay import table header.
- DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
- auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
-
- size_t Base = Addresses.size();
- for (DefinedImportData *S : Syms) {
- Chunk *T = newThunkChunk(S, Dir);
- auto *A = make<DelayAddressChunk>(T);
- Addresses.push_back(A);
- Thunks.push_back(T);
- StringRef ExtName = S->getExternalName();
- if (ExtName.empty()) {
- Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
+ dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
+ auto *dir = make<DelayDirectoryChunk>(dllNames.back());
+
+ size_t base = addresses.size();
+ Chunk *tm = newTailMergeChunk(dir);
+ for (DefinedImportData *s : syms) {
+ Chunk *t = newThunkChunk(s, tm);
+ auto *a = make<DelayAddressChunk>(t);
+ addresses.push_back(a);
+ thunks.push_back(t);
+ StringRef extName = s->getExternalName();
+ if (extName.empty()) {
+ names.push_back(make<OrdinalOnlyChunk>(s->getOrdinal()));
} else {
- auto *C = make<HintNameChunk>(ExtName, 0);
- Names.push_back(make<LookupChunk>(C));
- HintNames.push_back(C);
+ auto *c = make<HintNameChunk>(extName, 0);
+ names.push_back(make<LookupChunk>(c));
+ hintNames.push_back(c);
}
}
+ thunks.push_back(tm);
// Terminate with null values.
- Addresses.push_back(make<NullChunk>(8));
- Names.push_back(make<NullChunk>(8));
+ addresses.push_back(make<NullChunk>(8));
+ names.push_back(make<NullChunk>(8));
- for (int I = 0, E = Syms.size(); I < E; ++I)
- Syms[I]->setLocation(Addresses[Base + I]);
- auto *MH = make<NullChunk>(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<NullChunk>(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<NullChunk>(sizeof(delay_import_directory_table_entry)));
+ dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
+}
+
+Chunk *DelayLoadContents::newTailMergeChunk(Chunk *dir) {
+ switch (config->machine) {
+ case AMD64:
+ return make<TailMergeChunkX64>(dir, helper);
+ case I386:
+ return make<TailMergeChunkX86>(dir, helper);
+ case ARMNT:
+ return make<TailMergeChunkARM>(dir, helper);
+ case ARM64:
+ return make<TailMergeChunkARM64>(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<ThunkChunkX64>(S, Dir, Helper);
+ return make<ThunkChunkX64>(s, tailMerge);
case I386:
- return make<ThunkChunkX86>(S, Dir, Helper);
+ return make<ThunkChunkX86>(s, tailMerge);
case ARMNT:
- return make<ThunkChunkARM>(S, Dir, Helper);
+ return make<ThunkChunkARM>(s, tailMerge);
case ARM64:
- return make<ThunkChunkARM64>(S, Dir, Helper);
+ return make<ThunkChunkARM64>(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<StringChunk>(sys::path::filename(Config->OutputFile));
- auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
- std::vector<Chunk *> Names;
- for (Export &E : Config->Exports)
- if (!E.Noname)
- Names.push_back(make<StringChunk>(E.ExportName));
-
- std::vector<Chunk *> 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<StringChunk>(sys::path::filename(config->outputFile));
+ auto *addressTab = make<AddressTableChunk>(maxOrdinal);
+ std::vector<Chunk *> names;
+ for (Export &e : config->exports)
+ if (!e.noname)
+ names.push_back(make<StringChunk>(e.exportName));
+
+ std::vector<Chunk *> forwards;
+ for (Export &e : config->exports) {
+ if (e.forwardTo.empty())
continue;
- E.ForwardChunk = make<StringChunk>(E.ForwardTo);
- Forwards.push_back(E.ForwardChunk);
- }
-
- auto *NameTab = make<NamePointersChunk>(Names);
- auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
- auto *Dir = make<ExportDirectoryChunk>(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<StringChunk>(e.forwardTo);
+ forwards.push_back(e.forwardChunk);
+ }
+
+ auto *nameTab = make<NamePointersChunk>(names);
+ auto *ordinalTab = make<ExportOrdinalChunk>(names.size());
+ auto *dir = make<ExportDirectoryChunk>(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