Coverage Report

Created: 2018-10-20 12:32

/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
//                             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
//
10
// This file defines various types of chunks for the DLL import or export
11
// descriptor tables. They are inherently Windows-specific.
12
// 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 "DLL.h"
22
#include "Chunks.h"
23
#include "llvm/Object/COFF.h"
24
#include "llvm/Support/Endian.h"
25
#include "llvm/Support/Path.h"
26
27
using namespace llvm;
28
using namespace llvm::object;
29
using namespace llvm::support::endian;
30
using namespace llvm::COFF;
31
32
namespace lld {
33
namespace coff {
34
namespace {
35
36
// Import table
37
38
// A chunk for the import descriptor table.
39
class HintNameChunk : public Chunk {
40
public:
41
81
  HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
42
43
89
  size_t getSize() const override {
44
89
    // Starts with 2 byte Hint field, followed by a null-terminated string,
45
89
    // ends with 0 or 1 byte padding.
46
89
    return alignTo(Name.size() + 3, 2);
47
89
  }
48
49
81
  void writeTo(uint8_t *Buf) const override {
50
81
    write16le(Buf + OutputSectionOff, Hint);
51
81
    memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
52
81
  }
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
156
  explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = Config->Wordsize; }
63
247
  size_t getSize() const override { return Config->Wordsize; }
64
65
156
  void writeTo(uint8_t *Buf) const override {
66
156
    write32le(Buf + OutputSectionOff, HintName->getRVA());
67
156
  }
68
69
  Chunk *HintName;
70
};
71
72
// A chunk for the import descriptor table.
73
// This chunk represent import-by-ordinal symbols.
74
// See Microsoft PE/COFF spec 7.1. Import Header for details.
75
class OrdinalOnlyChunk : public Chunk {
76
public:
77
23
  explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {
78
23
    Alignment = Config->Wordsize;
79
23
  }
80
34
  size_t getSize() const override { return Config->Wordsize; }
81
82
23
  void writeTo(uint8_t *Buf) const override {
83
23
    // An import-by-ordinal slot has MSB 1 to indicate that
84
23
    // this is import-by-ordinal (and not import-by-name).
85
23
    if (Config->is64()) {
86
23
      write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);
87
23
    } else {
88
0
      write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);
89
0
    }
90
23
  }
91
92
  uint16_t Ordinal;
93
};
94
95
// A chunk for the import descriptor table.
96
class ImportDirectoryChunk : public Chunk {
97
public:
98
44
  explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
99
92
  size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
100
101
44
  void writeTo(uint8_t *Buf) const override {
102
44
    auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
103
44
    E->ImportLookupTableRVA = LookupTab->getRVA();
104
44
    E->NameRVA = DLLName->getRVA();
105
44
    E->ImportAddressTableRVA = AddressTab->getRVA();
106
44
  }
107
108
  Chunk *DLLName;
109
  Chunk *LookupTab;
110
  Chunk *AddressTab;
111
};
112
113
// A chunk representing null terminator in the import table.
114
// Contents of this chunk is always null bytes.
115
class NullChunk : public Chunk {
116
public:
117
149
  explicit NullChunk(size_t N) : Size(N) {}
118
149
  bool hasData() const override { return false; }
119
250
  size_t getSize() const override { return Size; }
120
121
private:
122
  size_t Size;
123
};
124
125
static std::vector<std::vector<DefinedImportData *>>
126
49
binImports(const std::vector<DefinedImportData *> &Imports) {
127
49
  // Group DLL-imported symbols by DLL name because that's how
128
49
  // symbols are layed out in the import descriptor table.
129
92
  auto Less = [](const std::string &A, const std::string &B) {
130
92
    return Config->DLLOrder[A] < Config->DLLOrder[B];
131
92
  };
132
49
  std::map<std::string, std::vector<DefinedImportData *>,
133
49
           bool(*)(const std::string &, const std::string &)> M(Less);
134
49
  for (DefinedImportData *Sym : Imports)
135
93
    M[Sym->getDLLName().lower()].push_back(Sym);
136
49
137
49
  std::vector<std::vector<DefinedImportData *>> V;
138
49
  for (auto &KV : M) {
139
48
    // Sort symbols by name for each group.
140
48
    std::vector<DefinedImportData *> &Syms = KV.second;
141
48
    std::sort(Syms.begin(), Syms.end(),
142
48
              [](DefinedImportData *A, DefinedImportData *B) {
143
48
                return A->getName() < B->getName();
144
48
              });
145
48
    V.push_back(std::move(Syms));
146
48
  }
147
49
  return V;
148
49
}
149
150
// Export table
151
// See Microsoft PE/COFF spec 4.3 for details.
152
153
// A chunk for the delay import descriptor table etnry.
154
class DelayDirectoryChunk : public Chunk {
155
public:
156
4
  explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
157
158
4
  size_t getSize() const override {
159
4
    return sizeof(delay_import_directory_table_entry);
160
4
  }
161
162
4
  void writeTo(uint8_t *Buf) const override {
163
4
    auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
164
4
    E->Attributes = 1;
165
4
    E->Name = DLLName->getRVA();
166
4
    E->ModuleHandle = ModuleHandle->getRVA();
167
4
    E->DelayImportAddressTable = AddressTab->getRVA();
168
4
    E->DelayImportNameTable = NameTab->getRVA();
169
4
  }
170
171
  Chunk *DLLName;
172
  Chunk *ModuleHandle;
173
  Chunk *AddressTab;
174
  Chunk *NameTab;
175
};
176
177
// Initial contents for delay-loaded functions.
178
// This code calls __delayLoadHelper2 function to resolve a symbol
179
// and then overwrites its jump table slot with the result
180
// for subsequent function calls.
181
static const uint8_t ThunkX64[] = {
182
    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
206
static 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
217
static 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
233
static 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
263
// A chunk for the delay import thunk.
264
class ThunkChunkX64 : public Chunk {
265
public:
266
  ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
267
3
      : Imp(I), Desc(D), Helper(H) {}
268
269
3
  size_t getSize() const override { return sizeof(ThunkX64); }
270
271
3
  void writeTo(uint8_t *Buf) const override {
272
3
    memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
273
3
    write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
274
3
    write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
275
3
    write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
276
3
  }
277
278
  Defined *Imp = nullptr;
279
  Chunk *Desc = nullptr;
280
  Defined *Helper = nullptr;
281
};
282
283
class ThunkChunkX86 : public Chunk {
284
public:
285
  ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
286
2
      : Imp(I), Desc(D), Helper(H) {}
287
288
2
  size_t getSize() const override { return sizeof(ThunkX86); }
289
290
2
  void writeTo(uint8_t *Buf) const override {
291
2
    memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
292
2
    write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
293
2
    write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
294
2
    write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
295
2
  }
296
297
2
  void getBaserels(std::vector<Baserel> *Res) override {
298
2
    Res->emplace_back(RVA + 3);
299
2
    Res->emplace_back(RVA + 8);
300
2
  }
301
302
  Defined *Imp = nullptr;
303
  Chunk *Desc = nullptr;
304
  Defined *Helper = nullptr;
305
};
306
307
class ThunkChunkARM : public Chunk {
308
public:
309
  ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
310
1
      : Imp(I), Desc(D), Helper(H) {}
311
312
1
  size_t getSize() const override { return sizeof(ThunkARM); }
313
314
1
  void writeTo(uint8_t *Buf) const override {
315
1
    memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM));
316
1
    applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase);
