Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/Chunks.h
Line
Count
Source (jump to first uncovered line)
1
//===- Chunks.h -------------------------------------------------*- C++ -*-===//
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
#ifndef LLD_COFF_CHUNKS_H
10
#define LLD_COFF_CHUNKS_H
11
12
#include "Config.h"
13
#include "InputFiles.h"
14
#include "lld/Common/LLVM.h"
15
#include "llvm/ADT/ArrayRef.h"
16
#include "llvm/ADT/PointerIntPair.h"
17
#include "llvm/ADT/iterator.h"
18
#include "llvm/ADT/iterator_range.h"
19
#include "llvm/MC/StringTableBuilder.h"
20
#include "llvm/Object/COFF.h"
21
#include <utility>
22
#include <vector>
23
24
namespace lld {
25
namespace coff {
26
27
using llvm::COFF::ImportDirectoryTableEntry;
28
using llvm::object::COFFSymbolRef;
29
using llvm::object::SectionRef;
30
using llvm::object::coff_relocation;
31
using llvm::object::coff_section;
32
33
class Baserel;
34
class Defined;
35
class DefinedImportData;
36
class DefinedRegular;
37
class ObjFile;
38
class OutputSection;
39
class RuntimePseudoReloc;
40
class Symbol;
41
42
// Mask for permissions (discardable, writable, readable, executable, etc).
43
const uint32_t permMask = 0xFE000000;
44
45
// Mask for section types (code, data, bss).
46
const uint32_t typeMask = 0x000000E0;
47
48
// The log base 2 of the largest section alignment, which is log2(8192), or 13.
49
enum : unsigned { Log2MaxSectionAlignment = 13 };
50
51
// A Chunk represents a chunk of data that will occupy space in the
52
// output (if the resolver chose that). It may or may not be backed by
53
// a section of an input file. It could be linker-created data, or
54
// doesn't even have actual data (if common or bss).
55
class Chunk {
56
public:
57
  enum Kind : uint8_t { SectionKind, OtherKind, ImportThunkKind };
58
29.6k
  Kind kind() const { return chunkKind; }
59
60
  // Returns the size of this chunk (even if this is a common or BSS.)
61
  size_t getSize() const;
62
63
  // Returns chunk alignment in power of two form. Value values are powers of
64
  // two from 1 to 8192.
65
4.51k
  uint32_t getAlignment() const { return 1U << p2Align; }
66
67
  // Update the chunk section alignment measured in bytes. Internally alignment
68
  // is stored in log2.
69
3.28k
  void setAlignment(uint32_t align) {
70
3.28k
    // Treat zero byte alignment as 1 byte alignment.
71
3.28k
    align = align ? align : 
10
;
72
3.28k
    assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2");
73
3.28k
    p2Align = llvm::Log2_32(align);
74
3.28k
    assert(p2Align <= Log2MaxSectionAlignment &&
75
3.28k
           "impossible requested alignment");
76
3.28k
  }
77
78
  // Write this chunk to a mmap'ed file, assuming Buf is pointing to
79
  // beginning of the file. Because this function may use RVA values
80
  // of other chunks for relocations, you need to set them properly
81
  // before calling this function.
82
  void writeTo(uint8_t *buf) const;
83
84
  // The writer sets and uses the addresses. In practice, PE images cannot be
85
  // larger than 2GB. Chunks are always laid as part of the image, so Chunk RVAs
86
  // can be stored with 32 bits.
87
11.2k
  uint32_t getRVA() const { return rva; }
88
4.49k
  void setRVA(uint64_t v) {
89
4.49k
    rva = (uint32_t)v;
90
4.49k
    assert(rva == v && "RVA truncated");
91
4.49k
  }
92
93
  // Returns readable/writable/executable bits.
94
  uint32_t getOutputCharacteristics() const;
95
96
  // Returns the section name if this is a section chunk.
97
  // It is illegal to call this function on non-section chunks.
98
  StringRef getSectionName() const;
99
100
  // An output section has pointers to chunks in the section, and each
101
  // chunk has a back pointer to an output section.
102
3.70k
  void setOutputSectionIdx(uint16_t o) { osidx = o; }
103
12
  uint16_t getOutputSectionIdx() const { return osidx; }
104
  OutputSection *getOutputSection() const;
105
106
  // Windows-specific.
107
  // Collect all locations that contain absolute addresses for base relocations.
108
  void getBaserels(std::vector<Baserel> *res);
109
110
  // Returns a human-readable name of this chunk. Chunks are unnamed chunks of
111
  // bytes, so this is used only for logging or debugging.
112
  StringRef getDebugName() const;
113
114
  // Return true if this file has the hotpatch flag set to true in the
115
  // S_COMPILE3 record in codeview debug info. Also returns true for some thunks
116
  // synthesized by the linker.
117
  bool isHotPatchable() const;
118
119
protected:
120
7.22k
  Chunk(Kind k = OtherKind) : chunkKind(k), hasData(true), p2Align(0) {}
121
122
  const Kind chunkKind;
123
124
public:
125
  // Returns true if this has non-zero data. BSS chunks return
126
  // false. If false is returned, the space occupied by this chunk
127
  // will be filled with zeros. Corresponds to the
128
  // IMAGE_SCN_CNT_UNINITIALIZED_DATA section characteristic bit.
129
  uint8_t hasData : 1;
130
131
public:
132
  // The alignment of this chunk, stored in log2 form. The writer uses the
133
  // value.
134
  uint8_t p2Align : 7;
135
136
  // The output section index for this chunk. The first valid section number is
137
  // one.
138
  uint16_t osidx = 0;
139
140
  // The RVA of this chunk in the output. The writer sets a value.
141
  uint32_t rva = 0;
142
};
143
144
class NonSectionChunk : public Chunk {
145
public:
146
4.50k
  virtual ~NonSectionChunk() = default;
147
148
  // Returns the size of this chunk (even if this is a common or BSS.)
149
  virtual size_t getSize() const = 0;
150
151
0
  virtual uint32_t getOutputCharacteristics() const { return 0; }
152
153
  // Write this chunk to a mmap'ed file, assuming Buf is pointing to
154
  // beginning of the file. Because this function may use RVA values
155
  // of other chunks for relocations, you need to set them properly
156
  // before calling this function.
157
14
  virtual void writeTo(uint8_t *buf) const {}
158
159
  // Returns the section name if this is a section chunk.
160
  // It is illegal to call this function on non-section chunks.
161
0
  virtual StringRef getSectionName() const {
162
0
    llvm_unreachable("unimplemented getSectionName");
163
0
  }
164
165
  // Windows-specific.
166
  // Collect all locations that contain absolute addresses for base relocations.
167
2.00k
  virtual void getBaserels(std::vector<Baserel> *res) {}
168
169
  // Returns a human-readable name of this chunk. Chunks are unnamed chunks of
170
  // bytes, so this is used only for logging or debugging.
171
0
  virtual StringRef getDebugName() const { return ""; }
172
173
0
  static bool classof(const Chunk *c) { return c->kind() != SectionKind; }
174
175
protected:
176
4.50k
  NonSectionChunk(Kind k = OtherKind) : Chunk(k) {}
177
};
178
179
// A chunk corresponding a section of an input file.
180
class SectionChunk final : public Chunk {
181
  // Identical COMDAT Folding feature accesses section internal data.
182
  friend class ICF;
183
184
public:
185
  class symbol_iterator : public llvm::iterator_adaptor_base<
186
                              symbol_iterator, const coff_relocation *,
187
                              std::random_access_iterator_tag, Symbol *> {
188
    friend SectionChunk;
189
190
    ObjFile *file;
191
192
    symbol_iterator(ObjFile *file, const coff_relocation *i)
193
3.93k
        : symbol_iterator::iterator_adaptor_base(i), file(file) {}
194
195
  public:
196
    symbol_iterator() = default;
197
198
1.02k
    Symbol *operator*() const { return file->getSymbol(I->SymbolTableIndex); }
199
  };
200
201
  SectionChunk(ObjFile *file, const coff_section *header);
202
29.6k
  static bool classof(const Chunk *c) { return c->kind() == SectionKind; }
203
5.21k
  size_t getSize() const { return header->SizeOfRawData; }
204
  ArrayRef<uint8_t> getContents() const;
205
  void writeTo(uint8_t *buf) const;
206
207
4.12k
  uint32_t getOutputCharacteristics() const {
208
4.12k
    return header->Characteristics & (permMask | typeMask);
209
4.12k
  }
210
9.10k
  StringRef getSectionName() const {
211
9.10k
    return StringRef(sectionNameData, sectionNameSize);
212
9.10k
  }
213
  void getBaserels(std::vector<Baserel> *res);
214
  bool isCOMDAT() const;
215
  void applyRelX64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
216
                   uint64_t p) const;
217
  void applyRelX86(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
218
                   uint64_t p) const;
219
  void applyRelARM(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
220
                   uint64_t p) const;
221
  void applyRelARM64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
222
                     uint64_t p) const;
223
224
  void getRuntimePseudoRelocs(std::vector<RuntimePseudoReloc> &res);
225
226
  // Called if the garbage collector decides to not include this chunk
227
  // in a final output. It's supposed to print out a log message to stdout.
228
  void printDiscardedMessage() const;
229
230
  // Adds COMDAT associative sections to this COMDAT section. A chunk
231
  // and its children are treated as a group by the garbage collector.
232
  void addAssociative(SectionChunk *child);
233
234
  StringRef getDebugName() const;
235
236
  // True if this is a codeview debug info chunk. These will not be laid out in
237
  // the image. Instead they will end up in the PDB, if one is requested.
238
2.74k
  bool isCodeView() const {
239
2.74k
    return getSectionName() == ".debug" || getSectionName().startswith(".debug$");
240
2.74k
  }
241
242
  // True if this is a DWARF debug info or exception handling chunk.
243
23
  bool isDWARF() const {
244
23
    return getSectionName().startswith(".debug_") || 
getSectionName() == ".eh_frame"7
;
245
23
  }
246
247
  // Allow iteration over the bodies of this chunk's relocated symbols.
248
1.96k
  llvm::iterator_range<symbol_iterator> symbols() const {
249
1.96k
    return llvm::make_range(symbol_iterator(file, relocsData),
250
1.96k
                            symbol_iterator(file, relocsData + relocsSize));
251
1.96k
  }
252
253
871
  ArrayRef<coff_relocation> getRelocs() const {
254
871
    return llvm::makeArrayRef(relocsData, relocsSize);
255
871
  }
256
257
  // Reloc setter used by ARM range extension thunk insertion.
258
2.81k
  void setRelocs(ArrayRef<coff_relocation> newRelocs) {
259
2.81k
    relocsData = newRelocs.data();
260
2.81k
    relocsSize = newRelocs.size();
261
2.81k
    assert(relocsSize == newRelocs.size() && "reloc size truncation");
262
2.81k
  }
263
264
  // Single linked list iterator for associated comdat children.
265
  class AssociatedIterator
266
      : public llvm::iterator_facade_base<
267
            AssociatedIterator, std::forward_iterator_tag, SectionChunk> {
268
  public:
269
    AssociatedIterator() = default;
270
3.52k
    AssociatedIterator(SectionChunk *head) : cur(head) {}
271
0
    AssociatedIterator &operator=(const AssociatedIterator &r) {
272
0
      cur = r.cur;
273
0
      return *this;
274
0
    }
275
1.88k
    bool operator==(const AssociatedIterator &r) const { return cur == r.cur; }
276
0
    const SectionChunk &operator*() const { return *cur; }
277
121
    SectionChunk &operator*() { return *cur; }
278
121
    AssociatedIterator &operator++() {
279
121
      cur = cur->assocChildren;
280
121
      return *this;
281
121
    }
282
283
  private:
284
    SectionChunk *cur = nullptr;
285
  };
286
287
  // Allow iteration over the associated child chunks for this section.
288
1.76k
  llvm::iterator_range<AssociatedIterator> children() const {
289
1.76k
    return llvm::make_range(AssociatedIterator(assocChildren),
290
1.76k
                            AssociatedIterator(nullptr));
291
1.76k
  }
292
293
  // The section ID this chunk belongs to in its Obj.
294
  uint32_t getSectionNumber() const;
295
296
  ArrayRef<uint8_t> consumeDebugMagic();
297
298
  static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> data,
299
                                             StringRef sectionName);
