Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- X86ELFObjectWriter.cpp - X86 ELF Writer ---------------------------===//
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
#include "MCTargetDesc/X86FixupKinds.h"
10
#include "MCTargetDesc/X86MCTargetDesc.h"
11
#include "llvm/BinaryFormat/ELF.h"
12
#include "llvm/MC/MCAsmInfo.h"
13
#include "llvm/MC/MCContext.h"
14
#include "llvm/MC/MCELFObjectWriter.h"
15
#include "llvm/MC/MCExpr.h"
16
#include "llvm/MC/MCFixup.h"
17
#include "llvm/MC/MCObjectWriter.h"
18
#include "llvm/MC/MCValue.h"
19
#include "llvm/Support/ErrorHandling.h"
20
#include <cassert>
21
#include <cstdint>
22
23
using namespace llvm;
24
25
namespace {
26
27
class X86ELFObjectWriter : public MCELFObjectTargetWriter {
28
public:
29
  X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
30
8.88k
  ~X86ELFObjectWriter() override = default;
31
32
protected:
33
  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
34
                        const MCFixup &Fixup, bool IsPCRel) const override;
35
};
36
37
} // end anonymous namespace
38
39
X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
40
                                       uint16_t EMachine)
41
    : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
42
                              // Only i386 and IAMCU use Rel instead of RelA.
43
                              /*HasRelocationAddend*/
44
                              (EMachine != ELF::EM_386) &&
45
8.93k
                                  (EMachine != ELF::EM_IAMCU)) {}
46
47
enum X86_64RelType { RT64_NONE, RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 };
48
49
static X86_64RelType getType64(unsigned Kind,
50
                               MCSymbolRefExpr::VariantKind &Modifier,
51
7.91k
                               bool &IsPCRel) {
52
7.91k
  switch (Kind) {
53
7.91k
  default:
54
0
    llvm_unreachable("Unimplemented");
55
7.91k
  case FK_NONE:
56
16
    return RT64_NONE;
57
7.91k
  case X86::reloc_global_offset_table8:
58
6
    Modifier = MCSymbolRefExpr::VK_GOT;
59
6
    IsPCRel = true;
60
6
    return RT64_64;
61
7.91k
  case FK_Data_8:
62
1.62k
    return RT64_64;
63
7.91k
  case X86::reloc_signed_4byte:
64
344
  case X86::reloc_signed_4byte_relax:
65
344
    if (Modifier == MCSymbolRefExpr::VK_None && 
!IsPCRel201
)
66
198
      return RT64_32S;
67
146
    return RT64_32;
68
146
  case X86::reloc_global_offset_table:
69
17
    Modifier = MCSymbolRefExpr::VK_GOT;
70
17
    IsPCRel = true;
71
17
    return RT64_32;
72
5.28k
  case FK_Data_4:
73
5.28k
  case FK_PCRel_4:
74
5.28k
  case X86::reloc_riprel_4byte:
75
5.28k
  case X86::reloc_riprel_4byte_relax:
76
5.28k
  case X86::reloc_riprel_4byte_relax_rex:
77
5.28k
  case X86::reloc_riprel_4byte_movq_load:
78
5.28k
    return RT64_32;
79
5.28k
  case X86::reloc_branch_4byte_pcrel:
80
531
    Modifier = MCSymbolRefExpr::VK_PLT;
81
531
    return RT64_32;
82
5.28k
  case FK_PCRel_2:
83
61
  case FK_Data_2:
84
61
    return RT64_16;
85
61
  case FK_PCRel_1:
86
32
  case FK_Data_1:
87
32
    return RT64_8;
88
7.91k
  }
89
7.91k
}
90
91
987
static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
92
987
  if (Type != RT64_32)
93
5
    Ctx.reportError(Loc,
94
5
                    "32 bit reloc applied to a field with a different size");
95
987
}
96
97
static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
98
                               MCSymbolRefExpr::VariantKind Modifier,
99
                               X86_64RelType Type, bool IsPCRel,
