Coverage Report

Created: 2019-05-19 14:56

/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 Chunk {
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 Chunk {
61
public:
62
170
  explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = Config->Wordsize; }
63
266
  size_t getSize() const override { return Config->Wordsize; }
64
65
170
  void writeTo(uint8_t *Buf) const override {
66
170
    if (Config->is64())
67
125
      write64le(Buf, HintName->getRVA());
68
45
    else
69
45
      write32le(Buf, HintName->getRVA());
70
170
  }
71
72
  Chunk *HintName;
73
};
74
75
// A chunk for the import descriptor table.
76
// This chunk represent import-by-ordinal symbols.
77
// See Microsoft PE/COFF spec 7.1. Import Header for details.
78
class OrdinalOnlyChunk : public Chunk {
79
public:
80
25
  explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {
81
25
    Alignment = Config->Wordsize;
82
25
  }
83
37
  size_t getSize() const override { return Config->Wordsize; }
84
85
25
  void writeTo(uint8_t *Buf) const override {
86
25
    // An import-by-ordinal slot has MSB 1 to indicate that
87
25
    // this is import-by-ordinal (and not import-by-name).
88
25
    if (Config->is64()) {
89
25
      write64le(Buf, (1ULL << 63) | Ordinal);
90
25
    } else {
91
0
      write32le(Buf, (1ULL << 31) | Ordinal);
92
0
    }
93
25
  }
94
95
  uint16_t Ordinal;
96
};
97
98
// A chunk for the import descriptor table.
99
class ImportDirectoryChunk : public Chunk {
100
public:
101
48
  explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
102
148
  size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
103
104
48
  void writeTo(uint8_t *Buf) const override {
105
48
    memset(Buf, 0, getSize());
106
48
107
48
    auto *E = (coff_import_directory_table_entry *)(Buf);
108
48
    E->ImportLookupTableRVA = LookupTab->getRVA();
109
48
    E->NameRVA = DLLName->getRVA();
110
48
    E->ImportAddressTableRVA = AddressTab->getRVA();
111
48
  }
112
113
  Chunk *DLLName;
114
  Chunk *LookupTab;
115
  Chunk *AddressTab;
116
};
117
118
// A chunk representing null terminator in the import table.
119
// Contents of this chunk is always null bytes.
120
class NullChunk : public Chunk {
121
public:
122
168
  explicit NullChunk(size_t N) : Size(N) {}
123
168
  bool hasData() const override { return false; }
124
289
  size_t getSize() const override { return Size; }
125
126
168
  void writeTo(uint8_t *Buf) const override {
127
168
    memset(Buf, 0, Size);
128
168
  }
129
130
private:
131
  size_t Size;
132
};
133
134
static std::vector<std::vector<DefinedImportData *>>
135
54
binImports(const std::vector<DefinedImportData *> &Imports) {
136
54
  // Group DLL-imported symbols by DLL name because that's how
137
54
  // symbols are layed out in the import descriptor table.
138
104
  auto Less = [](const std::string &A, const std::string &B) {
139
104
    return Config->DLLOrder[A] < Config->DLLOrder[B];
140
104
  };
141
54
  std::map<std::string, std::vector<DefinedImportData *>,
142
54
           bool(*)(const std::string &, const std::string &)> M(Less);
143
54
  for (DefinedImportData *Sym : Imports)
144
103
    M[Sym->getDLLName().lower()].push_back(Sym);
145
54
146
54
  std::vector<std::vector<DefinedImportData *>> V;
147
54
  for (auto &KV : M) {
148
54
    // Sort symbols by name for each group.
149
54
    std::vector<DefinedImportData *> &Syms = KV.second;
150
54
    std::sort(Syms.begin(), Syms.end(),
151
54
              [](DefinedImportData *A, DefinedImportData *B) {
152
52
                return A->getName() < B->getName();
153
52
              });
154
54
    V.push_back(std::move(Syms));
155
54
  }
156
54
  return V;
157
54
}
158
159
// Export table
160
// See Microsoft PE/COFF spec 4.3 for details.
161
162
// A chunk for the delay import descriptor table etnry.
163
class DelayDirectoryChunk : public Chunk {
164
public:
165
6
  explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
166
167
12
  size_t getSize() const override {
168
12
    return sizeof(delay_import_directory_table_entry);
169
12
  }
170
171
6
  void writeTo(uint8_t *Buf) const override {
172
6
    memset(Buf, 0, getSize());
173
6
174
6
    auto *E = (delay_import_directory_table_entry *)(Buf);
175
6
    E->Attributes = 1;
176
6
    E->Name = DLLName->getRVA();
177
6
    E->ModuleHandle = ModuleHandle->getRVA();
178
6
    E->DelayImportAddressTable = AddressTab->getRVA();
179
6
    E->DelayImportNameTable = NameTab->getRVA();
180
6
  }
181
182
  Chunk *DLLName;
183
  Chunk *ModuleHandle;
184
  Chunk *AddressTab;
185
  Chunk *NameTab;
186
};
187
188
// Initial contents for delay-loaded functions.
189
// This code calls __delayLoadHelper2 function to resolve a symbol
190
// and then overwrites its jump table slot with the result
191
// for subsequent function calls.
192
static const uint8_t ThunkX64[] = {
193
    0x51,                               // push    rcx
194
    0x52,                               // push    rdx
195
    0x41, 0x50,                         // push    r8
196
    0x41, 0x51,                         // push    r9
197
    0x48, 0x83, 0xEC, 0x48,             // sub     rsp, 48h
198
    0x66, 0x0F, 0x7F, 0x04, 0x24,       // movdqa  xmmword ptr [rsp], xmm0
199
    0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa  xmmword ptr [rsp+10h], xmm1
200
    0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa  xmmword ptr [rsp+20h], xmm2
201
    0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa  xmmword ptr [rsp+30h], xmm3
202
    0x48, 0x8D, 0x15, 0, 0, 0, 0,       // lea     rdx, [__imp_<FUNCNAME>]
203
    0x48, 0x8D, 0x0D, 0, 0, 0, 0,       // lea     rcx, [___DELAY_IMPORT_...]
204
    0xE8, 0, 0, 0, 0,                   // call    __delayLoadHelper2
205
    0x66, 0x0F, 0x6F, 0x04, 0x24,       // movdqa  xmm0, xmmword ptr [rsp]
206
    0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa  xmm1, xmmword ptr [rsp+10h]
207
    0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa  xmm2, xmmword ptr [rsp+20h]
208
    0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa  xmm3, xmmword ptr [rsp+30h]
209
    0x48, 0x83, 0xC4, 0x48,             // add     rsp, 48h
210
    0x41, 0x59,                         // pop     r9
211
    0x41, 0x58,                         // pop     r8
212
    0x5A,                               // pop     rdx
213
    0x59,                               // pop     rcx
214
    0xFF, 0xE0,                         // jmp     rax
215
};
216
217
static const uint8_t ThunkX86[] = {
218
    0x51,              // push  ecx
219
    0x52,              // push  edx
220
    0x68, 0, 0, 0, 0,  // push  offset ___imp__<FUNCNAME>
221
    0x68, 0, 0, 0, 0,  // push  offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
222
    0xE8, 0, 0, 0, 0,  // call  ___delayLoadHelper2@8
223
    0x5A,              // pop   edx
224
    0x59,              // pop   ecx
225
    0xFF, 0xE0,        // jmp   eax
226
};
227
228
static const uint8_t ThunkARM[] = {
229
    0x40, 0xf2, 0x00, 0x0c, // mov.w   ip, #0 __imp_<FUNCNAME>
230
    0xc0, 0xf2, 0x00, 0x0c, // mov.t   ip, #0 __imp_<FUNCNAME>
231
    0x2d, 0xe9, 0x0f, 0x48, // push.w  {r0, r1, r2, r3, r11, lr}
232
    0x0d, 0xf2, 0x10, 0x0b, // addw    r11, sp, #16
233
    0x2d, 0xed, 0x10, 0x0b, // vpush   {d0, d1, d2, d3, d4, d5, d6, d7}
234
    0x61, 0x46,             // mov     r1, ip
235
    0x40, 0xf2, 0x00, 0x00, // mov.w   r0, #0 DELAY_IMPORT_DESCRIPTOR
236
    0xc0, 0xf2, 0x00, 0x00, // mov.t   r0, #0 DELAY_IMPORT_DESCRIPTOR
237
    0x00, 0xf0, 0x00, 0xd0, // bl      #0 __delayLoadHelper2
238
    0x84, 0x46,             // mov     ip, r0
239
    0xbd, 0xec, 0x10, 0x0b, // vpop    {d0, d1, d2, d3, d4, d5, d6, d7}
240
    0xbd, 0xe8, 0x0f, 0x48, // pop.w   {r0, r1, r2, r3, r11, lr}
241
    0x60, 0x47,             // bx      ip
242
};
243
244
static const uint8_t ThunkARM64[] = {
245
    0x11, 0x00, 0x00, 0x90, // adrp    x17, #0      __imp_<FUNCNAME>
246
    0x31, 0x02, 0x00, 0x91, // add     x17, x17, #0 :lo12:__imp_<FUNCNAME>
247
    0xfd, 0x7b, 0xb3, 0xa9, // stp     x29, x30, [sp, #-208]!
248
    0xfd, 0x03, 0x00, 0x91, // mov     x29, sp
249
    0xe0, 0x07, 0x01, 0xa9, // stp     x0, x1, [sp, #16]
250
    0xe2, 0x0f, 0x02, 0xa9, // stp     x2, x3, [sp, #32]
251
    0xe4, 0x17, 0x03, 0xa9, // stp     x4, x5, [sp, #48]
252
    0xe6, 0x1f, 0x04, 0xa9, // stp     x6, x7, [sp, #64]
253
    0xe0, 0x87, 0x02, 0xad, // stp     q0, q1, [sp, #80]
254
    0xe2, 0x8f, 0x03, 0xad, // stp     q2, q3, [sp, #112]
255
    0xe4, 0x97, 0x04, 0xad, // stp     q4, q5, [sp, #144]
256
    0xe6, 0x9f, 0x05, 0xad, // stp     q6, q7, [sp, #176]
257
    0xe1, 0x03, 0x11, 0xaa, // mov     x1, x17
258
    0x00, 0x00, 0x00, 0x90, // adrp    x0, #0     DELAY_IMPORT_DESCRIPTOR
259
    0x00, 0x00, 0x00, 0x91, // add     x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR
260
    0x00, 0x00, 0x00, 0x94, // bl      #0 __delayLoadHelper2
261
    0xf0, 0x03, 0x00, 0xaa, // mov     x16, x0
262
    0xe6, 0x9f, 0x45, 0xad, // ldp     q6, q7, [sp, #176]
263
    0xe4, 0x97, 0x44, 0xad, // ldp     q4, q5, [sp, #144]
264
    0xe2, 0x8f, 0x43, 0xad, // ldp     q2, q3, [sp, #112]
265
    0xe0, 0x87, 0x42, 0xad, // ldp     q0, q1, [sp, #80]
266
    0xe6, 0x1f, 0x44, 0xa9, // ldp     x6, x7, [sp, #64]
267
    0xe4, 0x17, 0x43, 0xa9, // ldp     x4, x5, [sp, #48]
268
    0xe2, 0x0f, 0x42, 0xa9, // ldp     x2, x3, [sp, #32]
269
    0xe0, 0x07, 0x41, 0xa9, // ldp     x0, x1, [sp, #16]
270
    0xfd, 0x7b, 0xcd, 0xa8, // ldp     x29, x30, [sp], #208
271
    0x00, 0x02, 0x1f, 0xd6, // br      x16
272
};
273
274
// A chunk for the delay import thunk.
275
class ThunkChunkX64 : public Chunk {
276
public:
277
  ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
278
7
      : Imp(I), Desc(D), Helper(H) {}
279
280
7
  size_t getSize() const override { return sizeof(ThunkX64); }
281
282
7
  void writeTo(uint8_t *Buf) const override {
283
7
    memcpy(Buf, ThunkX64, sizeof(ThunkX64));
284
7
    write32le(Buf + 36, Imp->getRVA() - RVA - 40);
285
7
    write32le(Buf + 43, Desc->getRVA() - RVA - 47);
286
7
    write32le(Buf + 48, Helper->getRVA() - RVA - 52);
287
7
  }
288
289
  Defined *Imp = nullptr;
290
  Chunk *Desc = nullptr;
291
  Defined *Helper = nullptr;
292
};
293
294
class ThunkChunkX86 : public Chunk {
295
public:
296
  ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
297
2
      : Imp(I), Desc(D), Helper(H) {}
298
299
2
  size_t getSize() const override { return sizeof(ThunkX86); }
300
301
2
  void writeTo(uint8_t *Buf) const override {
302
2
    memcpy(Buf, ThunkX86, sizeof(ThunkX86));
303
2
    write32le(Buf + 3, Imp->getRVA() + Config->ImageBase);
304
2
    write32le(Buf + 8, Desc->getRVA() + Config->ImageBase);
305
2
    write32le(Buf + 13, Helper->getRVA() - RVA - 17);
306
2
  }
307
308
2
  void getBaserels(std::vector<Baserel> *Res) override {
309
2
    Res->emplace_back(RVA + 3);
310
2
    Res->emplace_back(RVA + 8);
311
2
  }
312
313
  Defined *Imp = nullptr;
314
  Chunk *Desc = nullptr;
315
  Defined *Helper = nullptr;
316
};
317
318
class ThunkChunkARM : public Chunk {
319
public:
320
  ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
321
1
      : Imp(I), Desc(D), Helper(H) {}
322
323
1
  size_t getSize() const override { return sizeof(ThunkARM); }
324
325
1
  void writeTo(uint8_t *Buf) const override {
326
1
    memcpy(Buf, ThunkARM, sizeof(ThunkARM));
327
1
    applyMOV32T(Buf + 0, Imp->getRVA() + Config->ImageBase);
328
1
    applyMOV32T(Buf + 22, Desc->getRVA() + Config->ImageBase);
329
1
    applyBranch24T(Buf + 30, Helper->getRVA() - RVA - 34);
330
1
  }
331
332
1
  void getBaserels(std::vector<Baserel> *Res) override {
333
1
    Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
334
1
    Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
335
1
  }
336
337
  Defined *Imp = nullptr;
338
  Chunk *Desc = nullptr;
339
  Defined *Helper = nullptr;
340
};
341
342
class ThunkChunkARM64 : public Chunk {
343
public:
344
  ThunkChunkARM64(Defined *I, Chunk *D, Defined *H)
345
1
      : Imp(I), Desc(D), Helper(H) {}
346
347
1
  size_t getSize() const override { return sizeof(ThunkARM64); }
348
349
1
  void writeTo(uint8_t *Buf) const override {
350
1
    memcpy(Buf, ThunkARM64, sizeof(ThunkARM64));
351
1
    applyArm64Addr(Buf + 0, Imp->getRVA(), RVA + 0, 12);
352
1
    applyArm64Imm(Buf + 4, Imp->getRVA() & 0xfff, 0);
353
1
    applyArm64Addr(Buf + 52, Desc->getRVA(), RVA + 52, 12);
354
1
    applyArm64Imm(Buf + 56, Desc->getRVA() & 0xfff, 0);
355
1
    applyArm64Branch26(Buf + 60, Helper->getRVA() - RVA - 60);
356
1
  }
357
358
  Defined *Imp = nullptr;
359
  Chunk *Desc = nullptr;
360
  Defined *Helper = nullptr;
361
};
362
363
// A chunk for the import descriptor table.
364
class DelayAddressChunk : public Chunk {
365
public:
366
11
  explicit DelayAddressChunk(Chunk *C) : Thunk(C) {
367
11
    Alignment = Config->Wordsize;
368
11
  }
369
11
  size_t getSize() const override { return Config->Wordsize; }
370
371
11
  void writeTo(uint8_t *Buf) const override {
372
11
    if (Config->is64()) {
373
8
      write64le(Buf, Thunk->getRVA() + Config->ImageBase);
374
8
    } else {
375
3
      uint32_t Bit = 0;
376
3
      // Pointer to thumb code must have the LSB set, so adjust it.
377
3
      if (Config->Machine == ARMNT)
378
1
        Bit = 1;
379
3
      write32le(Buf, (Thunk->getRVA() + Config->ImageBase) | Bit);
380
3
    }
381
11
  }
382
383
11
  void getBaserels(std::vector<Baserel> *Res) override {
384
11
    Res->emplace_back(RVA);
385
11
  }
386
387
  Chunk *Thunk;
388
};
389
390
// Export table
391
// Read Microsoft PE/COFF spec 5.3 for details.
392
393
// A chunk for the export descriptor table.
394
class ExportDirectoryChunk : public Chunk {
395
public:
396
  ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
397
      : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
398
544
        OrdinalTab(O) {}
399
400
242
  size_t getSize() const override {
401
242
    return sizeof(export_directory_table_entry);
402
242
  }
403
404
115
  void writeTo(uint8_t *Buf) const override {
405
115
    memset(Buf, 0, getSize());
406
115
407
115
    auto *E = (export_directory_table_entry *)(Buf);
408
115
    E->NameRVA = DLLName->getRVA();
409
115
    E->OrdinalBase = 0;
410
115
    E->AddressTableEntries = MaxOrdinal + 1;
411
115
    E->NumberOfNamePointers = NameTabSize;
412
115
    E->ExportAddressTableRVA = AddressTab->getRVA();
413
115
    E->NamePointerRVA = NameTab->getRVA();
414
115
    E->OrdinalTableRVA = OrdinalTab->getRVA();
415
115
  }
416
417
  uint16_t MaxOrdinal;
418
  uint16_t NameTabSize;
419
  Chunk *DLLName;
420
  Chunk *AddressTab;
421
  Chunk *NameTab;
422
  Chunk *OrdinalTab;
423
};
424
425
class AddressTableChunk : public Chunk {
426
public:
427
544
  explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
428
242
  size_t getSize() const override { return Size * 4; }
429
430
115
  void writeTo(uint8_t *Buf) const override {
431
115
    memset(Buf, 0, getSize());
432
115
433
206
    for (const Export &E : Config->Exports) {
434
206
      uint8_t *P = Buf + E.Ordinal * 4;
435
206
      uint32_t Bit = 0;
436
206
      // Pointer to thumb code must have the LSB set, so adjust it.
437
206
      if (Config->Machine == ARMNT && 
!E.Data6
)
438
3
        Bit = 1;
439
206
      if (E.ForwardChunk) {
440
2
        write32le(P, E.ForwardChunk->getRVA() | Bit);
441
204
      } else {
442
204
        write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);
443
204
      }
444
206
    }
445
115
  }