300
301
  static SectionChunk *findByName(ArrayRef<SectionChunk *> sections,
302
                                  StringRef name);
303
304
  // The file that this chunk was created from.
305
  ObjFile *file;
306
307
  // Pointer to the COFF section header in the input file.
308
  const coff_section *header;
309
310
  // The COMDAT leader symbol if this is a COMDAT chunk.
311
  DefinedRegular *sym = nullptr;
312
313
  // The CRC of the contents as described in the COFF spec 4.5.5.
314
  // Auxiliary Format 5: Section Definitions. Used for ICF.
315
  uint32_t checksum = 0;
316
317
  // Used by the garbage collector.
318
  bool live;
319
320
  // Whether this section needs to be kept distinct from other sections during
321
  // ICF. This is set by the driver using address-significance tables.
322
  bool keepUnique = false;
323
324
  // The COMDAT selection if this is a COMDAT chunk.
325
  llvm::COFF::COMDATType selection = (llvm::COFF::COMDATType)0;
326
327
  // A pointer pointing to a replacement for this chunk.
328
  // Initially it points to "this" object. If this chunk is merged
329
  // with other chunk by ICF, it points to another chunk,
330
  // and this chunk is considered as dead.
331
  SectionChunk *repl;
332
333
private:
334
  SectionChunk *assocChildren = nullptr;