317
1
    applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase);
318
1
    applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34);
319
1
  }
320
321
1
  void getBaserels(std::vector<Baserel> *Res) override {
322
1
    Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
323
1
    Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
324
1
  }
325
326
  Defined *Imp = nullptr;
327
  Chunk *Desc = nullptr;
328
  Defined *Helper = nullptr;
329
};
330
331
class ThunkChunkARM64 : public Chunk {
332
public:
333
  ThunkChunkARM64(Defined *I, Chunk *D, Defined *H)
334
1
      : Imp(I), Desc(D), Helper(H) {}
335
336
1
  size_t getSize() const override { return sizeof(ThunkARM64); }
337
338
1
  void writeTo(uint8_t *Buf) const override {
339
1
    memcpy(Buf + OutputSectionOff, ThunkARM64, sizeof(ThunkARM64));
340
1
    applyArm64Addr(Buf + OutputSectionOff + 0, Imp->getRVA(), RVA + 0, 12);
341
1
    applyArm64Imm(Buf + OutputSectionOff + 4, Imp->getRVA() & 0xfff, 0);
342
1
    applyArm64Addr(Buf + OutputSectionOff + 52, Desc->getRVA(), RVA + 52, 12);
343
1
    applyArm64Imm(Buf + OutputSectionOff + 56, Desc->getRVA() & 0xfff, 0);
344
1
    applyArm64Branch26(Buf + OutputSectionOff + 60,
345
1
                       Helper->getRVA() - RVA - 60);
346
1
  }
347
348
  Defined *Imp = nullptr;
349
  Chunk *Desc = nullptr;
350
  Defined *Helper = nullptr;
351
};
352
353
// A chunk for the import descriptor table.
354
class DelayAddressChunk : public Chunk {
355
public:
356
7
  explicit DelayAddressChunk(Chunk *C) : Thunk(C) {
357
7
    Alignment = Config->Wordsize;
358
7
  }
359
7
  size_t getSize() const override { return Config->Wordsize; }
360
361
7
  void writeTo(uint8_t *Buf) const override {
362
7
    if (Config->is64()) {
363
4
      write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
364
4
    } else {
365
3
      uint32_t Bit = 0;
366
3
      // Pointer to thumb code must have the LSB set, so adjust it.
367
3
      if (Config->Machine == ARMNT)
368
1
        Bit = 1;
369
3
      write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit);
370
3
    }
371
7
  }
