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