335
336
  // Used for ICF (Identical COMDAT Folding)
337
  void replace(SectionChunk *other);
338
  uint32_t eqClass[2] = {0, 0};
339
340
  // Relocations for this section. Size is stored below.
341
  const coff_relocation *relocsData;
342
343
  // Section name string. Size is stored below.
344
  const char *sectionNameData;
345
346
  uint32_t relocsSize = 0;
347
  uint32_t sectionNameSize = 0;
348
};
349
350
// Inline methods to implement faux-virtual dispatch for SectionChunk.
351
352
6.22k
inline size_t Chunk::getSize() const {
353
6.22k
  if (isa<SectionChunk>(this))
354
3.04k
    return static_cast<const SectionChunk *>(this)->getSize();
355
3.17k
  else
356
3.17k
    return static_cast<const NonSectionChunk *>(this)->getSize();
357
6.22k
}
358
359
2.18k
inline uint32_t Chunk::getOutputCharacteristics() const {
360
2.18k
  if (isa<SectionChunk>(this))
361
2.17k
    return static_cast<const SectionChunk *>(this)->getOutputCharacteristics();
362
14
  else
363
14
    return static_cast<const NonSectionChunk *>(this)
364
14
        ->getOutputCharacteristics();
365
2.18k
}
366
367
3.69k
inline void Chunk::writeTo(uint8_t *buf) const {
368
3.69k
  if (isa<SectionChunk>(this))
369
1.51k
    static_cast<const SectionChunk *>(this)->writeTo(buf);
370
2.17k
  else
371
2.17k
    static_cast<const NonSectionChunk *>(this)->writeTo(buf);
372
3.69k
}
373
374
2.15k
inline StringRef Chunk::getSectionName() const {
375
2.15k
  if (isa<SectionChunk>(this))
376
2.13k
    return static_cast<const SectionChunk *>(this)->getSectionName();
377
14
  else
378
14
    return static_cast<const NonSectionChunk *>(this)->getSectionName();
379
2.15k
}
380
381
4.23k
inline void Chunk::getBaserels(std::vector<Baserel> *res) {
382
4.23k
  if (isa<SectionChunk>(this))
383
2.19k
    static_cast<SectionChunk *>(this)->getBaserels(res);
384
2.04k
  else
385
2.04k
    static_cast<NonSectionChunk *>(this)->getBaserels(res);
386
4.23k
}
387
388
0
inline StringRef Chunk::getDebugName() const {
389
0
  if (isa<SectionChunk>(this))
390
0
    return static_cast<const SectionChunk *>(this)->getDebugName();
391
0
  else
392
0
    return static_cast<const NonSectionChunk *>(this)->getDebugName();
393
0
}
394
395
// This class is used to implement an lld-specific feature (not implemented in
396
// MSVC) that minimizes the output size by finding string literals sharing tail
397
// parts and merging them.
398
//
399
// If string tail merging is enabled and a section is identified as containing a
400
// string literal, it is added to a MergeChunk with an appropriate alignment.
401
// The MergeChunk then tail merges the strings using the StringTableBuilder
402
// class and assigns RVAs and section offsets to each of the member chunks based
403
// on the offsets assigned by the StringTableBuilder.
404
class MergeChunk : public NonSectionChunk {
405
public:
406
  MergeChunk(uint32_t alignment);
407
  static void addSection(SectionChunk *c);
408
  void finalizeContents();
409
  void assignSubsectionRVAs();
410
411
  uint32_t getOutputCharacteristics() const override;
412
0
  StringRef getSectionName() const override { return ".rdata"; }
413
  size_t getSize() const override;
414
  void writeTo(uint8_t *buf) const override;
415
416
  static MergeChunk *instances[Log2MaxSectionAlignment + 1];
417
  std::vector<SectionChunk *> sections;
418
419
private:
420
  llvm::StringTableBuilder builder;
421
  bool finalized = false;
422
};
423
424
// A chunk for common symbols. Common chunks don't have actual data.
425
class CommonChunk : public NonSectionChunk {
426
public:
427
  CommonChunk(const COFFSymbolRef sym);
428
18
  size_t getSize() const override { return sym.getValue(); }
429
  uint32_t getOutputCharacteristics() const override;
430
14
  StringRef getSectionName() const override { return ".bss"; }
431
432
private:
433
  const COFFSymbolRef sym;
434
};
435
436
// A chunk for linker-created strings.
437
class StringChunk : public NonSectionChunk {
438
public:
439
839
  explicit StringChunk(StringRef s) : str(s) {}
440
529
  size_t getSize() const override { return str.size() + 1; }
441
  void writeTo(uint8_t *buf) const override;
442
443
private:
444
  StringRef str;
445
};
446
447
static const uint8_t importThunkX86[] = {
448
    0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0
449
};
450
451
static const uint8_t importThunkARM[] = {
452
    0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0
453
    0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0
454
    0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]
