Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/lld/COFF/Chunks.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Chunks.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
#include "Chunks.h"
11
#include "Error.h"
12
#include "InputFiles.h"
13
#include "Symbols.h"
14
#include "Writer.h"
15
#include "llvm/ADT/Twine.h"
16
#include "llvm/BinaryFormat/COFF.h"
17
#include "llvm/Object/COFF.h"
18
#include "llvm/Support/Debug.h"
19
#include "llvm/Support/Endian.h"
20
#include "llvm/Support/raw_ostream.h"
21
#include <algorithm>
22
23
using namespace llvm;
24
using namespace llvm::object;
25
using namespace llvm::support::endian;
26
using namespace llvm::COFF;
27
using llvm::support::ulittle32_t;
28
29
namespace lld {
30
namespace coff {
31
32
SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)
33
    : Chunk(SectionKind), Repl(this), Header(H), File(F),
34
      Relocs(File->getCOFFObj()->getRelocations(Header)),
35
821
      NumRelocs(std::distance(Relocs.begin(), Relocs.end())) {
36
821
  // Initialize SectionName.
37
821
  File->getCOFFObj()->getSectionName(Header, SectionName);
38
821
39
821
  Alignment = Header->getAlignment();
40
821
41
821
  // Chunks may be discarded during comdat merging.
42
821
  Discarded = false;
43
821
44
821
  // If linker GC is disabled, every chunk starts out alive.  If linker GC is
45
821
  // enabled, treat non-comdat sections as roots. Generally optimized object
46
821
  // files will be built with -ffunction-sections or /Gy, so most things worth
47
821
  // stripping will be in a comdat.
48
796
  Live = !Config->DoGC || !isCOMDAT();
49
821
}
50
51
99
static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
52
416
static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
53
55
static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
54
8
static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
55
3
static void or32(uint8_t *P, uint32_t V) { write32le(P, read32le(P) | V); }
56
57
static void applySecRel(const SectionChunk *Sec, uint8_t *Off,
58
110
                        OutputSection *OS, uint64_t S) {
59
110
  if (
!OS110
) {
60
2
    if (Sec->isCodeView())
61
2
      return;
62
0
    fatal("SECREL relocation cannot be applied to absolute symbols");
63
0
  }
64
108
  uint64_t SecRel = S - OS->getRVA();
65
108
  if (
SecRel > UINT32_MAX108
) {
66
0
    error("overflow in SECREL relocation in section: " + Sec->getSectionName());
67
0
    return;
68
0
  }
69
108
  add32(Off, SecRel);
70
108
}
71
72
99
static void applySecIdx(uint8_t *Off, OutputSection *OS) {
73
99
  // If we have no output section, this must be an absolute symbol. Use the
74
99
  // sentinel absolute symbol section index.
75
99
  uint16_t SecIdx = OS ? 
OS->SectionIndex96
:
DefinedAbsolute::OutputSectionIndex3
;
76
99
  add16(Off, SecIdx);
77
99
}
78
79
void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS,
80
457
                               uint64_t S, uint64_t P) const {
81
457
  switch (Type) {
82
8
  case IMAGE_REL_AMD64_ADDR32:   add32(Off, S + Config->ImageBase); break;
83
54
  case IMAGE_REL_AMD64_ADDR64:   add64(Off, S + Config->ImageBase); break;
84
130
  case IMAGE_REL_AMD64_ADDR32NB: add32(Off, S); break;
85
115
  case IMAGE_REL_AMD64_REL32:    add32(Off, S - P - 4); break;
86
1
  case IMAGE_REL_AMD64_REL32_1:  add32(Off, S - P - 5); break;
87
1
  case IMAGE_REL_AMD64_REL32_2:  add32(Off, S - P - 6); break;
88
1
  case IMAGE_REL_AMD64_REL32_3:  add32(Off, S - P - 7); break;
89
1
  case IMAGE_REL_AMD64_REL32_4:  add32(Off, S - P - 8); break;
90
1
  case IMAGE_REL_AMD64_REL32_5:  add32(Off, S - P - 9); break;
91
73
  case IMAGE_REL_AMD64_SECTION:  applySecIdx(Off, OS); break;
92
72
  case IMAGE_REL_AMD64_SECREL:   applySecRel(this, Off, OS, S); break;
93
0
  default:
94
0
    fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
95
458
  }
96
458
}
97
98
void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS,
99
112
                               uint64_t S, uint64_t P) const {
100
112
  switch (Type) {
101
1
  case IMAGE_REL_I386_ABSOLUTE: break;
102
26
  case IMAGE_REL_I386_DIR32:    add32(Off, S + Config->ImageBase); break;
103
4
  case IMAGE_REL_I386_DIR32NB:  add32(Off, S); break;
104
18
  case IMAGE_REL_I386_REL32:    add32(Off, S - P - 4); break;
105
26
  case IMAGE_REL_I386_SECTION:  applySecIdx(Off, OS); break;
106
37
  case IMAGE_REL_I386_SECREL:   applySecRel(this, Off, OS, S); break;
107
0
  default:
108
0
    fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
109
112
  }
110
112
}
111
112
18
static void applyMOV(uint8_t *Off, uint16_t V) {
113
18
  write16le(Off, (read16le(Off) & 0xfbf0) | ((V & 0x800) >> 1) | ((V >> 12) & 0xf));
114
18
  write16le(Off + 2, (read16le(Off + 2) & 0x8f00) | ((V & 0x700) << 4) | (V & 0xff));
115
18
}
116
117
18
static uint16_t readMOV(uint8_t *Off) {
118
18
  uint16_t Opcode1 = read16le(Off);
119
18
  uint16_t Opcode2 = read16le(Off + 2);
120
18
  uint16_t Imm = (Opcode2 & 0x00ff) | ((Opcode2 >> 4) & 0x0700);
121
18
  Imm |= ((Opcode1 << 1) & 0x0800) | ((Opcode1 & 0x000f) << 12);
122
18
  return Imm;
123
18
}
124
125
9
void applyMOV32T(uint8_t *Off, uint32_t V) {
126
9
  uint16_t ImmW = readMOV(Off);     // read MOVW operand
127
9
  uint16_t ImmT = readMOV(Off + 4); // read MOVT operand
128
9
  uint32_t Imm = ImmW | (ImmT << 16);
129
9
  V += Imm;                         // add the immediate offset
130
9
  applyMOV(Off, V);           // set MOVW operand
131
9
  applyMOV(Off + 4, V >> 16); // set MOVT operand
132
9
}
133
134
1
static void applyBranch20T(uint8_t *Off, int32_t V) {
135
1
  uint32_t S = V < 0 ? 
11
:
00
;
136
1
  uint32_t J1 = (V >> 19) & 1;
137
1
  uint32_t J2 = (V >> 18) & 1;
138
1
  or16(Off, (S << 10) | ((V >> 12) & 0x3f));
139
1
  or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
140
1
}
141
142
6
void applyBranch24T(uint8_t *Off, int32_t V) {
143
6
  if (!isInt<25>(V))
144
0
    fatal("relocation out of range");
145
6
  
uint32_t S = V < 0 ? 6
15
:
01
;
146
6
  uint32_t J1 = ((~V >> 23) & 1) ^ S;
147
6
  uint32_t J2 = ((~V >> 22) & 1) ^ S;
148
6
  or16(Off, (S << 10) | ((V >> 12) & 0x3ff));
149
6
  // Clear out the J1 and J2 bits which may be set.
150
6
  write16le(Off + 2, (read16le(Off + 2) & 0xd000) | (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
151
6
}
152
153
void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS,
154
14
                               uint64_t S, uint64_t P) const {
155
14
  // Pointer to thumb code must have the LSB set.
156
14
  uint64_t SX = S;
157
14
  if (
OS && 14
(OS->getPermissions() & IMAGE_SCN_MEM_EXECUTE)14
)
158
11
    SX |= 1;
159
14
  switch (Type) {
160
1
  case IMAGE_REL_ARM_ADDR32:    add32(Off, SX + Config->ImageBase); break;
161
1
  case IMAGE_REL_ARM_ADDR32NB:  add32(Off, SX); break;
162
5
  case IMAGE_REL_ARM_MOV32T:    applyMOV32T(Off, SX + Config->ImageBase); break;
163
1
  case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(Off, SX - P - 4); break;
164
3
  case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, SX - P - 4); break;
165
2
  case IMAGE_REL_ARM_BLX23T:    applyBranch24T(Off, SX - P - 4); break;
166
0
  case IMAGE_REL_ARM_SECTION:   applySecIdx(Off, OS); break;
167
1
  case IMAGE_REL_ARM_SECREL:    applySecRel(this, Off, OS, S); break;
168
0
  default:
169
0
    fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
170
14
  }
171
14
}
172
173
// Interpret the existing immediate value as a byte offset to the
174
// target symbol, then update the instruction with the immediate as
175
// the page offset from the current instruction to the target.
176
5
static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P) {
177
5
  uint32_t Orig = read32le(Off);
178
5
  uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC);
