Coverage Report

Created: 2018-10-23 15:26

/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
//                             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
#ifndef LLD_COFF_CHUNKS_H
11
#define LLD_COFF_CHUNKS_H
12
13
#include "Config.h"
14
#include "InputFiles.h"
15
#include "lld/Common/LLVM.h"
16
#include "llvm/ADT/ArrayRef.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
// A Chunk represents a chunk of data that will occupy space in the
49
// output (if the resolver chose that). It may or may not be backed by
50
// a section of an input file. It could be linker-created data, or
51
// doesn't even have actual data (if common or bss).
52
class Chunk {
53
public:
54
  enum Kind { SectionKind, OtherKind };
55
6.22k
  Kind kind() const { return ChunkKind; }
56
5.88k
  virtual ~Chunk() = default;
57
58
  // Returns the size of this chunk (even if this is a common or BSS.)
59
  virtual size_t getSize() const = 0;
60
61
  // Write this chunk to a mmap'ed file, assuming Buf is pointing to
62
  // beginning of the file. Because this function may use RVA values
63
  // of other chunks for relocations, you need to set them properly
64
  // before calling this function.
65
161
  virtual void writeTo(uint8_t *Buf) const {}
66
67
  // Called by the writer once before assigning addresses and writing
68
  // the output.
69
1.77k
  virtual void readRelocTargets() {}
70
71
  // Called if restarting thunk addition.
72
0
  virtual void resetRelocTargets() {}
73
74
  // Called by the writer after an RVA is assigned, but before calling
75
  // getSize().
76
3.75k
  virtual void finalizeContents() {}
77
78
  // The writer sets and uses the addresses.
79
5.78k
  uint64_t getRVA() const { return RVA; }
80
3.82k
  void setRVA(uint64_t V) { RVA = V; }
81
82
  // Returns true if this has non-zero data. BSS chunks return
83
  // false. If false is returned, the space occupied by this chunk
84
  // will be filled with zeros.
85
1.76k
  virtual bool hasData() const { return true; }
86
87
  // Returns readable/writable/executable bits.
88
0
  virtual uint32_t getOutputCharacteristics() const { return 0; }
89
90
  // Returns the section name if this is a section chunk.
91
  // It is illegal to call this function on non-section chunks.
92
0
  virtual StringRef getSectionName() const {
93
0
    llvm_unreachable("unimplemented getSectionName");
94
0
  }
95
96
  // An output section has pointers to chunks in the section, and each
97
  // chunk has a back pointer to an output section.
98
5.36k
  void setOutputSection(OutputSection *O) { Out = O; }
99
2.75k
  OutputSection *getOutputSection() const { return Out; }
100
101
  // Windows-specific.
102
  // Collect all locations that contain absolute addresses for base relocations.
103
1.74k
  virtual void getBaserels(std::vector<Baserel> *Res) {}
104
105
  // Returns a human-readable name of this chunk. Chunks are unnamed chunks of
106
  // bytes, so this is used only for logging or debugging.
107
0
  virtual StringRef getDebugName() { return ""; }
108
109
  // The alignment of this chunk. The writer uses the value.
110
  uint32_t Alignment = 1;
111
112
protected:
113
5.88k
  Chunk(Kind K = OtherKind) : ChunkKind(K) {}
114
  const Kind ChunkKind;
115
116
  // The RVA of this chunk in the output. The writer sets a value.
117
  uint64_t RVA = 0;
118
119
  // The output section for this chunk.
120
  OutputSection *Out = nullptr;
121
122
public:
123
  // The offset from beginning of the output section. The writer sets a value.
124
  uint64_t OutputSectionOff = 0;
125
126
  // Whether this section needs to be kept distinct from other sections during
127
  // ICF. This is set by the driver using address-significance tables.
128
  bool KeepUnique = false;
129
};
130
131
// A chunk corresponding a section of an input file.
132
class SectionChunk final : public Chunk {
133
  // Identical COMDAT Folding feature accesses section internal data.
134
  friend class ICF;
135
136
public:
137
  class symbol_iterator : public llvm::iterator_adaptor_base<
138
                              symbol_iterator, const coff_relocation *,
139
                              std::random_access_iterator_tag, Symbol *> {
140
    friend SectionChunk;
141
142
    ObjFile *File;
143
144
    symbol_iterator(ObjFile *File, const coff_relocation *I)
145
2.65k
        : symbol_iterator::iterator_adaptor_base(I), File(File) {}
146
147
  public:
148
    symbol_iterator() = default;
149
150
689
    Symbol *operator*() const { return File->getSymbol(I->SymbolTableIndex); }
151
  };
152
153
  SectionChunk(ObjFile *File, const coff_section *Header);
154
6.22k
  static bool classof(const Chunk *C) { return C->kind() == SectionKind; }
155
  void readRelocTargets() override;
156
  void resetRelocTargets() override;
157
4.04k
  size_t getSize() const override { return Header->SizeOfRawData; }
158
  ArrayRef<uint8_t> getContents() const;
159
  void writeTo(uint8_t *Buf) const override;
160
  bool hasData() const override;
161
  uint32_t getOutputCharacteristics() const override;
162
2.28k
  StringRef getSectionName() const override { return SectionName; }
163
  void getBaserels(std::vector<Baserel> *Res) override;
164
  bool isCOMDAT() const;
165
  void applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
166
                   uint64_t P) const;
