Coverage Report

Created: 2018-09-19 20:53

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Object/RelocVisitor.h
Line
Count
Source (jump to first uncovered line)
1
//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
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
// This file provides a wrapper around all the different types of relocations
11
// in different file formats, such that a client can handle them in a unified
12
// manner by only implementing a minimal number of functions.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#ifndef LLVM_OBJECT_RELOCVISITOR_H
17
#define LLVM_OBJECT_RELOCVISITOR_H
18
19
#include "llvm/ADT/Triple.h"
20
#include "llvm/BinaryFormat/ELF.h"
21
#include "llvm/BinaryFormat/MachO.h"
22
#include "llvm/Object/COFF.h"
23
#include "llvm/Object/ELFObjectFile.h"
24
#include "llvm/Object/MachO.h"
25
#include "llvm/Object/ObjectFile.h"
26
#include "llvm/Object/Wasm.h"
27
#include "llvm/Support/Casting.h"
28
#include "llvm/Support/ErrorHandling.h"
29
#include <cstdint>
30
#include <system_error>
31
32
namespace llvm {
33
namespace object {
34
35
/// Base class for object file relocation visitors.
36
class RelocVisitor {
37
public:
38
  explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
39
40
  // TODO: Should handle multiple applied relocations via either passing in the
41
  // previously computed value or just count paired relocations as a single
42
  // visit.
43
  uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
44
    if (isa<ELFObjectFileBase>(ObjToVisit))
45
      return visitELF(Rel, R, Value);
46
    if (isa<COFFObjectFile>(ObjToVisit))
47
      return visitCOFF(Rel, R, Value);
48
    if (isa<MachOObjectFile>(ObjToVisit))
49
      return visitMachO(Rel, R, Value);
50
    if (isa<WasmObjectFile>(ObjToVisit))
51
      return visitWasm(Rel, R, Value);
52
53
    HasError = true;
54
    return 0;
55
  }
56
57
  bool error() { return HasError; }
58
59
private:
60
  const ObjectFile &ObjToVisit;
61
  bool HasError = false;
62
63
  uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
64
    if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
65
      switch (ObjToVisit.getArch()) {
66
      case Triple::x86_64:
67
        return visitX86_64(Rel, R, Value);
68
      case Triple::aarch64:
69
      case Triple::aarch64_be:
70
        return visitAarch64(Rel, R, Value);
71
      case Triple::bpfel:
72
      case Triple::bpfeb:
73
        return visitBpf(Rel, R, Value);
74
      case Triple::mips64el:
75
      case Triple::mips64:
76
        return visitMips64(Rel, R, Value);
77
      case Triple::ppc64le:
78
      case Triple::ppc64:
79
        return visitPPC64(Rel, R, Value);
80
      case Triple::systemz:
81
        return visitSystemz(Rel, R, Value);
82
      case Triple::sparcv9:
83
        return visitSparc64(Rel, R, Value);
84
      case Triple::amdgcn:
85
        return visitAmdgpu(Rel, R, Value);
86
      default:
87
        HasError = true;
88
        return 0;
89
      }
90
    }
91
92
    // 32-bit object file
93
    assert(ObjToVisit.getBytesInAddress() == 4 &&
94
           "Invalid word size in object file");
95
96
    switch (ObjToVisit.getArch()) {
97
    case Triple::x86:
98
      return visitX86(Rel, R, Value);
99
    case Triple::ppc:
100
      return visitPPC32(Rel, R, Value);
101
    case Triple::arm:
102
    case Triple::armeb:
103
      return visitARM(Rel, R, Value);
104
    case Triple::lanai:
105
      return visitLanai(Rel, R, Value);
106
    case Triple::mipsel:
107
    case Triple::mips:
108
      return visitMips32(Rel, R, Value);
109
    case Triple::sparc:
110
      return visitSparc32(Rel, R, Value);
111
    case Triple::hexagon:
112
      return visitHexagon(Rel, R, Value);
113
    default:
114
      HasError = true;
115
      return 0;
116
    }
117
  }
118
119
  int64_t getELFAddend(RelocationRef R) {
120
    Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
121
0
    handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
122
0
      report_fatal_error(EI.message());
123
0
    });
124
    return *AddendOrErr;
125
  }
126
127
  uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
128
    switch (Rel) {
129
    case ELF::R_X86_64_NONE:
130
      return 0;
131
    case ELF::R_X86_64_64:
132
      return Value + getELFAddend(R);
133
    case ELF::R_X86_64_PC32:
134
      return Value + getELFAddend(R) - R.getOffset();
135
    case ELF::R_X86_64_32:
136
    case ELF::R_X86_64_32S:
137
      return (Value + getELFAddend(R)) & 0xFFFFFFFF;
138
    }
139
    HasError = true;
140
    return 0;
141
  }
142
143
  uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
144
    switch (Rel) {
145
    case ELF::R_AARCH64_ABS32: {
146
      int64_t Res = Value + getELFAddend(R);
147
      if (Res < INT32_MIN || Res > UINT32_MAX)
148
        HasError = true;
149
      return static_cast<uint32_t>(Res);
150
    }
151
    case ELF::R_AARCH64_ABS64:
152
      return Value + getELFAddend(R);
153
    }
154
    HasError = true;
155
    return 0;
156
  }
157
158
  uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
