Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/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 "Chunks.h"
22
#include "DLL.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
348
static int ptrSize() 
{ return Config->is64() ? 348
8263
:
485
; }
39
40
// A chunk for the import descriptor table.
41
class HintNameChunk : public Chunk {
42
public:
43
54
  HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
44
45
64
  size_t getSize() const override {
46
64
    // Starts with 2 byte Hint field, followed by a null-terminated string,
47
64
    // ends with 0 or 1 byte padding.
48
64
    return alignTo(Name.size() + 3, 2);
49
64
  }
50
51
54
  void writeTo(uint8_t *Buf) const override {
52
54
    write16le(Buf + OutputSectionOff, Hint);
53
54
    memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
54
54
  }
55
56
private:
57
  StringRef Name;
58
  uint16_t Hint;
59
};
60
61
// A chunk for the import descriptor table.
62
class LookupChunk : public Chunk {
63
public:
64
103
  explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = ptrSize(); }
65
121
  size_t getSize() const override { return ptrSize(); }
66
67
103
  void writeTo(uint8_t *Buf) const override {
68
103
    write32le(Buf + OutputSectionOff, HintName->getRVA());
69
103
  }
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.
77
class OrdinalOnlyChunk : public Chunk {
78
public:
79
15
  explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { Alignment = ptrSize(); }
80
15
  size_t getSize() const override { return ptrSize(); }
81
82
15
  void writeTo(uint8_t *Buf) const override {
83
15
    // An import-by-ordinal slot has MSB 1 to indicate that
84
15
    // this is import-by-ordinal (and not import-by-name).
85
15
    if (
Config->is64()15
) {
86
15
      write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);
87
15
    } else {
88
0
      write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);
89
0
    }
90
15
  }
91
92
  uint16_t Ordinal;
93
};
94
95
// A chunk for the import descriptor table.
96
class ImportDirectoryChunk : public Chunk {
97
public:
98
27
  explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
99
31
  size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
100
101
27
  void writeTo(uint8_t *Buf) const override {
102
27
    auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
103
27
    E->ImportLookupTableRVA = LookupTab->getRVA();
104
27
    E->NameRVA = DLLName->getRVA();
105
27
    E->ImportAddressTableRVA = AddressTab->getRVA();
106
27
  }
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
92
  explicit NullChunk(size_t N) : Size(N) {}
118
92
  bool hasData() const override { return false; }
119
108
  size_t getSize() const override { return Size; }
120
121
private:
122
  size_t Size;
123
};
124
125
static std::vector<std::vector<DefinedImportData *>>
126
29
binImports(const std::vector<DefinedImportData *> &Imports) {
127
29
  // Group DLL-imported symbols by DLL name because that's how
128
29
  // symbols are layed out in the import descriptor table.
129
66
  auto Less = [](const std::string &A, const std::string &B) {
130
66
    return Config->DLLOrder[A] < Config->DLLOrder[B];
131
66
  };
132
29
  std::map<std::string, std::vector<DefinedImportData *>,
133
29
           bool(*)(const std::string &, const std::string &)> M(Less);
134
29
  for (DefinedImportData *Sym : Imports)
135
62
    M[Sym->getDLLName().lower()].push_back(Sym);
136
29
137
29
  std::vector<std::vector<DefinedImportData *>> V;
138
30
  for (auto &KV : M) {
139
30
    // Sort symbols by name for each group.
140
30
    std::vector<DefinedImportData *> &Syms = KV.second;
141
30
    std::sort(Syms.begin(), Syms.end(),
142
34
              [](DefinedImportData *A, DefinedImportData *B) {
143
34
                return A->getName() < B->getName();
144
34
              });
145
30
    V.push_back(std::move(Syms));
146
30
  }
147
29
  return V;
148
29
}
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
3
  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