179
5
  S += Imm;
180
5
  Imm = (S >> 12) - (P >> 12);
181
5
  uint32_t ImmLo = (Imm & 0x3) << 29;
182
5
  uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;
183
5
  uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);
184
5
  write32le(Off, (Orig & ~Mask) | ImmLo | ImmHi);
185
5
}
186
187
// Update the immediate field in a AARCH64 ldr, str, and add instruction.
188
// Optionally limit the range of the written immediate by one or more bits
189
// (RangeLimit).
190
24
static void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) {
191
24
  uint32_t Orig = read32le(Off);
192
24
  Imm += (Orig >> 10) & 0xFFF;
193
24
  Orig &= ~(0xFFF << 10);
194
24
  write32le(Off, Orig | ((Imm & (0xFFF >> RangeLimit)) << 10));
195
24
}
196
197
// Add the 12 bit page offset to the existing immediate.
198
// Ldr/str instructions store the opcode immediate scaled
199
// by the load/store size (giving a larger range for larger
200
// loads/stores). The immediate is always (both before and after
201
// fixing up the relocation) stored scaled similarly.
202
// Even if larger loads/stores have a larger range, limit the
203
// effective offset to 12 bit, since it is intended to be a
204
// page offset.
205
23
static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) {
206
23
  uint32_t Orig = read32le(Off);
207
23
  uint32_t Size = Orig >> 30;
208
23
  // 0x04000000 indicates SIMD/FP registers
209
23
  // 0x00800000 indicates 128 bit
210
23
  if ((Orig & 0x4800000) == 0x4800000)
211
2
    Size += 4;
212
23
  if ((Imm & ((1 << Size) - 1)) != 0)
213
0
    fatal("misaligned ldr/str offset");
214
23
  applyArm64Imm(Off, Imm >> Size, Size);
215
23
}
216
217
void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS,
218
27
                                 uint64_t S, uint64_t P) const {
219
27
  switch (Type) {
220
2
  case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P); break;
221
1
  case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff, 0); break;
