xref: /llvm-project-15.0.7/llvm/lib/Object/ELF.cpp (revision 9fedbb9d)
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   case ELF::EM_BPF:
142     switch (Type) {
143 #include "llvm/BinaryFormat/ELFRelocs/BPF.def"
144     default:
145       break;
146     }
147     break;
148   default:
149     break;
150   }
151   return "Unknown";
152 }
153 
154 #undef ELF_RELOC
155 
156 StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
157   switch (Machine) {
158   case ELF::EM_ARM:
159     switch (Type) {
160       STRINGIFY_ENUM_CASE(ELF, SHT_ARM_EXIDX);
161       STRINGIFY_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP);
162       STRINGIFY_ENUM_CASE(ELF, SHT_ARM_ATTRIBUTES);
163       STRINGIFY_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY);
164       STRINGIFY_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION);
165     }
166     break;
167   case ELF::EM_HEXAGON:
168     switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED); }
169     break;
170   case ELF::EM_X86_64:
171     switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_X86_64_UNWIND); }
172     break;
173   case ELF::EM_MIPS:
174   case ELF::EM_MIPS_RS3_LE:
175     switch (Type) {
176       STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_REGINFO);
177       STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_OPTIONS);
178       STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS);
179       STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_DWARF);
180     }
181     break;
182   default:
183     break;
184   }
185 
186   switch (Type) {
187     STRINGIFY_ENUM_CASE(ELF, SHT_NULL);
188     STRINGIFY_ENUM_CASE(ELF, SHT_PROGBITS);
189     STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB);
190     STRINGIFY_ENUM_CASE(ELF, SHT_STRTAB);
191     STRINGIFY_ENUM_CASE(ELF, SHT_RELA);
192     STRINGIFY_ENUM_CASE(ELF, SHT_HASH);
193     STRINGIFY_ENUM_CASE(ELF, SHT_DYNAMIC);
194     STRINGIFY_ENUM_CASE(ELF, SHT_NOTE);
195     STRINGIFY_ENUM_CASE(ELF, SHT_NOBITS);
196     STRINGIFY_ENUM_CASE(ELF, SHT_REL);
197     STRINGIFY_ENUM_CASE(ELF, SHT_SHLIB);
198     STRINGIFY_ENUM_CASE(ELF, SHT_DYNSYM);
199     STRINGIFY_ENUM_CASE(ELF, SHT_INIT_ARRAY);
200     STRINGIFY_ENUM_CASE(ELF, SHT_FINI_ARRAY);
201     STRINGIFY_ENUM_CASE(ELF, SHT_PREINIT_ARRAY);
202     STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
203     STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
204     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB);
205     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
206     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
207     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef);
208     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verneed);
209     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_versym);
210   default:
211     return "Unknown";
212   }
213 }
214 
215 template <class ELFT>
216 Expected<std::vector<typename ELFT::Rela>>
217 ELFFile<ELFT>::android_relas(const Elf_Shdr *Sec) const {
218   // This function reads relocations in Android's packed relocation format,
219   // which is based on SLEB128 and delta encoding.
220   Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
221   if (!ContentsOrErr)
222     return ContentsOrErr.takeError();
223   const uint8_t *Cur = ContentsOrErr->begin();
224   const uint8_t *End = ContentsOrErr->end();
225   if (ContentsOrErr->size() < 4 || Cur[0] != 'A' || Cur[1] != 'P' ||
226       Cur[2] != 'S' || Cur[3] != '2')
227     return createError("invalid packed relocation header");
228   Cur += 4;
229 
230   const char *ErrStr = nullptr;
231   auto ReadSLEB = [&]() -> int64_t {
232     if (ErrStr)
233       return 0;
234     unsigned Len;
235     int64_t Result = decodeSLEB128(Cur, &Len, End, &ErrStr);
236     Cur += Len;
237     return Result;
238   };
239 
240   uint64_t NumRelocs = ReadSLEB();
241   uint64_t Offset = ReadSLEB();
242   uint64_t Addend = 0;
243 
244   if (ErrStr)
245     return createError(ErrStr);
246 
247   std::vector<Elf_Rela> Relocs;
248   Relocs.reserve(NumRelocs);
249   while (NumRelocs) {
250     uint64_t NumRelocsInGroup = ReadSLEB();
251     if (NumRelocsInGroup > NumRelocs)
252       return createError("relocation group unexpectedly large");
253     NumRelocs -= NumRelocsInGroup;
254 
255     uint64_t GroupFlags = ReadSLEB();
256     bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG;
257     bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG;
258     bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG;
259     bool GroupHasAddend = GroupFlags & ELF::RELOCATION_GROUP_HAS_ADDEND_FLAG;
260 
261     uint64_t GroupOffsetDelta;
262     if (GroupedByOffsetDelta)
263       GroupOffsetDelta = ReadSLEB();
264 
265     uint64_t GroupRInfo;
266     if (GroupedByInfo)
267       GroupRInfo = ReadSLEB();
268 
269     if (GroupedByAddend && GroupHasAddend)
270       Addend += ReadSLEB();
271 
272     for (uint64_t I = 0; I != NumRelocsInGroup; ++I) {
273       Elf_Rela R;
274       Offset += GroupedByOffsetDelta ? GroupOffsetDelta : ReadSLEB();
275       R.r_offset = Offset;
276       R.r_info = GroupedByInfo ? GroupRInfo : ReadSLEB();
277 
278       if (GroupHasAddend) {
279         if (!GroupedByAddend)
280           Addend += ReadSLEB();
281         R.r_addend = Addend;
282       } else {
283         R.r_addend = 0;
284       }
285 
286       Relocs.push_back(R);
287 
288       if (ErrStr)
289         return createError(ErrStr);
290     }
291 
292     if (ErrStr)
293       return createError(ErrStr);
294   }
295 
296   return Relocs;
297 }
298 
299 template class llvm::object::ELFFile<ELF32LE>;
300 template class llvm::object::ELFFile<ELF32BE>;
301 template class llvm::object::ELFFile<ELF64LE>;
302 template class llvm::object::ELFFile<ELF64BE>;
303