blob: 093eaa5e4f69fd59503b22847d8810b195622c59 [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
Rui Ueyama4b22fa72015-06-07 01:15:04 +000021#include "DLL.h"
Sam Clegg3141ddc2018-02-20 21:53:18 +000022#include "Chunks.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:
Rui Ueyamacfc2f802017-09-13 21:54:55 +000064 explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = 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:
Rui Ueyamacfc2f802017-09-13 21:54:55 +000079 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { Alignment = 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; }
120
121private:
122 size_t Size;
123};
124
Rui Ueyamad1570882015-08-17 08:30:31 +0000125static std::vector<std::vector<DefinedImportData *>>
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000126binImports(const std::vector<DefinedImportData *> &Imports) {
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000127 // Group DLL-imported symbols by DLL name because that's how
128 // symbols are layed out in the import descriptor table.
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000129 auto Less = [](const std::string &A, const std::string &B) {
Rui Ueyamad1570882015-08-17 08:30:31 +0000130 return Config->DLLOrder[A] < Config->DLLOrder[B];
131 };
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000132 std::map<std::string, std::vector<DefinedImportData *>,
133 bool(*)(const std::string &, const std::string &)> M(Less);
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000134 for (DefinedImportData *Sym : Imports)
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000135 M[Sym->getDLLName().lower()].push_back(Sym);
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000136
Rui Ueyamad1570882015-08-17 08:30:31 +0000137 std::vector<std::vector<DefinedImportData *>> V;
Rui Ueyama01f93332017-05-18 17:03:49 +0000138 for (auto &KV : M) {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000139 // Sort symbols by name for each group.
Rui Ueyama01f93332017-05-18 17:03:49 +0000140 std::vector<DefinedImportData *> &Syms = KV.second;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000141 std::sort(Syms.begin(), Syms.end(),
142 [](DefinedImportData *A, DefinedImportData *B) {
143 return A->getName() < B->getName();
144 });
Rui Ueyamad1570882015-08-17 08:30:31 +0000145 V.push_back(std::move(Syms));
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000146 }
Rui Ueyamad1570882015-08-17 08:30:31 +0000147 return V;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000148}
149
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000150// Export table
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000151// See Microsoft PE/COFF spec 4.3 for details.
152
153// A chunk for the delay import descriptor table etnry.
154class DelayDirectoryChunk : public Chunk {
155public:
156 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
157
158 size_t getSize() const override {
159 return sizeof(delay_import_directory_table_entry);
160 }
161
Rui Ueyama63bbe842015-09-19 23:28:57 +0000162 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000163 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
Rui Ueyama382dc962015-06-26 21:40:15 +0000164 E->Attributes = 1;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000165 E->Name = DLLName->getRVA();
166 E->ModuleHandle = ModuleHandle->getRVA();
167 E->DelayImportAddressTable = AddressTab->getRVA();
168 E->DelayImportNameTable = NameTab->getRVA();
169 }
170
171 Chunk *DLLName;
172 Chunk *ModuleHandle;
173 Chunk *AddressTab;
174 Chunk *NameTab;
175};
176
177// Initial contents for delay-loaded functions.
Rui Ueyama61096202015-06-22 17:26:27 +0000178// This code calls __delayLoadHelper2 function to resolve a symbol
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000179// and then overwrites its jump table slot with the result
180// for subsequent function calls.
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000181static const uint8_t ThunkX64[] = {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000182 0x51, // push rcx
183 0x52, // push rdx
184 0x41, 0x50, // push r8
185 0x41, 0x51, // push r9
186 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
187 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
188 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
189 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
190 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
191 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
192 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
193 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
194 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
195 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
196 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
197 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
198 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
199 0x41, 0x59, // pop r9
200 0x41, 0x58, // pop r8
201 0x5A, // pop rdx
202 0x59, // pop rcx
203 0xFF, 0xE0, // jmp rax
204};
205
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000206static const uint8_t ThunkX86[] = {
207 0x51, // push ecx
208 0x52, // push edx
209 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
210 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
211 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
212 0x5A, // pop edx
213 0x59, // pop ecx
214 0xFF, 0xE0, // jmp eax
215};
216
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000217static const uint8_t ThunkARM[] = {
218 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME>
219 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME>
220 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr}
221 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16
222 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7}
223 0x61, 0x46, // mov r1, ip
224 0x40, 0xf2, 0x00, 0x00, // mov.w r0, #0 DELAY_IMPORT_DESCRIPTOR
225 0xc0, 0xf2, 0x00, 0x00, // mov.t r0, #0 DELAY_IMPORT_DESCRIPTOR
226 0x00, 0xf0, 0x00, 0xd0, // bl #0 __delayLoadHelper2
227 0x84, 0x46, // mov ip, r0
228 0xbd, 0xec, 0x10, 0x0b, // vpop {d0, d1, d2, d3, d4, d5, d6, d7}
229 0xbd, 0xe8, 0x0f, 0x48, // pop.w {r0, r1, r2, r3, r11, lr}
230 0x60, 0x47, // bx ip
231};
232
Martin Storsjo32d21d62018-09-18 07:22:01 +0000233static const uint8_t ThunkARM64[] = {
234 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_<FUNCNAME>
235 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_<FUNCNAME>
236 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]!
237 0xfd, 0x03, 0x00, 0x91, // mov x29, sp
238 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16]
239 0xe2, 0x0f, 0x02, 0xa9, // stp x2, x3, [sp, #32]
240 0xe4, 0x17, 0x03, 0xa9, // stp x4, x5, [sp, #48]
241 0xe6, 0x1f, 0x04, 0xa9, // stp x6, x7, [sp, #64]
242 0xe0, 0x87, 0x02, 0xad, // stp q0, q1, [sp, #80]
243 0xe2, 0x8f, 0x03, 0xad, // stp q2, q3, [sp, #112]
244 0xe4, 0x97, 0x04, 0xad, // stp q4, q5, [sp, #144]
245 0xe6, 0x9f, 0x05, 0xad, // stp q6, q7, [sp, #176]
246 0xe1, 0x03, 0x11, 0xaa, // mov x1, x17
247 0x00, 0x00, 0x00, 0x90, // adrp x0, #0 DELAY_IMPORT_DESCRIPTOR
248 0x00, 0x00, 0x00, 0x91, // add x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR
249 0x00, 0x00, 0x00, 0x94, // bl #0 __delayLoadHelper2
250 0xf0, 0x03, 0x00, 0xaa, // mov x16, x0
251 0xe6, 0x9f, 0x45, 0xad, // ldp q6, q7, [sp, #176]
252 0xe4, 0x97, 0x44, 0xad, // ldp q4, q5, [sp, #144]
253 0xe2, 0x8f, 0x43, 0xad, // ldp q2, q3, [sp, #112]
254 0xe0, 0x87, 0x42, 0xad, // ldp q0, q1, [sp, #80]
255 0xe6, 0x1f, 0x44, 0xa9, // ldp x6, x7, [sp, #64]
256 0xe4, 0x17, 0x43, 0xa9, // ldp x4, x5, [sp, #48]
257 0xe2, 0x0f, 0x42, 0xa9, // ldp x2, x3, [sp, #32]
258 0xe0, 0x07, 0x41, 0xa9, // ldp x0, x1, [sp, #16]
259 0xfd, 0x7b, 0xcd, 0xa8, // ldp x29, x30, [sp], #208
260 0x00, 0x02, 0x1f, 0xd6, // br x16
261};
262
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000263// A chunk for the delay import thunk.
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000264class ThunkChunkX64 : public Chunk {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000265public:
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000266 ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
267 : Imp(I), Desc(D), Helper(H) {}
268
269 size_t getSize() const override { return sizeof(ThunkX64); }
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000270
Rui Ueyama63bbe842015-09-19 23:28:57 +0000271 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000272 memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
273 write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
274 write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
275 write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000276 }
277
278 Defined *Imp = nullptr;
279 Chunk *Desc = nullptr;
280 Defined *Helper = nullptr;
281};
282
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000283class ThunkChunkX86 : public Chunk {
284public:
285 ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
286 : Imp(I), Desc(D), Helper(H) {}
287
288 size_t getSize() const override { return sizeof(ThunkX86); }
289
Rui Ueyama63bbe842015-09-19 23:28:57 +0000290 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000291 memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
292 write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
293 write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
294 write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000295 }
296
Rui Ueyama3afd5bf2015-07-25 01:44:32 +0000297 void getBaserels(std::vector<Baserel> *Res) override {
298 Res->emplace_back(RVA + 3);
299 Res->emplace_back(RVA + 8);
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000300 }
301
302 Defined *Imp = nullptr;
303 Chunk *Desc = nullptr;
304 Defined *Helper = nullptr;
305};
306
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000307class ThunkChunkARM : public Chunk {
308public:
309 ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
310 : Imp(I), Desc(D), Helper(H) {}
311
312 size_t getSize() const override { return sizeof(ThunkARM); }
313
314 void writeTo(uint8_t *Buf) const override {
315 memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM));
316 applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase);
317 applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase);
318 applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34);
319 }
320
321 void getBaserels(std::vector<Baserel> *Res) override {
322 Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
323 Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
324 }
325
326 Defined *Imp = nullptr;
327 Chunk *Desc = nullptr;
328 Defined *Helper = nullptr;
329};
330
Martin Storsjo32d21d62018-09-18 07:22:01 +0000331class ThunkChunkARM64 : public Chunk {
332public:
333 ThunkChunkARM64(Defined *I, Chunk *D, Defined *H)
334 : Imp(I), Desc(D), Helper(H) {}
335
336 size_t getSize() const override { return sizeof(ThunkARM64); }
337
338 void writeTo(uint8_t *Buf) const override {
339 memcpy(Buf + OutputSectionOff, ThunkARM64, sizeof(ThunkARM64));
340 applyArm64Addr(Buf + OutputSectionOff + 0, Imp->getRVA(), RVA + 0, 12);
341 applyArm64Imm(Buf + OutputSectionOff + 4, Imp->getRVA() & 0xfff, 0);
342 applyArm64Addr(Buf + OutputSectionOff + 52, Desc->getRVA(), RVA + 52, 12);
343 applyArm64Imm(Buf + OutputSectionOff + 56, Desc->getRVA() & 0xfff, 0);
344 applyArm64Branch26(Buf + OutputSectionOff + 60,
345 Helper->getRVA() - RVA - 60);
346 }
347
348 Defined *Imp = nullptr;
349 Chunk *Desc = nullptr;
350 Defined *Helper = nullptr;
351};
352
Rui Ueyama382dc962015-06-26 21:40:15 +0000353// A chunk for the import descriptor table.
354class DelayAddressChunk : public Chunk {
355public:
Rui Ueyamacfc2f802017-09-13 21:54:55 +0000356 explicit DelayAddressChunk(Chunk *C) : Thunk(C) { Alignment = ptrSize(); }
Rui Ueyama7e387a62015-07-28 02:54:18 +0000357 size_t getSize() const override { return ptrSize(); }
Rui Ueyama382dc962015-06-26 21:40:15 +0000358
Rui Ueyama63bbe842015-09-19 23:28:57 +0000359 void writeTo(uint8_t *Buf) const override {
Rui Ueyama7e387a62015-07-28 02:54:18 +0000360 if (Config->is64()) {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000361 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
Rui Ueyama7e387a62015-07-28 02:54:18 +0000362 } else {
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000363 uint32_t Bit = 0;
364 // Pointer to thumb code must have the LSB set, so adjust it.
365 if (Config->Machine == ARMNT)
366 Bit = 1;
367 write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit);
Rui Ueyama7e387a62015-07-28 02:54:18 +0000368 }
Rui Ueyama382dc962015-06-26 21:40:15 +0000369 }
370
Rui Ueyama3afd5bf2015-07-25 01:44:32 +0000371 void getBaserels(std::vector<Baserel> *Res) override {
372 Res->emplace_back(RVA);
Rui Ueyama810551a2015-06-26 22:05:32 +0000373 }
374
Rui Ueyama382dc962015-06-26 21:40:15 +0000375 Chunk *Thunk;
376};
377
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000378// Export table
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000379// Read Microsoft PE/COFF spec 5.3 for details.
380
381// A chunk for the export descriptor table.
382class ExportDirectoryChunk : public Chunk {
383public:
384 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
385 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
386 OrdinalTab(O) {}
387
388 size_t getSize() const override {
389 return sizeof(export_directory_table_entry);
390 }
391
Rui Ueyama63bbe842015-09-19 23:28:57 +0000392 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000393 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000394 E->NameRVA = DLLName->getRVA();
395 E->OrdinalBase = 0;
396 E->AddressTableEntries = MaxOrdinal + 1;
397 E->NumberOfNamePointers = NameTabSize;
398 E->ExportAddressTableRVA = AddressTab->getRVA();
399 E->NamePointerRVA = NameTab->getRVA();
400 E->OrdinalTableRVA = OrdinalTab->getRVA();
401 }
402
403 uint16_t MaxOrdinal;
404 uint16_t NameTabSize;
405 Chunk *DLLName;
406 Chunk *AddressTab;
407 Chunk *NameTab;
408 Chunk *OrdinalTab;
409};
410
411class AddressTableChunk : public Chunk {
412public:
413 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
414 size_t getSize() const override { return Size * 4; }
415
Rui Ueyama63bbe842015-09-19 23:28:57 +0000416 void writeTo(uint8_t *Buf) const override {
Martin Storsjo6528fb82017-12-20 06:50:45 +0000417 for (const Export &E : Config->Exports) {
Rui Ueyama84425d72016-01-09 01:22:00 +0000418 uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
Martin Storsjo6528fb82017-12-20 06:50:45 +0000419 uint32_t Bit = 0;
420 // Pointer to thumb code must have the LSB set, so adjust it.
421 if (Config->Machine == ARMNT && !E.Data)
422 Bit = 1;
Rui Ueyama84425d72016-01-09 01:22:00 +0000423 if (E.ForwardChunk) {
Martin Storsjo405b5bc2017-07-25 06:10:44 +0000424 write32le(P, E.ForwardChunk->getRVA() | Bit);
Rui Ueyama84425d72016-01-09 01:22:00 +0000425 } else {
Martin Storsjo405b5bc2017-07-25 06:10:44 +0000426 write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);
Rui Ueyama84425d72016-01-09 01:22:00 +0000427 }
Rui Ueyamaf5313b32015-06-28 22:16:41 +0000428 }
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000429 }
430
431private:
432 size_t Size;
433};
434
435class NamePointersChunk : public Chunk {
436public:
437 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
438 size_t getSize() const override { return Chunks.size() * 4; }
439
Rui Ueyama63bbe842015-09-19 23:28:57 +0000440 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000441 uint8_t *P = Buf + OutputSectionOff;
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000442 for (Chunk *C : Chunks) {
443 write32le(P, C->getRVA());
444 P += 4;
445 }
446 }
447
448private:
449 std::vector<Chunk *> Chunks;
450};
451
452class ExportOrdinalChunk : public Chunk {
453public:
454 explicit ExportOrdinalChunk(size_t I) : Size(I) {}
455 size_t getSize() const override { return Size * 2; }
456
Rui Ueyama63bbe842015-09-19 23:28:57 +0000457 void writeTo(uint8_t *Buf) const override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000458 uint8_t *P = Buf + OutputSectionOff;
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000459 for (Export &E : Config->Exports) {
460 if (E.Noname)
461 continue;
462 write16le(P, E.Ordinal);
463 P += 2;
464 }
465 }
466
467private:
468 size_t Size;
469};
470
Rui Ueyama857b3032015-08-10 23:02:57 +0000471} // anonymous namespace
472
Rui Ueyama857b3032015-08-10 23:02:57 +0000473void IdataContents::create() {
Rui Ueyamad1570882015-08-17 08:30:31 +0000474 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
Rui Ueyama857b3032015-08-10 23:02:57 +0000475
476 // Create .idata contents for each DLL.
Rui Ueyamad1570882015-08-17 08:30:31 +0000477 for (std::vector<DefinedImportData *> &Syms : V) {
Rui Ueyama857b3032015-08-10 23:02:57 +0000478 // Create lookup and address tables. If they have external names,
479 // we need to create HintName chunks to store the names.
480 // If they don't (if they are import-by-ordinals), we store only
481 // ordinal values to the table.
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000482 size_t Base = Lookups.size();
Rui Ueyama857b3032015-08-10 23:02:57 +0000483 for (DefinedImportData *S : Syms) {
484 uint16_t Ord = S->getOrdinal();
485 if (S->getExternalName().empty()) {
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000486 Lookups.push_back(make<OrdinalOnlyChunk>(Ord));
Rui Ueyama01f93332017-05-18 17:03:49 +0000487 Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
Rui Ueyama857b3032015-08-10 23:02:57 +0000488 continue;
489 }
Rui Ueyama01f93332017-05-18 17:03:49 +0000490 auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000491 Lookups.push_back(make<LookupChunk>(C));
Rui Ueyama01f93332017-05-18 17:03:49 +0000492 Addresses.push_back(make<LookupChunk>(C));
493 Hints.push_back(C);
Rui Ueyama857b3032015-08-10 23:02:57 +0000494 }
495 // Terminate with null values.
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000496 Lookups.push_back(make<NullChunk>(ptrSize()));
Rui Ueyama01f93332017-05-18 17:03:49 +0000497 Addresses.push_back(make<NullChunk>(ptrSize()));
Rui Ueyama857b3032015-08-10 23:02:57 +0000498
499 for (int I = 0, E = Syms.size(); I < E; ++I)
Rui Ueyama01f93332017-05-18 17:03:49 +0000500 Syms[I]->setLocation(Addresses[Base + I]);
Rui Ueyama857b3032015-08-10 23:02:57 +0000501
502 // Create the import table header.
Peter Collingbourne03638d02017-05-18 18:53:39 +0000503 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
504 auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
Reid Klecknerc2eaccb02017-06-02 18:49:38 +0000505 Dir->LookupTab = Lookups[Base];
Rui Ueyama01f93332017-05-18 17:03:49 +0000506 Dir->AddressTab = Addresses[Base];
507 Dirs.push_back(Dir);
Rui Ueyama857b3032015-08-10 23:02:57 +0000508 }
509 // Add null terminator.
Rui Ueyama01f93332017-05-18 17:03:49 +0000510 Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
Rui Ueyama857b3032015-08-10 23:02:57 +0000511}
512
513std::vector<Chunk *> DelayLoadContents::getChunks() {
514 std::vector<Chunk *> V;
Rui Ueyama01f93332017-05-18 17:03:49 +0000515 V.insert(V.end(), Dirs.begin(), Dirs.end());
516 V.insert(V.end(), Names.begin(), Names.end());
517 V.insert(V.end(), HintNames.begin(), HintNames.end());
Peter Collingbourne03638d02017-05-18 18:53:39 +0000518 V.insert(V.end(), DLLNames.begin(), DLLNames.end());
Rui Ueyama857b3032015-08-10 23:02:57 +0000519 return V;
520}
521
522std::vector<Chunk *> DelayLoadContents::getDataChunks() {
523 std::vector<Chunk *> V;
Rui Ueyama01f93332017-05-18 17:03:49 +0000524 V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
525 V.insert(V.end(), Addresses.begin(), Addresses.end());
Rui Ueyama857b3032015-08-10 23:02:57 +0000526 return V;
527}
528
529uint64_t DelayLoadContents::getDirSize() {
530 return Dirs.size() * sizeof(delay_import_directory_table_entry);
531}
532
533void DelayLoadContents::create(Defined *H) {
534 Helper = H;
Rui Ueyamad1570882015-08-17 08:30:31 +0000535 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
Rui Ueyama857b3032015-08-10 23:02:57 +0000536
537 // Create .didat contents for each DLL.
Rui Ueyamad1570882015-08-17 08:30:31 +0000538 for (std::vector<DefinedImportData *> &Syms : V) {
Rui Ueyama857b3032015-08-10 23:02:57 +0000539 // Create the delay import table header.
Peter Collingbourne03638d02017-05-18 18:53:39 +0000540 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
541 auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
Rui Ueyama857b3032015-08-10 23:02:57 +0000542
543 size_t Base = Addresses.size();
544 for (DefinedImportData *S : Syms) {
Rui Ueyama01f93332017-05-18 17:03:49 +0000545 Chunk *T = newThunkChunk(S, Dir);
546 auto *A = make<DelayAddressChunk>(T);
547 Addresses.push_back(A);
548 Thunks.push_back(T);
Rui Ueyama857b3032015-08-10 23:02:57 +0000549 StringRef ExtName = S->getExternalName();
550 if (ExtName.empty()) {
Rui Ueyama01f93332017-05-18 17:03:49 +0000551 Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
Rui Ueyama857b3032015-08-10 23:02:57 +0000552 } else {
Rui Ueyama01f93332017-05-18 17:03:49 +0000553 auto *C = make<HintNameChunk>(ExtName, 0);
554 Names.push_back(make<LookupChunk>(C));
555 HintNames.push_back(C);
Rui Ueyama857b3032015-08-10 23:02:57 +0000556 }
557 }
558 // Terminate with null values.
Rui Ueyama01f93332017-05-18 17:03:49 +0000559 Addresses.push_back(make<NullChunk>(8));
560 Names.push_back(make<NullChunk>(8));
Rui Ueyama857b3032015-08-10 23:02:57 +0000561
562 for (int I = 0, E = Syms.size(); I < E; ++I)
Rui Ueyama01f93332017-05-18 17:03:49 +0000563 Syms[I]->setLocation(Addresses[Base + I]);
564 auto *MH = make<NullChunk>(8);
Rui Ueyamacfc2f802017-09-13 21:54:55 +0000565 MH->Alignment = 8;
Rui Ueyama01f93332017-05-18 17:03:49 +0000566 ModuleHandles.push_back(MH);
Rui Ueyama857b3032015-08-10 23:02:57 +0000567
568 // Fill the delay import table header fields.
569 Dir->ModuleHandle = MH;
Rui Ueyama01f93332017-05-18 17:03:49 +0000570 Dir->AddressTab = Addresses[Base];
571 Dir->NameTab = Names[Base];
572 Dirs.push_back(Dir);
Rui Ueyama857b3032015-08-10 23:02:57 +0000573 }
574 // Add null terminator.
Rui Ueyama01f93332017-05-18 17:03:49 +0000575 Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
Rui Ueyama857b3032015-08-10 23:02:57 +0000576}
577
578Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
579 switch (Config->Machine) {
580 case AMD64:
Rui Ueyama01f93332017-05-18 17:03:49 +0000581 return make<ThunkChunkX64>(S, Dir, Helper);
Rui Ueyama857b3032015-08-10 23:02:57 +0000582 case I386:
Rui Ueyama01f93332017-05-18 17:03:49 +0000583 return make<ThunkChunkX86>(S, Dir, Helper);
Martin Storsjo82eaf6c2017-07-25 20:00:37 +0000584 case ARMNT:
585 return make<ThunkChunkARM>(S, Dir, Helper);
Martin Storsjo32d21d62018-09-18 07:22:01 +0000586 case ARM64:
587 return make<ThunkChunkARM64>(S, Dir, Helper);
Rui Ueyama857b3032015-08-10 23:02:57 +0000588 default:
589 llvm_unreachable("unsupported machine type");
590 }
591}
592
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000593EdataContents::EdataContents() {
594 uint16_t MaxOrdinal = 0;
595 for (Export &E : Config->Exports)
596 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
597
Rui Ueyama01f93332017-05-18 17:03:49 +0000598 auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
599 auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000600 std::vector<Chunk *> Names;
601 for (Export &E : Config->Exports)
602 if (!E.Noname)
Rui Ueyama01f93332017-05-18 17:03:49 +0000603 Names.push_back(make<StringChunk>(E.ExportName));
Rui Ueyama84425d72016-01-09 01:22:00 +0000604
605 std::vector<Chunk *> Forwards;
606 for (Export &E : Config->Exports) {
607 if (E.ForwardTo.empty())
608 continue;
Rui Ueyama01f93332017-05-18 17:03:49 +0000609 E.ForwardChunk = make<StringChunk>(E.ForwardTo);
Rui Ueyama84425d72016-01-09 01:22:00 +0000610 Forwards.push_back(E.ForwardChunk);
611 }
612
Rui Ueyama01f93332017-05-18 17:03:49 +0000613 auto *NameTab = make<NamePointersChunk>(Names);
614 auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
615 auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
616 AddressTab, NameTab, OrdinalTab);
617 Chunks.push_back(Dir);
618 Chunks.push_back(DLLName);
619 Chunks.push_back(AddressTab);
620 Chunks.push_back(NameTab);
621 Chunks.push_back(OrdinalTab);
622 Chunks.insert(Chunks.end(), Names.begin(), Names.end());
623 Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000624}
625
626} // namespace coff
627} // namespace lld