222
20
  case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break;
223
3
  case IMAGE_REL_ARM64_BRANCH26:       or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break;
224
0
  case IMAGE_REL_ARM64_ADDR32:         add32(Off, S + Config->ImageBase); break;
225
1
  case IMAGE_REL_ARM64_ADDR64:         add64(Off, S + Config->ImageBase); break;
226
0
  default:
227
0
    fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
228
27
  }
229
27
}
230
231
505
void SectionChunk::writeTo(uint8_t *Buf) const {
232
505
  if (!hasData())
233
5
    return;
234
500
  // Copy section contents from source object file to output file.
235
500
  ArrayRef<uint8_t> A = getContents();
236
500
  memcpy(Buf + OutputSectionOff, A.data(), A.size());
237
500
238
500
  // Apply relocations.
239
500
  size_t InputSize = getSize();
240
615
  for (const coff_relocation &Rel : Relocs) {
241
615
    // Check for an invalid relocation offset. This check isn't perfect, because
242
615
    // we don't have the relocation size, which is only known after checking the
243
615
    // machine and relocation type. As a result, a relocation may overwrite the
244
615
    // beginning of the following input section.
245
615
    if (Rel.VirtualAddress >= InputSize)
246
0
      fatal("relocation points beyond the end of its parent section");
247
615
248
615
    uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;
249
615
250
615
    // Get the output section of the symbol for this relocation.  The output
251
615
    // section is needed to compute SECREL and SECTION relocations used in debug
252
615
    // info.
253
615
    SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
254
615
    Defined *Sym = cast<Defined>(Body);
255
615
    Chunk *C = Sym->getChunk();
256
615
    OutputSection *OS = C ? 
C->getOutputSection()576
:
nullptr39
;
257
615
258
615
    // Only absolute and __ImageBase symbols lack an output section. For any
259
615
    // other symbol, this indicates that the chunk was discarded.  Normally
260
615
    // relocations against discarded sections are an error.  However, debug info
261
615
    // sections are not GC roots and can end up with these kinds of relocations.
262
615
    // Skip these relocations.
263
615
    if (
!OS && 615
!isa<DefinedAbsolute>(Sym)42
&&
!isa<DefinedSynthetic>(Sym)20
) {
264
5
      if (
isCodeView() || 5
isDWARF()1
)
265
5
        continue;
266
0
      fatal("relocation against symbol in discarded section: " +
267
0
            Sym->getName());
268
0
    }
269
610
    uint64_t S = Sym->getRVA();
270
610
271
610
    // Compute the RVA of the relocation for relative relocations.
272
610
    uint64_t P = RVA + Rel.VirtualAddress;
273
610
    switch (Config->Machine) {
274
457
    case AMD64:
275
457
      applyRelX64(Off, Rel.Type, OS, S, P);
276
457
      break;
277
112
    case I386:
278
112
      applyRelX86(Off, Rel.Type, OS, S, P);
279
112
      break;
280
14
    case ARMNT:
281
14
      applyRelARM(Off, Rel.Type, OS, S, P);
282
14
      break;
283
27
    case ARM64:
284
27
      applyRelARM64(Off, Rel.Type, OS, S, P);
285
27
      break;
286
0
    default:
287
0
      llvm_unreachable("unknown machine type");
288
501
    }
289
501
  }
290
505
}
291
292
14
void SectionChunk::addAssociative(SectionChunk *Child) {
293
14
  AssocChildren.push_back(Child);
294
14
}
295
296
408
static uint8_t getBaserelType(const coff_relocation &Rel) {
297
408
  switch (Config->Machine) {
298
307
  case AMD64:
299
307
    if (Rel.Type == IMAGE_REL_AMD64_ADDR64)
300
47
      return IMAGE_REL_BASED_DIR64;
301
260
    return IMAGE_REL_BASED_ABSOLUTE;
302
60
  case I386:
303
60
    if (Rel.Type == IMAGE_REL_I386_DIR32)
304
26
      return IMAGE_REL_BASED_HIGHLOW;
305
34
    return IMAGE_REL_BASED_ABSOLUTE;
306
14
  case ARMNT:
307
14
    if (Rel.Type == IMAGE_REL_ARM_ADDR32)
308
1
      return IMAGE_REL_BASED_HIGHLOW;
309
13
    
if (13
Rel.Type == IMAGE_REL_ARM_MOV32T13
)
310
5
      return IMAGE_REL_BASED_ARM_MOV32T;
311
8
    return IMAGE_REL_BASED_ABSOLUTE;
312
27
  case ARM64:
313
27
    if (Rel.Type == IMAGE_REL_ARM64_ADDR64)
314
1
      return IMAGE_REL_BASED_DIR64;
315
26
    return IMAGE_REL_BASED_ABSOLUTE;
316
0
  default:
317
0
    llvm_unreachable("unknown machine type");
318
0
  }
319
0
}
320
321
// Windows-specific.
322
// Collect all locations that contain absolute addresses, which need to be
323
// fixed by the loader if load-time relocation is needed.
324
// Only called when base relocation is enabled.
325
706
void SectionChunk::getBaserels(std::vector<Baserel> *Res) {
326
408
  for (const coff_relocation &Rel : Relocs) {
327
408
    uint8_t Ty = getBaserelType(Rel);
328
408
    if (Ty == IMAGE_REL_BASED_ABSOLUTE)
329
328
      continue;
330
80
    SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
331
80
    if (isa<DefinedAbsolute>(Body))
332
14
      continue;
333
66
    Res->emplace_back(RVA + Rel.VirtualAddress, Ty);
334
66
  }
335
706
}
336
337
1.22k
bool SectionChunk::hasData() const {
338
1.22k
  return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
339
1.22k
}
340
341
2.17k
uint32_t SectionChunk::getPermissions() const {
342
2.17k
  return Header->Characteristics & PermMask;
343
2.17k
}
344
345
4.38k
bool SectionChunk::isCOMDAT() const {
346
4.38k
  return Header->Characteristics & IMAGE_SCN_LNK_COMDAT;
347
4.38k
}
348
349
11
void SectionChunk::printDiscardedMessage() const {
350
11
  // Removed by dead-stripping. If it's removed by ICF, ICF already
351
11
  // printed out the name, so don't repeat that here.
352
11
  if (
Sym && 11
this == Repl11
) {
353
4
    if (Discarded)
354
0
      message("Discarded comdat symbol " + Sym->getName());
355
4
    else 
if (4
!Live4
)
356
4
      message("Discarded " + Sym->getName());
357
4
  }
358
11
}
359
360
13
StringRef SectionChunk::getDebugName() {
361
13
  if (Sym)
362
13
    return Sym->getName();
363
0
  return "";
364
0
}
365
366
664
ArrayRef<uint8_t> SectionChunk::getContents() const {
367
664
  ArrayRef<uint8_t> A;
368
664
  File->getCOFFObj()->getSectionContents(Header, A);
369
664
  return A;
370
664
}
371
372
7
void SectionChunk::replace(SectionChunk *Other) {
373
7
  Other->Repl = Repl;
374
7
  Other->Live = false;
375
7
}
376
377
10
CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
378
10
  // Common symbols are aligned on natural boundaries up to 32 bytes.