372
373
7
  void getBaserels(std::vector<Baserel> *Res) override {
374
7
    Res->emplace_back(RVA);
375
7
  }
376
377
  Chunk *Thunk;
378
};
379
380
// Export table
381
// Read Microsoft PE/COFF spec 5.3 for details.
382
383
// A chunk for the export descriptor table.
384
class ExportDirectoryChunk : public Chunk {
385
public:
386
  ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
387
      : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
388
479
        OrdinalTab(O) {}
389
390
116
  size_t getSize() const override {
391
116
    return sizeof(export_directory_table_entry);
392
116
  }
393
394
104
  void writeTo(uint8_t *Buf) const override {
395
104
    auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
396
104
    E->NameRVA = DLLName->getRVA();
397
104
    E->OrdinalBase = 0;
398
104
    E->AddressTableEntries = MaxOrdinal + 1;
399
104
    E->NumberOfNamePointers = NameTabSize;
400
104
    E->ExportAddressTableRVA = AddressTab->getRVA();
401
104
    E->NamePointerRVA = NameTab->getRVA();
402
104
    E->OrdinalTableRVA = OrdinalTab->getRVA();
403
104
  }
404
405
  uint16_t MaxOrdinal;
406
  uint16_t NameTabSize;
407
  Chunk *DLLName;
408
  Chunk *AddressTab;
409
  Chunk *NameTab;
410
  Chunk *OrdinalTab;
411
};
412
413
class AddressTableChunk : public Chunk {
414
public:
415
479
  explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
416
116
  size_t getSize() const override { return Size * 4; }
417
418
104
  void writeTo(uint8_t *Buf) const override {
419
188
    for (const Export &E : Config->Exports) {
420
188
      uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
421
188
      uint32_t Bit = 0;
422
188
      // Pointer to thumb code must have the LSB set, so adjust it.
423
188
      if (Config->Machine == ARMNT && 
!E.Data6
)
424
3
        Bit = 1;
425
188
      if (E.ForwardChunk) {
426
2
        write32le(P, E.ForwardChunk->getRVA() | Bit);
427
186
      } else {
428
186
        write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);
429
186
      }
430
188
    }
431
104
  }