446
447
private:
448
  size_t Size;
449
};
450
451
class NamePointersChunk : public Chunk {
452
public:
453
544
  explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
454
127
  size_t getSize() const override { return Chunks.size() * 4; }
455
456
115
  void writeTo(uint8_t *Buf) const override {
457
204
    for (Chunk *C : Chunks) {
458
204
      write32le(Buf, C->getRVA());
459
204
      Buf += 4;
460
204
    }
461
115
  }
462
463
private:
464
  std::vector<Chunk *> Chunks;
465
};
466
467
class ExportOrdinalChunk : public Chunk {
468
public:
469
544
  explicit ExportOrdinalChunk(size_t I) : Size(I) {}
470
127
  size_t getSize() const override { return Size * 2; }
471
472
115
  void writeTo(uint8_t *Buf) const override {
473
206
    for (Export &E : Config->Exports) {
474
206
      if (E.Noname)
475
2
        continue;
476
204
      write16le(Buf, E.Ordinal);
477
204
      Buf += 2;
478
204
    }
479
115
  }
480
481
private:
482
  size_t Size;
483
};
484
485
} // anonymous namespace
486
487
49
void IdataContents::create() {
488
49
  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
489
49
490
49
  // Create .idata contents for each DLL.
491
49
  for (std::vector<DefinedImportData *> &Syms : V) {
492
48
    // Create lookup and address tables. If they have external names,
493
48
    // we need to create HintName chunks to store the names.
494
48
    // If they don't (if they are import-by-ordinals), we store only
495
48
    // ordinal values to the table.
496
48
    size_t Base = Lookups.size();
497
92
    for (DefinedImportData *S : Syms) {
498
92
      uint16_t Ord = S->getOrdinal();
499
92
      if (S->getExternalName().empty()) {
500
12
        Lookups.push_back(make<OrdinalOnlyChunk>(Ord));
501
12
        Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
502
12
        continue;
503
12
      }
504
80
      auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
505
80
      Lookups.push_back(make<LookupChunk>(C));
506
80
      Addresses.push_back(make<LookupChunk>(C));
507
80
      Hints.push_back(C);
508
80
    }
509
48
    // Terminate with null values.
510
48
    Lookups.push_back(make<NullChunk>(Config->Wordsize));
511
48
    Addresses.push_back(make<NullChunk>(Config->Wordsize));
512
48
513
140
    for (int I = 0, E = Syms.size(); I < E; 
++I92
)
514
92
      Syms[I]->setLocation(Addresses[Base + I]);
515
48
516
48
    // Create the import table header.
517
48
    DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
518
48
    auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
519
48
    Dir->LookupTab = Lookups[Base];
520
48
    Dir->AddressTab = Addresses[Base];
521
48
    Dirs.push_back(Dir);
522
48
  }
523
49
  // Add null terminator.
524
49
  Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
525
49
}
526
527
5
std::vector<Chunk *> DelayLoadContents::getChunks() {
528
5
  std::vector<Chunk *> V;
529
5
  V.insert(V.end(), Dirs.begin(), Dirs.end());
530
5
  V.insert(V.end(), Names.begin(), Names.end());
531
5
  V.insert(V.end(), HintNames.begin(), HintNames.end());
532
5
  V.insert(V.end(), DLLNames.begin(), DLLNames.end());
533
5
  return V;
534
5
}
535
536
5
std::vector<Chunk *> DelayLoadContents::getDataChunks() {
537
5
  std::vector<Chunk *> V;
538
5
  V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
539
5
  V.insert(V.end(), Addresses.begin(), Addresses.end());
540
5
  return V;
541
5
}
542
543
5
uint64_t DelayLoadContents::getDirSize() {
544
5
  return Dirs.size() * sizeof(delay_import_directory_table_entry);
545
5
}
546
547
5
void DelayLoadContents::create(Defined *H) {
548
5
  Helper = H;
549
5
  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
550
5
551
5
  // Create .didat contents for each DLL.
552
6
  for (std::vector<DefinedImportData *> &Syms : V) {
553
6
    // Create the delay import table header.
554
6
    DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
555
6
    auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
556
6
557
6
    size_t Base = Addresses.size();
558
11
    for (DefinedImportData *S : Syms) {
559
11
      Chunk *T = newThunkChunk(S, Dir);
560
11
      auto *A = make<DelayAddressChunk>(T);
561
11
      Addresses.push_back(A);
562
11
      Thunks.push_back(T);
563
11
      StringRef ExtName = S->getExternalName();
564
11
      if (ExtName.empty()) {
565
1
        Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
566
10
      } else {
567
10
        auto *C = make<HintNameChunk>(ExtName, 0);
568
10
        Names.push_back(make<LookupChunk>(C));
569
10
        HintNames.push_back(C);
570
10
      }
571
11
    }
572
6
    // Terminate with null values.
573
6
    Addresses.push_back(make<NullChunk>(8));
574
6
    Names.push_back(make<NullChunk>(8));
575
6
576
17
    for (int I = 0, E = Syms.size(); I < E; 
++I11
)
577
11
      Syms[I]->setLocation(Addresses[Base + I]);
578
6
    auto *MH = make<NullChunk>(8);
579
6
    MH->Alignment = 8;
580
6
    ModuleHandles.push_back(MH);
581
6
582
6
    // Fill the delay import table header fields.
583
6
    Dir->ModuleHandle = MH;
584
6
    Dir->AddressTab = Addresses[Base];
585
6
    Dir->NameTab = Names[Base];
586
6
    Dirs.push_back(Dir);
587
6
  }
588
5
  // Add null terminator.
589
5
  Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
590
5
}
591
592
11
Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
593
11
  switch (Config->Machine) {
594
11
  case AMD64:
595
7
    return make<ThunkChunkX64>(S, Dir, Helper);
596
11
  case I386:
597
2
    return make<ThunkChunkX86>(S, Dir, Helper);
598
11
  case ARMNT:
599
1
    return make<ThunkChunkARM>(S, Dir, Helper);
600
11
  case ARM64:
601
1
    return make<ThunkChunkARM64>(S, Dir, Helper);
602
11
  default:
603
0
    llvm_unreachable("unsupported machine type");
604
11
  }