379
10
  // This is what MSVC link.exe does.
380
10
  Alignment = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue()));
381
10
}
382
383
10
uint32_t CommonChunk::getPermissions() const {
384
10
  return IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ |
385
10
         IMAGE_SCN_MEM_WRITE;
386
10
}
387
388
149
void StringChunk::writeTo(uint8_t *Buf) const {
389
149
  memcpy(Buf + OutputSectionOff, Str.data(), Str.size());
390
149
}
391
392
46
ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {
393
46
  // Intel Optimization Manual says that all branch targets
394
46
  // should be 16-byte aligned. MSVC linker does this too.
395
46
  Alignment = 16;
396
46
}
397
398
44
void ImportThunkChunkX64::writeTo(uint8_t *Buf) const {
399
44
  memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));
400
44
  // The first two bytes is a JMP instruction. Fill its operand.
401
44
  write32le(Buf + OutputSectionOff + 2, ImpSymbol->getRVA() - RVA - getSize());
402
44
}
403
404
12
void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *Res) {
405
12
  Res->emplace_back(getRVA() + 2);
406
12
}
407
408
12
void ImportThunkChunkX86::writeTo(uint8_t *Buf) const {
409
12
  memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));
410
12
  // The first two bytes is a JMP instruction. Fill its operand.