3
  void writeTo(uint8_t *Buf) const override {
163
3
    auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
164
3
    E->Attributes = 1;
165
3
    E->Name = DLLName->getRVA();
166
3
    E->ModuleHandle = ModuleHandle->getRVA();
167
3
    E->DelayImportAddressTable = AddressTab->getRVA();
168
3
    E->DelayImportNameTable = NameTab->getRVA();
169
3
  }
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
// A chunk for the delay import thunk.
234
class ThunkChunkX64 : public Chunk {
235
public:
236
  ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
237
3
      : Imp(I), Desc(D), Helper(H) {}
238
239
3
  size_t getSize() const override { return sizeof(ThunkX64); }
240
241
3
  void writeTo(uint8_t *Buf) const override {
242
3
    memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
243
3
    write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
244
3
    write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
245
3
    write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
246
3
  }
247
248
  Defined *Imp = nullptr;
249
  Chunk *Desc = nullptr;
250
  Defined *Helper = nullptr;
251
};
252
253
class ThunkChunkX86 : public Chunk {
254
public:
255
  ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
256
2
      : Imp(I), Desc(D), Helper(H) {}
257
258
4
  size_t getSize() const override { return sizeof(ThunkX86); }
259
260
2
  void writeTo(uint8_t *Buf) const override {
261
2
    memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
262
2
    write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
263
2
    write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
264
2
    write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
265
2
  }
266
267
2
  void getBaserels(std::vector<Baserel> *Res) override {
268
2
    Res->emplace_back(RVA + 3);
269
2
    Res->emplace_back(RVA + 8);
270
2
  }
271
272
  Defined *Imp = nullptr;
273
  Chunk *Desc = nullptr;
274
  Defined *Helper = nullptr;
275
};
276
277
class ThunkChunkARM : public Chunk {
278
public:
279
  ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
280
1
      : Imp(I), Desc(D), Helper(H) {}
281
282
1
  size_t getSize() const override { return sizeof(ThunkARM); }
283
284
1
  void writeTo(uint8_t *Buf) const override {
285
1
    memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM));
286
1
    applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase);
287
1
    applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase);
288
1
    applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34);
289
1
  }
290
291
1
  void getBaserels(std::vector<Baserel> *Res) override {
292
1
    Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
293
1
    Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
294
1
  }
295
296
  Defined *Imp = nullptr;
297
  Chunk *Desc = nullptr;
298
  Defined *Helper = nullptr;
299
};
300
301
// A chunk for the import descriptor table.
302
class DelayAddressChunk : public Chunk {
303
public:
304
6
  explicit DelayAddressChunk(Chunk *C) : Thunk(C) { Alignment = ptrSize(); }
305
8
  size_t getSize() const override { return ptrSize(); }
306
307
6
  void writeTo(uint8_t *Buf) const override {
308
6
    if (
Config->is64()6
) {
309
3
      write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
310
6
    } else {
311
3
      uint32_t Bit = 0;
312
3
      // Pointer to thumb code must have the LSB set, so adjust it.
313
3
      if (Config->Machine == ARMNT)
314
1
        Bit = 1;
315
3
      write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit);
316
3
    }
317
6
  }
318
319
6
  void getBaserels(std::vector<Baserel> *Res) override {
320
6
    Res->emplace_back(RVA);
321
6
  }
322
323
  Chunk *Thunk;
324
};
325
326
// Export table
327
// Read Microsoft PE/COFF spec 5.3 for details.
328
329
// A chunk for the export descriptor table.
330
class ExportDirectoryChunk : public Chunk {
331
public:
332
  ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
333
      : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
334
257
        OrdinalTab(O) {}
335
336
39
  size_t getSize() const override {
337
39
    return sizeof(export_directory_table_entry);
338
39
  }
339
340
39
  void writeTo(uint8_t *Buf) const override {
341
39
    auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
342
39
    E->NameRVA = DLLName->getRVA();
343
39
    E->OrdinalBase = 0;
344
39
    E->AddressTableEntries = MaxOrdinal + 1;
345
39
    E->NumberOfNamePointers = NameTabSize;
346
39
    E->ExportAddressTableRVA = AddressTab->getRVA();
347
39
    E->NamePointerRVA = NameTab->getRVA();
348
39
    E->OrdinalTableRVA = OrdinalTab->getRVA();
349
39
  }
350
351
  uint16_t MaxOrdinal;
352
  uint16_t NameTabSize;
353
  Chunk *DLLName;
354
  Chunk *AddressTab;
355
  Chunk *NameTab;
356
  Chunk *OrdinalTab;
357
};
358
359
class AddressTableChunk : public Chunk {
360
public:
361
257
  explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
362
39
  size_t getSize() const override { return Size * 4; }
363
364
39
  void writeTo(uint8_t *Buf) const override {
365
39
    uint32_t Bit = 0;
366
39
    // Pointer to thumb code must have the LSB set, so adjust it.
367
39
    if (Config->Machine == ARMNT)
368
1
      Bit = 1;
369
81
    for (Export &E : Config->Exports) {
370
81
      uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
371
81
      if (
E.ForwardChunk81
) {
372
1
        write32le(P, E.ForwardChunk->getRVA() | Bit);
373
81
      } else {
374
80
        write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);
375
80
      }
376
81
    }
377
39
  }