167
  void applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
168
                   uint64_t P) const;
169
  void applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
170
                   uint64_t P) const;
171
  void applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
172
                     uint64_t P) const;
173
174
  void getRuntimePseudoRelocs(std::vector<RuntimePseudoReloc> &Res);
175
176
  // Called if the garbage collector decides to not include this chunk
177
  // in a final output. It's supposed to print out a log message to stdout.
178
  void printDiscardedMessage() const;
179
180
  // Adds COMDAT associative sections to this COMDAT section. A chunk
181
  // and its children are treated as a group by the garbage collector.
182
  void addAssociative(SectionChunk *Child);
183
184
  StringRef getDebugName() override;
185
186
  // True if this is a codeview debug info chunk. These will not be laid out in
187
  // the image. Instead they will end up in the PDB, if one is requested.
188
2.10k
  bool isCodeView() const {
189
2.10k
    return SectionName == ".debug" || SectionName.startswith(".debug$");
190
2.10k
  }
191
192
  // True if this is a DWARF debug info or exception handling chunk.
193
9
  bool isDWARF() const {
194
9
    return SectionName.startswith(".debug_") || 
SectionName == ".eh_frame"7
;
195
9
  }
196
197
  // Allow iteration over the bodies of this chunk's relocated symbols.
198
1.32k
  llvm::iterator_range<symbol_iterator> symbols() const {
199
1.32k
    return llvm::make_range(symbol_iterator(File, Relocs.begin()),
200
1.32k
                            symbol_iterator(File, Relocs.end()));
201
1.32k
  }
202
203
  // Allow iteration over the associated child chunks for this section.
204
1.43k
  ArrayRef<SectionChunk *> children() const { return AssocChildren; }
205
206
  // The section ID this chunk belongs to in its Obj.
207
  uint32_t getSectionNumber() const;
208
209
  // A pointer pointing to a replacement for this chunk.
210
  // Initially it points to "this" object. If this chunk is merged
211
  // with other chunk by ICF, it points to another chunk,
212
  // and this chunk is considered as dead.
213
  SectionChunk *Repl;
214
215
  // The CRC of the contents as described in the COFF spec 4.5.5.
216
  // Auxiliary Format 5: Section Definitions. Used for ICF.
217
  uint32_t Checksum = 0;
218
219
  const coff_section *Header;
220
221
  // The file that this chunk was created from.
222
  ObjFile *File;
223
224
  // The COMDAT leader symbol if this is a COMDAT chunk.
225
  DefinedRegular *Sym = nullptr;
226
227
  ArrayRef<coff_relocation> Relocs;
228
229
  // Used by the garbage collector.
230
  bool Live;
231
232
  // When inserting a thunk, we need to adjust a relocation to point to
233
  // the thunk instead of the actual original target Symbol.
234
  std::vector<Symbol *> RelocTargets;
235
236
private:
237
  StringRef SectionName;
238
  std::vector<SectionChunk *> AssocChildren;
239
240
  // Used for ICF (Identical COMDAT Folding)
241
  void replace(SectionChunk *Other);
242
  uint32_t Class[2] = {0, 0};
243
};
244
245
// This class is used to implement an lld-specific feature (not implemented in
246
// MSVC) that minimizes the output size by finding string literals sharing tail
247
// parts and merging them.
248
//
249
// If string tail merging is enabled and a section is identified as containing a
250
// string literal, it is added to a MergeChunk with an appropriate alignment.
251
// The MergeChunk then tail merges the strings using the StringTableBuilder
252
// class and assigns RVAs and section offsets to each of the member chunks based
253
// on the offsets assigned by the StringTableBuilder.
254
class MergeChunk : public Chunk {
255
public:
256
  MergeChunk(uint32_t Alignment);
257
  static void addSection(SectionChunk *C);
258
  void finalizeContents() override;
259
260
  uint32_t getOutputCharacteristics() const override;
261
0
  StringRef getSectionName() const override { return ".rdata"; }
262
  size_t getSize() const override;
263
  void writeTo(uint8_t *Buf) const override;
264
265
  static std::map<uint32_t, MergeChunk *> Instances;
266
  std::vector<SectionChunk *> Sections;
267
268
private:
269
  llvm::StringTableBuilder Builder;
270
  bool Finalized = false;
271
};
272
273
// A chunk for common symbols. Common chunks don't have actual data.
274
class CommonChunk : public Chunk {
275
public:
276
  CommonChunk(const COFFSymbolRef Sym);
277
12
  size_t getSize() const override { return Sym.getValue(); }
278
12
  bool hasData() const override { return false; }
279
  uint32_t getOutputCharacteristics() const override;
280
12
  StringRef getSectionName() const override { return ".bss"; }
281
282
private:
283
  const COFFSymbolRef Sym;
284
};
285
286
// A chunk for linker-created strings.
287
class StringChunk : public Chunk {
288
public:
289
715
  explicit StringChunk(StringRef S) : Str(S) {}
290
472
  size_t getSize() const override { return Str.size() + 1; }
291
  void writeTo(uint8_t *Buf) const override;
292
293
private:
294
  StringRef Str;
295
};
296
297
static const uint8_t ImportThunkX86[] = {
298
    0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0
299
};
300
301
static const uint8_t ImportThunkARM[] = {
302
    0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0
303
    0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0
304
    0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]
