Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/DLL.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- DLL.cpp ------------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file defines various types of chunks for the DLL import or export
10
// descriptor tables. They are inherently Windows-specific.
11
// You need to read Microsoft PE/COFF spec to understand details
12
// about the data structures.
13
//
14
// If you are not particularly interested in linking against Windows
15
// DLL, you can skip this file, and you should still be able to
16
// understand the rest of the linker.
17
//
18
//===----------------------------------------------------------------------===//
19
20
#include "DLL.h"
21
#include "Chunks.h"
22
#include "llvm/Object/COFF.h"
23
#include "llvm/Support/Endian.h"
24
#include "llvm/Support/Path.h"
25
26
using namespace llvm;
27
using namespace llvm::object;
28
using namespace llvm::support::endian;
29
using namespace llvm::COFF;
30
31
namespace lld {
32
namespace coff {
33
namespace {
34
35
// Import table
36
37
// A chunk for the import descriptor table.
38
class HintNameChunk : public NonSectionChunk {
39
public:
40
90
  HintNameChunk(StringRef n, uint16_t h) : name(n), hint(h) {}
41
42
192
  size_t getSize() const override {
43
192
    // Starts with 2 byte Hint field, followed by a null-terminated string,
44
192
    // ends with 0 or 1 byte padding.
45
192
    return alignTo(name.size() + 3, 2);
46
192
  }
47
48
90
  void writeTo(uint8_t *buf) const override {
49
90
    memset(buf, 0, getSize());
50
90
    write16le(buf, hint);
51
90
    memcpy(buf + 2, name.data(), name.size());
52
90
  }
53
54
private:
55
  StringRef name;
56
  uint16_t hint;
57
};
58
59
// A chunk for the import descriptor table.
60
class LookupChunk : public NonSectionChunk {
61
public:
62
170
  explicit LookupChunk(Chunk *c) : hintName(c) {
63
170
    setAlignment(config->wordsize);
64
170
  }
65
266
  size_t getSize() const override { return config->wordsize; }
66
67
170
  void writeTo(uint8_t *buf) const override {
68
170
    if (config->is64())
69
125
      write64le(buf, hintName->getRVA());
70
45
    else
71
45
      write32le(buf, hintName->getRVA());
72
170
  }
73
74
  Chunk *hintName;
75
};
76
77
// A chunk for the import descriptor table.
78
// This chunk represent import-by-ordinal symbols.
79
// See Microsoft PE/COFF spec 7.1. Import Header for details.
80
class OrdinalOnlyChunk : public NonSectionChunk {
81
public:
82
25
  explicit OrdinalOnlyChunk(uint16_t v) : ordinal(v) {
83
25
    setAlignment(config->wordsize);
84
25
  }
85
37
  size_t getSize() const override { return config->wordsize; }
86
87
25
  void writeTo(uint8_t *buf) const override {
88
25
    // An import-by-ordinal slot has MSB 1 to indicate that
89
25
    // this is import-by-ordinal (and not import-by-name).
90
25
    if (config->is64()) {
91
25
      write64le(buf, (1ULL << 63) | ordinal);
92
25
    } else {
93
0
      write32le(buf, (1ULL << 31) | ordinal);
94
0
    }
95
25
  }
96
97
  uint16_t ordinal;
98
};
99
100
// A chunk for the import descriptor table.
101
class ImportDirectoryChunk : public NonSectionChunk {
102
public:
103
48
  explicit ImportDirectoryChunk(Chunk *n) : dllName(n) {}
104
148
  size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
105
106
48
  void writeTo(uint8_t *buf) const override {
107
48
    memset(buf, 0, getSize());
108
48
109
48
    auto *e = (coff_import_directory_table_entry *)(buf);
110
48
    e->ImportLookupTableRVA = lookupTab->getRVA();
111
48
    e->NameRVA = dllName->getRVA();
112
48
    e->ImportAddressTableRVA = addressTab->getRVA();
113
48
  }
114
115
  Chunk *dllName;
116
  Chunk *lookupTab;
117
  Chunk *addressTab;
118
};
119
120
// A chunk representing null terminator in the import table.
121
// Contents of this chunk is always null bytes.
122
class NullChunk : public NonSectionChunk {
123
public:
124
168
  explicit NullChunk(size_t n) : size(n) { hasData = false; }
125
289
  size_t getSize() const override { return size; }
126
127
168
  void writeTo(uint8_t *buf) const override {
128
168
    memset(buf, 0, size);
129
168
  }
130
131
private:
132
  size_t size;
133
};
134
135
static std::vector<std::vector<DefinedImportData *>>
136
54
binImports(const std::vector<DefinedImportData *> &imports) {
137
54
  // Group DLL-imported symbols by DLL name because that's how
138
54
  // symbols are layed out in the import descriptor table.
139
104
  auto less = [](const std::string &a, const std::string &b) {
140
104
    return config->dllOrder[a] < config->dllOrder[b];
141
104
  };
142
54
  std::map<std::string, std::vector<DefinedImportData *>,
143
54
           bool(*)(const std::string &, const std::string &)> m(less);
144
54
  for (DefinedImportData *sym : imports)
145
103
    m[sym->getDLLName().lower()].push_back(sym);
146
54
147
54
  std::vector<std::vector<DefinedImportData *>> v;
148
54
  for (auto &kv : m) {
149
54
    // Sort symbols by name for each group.
150
54
    std::vector<DefinedImportData *> &syms = kv.second;
151
54
    std::sort(syms.begin(), syms.end(),
152
54
              [](DefinedImportData *a, DefinedImportData *b) {
153
52
                return a->getName() < b->getName();
154
52
              });
155
54
    v.push_back(std::move(syms));
156
54
  }
157
54
  return v;
158
54
}
159
160
// Export table
161
// See Microsoft PE/COFF spec 4.3 for details.
162
163
// A chunk for the delay import descriptor table etnry.
164
class DelayDirectoryChunk : public NonSectionChunk {
165
public:
166
6
  explicit DelayDirectoryChunk(Chunk *n) : dllName(n) {}
167
168
12
  size_t getSize() const override {
169
12
    return sizeof(delay_import_directory_table_entry);
170
12
  }
171
172
6
  void writeTo(uint8_t *buf) const override {
173
6
    memset(buf, 0, getSize());
174
6
175
6
    auto *e = (delay_import_directory_table_entry *)(buf);
176
6
    e->Attributes = 1;
177
6
    e->Name = dllName->getRVA();
178
6
    e->ModuleHandle = moduleHandle->getRVA();
179
6
    e->DelayImportAddressTable = addressTab->getRVA();
180
6
    e->DelayImportNameTable = nameTab->getRVA();
181
6
  }
182
183
  Chunk *dllName;
184
  Chunk *moduleHandle;
185
  Chunk *addressTab;
186
  Chunk *nameTab;
187
};
188
189
// Initial contents for delay-loaded functions.
190
// This code calls __delayLoadHelper2 function to resolve a symbol
191
// and then overwrites its jump table slot with the result
192
// for subsequent function calls.
193
static const uint8_t thunkX64[] = {
194
    0x48, 0x8D, 0x05, 0, 0, 0, 0,       // lea     rax, [__imp_<FUNCNAME>]
195
    0xE9, 0, 0, 0, 0,                   // jmp     __tailMerge_<lib>
196
};
197
198
static const uint8_t tailMergeX64[] = {
199
    0x51,                               // push    rcx
200
    0x52,                               // push    rdx
201
    0x41, 0x50,                         // push    r8
202
    0x41, 0x51,                         // push    r9
203
    0x48, 0x83, 0xEC, 0x48,             // sub     rsp, 48h
204
    0x66, 0x0F, 0x7F, 0x04, 0x24,       // movdqa  xmmword ptr [rsp], xmm0
205
    0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa  xmmword ptr [rsp+10h], xmm1
206
    0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa  xmmword ptr [rsp+20h], xmm2
207
    0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa  xmmword ptr [rsp+30h], xmm3
208
    0x48, 0x8B, 0xD0,                   // mov     rdx, rax
209
    0x48, 0x8D, 0x0D, 0, 0, 0, 0,       // lea     rcx, [___DELAY_IMPORT_...]
210
    0xE8, 0, 0, 0, 0,                   // call    __delayLoadHelper2
211
    0x66, 0x0F, 0x6F, 0x04, 0x24,       // movdqa  xmm0, xmmword ptr [rsp]
212
    0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa  xmm1, xmmword ptr [rsp+10h]
213
    0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa  xmm2, xmmword ptr [rsp+20h]
214
    0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa  xmm3, xmmword ptr [rsp+30h]
215
    0x48, 0x83, 0xC4, 0x48,             // add     rsp, 48h
216
    0x41, 0x59,                         // pop     r9
217
    0x41, 0x58,                         // pop     r8
218
    0x5A,                               // pop     rdx
219
    0x59,                               // pop     rcx
220
    0xFF, 0xE0,                         // jmp     rax
221
};
222
223
static const uint8_t thunkX86[] = {
224
    0xB8, 0, 0, 0, 0,  // mov   eax, offset ___imp__<FUNCNAME>
225
    0xE9, 0, 0, 0, 0,  // jmp   __tailMerge_<lib>
226
};
227
228
static const uint8_t tailMergeX86[] = {
229
    0x51,              // push  ecx
230
    0x52,              // push  edx
231
    0x50,              // push  eax
232
    0x68, 0, 0, 0, 0,  // push  offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
233
    0xE8, 0, 0, 0, 0,  // call  ___delayLoadHelper2@8
234
    0x5A,              // pop   edx
235
    0x59,              // pop   ecx
236
    0xFF, 0xE0,        // jmp   eax
237
};
238
239
static const uint8_t thunkARM[] = {
240
    0x40, 0xf2, 0x00, 0x0c, // mov.w   ip, #0 __imp_<FUNCNAME>
241
    0xc0, 0xf2, 0x00, 0x0c, // mov.t   ip, #0 __imp_<FUNCNAME>
242
    0x00, 0xf0, 0x00, 0xb8, // b.w     __tailMerge_<lib>
243
};
244
245
static const uint8_t tailMergeARM[] = {
246
    0x2d, 0xe9, 0x0f, 0x48, // push.w  {r0, r1, r2, r3, r11, lr}
247
    0x0d, 0xf2, 0x10, 0x0b, // addw    r11, sp, #16
248
    0x2d, 0xed, 0x10, 0x0b, // vpush   {d0, d1, d2, d3, d4, d5, d6, d7}
249
    0x61, 0x46,             // mov     r1, ip
250
    0x40, 0xf2, 0x00, 0x00, // mov.w   r0, #0 DELAY_IMPORT_DESCRIPTOR
251
    0xc0, 0xf2, 0x00, 0x00, // mov.t   r0, #0 DELAY_IMPORT_DESCRIPTOR
252
    0x00, 0xf0, 0x00, 0xd0, // bl      #0 __delayLoadHelper2
253
    0x84, 0x46,             // mov     ip, r0
254
    0xbd, 0xec, 0x10, 0x0b, // vpop    {d0, d1, d2, d3, d4, d5, d6, d7}
255
    0xbd, 0xe8, 0x0f, 0x48, // pop.w   {r0, r1, r2, r3, r11, lr}
256
    0x60, 0x47,             // bx      ip
257
};
258
259
static const uint8_t thunkARM64[] = {
260
    0x11, 0x00, 0x00, 0x90, // adrp    x17, #0      __imp_<FUNCNAME>
261
    0x31, 0x02, 0x00, 0x91, // add     x17, x17, #0 :lo12:__imp_<FUNCNAME>
262
    0x00, 0x00, 0x00, 0x14, // b       __tailMerge_<lib>
263
};
264
265
static const uint8_t tailMergeARM64[] = {
266
    0xfd, 0x7b, 0xb3, 0xa9, // stp     x29, x30, [sp, #-208]!
267
    0xfd, 0x03, 0x00, 0x91, // mov     x29, sp
268
    0xe0, 0x07, 0x01, 0xa9, // stp     x0, x1, [sp, #16]
269
    0xe2, 0x0f, 0x02, 0xa9, // stp     x2, x3, [sp, #32]
270
    0xe4, 0x17, 0x03, 0xa9, // stp     x4, x5, [sp, #48]
271
    0xe6, 0x1f, 0x04, 0xa9, // stp     x6, x7, [sp, #64]
272
    0xe0, 0x87, 0x02, 0xad, // stp     q0, q1, [sp, #80]
273
    0xe2, 0x8f, 0x03, 0xad, // stp     q2, q3, [sp, #112]
274
    0xe4, 0x97, 0x04, 0xad, // stp     q4, q5, [sp, #144]
275
    0xe6, 0x9f, 0x05, 0xad, // stp     q6, q7, [sp, #176]
276
    0xe1, 0x03, 0x11, 0xaa, // mov     x1, x17
277
    0x00, 0x00, 0x00, 0x90, // adrp    x0, #0     DELAY_IMPORT_DESCRIPTOR
278
    0x00, 0x00, 0x00, 0x91, // add     x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR
279
    0x00, 0x00, 0x00, 0x94, // bl      #0 __delayLoadHelper2
280
    0xf0, 0x03, 0x00, 0xaa, // mov     x16, x0
281
    0xe6, 0x9f, 0x45, 0xad, // ldp     q6, q7, [sp, #176]
282
    0xe4, 0x97, 0x44, 0xad, // ldp     q4, q5, [sp, #144]
283
    0xe2, 0x8f, 0x43, 0xad, // ldp     q2, q3, [sp, #112]
284
    0xe0, 0x87, 0x42, 0xad, // ldp     q0, q1, [sp, #80]
285
    0xe6, 0x1f, 0x44, 0xa9, // ldp     x6, x7, [sp, #64]
286
    0xe4, 0x17, 0x43, 0xa9, // ldp     x4, x5, [sp, #48]
287
    0xe2, 0x0f, 0x42, 0xa9, // ldp     x2, x3, [sp, #32]
288
    0xe0, 0x07, 0x41, 0xa9, // ldp     x0, x1, [sp, #16]
289
    0xfd, 0x7b, 0xcd, 0xa8, // ldp     x29, x30, [sp], #208
290
    0x00, 0x02, 0x1f, 0xd6, // br      x16
291
};
292
293
// A chunk for the delay import thunk.
294
class ThunkChunkX64 : public NonSectionChunk {
295
public:
296
7
  ThunkChunkX64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
297
298
7
  size_t getSize() const override { return sizeof(thunkX64); }
299
300
7
  void writeTo(uint8_t *buf) const override {
301
7
    memcpy(buf, thunkX64, sizeof(thunkX64));
302
7
    write32le(buf + 3, imp->getRVA() - rva - 7);
303
7
    write32le(buf + 8, tailMerge->getRVA() - rva - 12);
304
7
  }
305
306
  Defined *imp = nullptr;
307
  Chunk *tailMerge = nullptr;
308
};
309
310
class TailMergeChunkX64 : public NonSectionChunk {
311
public:
312
3
  TailMergeChunkX64(Chunk *d, Defined *h) : desc(d), helper(h) {}
313
314
3
  size_t getSize() const override { return sizeof(tailMergeX64); }
315
316
3
  void writeTo(uint8_t *buf) const override {
317
3
    memcpy(buf, tailMergeX64, sizeof(tailMergeX64));
318
3
    write32le(buf + 39, desc->getRVA() - rva - 43);
319
3
    write32le(buf + 44, helper->getRVA() - rva - 48);
320
3
  }
321
322
  Chunk *desc = nullptr;
323
  Defined *helper = nullptr;
324
};
325
326
class ThunkChunkX86 : public NonSectionChunk {
327
public:
328
2
  ThunkChunkX86(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
329
330
2
  size_t getSize() const override { return sizeof(thunkX86); }
331
332
2
  void writeTo(uint8_t *buf) const override {
333
2
    memcpy(buf, thunkX86, sizeof(thunkX86));
334
2
    write32le(buf + 1, imp->getRVA() + config->imageBase);
335
2
    write32le(buf + 6, tailMerge->getRVA() - rva - 10);
336
2
  }
337
338
2
  void getBaserels(std::vector<Baserel> *res) override {
339
2
    res->emplace_back(rva + 1);
340
2
  }
341
342
  Defined *imp = nullptr;
343
  Chunk *tailMerge = nullptr;
344
};
345
346
class TailMergeChunkX86 : public NonSectionChunk {
347
public:
348
1
  TailMergeChunkX86(Chunk *d, Defined *h) : desc(d), helper(h) {}
349
350
1
  size_t getSize() const override { return sizeof(tailMergeX86); }
351
352
1
  void writeTo(uint8_t *buf) const override {
353
1
    memcpy(buf, tailMergeX86, sizeof(tailMergeX86));
354
1
    write32le(buf + 4, desc->getRVA() + config->imageBase);
355
1
    write32le(buf + 9, helper->getRVA() - rva - 13);
356
1
  }
357
358
1
  void getBaserels(std::vector<Baserel> *res) override {
359
1
    res->emplace_back(rva + 4);
360
1
  }
361
362
  Chunk *desc = nullptr;
363
  Defined *helper = nullptr;
364
};
365
366
class ThunkChunkARM : public NonSectionChunk {
367
public:
368
1
  ThunkChunkARM(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
369
370
1
  size_t getSize() const override { return sizeof(thunkARM); }
371
372
1
  void writeTo(uint8_t *buf) const override {
373
1
    memcpy(buf, thunkARM, sizeof(thunkARM));
374
1
    applyMOV32T(buf + 0, imp->getRVA() + config->imageBase);
375
1
    applyBranch24T(buf + 8, tailMerge->getRVA() - rva - 12);
376
1
  }
377
378
1
  void getBaserels(std::vector<Baserel> *res) override {
379
1
    res->emplace_back(rva + 0, IMAGE_REL_BASED_ARM_MOV32T);
380
1
  }
381
382
  Defined *imp = nullptr;
383
  Chunk *tailMerge = nullptr;
384
};
385
386
class TailMergeChunkARM : public NonSectionChunk {
387
public:
388
1
  TailMergeChunkARM(Chunk *d, Defined *h) : desc(d), helper(h) {}
389
390
1
  size_t getSize() const override { return sizeof(tailMergeARM); }
391
392
1
  void writeTo(uint8_t *buf) const override {
393
1
    memcpy(buf, tailMergeARM, sizeof(tailMergeARM));
394
1
    applyMOV32T(buf + 14, desc->getRVA() + config->imageBase);
395
1
    applyBranch24T(buf + 22, helper->getRVA() - rva - 26);
396
1
  }
397
398
1
  void getBaserels(std::vector<Baserel> *res) override {
399
1
    res->emplace_back(rva + 14, IMAGE_REL_BASED_ARM_MOV32T);
400
1
  }
401
402
  Chunk *desc = nullptr;
403
  Defined *helper = nullptr;
404
};
405
406
class ThunkChunkARM64 : public NonSectionChunk {
407
public:
408
1
  ThunkChunkARM64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
409
410
1
  size_t getSize() const override { return sizeof(thunkARM64); }
411
412
1
  void writeTo(uint8_t *buf) const override {
413
1
    memcpy(buf, thunkARM64, sizeof(thunkARM64));
414
1
    applyArm64Addr(buf + 0, imp->getRVA(), rva + 0, 12);
415
1
    applyArm64Imm(buf + 4, imp->getRVA() & 0xfff, 0);
416
1
    applyArm64Branch26(buf + 8, tailMerge->getRVA() - rva - 8);
417
1
  }
418
419
  Defined *imp = nullptr;
420
  Chunk *tailMerge = nullptr;
421
};
422
423
class TailMergeChunkARM64 : public NonSectionChunk {
424
public:
425
1
  TailMergeChunkARM64(Chunk *d, Defined *h) : desc(d), helper(h) {}
426
427
1
  size_t getSize() const override { return sizeof(tailMergeARM64); }
428
429
1
  void writeTo(uint8_t *buf) const override {
430
1
    memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64));
431
1
    applyArm64Addr(buf + 44, desc->getRVA(), rva + 44, 12);
432
1
    applyArm64Imm(buf + 48, desc->getRVA() & 0xfff, 0);
433
1
    applyArm64Branch26(buf + 52, helper->getRVA() - rva - 52);
434
1
  }
435
436
  Chunk *desc = nullptr;
437
  Defined *helper = nullptr;
438
};
439
440
// A chunk for the import descriptor table.
441
class DelayAddressChunk : public NonSectionChunk {
442
public:
443
11
  explicit DelayAddressChunk(Chunk *c) : thunk(c) {
444
11
    setAlignment(config->wordsize);
445
11
  }
446
11
  size_t getSize() const override { return config->wordsize; }
447
448
11
  void writeTo(uint8_t *buf) const override {
449
11
    if (config->is64()) {
450
8
      write64le(buf, thunk->getRVA() + config->imageBase);
451
8
    } else {
452
3
      uint32_t bit = 0;
453
3
      // Pointer to thumb code must have the LSB set, so adjust it.
454
3
      if (config->machine == ARMNT)
455
1
        bit = 1;
456
3
      write32le(buf, (thunk->getRVA() + config->imageBase) | bit);
457
3
    }
458
11
  }
459
460
11
  void getBaserels(std::vector<Baserel> *res) override {
461
11
    res->emplace_back(rva);
462
11
  }
463
464
  Chunk *thunk;
465
};
466
467
// Export table
468
// Read Microsoft PE/COFF spec 5.3 for details.
469
470
// A chunk for the export descriptor table.
471
class ExportDirectoryChunk : public NonSectionChunk {
472
public:
473
  ExportDirectoryChunk(int i, int j, Chunk *d, Chunk *a, Chunk *n, Chunk *o)
474
      : maxOrdinal(i), nameTabSize(j), dllName(d), addressTab(a), nameTab(n),
475
576
        ordinalTab(o) {}
476
477
246
  size_t getSize() const override {
478
246
    return sizeof(export_directory_table_entry);
479
246
  }
480
481
117
  void writeTo(uint8_t *buf) const override {
482
117
    memset(buf, 0, getSize());
483
117
484
117
    auto *e = (export_directory_table_entry *)(buf);
485
117
    e->NameRVA = dllName->getRVA();
486
117
    e->OrdinalBase = 0;
487
117
    e->AddressTableEntries = maxOrdinal + 1;
488
117
    e->NumberOfNamePointers = nameTabSize;
489
117
    e->ExportAddressTableRVA = addressTab->getRVA();
490
117
    e->NamePointerRVA = nameTab->getRVA();
491
117
    e->OrdinalTableRVA = ordinalTab->getRVA();
492
117
  }
493
494
  uint16_t maxOrdinal;
495
  uint16_t nameTabSize;
496
  Chunk *dllName;
497
  Chunk *addressTab;
498
  Chunk *nameTab;
499
  Chunk *ordinalTab;
500
};
501
502
class AddressTableChunk : public NonSectionChunk {
503
public:
504
576
  explicit AddressTableChunk(size_t maxOrdinal) : size(maxOrdinal + 1) {}
505
246
  size_t getSize() const override { return size * 4; }
506
507
117
  void writeTo(uint8_t *buf) const override {
508
117
    memset(buf, 0, getSize());
509
117
510
209
    for (const Export &e : config->exports) {
511
209
      uint8_t *p = buf + e.ordinal * 4;
512
209
      uint32_t bit = 0;
513
209
      // Pointer to thumb code must have the LSB set, so adjust it.
514
209
      if (config->machine == ARMNT && 
!e.data6
)
515
3
        bit = 1;
516
209
      if (e.forwardChunk) {
517
2
        write32le(p, e.forwardChunk->getRVA() | bit);
518
207
      } else {
519
207
        write32le(p, cast<Defined>(e.sym)->getRVA() | bit);
520
207
      }
521
209
    }
522
117
  }
523
524
private:
525
  size_t size;
526
};
527
528
class NamePointersChunk : public NonSectionChunk {
529
public:
530
576
  explicit NamePointersChunk(std::vector<Chunk *> &v) : chunks(v) {}
531
129
  size_t getSize() const override { return chunks.size() * 4; }
532
533
117
  void writeTo(uint8_t *buf) const override {
534
207
    for (Chunk *c : chunks) {
535
207
      write32le(buf, c->getRVA());
536
207
      buf += 4;
537
207
    }
538
117
  }
539
540
private:
541
  std::vector<Chunk *> chunks;
542
};
543
544
class ExportOrdinalChunk : public NonSectionChunk {
545
public:
546
576
  explicit ExportOrdinalChunk(size_t i) : size(i) {}
547
129
  size_t getSize() const override { return size * 2; }
548
549
117
  void writeTo(uint8_t *buf) const override {
550
209
    for (Export &e : config->exports) {
551
209
      if (e.noname)
552
2
        continue;
553
207
      write16le(buf, e.ordinal);
554
207
      buf += 2;
555
207
    }
556
117
  }
557
558
private:
559
  size_t size;
560
};
561
562
} // anonymous namespace
563
564
49
void IdataContents::create() {
565
49
  std::vector<std::vector<DefinedImportData *>> v = binImports(imports);
566
49
567
49
  // Create .idata contents for each DLL.
568
49
  for (std::vector<DefinedImportData *> &syms : v) {
569
48
    // Create lookup and address tables. If they have external names,
570
48
    // we need to create hintName chunks to store the names.
571
48
    // If they don't (if they are import-by-ordinals), we store only
572
48
    // ordinal values to the table.
573
48
    size_t base = lookups.size();
574
92
    for (DefinedImportData *s : syms) {
575
92
      uint16_t ord = s->getOrdinal();
576
92
      if (s->getExternalName().empty()) {
577
12
        lookups.push_back(make<OrdinalOnlyChunk>(ord));
578
12
        addresses.push_back(make<OrdinalOnlyChunk>(ord));
579
12
        continue;
580
12
      }
581
80
      auto *c = make<HintNameChunk>(s->getExternalName(), ord);
582
80
      lookups.push_back(make<LookupChunk>(c));
583
80
      addresses.push_back(make<LookupChunk>(c));
584
80
      hints.push_back(c);
585
80
    }
586
48
    // Terminate with null values.
587
48
    lookups.push_back(make<NullChunk>(config->wordsize));
588
48
    addresses.push_back(make<NullChunk>(config->wordsize));
589
48
590
140
    for (int i = 0, e = syms.size(); i < e; 
++i92
)
591
92
      syms[i]->setLocation(addresses[base + i]);
592
48
593
48
    // Create the import table header.
594
48
    dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
595
48
    auto *dir = make<ImportDirectoryChunk>(dllNames.back());
596
48
    dir->lookupTab = lookups[base];
597
48
    dir->addressTab = addresses[base];
598
48
    dirs.push_back(dir);
599
48
  }
600
49
  // Add null terminator.
601
49
  dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
602
49
}
603
604
5
std::vector<Chunk *> DelayLoadContents::getChunks() {
605
5
  std::vector<Chunk *> v;
606
5
  v.insert(v.end(), dirs.begin(), dirs.end());
607
5
  v.insert(v.end(), names.begin(), names.end());
608
5
  v.insert(v.end(), hintNames.begin(), hintNames.end());
609
5
  v.insert(v.end(), dllNames.begin(), dllNames.end());
610
5
  return v;
611
5
}
612
613
5
std::vector<Chunk *> DelayLoadContents::getDataChunks() {
614
5
  std::vector<Chunk *> v;
615
5
  v.insert(v.end(), moduleHandles.begin(), moduleHandles.end());
616
5
  v.insert(v.end(), addresses.begin(), addresses.end());
617
5
  return v;
618
5
}
619
620
5
uint64_t DelayLoadContents::getDirSize() {
621
5
  return dirs.size() * sizeof(delay_import_directory_table_entry);
622
5
}
623
624
5
void DelayLoadContents::create(Defined *h) {
625
5
  helper = h;
626
5
  std::vector<std::vector<DefinedImportData *>> v = binImports(imports);
627
5
628
5
  // Create .didat contents for each DLL.
629
6
  for (std::vector<DefinedImportData *> &syms : v) {
630
6
    // Create the delay import table header.
631
6
    dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
632
6
    auto *dir = make<DelayDirectoryChunk>(dllNames.back());
633
6
634
6
    size_t base = addresses.size();
635
6
    Chunk *tm = newTailMergeChunk(dir);
636
11
    for (DefinedImportData *s : syms) {
637
11
      Chunk *t = newThunkChunk(s, tm);
638
11
      auto *a = make<DelayAddressChunk>(t);
639
11
      addresses.push_back(a);
640
11
      thunks.push_back(t);
641
11
      StringRef extName = s->getExternalName();
642
11
      if (extName.empty()) {
643
1
        names.push_back(make<OrdinalOnlyChunk>(s->getOrdinal()));
644
10
      } else {
645
10
        auto *c = make<HintNameChunk>(extName, 0);
646
10
        names.push_back(make<LookupChunk>(c));
647
10
        hintNames.push_back(c);
648
10
      }
649
11
    }
650
6
    thunks.push_back(tm);
651
6
    // Terminate with null values.
652
6
    addresses.push_back(make<NullChunk>(8));
653
6
    names.push_back(make<NullChunk>(8));
654
6
655
17
    for (int i = 0, e = syms.size(); i < e; 
++i11
)
656
11
      syms[i]->setLocation(addresses[base + i]);
657
6
    auto *mh = make<NullChunk>(8);
658
6
    mh->setAlignment(8);
659
6
    moduleHandles.push_back(mh);
660
6
661
6
    // Fill the delay import table header fields.
662
6
    dir->moduleHandle = mh;
663
6
    dir->addressTab = addresses[base];
664
6
    dir->nameTab = names[base];
665
6
    dirs.push_back(dir);
666
6
  }
667
5
  // Add null terminator.
668
5
  dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
669
5
}
670
671
6
Chunk *DelayLoadContents::newTailMergeChunk(Chunk *dir) {
672
6
  switch (config->machine) {
673
6
  case AMD64:
674
3
    return make<TailMergeChunkX64>(dir, helper);
675
6
  case I386:
676
1
    return make<TailMergeChunkX86>(dir, helper);
677
6
  case ARMNT:
678
1
    return make<TailMergeChunkARM>(dir, helper);
679
6
  case ARM64:
680
1
    return make<TailMergeChunkARM64>(dir, helper);
681
6
  default:
682
0
    llvm_unreachable("unsupported machine type");
683
6
  }
684
6
}
685
686
Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *s,
687
11
                                        Chunk *tailMerge) {
688
11
  switch (config->machine) {
689
11
  case AMD64:
690
7
    return make<ThunkChunkX64>(s, tailMerge);
691
11
  case I386:
692
2
    return make<ThunkChunkX86>(s, tailMerge);
693
11
  case ARMNT:
694
1
    return make<ThunkChunkARM>(s, tailMerge);
695
11
  case ARM64:
696
1
    return make<ThunkChunkARM64>(s, tailMerge);
697
11
  default:
698
0
    llvm_unreachable("unsupported machine type");
699
11
  }
700
11
}
701
702
576
EdataContents::EdataContents() {
703
576
  uint16_t maxOrdinal = 0;
704
576
  for (Export &e : config->exports)
705
209
    maxOrdinal = std::max(maxOrdinal, e.ordinal);
706
576
707
576
  auto *dllName = make<StringChunk>(sys::path::filename(config->outputFile));
708
576
  auto *addressTab = make<AddressTableChunk>(maxOrdinal);
709
576
  std::vector<Chunk *> names;
710
576
  for (Export &e : config->exports)
711
209
    if (!e.noname)
712
207
      names.push_back(make<StringChunk>(e.exportName));
713
576
714
576
  std::vector<Chunk *> forwards;
715
576
  for (Export &e : config->exports) {
716
209
    if (e.forwardTo.empty())
717
207
      continue;
718
2
    e.forwardChunk = make<StringChunk>(e.forwardTo);
719
2
    forwards.push_back(e.forwardChunk);
720
2
  }
721
576
722
576
  auto *nameTab = make<NamePointersChunk>(names);
723
576
  auto *ordinalTab = make<ExportOrdinalChunk>(names.size());
724
576
  auto *dir = make<ExportDirectoryChunk>(maxOrdinal, names.size(), dllName,
725
576
                                         addressTab, nameTab, ordinalTab);
726
576
  chunks.push_back(dir);
727
576
  chunks.push_back(dllName);
728
576
  chunks.push_back(addressTab);
729
576
  chunks.push_back(nameTab);
730
576
  chunks.push_back(ordinalTab);
731
576
  chunks.insert(chunks.end(), names.begin(), names.end());
732
576
  chunks.insert(chunks.end(), forwards.begin(), forwards.end());
733
576
}
734
735
} // namespace coff
736
} // namespace lld