432
433
private:
434
  size_t Size;
435
};
436
437
class NamePointersChunk : public Chunk {
438
public:
439
479
  explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
440
116
  size_t getSize() const override { return Chunks.size() * 4; }
441
442
104
  void writeTo(uint8_t *Buf) const override {
443
104
    uint8_t *P = Buf + OutputSectionOff;
444
186
    for (Chunk *C : Chunks) {
445
186
      write32le(P, C->getRVA());
446
186
      P += 4;
447
186
    }
448
104
  }
449
450
private:
451
  std::vector<Chunk *> Chunks;
452
};
453
454
class ExportOrdinalChunk : public Chunk {
455
public:
456
479
  explicit ExportOrdinalChunk(size_t I) : Size(I) {}
457
116
  size_t getSize() const override { return Size * 2; }
458
459
104
  void writeTo(uint8_t *Buf) const override {
460
104
    uint8_t *P = Buf + OutputSectionOff;
461
188
    for (Export &E : Config->Exports) {
462
188
      if (E.Noname)
463
2
        continue;
464
186
      write16le(P, E.Ordinal);
465
186
      P += 2;
466
186
    }
467
104
  }
468
469
private:
470
  size_t Size;
471
};
472
473
} // anonymous namespace
474
475
45
void IdataContents::create() {
476
45
  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
477
45
478
45
  // Create .idata contents for each DLL.
479
45
  for (std::vector<DefinedImportData *> &Syms : V) {
480
44
    // Create lookup and address tables. If they have external names,
481
44
    // we need to create HintName chunks to store the names.
482
44
    // If they don't (if they are import-by-ordinals), we store only
483
44
    // ordinal values to the table.
484
44
    size_t Base = Lookups.size();
485
86
    for (DefinedImportData *S : Syms) {
486
86
      uint16_t Ord = S->getOrdinal();
487
86
      if (S->getExternalName().empty()) {
488
11
        Lookups.push_back(make<OrdinalOnlyChunk>(Ord));
489
11
        Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
490
11
        continue;
491
11
      }
492
75
      auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
493
75
      Lookups.push_back(make<LookupChunk>(C));
494
75
      Addresses.push_back(make<LookupChunk>(C));
495
75
      Hints.push_back(C);
496
75
    }
497
44
    // Terminate with null values.
498
44
    Lookups.push_back(make<NullChunk>(Config->Wordsize));
499
44
    Addresses.push_back(make<NullChunk>(Config->Wordsize));
500
44
501
130
    for (int I = 0, E = Syms.size(); I < E; 
++I86
)
502
86
      Syms[I]->setLocation(Addresses[Base + I]);
503
44
504
44
    // Create the import table header.
505
44
    DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
506
44
    auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
507
44
    Dir->LookupTab = Lookups[Base];
508
44
    Dir->AddressTab = Addresses[Base];
509
44
    Dirs.push_back(Dir);
510
44
  }
511
45
  // Add null terminator.
512
45
  Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
513
45
}
514
515
4
std::vector<Chunk *> DelayLoadContents::getChunks() {
516
4
  std::vector<Chunk *> V;
517
4
  V.insert(V.end(), Dirs.begin(), Dirs.end());
518
4
  V.insert(V.end(), Names.begin(), Names.end());
519
4
  V.insert(V.end(), HintNames.begin(), HintNames.end());
520
4
  V.insert(V.end(), DLLNames.begin(), DLLNames.end());
521
4
  return V;
522
4
}
523
524
4
std::vector<Chunk *> DelayLoadContents::getDataChunks() {
525
4
  std::vector<Chunk *> V;
526
4
  V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
527
4
  V.insert(V.end(), Addresses.begin(), Addresses.end());
528
4
  return V;
529
4
}
530
531
4
uint64_t DelayLoadContents::getDirSize() {
532
4
  return Dirs.size() * sizeof(delay_import_directory_table_entry);
533
4
}
534
535
4
void DelayLoadContents::create(Defined *H) {
536
4
  Helper = H;
537
4
  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
538
4
539
4
  // Create .didat contents for each DLL.
540
4
  for (std::vector<DefinedImportData *> &Syms : V) {
541
4
    // Create the delay import table header.
542
4
    DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
543
4
    auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
544
4
545
4
    size_t Base = Addresses.size();
546
7
    for (DefinedImportData *S : Syms) {
547
7
      Chunk *T = newThunkChunk(S, Dir);
548
7
      auto *A = make<DelayAddressChunk>(T);
549
7
      Addresses.push_back(A);
550
7
      Thunks.push_back(T);
551
7
      StringRef ExtName = S->getExternalName();
552
7
      if (ExtName.empty()) {
553
1
        Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
554
6
      } else {
555
6
        auto *C = make<HintNameChunk>(ExtName, 0);
556
6
        Names.push_back(make<LookupChunk>(C));
557
6
        HintNames.push_back(C);
558
6
      }
559
7
    }
560
4
    // Terminate with null values.
561
4
    Addresses.push_back(make<NullChunk>(8));
562
4
    Names.push_back(make<NullChunk>(8));
563
4
564
11
    for (int I = 0, E = Syms.size(); I < E; 
++I7
)
565
7
      Syms[I]->setLocation(Addresses[Base + I]);
566
4
    auto *MH = make<NullChunk>(8);
567
4
    MH->Alignment = 8;
568
4
    ModuleHandles.push_back(MH);
569
4
570
4
    // Fill the delay import table header fields.
571
4
    Dir->ModuleHandle = MH;
572
4
    Dir->AddressTab = Addresses[Base];
573
4
    Dir->NameTab = Names[Base];
574
4
    Dirs.push_back(Dir);
575
4
  }
576
4
  // Add null terminator.
577
4
  Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
578
4
}
579
580
7
Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
581
7
  switch (Config->Machine) {
582
7
  case AMD64:
583
3
    return make<ThunkChunkX64>(S, Dir, Helper);
584
7
  case I386:
585
2
    return make<ThunkChunkX86>(S, Dir, Helper);
586
7
  case ARMNT:
587
1
    return make<ThunkChunkARM>(S, Dir, Helper);
588
7
  case ARM64:
589
1
    return make<ThunkChunkARM64>(S, Dir, Helper);
590
7
  default:
591
0
    llvm_unreachable("unsupported machine type");
592
7
  }