305
};
306
307
static const uint8_t ImportThunkARM64[] = {
308
    0x10, 0x00, 0x00, 0x90, // adrp x16, #0
309
    0x10, 0x02, 0x40, 0xf9, // ldr  x16, [x16]
310
    0x00, 0x02, 0x1f, 0xd6, // br   x16
311
};
312
313
// Windows-specific.
314
// A chunk for DLL import jump table entry. In a final output, it's
315
// contents will be a JMP instruction to some __imp_ symbol.
316
class ImportThunkChunkX64 : public Chunk {
317
public:
318
  explicit ImportThunkChunkX64(Defined *S);
319
126
  size_t getSize() const override { return sizeof(ImportThunkX86); }
320
  void writeTo(uint8_t *Buf) const override;
321
322
private:
323
  Defined *ImpSymbol;
324
};
325
326
class ImportThunkChunkX86 : public Chunk {
327
public:
328
18
  explicit ImportThunkChunkX86(Defined *S) : ImpSymbol(S) {}
329
22
  size_t getSize() const override { return sizeof(ImportThunkX86); }
330
  void getBaserels(std::vector<Baserel> *Res) override;
331
  void writeTo(uint8_t *Buf) const override;
332
333
private:
334
  Defined *ImpSymbol;
335
};
336
337
class ImportThunkChunkARM : public Chunk {
338
public:
339
2
  explicit ImportThunkChunkARM(Defined *S) : ImpSymbol(S) {}
340
0
  size_t getSize() const override { return sizeof(ImportThunkARM); }
341
  void getBaserels(std::vector<Baserel> *Res) override;
342
  void writeTo(uint8_t *Buf) const override;
343
344
private:
345
  Defined *ImpSymbol;
346
};
347
348
class ImportThunkChunkARM64 : public Chunk {
349
public:
350
4
  explicit ImportThunkChunkARM64(Defined *S) : ImpSymbol(S) {}
351
4
  size_t getSize() const override { return sizeof(ImportThunkARM64); }
352
  void writeTo(uint8_t *Buf) const override;
353
354
private:
355
  Defined *ImpSymbol;
356
};
357
358
class RangeExtensionThunk : public Chunk {
359
public:
360
49
  explicit RangeExtensionThunk(Defined *T) : Target(T) {}
361
  size_t getSize() const override;
362
  void writeTo(uint8_t *Buf) const override;
363
364
  Defined *Target;
365
};
366
367
// Windows-specific.
368
// See comments for DefinedLocalImport class.
369
class LocalImportChunk : public Chunk {
370
public:
371
7
  explicit LocalImportChunk(Defined *S) : Sym(S) {
372
7
    Alignment = Config->Wordsize;
373
7
  }
374
  size_t getSize() const override;
375
  void getBaserels(std::vector<Baserel> *Res) override;
376
  void writeTo(uint8_t *Buf) const override;
377
378
private:
379
  Defined *Sym;
380
};
381
382
// Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and
383
// offset into the chunk. Order does not matter as the RVA table will be sorted
384
// later.
385
struct ChunkAndOffset {
386
  Chunk *InputChunk;
387
  uint32_t Offset;
388
389
  struct DenseMapInfo {
390
192
    static ChunkAndOffset getEmptyKey() {
391
192
      return {llvm::DenseMapInfo<Chunk *>::getEmptyKey(), 0};
392
192
    }
393
141
    static ChunkAndOffset getTombstoneKey() {
394
141
      return {llvm::DenseMapInfo<Chunk *>::getTombstoneKey(), 0};
395
141
    }
396
36
    static unsigned getHashValue(const ChunkAndOffset &CO) {
397
36
      return llvm::DenseMapInfo<std::pair<Chunk *, uint32_t>>::getHashValue(
398
36
          {CO.InputChunk, CO.Offset});
399
36
    }
400
3.20k
    static bool isEqual(const ChunkAndOffset &LHS, const ChunkAndOffset &RHS) {
401
3.20k
      return LHS.InputChunk == RHS.InputChunk && 
LHS.Offset == RHS.Offset2.98k
;
402
3.20k
    }
403
  };
404
};
405
406
using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>;
407
408
// Table which contains symbol RVAs. Used for /safeseh and /guard:cf.
409
class RVATableChunk : public Chunk {
410
public:
411
18
  explicit RVATableChunk(SymbolRVASet S) : Syms(std::move(S)) {}
412
36
  size_t getSize() const override { return Syms.size() * 4; }
413
  void writeTo(uint8_t *Buf) const override;
414
415
private:
416
  SymbolRVASet Syms;
417
};
418
419
// Windows-specific.
420
// This class represents a block in .reloc section.
421
// See the PE/COFF spec 5.6 for details.
422
class BaserelChunk : public Chunk {
423
public:
424
  BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End);
