Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- X86ELFObjectWriter.cpp - X86 ELF Writer ---------------------------===//
2
//
3
//                     The LLVM Compiler Infrastructure
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 "MCTargetDesc/X86FixupKinds.h"
11
#include "MCTargetDesc/X86MCTargetDesc.h"
12
#include "llvm/BinaryFormat/ELF.h"
13
#include "llvm/MC/MCAsmInfo.h"
14
#include "llvm/MC/MCContext.h"
15
#include "llvm/MC/MCELFObjectWriter.h"
16
#include "llvm/MC/MCExpr.h"
17
#include "llvm/MC/MCFixup.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
1.58k
  ~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
1.59k
                                  (EMachine != ELF::EM_IAMCU)) {}
46
47
enum X86_64RelType { RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 };
48
49
static X86_64RelType getType64(unsigned Kind,
50
                               MCSymbolRefExpr::VariantKind &Modifier,
51
4.28k
                               bool &IsPCRel) {
52
4.28k
  switch (Kind) {
53
0
  default:
54
0
    llvm_unreachable("Unimplemented");
55
1
  case X86::reloc_global_offset_table8:
56
1
    Modifier = MCSymbolRefExpr::VK_GOT;
57
1
    IsPCRel = true;
58
1
    return RT64_64;
59
817
  case FK_Data_8:
60
817
    return RT64_64;
61
273
  case X86::reloc_signed_4byte:
62
273
  case X86::reloc_signed_4byte_relax:
63
273
    if (
Modifier == MCSymbolRefExpr::VK_None && 273
!IsPCRel159
)
64
156
      return RT64_32S;
65
117
    return RT64_32;
66
14
  case X86::reloc_global_offset_table:
67
14
    Modifier = MCSymbolRefExpr::VK_GOT;
68
14
    IsPCRel = true;
69
14
    return RT64_32;
70
3.10k
  case FK_Data_4:
71
3.10k
  case FK_PCRel_4:
72
3.10k
  case X86::reloc_riprel_4byte:
73
3.10k
  case X86::reloc_riprel_4byte_relax:
74
3.10k
  case X86::reloc_riprel_4byte_relax_rex:
75
3.10k
  case X86::reloc_riprel_4byte_movq_load:
76
3.10k
    return RT64_32;
77
51
  case FK_PCRel_2:
78
51
  case FK_Data_2:
79
51
    return RT64_16;
80
19
  case FK_PCRel_1:
81
19
  case FK_Data_1:
82
19
    return RT64_8;
83
0
  }
84
0
}
85
86
352
static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
87
352
  if (Type != RT64_32)
88
5
    Ctx.reportError(Loc,
89
5
                    "32 bit reloc applied to a field with a different size");
90
352
}
91
92
static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
93
                               MCSymbolRefExpr::VariantKind Modifier,
94
                               X86_64RelType Type, bool IsPCRel,
