xref: /llvm-project-15.0.7/llvm/lib/Object/ELF.cpp (revision e8ea8296)
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 
23 StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
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;
62   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;
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 
157 StringRef 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);
205     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL);
206     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
207     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB);
208     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 }
217 
218 template <class ELFT>
219 Expected<std::vector<typename ELFT::Rela>>
220 ELFFile<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 
302 template class llvm::object::ELFFile<ELF32LE>;
303 template class llvm::object::ELFFile<ELF32BE>;
304 template class llvm::object::ELFFile<ELF64LE>;
305 template class llvm::object::ELFFile<ELF64BE>;
306