378
379
private:
380
  size_t Size;
381
};
382
383
class NamePointersChunk : public Chunk {
384
public:
385
257
  explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
386
39
  size_t getSize() const override { return Chunks.size() * 4; }
387
388
39
  void writeTo(uint8_t *Buf) const override {
389
39
    uint8_t *P = Buf + OutputSectionOff;
390
79
    for (Chunk *C : Chunks) {
391
79
      write32le(P, C->getRVA());
392
79
      P += 4;
393
79
    }
394
39
  }
395
396
private:
397
  std::vector<Chunk *> Chunks;
398
};
399
400
class ExportOrdinalChunk : public Chunk {
401
public:
402
257
  explicit ExportOrdinalChunk(size_t I) : Size(I) {}
403
39
  size_t getSize() const override { return Size * 2; }
404
405
39
  void writeTo(uint8_t *Buf) const override {
406
39
    uint8_t *P = Buf + OutputSectionOff;
407
81
    for (Export &E : Config->Exports) {
408
81
      if (E.Noname)
409
2
        continue;
410
79
      write16le(P, E.Ordinal);
411
79
      P += 2;
412
79
    }
413
39
  }
414
415
private:
416
  size_t Size;
417
};
418
419
} // anonymous namespace
420
421
26
uint64_t IdataContents::getDirSize() {
422
26
  return Dirs.size() * sizeof(ImportDirectoryTableEntry);
423
26
}
424
425
26
uint64_t IdataContents::getIATSize() {
426
26
  return Addresses.size() * ptrSize();
427
26
}
428
429
// Returns a list of .idata contents.
430
// See Microsoft PE/COFF spec 5.4 for details.
431
26
std::vector<Chunk *> IdataContents::getChunks() {
432
26
  create();
433
26
434
26
  // The loader assumes a specific order of data.
435
26
  // Add each type in the correct order.
436
26
  std::vector<Chunk *> V;
437
26
  V.insert(V.end(), Dirs.begin(), Dirs.end());
438
26
  V.insert(V.end(), Lookups.begin(), Lookups.end());
439
26
  V.insert(V.end(), Addresses.begin(), Addresses.end());
440
26
  V.insert(V.end(), Hints.begin(), Hints.end());
441
26
  V.insert(V.end(), DLLNames.begin(), DLLNames.end());
442
26
  return V;
443
26
}
444
445
26
void IdataContents::create() {
446
26
  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
447
26
448
26
  // Create .idata contents for each DLL.
449
27
  for (std::vector<DefinedImportData *> &Syms : V) {
450
27
    // Create lookup and address tables. If they have external names,
451
27
    // we need to create HintName chunks to store the names.
452
27
    // If they don't (if they are import-by-ordinals), we store only
453
27
    // ordinal values to the table.
454
27
    size_t Base = Lookups.size();
455
56
    for (DefinedImportData *S : Syms) {
456
56
      uint16_t Ord = S->getOrdinal();
457
56
      if (
S->getExternalName().empty()56
) {
458
7
        Lookups.push_back(make<OrdinalOnlyChunk>(Ord));
459
7
        Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
460
7
        continue;
461
7
      }
462
49
      auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
463
49
      Lookups.push_back(make<LookupChunk>(C));
464
49
      Addresses.push_back(make<LookupChunk>(C));
465
49
      Hints.push_back(C);
466
49
    }
467
27
    // Terminate with null values.
468
27
    Lookups.push_back(make<NullChunk>(ptrSize()));
469
27
    Addresses.push_back(make<NullChunk>(ptrSize()));
470
27
471
83
    for (int I = 0, E = Syms.size(); 
I < E83
;
++I56
)
472
56
      Syms[I]->setLocation(Addresses[Base + I]);
473
27
474
27
    // Create the import table header.
475
27
    DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
476
27
    auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
477
27
    Dir->LookupTab = Lookups[Base];
478
27
    Dir->AddressTab = Addresses[Base];
479
27
    Dirs.push_back(Dir);
480
27
  }
481
26
  // Add null terminator.
482
26
  Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
483
26
}
484
485
3
std::vector<Chunk *> DelayLoadContents::getChunks() {
486
3
  std::vector<Chunk *> V;
487
3
  V.insert(V.end(), Dirs.begin(), Dirs.end());
488
3
  V.insert(V.end(), Names.begin(), Names.end());
489
3
  V.insert(V.end(), HintNames.begin(), HintNames.end());
490
3
  V.insert(V.end(), DLLNames.begin(), DLLNames.end());
491
3
  return V;
492
3
}
493
494
3
std::vector<Chunk *> DelayLoadContents::getDataChunks() {
495
3
  std::vector<Chunk *> V;
496
3
  V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
497
3
  V.insert(V.end(), Addresses.begin(), Addresses.end());
498
3
  return V;
499
3
}
500
501
3
uint64_t DelayLoadContents::getDirSize() {
502
3
  return Dirs.size() * sizeof(delay_import_directory_table_entry);
503
3
}
504
505
3
void DelayLoadContents::create(Defined *H) {
506
3
  Helper = H;
507
3
  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
508
3
509
3
  // Create .didat contents for each DLL.
510
3
  for (std::vector<DefinedImportData *> &Syms : V) {
511
3
    // Create the delay import table header.
512
3
    DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
513
3
    auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
514
3
515
3
    size_t Base = Addresses.size();
516
6
    for (DefinedImportData *S : Syms) {
517
6
      Chunk *T = newThunkChunk(S, Dir);
518
6
      auto *A = make<DelayAddressChunk>(T);
519
6
      Addresses.push_back(A);
520
6
      Thunks.push_back(T);
521
6
      StringRef ExtName = S->getExternalName();
522
6
      if (
ExtName.empty()6
) {
523
1
        Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
524
6
      } else {
525
5
        auto *C = make<HintNameChunk>(ExtName, 0);
526
5
        Names.push_back(make<LookupChunk>(C));
527
5
        HintNames.push_back(C);
528
5
      }
529
6
    }
530
3
    // Terminate with null values.
531
3
    Addresses.push_back(make<NullChunk>(8));
532
3
    Names.push_back(make<NullChunk>(8));
533
3
534
9
    for (int I = 0, E = Syms.size(); 
I < E9
;
++I6
)
535
6
      Syms[I]->setLocation(Addresses[Base + I]);
536
3
    auto *MH = make<NullChunk>(8);
537
3
    MH->Alignment = 8;
538
3
    ModuleHandles.push_back(MH);
539
3
540
3
    // Fill the delay import table header fields.
541
3
    Dir->ModuleHandle = MH;
542
3
    Dir->AddressTab = Addresses[Base];
543
3
    Dir->NameTab = Names[Base];
544
3
    Dirs.push_back(Dir);
545
3
  }
546
3
  // Add null terminator.
547
3
  Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
548
3
}
549
550
6
Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
551
6
  switch (Config->Machine) {
552
3
  case AMD64:
553
3
    return make<ThunkChunkX64>(S, Dir, Helper);
554
2
  case I386:
555
2
    return make<ThunkChunkX86>(S, Dir, Helper);
556
1
  case ARMNT:
557
1
    return make<ThunkChunkARM>(S, Dir, Helper);
558
0
  default:
559
0
    llvm_unreachable("unsupported machine type");
560
0
  }