100
7.28k
                               unsigned Kind) {
101
7.28k
  switch (Modifier) {
102
7.28k
  default:
103
0
    llvm_unreachable("Unimplemented");
104
7.28k
  case MCSymbolRefExpr::VK_None:
105
6.18k
  case MCSymbolRefExpr::VK_X86_ABS8:
106
6.18k
    switch (Type) {
107
6.18k
    case RT64_NONE:
108
6
      if (Modifier == MCSymbolRefExpr::VK_None)
109
6
        return ELF::R_X86_64_NONE;
110
0
      llvm_unreachable("Unimplemented");
111
1.57k
    case RT64_64:
112
1.57k
      return IsPCRel ? 
ELF::R_X86_64_PC6418
:
ELF::R_X86_64_641.55k
;
113
4.34k
    case RT64_32:
114
4.34k
      return IsPCRel ? 
ELF::R_X86_64_PC32933
:
ELF::R_X86_64_323.40k
;
115
198
    case RT64_32S:
116
198
      return ELF::R_X86_64_32S;
117
47
    case RT64_16:
118
47
      return IsPCRel ? 
ELF::R_X86_64_PC1610
:
ELF::R_X86_64_1637
;
119
18
    case RT64_8:
120
18
      return IsPCRel ? 
ELF::R_X86_64_PC86
:
ELF::R_X86_64_812
;
121
0
    }
122
0
    llvm_unreachable("unexpected relocation type!");
123
18
  case MCSymbolRefExpr::VK_GOT:
124
18
    switch (Type) {
125
18
    case RT64_64:
126
11
      return IsPCRel ? 
ELF::R_X86_64_GOTPC646
:
ELF::R_X86_64_GOT645
;
127
18
    case RT64_32:
128
7
      return IsPCRel ? 
ELF::R_X86_64_GOTPC324
:
ELF::R_X86_64_GOT323
;
129
18
    case RT64_32S:
130
0
    case RT64_16:
131
0
    case RT64_8:
132
0
    case RT64_NONE:
133
0
      llvm_unreachable("Unimplemented");
134
0
    }
135
0
    llvm_unreachable("unexpected relocation type!");
136
5
  case MCSymbolRefExpr::VK_GOTOFF:
137
5
    assert(Type == RT64_64);
138
5
    assert(!IsPCRel);
139
5
    return ELF::R_X86_64_GOTOFF64;
140
23
  case MCSymbolRefExpr::VK_TPOFF:
141
23
    assert(!IsPCRel);
142
23
    switch (Type) {
143
23
    case RT64_64:
144
1
      return ELF::R_X86_64_TPOFF64;
145
23
    case RT64_32:
146
22
      return ELF::R_X86_64_TPOFF32;
147
23
    case RT64_32S:
148
0
    case RT64_16:
149
0
    case RT64_8:
150
0
    case RT64_NONE:
151
0
      llvm_unreachable("Unimplemented");
152
0
    }
153
0
    llvm_unreachable("unexpected relocation type!");
154
33
  case MCSymbolRefExpr::VK_DTPOFF:
155
33
    assert(!IsPCRel);
156
33
    switch (Type) {
157
33
    case RT64_64:
158
20
      return ELF::R_X86_64_DTPOFF64;
159
33
    case RT64_32:
160
13
      return ELF::R_X86_64_DTPOFF32;
161
33
    case RT64_32S:
162
0
    case RT64_16:
163
0
    case RT64_8:
164
0
    case RT64_NONE:
165
0
      llvm_unreachable("Unimplemented");
166
0
    }
167
0
    llvm_unreachable("unexpected relocation type!");
168
31
  case MCSymbolRefExpr::VK_SIZE:
169
31
    assert(!IsPCRel);
170
31
    switch (Type) {
171
31
    case RT64_64:
172
16
      return ELF::R_X86_64_SIZE64;
173
31
    case RT64_32:
174
15
      return ELF::R_X86_64_SIZE32;
175
31
    case RT64_32S:
176
0
    case RT64_16:
177
0
    case RT64_8:
178
0
    case RT64_NONE:
179
0
      llvm_unreachable("Unimplemented");
180
0
    }
181
0
    llvm_unreachable("unexpected relocation type!");
182
5
  case MCSymbolRefExpr::VK_TLSCALL:
183
5
    return ELF::R_X86_64_TLSDESC_CALL;
184
5
  case MCSymbolRefExpr::VK_TLSDESC:
185
5
    return ELF::R_X86_64_GOTPC32_TLSDESC;
186
23
  case MCSymbolRefExpr::VK_TLSGD:
187
23
    checkIs32(Ctx, Loc, Type);
188
23
    return ELF::R_X86_64_TLSGD;
189
45
  case MCSymbolRefExpr::VK_GOTTPOFF:
190
45
    checkIs32(Ctx, Loc, Type);
191
45
    return ELF::R_X86_64_GOTTPOFF;
192
13
  case MCSymbolRefExpr::VK_TLSLD:
193
13
    checkIs32(Ctx, Loc, Type);
194
13
    return ELF::R_X86_64_TLSLD;
195
757
  case MCSymbolRefExpr::VK_PLT:
196
757
    checkIs32(Ctx, Loc, Type);
197
757
    return ELF::R_X86_64_PLT32;
198
149
  case MCSymbolRefExpr::VK_GOTPCREL:
199
149
    checkIs32(Ctx, Loc, Type);
200
149
    // Older versions of ld.bfd/ld.gold/lld
201
149
    // do not support GOTPCRELX/REX_GOTPCRELX,
202
149
    // and we want to keep back-compatibility.
203
149
    if (!Ctx.getAsmInfo()->canRelaxRelocations())
204
26
      return ELF::R_X86_64_GOTPCREL;
205
123
    switch (Kind) {
206
123
    default:
207
17
      return ELF::R_X86_64_GOTPCREL;
208
123
    case X86::reloc_riprel_4byte_relax:
209
28
      return ELF::R_X86_64_GOTPCRELX;
210
123
    case X86::reloc_riprel_4byte_relax_rex:
211
78
    case X86::reloc_riprel_4byte_movq_load:
212
78
      return ELF::R_X86_64_REX_GOTPCRELX;
213
0
    }
214
7.28k
    
llvm_unreachable0
("unexpected relocation type!");
215
7.28k
  }
216
7.28k
}
217
218
enum X86_32RelType { RT32_NONE, RT32_32, RT32_16, RT32_8 };
219
220
630
static X86_32RelType getType32(X86_64RelType T) {
221
630
  switch (T) {
222
630
  case RT64_NONE:
223
5
    return RT32_NONE;
224
630
  case RT64_64:
225
0
    llvm_unreachable("Unimplemented");
226
630
  case RT64_32:
227
597
  case RT64_32S:
228
597
    return RT32_32;
229
597
  case RT64_16:
230
14
    return RT32_16;
231
597
  case RT64_8:
232
14
    return RT32_8;
233
0
  }
234
0
  llvm_unreachable("unexpected relocation type!");
235
0
}
236
237
static unsigned getRelocType32(MCContext &Ctx,
238
                               MCSymbolRefExpr::VariantKind Modifier,
239
                               X86_32RelType Type, bool IsPCRel,
240
630
                               unsigned Kind) {
241
630
  switch (Modifier) {
242
630
  default:
243
0
    llvm_unreachable("Unimplemented");
244
630
  case MCSymbolRefExpr::VK_None:
245
433
  case MCSymbolRefExpr::VK_X86_ABS8:
246
433
    switch (Type) {
247
433
    case RT32_NONE:
248
4
      if (Modifier == MCSymbolRefExpr::VK_None)
249
4
        return ELF::R_386_NONE;
250
0
      llvm_unreachable("Unimplemented");
251
401
    case RT32_32:
252
401
      return IsPCRel ? 
ELF::R_386_PC32106
:
ELF::R_386_32295
;
253
14
    case RT32_16:
254
14
      return IsPCRel ? 
ELF::R_386_PC166
:
ELF::R_386_168
;
255
14
    case RT32_8:
256
14
      return IsPCRel ? 
ELF::R_386_PC85
:
ELF::R_386_89
;
257
0
    }
258
0
    llvm_unreachable("unexpected relocation type!");
259
43
  case MCSymbolRefExpr::VK_GOT:
260
43
    assert(Type == RT32_32);
261
43
    if (IsPCRel)
262
14
      return ELF::R_386_GOTPC;
263
29
    // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
264
29
    // want to maintain compatibility.
265
29
    if (!Ctx.getAsmInfo()->canRelaxRelocations())
266
9
      return ELF::R_386_GOT32;
267
20
268
20
    return Kind == X86::reloc_signed_4byte_relax ? 
ELF::R_386_GOT32X6
269
20
                                                 : 
ELF::R_386_GOT3214
;
270
20
  case MCSymbolRefExpr::VK_GOTOFF:
271
12
    assert(Type == RT32_32);
272
12
    assert(!IsPCRel);
273
12
    return ELF::R_386_GOTOFF;
274
20
  case MCSymbolRefExpr::VK_TLSCALL:
275
1
    return ELF::R_386_TLS_DESC_CALL;
276
20
  case MCSymbolRefExpr::VK_TLSDESC:
277
1
    return ELF::R_386_TLS_GOTDESC;
278
20
  case MCSymbolRefExpr::VK_TPOFF:
279
12
    assert(Type == RT32_32);
280
12
    assert(!IsPCRel);
281
12
    return ELF::R_386_TLS_LE_32;
282
20
  case MCSymbolRefExpr::VK_DTPOFF:
283
11
    assert(Type == RT32_32);
284
11
    assert(!IsPCRel);
285
11
    return ELF::R_386_TLS_LDO_32;
286
20
  case MCSymbolRefExpr::VK_TLSGD:
287
13
    assert(Type == RT32_32);
288
13
    assert(!IsPCRel);
289
13
    return ELF::R_386_TLS_GD;
290
20
  case MCSymbolRefExpr::VK_GOTTPOFF:
291
2
    assert(Type == RT32_32);
292
2
    assert(!IsPCRel);
293
2
    return ELF::R_386_TLS_IE_32;
294
42
  case MCSymbolRefExpr::VK_PLT:
295
42
    assert(Type == RT32_32);
296
42
    return ELF::R_386_PLT32;
297
24
  case MCSymbolRefExpr::VK_INDNTPOFF:
298
24
    assert(Type == RT32_32);
299
24
    assert(!IsPCRel);
300
24
    return ELF::R_386_TLS_IE;
301
20
  case MCSymbolRefExpr::VK_NTPOFF:
302
10
    assert(Type == RT32_32);
303
10
    assert(!IsPCRel);
304
10
    return ELF::R_386_TLS_LE;
305
20
  case MCSymbolRefExpr::VK_GOTNTPOFF:
306
15
    assert(Type == RT32_32);
307
15
    assert(!IsPCRel);
308
15
    return ELF::R_386_TLS_GOTIE;
309
20
  case MCSymbolRefExpr::VK_TLSLDM:
310
11
    assert(Type == RT32_32);
311
11
    assert(!IsPCRel);
312
11
    return ELF::R_386_TLS_LDM;
313
630
  }
314
630
}
315
316
unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
317
                                          const MCFixup &Fixup,
318
7.91k
                                          bool IsPCRel) const {
319
7.91k
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
320
7.91k
  unsigned Kind = Fixup.getKind();
321
7.91k
  X86_64RelType Type = getType64(Kind, Modifier, IsPCRel);
322
7.91k
  if (getEMachine() == ELF::EM_X86_64)
323
7.28k
    return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind);
324
630
325
630
  assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
326
630
         "Unsupported ELF machine type.");
327
630
  return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
328
630
}
329
330
std::unique_ptr<MCObjectTargetWriter>
331
8.93k
llvm::createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine) {
332
8.93k
  return llvm::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine);
333
8.93k
}