411
12
  write32le(Buf + OutputSectionOff + 2,
412
12
            ImpSymbol->getRVA() + Config->ImageBase);
413
12
}
414
415
2
void ImportThunkChunkARM::getBaserels(std::vector<Baserel> *Res) {
416
2
  Res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T);
417
2
}
418
419
2
void ImportThunkChunkARM::writeTo(uint8_t *Buf) const {
420
2
  memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM));
421
2
  // Fix mov.w and mov.t operands.
422
2
  applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase);
423
2
}
424
425
3
void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const {
426
3
  int64_t Off = ImpSymbol->getRVA() & 0xfff;
427
3
  memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64));
428
3
  applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA);
429
3
  applyArm64Ldr(Buf + OutputSectionOff + 4, Off);
430
3
}
431
432
2
void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {
433
2
  Res->emplace_back(getRVA());
434
2
}
435
436
2
size_t LocalImportChunk::getSize() const {
437
2
  return Config->is64() ? 
81
:
41
;
438
2
}
439
440
2
void LocalImportChunk::writeTo(uint8_t *Buf) const {
441
2
  if (
Config->is64()2
) {
442
1
    write64le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);
443
2
  } else {
444
1
    write32le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);
445
1
  }
446
2
}
447
448
2
void SEHTableChunk::writeTo(uint8_t *Buf) const {
449
2
  ulittle32_t *Begin = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff);