425
104
  size_t getSize() const override { return Data.size(); }
426
  void writeTo(uint8_t *Buf) const override;
427
428
private:
429
  std::vector<uint8_t> Data;
430
};
431
432
class Baserel {
433
public:
434
206
  Baserel(uint32_t V, uint8_t Ty) : RVA(V), Type(Ty) {}
435
34
  explicit Baserel(uint32_t V) : Baserel(V, getDefaultType()) {}
lld::coff::Baserel::Baserel(unsigned int)
Line
Count
Source
435
34
  explicit Baserel(uint32_t V) : Baserel(V, getDefaultType()) {}
Unexecuted instantiation: lld::coff::Baserel::Baserel(unsigned int)
436
  uint8_t getDefaultType();
437
438
  uint32_t RVA;
439
  uint8_t Type;
440
};
441
442
// This is a placeholder Chunk, to allow attaching a DefinedSynthetic to a
443
// specific place in a section, without any data. This is used for the MinGW
444
// specific symbol __RUNTIME_PSEUDO_RELOC_LIST_END__, even though the concept
445
// of an empty chunk isn't MinGW specific.
446
class EmptyChunk : public Chunk {
447
public:
448
38
  EmptyChunk() {}
449
38
  size_t getSize() const override { return 0; }
450
38
  void writeTo(uint8_t *Buf) const override {}
451
};
452
453
// MinGW specific, for the "automatic import of variables from DLLs" feature.
454
// This provides the table of runtime pseudo relocations, for variable
455
// references that turned out to need to be imported from a DLL even though
456
// the reference didn't use the dllimport attribute. The MinGW runtime will
457
// process this table after loading, before handling control over to user
458
// code.
459
class PseudoRelocTableChunk : public Chunk {
460
public:
461
  PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &Relocs)
462
38
      : Relocs(std::move(Relocs)) {
463
38
    Alignment = 4;
464
38
  }
465
  size_t getSize() const override;
466
  void writeTo(uint8_t *Buf) const override;
467
468
private:
469
  std::vector<RuntimePseudoReloc> Relocs;
470
};
471
472
// MinGW specific; information about one individual location in the image
473
// that needs to be fixed up at runtime after loading. This represents
474
// one individual element in the PseudoRelocTableChunk table.
475
class RuntimePseudoReloc {
476
public:
477
  RuntimePseudoReloc(Defined *Sym, SectionChunk *Target, uint32_t TargetOffset,
478
                     int Flags)
479
5
      : Sym(Sym), Target(Target), TargetOffset(TargetOffset), Flags(Flags) {}
480
481
  Defined *Sym;
482
  SectionChunk *Target;
483
  uint32_t TargetOffset;
484
  // The Flags field contains the size of the relocation, in bits. No other
485
  // flags are currently defined.
486
  int Flags;
487
};
488
489
// MinGW specific. A Chunk that contains one pointer-sized absolute value.
490
class AbsolutePointerChunk : public Chunk {
491
public:
492
152
  AbsolutePointerChunk(uint64_t Value) : Value(Value) {
493
152
    Alignment = getSize();
494
152
  }
495
  size_t getSize() const override;
496
  void writeTo(uint8_t *Buf) const override;
497
498
private:
499
  uint64_t Value;
500
};
501
502
void applyMOV32T(uint8_t *Off, uint32_t V);
503
void applyBranch24T(uint8_t *Off, int32_t V);
504
505
void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift);
506
void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit);
507
void applyArm64Branch26(uint8_t *Off, int64_t V);
508
509
} // namespace coff
510
} // namespace lld
511
512
namespace llvm {
513
template <>
514
struct DenseMapInfo<lld::coff::ChunkAndOffset>
515
    : lld::coff::ChunkAndOffset::DenseMapInfo {};
516
}
517
518
#endif