605
11
}
606
607
544
EdataContents::EdataContents() {
608
544
  uint16_t MaxOrdinal = 0;
609
544
  for (Export &E : Config->Exports)
610
206
    MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
611
544
612
544
  auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
613
544
  auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
614
544
  std::vector<Chunk *> Names;
615
544
  for (Export &E : Config->Exports)
616
206
    if (!E.Noname)
617
204
      Names.push_back(make<StringChunk>(E.ExportName));
618
544
619
544
  std::vector<Chunk *> Forwards;
620
544
  for (Export &E : Config->Exports) {
621
206
    if (E.ForwardTo.empty())
622
204
      continue;
623
2
    E.ForwardChunk = make<StringChunk>(E.ForwardTo);
624
2
    Forwards.push_back(E.ForwardChunk);
625
2
  }
626
544
627
544
  auto *NameTab = make<NamePointersChunk>(Names);
628
544
  auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
629
544
  auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
630
544
                                         AddressTab, NameTab, OrdinalTab);
631
544
  Chunks.push_back(Dir);
632
544
  Chunks.push_back(DLLName);
633
544
  Chunks.push_back(AddressTab);
634
544
  Chunks.push_back(NameTab);
635
544
  Chunks.push_back(OrdinalTab);
636
544
  Chunks.insert(Chunks.end(), Names.begin(), Names.end());
637
544
  Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());
638
544
}
639
640
} // namespace coff
641
} // namespace lld