593
7
}
594
595
479
EdataContents::EdataContents() {
596
479
  uint16_t MaxOrdinal = 0;
597
479
  for (Export &E : Config->Exports)
598
188
    MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
599
479
600
479
  auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
601
479
  auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
602
479
  std::vector<Chunk *> Names;
603
479
  for (Export &E : Config->Exports)
604
188
    if (!E.Noname)
605
186
      Names.push_back(make<StringChunk>(E.ExportName));
606
479
607
479
  std::vector<Chunk *> Forwards;
608
479
  for (Export &E : Config->Exports) {
609
188
    if (E.ForwardTo.empty())
610
186
      continue;
611
2
    E.ForwardChunk = make<StringChunk>(E.ForwardTo);
612
2
    Forwards.push_back(E.ForwardChunk);
613
2
  }
614
479
615
479
  auto *NameTab = make<NamePointersChunk>(Names);
616
479
  auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
617
479
  auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
618
479
                                         AddressTab, NameTab, OrdinalTab);
619
479
  Chunks.push_back(Dir);
620
479
  Chunks.push_back(DLLName);
621
479
  Chunks.push_back(AddressTab);
622
479
  Chunks.push_back(NameTab);
623
479
  Chunks.push_back(OrdinalTab);
624
479
  Chunks.insert(Chunks.end(), Names.begin(), Names.end());
625
479
  Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());
626
479
}
627
628
} // namespace coff
629
} // namespace lld