blob: 168590f9a235b7409482881dc2be95f3592c576f [file] [log] [blame]
Rui Ueyama4b22fa72015-06-07 01:15:04 +00001//===- DLL.cpp ------------------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Rui Ueyamaa77336b2015-06-21 22:31:52 +000010// This file defines various types of chunks for the DLL import or export
11// descriptor tables. They are inherently Windows-specific.
Rui Ueyama4b22fa72015-06-07 01:15:04 +000012// You need to read Microsoft PE/COFF spec to understand details
13// about the data structures.
14//
15// If you are not particularly interested in linking against Windows
16// DLL, you can skip this file, and you should still be able to
17// understand the rest of the linker.
18//
19//===----------------------------------------------------------------------===//
20
21#include "Chunks.h"
22#include "DLL.h"
Rui Ueyama4b22fa72015-06-07 01:15:04 +000023#include "llvm/Object/COFF.h"
24#include "llvm/Support/Endian.h"
Rui Ueyama97dff9e2015-06-17 00:16:33 +000025#include "llvm/Support/Path.h"
Rui Ueyama4b22fa72015-06-07 01:15:04 +000026
27using namespace llvm;
28using namespace llvm::object;
29using namespace llvm::support::endian;
30using namespace llvm::COFF;
Rui Ueyama4b22fa72015-06-07 01:15:04 +000031
Rui Ueyama4b22fa72015-06-07 01:15:04 +000032namespace lld {
33namespace coff {
Rui Ueyama857b3032015-08-10 23:02:57 +000034namespace {
Rui Ueyama4b22fa72015-06-07 01:15:04 +000035
Rui Ueyama97dff9e2015-06-17 00:16:33 +000036// Import table
37
Rui Ueyama25522f52015-07-09 00:45:50 +000038static int ptrSize() { return Config->is64() ? 8 : 4; }
39
Rui Ueyama4b22fa72015-06-07 01:15:04 +000040// A chunk for the import descriptor table.
41class HintNameChunk : public Chunk {
42public:
43 HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
44
45 size_t getSize() const override {
46 // Starts with 2 byte Hint field, followed by a null-terminated string,
47 // ends with 0 or 1 byte padding.
Rui Ueyama489a8062016-01-14 20:53:50 +000048 return alignTo(Name.size() + 3, 2);
Rui Ueyama4b22fa72015-06-07 01:15:04 +000049 }
50
Rui Ueyama63bbe842015-09-19 23:28:57 +000051 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +000052 write16le(Buf + OutputSectionOff, Hint);
53 memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
Rui Ueyama4b22fa72015-06-07 01:15:04 +000054 }
55
56private:
57 StringRef Name;
58 uint16_t Hint;
59};
60
61// A chunk for the import descriptor table.
62class LookupChunk : public Chunk {
63public:
Martin Storsjob3c97b92017-07-20 05:49:54 +000064 explicit LookupChunk(Chunk *C) : HintName(C) { Align = ptrSize(); }
Rui Ueyama25522f52015-07-09 00:45:50 +000065 size_t getSize() const override { return ptrSize(); }
Rui Ueyama4b22fa72015-06-07 01:15:04 +000066
Rui Ueyama63bbe842015-09-19 23:28:57 +000067 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +000068 write32le(Buf + OutputSectionOff, HintName->getRVA());
Rui Ueyama4b22fa72015-06-07 01:15:04 +000069 }
70
71 Chunk *HintName;
72};
73
74// A chunk for the import descriptor table.
75// This chunk represent import-by-ordinal symbols.
76// See Microsoft PE/COFF spec 7.1. Import Header for details.
77class OrdinalOnlyChunk : public Chunk {
78public:
Martin Storsjob3c97b92017-07-20 05:49:54 +000079 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { Align = ptrSize(); }
Rui Ueyama25522f52015-07-09 00:45:50 +000080 size_t getSize() const override { return ptrSize(); }
Rui Ueyama4b22fa72015-06-07 01:15:04 +000081
Rui Ueyama63bbe842015-09-19 23:28:57 +000082 void writeTo(uint8_t *Buf) const override {
Rui Ueyama4b22fa72015-06-07 01:15:04 +000083 // An import-by-ordinal slot has MSB 1 to indicate that
84 // this is import-by-ordinal (and not import-by-name).
Rui Ueyama25522f52015-07-09 00:45:50 +000085 if (Config->is64()) {
Rafael Espindola5c546a12015-08-14 03:30:59 +000086 write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);
Rui Ueyama25522f52015-07-09 00:45:50 +000087 } else {
Rafael Espindola5c546a12015-08-14 03:30:59 +000088 write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);
Rui Ueyama25522f52015-07-09 00:45:50 +000089 }
Rui Ueyama4b22fa72015-06-07 01:15:04 +000090 }
91
92 uint16_t Ordinal;
93};
94
95// A chunk for the import descriptor table.
Rui Ueyama97dff9e2015-06-17 00:16:33 +000096class ImportDirectoryChunk : public Chunk {
Rui Ueyama4b22fa72015-06-07 01:15:04 +000097public:
Rui Ueyama97dff9e2015-06-17 00:16:33 +000098 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
99 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000100
Rui Ueyama63bbe842015-09-19 23:28:57 +0000101 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000102 auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000103 E->ImportLookupTableRVA = LookupTab->getRVA();
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000104 E->NameRVA = DLLName->getRVA();
105 E->ImportAddressTableRVA = AddressTab->getRVA();
106 }
107
108 Chunk *DLLName;
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000109 Chunk *LookupTab;
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000110 Chunk *AddressTab;
111};
112
113// A chunk representing null terminator in the import table.
114// Contents of this chunk is always null bytes.
115class NullChunk : public Chunk {
116public:
117 explicit NullChunk(size_t N) : Size(N) {}
118 bool hasData() const override { return false; }
119 size_t getSize() const override { return Size; }
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000120 void setAlign(size_t N) { Align = N; }
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000121
122private:
123 size_t Size;
124};
125
Rui Ueyamad1570882015-08-17 08:30:31 +0000126static std::vector<std::vector<DefinedImportData *>>
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000127binImports(const std::vector<DefinedImportData *> &Imports) {
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000128 // Group DLL-imported symbols by DLL name because that's how
129 // symbols are layed out in the import descriptor table.
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000130 auto Less = [](const std::string &A, const std::string &B) {
Rui Ueyamad1570882015-08-17 08:30:31 +0000131 return Config->DLLOrder[A] < Config->DLLOrder[B];
132 };
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000133 std::map<std::string, std::vector<DefinedImportData *>,
134 bool(*)(const std::string &, const std::string &)> M(Less);
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000135 for (DefinedImportData *Sym : Imports)
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000136 M[Sym->getDLLName().lower()].push_back(Sym);
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000137
Rui Ueyamad1570882015-08-17 08:30:31 +0000138 std::vector<std::vector<DefinedImportData *>> V;
Rui Ueyama01f93332017-05-18 17:03:49 +0000139 for (auto &KV : M) {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000140 // Sort symbols by name for each group.
Rui Ueyama01f93332017-05-18 17:03:49 +0000141 std::vector<DefinedImportData *> &Syms = KV.second;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000142 std::sort(Syms.begin(), Syms.end(),
143 [](DefinedImportData *A, DefinedImportData *B) {
144 return A->getName() < B->getName();
145 });
Rui Ueyamad1570882015-08-17 08:30:31 +0000146 V.push_back(std::move(Syms));
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000147 }
Rui Ueyamad1570882015-08-17 08:30:31 +0000148 return V;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000149}
150
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000151// Export table
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000152// See Microsoft PE/COFF spec 4.3 for details.
153
154// A chunk for the delay import descriptor table etnry.
155class DelayDirectoryChunk : public Chunk {
156public:
157 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
158
159 size_t getSize() const override {
160 return sizeof(delay_import_directory_table_entry);
161 }
162
Rui Ueyama63bbe842015-09-19 23:28:57 +0000163 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000164 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
Rui Ueyama382dc962015-06-26 21:40:15 +0000165 E->Attributes = 1;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000166 E->Name = DLLName->getRVA();
167 E->ModuleHandle = ModuleHandle->getRVA();
168 E->DelayImportAddressTable = AddressTab->getRVA();
169 E->DelayImportNameTable = NameTab->getRVA();
170 }
171
172 Chunk *DLLName;
173 Chunk *ModuleHandle;
174 Chunk *AddressTab;
175 Chunk *NameTab;
176};
177
178// Initial contents for delay-loaded functions.
Rui Ueyama61096202015-06-22 17:26:27 +0000179// This code calls __delayLoadHelper2 function to resolve a symbol
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000180// and then overwrites its jump table slot with the result
181// for subsequent function calls.
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000182static const uint8_t ThunkX64[] = {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000183 0x51, // push rcx
184 0x52, // push rdx
185 0x41, 0x50, // push r8
186 0x41, 0x51, // push r9
187 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
188 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
189 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
190 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
191 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
192 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
193 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
194 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
195 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
196 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
197 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
198 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
199 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
200 0x41, 0x59, // pop r9
201 0x41, 0x58, // pop r8
202 0x5A, // pop rdx
203 0x59, // pop rcx
204 0xFF, 0xE0, // jmp rax
205};
206
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000207static const uint8_t ThunkX86[] = {
208 0x51, // push ecx
209 0x52, // push edx
210 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
211 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
212 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
213 0x5A, // pop edx
214 0x59, // pop ecx
215 0xFF, 0xE0, // jmp eax
216};
217
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000218static const uint8_t ThunkARM[] = {
219 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME>
220 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME>
221 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr}
222 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16
223 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7}
224 0x61, 0x46, // mov r1, ip
225 0x40, 0xf2, 0x00, 0x00, // mov.w r0, #0 DELAY_IMPORT_DESCRIPTOR
226 0xc0, 0xf2, 0x00, 0x00, // mov.t r0, #0 DELAY_IMPORT_DESCRIPTOR
227 0x00, 0xf0, 0x00, 0xd0, // bl #0 __delayLoadHelper2
228 0x84, 0x46, // mov ip, r0
229 0xbd, 0xec, 0x10, 0x0b, // vpop {d0, d1, d2, d3, d4, d5, d6, d7}
230 0xbd, 0xe8, 0x0f, 0x48, // pop.w {r0, r1, r2, r3, r11, lr}
231 0x60, 0x47, // bx ip
232};
233
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000234// A chunk for the delay import thunk.
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000235class ThunkChunkX64 : public Chunk {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000236public:
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000237 ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
238 : Imp(I), Desc(D), Helper(H) {}
239
240 size_t getSize() const override { return sizeof(ThunkX64); }
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000241
Rui Ueyama63bbe842015-09-19 23:28:57 +0000242 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000243 memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
244 write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
245 write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
246 write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000247 }
248
249 Defined *Imp = nullptr;
250 Chunk *Desc = nullptr;
251 Defined *Helper = nullptr;
252};
253
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000254class ThunkChunkX86 : public Chunk {
255public:
256 ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
257 : Imp(I), Desc(D), Helper(H) {}
258
259 size_t getSize() const override { return sizeof(ThunkX86); }
260
Rui Ueyama63bbe842015-09-19 23:28:57 +0000261 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000262 memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
263 write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
264 write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
265 write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000266 }
267
Rui Ueyama3afd5bf2015-07-25 01:44:32 +0000268 void getBaserels(std::vector<Baserel> *Res) override {
269 Res->emplace_back(RVA + 3);
270 Res->emplace_back(RVA + 8);
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000271 }
272
273 Defined *Imp = nullptr;
274 Chunk *Desc = nullptr;
275 Defined *Helper = nullptr;
276};
277
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000278class ThunkChunkARM : public Chunk {
279public:
280 ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
281 : Imp(I), Desc(D), Helper(H) {}
282
283 size_t getSize() const override { return sizeof(ThunkARM); }
284
285 void writeTo(uint8_t *Buf) const override {
286 memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM));
287 applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase);
288 applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase);
289 applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34);
290 }
291
292 void getBaserels(std::vector<Baserel> *Res) override {
293 Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
294 Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
295 }
296
297 Defined *Imp = nullptr;
298 Chunk *Desc = nullptr;
299 Defined *Helper = nullptr;
300};
301
Rui Ueyama382dc962015-06-26 21:40:15 +0000302// A chunk for the import descriptor table.
303class DelayAddressChunk : public Chunk {
304public:
Martin Storsjob3c97b92017-07-20 05:49:54 +0000305 explicit DelayAddressChunk(Chunk *C) : Thunk(C) { Align = ptrSize(); }
Rui Ueyama7e387a62015-07-28 02:54:18 +0000306 size_t getSize() const override { return ptrSize(); }
Rui Ueyama382dc962015-06-26 21:40:15 +0000307
Rui Ueyama63bbe842015-09-19 23:28:57 +0000308 void writeTo(uint8_t *Buf) const override {
Rui Ueyama7e387a62015-07-28 02:54:18 +0000309 if (Config->is64()) {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000310 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
Rui Ueyama7e387a62015-07-28 02:54:18 +0000311 } else {
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000312 uint32_t Bit = 0;
313 // Pointer to thumb code must have the LSB set, so adjust it.
314 if (Config->Machine == ARMNT)
315 Bit = 1;
316 write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit);
Rui Ueyama7e387a62015-07-28 02:54:18 +0000317 }
Rui Ueyama382dc962015-06-26 21:40:15 +0000318 }
319
Rui Ueyama3afd5bf2015-07-25 01:44:32 +0000320 void getBaserels(std::vector<Baserel> *Res) override {
321 Res->emplace_back(RVA);
Rui Ueyama810551a2015-06-26 22:05:32 +0000322 }
323
Rui Ueyama382dc962015-06-26 21:40:15 +0000324 Chunk *Thunk;
325};
326
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000327// Export table
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000328// Read Microsoft PE/COFF spec 5.3 for details.
329
330// A chunk for the export descriptor table.
331class ExportDirectoryChunk : public Chunk {
332public:
333 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
334 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
335 OrdinalTab(O) {}
336
337 size_t getSize() const override {
338 return sizeof(export_directory_table_entry);
339 }
340
Rui Ueyama63bbe842015-09-19 23:28:57 +0000341 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000342 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000343 E->NameRVA = DLLName->getRVA();
344 E->OrdinalBase = 0;
345 E->AddressTableEntries = MaxOrdinal + 1;
346 E->NumberOfNamePointers = NameTabSize;
347 E->ExportAddressTableRVA = AddressTab->getRVA();
348 E->NamePointerRVA = NameTab->getRVA();
349 E->OrdinalTableRVA = OrdinalTab->getRVA();
350 }
351
352 uint16_t MaxOrdinal;
353 uint16_t NameTabSize;
354 Chunk *DLLName;
355 Chunk *AddressTab;
356 Chunk *NameTab;
357 Chunk *OrdinalTab;
358};
359
360class AddressTableChunk : public Chunk {
361public:
362 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
363 size_t getSize() const override { return Size * 4; }
364
Rui Ueyama63bbe842015-09-19 23:28:57 +0000365 void writeTo(uint8_t *Buf) const override {
Martin Storsjo405b5bc2017-07-25 06:10:44 +0000366 uint32_t Bit = 0;
367 // Pointer to thumb code must have the LSB set, so adjust it.
368 if (Config->Machine == ARMNT)
369 Bit = 1;
Rui Ueyamaf5313b32015-06-28 22:16:41 +0000370 for (Export &E : Config->Exports) {
Rui Ueyama84425d72016-01-09 01:22:00 +0000371 uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
372 if (E.ForwardChunk) {
Martin Storsjo405b5bc2017-07-25 06:10:44 +0000373 write32le(P, E.ForwardChunk->getRVA() | Bit);
Rui Ueyama84425d72016-01-09 01:22:00 +0000374 } else {
Martin Storsjo405b5bc2017-07-25 06:10:44 +0000375 write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);
Rui Ueyama84425d72016-01-09 01:22:00 +0000376 }
Rui Ueyamaf5313b32015-06-28 22:16:41 +0000377 }
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000378 }
379
380private:
381 size_t Size;
382};
383
384class NamePointersChunk : public Chunk {
385public:
386 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
387 size_t getSize() const override { return Chunks.size() * 4; }
388
Rui Ueyama63bbe842015-09-19 23:28:57 +0000389 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000390 uint8_t *P = Buf + OutputSectionOff;
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000391 for (Chunk *C : Chunks) {
392 write32le(P, C->getRVA());
393 P += 4;
394 }
395 }
396
397private:
398 std::vector<Chunk *> Chunks;
399};
400
401class ExportOrdinalChunk : public Chunk {
402public:
403 explicit ExportOrdinalChunk(size_t I) : Size(I) {}
404 size_t getSize() const override { return Size * 2; }
405
Rui Ueyama63bbe842015-09-19 23:28:57 +0000406 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000407 uint8_t *P = Buf + OutputSectionOff;
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000408 for (Export &E : Config->Exports) {
409 if (E.Noname)
410 continue;
411 write16le(P, E.Ordinal);
412 P += 2;
413 }
414 }
415
416private:
417 size_t Size;
418};
419
Rui Ueyama857b3032015-08-10 23:02:57 +0000420} // anonymous namespace
421
422uint64_t IdataContents::getDirSize() {
423 return Dirs.size() * sizeof(ImportDirectoryTableEntry);
424}
425
426uint64_t IdataContents::getIATSize() {
427 return Addresses.size() * ptrSize();
428}
429
430// Returns a list of .idata contents.
431// See Microsoft PE/COFF spec 5.4 for details.
432std::vector<Chunk *> IdataContents::getChunks() {
433 create();
Rui Ueyama01f93332017-05-18 17:03:49 +0000434
Rui Ueyama857b3032015-08-10 23:02:57 +0000435 // The loader assumes a specific order of data.
436 // Add each type in the correct order.
Rui Ueyama01f93332017-05-18 17:03:49 +0000437 std::vector<Chunk *> V;
438 V.insert(V.end(), Dirs.begin(), Dirs.end());
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000439 V.insert(V.end(), Lookups.begin(), Lookups.end());
Rui Ueyama01f93332017-05-18 17:03:49 +0000440 V.insert(V.end(), Addresses.begin(), Addresses.end());
441 V.insert(V.end(), Hints.begin(), Hints.end());
Peter Collingbourne03638d02017-05-18 18:53:39 +0000442 V.insert(V.end(), DLLNames.begin(), DLLNames.end());
Rui Ueyama857b3032015-08-10 23:02:57 +0000443 return V;
444}
445
446void IdataContents::create() {
Rui Ueyamad1570882015-08-17 08:30:31 +0000447 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
Rui Ueyama857b3032015-08-10 23:02:57 +0000448
449 // Create .idata contents for each DLL.
Rui Ueyamad1570882015-08-17 08:30:31 +0000450 for (std::vector<DefinedImportData *> &Syms : V) {
Rui Ueyama857b3032015-08-10 23:02:57 +0000451 // Create lookup and address tables. If they have external names,
452 // we need to create HintName chunks to store the names.
453 // If they don't (if they are import-by-ordinals), we store only
454 // ordinal values to the table.
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000455 size_t Base = Lookups.size();
Rui Ueyama857b3032015-08-10 23:02:57 +0000456 for (DefinedImportData *S : Syms) {
457 uint16_t Ord = S->getOrdinal();
458 if (S->getExternalName().empty()) {
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000459 Lookups.push_back(make<OrdinalOnlyChunk>(Ord));
Rui Ueyama01f93332017-05-18 17:03:49 +0000460 Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
Rui Ueyama857b3032015-08-10 23:02:57 +0000461 continue;
462 }
Rui Ueyama01f93332017-05-18 17:03:49 +0000463 auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000464 Lookups.push_back(make<LookupChunk>(C));
Rui Ueyama01f93332017-05-18 17:03:49 +0000465 Addresses.push_back(make<LookupChunk>(C));
466 Hints.push_back(C);
Rui Ueyama857b3032015-08-10 23:02:57 +0000467 }
468 // Terminate with null values.
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000469 Lookups.push_back(make<NullChunk>(ptrSize()));
Rui Ueyama01f93332017-05-18 17:03:49 +0000470 Addresses.push_back(make<NullChunk>(ptrSize()));
Rui Ueyama857b3032015-08-10 23:02:57 +0000471
472 for (int I = 0, E = Syms.size(); I < E; ++I)
Rui Ueyama01f93332017-05-18 17:03:49 +0000473 Syms[I]->setLocation(Addresses[Base + I]);
Rui Ueyama857b3032015-08-10 23:02:57 +0000474
475 // Create the import table header.
Peter Collingbourne03638d02017-05-18 18:53:39 +0000476 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
477 auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000478 Dir->LookupTab = Lookups[Base];
Rui Ueyama01f93332017-05-18 17:03:49 +0000479 Dir->AddressTab = Addresses[Base];
480 Dirs.push_back(Dir);
Rui Ueyama857b3032015-08-10 23:02:57 +0000481 }
482 // Add null terminator.
Rui Ueyama01f93332017-05-18 17:03:49 +0000483 Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
Rui Ueyama857b3032015-08-10 23:02:57 +0000484}
485
486std::vector<Chunk *> DelayLoadContents::getChunks() {
487 std::vector<Chunk *> V;
Rui Ueyama01f93332017-05-18 17:03:49 +0000488 V.insert(V.end(), Dirs.begin(), Dirs.end());
489 V.insert(V.end(), Names.begin(), Names.end());
490 V.insert(V.end(), HintNames.begin(), HintNames.end());
Peter Collingbourne03638d02017-05-18 18:53:39 +0000491 V.insert(V.end(), DLLNames.begin(), DLLNames.end());
Rui Ueyama857b3032015-08-10 23:02:57 +0000492 return V;
493}
494
495std::vector<Chunk *> DelayLoadContents::getDataChunks() {
496 std::vector<Chunk *> V;
Rui Ueyama01f93332017-05-18 17:03:49 +0000497 V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
498 V.insert(V.end(), Addresses.begin(), Addresses.end());
Rui Ueyama857b3032015-08-10 23:02:57 +0000499 return V;
500}
501
502uint64_t DelayLoadContents::getDirSize() {
503 return Dirs.size() * sizeof(delay_import_directory_table_entry);
504}
505
506void DelayLoadContents::create(Defined *H) {
507 Helper = H;
Rui Ueyamad1570882015-08-17 08:30:31 +0000508 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
Rui Ueyama857b3032015-08-10 23:02:57 +0000509
510 // Create .didat contents for each DLL.
Rui Ueyamad1570882015-08-17 08:30:31 +0000511 for (std::vector<DefinedImportData *> &Syms : V) {
Rui Ueyama857b3032015-08-10 23:02:57 +0000512 // Create the delay import table header.
Peter Collingbourne03638d02017-05-18 18:53:39 +0000513 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
514 auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
Rui Ueyama857b3032015-08-10 23:02:57 +0000515
516 size_t Base = Addresses.size();
517 for (DefinedImportData *S : Syms) {
Rui Ueyama01f93332017-05-18 17:03:49 +0000518 Chunk *T = newThunkChunk(S, Dir);
519 auto *A = make<DelayAddressChunk>(T);
520 Addresses.push_back(A);
521 Thunks.push_back(T);
Rui Ueyama857b3032015-08-10 23:02:57 +0000522 StringRef ExtName = S->getExternalName();
523 if (ExtName.empty()) {
Rui Ueyama01f93332017-05-18 17:03:49 +0000524 Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
Rui Ueyama857b3032015-08-10 23:02:57 +0000525 } else {
Rui Ueyama01f93332017-05-18 17:03:49 +0000526 auto *C = make<HintNameChunk>(ExtName, 0);
527 Names.push_back(make<LookupChunk>(C));
528 HintNames.push_back(C);
Rui Ueyama857b3032015-08-10 23:02:57 +0000529 }
530 }
531 // Terminate with null values.
Rui Ueyama01f93332017-05-18 17:03:49 +0000532 Addresses.push_back(make<NullChunk>(8));
533 Names.push_back(make<NullChunk>(8));
Rui Ueyama857b3032015-08-10 23:02:57 +0000534
535 for (int I = 0, E = Syms.size(); I < E; ++I)
Rui Ueyama01f93332017-05-18 17:03:49 +0000536 Syms[I]->setLocation(Addresses[Base + I]);
537 auto *MH = make<NullChunk>(8);
Rui Ueyama857b3032015-08-10 23:02:57 +0000538 MH->setAlign(8);
Rui Ueyama01f93332017-05-18 17:03:49 +0000539 ModuleHandles.push_back(MH);
Rui Ueyama857b3032015-08-10 23:02:57 +0000540
541 // Fill the delay import table header fields.
542 Dir->ModuleHandle = MH;
Rui Ueyama01f93332017-05-18 17:03:49 +0000543 Dir->AddressTab = Addresses[Base];
544 Dir->NameTab = Names[Base];
545 Dirs.push_back(Dir);
Rui Ueyama857b3032015-08-10 23:02:57 +0000546 }
547 // Add null terminator.
Rui Ueyama01f93332017-05-18 17:03:49 +0000548 Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
Rui Ueyama857b3032015-08-10 23:02:57 +0000549}
550
551Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
552 switch (Config->Machine) {
553 case AMD64:
Rui Ueyama01f93332017-05-18 17:03:49 +0000554 return make<ThunkChunkX64>(S, Dir, Helper);
Rui Ueyama857b3032015-08-10 23:02:57 +0000555 case I386:
Rui Ueyama01f93332017-05-18 17:03:49 +0000556 return make<ThunkChunkX86>(S, Dir, Helper);
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000557 case ARMNT:
558 return make<ThunkChunkARM>(S, Dir, Helper);
Rui Ueyama857b3032015-08-10 23:02:57 +0000559 default:
560 llvm_unreachable("unsupported machine type");
561 }
562}
563
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000564EdataContents::EdataContents() {
565 uint16_t MaxOrdinal = 0;
566 for (Export &E : Config->Exports)
567 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
568
Rui Ueyama01f93332017-05-18 17:03:49 +0000569 auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
570 auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000571 std::vector<Chunk *> Names;
572 for (Export &E : Config->Exports)
573 if (!E.Noname)
Rui Ueyama01f93332017-05-18 17:03:49 +0000574 Names.push_back(make<StringChunk>(E.ExportName));
Rui Ueyama84425d72016-01-09 01:22:00 +0000575
576 std::vector<Chunk *> Forwards;
577 for (Export &E : Config->Exports) {
578 if (E.ForwardTo.empty())
579 continue;
Rui Ueyama01f93332017-05-18 17:03:49 +0000580 E.ForwardChunk = make<StringChunk>(E.ForwardTo);
Rui Ueyama84425d72016-01-09 01:22:00 +0000581 Forwards.push_back(E.ForwardChunk);
582 }
583
Rui Ueyama01f93332017-05-18 17:03:49 +0000584 auto *NameTab = make<NamePointersChunk>(Names);
585 auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
586 auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
587 AddressTab, NameTab, OrdinalTab);
588 Chunks.push_back(Dir);
589 Chunks.push_back(DLLName);
590 Chunks.push_back(AddressTab);
591 Chunks.push_back(NameTab);
592 Chunks.push_back(OrdinalTab);
593 Chunks.insert(Chunks.end(), Names.begin(), Names.end());
594 Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000595}
596
597} // namespace coff
598} // namespace lld