LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RelocVisitor.h
Go to the documentation of this file.
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/StringRef.h"
20 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/ELF.h"
25 
26 namespace llvm {
27 namespace object {
28 
29 struct RelocToApply {
30  // The computed value after applying the relevant relocations.
31  int64_t Value;
32 
33  // The width of the value; how many bytes to touch when applying the
34  // relocation.
35  char Width;
37  RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
38  RelocToApply() : Value(0), Width(0) {}
39 };
40 
41 /// @brief Base class for object file relocation visitors.
42 class RelocVisitor {
43 public:
44  explicit RelocVisitor(StringRef FileFormat)
45  : FileFormat(FileFormat), HasError(false) {}
46 
47  // TODO: Should handle multiple applied relocations via either passing in the
48  // previously computed value or just count paired relocations as a single
49  // visit.
50  RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0,
51  uint64_t Value = 0) {
52  if (FileFormat == "ELF64-x86-64") {
53  switch (RelocType) {
55  return visitELF_X86_64_NONE(R);
57  return visitELF_X86_64_64(R, Value);
59  return visitELF_X86_64_PC32(R, Value, SecAddr);
61  return visitELF_X86_64_32(R, Value);
63  return visitELF_X86_64_32S(R, Value);
64  default:
65  HasError = true;
66  return RelocToApply();
67  }
68  } else if (FileFormat == "ELF32-i386") {
69  switch (RelocType) {
71  return visitELF_386_NONE(R);
73  return visitELF_386_32(R, Value);
75  return visitELF_386_PC32(R, Value, SecAddr);
76  default:
77  HasError = true;
78  return RelocToApply();
79  }
80  } else if (FileFormat == "ELF64-ppc64") {
81  switch (RelocType) {
83  return visitELF_PPC64_ADDR32(R, Value);
85  return visitELF_PPC64_ADDR64(R, Value);
86  default:
87  HasError = true;
88  return RelocToApply();
89  }
90  } else if (FileFormat == "ELF32-ppc") {
91  switch (RelocType) {
93  return visitELF_PPC_ADDR32(R, Value);
94  default:
95  HasError = true;
96  return RelocToApply();
97  }
98  } else if (FileFormat == "ELF32-mips") {
99  switch (RelocType) {
101  return visitELF_MIPS_32(R, Value);
102  default:
103  HasError = true;
104  return RelocToApply();
105  }
106  } else if (FileFormat == "ELF64-aarch64") {
107  switch (RelocType) {
109  return visitELF_AARCH64_ABS32(R, Value);
111  return visitELF_AARCH64_ABS64(R, Value);
112  default:
113  HasError = true;
114  return RelocToApply();
115  }
116  } else if (FileFormat == "ELF64-s390") {
117  switch (RelocType) {
118  case llvm::ELF::R_390_32:
119  return visitELF_390_32(R, Value);
120  case llvm::ELF::R_390_64:
121  return visitELF_390_64(R, Value);
122  default:
123  HasError = true;
124  return RelocToApply();
125  }
126  }
127  HasError = true;
128  return RelocToApply();
129  }
130 
131  bool error() { return HasError; }
132 
133 private:
134  StringRef FileFormat;
135  bool HasError;
136 
137  int64_t getAddend32LE(RelocationRef R) {
138  const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
139  DataRefImpl DRI = R.getRawDataRefImpl();
140  int64_t Addend;
141  Obj->getRelocationAddend(DRI, Addend);
142  return Addend;
143  }
144 
145  int64_t getAddend64LE(RelocationRef R) {
146  const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile());
147  DataRefImpl DRI = R.getRawDataRefImpl();
148  int64_t Addend;
149  Obj->getRelocationAddend(DRI, Addend);
150  return Addend;
151  }
152 
153  int64_t getAddend32BE(RelocationRef R) {
154  const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile());
155  DataRefImpl DRI = R.getRawDataRefImpl();
156  int64_t Addend;
157  Obj->getRelocationAddend(DRI, Addend);
158  return Addend;
159  }
160 
161  int64_t getAddend64BE(RelocationRef R) {
162  const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile());
163  DataRefImpl DRI = R.getRawDataRefImpl();
164  int64_t Addend;
165  Obj->getRelocationAddend(DRI, Addend);
166  return Addend;
167  }
168  /// Operations
169 
170  /// 386-ELF
171  RelocToApply visitELF_386_NONE(RelocationRef R) {
172  return RelocToApply(0, 0);
173  }
174 
175  // Ideally the Addend here will be the addend in the data for
176  // the relocation. It's not actually the case for Rel relocations.
177  RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
178  int64_t Addend = getAddend32LE(R);
179  return RelocToApply(Value + Addend, 4);
180  }
181 
182  RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value,
183  uint64_t SecAddr) {
184  int64_t Addend = getAddend32LE(R);
185  uint64_t Address;
186  R.getOffset(Address);
187  return RelocToApply(Value + Addend - Address, 4);
188  }
189 
190  /// X86-64 ELF
191  RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
192  return RelocToApply(0, 0);
193  }
194  RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
195  int64_t Addend = getAddend64LE(R);
196  return RelocToApply(Value + Addend, 8);
197  }
198  RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value,
199  uint64_t SecAddr) {
200  int64_t Addend = getAddend64LE(R);
201  uint64_t Address;
202  R.getOffset(Address);
203  return RelocToApply(Value + Addend - Address, 4);
204  }
205  RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
206  int64_t Addend = getAddend64LE(R);
207  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
208  return RelocToApply(Res, 4);
209  }
210  RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
211  int64_t Addend = getAddend64LE(R);
212  int32_t Res = (Value + Addend) & 0xFFFFFFFF;
213  return RelocToApply(Res, 4);
214  }
215 
216  /// PPC64 ELF
217  RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
218  int64_t Addend = getAddend64BE(R);
219  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
220  return RelocToApply(Res, 4);
221  }
222  RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
223  int64_t Addend = getAddend64BE(R);
224  return RelocToApply(Value + Addend, 8);
225  }
226 
227  /// PPC32 ELF
228  RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
229  int64_t Addend = getAddend32BE(R);
230  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
231  return RelocToApply(Res, 4);
232  }
233 
234  /// MIPS ELF
235  RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
236  int64_t Addend;
237  getELFRelocationAddend(R, Addend);
238  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
239  return RelocToApply(Res, 4);
240  }
241 
242  // AArch64 ELF
243  RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
244  int64_t Addend = getAddend64LE(R);
245  int64_t Res = Value + Addend;
246 
247  // Overflow check allows for both signed and unsigned interpretation.
248  if (Res < INT32_MIN || Res > UINT32_MAX)
249  HasError = true;
250 
251  return RelocToApply(static_cast<uint32_t>(Res), 4);
252  }
253 
254  RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
255  int64_t Addend = getAddend64LE(R);
256  return RelocToApply(Value + Addend, 8);
257  }
258 
259  // SystemZ ELF
260  RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
261  int64_t Addend = getAddend64BE(R);
262  int64_t Res = Value + Addend;
263 
264  // Overflow check allows for both signed and unsigned interpretation.
265  if (Res < INT32_MIN || Res > UINT32_MAX)
266  HasError = true;
267 
268  return RelocToApply(static_cast<uint32_t>(Res), 4);
269  }
270 
271  RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
272  int64_t Addend = getAddend64BE(R);
273  return RelocToApply(Value + Addend, 8);
274  }
275 };
276 
277 }
278 }
279 #endif
RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr=0, uint64_t Value=0)
Definition: RelocVisitor.h:50
#define false
Definition: ConvertUTF.c:64
RelocVisitor(StringRef FileFormat)
Definition: RelocVisitor.h:44
static error_code getELFRelocationAddend(const RelocationRef R, int64_t &Addend)
ELFObjectFile< ELFType< support::big, 2, true > > ELF64BEObjectFile
RelocToApply(const RelocToApply &In)
Definition: RelocVisitor.h:36
ELFObjectFile< ELFType< support::big, 2, false > > ELF32BEObjectFile
LLVM Value Representation.
Definition: Value.h:66
RelocToApply(int64_t Value, char Width)
Definition: RelocVisitor.h:37
const ObjectFile * getObjectFile() const
Definition: ObjectFile.h:585
error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const
Base class for object file relocation visitors.
Definition: RelocVisitor.h:42
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:581