450
2
  size_t Cnt = 0;
451
2
  for (Defined *D : Syms)
452
3
    Begin[Cnt++] = D->getRVA();
453
2
  std::sort(Begin, Begin + Cnt);
454
2
}
455
456
// Windows-specific. This class represents a block in .reloc section.
457
// The format is described here.
458
//
459
// On Windows, each DLL is linked against a fixed base address and
460
// usually loaded to that address. However, if there's already another
461
// DLL that overlaps, the loader has to relocate it. To do that, DLLs
462
// contain .reloc sections which contain offsets that need to be fixed
463
// up at runtime. If the loader finds that a DLL cannot be loaded to its
464
// desired base address, it loads it to somewhere else, and add <actual
465
// base address> - <desired base address> to each offset that is
466
// specified by the .reloc section. In ELF terms, .reloc sections
467
// contain relative relocations in REL format (as opposed to RELA.)
468
//
469
// This already significantly reduces the size of relocations compared
470
// to ELF .rel.dyn, but Windows does more to reduce it (probably because
471
// it was invented for PCs in the late '80s or early '90s.)  Offsets in
472
// .reloc are grouped by page where the page size is 12 bits, and
473
// offsets sharing the same page address are stored consecutively to
474
// represent them with less space. This is very similar to the page
475
// table which is grouped by (multiple stages of) pages.
476
//
477
// For example, let's say we have 0x00030, 0x00500, 0x00700, 0x00A00,
478
// 0x20004, and 0x20008 in a .reloc section for x64. The uppermost 4
479
// bits have a type IMAGE_REL_BASED_DIR64 or 0xA. In the section, they
480
// are represented like this:
481
//
482
//   0x00000  -- page address (4 bytes)
483
//   16       -- size of this block (4 bytes)
484
//     0xA030 -- entries (2 bytes each)
485
//     0xA500
486
//     0xA700
487
//     0xAA00
488
//   0x20000  -- page address (4 bytes)
489
//   12       -- size of this block (4 bytes)
490
//     0xA004 -- entries (2 bytes each)
491
//     0xA008
492
//
493
// Usually we have a lot of relocations for each page, so the number of
494
// bytes for one .reloc entry is close to 2 bytes on average.
495
41
BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
496
41
  // Block header consists of 4 byte page RVA and 4 byte block size.
497
41
  // Each entry is 2 byte. Last entry may be padding.
498
41
  Data.resize(alignTo((End - Begin) * 2 + 8, 4));
499
41
  uint8_t *P = Data.data();
500
41
  write32le(P, Page);
501
41
  write32le(P + 4, Data.size());
502
41
  P += 8;
503
135
  for (Baserel *I = Begin; 
I != End135
;
++I94
) {
504
94
    write16le(P, (I->Type << 12) | (I->RVA - Page));
505
94
    P += 2;
506
94
  }
507
41
}
508
509
41
void BaserelChunk::writeTo(uint8_t *Buf) const {
510
41
  memcpy(Buf + OutputSectionOff, Data.data(), Data.size());
511
41
}
512
513
24
uint8_t Baserel::getDefaultType() {
514
24
  switch (Config->Machine) {
515
4
  case AMD64:
516
4
    return IMAGE_REL_BASED_DIR64;
517
20
  case I386:
518
20
  case ARMNT:
519
20
    return IMAGE_REL_BASED_HIGHLOW;
520
0
  default:
521
0
    llvm_unreachable("unknown machine type");
522
0
  }
523
0
}
524
525
} // namespace coff
526
} // namespace lld