455
};
456
457
static const uint8_t importThunkARM64[] = {
458
    0x10, 0x00, 0x00, 0x90, // adrp x16, #0
459
    0x10, 0x02, 0x40, 0xf9, // ldr  x16, [x16]
460
    0x00, 0x02, 0x1f, 0xd6, // br   x16
461
};
462
463
// Windows-specific.
464
// A chunk for DLL import jump table entry. In a final output, its
465
// contents will be a JMP instruction to some __imp_ symbol.
466
class ImportThunkChunk : public NonSectionChunk {
467
public:
468
  ImportThunkChunk(Defined *s)
469
98
      : NonSectionChunk(ImportThunkKind), impSymbol(s) {}
470
1
  static bool classof(const Chunk *c) { return c->kind() == ImportThunkKind; }
471
472
protected:
473
  Defined *impSymbol;
474
};
475
476
class ImportThunkChunkX64 : public ImportThunkChunk {
477
public:
478
  explicit ImportThunkChunkX64(Defined *s);
479
146
  size_t getSize() const override { return sizeof(importThunkX86); }
480
  void writeTo(uint8_t *buf) const override;
481
};
482
483
class ImportThunkChunkX86 : public ImportThunkChunk {
484
public:
485
18
  explicit ImportThunkChunkX86(Defined *s) : ImportThunkChunk(s) {}
486
30
  size_t getSize() const override { return sizeof(importThunkX86); }
487
  void getBaserels(std::vector<Baserel> *res) override;
488
  void writeTo(uint8_t *buf) const override;
489
};
490
491
class ImportThunkChunkARM : public ImportThunkChunk {
492
public:
493
2
  explicit ImportThunkChunkARM(Defined *s) : ImportThunkChunk(s) {}
494
0
  size_t getSize() const override { return sizeof(importThunkARM); }
495
  void getBaserels(std::vector<Baserel> *res) override;
496
  void writeTo(uint8_t *buf) const override;
497
};
498
499
class ImportThunkChunkARM64 : public ImportThunkChunk {
500
public:
501
4
  explicit ImportThunkChunkARM64(Defined *s) : ImportThunkChunk(s) {}
502
4
  size_t getSize() const override { return sizeof(importThunkARM64); }
503
  void writeTo(uint8_t *buf) const override;
504
};
505
506
class RangeExtensionThunkARM : public NonSectionChunk {
507
public:
508
50
  explicit RangeExtensionThunkARM(Defined *t) : target(t) {}
509
  size_t getSize() const override;
510
  void writeTo(uint8_t *buf) const override;
511
512
  Defined *target;
513
};
514
515
class RangeExtensionThunkARM64 : public NonSectionChunk {
516
public:
517
1
  explicit RangeExtensionThunkARM64(Defined *t) : target(t) {}
518
  size_t getSize() const override;
519
  void writeTo(uint8_t *buf) const override;
520
521
  Defined *target;
522
};
523
524
// Windows-specific.
525
// See comments for DefinedLocalImport class.
526
class LocalImportChunk : public NonSectionChunk {
527
public:
528
9
  explicit LocalImportChunk(Defined *s) : sym(s) {
529
9
    setAlignment(config->wordsize);
530
9
  }
531
  size_t getSize() const override;
532
  void getBaserels(std::vector<Baserel> *res) override;
533
  void writeTo(uint8_t *buf) const override;
534
535
private:
536
  Defined *sym;
537
};
538
539
// Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and
540
// offset into the chunk. Order does not matter as the RVA table will be sorted
541
// later.
542
struct ChunkAndOffset {
543
  Chunk *inputChunk;
544
  uint32_t offset;
545
546
  struct DenseMapInfo {
547
208
    static ChunkAndOffset getEmptyKey() {
548
208
      return {llvm::DenseMapInfo<Chunk *>::getEmptyKey(), 0};
549
208
    }
550
153
    static ChunkAndOffset getTombstoneKey() {
551
153
      return {llvm::DenseMapInfo<Chunk *>::getTombstoneKey(), 0};
552
153
    }
553
38
    static unsigned getHashValue(const ChunkAndOffset &co) {
554
38
      return llvm::DenseMapInfo<std::pair<Chunk *, uint32_t>>::getHashValue(
555
38
          {co.inputChunk, co.offset});
556
38
    }
557
3.60k
    static bool isEqual(const ChunkAndOffset &lhs, const ChunkAndOffset &rhs) {
558
3.60k
      return lhs.inputChunk == rhs.inputChunk && 
lhs.offset == rhs.offset3.36k
;
559
3.60k
    }
560
  };
561
};
562
563
using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>;
564
565
// Table which contains symbol RVAs. Used for /safeseh and /guard:cf.
566
class RVATableChunk : public NonSectionChunk {
567
public:
568
20
  explicit RVATableChunk(SymbolRVASet s) : syms(std::move(s)) {}
569
40
  size_t getSize() const override { return syms.size() * 4; }
570
  void writeTo(uint8_t *buf) const override;
571
572
private:
573
  SymbolRVASet syms;
574
};
575
576
// Windows-specific.
577
// This class represents a block in .reloc section.
578
// See the PE/COFF spec 5.6 for details.
579
class BaserelChunk : public NonSectionChunk {
580
public:
581
  BaserelChunk(uint32_t page, Baserel *begin, Baserel *end);
582
122
  size_t getSize() const override { return data.size(); }
583
  void writeTo(uint8_t *buf) const override;
584
585
private:
586
  std::vector<uint8_t> data;
587
};
588
589
class Baserel {
590
public:
591
221
  Baserel(uint32_t v, uint8_t ty) : rva(v), type(ty) {}
592
39
  explicit Baserel(uint32_t v) : Baserel(v, getDefaultType()) {}
lld::coff::Baserel::Baserel(unsigned int)
Line
Count
Source
592
39
  explicit Baserel(uint32_t v) : Baserel(v, getDefaultType()) {}
Unexecuted instantiation: lld::coff::Baserel::Baserel(unsigned int)
593
  uint8_t getDefaultType();
594
595
  uint32_t rva;
596
  uint8_t type;
597
};
598
599
// This is a placeholder Chunk, to allow attaching a DefinedSynthetic to a
600
// specific place in a section, without any data. This is used for the MinGW
601
// specific symbol __RUNTIME_PSEUDO_RELOC_LIST_END__, even though the concept
602
// of an empty chunk isn't MinGW specific.
603
class EmptyChunk : public NonSectionChunk {
604
public:
605
46
  EmptyChunk() {}
606
46
  size_t getSize() const override { return 0; }
607
46
  void writeTo(uint8_t *buf) const override {}
608
};
609
610
// MinGW specific, for the "automatic import of variables from DLLs" feature.
611
// This provides the table of runtime pseudo relocations, for variable
612
// references that turned out to need to be imported from a DLL even though
613
// the reference didn't use the dllimport attribute. The MinGW runtime will
614
// process this table after loading, before handling control over to user
615
// code.
616
class PseudoRelocTableChunk : public NonSectionChunk {
617
public:
618
  PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &relocs)