561
0
}
562
563
257
EdataContents::EdataContents() {
564
257
  uint16_t MaxOrdinal = 0;
565
257
  for (Export &E : Config->Exports)
566
81
    MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
567
257
568
257
  auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
569
257
  auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
570
257
  std::vector<Chunk *> Names;
571
257
  for (Export &E : Config->Exports)
572
81
    
if (81
!E.Noname81
)
573
79
      Names.push_back(make<StringChunk>(E.ExportName));
574
257
575
257
  std::vector<Chunk *> Forwards;
576
81
  for (Export &E : Config->Exports) {
577
81
    if (E.ForwardTo.empty())
578
80
      continue;
579
1
    E.ForwardChunk = make<StringChunk>(E.ForwardTo);
580
1
    Forwards.push_back(E.ForwardChunk);
581
1
  }
582
257
583
257
  auto *NameTab = make<NamePointersChunk>(Names);
584
257
  auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
585
257
  auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
586
257
                                         AddressTab, NameTab, OrdinalTab);
587
257
  Chunks.push_back(Dir);
588
257
  Chunks.push_back(DLLName);
589
257
  Chunks.push_back(AddressTab);
590
257
  Chunks.push_back(NameTab);
591
257
  Chunks.push_back(OrdinalTab);
592
257
  Chunks.insert(Chunks.end(), Names.begin(), Names.end());
593
257
  Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());
594
257
}
595
596
} // namespace coff
597
} // namespace lld