95
3.82k
                               unsigned Kind) {
96
3.82k
  switch (Modifier) {
97
0
  default:
98
0
    llvm_unreachable("Unimplemented");
99
3.40k
  case MCSymbolRefExpr::VK_None:
100
3.40k
  case MCSymbolRefExpr::VK_X86_ABS8:
101
3.40k
    switch (Type) {
102
785
    case RT64_64:
103
785
      return IsPCRel ? 
ELF::R_X86_64_PC6412
:
ELF::R_X86_64_64773
;
104
2.42k
    case RT64_32:
105
2.42k
      return IsPCRel ? 
ELF::R_X86_64_PC32843
:
ELF::R_X86_64_321.57k
;
106
156
    case RT64_32S:
107
156
      return ELF::R_X86_64_32S;
108
39
    case RT64_16:
109
39
      return IsPCRel ? 
ELF::R_X86_64_PC167
:
ELF::R_X86_64_1632
;
110
7
    case RT64_8:
111
7
      return IsPCRel ? 
ELF::R_X86_64_PC83
:
ELF::R_X86_64_84
;
112
0
    }
113
8
  case MCSymbolRefExpr::VK_GOT:
114
8
    switch (Type) {
115
4
    case RT64_64:
116
4
      return IsPCRel ? 
ELF::R_X86_64_GOTPC641
:
ELF::R_X86_64_GOT643
;
117
4
    case RT64_32:
118
4
      return IsPCRel ? 
ELF::R_X86_64_GOTPC321
:
ELF::R_X86_64_GOT323
;
119
0
    case RT64_32S:
120
0
    case RT64_16:
121
0
    case RT64_8:
122
0
      llvm_unreachable("Unimplemented");
123
0
    }
124
1
  case MCSymbolRefExpr::VK_GOTOFF:
125
1
    assert(Type == RT64_64);
126
1
    assert(!IsPCRel);
127
1
    return ELF::R_X86_64_GOTOFF64;
128
9
  case MCSymbolRefExpr::VK_TPOFF:
129
9
    assert(!IsPCRel);
130
9
    switch (Type) {
131
1
    case RT64_64:
132
1
      return ELF::R_X86_64_TPOFF64;
133
8
    case RT64_32:
134
8
      return ELF::R_X86_64_TPOFF32;
135
0
    case RT64_32S:
136
0
    case RT64_16:
137
0
    case RT64_8:
138
0
      llvm_unreachable("Unimplemented");
139
0
    }
140
15
  case MCSymbolRefExpr::VK_DTPOFF:
141
15
    assert(!IsPCRel);
142
15
    switch (Type) {
143
7
    case RT64_64:
144
7
      return ELF::R_X86_64_DTPOFF64;
145
8
    case RT64_32:
146
8
      return ELF::R_X86_64_DTPOFF32;
147
0
    case RT64_32S:
148
0
    case RT64_16:
149
0
    case RT64_8:
150
0
      llvm_unreachable("Unimplemented");
151
0
    }
152
30
  case MCSymbolRefExpr::VK_SIZE:
153
30
    assert(!IsPCRel);
154
30
    switch (Type) {
155
15
    case RT64_64:
156
15
      return ELF::R_X86_64_SIZE64;
157
15
    case RT64_32:
158
15
      return ELF::R_X86_64_SIZE32;
159
0
    case RT64_32S:
160
0
    case RT64_16:
161
0
    case RT64_8:
162
0
      llvm_unreachable("Unimplemented");
163
0
    }
164
1
  case MCSymbolRefExpr::VK_TLSCALL:
165
1
    return ELF::R_X86_64_TLSDESC_CALL;
166
1
  case MCSymbolRefExpr::VK_TLSDESC:
167
1
    return ELF::R_X86_64_GOTPC32_TLSDESC;
168
17
  case MCSymbolRefExpr::VK_TLSGD:
169
17
    checkIs32(Ctx, Loc, Type);
170
17
    return ELF::R_X86_64_TLSGD;
171
42
  case MCSymbolRefExpr::VK_GOTTPOFF:
172
42
    checkIs32(Ctx, Loc, Type);
173
42
    return ELF::R_X86_64_GOTTPOFF;
174
9
  case MCSymbolRefExpr::VK_TLSLD:
175
9
    checkIs32(Ctx, Loc, Type);
176
9
    return ELF::R_X86_64_TLSLD;
177
150
  case MCSymbolRefExpr::VK_PLT:
178
150
    checkIs32(Ctx, Loc, Type);
179
150
    return ELF::R_X86_64_PLT32;
180
134
  case MCSymbolRefExpr::VK_GOTPCREL:
181
134
    checkIs32(Ctx, Loc, Type);
182
134
    // Older versions of ld.bfd/ld.gold/lld
183
134
    // do not support GOTPCRELX/REX_GOTPCRELX,
184
134
    // and we want to keep back-compatibility.
185
134
    if (!Ctx.getAsmInfo()->canRelaxRelocations())
186
26
      return ELF::R_X86_64_GOTPCREL;
187
108
    switch (Kind) {
188
15
    default:
189
15
      return ELF::R_X86_64_GOTPCREL;
190
21
    case X86::reloc_riprel_4byte_relax:
191
21
      return ELF::R_X86_64_GOTPCRELX;
192
72
    case X86::reloc_riprel_4byte_relax_rex:
193
72
    case X86::reloc_riprel_4byte_movq_load:
194
72
      return ELF::R_X86_64_REX_GOTPCRELX;
195
0
    }
196
3.82k
  }
197
3.82k
}
198
199
enum X86_32RelType { RT32_32, RT32_16, RT32_8 };
200
201
457
static X86_32RelType getType32(X86_64RelType T) {
202
457
  switch (T) {
203
0
  case RT64_64:
204
0
    llvm_unreachable("Unimplemented");
205
433
  case RT64_32:
206
433
  case RT64_32S:
207
433
    return RT32_32;
208
12
  case RT64_16:
209
12
    return RT32_16;
210
12
  case RT64_8:
211
12
    return RT32_8;
212
0
  }
213
0
  
llvm_unreachable0
("unexpected relocation type!");
214
0
}
215
216
static unsigned getRelocType32(MCContext &Ctx,
217
                               MCSymbolRefExpr::VariantKind Modifier,
218
                               X86_32RelType Type, bool IsPCRel,
219
457
                               unsigned Kind) {
220
457
  switch (Modifier) {
221
0
  default:
222
0
    llvm_unreachable("Unimplemented");
223
295
  case MCSymbolRefExpr::VK_None:
224
295
  case MCSymbolRefExpr::VK_X86_ABS8:
225
295
    switch (Type) {
226
271
    case RT32_32:
227
271
      return IsPCRel ? 
ELF::R_386_PC3290
:
ELF::R_386_32181
;
228
12
    case RT32_16:
229
12
      return IsPCRel ? 
ELF::R_386_PC166
:
ELF::R_386_166
;
230
12
    case RT32_8:
231
12
      return IsPCRel ? 
ELF::R_386_PC85
:
ELF::R_386_87
;
232
0
    }
233
41
  case MCSymbolRefExpr::VK_GOT:
234
41
    assert(Type == RT32_32);
235
41
    if (IsPCRel)
236
14
      return ELF::R_386_GOTPC;
237
27
    // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
238
27
    // want to maintain compatibility.
239
27
    
if (27
!Ctx.getAsmInfo()->canRelaxRelocations()27
)
240
9
      return ELF::R_386_GOT32;
241
18
242
18
    
return Kind == X86::reloc_signed_4byte_relax ? 18
ELF::R_386_GOT32X5
243
13
                                                 : ELF::R_386_GOT32;
244
12
  case MCSymbolRefExpr::VK_GOTOFF:
245
12
    assert(Type == RT32_32);
246
12
    assert(!IsPCRel);
247
12
    return ELF::R_386_GOTOFF;
248
8
  case MCSymbolRefExpr::VK_TPOFF:
249
8
    assert(Type == RT32_32);
250
8
    assert(!IsPCRel);
251
8
    return ELF::R_386_TLS_LE_32;
252
10
  case MCSymbolRefExpr::VK_DTPOFF:
253
10
    assert(Type == RT32_32);
254
10
    assert(!IsPCRel);
255
10
    return ELF::R_386_TLS_LDO_32;
256
12
  case MCSymbolRefExpr::VK_TLSGD:
257
12
    assert(Type == RT32_32);
258
12
    assert(!IsPCRel);
259
12
    return ELF::R_386_TLS_GD;
260
2
  case MCSymbolRefExpr::VK_GOTTPOFF:
261
2
    assert(Type == RT32_32);
262
2
    assert(!IsPCRel);
263
2
    return ELF::R_386_TLS_IE_32;
264
24
  case MCSymbolRefExpr::VK_PLT:
265
24
    assert(Type == RT32_32);
266
24
    return ELF::R_386_PLT32;
267
23
  case MCSymbolRefExpr::VK_INDNTPOFF:
268
23
    assert(Type == RT32_32);
269
23
    assert(!IsPCRel);
270
23
    return ELF::R_386_TLS_IE;
271
8
  case MCSymbolRefExpr::VK_NTPOFF:
272
8
    assert(Type == RT32_32);
273
8
    assert(!IsPCRel);
274
8
    return ELF::R_386_TLS_LE;
275
12
  case MCSymbolRefExpr::VK_GOTNTPOFF:
276
12
    assert(Type == RT32_32);
277
12
    assert(!IsPCRel);
278
12
    return ELF::R_386_TLS_GOTIE;
279
10
  case MCSymbolRefExpr::VK_TLSLDM:
280
10
    assert(Type == RT32_32);
281
10
    assert(!IsPCRel);
282
10
    return ELF::R_386_TLS_LDM;
283
0
  }
284
0
}
285
286
unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
287
                                          const MCFixup &Fixup,
288
4.28k
                                          bool IsPCRel) const {
289
4.28k
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
290
4.28k
  unsigned Kind = Fixup.getKind();
291
4.28k
  X86_64RelType Type = getType64(Kind, Modifier, IsPCRel);
292
4.28k
  if (getEMachine() == ELF::EM_X86_64)
293
3.82k
    return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind);
294
457
295
4.28k
  assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
296
457
         "Unsupported ELF machine type.");
297
457
  return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
298
457
}
299
300
MCObjectWriter *llvm::createX86ELFObjectWriter(raw_pwrite_stream &OS,
301
                                               bool IsELF64, uint8_t OSABI,
302
1.59k
                                               uint16_t EMachine) {
303
1.59k
  MCELFObjectTargetWriter *MOTW =
304
1.59k
    new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
305
1.59k
  return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
306
1.59k
}