619
46
      : relocs(std::move(relocs)) {
620
46
    setAlignment(4);
621
46
  }
622
  size_t getSize() const override;
623
  void writeTo(uint8_t *buf) const override;
624
625
private:
626
  std::vector<RuntimePseudoReloc> relocs;
627
};
628
629
// MinGW specific; information about one individual location in the image
630
// that needs to be fixed up at runtime after loading. This represents
631
// one individual element in the PseudoRelocTableChunk table.
632
class RuntimePseudoReloc {
633
public:
634
  RuntimePseudoReloc(Defined *sym, SectionChunk *target, uint32_t targetOffset,
635
                     int flags)
636
5
      : sym(sym), target(target), targetOffset(targetOffset), flags(flags) {}
637
638
  Defined *sym;
639
  SectionChunk *target;
640
  uint32_t targetOffset;
641
  // The Flags field contains the size of the relocation, in bits. No other
642
  // flags are currently defined.
643
  int flags;
644
};
645
646
// MinGW specific. A Chunk that contains one pointer-sized absolute value.
647
class AbsolutePointerChunk : public NonSectionChunk {
648
public:
649
184
  AbsolutePointerChunk(uint64_t value) : value(value) {
650
184
    setAlignment(getSize());
651
184
  }
652
  size_t getSize() const override;
653
  void writeTo(uint8_t *buf) const override;
654
655
private:
656
  uint64_t value;
657
};
658
659
// Return true if this file has the hotpatch flag set to true in the S_COMPILE3
660
// record in codeview debug info. Also returns true for some thunks synthesized
661
// by the linker.
662
11
inline bool Chunk::isHotPatchable() const {
663
11
  if (auto *sc = dyn_cast<SectionChunk>(this))
664
10
    return sc->file->hotPatchable;
665
1
  else if (isa<ImportThunkChunk>(this))
666
1
    return true;
667
0
  return false;
668
0
}
669
670
void applyMOV32T(uint8_t *off, uint32_t v);
671
void applyBranch24T(uint8_t *off, int32_t v);
672
673
void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift);
674
void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit);
675
void applyArm64Branch26(uint8_t *off, int64_t v);
676
677
} // namespace coff
678
} // namespace lld
679
680
namespace llvm {
681
template <>
682
struct DenseMapInfo<lld::coff::ChunkAndOffset>
683
    : lld::coff::ChunkAndOffset::DenseMapInfo {};
684
}
685
686
#endif