File: | tools/llvm-readobj/ELFDumper.cpp |
Location: | line 1133, column 33 |
Description: | Called C++ object pointer is null |
1 | //===-- ELFDumper.cpp - ELF-specific dumper ---------------------*- 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 | /// \file | |||
11 | /// \brief This file implements the ELF-specific dumper for llvm-readobj. | |||
12 | /// | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "llvm-readobj.h" | |||
16 | #include "ARMAttributeParser.h" | |||
17 | #include "ARMEHABIPrinter.h" | |||
18 | #include "Error.h" | |||
19 | #include "ObjDumper.h" | |||
20 | #include "StackMapPrinter.h" | |||
21 | #include "StreamWriter.h" | |||
22 | #include "llvm/ADT/Optional.h" | |||
23 | #include "llvm/ADT/SmallString.h" | |||
24 | #include "llvm/ADT/StringExtras.h" | |||
25 | #include "llvm/Object/ELFObjectFile.h" | |||
26 | #include "llvm/Support/ARMBuildAttributes.h" | |||
27 | #include "llvm/Support/Compiler.h" | |||
28 | #include "llvm/Support/Format.h" | |||
29 | #include "llvm/Support/MathExtras.h" | |||
30 | #include "llvm/Support/MipsABIFlags.h" | |||
31 | #include "llvm/Support/raw_ostream.h" | |||
32 | ||||
33 | using namespace llvm; | |||
34 | using namespace llvm::object; | |||
35 | using namespace ELF; | |||
36 | ||||
37 | #define LLVM_READOBJ_ENUM_CASE(ns, enum)case ns::enum: return "enum"; \ | |||
38 | case ns::enum: return #enum; | |||
39 | ||||
40 | namespace { | |||
41 | ||||
42 | template<typename ELFT> | |||
43 | class ELFDumper : public ObjDumper { | |||
44 | public: | |||
45 | ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer); | |||
46 | ||||
47 | void printFileHeaders() override; | |||
48 | void printSections() override; | |||
49 | void printRelocations() override; | |||
50 | void printDynamicRelocations() override; | |||
51 | void printSymbols() override; | |||
52 | void printDynamicSymbols() override; | |||
53 | void printUnwindInfo() override; | |||
54 | ||||
55 | void printDynamicTable() override; | |||
56 | void printNeededLibraries() override; | |||
57 | void printProgramHeaders() override; | |||
58 | void printHashTable() override; | |||
59 | void printLoadName() override; | |||
60 | ||||
61 | void printAttributes() override; | |||
62 | void printMipsPLTGOT() override; | |||
63 | void printMipsABIFlags() override; | |||
64 | void printMipsReginfo() override; | |||
65 | ||||
66 | void printStackMap() const override; | |||
67 | ||||
68 | private: | |||
69 | typedef ELFFile<ELFT> ELFO; | |||
70 | typedef typename ELFO::Elf_Shdr Elf_Shdr; | |||
71 | typedef typename ELFO::Elf_Sym Elf_Sym; | |||
72 | typedef typename ELFO::Elf_Dyn Elf_Dyn; | |||
73 | typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; | |||
74 | typedef typename ELFO::Elf_Rel Elf_Rel; | |||
75 | typedef typename ELFO::Elf_Rela Elf_Rela; | |||
76 | typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range; | |||
77 | typedef typename ELFO::Elf_Phdr Elf_Phdr; | |||
78 | typedef typename ELFO::Elf_Hash Elf_Hash; | |||
79 | typedef typename ELFO::Elf_Ehdr Elf_Ehdr; | |||
80 | typedef typename ELFO::Elf_Word Elf_Word; | |||
81 | typedef typename ELFO::uintX_t uintX_t; | |||
82 | typedef typename ELFO::Elf_Versym Elf_Versym; | |||
83 | typedef typename ELFO::Elf_Verneed Elf_Verneed; | |||
84 | typedef typename ELFO::Elf_Vernaux Elf_Vernaux; | |||
85 | typedef typename ELFO::Elf_Verdef Elf_Verdef; | |||
86 | ||||
87 | /// \brief Represents a region described by entries in the .dynamic table. | |||
88 | struct DynRegionInfo { | |||
89 | DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} | |||
90 | /// \brief Address in current address space. | |||
91 | const void *Addr; | |||
92 | /// \brief Size in bytes of the region. | |||
93 | uintX_t Size; | |||
94 | /// \brief Size of each entity in the region. | |||
95 | uintX_t EntSize; | |||
96 | }; | |||
97 | ||||
98 | void printSymbolsHelper(bool IsDynamic); | |||
99 | void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab, | |||
100 | StringRef StrTable, bool IsDynamic); | |||
101 | ||||
102 | void printRelocations(const Elf_Shdr *Sec); | |||
103 | void printRelocation(const Elf_Shdr *Sec, Elf_Rela Rel); | |||
104 | void printValue(uint64_t Type, uint64_t Value); | |||
105 | ||||
106 | const Elf_Rela *dyn_rela_begin() const; | |||
107 | const Elf_Rela *dyn_rela_end() const; | |||
108 | Elf_Rela_Range dyn_relas() const; | |||
109 | StringRef getDynamicString(uint64_t Offset) const; | |||
110 | const Elf_Dyn *dynamic_table_begin() const { | |||
111 | ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_begin(DynamicProgHeader); | |||
112 | error(Ret.getError()); | |||
113 | return *Ret; | |||
114 | } | |||
115 | const Elf_Dyn *dynamic_table_end() const { | |||
116 | ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_end(DynamicProgHeader); | |||
117 | error(Ret.getError()); | |||
118 | return *Ret; | |||
119 | } | |||
120 | Elf_Dyn_Range dynamic_table() const { | |||
121 | ErrorOr<Elf_Dyn_Range> Ret = Obj->dynamic_table(DynamicProgHeader); | |||
122 | error(Ret.getError()); | |||
123 | return *Ret; | |||
124 | } | |||
125 | ||||
126 | StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, | |||
127 | bool &IsDefault); | |||
128 | void LoadVersionMap(); | |||
129 | void LoadVersionNeeds(const Elf_Shdr *ec) const; | |||
130 | void LoadVersionDefs(const Elf_Shdr *sec) const; | |||
131 | ||||
132 | const ELFO *Obj; | |||
133 | DynRegionInfo DynRelaRegion; | |||
134 | const Elf_Phdr *DynamicProgHeader = nullptr; | |||
135 | StringRef DynamicStringTable; | |||
136 | const Elf_Sym *DynSymStart = nullptr; | |||
137 | StringRef SOName; | |||
138 | const Elf_Hash *HashTable = nullptr; | |||
139 | const Elf_Shdr *DotDynSymSec = nullptr; | |||
140 | const Elf_Shdr *DotSymtabSec = nullptr; | |||
141 | ArrayRef<Elf_Word> ShndxTable; | |||
142 | ||||
143 | const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version | |||
144 | const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r | |||
145 | const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d | |||
146 | ||||
147 | // Records for each version index the corresponding Verdef or Vernaux entry. | |||
148 | // This is filled the first time LoadVersionMap() is called. | |||
149 | class VersionMapEntry : public PointerIntPair<const void *, 1> { | |||
150 | public: | |||
151 | // If the integer is 0, this is an Elf_Verdef*. | |||
152 | // If the integer is 1, this is an Elf_Vernaux*. | |||
153 | VersionMapEntry() : PointerIntPair<const void *, 1>(nullptr, 0) {} | |||
154 | VersionMapEntry(const Elf_Verdef *verdef) | |||
155 | : PointerIntPair<const void *, 1>(verdef, 0) {} | |||
156 | VersionMapEntry(const Elf_Vernaux *vernaux) | |||
157 | : PointerIntPair<const void *, 1>(vernaux, 1) {} | |||
158 | bool isNull() const { return getPointer() == nullptr; } | |||
159 | bool isVerdef() const { return !isNull() && getInt() == 0; } | |||
160 | bool isVernaux() const { return !isNull() && getInt() == 1; } | |||
161 | const Elf_Verdef *getVerdef() const { | |||
162 | return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr; | |||
163 | } | |||
164 | const Elf_Vernaux *getVernaux() const { | |||
165 | return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr; | |||
166 | } | |||
167 | }; | |||
168 | mutable SmallVector<VersionMapEntry, 16> VersionMap; | |||
169 | ||||
170 | public: | |||
171 | std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, | |||
172 | bool IsDynamic); | |||
173 | const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; } | |||
174 | const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } | |||
175 | ArrayRef<Elf_Word> getShndxTable() { return ShndxTable; } | |||
176 | }; | |||
177 | ||||
178 | template <class T> T errorOrDefault(ErrorOr<T> Val, T Default = T()) { | |||
179 | if (!Val) { | |||
180 | error(Val.getError()); | |||
181 | return Default; | |||
182 | } | |||
183 | ||||
184 | return *Val; | |||
185 | } | |||
186 | } // namespace | |||
187 | ||||
188 | namespace llvm { | |||
189 | ||||
190 | template <class ELFT> | |||
191 | static std::error_code createELFDumper(const ELFFile<ELFT> *Obj, | |||
192 | StreamWriter &Writer, | |||
193 | std::unique_ptr<ObjDumper> &Result) { | |||
194 | Result.reset(new ELFDumper<ELFT>(Obj, Writer)); | |||
195 | return readobj_error::success; | |||
196 | } | |||
197 | ||||
198 | std::error_code createELFDumper(const object::ObjectFile *Obj, | |||
199 | StreamWriter &Writer, | |||
200 | std::unique_ptr<ObjDumper> &Result) { | |||
201 | // Little-endian 32-bit | |||
202 | if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) | |||
203 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
204 | ||||
205 | // Big-endian 32-bit | |||
206 | if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) | |||
207 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
208 | ||||
209 | // Little-endian 64-bit | |||
210 | if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) | |||
211 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
212 | ||||
213 | // Big-endian 64-bit | |||
214 | if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) | |||
215 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
216 | ||||
217 | return readobj_error::unsupported_obj_file_format; | |||
218 | } | |||
219 | ||||
220 | } // namespace llvm | |||
221 | ||||
222 | // Iterate through the versions needed section, and place each Elf_Vernaux | |||
223 | // in the VersionMap according to its index. | |||
224 | template <class ELFT> | |||
225 | void ELFDumper<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { | |||
226 | unsigned vn_size = sec->sh_size; // Size of section in bytes | |||
227 | unsigned vn_count = sec->sh_info; // Number of Verneed entries | |||
228 | const char *sec_start = (const char *)Obj->base() + sec->sh_offset; | |||
229 | const char *sec_end = sec_start + vn_size; | |||
230 | // The first Verneed entry is at the start of the section. | |||
231 | const char *p = sec_start; | |||
232 | for (unsigned i = 0; i < vn_count; i++) { | |||
233 | if (p + sizeof(Elf_Verneed) > sec_end) | |||
234 | report_fatal_error("Section ended unexpectedly while scanning " | |||
235 | "version needed records."); | |||
236 | const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p); | |||
237 | if (vn->vn_version != ELF::VER_NEED_CURRENT) | |||
238 | report_fatal_error("Unexpected verneed version"); | |||
239 | // Iterate through the Vernaux entries | |||
240 | const char *paux = p + vn->vn_aux; | |||
241 | for (unsigned j = 0; j < vn->vn_cnt; j++) { | |||
242 | if (paux + sizeof(Elf_Vernaux) > sec_end) | |||
243 | report_fatal_error("Section ended unexpected while scanning auxiliary " | |||
244 | "version needed records."); | |||
245 | const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux); | |||
246 | size_t index = vna->vna_other & ELF::VERSYM_VERSION; | |||
247 | if (index >= VersionMap.size()) | |||
248 | VersionMap.resize(index + 1); | |||
249 | VersionMap[index] = VersionMapEntry(vna); | |||
250 | paux += vna->vna_next; | |||
251 | } | |||
252 | p += vn->vn_next; | |||
253 | } | |||
254 | } | |||
255 | ||||
256 | // Iterate through the version definitions, and place each Elf_Verdef | |||
257 | // in the VersionMap according to its index. | |||
258 | template <class ELFT> | |||
259 | void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { | |||
260 | unsigned vd_size = sec->sh_size; // Size of section in bytes | |||
261 | unsigned vd_count = sec->sh_info; // Number of Verdef entries | |||
262 | const char *sec_start = (const char *)Obj->base() + sec->sh_offset; | |||
263 | const char *sec_end = sec_start + vd_size; | |||
264 | // The first Verdef entry is at the start of the section. | |||
265 | const char *p = sec_start; | |||
266 | for (unsigned i = 0; i < vd_count; i++) { | |||
267 | if (p + sizeof(Elf_Verdef) > sec_end) | |||
268 | report_fatal_error("Section ended unexpectedly while scanning " | |||
269 | "version definitions."); | |||
270 | const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p); | |||
271 | if (vd->vd_version != ELF::VER_DEF_CURRENT) | |||
272 | report_fatal_error("Unexpected verdef version"); | |||
273 | size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; | |||
274 | if (index >= VersionMap.size()) | |||
275 | VersionMap.resize(index + 1); | |||
276 | VersionMap[index] = VersionMapEntry(vd); | |||
277 | p += vd->vd_next; | |||
278 | } | |||
279 | } | |||
280 | ||||
281 | template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() { | |||
282 | // If there is no dynamic symtab or version table, there is nothing to do. | |||
283 | if (!DynSymStart || !dot_gnu_version_sec) | |||
284 | return; | |||
285 | ||||
286 | // Has the VersionMap already been loaded? | |||
287 | if (VersionMap.size() > 0) | |||
288 | return; | |||
289 | ||||
290 | // The first two version indexes are reserved. | |||
291 | // Index 0 is LOCAL, index 1 is GLOBAL. | |||
292 | VersionMap.push_back(VersionMapEntry()); | |||
293 | VersionMap.push_back(VersionMapEntry()); | |||
294 | ||||
295 | if (dot_gnu_version_d_sec) | |||
296 | LoadVersionDefs(dot_gnu_version_d_sec); | |||
297 | ||||
298 | if (dot_gnu_version_r_sec) | |||
299 | LoadVersionNeeds(dot_gnu_version_r_sec); | |||
300 | } | |||
301 | ||||
302 | template <typename ELFT> | |||
303 | StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab, | |||
304 | const Elf_Sym *symb, | |||
305 | bool &IsDefault) { | |||
306 | // This is a dynamic symbol. Look in the GNU symbol version table. | |||
307 | if (!dot_gnu_version_sec) { | |||
308 | // No version table. | |||
309 | IsDefault = false; | |||
310 | return StringRef(""); | |||
311 | } | |||
312 | ||||
313 | // Determine the position in the symbol table of this entry. | |||
314 | size_t entry_index = (reinterpret_cast<uintptr_t>(symb) - | |||
315 | reinterpret_cast<uintptr_t>(DynSymStart)) / | |||
316 | sizeof(Elf_Sym); | |||
317 | ||||
318 | // Get the corresponding version index entry | |||
319 | const Elf_Versym *vs = | |||
320 | Obj->template getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index); | |||
321 | size_t version_index = vs->vs_index & ELF::VERSYM_VERSION; | |||
322 | ||||
323 | // Special markers for unversioned symbols. | |||
324 | if (version_index == ELF::VER_NDX_LOCAL || | |||
325 | version_index == ELF::VER_NDX_GLOBAL) { | |||
326 | IsDefault = false; | |||
327 | return StringRef(""); | |||
328 | } | |||
329 | ||||
330 | // Lookup this symbol in the version table | |||
331 | LoadVersionMap(); | |||
332 | if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) | |||
333 | reportError("Invalid version entry"); | |||
334 | const VersionMapEntry &entry = VersionMap[version_index]; | |||
335 | ||||
336 | // Get the version name string | |||
337 | size_t name_offset; | |||
338 | if (entry.isVerdef()) { | |||
339 | // The first Verdaux entry holds the name. | |||
340 | name_offset = entry.getVerdef()->getAux()->vda_name; | |||
341 | } else { | |||
342 | name_offset = entry.getVernaux()->vna_name; | |||
343 | } | |||
344 | ||||
345 | // Set IsDefault | |||
346 | if (entry.isVerdef()) { | |||
347 | IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN); | |||
348 | } else { | |||
349 | IsDefault = false; | |||
350 | } | |||
351 | ||||
352 | if (name_offset >= StrTab.size()) | |||
353 | reportError("Invalid string offset"); | |||
354 | return StringRef(StrTab.data() + name_offset); | |||
355 | } | |||
356 | ||||
357 | template <typename ELFT> | |||
358 | std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol, | |||
359 | StringRef StrTable, | |||
360 | bool IsDynamic) { | |||
361 | StringRef SymbolName = errorOrDefault(Symbol->getName(StrTable)); | |||
362 | if (!IsDynamic) | |||
363 | return SymbolName; | |||
364 | ||||
365 | std::string FullSymbolName(SymbolName); | |||
366 | ||||
367 | bool IsDefault; | |||
368 | StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault); | |||
369 | FullSymbolName += (IsDefault ? "@@" : "@"); | |||
370 | FullSymbolName += Version; | |||
371 | return FullSymbolName; | |||
372 | } | |||
373 | ||||
374 | template <typename ELFO> | |||
375 | static void | |||
376 | getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, | |||
377 | const typename ELFO::Elf_Shdr *SymTab, | |||
378 | ArrayRef<typename ELFO::Elf_Word> ShndxTable, | |||
379 | StringRef &SectionName, unsigned &SectionIndex) { | |||
380 | SectionIndex = Symbol->st_shndx; | |||
381 | if (Symbol->isUndefined()) | |||
382 | SectionName = "Undefined"; | |||
383 | else if (Symbol->isProcessorSpecific()) | |||
384 | SectionName = "Processor Specific"; | |||
385 | else if (Symbol->isOSSpecific()) | |||
386 | SectionName = "Operating System Specific"; | |||
387 | else if (Symbol->isAbsolute()) | |||
388 | SectionName = "Absolute"; | |||
389 | else if (Symbol->isCommon()) | |||
390 | SectionName = "Common"; | |||
391 | else if (Symbol->isReserved() && SectionIndex != SHN_XINDEX) | |||
392 | SectionName = "Reserved"; | |||
393 | else { | |||
394 | if (SectionIndex == SHN_XINDEX) | |||
395 | SectionIndex = | |||
396 | Obj.getExtendedSymbolTableIndex(Symbol, SymTab, ShndxTable); | |||
397 | ErrorOr<const typename ELFO::Elf_Shdr *> Sec = Obj.getSection(SectionIndex); | |||
398 | error(Sec.getError()); | |||
399 | SectionName = errorOrDefault(Obj.getSectionName(*Sec)); | |||
400 | } | |||
401 | } | |||
402 | ||||
403 | template <class ELFO> | |||
404 | static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj, | |||
405 | uint64_t Addr) { | |||
406 | for (const auto &Shdr : Obj->sections()) | |||
407 | if (Shdr.sh_addr == Addr) | |||
408 | return &Shdr; | |||
409 | return nullptr; | |||
410 | } | |||
411 | ||||
412 | template <class ELFO> | |||
413 | static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj, | |||
414 | StringRef Name) { | |||
415 | for (const auto &Shdr : Obj.sections()) { | |||
416 | if (Name == errorOrDefault(Obj.getSectionName(&Shdr))) | |||
417 | return &Shdr; | |||
418 | } | |||
419 | return nullptr; | |||
420 | } | |||
421 | ||||
422 | static const EnumEntry<unsigned> ElfClass[] = { | |||
423 | { "None", ELF::ELFCLASSNONE }, | |||
424 | { "32-bit", ELF::ELFCLASS32 }, | |||
425 | { "64-bit", ELF::ELFCLASS64 }, | |||
426 | }; | |||
427 | ||||
428 | static const EnumEntry<unsigned> ElfDataEncoding[] = { | |||
429 | { "None", ELF::ELFDATANONE }, | |||
430 | { "LittleEndian", ELF::ELFDATA2LSB }, | |||
431 | { "BigEndian", ELF::ELFDATA2MSB }, | |||
432 | }; | |||
433 | ||||
434 | static const EnumEntry<unsigned> ElfObjectFileType[] = { | |||
435 | { "None", ELF::ET_NONE }, | |||
436 | { "Relocatable", ELF::ET_REL }, | |||
437 | { "Executable", ELF::ET_EXEC }, | |||
438 | { "SharedObject", ELF::ET_DYN }, | |||
439 | { "Core", ELF::ET_CORE }, | |||
440 | }; | |||
441 | ||||
442 | static const EnumEntry<unsigned> ElfOSABI[] = { | |||
443 | { "SystemV", ELF::ELFOSABI_NONE }, | |||
444 | { "HPUX", ELF::ELFOSABI_HPUX }, | |||
445 | { "NetBSD", ELF::ELFOSABI_NETBSD }, | |||
446 | { "GNU/Linux", ELF::ELFOSABI_LINUX }, | |||
447 | { "GNU/Hurd", ELF::ELFOSABI_HURD }, | |||
448 | { "Solaris", ELF::ELFOSABI_SOLARIS }, | |||
449 | { "AIX", ELF::ELFOSABI_AIX }, | |||
450 | { "IRIX", ELF::ELFOSABI_IRIX }, | |||
451 | { "FreeBSD", ELF::ELFOSABI_FREEBSD }, | |||
452 | { "TRU64", ELF::ELFOSABI_TRU64 }, | |||
453 | { "Modesto", ELF::ELFOSABI_MODESTO }, | |||
454 | { "OpenBSD", ELF::ELFOSABI_OPENBSD }, | |||
455 | { "OpenVMS", ELF::ELFOSABI_OPENVMS }, | |||
456 | { "NSK", ELF::ELFOSABI_NSK }, | |||
457 | { "AROS", ELF::ELFOSABI_AROS }, | |||
458 | { "FenixOS", ELF::ELFOSABI_FENIXOS }, | |||
459 | { "CloudABI", ELF::ELFOSABI_CLOUDABI }, | |||
460 | { "C6000_ELFABI", ELF::ELFOSABI_C6000_ELFABI }, | |||
461 | { "C6000_LINUX" , ELF::ELFOSABI_C6000_LINUX }, | |||
462 | { "ARM", ELF::ELFOSABI_ARM }, | |||
463 | { "Standalone" , ELF::ELFOSABI_STANDALONE } | |||
464 | }; | |||
465 | ||||
466 | static const EnumEntry<unsigned> ElfMachineType[] = { | |||
467 | LLVM_READOBJ_ENUM_ENT(ELF, EM_NONE ){ "EM_NONE", ELF::EM_NONE }, | |||
468 | LLVM_READOBJ_ENUM_ENT(ELF, EM_M32 ){ "EM_M32", ELF::EM_M32 }, | |||
469 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SPARC ){ "EM_SPARC", ELF::EM_SPARC }, | |||
470 | LLVM_READOBJ_ENUM_ENT(ELF, EM_386 ){ "EM_386", ELF::EM_386 }, | |||
471 | LLVM_READOBJ_ENUM_ENT(ELF, EM_68K ){ "EM_68K", ELF::EM_68K }, | |||
472 | LLVM_READOBJ_ENUM_ENT(ELF, EM_88K ){ "EM_88K", ELF::EM_88K }, | |||
473 | LLVM_READOBJ_ENUM_ENT(ELF, EM_IAMCU ){ "EM_IAMCU", ELF::EM_IAMCU }, | |||
474 | LLVM_READOBJ_ENUM_ENT(ELF, EM_860 ){ "EM_860", ELF::EM_860 }, | |||
475 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MIPS ){ "EM_MIPS", ELF::EM_MIPS }, | |||
476 | LLVM_READOBJ_ENUM_ENT(ELF, EM_S370 ){ "EM_S370", ELF::EM_S370 }, | |||
477 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MIPS_RS3_LE ){ "EM_MIPS_RS3_LE", ELF::EM_MIPS_RS3_LE }, | |||
478 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PARISC ){ "EM_PARISC", ELF::EM_PARISC }, | |||
479 | LLVM_READOBJ_ENUM_ENT(ELF, EM_VPP500 ){ "EM_VPP500", ELF::EM_VPP500 }, | |||
480 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SPARC32PLUS ){ "EM_SPARC32PLUS", ELF::EM_SPARC32PLUS }, | |||
481 | LLVM_READOBJ_ENUM_ENT(ELF, EM_960 ){ "EM_960", ELF::EM_960 }, | |||
482 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PPC ){ "EM_PPC", ELF::EM_PPC }, | |||
483 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PPC64 ){ "EM_PPC64", ELF::EM_PPC64 }, | |||
484 | LLVM_READOBJ_ENUM_ENT(ELF, EM_S390 ){ "EM_S390", ELF::EM_S390 }, | |||
485 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SPU ){ "EM_SPU", ELF::EM_SPU }, | |||
486 | LLVM_READOBJ_ENUM_ENT(ELF, EM_V800 ){ "EM_V800", ELF::EM_V800 }, | |||
487 | LLVM_READOBJ_ENUM_ENT(ELF, EM_FR20 ){ "EM_FR20", ELF::EM_FR20 }, | |||
488 | LLVM_READOBJ_ENUM_ENT(ELF, EM_RH32 ){ "EM_RH32", ELF::EM_RH32 }, | |||
489 | LLVM_READOBJ_ENUM_ENT(ELF, EM_RCE ){ "EM_RCE", ELF::EM_RCE }, | |||
490 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ARM ){ "EM_ARM", ELF::EM_ARM }, | |||
491 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ALPHA ){ "EM_ALPHA", ELF::EM_ALPHA }, | |||
492 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SH ){ "EM_SH", ELF::EM_SH }, | |||
493 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SPARCV9 ){ "EM_SPARCV9", ELF::EM_SPARCV9 }, | |||
494 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TRICORE ){ "EM_TRICORE", ELF::EM_TRICORE }, | |||
495 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ARC ){ "EM_ARC", ELF::EM_ARC }, | |||
496 | LLVM_READOBJ_ENUM_ENT(ELF, EM_H8_300 ){ "EM_H8_300", ELF::EM_H8_300 }, | |||
497 | LLVM_READOBJ_ENUM_ENT(ELF, EM_H8_300H ){ "EM_H8_300H", ELF::EM_H8_300H }, | |||
498 | LLVM_READOBJ_ENUM_ENT(ELF, EM_H8S ){ "EM_H8S", ELF::EM_H8S }, | |||
499 | LLVM_READOBJ_ENUM_ENT(ELF, EM_H8_500 ){ "EM_H8_500", ELF::EM_H8_500 }, | |||
500 | LLVM_READOBJ_ENUM_ENT(ELF, EM_IA_64 ){ "EM_IA_64", ELF::EM_IA_64 }, | |||
501 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MIPS_X ){ "EM_MIPS_X", ELF::EM_MIPS_X }, | |||
502 | LLVM_READOBJ_ENUM_ENT(ELF, EM_COLDFIRE ){ "EM_COLDFIRE", ELF::EM_COLDFIRE }, | |||
503 | LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC12 ){ "EM_68HC12", ELF::EM_68HC12 }, | |||
504 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MMA ){ "EM_MMA", ELF::EM_MMA }, | |||
505 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PCP ){ "EM_PCP", ELF::EM_PCP }, | |||
506 | LLVM_READOBJ_ENUM_ENT(ELF, EM_NCPU ){ "EM_NCPU", ELF::EM_NCPU }, | |||
507 | LLVM_READOBJ_ENUM_ENT(ELF, EM_NDR1 ){ "EM_NDR1", ELF::EM_NDR1 }, | |||
508 | LLVM_READOBJ_ENUM_ENT(ELF, EM_STARCORE ){ "EM_STARCORE", ELF::EM_STARCORE }, | |||
509 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ME16 ){ "EM_ME16", ELF::EM_ME16 }, | |||
510 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ST100 ){ "EM_ST100", ELF::EM_ST100 }, | |||
511 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TINYJ ){ "EM_TINYJ", ELF::EM_TINYJ }, | |||
512 | LLVM_READOBJ_ENUM_ENT(ELF, EM_X86_64 ){ "EM_X86_64", ELF::EM_X86_64 }, | |||
513 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PDSP ){ "EM_PDSP", ELF::EM_PDSP }, | |||
514 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PDP10 ){ "EM_PDP10", ELF::EM_PDP10 }, | |||
515 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PDP11 ){ "EM_PDP11", ELF::EM_PDP11 }, | |||
516 | LLVM_READOBJ_ENUM_ENT(ELF, EM_FX66 ){ "EM_FX66", ELF::EM_FX66 }, | |||
517 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ST9PLUS ){ "EM_ST9PLUS", ELF::EM_ST9PLUS }, | |||
518 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ST7 ){ "EM_ST7", ELF::EM_ST7 }, | |||
519 | LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC16 ){ "EM_68HC16", ELF::EM_68HC16 }, | |||
520 | LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC11 ){ "EM_68HC11", ELF::EM_68HC11 }, | |||
521 | LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC08 ){ "EM_68HC08", ELF::EM_68HC08 }, | |||
522 | LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC05 ){ "EM_68HC05", ELF::EM_68HC05 }, | |||
523 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SVX ){ "EM_SVX", ELF::EM_SVX }, | |||
524 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ST19 ){ "EM_ST19", ELF::EM_ST19 }, | |||
525 | LLVM_READOBJ_ENUM_ENT(ELF, EM_VAX ){ "EM_VAX", ELF::EM_VAX }, | |||
526 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CRIS ){ "EM_CRIS", ELF::EM_CRIS }, | |||
527 | LLVM_READOBJ_ENUM_ENT(ELF, EM_JAVELIN ){ "EM_JAVELIN", ELF::EM_JAVELIN }, | |||
528 | LLVM_READOBJ_ENUM_ENT(ELF, EM_FIREPATH ){ "EM_FIREPATH", ELF::EM_FIREPATH }, | |||
529 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ZSP ){ "EM_ZSP", ELF::EM_ZSP }, | |||
530 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MMIX ){ "EM_MMIX", ELF::EM_MMIX }, | |||
531 | LLVM_READOBJ_ENUM_ENT(ELF, EM_HUANY ){ "EM_HUANY", ELF::EM_HUANY }, | |||
532 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PRISM ){ "EM_PRISM", ELF::EM_PRISM }, | |||
533 | LLVM_READOBJ_ENUM_ENT(ELF, EM_AVR ){ "EM_AVR", ELF::EM_AVR }, | |||
534 | LLVM_READOBJ_ENUM_ENT(ELF, EM_FR30 ){ "EM_FR30", ELF::EM_FR30 }, | |||
535 | LLVM_READOBJ_ENUM_ENT(ELF, EM_D10V ){ "EM_D10V", ELF::EM_D10V }, | |||
536 | LLVM_READOBJ_ENUM_ENT(ELF, EM_D30V ){ "EM_D30V", ELF::EM_D30V }, | |||
537 | LLVM_READOBJ_ENUM_ENT(ELF, EM_V850 ){ "EM_V850", ELF::EM_V850 }, | |||
538 | LLVM_READOBJ_ENUM_ENT(ELF, EM_M32R ){ "EM_M32R", ELF::EM_M32R }, | |||
539 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MN10300 ){ "EM_MN10300", ELF::EM_MN10300 }, | |||
540 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MN10200 ){ "EM_MN10200", ELF::EM_MN10200 }, | |||
541 | LLVM_READOBJ_ENUM_ENT(ELF, EM_PJ ){ "EM_PJ", ELF::EM_PJ }, | |||
542 | LLVM_READOBJ_ENUM_ENT(ELF, EM_OPENRISC ){ "EM_OPENRISC", ELF::EM_OPENRISC }, | |||
543 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ARC_COMPACT ){ "EM_ARC_COMPACT", ELF::EM_ARC_COMPACT }, | |||
544 | LLVM_READOBJ_ENUM_ENT(ELF, EM_XTENSA ){ "EM_XTENSA", ELF::EM_XTENSA }, | |||
545 | LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE ){ "EM_VIDEOCORE", ELF::EM_VIDEOCORE }, | |||
546 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TMM_GPP ){ "EM_TMM_GPP", ELF::EM_TMM_GPP }, | |||
547 | LLVM_READOBJ_ENUM_ENT(ELF, EM_NS32K ){ "EM_NS32K", ELF::EM_NS32K }, | |||
548 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TPC ){ "EM_TPC", ELF::EM_TPC }, | |||
549 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SNP1K ){ "EM_SNP1K", ELF::EM_SNP1K }, | |||
550 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ST200 ){ "EM_ST200", ELF::EM_ST200 }, | |||
551 | LLVM_READOBJ_ENUM_ENT(ELF, EM_IP2K ){ "EM_IP2K", ELF::EM_IP2K }, | |||
552 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MAX ){ "EM_MAX", ELF::EM_MAX }, | |||
553 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CR ){ "EM_CR", ELF::EM_CR }, | |||
554 | LLVM_READOBJ_ENUM_ENT(ELF, EM_F2MC16 ){ "EM_F2MC16", ELF::EM_F2MC16 }, | |||
555 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MSP430 ){ "EM_MSP430", ELF::EM_MSP430 }, | |||
556 | LLVM_READOBJ_ENUM_ENT(ELF, EM_BLACKFIN ){ "EM_BLACKFIN", ELF::EM_BLACKFIN }, | |||
557 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SE_C33 ){ "EM_SE_C33", ELF::EM_SE_C33 }, | |||
558 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SEP ){ "EM_SEP", ELF::EM_SEP }, | |||
559 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ARCA ){ "EM_ARCA", ELF::EM_ARCA }, | |||
560 | LLVM_READOBJ_ENUM_ENT(ELF, EM_UNICORE ){ "EM_UNICORE", ELF::EM_UNICORE }, | |||
561 | LLVM_READOBJ_ENUM_ENT(ELF, EM_EXCESS ){ "EM_EXCESS", ELF::EM_EXCESS }, | |||
562 | LLVM_READOBJ_ENUM_ENT(ELF, EM_DXP ){ "EM_DXP", ELF::EM_DXP }, | |||
563 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ALTERA_NIOS2 ){ "EM_ALTERA_NIOS2", ELF::EM_ALTERA_NIOS2 }, | |||
564 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CRX ){ "EM_CRX", ELF::EM_CRX }, | |||
565 | LLVM_READOBJ_ENUM_ENT(ELF, EM_XGATE ){ "EM_XGATE", ELF::EM_XGATE }, | |||
566 | LLVM_READOBJ_ENUM_ENT(ELF, EM_C166 ){ "EM_C166", ELF::EM_C166 }, | |||
567 | LLVM_READOBJ_ENUM_ENT(ELF, EM_M16C ){ "EM_M16C", ELF::EM_M16C }, | |||
568 | LLVM_READOBJ_ENUM_ENT(ELF, EM_DSPIC30F ){ "EM_DSPIC30F", ELF::EM_DSPIC30F }, | |||
569 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CE ){ "EM_CE", ELF::EM_CE }, | |||
570 | LLVM_READOBJ_ENUM_ENT(ELF, EM_M32C ){ "EM_M32C", ELF::EM_M32C }, | |||
571 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TSK3000 ){ "EM_TSK3000", ELF::EM_TSK3000 }, | |||
572 | LLVM_READOBJ_ENUM_ENT(ELF, EM_RS08 ){ "EM_RS08", ELF::EM_RS08 }, | |||
573 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SHARC ){ "EM_SHARC", ELF::EM_SHARC }, | |||
574 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG2 ){ "EM_ECOG2", ELF::EM_ECOG2 }, | |||
575 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SCORE7 ){ "EM_SCORE7", ELF::EM_SCORE7 }, | |||
576 | LLVM_READOBJ_ENUM_ENT(ELF, EM_DSP24 ){ "EM_DSP24", ELF::EM_DSP24 }, | |||
577 | LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE3 ){ "EM_VIDEOCORE3", ELF::EM_VIDEOCORE3 }, | |||
578 | LLVM_READOBJ_ENUM_ENT(ELF, EM_LATTICEMICO32){ "EM_LATTICEMICO32", ELF::EM_LATTICEMICO32 }, | |||
579 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SE_C17 ){ "EM_SE_C17", ELF::EM_SE_C17 }, | |||
580 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TI_C6000 ){ "EM_TI_C6000", ELF::EM_TI_C6000 }, | |||
581 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TI_C2000 ){ "EM_TI_C2000", ELF::EM_TI_C2000 }, | |||
582 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TI_C5500 ){ "EM_TI_C5500", ELF::EM_TI_C5500 }, | |||
583 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MMDSP_PLUS ){ "EM_MMDSP_PLUS", ELF::EM_MMDSP_PLUS }, | |||
584 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CYPRESS_M8C ){ "EM_CYPRESS_M8C", ELF::EM_CYPRESS_M8C }, | |||
585 | LLVM_READOBJ_ENUM_ENT(ELF, EM_R32C ){ "EM_R32C", ELF::EM_R32C }, | |||
586 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TRIMEDIA ){ "EM_TRIMEDIA", ELF::EM_TRIMEDIA }, | |||
587 | LLVM_READOBJ_ENUM_ENT(ELF, EM_HEXAGON ){ "EM_HEXAGON", ELF::EM_HEXAGON }, | |||
588 | LLVM_READOBJ_ENUM_ENT(ELF, EM_8051 ){ "EM_8051", ELF::EM_8051 }, | |||
589 | LLVM_READOBJ_ENUM_ENT(ELF, EM_STXP7X ){ "EM_STXP7X", ELF::EM_STXP7X }, | |||
590 | LLVM_READOBJ_ENUM_ENT(ELF, EM_NDS32 ){ "EM_NDS32", ELF::EM_NDS32 }, | |||
591 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG1 ){ "EM_ECOG1", ELF::EM_ECOG1 }, | |||
592 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG1X ){ "EM_ECOG1X", ELF::EM_ECOG1X }, | |||
593 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MAXQ30 ){ "EM_MAXQ30", ELF::EM_MAXQ30 }, | |||
594 | LLVM_READOBJ_ENUM_ENT(ELF, EM_XIMO16 ){ "EM_XIMO16", ELF::EM_XIMO16 }, | |||
595 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MANIK ){ "EM_MANIK", ELF::EM_MANIK }, | |||
596 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CRAYNV2 ){ "EM_CRAYNV2", ELF::EM_CRAYNV2 }, | |||
597 | LLVM_READOBJ_ENUM_ENT(ELF, EM_RX ){ "EM_RX", ELF::EM_RX }, | |||
598 | LLVM_READOBJ_ENUM_ENT(ELF, EM_METAG ){ "EM_METAG", ELF::EM_METAG }, | |||
599 | LLVM_READOBJ_ENUM_ENT(ELF, EM_MCST_ELBRUS ){ "EM_MCST_ELBRUS", ELF::EM_MCST_ELBRUS }, | |||
600 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG16 ){ "EM_ECOG16", ELF::EM_ECOG16 }, | |||
601 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CR16 ){ "EM_CR16", ELF::EM_CR16 }, | |||
602 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ETPU ){ "EM_ETPU", ELF::EM_ETPU }, | |||
603 | LLVM_READOBJ_ENUM_ENT(ELF, EM_SLE9X ){ "EM_SLE9X", ELF::EM_SLE9X }, | |||
604 | LLVM_READOBJ_ENUM_ENT(ELF, EM_L10M ){ "EM_L10M", ELF::EM_L10M }, | |||
605 | LLVM_READOBJ_ENUM_ENT(ELF, EM_K10M ){ "EM_K10M", ELF::EM_K10M }, | |||
606 | LLVM_READOBJ_ENUM_ENT(ELF, EM_AARCH64 ){ "EM_AARCH64", ELF::EM_AARCH64 }, | |||
607 | LLVM_READOBJ_ENUM_ENT(ELF, EM_AVR32 ){ "EM_AVR32", ELF::EM_AVR32 }, | |||
608 | LLVM_READOBJ_ENUM_ENT(ELF, EM_STM8 ){ "EM_STM8", ELF::EM_STM8 }, | |||
609 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TILE64 ){ "EM_TILE64", ELF::EM_TILE64 }, | |||
610 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEPRO ){ "EM_TILEPRO", ELF::EM_TILEPRO }, | |||
611 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CUDA ){ "EM_CUDA", ELF::EM_CUDA }, | |||
612 | LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEGX ){ "EM_TILEGX", ELF::EM_TILEGX }, | |||
613 | LLVM_READOBJ_ENUM_ENT(ELF, EM_CLOUDSHIELD ){ "EM_CLOUDSHIELD", ELF::EM_CLOUDSHIELD }, | |||
614 | LLVM_READOBJ_ENUM_ENT(ELF, EM_COREA_1ST ){ "EM_COREA_1ST", ELF::EM_COREA_1ST }, | |||
615 | LLVM_READOBJ_ENUM_ENT(ELF, EM_COREA_2ND ){ "EM_COREA_2ND", ELF::EM_COREA_2ND }, | |||
616 | LLVM_READOBJ_ENUM_ENT(ELF, EM_ARC_COMPACT2 ){ "EM_ARC_COMPACT2", ELF::EM_ARC_COMPACT2 }, | |||
617 | LLVM_READOBJ_ENUM_ENT(ELF, EM_OPEN8 ){ "EM_OPEN8", ELF::EM_OPEN8 }, | |||
618 | LLVM_READOBJ_ENUM_ENT(ELF, EM_RL78 ){ "EM_RL78", ELF::EM_RL78 }, | |||
619 | LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE5 ){ "EM_VIDEOCORE5", ELF::EM_VIDEOCORE5 }, | |||
620 | LLVM_READOBJ_ENUM_ENT(ELF, EM_78KOR ){ "EM_78KOR", ELF::EM_78KOR }, | |||
621 | LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX ){ "EM_56800EX", ELF::EM_56800EX }, | |||
622 | LLVM_READOBJ_ENUM_ENT(ELF, EM_AMDGPU ){ "EM_AMDGPU", ELF::EM_AMDGPU } | |||
623 | }; | |||
624 | ||||
625 | static const EnumEntry<unsigned> ElfSymbolBindings[] = { | |||
626 | { "Local", ELF::STB_LOCAL }, | |||
627 | { "Global", ELF::STB_GLOBAL }, | |||
628 | { "Weak", ELF::STB_WEAK }, | |||
629 | { "Unique", ELF::STB_GNU_UNIQUE } | |||
630 | }; | |||
631 | ||||
632 | static const EnumEntry<unsigned> ElfSymbolTypes[] = { | |||
633 | { "None", ELF::STT_NOTYPE }, | |||
634 | { "Object", ELF::STT_OBJECT }, | |||
635 | { "Function", ELF::STT_FUNC }, | |||
636 | { "Section", ELF::STT_SECTION }, | |||
637 | { "File", ELF::STT_FILE }, | |||
638 | { "Common", ELF::STT_COMMON }, | |||
639 | { "TLS", ELF::STT_TLS }, | |||
640 | { "GNU_IFunc", ELF::STT_GNU_IFUNC } | |||
641 | }; | |||
642 | ||||
643 | static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = { | |||
644 | { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }, | |||
645 | { "AMDGPU_HSA_INDIRECT_FUNCTION", ELF::STT_AMDGPU_HSA_INDIRECT_FUNCTION }, | |||
646 | { "AMDGPU_HSA_METADATA", ELF::STT_AMDGPU_HSA_METADATA } | |||
647 | }; | |||
648 | ||||
649 | static const char *getElfSectionType(unsigned Arch, unsigned Type) { | |||
650 | switch (Arch) { | |||
651 | case ELF::EM_ARM: | |||
652 | switch (Type) { | |||
653 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_EXIDX)case ELF::SHT_ARM_EXIDX: return "SHT_ARM_EXIDX";; | |||
654 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP)case ELF::SHT_ARM_PREEMPTMAP: return "SHT_ARM_PREEMPTMAP";; | |||
655 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_ATTRIBUTES)case ELF::SHT_ARM_ATTRIBUTES: return "SHT_ARM_ATTRIBUTES";; | |||
656 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY)case ELF::SHT_ARM_DEBUGOVERLAY: return "SHT_ARM_DEBUGOVERLAY" ;; | |||
657 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION)case ELF::SHT_ARM_OVERLAYSECTION: return "SHT_ARM_OVERLAYSECTION" ;; | |||
658 | } | |||
659 | case ELF::EM_HEXAGON: | |||
660 | switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_HEX_ORDERED)case ELF::SHT_HEX_ORDERED: return "SHT_HEX_ORDERED";; } | |||
661 | case ELF::EM_X86_64: | |||
662 | switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_X86_64_UNWIND)case ELF::SHT_X86_64_UNWIND: return "SHT_X86_64_UNWIND";; } | |||
663 | case ELF::EM_MIPS: | |||
664 | case ELF::EM_MIPS_RS3_LE: | |||
665 | switch (Type) { | |||
666 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_REGINFO)case ELF::SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO";; | |||
667 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_OPTIONS)case ELF::SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS";; | |||
668 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS)case ELF::SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS";; | |||
669 | } | |||
670 | } | |||
671 | ||||
672 | switch (Type) { | |||
673 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_NULL )case ELF::SHT_NULL: return "SHT_NULL";; | |||
674 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_PROGBITS )case ELF::SHT_PROGBITS: return "SHT_PROGBITS";; | |||
675 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_SYMTAB )case ELF::SHT_SYMTAB: return "SHT_SYMTAB";; | |||
676 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_STRTAB )case ELF::SHT_STRTAB: return "SHT_STRTAB";; | |||
677 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_RELA )case ELF::SHT_RELA: return "SHT_RELA";; | |||
678 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_HASH )case ELF::SHT_HASH: return "SHT_HASH";; | |||
679 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_DYNAMIC )case ELF::SHT_DYNAMIC: return "SHT_DYNAMIC";; | |||
680 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_NOTE )case ELF::SHT_NOTE: return "SHT_NOTE";; | |||
681 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_NOBITS )case ELF::SHT_NOBITS: return "SHT_NOBITS";; | |||
682 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_REL )case ELF::SHT_REL: return "SHT_REL";; | |||
683 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_SHLIB )case ELF::SHT_SHLIB: return "SHT_SHLIB";; | |||
684 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_DYNSYM )case ELF::SHT_DYNSYM: return "SHT_DYNSYM";; | |||
685 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_INIT_ARRAY )case ELF::SHT_INIT_ARRAY: return "SHT_INIT_ARRAY";; | |||
686 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_FINI_ARRAY )case ELF::SHT_FINI_ARRAY: return "SHT_FINI_ARRAY";; | |||
687 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_PREINIT_ARRAY )case ELF::SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY";; | |||
688 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_GROUP )case ELF::SHT_GROUP: return "SHT_GROUP";; | |||
689 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX )case ELF::SHT_SYMTAB_SHNDX: return "SHT_SYMTAB_SHNDX";; | |||
690 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES )case ELF::SHT_GNU_ATTRIBUTES: return "SHT_GNU_ATTRIBUTES";; | |||
691 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_HASH )case ELF::SHT_GNU_HASH: return "SHT_GNU_HASH";; | |||
692 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_verdef )case ELF::SHT_GNU_verdef: return "SHT_GNU_verdef";; | |||
693 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_verneed )case ELF::SHT_GNU_verneed: return "SHT_GNU_verneed";; | |||
694 | LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_versym )case ELF::SHT_GNU_versym: return "SHT_GNU_versym";; | |||
695 | default: return ""; | |||
696 | } | |||
697 | } | |||
698 | ||||
699 | static const EnumEntry<unsigned> ElfSectionFlags[] = { | |||
700 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_WRITE ){ "SHF_WRITE", ELF::SHF_WRITE }, | |||
701 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_ALLOC ){ "SHF_ALLOC", ELF::SHF_ALLOC }, | |||
702 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_EXCLUDE ){ "SHF_EXCLUDE", ELF::SHF_EXCLUDE }, | |||
703 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_EXECINSTR ){ "SHF_EXECINSTR", ELF::SHF_EXECINSTR }, | |||
704 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MERGE ){ "SHF_MERGE", ELF::SHF_MERGE }, | |||
705 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_STRINGS ){ "SHF_STRINGS", ELF::SHF_STRINGS }, | |||
706 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_INFO_LINK ){ "SHF_INFO_LINK", ELF::SHF_INFO_LINK }, | |||
707 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_LINK_ORDER ){ "SHF_LINK_ORDER", ELF::SHF_LINK_ORDER }, | |||
708 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_OS_NONCONFORMING){ "SHF_OS_NONCONFORMING", ELF::SHF_OS_NONCONFORMING }, | |||
709 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_GROUP ){ "SHF_GROUP", ELF::SHF_GROUP }, | |||
710 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_TLS ){ "SHF_TLS", ELF::SHF_TLS }, | |||
711 | LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION){ "XCORE_SHF_CP_SECTION", ELF::XCORE_SHF_CP_SECTION }, | |||
712 | LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION){ "XCORE_SHF_DP_SECTION", ELF::XCORE_SHF_DP_SECTION }, | |||
713 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ){ "SHF_MIPS_NOSTRIP", ELF::SHF_MIPS_NOSTRIP }, | |||
714 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_GLOBAL){ "SHF_AMDGPU_HSA_GLOBAL", ELF::SHF_AMDGPU_HSA_GLOBAL }, | |||
715 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_READONLY){ "SHF_AMDGPU_HSA_READONLY", ELF::SHF_AMDGPU_HSA_READONLY }, | |||
716 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_CODE){ "SHF_AMDGPU_HSA_CODE", ELF::SHF_AMDGPU_HSA_CODE }, | |||
717 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT){ "SHF_AMDGPU_HSA_AGENT", ELF::SHF_AMDGPU_HSA_AGENT } | |||
718 | }; | |||
719 | ||||
720 | static const char *getElfSegmentType(unsigned Arch, unsigned Type) { | |||
721 | // Check potentially overlapped processor-specific | |||
722 | // program header type. | |||
723 | switch (Arch) { | |||
724 | case ELF::EM_AMDGPU: | |||
725 | switch (Type) { | |||
726 | LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM)case ELF::PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM: return "PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM" ;; | |||
727 | LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT)case ELF::PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT: return "PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT" ;; | |||
728 | LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT)case ELF::PT_AMDGPU_HSA_LOAD_READONLY_AGENT: return "PT_AMDGPU_HSA_LOAD_READONLY_AGENT" ;; | |||
729 | LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT)case ELF::PT_AMDGPU_HSA_LOAD_CODE_AGENT: return "PT_AMDGPU_HSA_LOAD_CODE_AGENT" ;; | |||
730 | } | |||
731 | case ELF::EM_ARM: | |||
732 | switch (Type) { | |||
733 | LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX)case ELF::PT_ARM_EXIDX: return "PT_ARM_EXIDX";; | |||
734 | } | |||
735 | case ELF::EM_MIPS: | |||
736 | case ELF::EM_MIPS_RS3_LE: | |||
737 | switch (Type) { | |||
738 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO)case ELF::PT_MIPS_REGINFO: return "PT_MIPS_REGINFO";; | |||
739 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC)case ELF::PT_MIPS_RTPROC: return "PT_MIPS_RTPROC";; | |||
740 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS)case ELF::PT_MIPS_OPTIONS: return "PT_MIPS_OPTIONS";; | |||
741 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS)case ELF::PT_MIPS_ABIFLAGS: return "PT_MIPS_ABIFLAGS";; | |||
742 | } | |||
743 | } | |||
744 | ||||
745 | switch (Type) { | |||
746 | LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL )case ELF::PT_NULL: return "PT_NULL";; | |||
747 | LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD )case ELF::PT_LOAD: return "PT_LOAD";; | |||
748 | LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC)case ELF::PT_DYNAMIC: return "PT_DYNAMIC";; | |||
749 | LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP )case ELF::PT_INTERP: return "PT_INTERP";; | |||
750 | LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE )case ELF::PT_NOTE: return "PT_NOTE";; | |||
751 | LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB )case ELF::PT_SHLIB: return "PT_SHLIB";; | |||
752 | LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR )case ELF::PT_PHDR: return "PT_PHDR";; | |||
753 | LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS )case ELF::PT_TLS: return "PT_TLS";; | |||
754 | ||||
755 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME)case ELF::PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME";; | |||
756 | LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND)case ELF::PT_SUNW_UNWIND: return "PT_SUNW_UNWIND";; | |||
757 | ||||
758 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK)case ELF::PT_GNU_STACK: return "PT_GNU_STACK";; | |||
759 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO)case ELF::PT_GNU_RELRO: return "PT_GNU_RELRO";; | |||
760 | default: return ""; | |||
761 | } | |||
762 | } | |||
763 | ||||
764 | static const EnumEntry<unsigned> ElfSegmentFlags[] = { | |||
765 | LLVM_READOBJ_ENUM_ENT(ELF, PF_X){ "PF_X", ELF::PF_X }, | |||
766 | LLVM_READOBJ_ENUM_ENT(ELF, PF_W){ "PF_W", ELF::PF_W }, | |||
767 | LLVM_READOBJ_ENUM_ENT(ELF, PF_R){ "PF_R", ELF::PF_R } | |||
768 | }; | |||
769 | ||||
770 | static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { | |||
771 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NOREORDER){ "EF_MIPS_NOREORDER", ELF::EF_MIPS_NOREORDER }, | |||
772 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_PIC){ "EF_MIPS_PIC", ELF::EF_MIPS_PIC }, | |||
773 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC){ "EF_MIPS_CPIC", ELF::EF_MIPS_CPIC }, | |||
774 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2){ "EF_MIPS_ABI2", ELF::EF_MIPS_ABI2 }, | |||
775 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE){ "EF_MIPS_32BITMODE", ELF::EF_MIPS_32BITMODE }, | |||
776 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_FP64){ "EF_MIPS_FP64", ELF::EF_MIPS_FP64 }, | |||
777 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008){ "EF_MIPS_NAN2008", ELF::EF_MIPS_NAN2008 }, | |||
778 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32){ "EF_MIPS_ABI_O32", ELF::EF_MIPS_ABI_O32 }, | |||
779 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O64){ "EF_MIPS_ABI_O64", ELF::EF_MIPS_ABI_O64 }, | |||
780 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI32){ "EF_MIPS_ABI_EABI32", ELF::EF_MIPS_ABI_EABI32 }, | |||
781 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI64){ "EF_MIPS_ABI_EABI64", ELF::EF_MIPS_ABI_EABI64 }, | |||
782 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_3900){ "EF_MIPS_MACH_3900", ELF::EF_MIPS_MACH_3900 }, | |||
783 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4010){ "EF_MIPS_MACH_4010", ELF::EF_MIPS_MACH_4010 }, | |||
784 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4100){ "EF_MIPS_MACH_4100", ELF::EF_MIPS_MACH_4100 }, | |||
785 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4650){ "EF_MIPS_MACH_4650", ELF::EF_MIPS_MACH_4650 }, | |||
786 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4120){ "EF_MIPS_MACH_4120", ELF::EF_MIPS_MACH_4120 }, | |||
787 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4111){ "EF_MIPS_MACH_4111", ELF::EF_MIPS_MACH_4111 }, | |||
788 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_SB1){ "EF_MIPS_MACH_SB1", ELF::EF_MIPS_MACH_SB1 }, | |||
789 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON){ "EF_MIPS_MACH_OCTEON", ELF::EF_MIPS_MACH_OCTEON }, | |||
790 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_XLR){ "EF_MIPS_MACH_XLR", ELF::EF_MIPS_MACH_XLR }, | |||
791 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON2){ "EF_MIPS_MACH_OCTEON2", ELF::EF_MIPS_MACH_OCTEON2 }, | |||
792 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON3){ "EF_MIPS_MACH_OCTEON3", ELF::EF_MIPS_MACH_OCTEON3 }, | |||
793 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5400){ "EF_MIPS_MACH_5400", ELF::EF_MIPS_MACH_5400 }, | |||
794 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5900){ "EF_MIPS_MACH_5900", ELF::EF_MIPS_MACH_5900 }, | |||
795 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5500){ "EF_MIPS_MACH_5500", ELF::EF_MIPS_MACH_5500 }, | |||
796 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_9000){ "EF_MIPS_MACH_9000", ELF::EF_MIPS_MACH_9000 }, | |||
797 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2E){ "EF_MIPS_MACH_LS2E", ELF::EF_MIPS_MACH_LS2E }, | |||
798 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2F){ "EF_MIPS_MACH_LS2F", ELF::EF_MIPS_MACH_LS2F }, | |||
799 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS3A){ "EF_MIPS_MACH_LS3A", ELF::EF_MIPS_MACH_LS3A }, | |||
800 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS){ "EF_MIPS_MICROMIPS", ELF::EF_MIPS_MICROMIPS }, | |||
801 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16){ "EF_MIPS_ARCH_ASE_M16", ELF::EF_MIPS_ARCH_ASE_M16 }, | |||
802 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_MDMX){ "EF_MIPS_ARCH_ASE_MDMX", ELF::EF_MIPS_ARCH_ASE_MDMX }, | |||
803 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1){ "EF_MIPS_ARCH_1", ELF::EF_MIPS_ARCH_1 }, | |||
804 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2){ "EF_MIPS_ARCH_2", ELF::EF_MIPS_ARCH_2 }, | |||
805 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3){ "EF_MIPS_ARCH_3", ELF::EF_MIPS_ARCH_3 }, | |||
806 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_4){ "EF_MIPS_ARCH_4", ELF::EF_MIPS_ARCH_4 }, | |||
807 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_5){ "EF_MIPS_ARCH_5", ELF::EF_MIPS_ARCH_5 }, | |||
808 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32){ "EF_MIPS_ARCH_32", ELF::EF_MIPS_ARCH_32 }, | |||
809 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64){ "EF_MIPS_ARCH_64", ELF::EF_MIPS_ARCH_64 }, | |||
810 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R2){ "EF_MIPS_ARCH_32R2", ELF::EF_MIPS_ARCH_32R2 }, | |||
811 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R2){ "EF_MIPS_ARCH_64R2", ELF::EF_MIPS_ARCH_64R2 }, | |||
812 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R6){ "EF_MIPS_ARCH_32R6", ELF::EF_MIPS_ARCH_32R6 }, | |||
813 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6){ "EF_MIPS_ARCH_64R6", ELF::EF_MIPS_ARCH_64R6 } | |||
814 | }; | |||
815 | ||||
816 | template <typename ELFT> | |||
817 | ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer) | |||
818 | : ObjDumper(Writer), Obj(Obj) { | |||
819 | ||||
820 | SmallVector<const Elf_Phdr *, 4> LoadSegments; | |||
821 | for (const Elf_Phdr &Phdr : Obj->program_headers()) { | |||
822 | if (Phdr.p_type == ELF::PT_DYNAMIC) { | |||
823 | DynamicProgHeader = &Phdr; | |||
824 | continue; | |||
825 | } | |||
826 | if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) | |||
827 | continue; | |||
828 | LoadSegments.push_back(&Phdr); | |||
829 | } | |||
830 | ||||
831 | auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * { | |||
832 | const Elf_Phdr **I = std::upper_bound( | |||
833 | LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>); | |||
834 | if (I == LoadSegments.begin()) | |||
835 | report_fatal_error("Virtual address is not in any segment"); | |||
836 | --I; | |||
837 | const Elf_Phdr &Phdr = **I; | |||
838 | uint64_t Delta = VAddr - Phdr.p_vaddr; | |||
839 | if (Delta >= Phdr.p_filesz) | |||
840 | report_fatal_error("Virtual address is not in any segment"); | |||
841 | return Obj->base() + Phdr.p_offset + Delta; | |||
842 | }; | |||
843 | ||||
844 | uint64_t SONameOffset = 0; | |||
845 | const char *StringTableBegin = nullptr; | |||
846 | uint64_t StringTableSize = 0; | |||
847 | for (const Elf_Dyn &Dyn : dynamic_table()) { | |||
848 | switch (Dyn.d_tag) { | |||
849 | case ELF::DT_HASH: | |||
850 | HashTable = | |||
851 | reinterpret_cast<const Elf_Hash *>(toMappedAddr(Dyn.getPtr())); | |||
852 | break; | |||
853 | case ELF::DT_RELA: | |||
854 | DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr()); | |||
855 | break; | |||
856 | case ELF::DT_RELASZ: | |||
857 | DynRelaRegion.Size = Dyn.getVal(); | |||
858 | break; | |||
859 | case ELF::DT_RELAENT: | |||
860 | DynRelaRegion.EntSize = Dyn.getVal(); | |||
861 | break; | |||
862 | case ELF::DT_SONAME: | |||
863 | SONameOffset = Dyn.getVal(); | |||
864 | break; | |||
865 | case ELF::DT_STRTAB: | |||
866 | StringTableBegin = (const char *)toMappedAddr(Dyn.getPtr()); | |||
867 | break; | |||
868 | case ELF::DT_STRSZ: | |||
869 | StringTableSize = Dyn.getVal(); | |||
870 | break; | |||
871 | case ELF::DT_SYMTAB: | |||
872 | DynSymStart = | |||
873 | reinterpret_cast<const Elf_Sym *>(toMappedAddr(Dyn.getPtr())); | |||
874 | break; | |||
875 | } | |||
876 | } | |||
877 | if (StringTableBegin) | |||
878 | DynamicStringTable = StringRef(StringTableBegin, StringTableSize); | |||
879 | if (SONameOffset) | |||
880 | SOName = getDynamicString(SONameOffset); | |||
881 | ||||
882 | for (const Elf_Shdr &Sec : Obj->sections()) { | |||
883 | switch (Sec.sh_type) { | |||
884 | case ELF::SHT_GNU_versym: | |||
885 | if (dot_gnu_version_sec != nullptr) | |||
886 | reportError("Multiple SHT_GNU_versym"); | |||
887 | dot_gnu_version_sec = &Sec; | |||
888 | break; | |||
889 | case ELF::SHT_GNU_verdef: | |||
890 | if (dot_gnu_version_d_sec != nullptr) | |||
891 | reportError("Multiple SHT_GNU_verdef"); | |||
892 | dot_gnu_version_d_sec = &Sec; | |||
893 | break; | |||
894 | case ELF::SHT_GNU_verneed: | |||
895 | if (dot_gnu_version_r_sec != nullptr) | |||
896 | reportError("Multilpe SHT_GNU_verneed"); | |||
897 | dot_gnu_version_r_sec = &Sec; | |||
898 | break; | |||
899 | case ELF::SHT_DYNSYM: | |||
900 | if (DotDynSymSec != nullptr) | |||
901 | reportError("Multilpe SHT_DYNSYM"); | |||
902 | DotDynSymSec = &Sec; | |||
903 | break; | |||
904 | case ELF::SHT_SYMTAB: | |||
905 | if (DotSymtabSec != nullptr) | |||
906 | reportError("Multilpe SHT_SYMTAB"); | |||
907 | DotSymtabSec = &Sec; | |||
908 | break; | |||
909 | case ELF::SHT_SYMTAB_SHNDX: { | |||
910 | ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec); | |||
911 | error(TableOrErr.getError()); | |||
912 | ShndxTable = *TableOrErr; | |||
913 | break; | |||
914 | } | |||
915 | } | |||
916 | } | |||
917 | } | |||
918 | ||||
919 | template <typename ELFT> | |||
920 | const typename ELFDumper<ELFT>::Elf_Rela * | |||
921 | ELFDumper<ELFT>::dyn_rela_begin() const { | |||
922 | if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela)) | |||
923 | report_fatal_error("Invalid relocation entry size"); | |||
924 | return reinterpret_cast<const Elf_Rela *>(DynRelaRegion.Addr); | |||
925 | } | |||
926 | ||||
927 | template <typename ELFT> | |||
928 | const typename ELFDumper<ELFT>::Elf_Rela * | |||
929 | ELFDumper<ELFT>::dyn_rela_end() const { | |||
930 | uint64_t Size = DynRelaRegion.Size; | |||
931 | if (Size % sizeof(Elf_Rela)) | |||
932 | report_fatal_error("Invalid relocation table size"); | |||
933 | return dyn_rela_begin() + Size / sizeof(Elf_Rela); | |||
934 | } | |||
935 | ||||
936 | template <typename ELFT> | |||
937 | typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const { | |||
938 | return make_range(dyn_rela_begin(), dyn_rela_end()); | |||
939 | } | |||
940 | ||||
941 | template<class ELFT> | |||
942 | void ELFDumper<ELFT>::printFileHeaders() { | |||
943 | const Elf_Ehdr *Header = Obj->getHeader(); | |||
944 | ||||
945 | { | |||
946 | DictScope D(W, "ElfHeader"); | |||
947 | { | |||
948 | DictScope D(W, "Ident"); | |||
949 | W.printBinary("Magic", makeArrayRef(Header->e_ident).slice(ELF::EI_MAG0, | |||
950 | 4)); | |||
951 | W.printEnum ("Class", Header->e_ident[ELF::EI_CLASS], | |||
952 | makeArrayRef(ElfClass)); | |||
953 | W.printEnum ("DataEncoding", Header->e_ident[ELF::EI_DATA], | |||
954 | makeArrayRef(ElfDataEncoding)); | |||
955 | W.printNumber("FileVersion", Header->e_ident[ELF::EI_VERSION]); | |||
956 | ||||
957 | // Handle architecture specific OS/ABI values. | |||
958 | if (Header->e_machine == ELF::EM_AMDGPU && | |||
959 | Header->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA) | |||
960 | W.printHex("OS/ABI", "AMDGPU_HSA", ELF::ELFOSABI_AMDGPU_HSA); | |||
961 | else | |||
962 | W.printEnum ("OS/ABI", Header->e_ident[ELF::EI_OSABI], | |||
963 | makeArrayRef(ElfOSABI)); | |||
964 | W.printNumber("ABIVersion", Header->e_ident[ELF::EI_ABIVERSION]); | |||
965 | W.printBinary("Unused", makeArrayRef(Header->e_ident).slice(ELF::EI_PAD)); | |||
966 | } | |||
967 | ||||
968 | W.printEnum ("Type", Header->e_type, makeArrayRef(ElfObjectFileType)); | |||
969 | W.printEnum ("Machine", Header->e_machine, makeArrayRef(ElfMachineType)); | |||
970 | W.printNumber("Version", Header->e_version); | |||
971 | W.printHex ("Entry", Header->e_entry); | |||
972 | W.printHex ("ProgramHeaderOffset", Header->e_phoff); | |||
973 | W.printHex ("SectionHeaderOffset", Header->e_shoff); | |||
974 | if (Header->e_machine == EM_MIPS) | |||
975 | W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags), | |||
976 | unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), | |||
977 | unsigned(ELF::EF_MIPS_MACH)); | |||
978 | else | |||
979 | W.printFlags("Flags", Header->e_flags); | |||
980 | W.printNumber("HeaderSize", Header->e_ehsize); | |||
981 | W.printNumber("ProgramHeaderEntrySize", Header->e_phentsize); | |||
982 | W.printNumber("ProgramHeaderCount", Header->e_phnum); | |||
983 | W.printNumber("SectionHeaderEntrySize", Header->e_shentsize); | |||
984 | W.printNumber("SectionHeaderCount", Header->e_shnum); | |||
985 | W.printNumber("StringTableSectionIndex", Header->e_shstrndx); | |||
986 | } | |||
987 | } | |||
988 | ||||
989 | template<class ELFT> | |||
990 | void ELFDumper<ELFT>::printSections() { | |||
991 | ListScope SectionsD(W, "Sections"); | |||
992 | ||||
993 | int SectionIndex = -1; | |||
994 | for (const Elf_Shdr &Sec : Obj->sections()) { | |||
995 | ++SectionIndex; | |||
996 | ||||
997 | StringRef Name = errorOrDefault(Obj->getSectionName(&Sec)); | |||
998 | ||||
999 | DictScope SectionD(W, "Section"); | |||
1000 | W.printNumber("Index", SectionIndex); | |||
1001 | W.printNumber("Name", Name, Sec.sh_name); | |||
1002 | W.printHex("Type", | |||
1003 | getElfSectionType(Obj->getHeader()->e_machine, Sec.sh_type), | |||
1004 | Sec.sh_type); | |||
1005 | W.printFlags("Flags", Sec.sh_flags, makeArrayRef(ElfSectionFlags)); | |||
1006 | W.printHex("Address", Sec.sh_addr); | |||
1007 | W.printHex("Offset", Sec.sh_offset); | |||
1008 | W.printNumber("Size", Sec.sh_size); | |||
1009 | W.printNumber("Link", Sec.sh_link); | |||
1010 | W.printNumber("Info", Sec.sh_info); | |||
1011 | W.printNumber("AddressAlignment", Sec.sh_addralign); | |||
1012 | W.printNumber("EntrySize", Sec.sh_entsize); | |||
1013 | ||||
1014 | if (opts::SectionRelocations) { | |||
1015 | ListScope D(W, "Relocations"); | |||
1016 | printRelocations(&Sec); | |||
1017 | } | |||
1018 | ||||
1019 | if (opts::SectionSymbols) { | |||
1020 | ListScope D(W, "Symbols"); | |||
1021 | const Elf_Shdr *Symtab = DotSymtabSec; | |||
1022 | ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab); | |||
1023 | error(StrTableOrErr.getError()); | |||
1024 | StringRef StrTable = *StrTableOrErr; | |||
1025 | ||||
1026 | for (const Elf_Sym &Sym : Obj->symbols(Symtab)) { | |||
1027 | ErrorOr<const Elf_Shdr *> SymSec = | |||
1028 | Obj->getSection(&Sym, Symtab, ShndxTable); | |||
1029 | if (!SymSec) | |||
1030 | continue; | |||
1031 | if (*SymSec == &Sec) | |||
1032 | printSymbol(&Sym, Symtab, StrTable, false); | |||
1033 | } | |||
1034 | } | |||
1035 | ||||
1036 | if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { | |||
1037 | ArrayRef<uint8_t> Data = errorOrDefault(Obj->getSectionContents(&Sec)); | |||
1038 | W.printBinaryBlock("SectionData", | |||
1039 | StringRef((const char *)Data.data(), Data.size())); | |||
1040 | } | |||
1041 | } | |||
1042 | } | |||
1043 | ||||
1044 | template<class ELFT> | |||
1045 | void ELFDumper<ELFT>::printRelocations() { | |||
1046 | ListScope D(W, "Relocations"); | |||
1047 | ||||
1048 | int SectionNumber = -1; | |||
1049 | for (const Elf_Shdr &Sec : Obj->sections()) { | |||
| ||||
1050 | ++SectionNumber; | |||
1051 | ||||
1052 | if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) | |||
1053 | continue; | |||
1054 | ||||
1055 | StringRef Name = errorOrDefault(Obj->getSectionName(&Sec)); | |||
1056 | ||||
1057 | W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; | |||
1058 | W.indent(); | |||
1059 | ||||
1060 | printRelocations(&Sec); | |||
1061 | ||||
1062 | W.unindent(); | |||
1063 | W.startLine() << "}\n"; | |||
1064 | } | |||
1065 | } | |||
1066 | ||||
1067 | template<class ELFT> | |||
1068 | void ELFDumper<ELFT>::printDynamicRelocations() { | |||
1069 | W.startLine() << "Dynamic Relocations {\n"; | |||
1070 | W.indent(); | |||
1071 | for (const Elf_Rela &Rel : dyn_relas()) { | |||
1072 | SmallString<32> RelocName; | |||
1073 | Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); | |||
1074 | StringRef SymbolName; | |||
1075 | uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); | |||
1076 | const Elf_Sym *Sym = DynSymStart + SymIndex; | |||
1077 | SymbolName = errorOrDefault(Sym->getName(DynamicStringTable)); | |||
1078 | if (opts::ExpandRelocs) { | |||
1079 | DictScope Group(W, "Relocation"); | |||
1080 | W.printHex("Offset", Rel.r_offset); | |||
1081 | W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); | |||
1082 | W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); | |||
1083 | W.printHex("Addend", Rel.r_addend); | |||
1084 | } | |||
1085 | else { | |||
1086 | raw_ostream& OS = W.startLine(); | |||
1087 | OS << W.hex(Rel.r_offset) << " " << RelocName << " " | |||
1088 | << (SymbolName.size() > 0 ? SymbolName : "-") << " " | |||
1089 | << W.hex(Rel.r_addend) << "\n"; | |||
1090 | } | |||
1091 | } | |||
1092 | W.unindent(); | |||
1093 | W.startLine() << "}\n"; | |||
1094 | } | |||
1095 | ||||
1096 | template <class ELFT> | |||
1097 | void ELFDumper<ELFT>::printRelocations(const Elf_Shdr *Sec) { | |||
1098 | switch (Sec->sh_type) { | |||
1099 | case ELF::SHT_REL: | |||
1100 | for (const Elf_Rel &R : Obj->rels(Sec)) { | |||
1101 | Elf_Rela Rela; | |||
1102 | Rela.r_offset = R.r_offset; | |||
1103 | Rela.r_info = R.r_info; | |||
1104 | Rela.r_addend = 0; | |||
1105 | printRelocation(Sec, Rela); | |||
1106 | } | |||
1107 | break; | |||
1108 | case ELF::SHT_RELA: | |||
1109 | for (const Elf_Rela &R : Obj->relas(Sec)) | |||
1110 | printRelocation(Sec, R); | |||
1111 | break; | |||
1112 | } | |||
1113 | } | |||
1114 | ||||
1115 | template <class ELFT> | |||
1116 | void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec, Elf_Rela Rel) { | |||
1117 | SmallString<32> RelocName; | |||
1118 | Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); | |||
1119 | StringRef TargetName; | |||
1120 | std::pair<const Elf_Shdr *, const Elf_Sym *> Sym = | |||
1121 | Obj->getRelocationSymbol(Sec, &Rel); | |||
1122 | if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) { | |||
1123 | ErrorOr<const Elf_Shdr *> Sec = | |||
1124 | Obj->getSection(Sym.second, Sym.first, ShndxTable); | |||
1125 | error(Sec.getError()); | |||
1126 | ErrorOr<StringRef> SecName = Obj->getSectionName(*Sec); | |||
1127 | if (SecName) | |||
1128 | TargetName = SecName.get(); | |||
1129 | } else if (Sym.first) { | |||
1130 | const Elf_Shdr *SymTable = Sym.first; | |||
1131 | ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*SymTable); | |||
1132 | error(StrTableOrErr.getError()); | |||
1133 | TargetName = errorOrDefault(Sym.second->getName(*StrTableOrErr)); | |||
| ||||
1134 | } | |||
1135 | ||||
1136 | if (opts::ExpandRelocs) { | |||
1137 | DictScope Group(W, "Relocation"); | |||
1138 | W.printHex("Offset", Rel.r_offset); | |||
1139 | W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); | |||
1140 | W.printNumber("Symbol", TargetName.size() > 0 ? TargetName : "-", | |||
1141 | Rel.getSymbol(Obj->isMips64EL())); | |||
1142 | W.printHex("Addend", Rel.r_addend); | |||
1143 | } else { | |||
1144 | raw_ostream& OS = W.startLine(); | |||
1145 | OS << W.hex(Rel.r_offset) << " " << RelocName << " " | |||
1146 | << (TargetName.size() > 0 ? TargetName : "-") << " " | |||
1147 | << W.hex(Rel.r_addend) << "\n"; | |||
1148 | } | |||
1149 | } | |||
1150 | ||||
1151 | template<class ELFT> | |||
1152 | void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) { | |||
1153 | const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec; | |||
1154 | ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab); | |||
1155 | error(StrTableOrErr.getError()); | |||
1156 | StringRef StrTable = *StrTableOrErr; | |||
1157 | for (const Elf_Sym &Sym : Obj->symbols(Symtab)) | |||
1158 | printSymbol(&Sym, Symtab, StrTable, IsDynamic); | |||
1159 | } | |||
1160 | ||||
1161 | template<class ELFT> | |||
1162 | void ELFDumper<ELFT>::printSymbols() { | |||
1163 | ListScope Group(W, "Symbols"); | |||
1164 | printSymbolsHelper(false); | |||
1165 | } | |||
1166 | ||||
1167 | template<class ELFT> | |||
1168 | void ELFDumper<ELFT>::printDynamicSymbols() { | |||
1169 | ListScope Group(W, "DynamicSymbols"); | |||
1170 | printSymbolsHelper(true); | |||
1171 | } | |||
1172 | ||||
1173 | template <class ELFT> | |||
1174 | void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab, | |||
1175 | StringRef StrTable, bool IsDynamic) { | |||
1176 | unsigned SectionIndex = 0; | |||
1177 | StringRef SectionName; | |||
1178 | getSectionNameIndex(*Obj, Symbol, SymTab, ShndxTable, SectionName, | |||
1179 | SectionIndex); | |||
1180 | std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic); | |||
1181 | unsigned char SymbolType = Symbol->getType(); | |||
1182 | ||||
1183 | DictScope D(W, "Symbol"); | |||
1184 | W.printNumber("Name", FullSymbolName, Symbol->st_name); | |||
1185 | W.printHex ("Value", Symbol->st_value); | |||
1186 | W.printNumber("Size", Symbol->st_size); | |||
1187 | W.printEnum ("Binding", Symbol->getBinding(), | |||
1188 | makeArrayRef(ElfSymbolBindings)); | |||
1189 | if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && | |||
1190 | SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) | |||
1191 | W.printEnum ("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); | |||
1192 | else | |||
1193 | W.printEnum ("Type", SymbolType, makeArrayRef(ElfSymbolTypes)); | |||
1194 | W.printNumber("Other", Symbol->st_other); | |||
1195 | W.printHex("Section", SectionName, SectionIndex); | |||
1196 | } | |||
1197 | ||||
1198 | #define LLVM_READOBJ_TYPE_CASE(name) \ | |||
1199 | case DT_##name: return #name | |||
1200 | ||||
1201 | static const char *getTypeString(uint64_t Type) { | |||
1202 | switch (Type) { | |||
1203 | LLVM_READOBJ_TYPE_CASE(BIND_NOW); | |||
1204 | LLVM_READOBJ_TYPE_CASE(DEBUG); | |||
1205 | LLVM_READOBJ_TYPE_CASE(FINI); | |||
1206 | LLVM_READOBJ_TYPE_CASE(FINI_ARRAY); | |||
1207 | LLVM_READOBJ_TYPE_CASE(FINI_ARRAYSZ); | |||
1208 | LLVM_READOBJ_TYPE_CASE(FLAGS); | |||
1209 | LLVM_READOBJ_TYPE_CASE(FLAGS_1); | |||
1210 | LLVM_READOBJ_TYPE_CASE(HASH); | |||
1211 | LLVM_READOBJ_TYPE_CASE(INIT); | |||
1212 | LLVM_READOBJ_TYPE_CASE(INIT_ARRAY); | |||
1213 | LLVM_READOBJ_TYPE_CASE(INIT_ARRAYSZ); | |||
1214 | LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAY); | |||
1215 | LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAYSZ); | |||
1216 | LLVM_READOBJ_TYPE_CASE(JMPREL); | |||
1217 | LLVM_READOBJ_TYPE_CASE(NEEDED); | |||
1218 | LLVM_READOBJ_TYPE_CASE(NULL__null); | |||
1219 | LLVM_READOBJ_TYPE_CASE(PLTGOT); | |||
1220 | LLVM_READOBJ_TYPE_CASE(PLTREL); | |||
1221 | LLVM_READOBJ_TYPE_CASE(PLTRELSZ); | |||
1222 | LLVM_READOBJ_TYPE_CASE(REL); | |||
1223 | LLVM_READOBJ_TYPE_CASE(RELA); | |||
1224 | LLVM_READOBJ_TYPE_CASE(RELENT); | |||
1225 | LLVM_READOBJ_TYPE_CASE(RELSZ); | |||
1226 | LLVM_READOBJ_TYPE_CASE(RELAENT); | |||
1227 | LLVM_READOBJ_TYPE_CASE(RELASZ); | |||
1228 | LLVM_READOBJ_TYPE_CASE(RPATH); | |||
1229 | LLVM_READOBJ_TYPE_CASE(RUNPATH); | |||
1230 | LLVM_READOBJ_TYPE_CASE(SONAME); | |||
1231 | LLVM_READOBJ_TYPE_CASE(STRSZ); | |||
1232 | LLVM_READOBJ_TYPE_CASE(STRTAB); | |||
1233 | LLVM_READOBJ_TYPE_CASE(SYMBOLIC); | |||
1234 | LLVM_READOBJ_TYPE_CASE(SYMENT); | |||
1235 | LLVM_READOBJ_TYPE_CASE(SYMTAB); | |||
1236 | LLVM_READOBJ_TYPE_CASE(TEXTREL); | |||
1237 | LLVM_READOBJ_TYPE_CASE(VERNEED); | |||
1238 | LLVM_READOBJ_TYPE_CASE(VERNEEDNUM); | |||
1239 | LLVM_READOBJ_TYPE_CASE(VERSYM); | |||
1240 | LLVM_READOBJ_TYPE_CASE(RELCOUNT); | |||
1241 | LLVM_READOBJ_TYPE_CASE(GNU_HASH); | |||
1242 | LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); | |||
1243 | LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP_REL); | |||
1244 | LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); | |||
1245 | LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); | |||
1246 | LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO); | |||
1247 | LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO); | |||
1248 | LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO); | |||
1249 | LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM); | |||
1250 | LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP); | |||
1251 | LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT); | |||
1252 | LLVM_READOBJ_TYPE_CASE(MIPS_OPTIONS); | |||
1253 | default: return "unknown"; | |||
1254 | } | |||
1255 | } | |||
1256 | ||||
1257 | #undef LLVM_READOBJ_TYPE_CASE | |||
1258 | ||||
1259 | #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ | |||
1260 | { #enum, prefix##_##enum } | |||
1261 | ||||
1262 | static const EnumEntry<unsigned> ElfDynamicDTFlags[] = { | |||
1263 | LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), | |||
1264 | LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), | |||
1265 | LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), | |||
1266 | LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), | |||
1267 | LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) | |||
1268 | }; | |||
1269 | ||||
1270 | static const EnumEntry<unsigned> ElfDynamicDTFlags1[] = { | |||
1271 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW), | |||
1272 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL), | |||
1273 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP), | |||
1274 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE), | |||
1275 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR), | |||
1276 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST), | |||
1277 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN), | |||
1278 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN), | |||
1279 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT), | |||
1280 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS), | |||
1281 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE), | |||
1282 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB), | |||
1283 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP), | |||
1284 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT), | |||
1285 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE), | |||
1286 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE), | |||
1287 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT), | |||
1288 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF), | |||
1289 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS), | |||
1290 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR), | |||
1291 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED), | |||
1292 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC), | |||
1293 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE), | |||
1294 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT), | |||
1295 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON) | |||
1296 | }; | |||
1297 | ||||
1298 | static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { | |||
1299 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), | |||
1300 | LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), | |||
1301 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), | |||
1302 | LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), | |||
1303 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), | |||
1304 | LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), | |||
1305 | LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), | |||
1306 | LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), | |||
1307 | LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), | |||
1308 | LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), | |||
1309 | LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), | |||
1310 | LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), | |||
1311 | LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), | |||
1312 | LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), | |||
1313 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), | |||
1314 | LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) | |||
1315 | }; | |||
1316 | ||||
1317 | #undef LLVM_READOBJ_DT_FLAG_ENT | |||
1318 | ||||
1319 | template <typename T, typename TFlag> | |||
1320 | void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { | |||
1321 | typedef EnumEntry<TFlag> FlagEntry; | |||
1322 | typedef SmallVector<FlagEntry, 10> FlagVector; | |||
1323 | FlagVector SetFlags; | |||
1324 | ||||
1325 | for (const auto &Flag : Flags) { | |||
1326 | if (Flag.Value == 0) | |||
1327 | continue; | |||
1328 | ||||
1329 | if ((Value & Flag.Value) == Flag.Value) | |||
1330 | SetFlags.push_back(Flag); | |||
1331 | } | |||
1332 | ||||
1333 | for (const auto &Flag : SetFlags) { | |||
1334 | OS << Flag.Name << " "; | |||
1335 | } | |||
1336 | } | |||
1337 | ||||
1338 | template <class ELFT> | |||
1339 | StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const { | |||
1340 | if (Value >= DynamicStringTable.size()) | |||
1341 | reportError("Invalid dynamic string table reference"); | |||
1342 | return StringRef(DynamicStringTable.data() + Value); | |||
1343 | } | |||
1344 | ||||
1345 | template <class ELFT> | |||
1346 | void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { | |||
1347 | raw_ostream &OS = W.getOStream(); | |||
1348 | switch (Type) { | |||
1349 | case DT_PLTREL: | |||
1350 | if (Value == DT_REL) { | |||
1351 | OS << "REL"; | |||
1352 | break; | |||
1353 | } else if (Value == DT_RELA) { | |||
1354 | OS << "RELA"; | |||
1355 | break; | |||
1356 | } | |||
1357 | // Fallthrough. | |||
1358 | case DT_PLTGOT: | |||
1359 | case DT_HASH: | |||
1360 | case DT_STRTAB: | |||
1361 | case DT_SYMTAB: | |||
1362 | case DT_RELA: | |||
1363 | case DT_INIT: | |||
1364 | case DT_FINI: | |||
1365 | case DT_REL: | |||
1366 | case DT_JMPREL: | |||
1367 | case DT_INIT_ARRAY: | |||
1368 | case DT_FINI_ARRAY: | |||
1369 | case DT_PREINIT_ARRAY: | |||
1370 | case DT_DEBUG: | |||
1371 | case DT_VERNEED: | |||
1372 | case DT_VERSYM: | |||
1373 | case DT_GNU_HASH: | |||
1374 | case DT_NULL: | |||
1375 | case DT_MIPS_BASE_ADDRESS: | |||
1376 | case DT_MIPS_GOTSYM: | |||
1377 | case DT_MIPS_RLD_MAP: | |||
1378 | case DT_MIPS_RLD_MAP_REL: | |||
1379 | case DT_MIPS_PLTGOT: | |||
1380 | case DT_MIPS_OPTIONS: | |||
1381 | OS << format("0x%" PRIX64"l" "X", Value); | |||
1382 | break; | |||
1383 | case DT_RELCOUNT: | |||
1384 | case DT_VERNEEDNUM: | |||
1385 | case DT_MIPS_RLD_VERSION: | |||
1386 | case DT_MIPS_LOCAL_GOTNO: | |||
1387 | case DT_MIPS_SYMTABNO: | |||
1388 | case DT_MIPS_UNREFEXTNO: | |||
1389 | OS << Value; | |||
1390 | break; | |||
1391 | case DT_PLTRELSZ: | |||
1392 | case DT_RELASZ: | |||
1393 | case DT_RELAENT: | |||
1394 | case DT_STRSZ: | |||
1395 | case DT_SYMENT: | |||
1396 | case DT_RELSZ: | |||
1397 | case DT_RELENT: | |||
1398 | case DT_INIT_ARRAYSZ: | |||
1399 | case DT_FINI_ARRAYSZ: | |||
1400 | case DT_PREINIT_ARRAYSZ: | |||
1401 | OS << Value << " (bytes)"; | |||
1402 | break; | |||
1403 | case DT_NEEDED: | |||
1404 | OS << "SharedLibrary (" << getDynamicString(Value) << ")"; | |||
1405 | break; | |||
1406 | case DT_SONAME: | |||
1407 | OS << "LibrarySoname (" << getDynamicString(Value) << ")"; | |||
1408 | break; | |||
1409 | case DT_RPATH: | |||
1410 | case DT_RUNPATH: | |||
1411 | OS << getDynamicString(Value); | |||
1412 | break; | |||
1413 | case DT_MIPS_FLAGS: | |||
1414 | printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS); | |||
1415 | break; | |||
1416 | case DT_FLAGS: | |||
1417 | printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS); | |||
1418 | break; | |||
1419 | case DT_FLAGS_1: | |||
1420 | printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS); | |||
1421 | break; | |||
1422 | default: | |||
1423 | OS << format("0x%" PRIX64"l" "X", Value); | |||
1424 | break; | |||
1425 | } | |||
1426 | } | |||
1427 | ||||
1428 | template<class ELFT> | |||
1429 | void ELFDumper<ELFT>::printUnwindInfo() { | |||
1430 | W.startLine() << "UnwindInfo not implemented.\n"; | |||
1431 | } | |||
1432 | ||||
1433 | namespace { | |||
1434 | template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() { | |||
1435 | const unsigned Machine = Obj->getHeader()->e_machine; | |||
1436 | if (Machine == EM_ARM) { | |||
1437 | ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx( | |||
1438 | W, Obj, DotSymtabSec); | |||
1439 | return Ctx.PrintUnwindInformation(); | |||
1440 | } | |||
1441 | W.startLine() << "UnwindInfo not implemented.\n"; | |||
1442 | } | |||
1443 | } | |||
1444 | ||||
1445 | template<class ELFT> | |||
1446 | void ELFDumper<ELFT>::printDynamicTable() { | |||
1447 | auto I = dynamic_table_begin(); | |||
1448 | auto E = dynamic_table_end(); | |||
1449 | ||||
1450 | if (I == E) | |||
1451 | return; | |||
1452 | ||||
1453 | --E; | |||
1454 | while (I != E && E->getTag() == ELF::DT_NULL) | |||
1455 | --E; | |||
1456 | if (E->getTag() != ELF::DT_NULL) | |||
1457 | ++E; | |||
1458 | ++E; | |||
1459 | ||||
1460 | ptrdiff_t Total = std::distance(I, E); | |||
1461 | if (Total == 0) | |||
1462 | return; | |||
1463 | ||||
1464 | raw_ostream &OS = W.getOStream(); | |||
1465 | W.startLine() << "DynamicSection [ (" << Total << " entries)\n"; | |||
1466 | ||||
1467 | bool Is64 = ELFT::Is64Bits; | |||
1468 | ||||
1469 | W.startLine() | |||
1470 | << " Tag" << (Is64 ? " " : " ") << "Type" | |||
1471 | << " " << "Name/Value\n"; | |||
1472 | while (I != E) { | |||
1473 | const Elf_Dyn &Entry = *I; | |||
1474 | ++I; | |||
1475 | W.startLine() | |||
1476 | << " " | |||
1477 | << format(Is64 ? "0x%016" PRIX64"l" "X" : "0x%08" PRIX64"l" "X", Entry.getTag()) | |||
1478 | << " " << format("%-21s", getTypeString(Entry.getTag())); | |||
1479 | printValue(Entry.getTag(), Entry.getVal()); | |||
1480 | OS << "\n"; | |||
1481 | } | |||
1482 | ||||
1483 | W.startLine() << "]\n"; | |||
1484 | } | |||
1485 | ||||
1486 | template<class ELFT> | |||
1487 | void ELFDumper<ELFT>::printNeededLibraries() { | |||
1488 | ListScope D(W, "NeededLibraries"); | |||
1489 | ||||
1490 | typedef std::vector<StringRef> LibsTy; | |||
1491 | LibsTy Libs; | |||
1492 | ||||
1493 | for (const auto &Entry : dynamic_table()) | |||
1494 | if (Entry.d_tag == ELF::DT_NEEDED) | |||
1495 | Libs.push_back(getDynamicString(Entry.d_un.d_val)); | |||
1496 | ||||
1497 | std::stable_sort(Libs.begin(), Libs.end()); | |||
1498 | ||||
1499 | for (const auto &L : Libs) { | |||
1500 | outs() << " " << L << "\n"; | |||
1501 | } | |||
1502 | } | |||
1503 | ||||
1504 | template<class ELFT> | |||
1505 | void ELFDumper<ELFT>::printProgramHeaders() { | |||
1506 | ListScope L(W, "ProgramHeaders"); | |||
1507 | ||||
1508 | for (const Elf_Phdr &Phdr : Obj->program_headers()) { | |||
1509 | DictScope P(W, "ProgramHeader"); | |||
1510 | W.printHex("Type", | |||
1511 | getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type), | |||
1512 | Phdr.p_type); | |||
1513 | W.printHex("Offset", Phdr.p_offset); | |||
1514 | W.printHex("VirtualAddress", Phdr.p_vaddr); | |||
1515 | W.printHex("PhysicalAddress", Phdr.p_paddr); | |||
1516 | W.printNumber("FileSize", Phdr.p_filesz); | |||
1517 | W.printNumber("MemSize", Phdr.p_memsz); | |||
1518 | W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags)); | |||
1519 | W.printNumber("Alignment", Phdr.p_align); | |||
1520 | } | |||
1521 | } | |||
1522 | ||||
1523 | template <typename ELFT> | |||
1524 | void ELFDumper<ELFT>::printHashTable() { | |||
1525 | DictScope D(W, "HashTable"); | |||
1526 | if (!HashTable) | |||
1527 | return; | |||
1528 | W.printNumber("Num Buckets", HashTable->nbucket); | |||
1529 | W.printNumber("Num Chains", HashTable->nchain); | |||
1530 | W.printList("Buckets", HashTable->buckets()); | |||
1531 | W.printList("Chains", HashTable->chains()); | |||
1532 | } | |||
1533 | ||||
1534 | template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { | |||
1535 | outs() << "LoadName: " << SOName << '\n'; | |||
1536 | } | |||
1537 | ||||
1538 | template <class ELFT> | |||
1539 | void ELFDumper<ELFT>::printAttributes() { | |||
1540 | W.startLine() << "Attributes not implemented.\n"; | |||
1541 | } | |||
1542 | ||||
1543 | namespace { | |||
1544 | template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { | |||
1545 | if (Obj->getHeader()->e_machine != EM_ARM) { | |||
1546 | W.startLine() << "Attributes not implemented.\n"; | |||
1547 | return; | |||
1548 | } | |||
1549 | ||||
1550 | DictScope BA(W, "BuildAttributes"); | |||
1551 | for (const ELFO::Elf_Shdr &Sec : Obj->sections()) { | |||
1552 | if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES) | |||
1553 | continue; | |||
1554 | ||||
1555 | ErrorOr<ArrayRef<uint8_t>> Contents = Obj->getSectionContents(&Sec); | |||
1556 | if (!Contents) | |||
1557 | continue; | |||
1558 | ||||
1559 | if ((*Contents)[0] != ARMBuildAttrs::Format_Version) { | |||
1560 | errs() << "unrecognised FormatVersion: 0x" << utohexstr((*Contents)[0]) | |||
1561 | << '\n'; | |||
1562 | continue; | |||
1563 | } | |||
1564 | ||||
1565 | W.printHex("FormatVersion", (*Contents)[0]); | |||
1566 | if (Contents->size() == 1) | |||
1567 | continue; | |||
1568 | ||||
1569 | ARMAttributeParser(W).Parse(*Contents); | |||
1570 | } | |||
1571 | } | |||
1572 | } | |||
1573 | ||||
1574 | namespace { | |||
1575 | template <class ELFT> class MipsGOTParser { | |||
1576 | public: | |||
1577 | typedef object::ELFFile<ELFT> ELFO; | |||
1578 | typedef typename ELFO::Elf_Shdr Elf_Shdr; | |||
1579 | typedef typename ELFO::Elf_Sym Elf_Sym; | |||
1580 | typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; | |||
1581 | typedef typename ELFO::Elf_Addr GOTEntry; | |||
1582 | typedef typename ELFO::Elf_Rel Elf_Rel; | |||
1583 | typedef typename ELFO::Elf_Rela Elf_Rela; | |||
1584 | ||||
1585 | MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj, | |||
1586 | Elf_Dyn_Range DynTable, StreamWriter &W); | |||
1587 | ||||
1588 | void parseGOT(); | |||
1589 | void parsePLT(); | |||
1590 | ||||
1591 | private: | |||
1592 | ELFDumper<ELFT> *Dumper; | |||
1593 | const ELFO *Obj; | |||
1594 | StreamWriter &W; | |||
1595 | llvm::Optional<uint64_t> DtPltGot; | |||
1596 | llvm::Optional<uint64_t> DtLocalGotNum; | |||
1597 | llvm::Optional<uint64_t> DtGotSym; | |||
1598 | llvm::Optional<uint64_t> DtMipsPltGot; | |||
1599 | llvm::Optional<uint64_t> DtJmpRel; | |||
1600 | ||||
1601 | std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const; | |||
1602 | const GOTEntry *makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum); | |||
1603 | ||||
1604 | void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, | |||
1605 | const GOTEntry *It); | |||
1606 | void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, | |||
1607 | const GOTEntry *It, const Elf_Sym *Sym, | |||
1608 | StringRef StrTable, bool IsDynamic); | |||
1609 | void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt, | |||
1610 | const GOTEntry *It, StringRef Purpose); | |||
1611 | void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt, | |||
1612 | const GOTEntry *It, StringRef StrTable, | |||
1613 | const Elf_Sym *Sym); | |||
1614 | }; | |||
1615 | } | |||
1616 | ||||
1617 | template <class ELFT> | |||
1618 | MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj, | |||
1619 | Elf_Dyn_Range DynTable, StreamWriter &W) | |||
1620 | : Dumper(Dumper), Obj(Obj), W(W) { | |||
1621 | for (const auto &Entry : DynTable) { | |||
1622 | switch (Entry.getTag()) { | |||
1623 | case ELF::DT_PLTGOT: | |||
1624 | DtPltGot = Entry.getVal(); | |||
1625 | break; | |||
1626 | case ELF::DT_MIPS_LOCAL_GOTNO: | |||
1627 | DtLocalGotNum = Entry.getVal(); | |||
1628 | break; | |||
1629 | case ELF::DT_MIPS_GOTSYM: | |||
1630 | DtGotSym = Entry.getVal(); | |||
1631 | break; | |||
1632 | case ELF::DT_MIPS_PLTGOT: | |||
1633 | DtMipsPltGot = Entry.getVal(); | |||
1634 | break; | |||
1635 | case ELF::DT_JMPREL: | |||
1636 | DtJmpRel = Entry.getVal(); | |||
1637 | break; | |||
1638 | } | |||
1639 | } | |||
1640 | } | |||
1641 | ||||
1642 | template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() { | |||
1643 | // See "Global Offset Table" in Chapter 5 in the following document | |||
1644 | // for detailed GOT description. | |||
1645 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | |||
1646 | if (!DtPltGot) { | |||
1647 | W.startLine() << "Cannot find PLTGOT dynamic table tag.\n"; | |||
1648 | return; | |||
1649 | } | |||
1650 | if (!DtLocalGotNum) { | |||
1651 | W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n"; | |||
1652 | return; | |||
1653 | } | |||
1654 | if (!DtGotSym) { | |||
1655 | W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n"; | |||
1656 | return; | |||
1657 | } | |||
1658 | ||||
1659 | const Elf_Shdr *GOTShdr = findSectionByAddress(Obj, *DtPltGot); | |||
1660 | if (!GOTShdr) { | |||
1661 | W.startLine() << "There is no .got section in the file.\n"; | |||
1662 | return; | |||
1663 | } | |||
1664 | ||||
1665 | ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(GOTShdr); | |||
1666 | if (!GOT) { | |||
1667 | W.startLine() << "The .got section is empty.\n"; | |||
1668 | return; | |||
1669 | } | |||
1670 | ||||
1671 | if (*DtLocalGotNum > getGOTTotal(*GOT)) { | |||
1672 | W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n"; | |||
1673 | return; | |||
1674 | } | |||
1675 | ||||
1676 | const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec(); | |||
1677 | ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*DynSymSec); | |||
1678 | error(StrTable.getError()); | |||
1679 | const Elf_Sym *DynSymBegin = Obj->symbol_begin(DynSymSec); | |||
1680 | const Elf_Sym *DynSymEnd = Obj->symbol_end(DynSymSec); | |||
1681 | std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd)); | |||
1682 | ||||
1683 | if (*DtGotSym > DynSymTotal) { | |||
1684 | W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n"; | |||
1685 | return; | |||
1686 | } | |||
1687 | ||||
1688 | std::size_t GlobalGotNum = DynSymTotal - *DtGotSym; | |||
1689 | ||||
1690 | if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) { | |||
1691 | W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n"; | |||
1692 | return; | |||
1693 | } | |||
1694 | ||||
1695 | const GOTEntry *GotBegin = makeGOTIter(*GOT, 0); | |||
1696 | const GOTEntry *GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum); | |||
1697 | const GOTEntry *It = GotBegin; | |||
1698 | ||||
1699 | DictScope GS(W, "Primary GOT"); | |||
1700 | ||||
1701 | W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0); | |||
1702 | { | |||
1703 | ListScope RS(W, "Reserved entries"); | |||
1704 | ||||
1705 | { | |||
1706 | DictScope D(W, "Entry"); | |||
1707 | printGotEntry(GOTShdr->sh_addr, GotBegin, It++); | |||
1708 | W.printString("Purpose", StringRef("Lazy resolver")); | |||
1709 | } | |||
1710 | ||||
1711 | if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) { | |||
1712 | DictScope D(W, "Entry"); | |||
1713 | printGotEntry(GOTShdr->sh_addr, GotBegin, It++); | |||
1714 | W.printString("Purpose", StringRef("Module pointer (GNU extension)")); | |||
1715 | } | |||
1716 | } | |||
1717 | { | |||
1718 | ListScope LS(W, "Local entries"); | |||
1719 | for (; It != GotLocalEnd; ++It) { | |||
1720 | DictScope D(W, "Entry"); | |||
1721 | printGotEntry(GOTShdr->sh_addr, GotBegin, It); | |||
1722 | } | |||
1723 | } | |||
1724 | { | |||
1725 | ListScope GS(W, "Global entries"); | |||
1726 | ||||
1727 | const GOTEntry *GotGlobalEnd = | |||
1728 | makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum); | |||
1729 | const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym; | |||
1730 | for (; It != GotGlobalEnd; ++It) { | |||
1731 | DictScope D(W, "Entry"); | |||
1732 | printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, | |||
1733 | *StrTable, true); | |||
1734 | } | |||
1735 | } | |||
1736 | ||||
1737 | std::size_t SpecGotNum = getGOTTotal(*GOT) - *DtLocalGotNum - GlobalGotNum; | |||
1738 | W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum)); | |||
1739 | } | |||
1740 | ||||
1741 | template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() { | |||
1742 | if (!DtMipsPltGot) { | |||
1743 | W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n"; | |||
1744 | return; | |||
1745 | } | |||
1746 | if (!DtJmpRel) { | |||
1747 | W.startLine() << "Cannot find JMPREL dynamic table tag.\n"; | |||
1748 | return; | |||
1749 | } | |||
1750 | ||||
1751 | const Elf_Shdr *PLTShdr = findSectionByAddress(Obj, *DtMipsPltGot); | |||
1752 | if (!PLTShdr) { | |||
1753 | W.startLine() << "There is no .got.plt section in the file.\n"; | |||
1754 | return; | |||
1755 | } | |||
1756 | ErrorOr<ArrayRef<uint8_t>> PLT = Obj->getSectionContents(PLTShdr); | |||
1757 | if (!PLT) { | |||
1758 | W.startLine() << "The .got.plt section is empty.\n"; | |||
1759 | return; | |||
1760 | } | |||
1761 | ||||
1762 | const Elf_Shdr *PLTRelShdr = findSectionByAddress(Obj, *DtJmpRel); | |||
1763 | if (!PLTShdr) { | |||
1764 | W.startLine() << "There is no .rel.plt section in the file.\n"; | |||
1765 | return; | |||
1766 | } | |||
1767 | ErrorOr<const Elf_Shdr *> SymTableOrErr = | |||
1768 | Obj->getSection(PLTRelShdr->sh_link); | |||
1769 | error(SymTableOrErr.getError()); | |||
1770 | ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(**SymTableOrErr); | |||
1771 | error(StrTable.getError()); | |||
1772 | ||||
1773 | const GOTEntry *PLTBegin = makeGOTIter(*PLT, 0); | |||
1774 | const GOTEntry *PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT)); | |||
1775 | const GOTEntry *It = PLTBegin; | |||
1776 | ||||
1777 | DictScope GS(W, "PLT GOT"); | |||
1778 | { | |||
1779 | ListScope RS(W, "Reserved entries"); | |||
1780 | printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver"); | |||
1781 | if (It != PLTEnd) | |||
1782 | printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer"); | |||
1783 | } | |||
1784 | { | |||
1785 | ListScope GS(W, "Entries"); | |||
1786 | ||||
1787 | switch (PLTRelShdr->sh_type) { | |||
1788 | case ELF::SHT_REL: | |||
1789 | for (const Elf_Rel *RI = Obj->rel_begin(PLTRelShdr), | |||
1790 | *RE = Obj->rel_end(PLTRelShdr); | |||
1791 | RI != RE && It != PLTEnd; ++RI, ++It) { | |||
1792 | const Elf_Sym *Sym = | |||
1793 | Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second; | |||
1794 | printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym); | |||
1795 | } | |||
1796 | break; | |||
1797 | case ELF::SHT_RELA: | |||
1798 | for (const Elf_Rela *RI = Obj->rela_begin(PLTRelShdr), | |||
1799 | *RE = Obj->rela_end(PLTRelShdr); | |||
1800 | RI != RE && It != PLTEnd; ++RI, ++It) { | |||
1801 | const Elf_Sym *Sym = | |||
1802 | Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second; | |||
1803 | printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym); | |||
1804 | } | |||
1805 | break; | |||
1806 | } | |||
1807 | } | |||
1808 | } | |||
1809 | ||||
1810 | template <class ELFT> | |||
1811 | std::size_t MipsGOTParser<ELFT>::getGOTTotal(ArrayRef<uint8_t> GOT) const { | |||
1812 | return GOT.size() / sizeof(GOTEntry); | |||
1813 | } | |||
1814 | ||||
1815 | template <class ELFT> | |||
1816 | const typename MipsGOTParser<ELFT>::GOTEntry * | |||
1817 | MipsGOTParser<ELFT>::makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) { | |||
1818 | const char *Data = reinterpret_cast<const char *>(GOT.data()); | |||
1819 | return reinterpret_cast<const GOTEntry *>(Data + EntryNum * sizeof(GOTEntry)); | |||
1820 | } | |||
1821 | ||||
1822 | template <class ELFT> | |||
1823 | void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, | |||
1824 | const GOTEntry *BeginIt, | |||
1825 | const GOTEntry *It) { | |||
1826 | int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); | |||
1827 | W.printHex("Address", GotAddr + Offset); | |||
1828 | W.printNumber("Access", Offset - 0x7ff0); | |||
1829 | W.printHex("Initial", *It); | |||
1830 | } | |||
1831 | ||||
1832 | template <class ELFT> | |||
1833 | void MipsGOTParser<ELFT>::printGlobalGotEntry( | |||
1834 | uint64_t GotAddr, const GOTEntry *BeginIt, const GOTEntry *It, | |||
1835 | const Elf_Sym *Sym, StringRef StrTable, bool IsDynamic) { | |||
1836 | printGotEntry(GotAddr, BeginIt, It); | |||
1837 | ||||
1838 | W.printHex("Value", Sym->st_value); | |||
1839 | W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); | |||
1840 | ||||
1841 | unsigned SectionIndex = 0; | |||
1842 | StringRef SectionName; | |||
1843 | getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(), | |||
1844 | Dumper->getShndxTable(), SectionName, SectionIndex); | |||
1845 | W.printHex("Section", SectionName, SectionIndex); | |||
1846 | ||||
1847 | std::string FullSymbolName = | |||
1848 | Dumper->getFullSymbolName(Sym, StrTable, IsDynamic); | |||
1849 | W.printNumber("Name", FullSymbolName, Sym->st_name); | |||
1850 | } | |||
1851 | ||||
1852 | template <class ELFT> | |||
1853 | void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, | |||
1854 | const GOTEntry *BeginIt, | |||
1855 | const GOTEntry *It, StringRef Purpose) { | |||
1856 | DictScope D(W, "Entry"); | |||
1857 | int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); | |||
1858 | W.printHex("Address", PLTAddr + Offset); | |||
1859 | W.printHex("Initial", *It); | |||
1860 | W.printString("Purpose", Purpose); | |||
1861 | } | |||
1862 | ||||
1863 | template <class ELFT> | |||
1864 | void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, | |||
1865 | const GOTEntry *BeginIt, | |||
1866 | const GOTEntry *It, StringRef StrTable, | |||
1867 | const Elf_Sym *Sym) { | |||
1868 | DictScope D(W, "Entry"); | |||
1869 | int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); | |||
1870 | W.printHex("Address", PLTAddr + Offset); | |||
1871 | W.printHex("Initial", *It); | |||
1872 | W.printHex("Value", Sym->st_value); | |||
1873 | W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); | |||
1874 | ||||
1875 | unsigned SectionIndex = 0; | |||
1876 | StringRef SectionName; | |||
1877 | getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(), | |||
1878 | Dumper->getShndxTable(), SectionName, SectionIndex); | |||
1879 | W.printHex("Section", SectionName, SectionIndex); | |||
1880 | ||||
1881 | std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true); | |||
1882 | W.printNumber("Name", FullSymbolName, Sym->st_name); | |||
1883 | } | |||
1884 | ||||
1885 | template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { | |||
1886 | if (Obj->getHeader()->e_machine != EM_MIPS) { | |||
1887 | W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n"; | |||
1888 | return; | |||
1889 | } | |||
1890 | ||||
1891 | MipsGOTParser<ELFT> GOTParser(this, Obj, dynamic_table(), W); | |||
1892 | GOTParser.parseGOT(); | |||
1893 | GOTParser.parsePLT(); | |||
1894 | } | |||
1895 | ||||
1896 | static const EnumEntry<unsigned> ElfMipsISAExtType[] = { | |||
1897 | {"None", Mips::AFL_EXT_NONE}, | |||
1898 | {"Broadcom SB-1", Mips::AFL_EXT_SB1}, | |||
1899 | {"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON}, | |||
1900 | {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2}, | |||
1901 | {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP}, | |||
1902 | {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3}, | |||
1903 | {"LSI R4010", Mips::AFL_EXT_4010}, | |||
1904 | {"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E}, | |||
1905 | {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F}, | |||
1906 | {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A}, | |||
1907 | {"MIPS R4650", Mips::AFL_EXT_4650}, | |||
1908 | {"MIPS R5900", Mips::AFL_EXT_5900}, | |||
1909 | {"MIPS R10000", Mips::AFL_EXT_10000}, | |||
1910 | {"NEC VR4100", Mips::AFL_EXT_4100}, | |||
1911 | {"NEC VR4111/VR4181", Mips::AFL_EXT_4111}, | |||
1912 | {"NEC VR4120", Mips::AFL_EXT_4120}, | |||
1913 | {"NEC VR5400", Mips::AFL_EXT_5400}, | |||
1914 | {"NEC VR5500", Mips::AFL_EXT_5500}, | |||
1915 | {"RMI Xlr", Mips::AFL_EXT_XLR}, | |||
1916 | {"Toshiba R3900", Mips::AFL_EXT_3900} | |||
1917 | }; | |||
1918 | ||||
1919 | static const EnumEntry<unsigned> ElfMipsASEFlags[] = { | |||
1920 | {"DSP", Mips::AFL_ASE_DSP}, | |||
1921 | {"DSPR2", Mips::AFL_ASE_DSPR2}, | |||
1922 | {"Enhanced VA Scheme", Mips::AFL_ASE_EVA}, | |||
1923 | {"MCU", Mips::AFL_ASE_MCU}, | |||
1924 | {"MDMX", Mips::AFL_ASE_MDMX}, | |||
1925 | {"MIPS-3D", Mips::AFL_ASE_MIPS3D}, | |||
1926 | {"MT", Mips::AFL_ASE_MT}, | |||
1927 | {"SmartMIPS", Mips::AFL_ASE_SMARTMIPS}, | |||
1928 | {"VZ", Mips::AFL_ASE_VIRT}, | |||
1929 | {"MSA", Mips::AFL_ASE_MSA}, | |||
1930 | {"MIPS16", Mips::AFL_ASE_MIPS16}, | |||
1931 | {"microMIPS", Mips::AFL_ASE_MICROMIPS}, | |||
1932 | {"XPA", Mips::AFL_ASE_XPA} | |||
1933 | }; | |||
1934 | ||||
1935 | static const EnumEntry<unsigned> ElfMipsFpABIType[] = { | |||
1936 | {"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY}, | |||
1937 | {"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE}, | |||
1938 | {"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE}, | |||
1939 | {"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT}, | |||
1940 | {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)", | |||
1941 | Mips::Val_GNU_MIPS_ABI_FP_OLD_64}, | |||
1942 | {"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX}, | |||
1943 | {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64}, | |||
1944 | {"Hard float compat (32-bit CPU, 64-bit FPU)", | |||
1945 | Mips::Val_GNU_MIPS_ABI_FP_64A} | |||
1946 | }; | |||
1947 | ||||
1948 | static const EnumEntry<unsigned> ElfMipsFlags1[] { | |||
1949 | {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG}, | |||
1950 | }; | |||
1951 | ||||
1952 | static int getMipsRegisterSize(uint8_t Flag) { | |||
1953 | switch (Flag) { | |||
1954 | case Mips::AFL_REG_NONE: | |||
1955 | return 0; | |||
1956 | case Mips::AFL_REG_32: | |||
1957 | return 32; | |||
1958 | case Mips::AFL_REG_64: | |||
1959 | return 64; | |||
1960 | case Mips::AFL_REG_128: | |||
1961 | return 128; | |||
1962 | default: | |||
1963 | return -1; | |||
1964 | } | |||
1965 | } | |||
1966 | ||||
1967 | template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() { | |||
1968 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags"); | |||
1969 | if (!Shdr) { | |||
1970 | W.startLine() << "There is no .MIPS.abiflags section in the file.\n"; | |||
1971 | return; | |||
1972 | } | |||
1973 | ErrorOr<ArrayRef<uint8_t>> Sec = Obj->getSectionContents(Shdr); | |||
1974 | if (!Sec) { | |||
1975 | W.startLine() << "The .MIPS.abiflags section is empty.\n"; | |||
1976 | return; | |||
1977 | } | |||
1978 | if (Sec->size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) { | |||
1979 | W.startLine() << "The .MIPS.abiflags section has a wrong size.\n"; | |||
1980 | return; | |||
1981 | } | |||
1982 | ||||
1983 | auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec->data()); | |||
1984 | ||||
1985 | raw_ostream &OS = W.getOStream(); | |||
1986 | DictScope GS(W, "MIPS ABI Flags"); | |||
1987 | ||||
1988 | W.printNumber("Version", Flags->version); | |||
1989 | W.startLine() << "ISA: "; | |||
1990 | if (Flags->isa_rev <= 1) | |||
1991 | OS << format("MIPS%u", Flags->isa_level); | |||
1992 | else | |||
1993 | OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev); | |||
1994 | OS << "\n"; | |||
1995 | W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType)); | |||
1996 | W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags)); | |||
1997 | W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType)); | |||
1998 | W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size)); | |||
1999 | W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size)); | |||
2000 | W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size)); | |||
2001 | W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1)); | |||
2002 | W.printHex("Flags 2", Flags->flags2); | |||
2003 | } | |||
2004 | ||||
2005 | template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() { | |||
2006 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".reginfo"); | |||
2007 | if (!Shdr) { | |||
2008 | W.startLine() << "There is no .reginfo section in the file.\n"; | |||
2009 | return; | |||
2010 | } | |||
2011 | ErrorOr<ArrayRef<uint8_t>> Sec = Obj->getSectionContents(Shdr); | |||
2012 | if (!Sec) { | |||
2013 | W.startLine() << "The .reginfo section is empty.\n"; | |||
2014 | return; | |||
2015 | } | |||
2016 | if (Sec->size() != sizeof(Elf_Mips_RegInfo<ELFT>)) { | |||
2017 | W.startLine() << "The .reginfo section has a wrong size.\n"; | |||
2018 | return; | |||
2019 | } | |||
2020 | ||||
2021 | auto *Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(Sec->data()); | |||
2022 | ||||
2023 | DictScope GS(W, "MIPS RegInfo"); | |||
2024 | W.printHex("GP", Reginfo->ri_gp_value); | |||
2025 | W.printHex("General Mask", Reginfo->ri_gprmask); | |||
2026 | W.printHex("Co-Proc Mask0", Reginfo->ri_cprmask[0]); | |||
2027 | W.printHex("Co-Proc Mask1", Reginfo->ri_cprmask[1]); | |||
2028 | W.printHex("Co-Proc Mask2", Reginfo->ri_cprmask[2]); | |||
2029 | W.printHex("Co-Proc Mask3", Reginfo->ri_cprmask[3]); | |||
2030 | } | |||
2031 | ||||
2032 | template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { | |||
2033 | const Elf_Shdr *StackMapSection = nullptr; | |||
2034 | for (const auto &Sec : Obj->sections()) { | |||
2035 | ErrorOr<StringRef> Name = Obj->getSectionName(&Sec); | |||
2036 | if (*Name == ".llvm_stackmaps") { | |||
2037 | StackMapSection = &Sec; | |||
2038 | break; | |||
2039 | } | |||
2040 | } | |||
2041 | ||||
2042 | if (!StackMapSection) | |||
2043 | return; | |||
2044 | ||||
2045 | StringRef StackMapContents; | |||
2046 | ErrorOr<ArrayRef<uint8_t>> StackMapContentsArray = | |||
2047 | Obj->getSectionContents(StackMapSection); | |||
2048 | ||||
2049 | prettyPrintStackMap( | |||
2050 | llvm::outs(), | |||
2051 | StackMapV1Parser<ELFT::TargetEndianness>(*StackMapContentsArray)); | |||
2052 | } |