159
    switch (Rel) {
160
    case ELF::R_BPF_64_32:
161
      return Value & 0xFFFFFFFF;
162
    case ELF::R_BPF_64_64:
163
      return Value;
164
    }
165
    HasError = true;
166
    return 0;
167
  }
168
169
  uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
170
    switch (Rel) {
171
    case ELF::R_MIPS_32:
172
      return (Value + getELFAddend(R)) & 0xFFFFFFFF;
173
    case ELF::R_MIPS_64:
174
      return Value + getELFAddend(R);
175
    case ELF::R_MIPS_TLS_DTPREL64:
176
      return Value + getELFAddend(R) - 0x8000;
177
    }
178
    HasError = true;
179
    return 0;
180
  }
181
182
  uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
183
    switch (Rel) {
184
    case ELF::R_PPC64_ADDR32:
185
      return (Value + getELFAddend(R)) & 0xFFFFFFFF;
186
    case ELF::R_PPC64_ADDR64:
187
      return Value + getELFAddend(R);
188
    }
189
    HasError = true;
190
    return 0;
191
  }
192
193
  uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
194
    switch (Rel) {
195
    case ELF::R_390_32: {
196
      int64_t Res = Value + getELFAddend(R);
197
      if (Res < INT32_MIN || Res > UINT32_MAX)
198
        HasError = true;
199
      return static_cast<uint32_t>(Res);
200
    }
201
    case ELF::R_390_64:
202
      return Value + getELFAddend(R);
203
    }
204
    HasError = true;
205
    return 0;
206
  }
207
208
  uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
209
    switch (Rel) {
210
    case ELF::R_SPARC_32:
211
    case ELF::R_SPARC_64:
212
    case ELF::R_SPARC_UA32:
213
    case ELF::R_SPARC_UA64:
214
      return Value + getELFAddend(R);
215
    }
216
    HasError = true;
217
    return 0;
218
  }
219
220
  uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
221
    switch (Rel) {
222
    case ELF::R_AMDGPU_ABS32:
223
    case ELF::R_AMDGPU_ABS64:
224
      return Value + getELFAddend(R);
225
    }
226
    HasError = true;
227
    return 0;
228
  }
229
230
  uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
231
    switch (Rel) {
232
    case ELF::R_386_NONE:
233
      return 0;
234
    case ELF::R_386_32:
235
      return Value;
236
    case ELF::R_386_PC32:
237
      return Value - R.getOffset();
238
    }
239
    HasError = true;
240
    return 0;
241
  }
242
243
  uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
244
    if (Rel == ELF::R_PPC_ADDR32)
245
      return (Value + getELFAddend(R)) & 0xFFFFFFFF;
246
    HasError = true;
247
    return 0;
248
  }
249
250
  uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
251
    if (Rel == ELF::R_ARM_ABS32) {
252
      if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
253
        HasError = true;
254
      return static_cast<uint32_t>(Value);
255
    }
256
    HasError = true;
257
    return 0;
258
  }
259
260
  uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
261
    if (Rel == ELF::R_LANAI_32)
262
      return (Value + getELFAddend(R)) & 0xFFFFFFFF;
263
    HasError = true;
264
    return 0;
265
  }
266
267
  uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
268
    // FIXME: Take in account implicit addends to get correct results.
269
    if (Rel == ELF::R_MIPS_32)
270
      return Value & 0xFFFFFFFF;
271
    if (Rel == ELF::R_MIPS_TLS_DTPREL32)
272
      return Value & 0xFFFFFFFF;
273
    HasError = true;
274
    return 0;
275
  }
276
277
  uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
278
    if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
279
      return Value + getELFAddend(R);
280
    HasError = true;
281
    return 0;
282
  }
283
284
  uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
285
    if (Rel == ELF::R_HEX_32)
286
      return Value + getELFAddend(R);
287
    HasError = true;
288
    return 0;
289
  }
290
291
  uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
292
    switch (ObjToVisit.getArch()) {
293
    case Triple::x86:
294
      switch (Rel) {
295
      case COFF::IMAGE_REL_I386_SECREL:
296
      case COFF::IMAGE_REL_I386_DIR32:
297
        return static_cast<uint32_t>(Value);
298
      }
299
      break;
300
    case Triple::x86_64:
301
      switch (Rel) {
302
      case COFF::IMAGE_REL_AMD64_SECREL:
303
        return static_cast<uint32_t>(Value);
304
      case COFF::IMAGE_REL_AMD64_ADDR64:
305
        return Value;
306
      }
307
      break;
308
    default:
309
      break;
310
    }
311
    HasError = true;
312
    return 0;
313
  }
314
315
  uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
316
    if (ObjToVisit.getArch() == Triple::x86_64 &&
317
        Rel == MachO::X86_64_RELOC_UNSIGNED)
318
      return Value;
319
    HasError = true;
320
    return 0;
321
  }
322
323
  uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
324
    if (ObjToVisit.getArch() == Triple::wasm32) {
325
      switch (Rel) {
326
      case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
327
      case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
328
      case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
329
      case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
330
      case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
331
      case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
332
      case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
333
      case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
334
      case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
335
      case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
336
        // For wasm section, its offset at 0 -- ignoring Value
337
        return 0;
338
      }
339
    }
340
    HasError = true;
341
    return 0;
342
  }
343
};
344
345
} // end namespace object
346
} // end namespace llvm
347
348
#endif // LLVM_OBJECT_RELOCVISITOR_H