blob: 5906dc5f5307b11c733a9c8d18f8232482feeba5 [file] [log] [blame]
Eugene Zelenko1df42fa2017-04-24 23:21:38 +00001//===- ELF.cpp - ELF object file implementation ---------------------------===//
Michael J. Spencer126973b2013-08-08 22:27:13 +00002//
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"
Zachary Turner264b5d92017-06-07 03:48:56 +000011#include "llvm/BinaryFormat/ELF.h"
Peter Collingbourne689e6c052017-10-25 03:37:12 +000012#include "llvm/Support/LEB128.h"
Michael J. Spencer126973b2013-08-08 22:27:13 +000013
Eugene Zelenko1df42fa2017-04-24 23:21:38 +000014using namespace llvm;
15using namespace object;
Michael J. Spencer126973b2013-08-08 22:27:13 +000016
Rafael Espindola3ba25732017-05-02 14:04:52 +000017#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)
Michael J. Spencer126973b2013-08-08 22:27:13 +000022
Eugene Zelenko1df42fa2017-04-24 23:21:38 +000023StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
24 uint32_t Type) {
Michael J. Spencer126973b2013-08-08 22:27:13 +000025 switch (Machine) {
26 case ELF::EM_X86_64:
27 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000028#include "llvm/BinaryFormat/ELFRelocs/x86_64.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +000029 default:
30 break;
31 }
32 break;
33 case ELF::EM_386:
Michael Kupersteina3b79dd2015-11-04 11:21:50 +000034 case ELF::EM_IAMCU:
Michael J. Spencer126973b2013-08-08 22:27:13 +000035 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000036#include "llvm/BinaryFormat/ELFRelocs/i386.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +000037 default:
38 break;
39 }
40 break;
41 case ELF::EM_MIPS:
42 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000043#include "llvm/BinaryFormat/ELFRelocs/Mips.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +000044 default:
45 break;
46 }
47 break;
48 case ELF::EM_AARCH64:
49 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000050#include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +000051 default:
52 break;
53 }
54 break;
55 case ELF::EM_ARM:
56 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000057#include "llvm/BinaryFormat/ELFRelocs/ARM.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +000058 default:
59 break;
60 }
61 break;
Leslie Zhai49277d12017-09-13 01:49:49 +000062 case ELF::EM_ARC_COMPACT:
63 case ELF::EM_ARC_COMPACT2:
64 switch (Type) {
65#include "llvm/BinaryFormat/ELFRelocs/ARC.def"
66 default:
67 break;
68 }
69 break;
Dylan McKay35047ed2016-09-28 13:23:42 +000070 case ELF::EM_AVR:
71 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000072#include "llvm/BinaryFormat/ELFRelocs/AVR.def"
Dylan McKay35047ed2016-09-28 13:23:42 +000073 default:
74 break;
75 }
76 break;
Michael J. Spencer126973b2013-08-08 22:27:13 +000077 case ELF::EM_HEXAGON:
78 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000079#include "llvm/BinaryFormat/ELFRelocs/Hexagon.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +000080 default:
81 break;
82 }
83 break;
Jacques Pienaarea9f25a2016-03-01 21:21:42 +000084 case ELF::EM_LANAI:
85 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000086#include "llvm/BinaryFormat/ELFRelocs/Lanai.def"
Jacques Pienaarea9f25a2016-03-01 21:21:42 +000087 default:
88 break;
89 }
90 break;
Michael J. Spencer126973b2013-08-08 22:27:13 +000091 case ELF::EM_PPC:
92 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +000093#include "llvm/BinaryFormat/ELFRelocs/PowerPC.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +000094 default:
95 break;
96 }
97 break;
98 case ELF::EM_PPC64:
99 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +0000100#include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +0000101 default:
102 break;
103 }
104 break;
Alex Bradbury1524f622016-11-01 16:59:37 +0000105 case ELF::EM_RISCV:
106 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +0000107#include "llvm/BinaryFormat/ELFRelocs/RISCV.def"
Alex Bradbury1524f622016-11-01 16:59:37 +0000108 default:
109 break;
110 }
111 break;
Michael J. Spencer126973b2013-08-08 22:27:13 +0000112 case ELF::EM_S390:
113 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +0000114#include "llvm/BinaryFormat/ELFRelocs/SystemZ.def"
Michael J. Spencer126973b2013-08-08 22:27:13 +0000115 default:
116 break;
117 }
118 break;
Venkatraman Govindarajucdee0ed2014-01-26 03:21:28 +0000119 case ELF::EM_SPARC:
120 case ELF::EM_SPARC32PLUS:
121 case ELF::EM_SPARCV9:
122 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +0000123#include "llvm/BinaryFormat/ELFRelocs/Sparc.def"
Venkatraman Govindarajucdee0ed2014-01-26 03:21:28 +0000124 default:
125 break;
126 }
127 break;
Dan Gohman46350172016-01-12 20:56:01 +0000128 case ELF::EM_WEBASSEMBLY:
129 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +0000130#include "llvm/BinaryFormat/ELFRelocs/WebAssembly.def"
Dan Gohman46350172016-01-12 20:56:01 +0000131 default:
132 break;
133 }
134 break;
Tom Stellardf8db61c2016-06-17 22:38:08 +0000135 case ELF::EM_AMDGPU:
136 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +0000137#include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def"
Tom Stellardf8db61c2016-06-17 22:38:08 +0000138 default:
139 break;
140 }
Adrian Prantl0e6694d2017-12-19 22:05:25 +0000141 break;
Alexei Starovoitovcfb51f52016-07-15 22:27:55 +0000142 case ELF::EM_BPF:
143 switch (Type) {
Zachary Turner264b5d92017-06-07 03:48:56 +0000144#include "llvm/BinaryFormat/ELFRelocs/BPF.def"
Alexei Starovoitovcfb51f52016-07-15 22:27:55 +0000145 default:
146 break;
147 }
Tom Stellardf8db61c2016-06-17 22:38:08 +0000148 break;
Michael J. Spencer126973b2013-08-08 22:27:13 +0000149 default:
150 break;
151 }
152 return "Unknown";
153}
154
Tim Northover242785c2014-11-21 20:16:07 +0000155#undef ELF_RELOC
Rafael Espindola3ba25732017-05-02 14:04:52 +0000156
157StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
158 switch (Machine) {
159 case ELF::EM_ARM:
160 switch (Type) {
161 STRINGIFY_ENUM_CASE(ELF, SHT_ARM_EXIDX);
162 STRINGIFY_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP);
163 STRINGIFY_ENUM_CASE(ELF, SHT_ARM_ATTRIBUTES);
164 STRINGIFY_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY);
165 STRINGIFY_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION);
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) {
177 STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_REGINFO);
178 STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_OPTIONS);
179 STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS);
180 STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_DWARF);
181 }
182 break;
183 default:
184 break;
185 }
186
187 switch (Type) {
188 STRINGIFY_ENUM_CASE(ELF, SHT_NULL);
189 STRINGIFY_ENUM_CASE(ELF, SHT_PROGBITS);
190 STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB);
191 STRINGIFY_ENUM_CASE(ELF, SHT_STRTAB);
192 STRINGIFY_ENUM_CASE(ELF, SHT_RELA);
193 STRINGIFY_ENUM_CASE(ELF, SHT_HASH);
194 STRINGIFY_ENUM_CASE(ELF, SHT_DYNAMIC);
195 STRINGIFY_ENUM_CASE(ELF, SHT_NOTE);
196 STRINGIFY_ENUM_CASE(ELF, SHT_NOBITS);
197 STRINGIFY_ENUM_CASE(ELF, SHT_REL);
198 STRINGIFY_ENUM_CASE(ELF, SHT_SHLIB);
199 STRINGIFY_ENUM_CASE(ELF, SHT_DYNSYM);
200 STRINGIFY_ENUM_CASE(ELF, SHT_INIT_ARRAY);
201 STRINGIFY_ENUM_CASE(ELF, SHT_FINI_ARRAY);
202 STRINGIFY_ENUM_CASE(ELF, SHT_PREINIT_ARRAY);
203 STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
204 STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
Peter Collingbourne5c54f152017-10-27 17:49:40 +0000205 STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL);
206 STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
Peter Collingbournef0e26e72017-06-14 18:52:12 +0000207 STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB);
Rafael Espindola3ba25732017-05-02 14:04:52 +0000208 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
209 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
210 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef);
211 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verneed);
212 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_versym);
213 default:
214 return "Unknown";
215 }
216}
Peter Collingbourne689e6c052017-10-25 03:37:12 +0000217
218template <class ELFT>
219Expected<std::vector<typename ELFT::Rela>>
220ELFFile<ELFT>::android_relas(const Elf_Shdr *Sec) const {
221 // This function reads relocations in Android's packed relocation format,
222 // which is based on SLEB128 and delta encoding.
223 Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
224 if (!ContentsOrErr)
225 return ContentsOrErr.takeError();
226 const uint8_t *Cur = ContentsOrErr->begin();
227 const uint8_t *End = ContentsOrErr->end();
228 if (ContentsOrErr->size() < 4 || Cur[0] != 'A' || Cur[1] != 'P' ||
229 Cur[2] != 'S' || Cur[3] != '2')
230 return createError("invalid packed relocation header");
231 Cur += 4;
232
233 const char *ErrStr = nullptr;
234 auto ReadSLEB = [&]() -> int64_t {
235 if (ErrStr)
236 return 0;
237 unsigned Len;
238 int64_t Result = decodeSLEB128(Cur, &Len, End, &ErrStr);
239 Cur += Len;
240 return Result;
241 };
242
243 uint64_t NumRelocs = ReadSLEB();
244 uint64_t Offset = ReadSLEB();
245 uint64_t Addend = 0;
246
247 if (ErrStr)
248 return createError(ErrStr);
249
250 std::vector<Elf_Rela> Relocs;
251 Relocs.reserve(NumRelocs);
252 while (NumRelocs) {
253 uint64_t NumRelocsInGroup = ReadSLEB();
254 if (NumRelocsInGroup > NumRelocs)
255 return createError("relocation group unexpectedly large");
256 NumRelocs -= NumRelocsInGroup;
257
258 uint64_t GroupFlags = ReadSLEB();
259 bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG;
260 bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG;
261 bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG;
262 bool GroupHasAddend = GroupFlags & ELF::RELOCATION_GROUP_HAS_ADDEND_FLAG;
263
264 uint64_t GroupOffsetDelta;
265 if (GroupedByOffsetDelta)
266 GroupOffsetDelta = ReadSLEB();
267
268 uint64_t GroupRInfo;
269 if (GroupedByInfo)
270 GroupRInfo = ReadSLEB();
271
272 if (GroupedByAddend && GroupHasAddend)
273 Addend += ReadSLEB();
274
275 for (uint64_t I = 0; I != NumRelocsInGroup; ++I) {
276 Elf_Rela R;
277 Offset += GroupedByOffsetDelta ? GroupOffsetDelta : ReadSLEB();
278 R.r_offset = Offset;
279 R.r_info = GroupedByInfo ? GroupRInfo : ReadSLEB();
280
281 if (GroupHasAddend) {
282 if (!GroupedByAddend)
283 Addend += ReadSLEB();
284 R.r_addend = Addend;
285 } else {
286 R.r_addend = 0;
287 }
288
289 Relocs.push_back(R);
290
291 if (ErrStr)
292 return createError(ErrStr);
293 }
294
295 if (ErrStr)
296 return createError(ErrStr);
297 }
298
299 return Relocs;
300}
301
302template class llvm::object::ELFFile<ELF32LE>;
303template class llvm::object::ELFFile<ELF32BE>;
304template class llvm::object::ELFFile<ELF64LE>;
305template class llvm::object::ELFFile<ELF64BE>;