LLVM  7.0.0svn
ELF.cpp
Go to the documentation of this file.
1 //===- ELF.cpp - ELF object file implementation ---------------------------===//
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 "llvm/Object/ELF.h"
11 #include "llvm/BinaryFormat/ELF.h"
12 #include "llvm/Support/LEB128.h"
13 
14 using namespace llvm;
15 using namespace object;
16 
17 #define STRINGIFY_ENUM_CASE(ns, name) \
18  case ns::name: \
19  return #name;
20 
21 #define ELF_RELOC(name, value) STRINGIFY_ENUM_CASE(ELF, name)
22 
24  uint32_t Type) {
25  switch (Machine) {
26  case ELF::EM_X86_64:
27  switch (Type) {
28 #include "llvm/BinaryFormat/ELFRelocs/x86_64.def"
29  default:
30  break;
31  }
32  break;
33  case ELF::EM_386:
34  case ELF::EM_IAMCU:
35  switch (Type) {
36 #include "llvm/BinaryFormat/ELFRelocs/i386.def"
37  default:
38  break;
39  }
40  break;
41  case ELF::EM_MIPS:
42  switch (Type) {
43 #include "llvm/BinaryFormat/ELFRelocs/Mips.def"
44  default:
45  break;
46  }
47  break;
48  case ELF::EM_AARCH64:
49  switch (Type) {
50 #include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
51  default:
52  break;
53  }
54  break;
55  case ELF::EM_ARM:
56  switch (Type) {
57 #include "llvm/BinaryFormat/ELFRelocs/ARM.def"
58  default:
59  break;
60  }
61  break;
64  switch (Type) {
65 #include "llvm/BinaryFormat/ELFRelocs/ARC.def"
66  default:
67  break;
68  }
69  break;
70  case ELF::EM_AVR:
71  switch (Type) {
72 #include "llvm/BinaryFormat/ELFRelocs/AVR.def"
73  default:
74  break;
75  }
76  break;
77  case ELF::EM_HEXAGON:
78  switch (Type) {
79 #include "llvm/BinaryFormat/ELFRelocs/Hexagon.def"
80  default:
81  break;
82  }
83  break;
84  case ELF::EM_LANAI:
85  switch (Type) {
86 #include "llvm/BinaryFormat/ELFRelocs/Lanai.def"
87  default:
88  break;
89  }
90  break;
91  case ELF::EM_PPC:
92  switch (Type) {
93 #include "llvm/BinaryFormat/ELFRelocs/PowerPC.def"
94  default:
95  break;
96  }
97  break;
98  case ELF::EM_PPC64:
99  switch (Type) {
100 #include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def"
101  default:
102  break;
103  }
104  break;
105  case ELF::EM_RISCV:
106  switch (Type) {
107 #include "llvm/BinaryFormat/ELFRelocs/RISCV.def"
108  default:
109  break;
110  }
111  break;
112  case ELF::EM_S390:
113  switch (Type) {
114 #include "llvm/BinaryFormat/ELFRelocs/SystemZ.def"
115  default:
116  break;
117  }
118  break;
119  case ELF::EM_SPARC:
120  case ELF::EM_SPARC32PLUS:
121  case ELF::EM_SPARCV9:
122  switch (Type) {
123 #include "llvm/BinaryFormat/ELFRelocs/Sparc.def"
124  default:
125  break;
126  }
127  break;
128  case ELF::EM_WEBASSEMBLY:
129  switch (Type) {
130 #include "llvm/BinaryFormat/ELFRelocs/WebAssembly.def"
131  default:
132  break;
133  }
134  break;
135  case ELF::EM_AMDGPU:
136  switch (Type) {
137 #include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def"
138  default:
139  break;
140  }
141  break;
142  case ELF::EM_BPF:
143  switch (Type) {
144 #include "llvm/BinaryFormat/ELFRelocs/BPF.def"
145  default:
146  break;
147  }
148  break;
149  default:
150  break;
151  }
152  return "Unknown";
153 }
154 
155 #undef ELF_RELOC
156 
158  switch (Machine) {
159  case ELF::EM_ARM:
160  switch (Type) {
166  }
167  break;
168  case ELF::EM_HEXAGON:
169  switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED); }
170  break;
171  case ELF::EM_X86_64:
172  switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_X86_64_UNWIND); }
173  break;
174  case ELF::EM_MIPS:
175  case ELF::EM_MIPS_RS3_LE:
176  switch (Type) {
181  }
182  break;
183  default:
184  break;
185  }
186 
187  switch (Type) {
214  default:
215  return "Unknown";
216  }
217 }
218 
219 template <class ELFT>
222  // This function reads relocations in Android's packed relocation format,
223  // which is based on SLEB128 and delta encoding.
224  Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
225  if (!ContentsOrErr)
226  return ContentsOrErr.takeError();
227  const uint8_t *Cur = ContentsOrErr->begin();
228  const uint8_t *End = ContentsOrErr->end();
229  if (ContentsOrErr->size() < 4 || Cur[0] != 'A' || Cur[1] != 'P' ||
230  Cur[2] != 'S' || Cur[3] != '2')
231  return createError("invalid packed relocation header");
232  Cur += 4;
233 
234  const char *ErrStr = nullptr;
235  auto ReadSLEB = [&]() -> int64_t {
236  if (ErrStr)
237  return 0;
238  unsigned Len;
239  int64_t Result = decodeSLEB128(Cur, &Len, End, &ErrStr);
240  Cur += Len;
241  return Result;
242  };
243 
244  uint64_t NumRelocs = ReadSLEB();
245  uint64_t Offset = ReadSLEB();
246  uint64_t Addend = 0;
247 
248  if (ErrStr)
249  return createError(ErrStr);
250 
251  std::vector<Elf_Rela> Relocs;
252  Relocs.reserve(NumRelocs);
253  while (NumRelocs) {
254  uint64_t NumRelocsInGroup = ReadSLEB();
255  if (NumRelocsInGroup > NumRelocs)
256  return createError("relocation group unexpectedly large");
257  NumRelocs -= NumRelocsInGroup;
258 
259  uint64_t GroupFlags = ReadSLEB();
260  bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG;
261  bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG;
262  bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG;
263  bool GroupHasAddend = GroupFlags & ELF::RELOCATION_GROUP_HAS_ADDEND_FLAG;
264 
265  uint64_t GroupOffsetDelta;
266  if (GroupedByOffsetDelta)
267  GroupOffsetDelta = ReadSLEB();
268 
269  uint64_t GroupRInfo;
270  if (GroupedByInfo)
271  GroupRInfo = ReadSLEB();
272 
273  if (GroupedByAddend && GroupHasAddend)
274  Addend += ReadSLEB();
275 
276  for (uint64_t I = 0; I != NumRelocsInGroup; ++I) {
277  Elf_Rela R;
278  Offset += GroupedByOffsetDelta ? GroupOffsetDelta : ReadSLEB();
279  R.r_offset = Offset;
280  R.r_info = GroupedByInfo ? GroupRInfo : ReadSLEB();
281 
282  if (GroupHasAddend) {
283  if (!GroupedByAddend)
284  Addend += ReadSLEB();
285  R.r_addend = Addend;
286  } else {
287  R.r_addend = 0;
288  }
289 
290  Relocs.push_back(R);
291 
292  if (ErrStr)
293  return createError(ErrStr);
294  }
295 
296  if (ErrStr)
297  return createError(ErrStr);
298  }
299 
300  return Relocs;
301 }
302 
303 template class llvm::object::ELFFile<ELF32LE>;
304 template class llvm::object::ELFFile<ELF32BE>;
305 template class llvm::object::ELFFile<ELF64LE>;
306 template class llvm::object::ELFFile<ELF64BE>;
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type)
static Error createError(StringRef Err)
Definition: ELF.h:47
Error takeError()
Take ownership of the stored error.
Definition: Error.h:537
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Definition: LEB128.h:162
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
COFF::MachineTypes Machine
Definition: COFFYAML.cpp:363
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static const unsigned End
typename ELFT::Rela Elf_Rela
Definition: ELF.h:62
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
Definition: ELF.cpp:23
#define STRINGIFY_ENUM_CASE(ns, name)
Definition: ELF.cpp:17
Expected< std::vector< Elf_Rela > > android_relas(const Elf_Shdr *Sec) const
Definition: ELF.cpp:221
#define I(x, y, z)
Definition: MD5.cpp:58
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
typename ELFT::Shdr Elf_Shdr
Definition: ELF.h:57