File: | tools/llvm-readobj/ELFDumper.cpp |
Warning: | line 3180, column 25 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- ELFDumper.cpp - ELF-specific dumper --------------------------------===// | |||
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 | /// This file implements the ELF-specific dumper for llvm-readobj. | |||
12 | /// | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "ARMEHABIPrinter.h" | |||
16 | #include "DwarfCFIEHPrinter.h" | |||
17 | #include "Error.h" | |||
18 | #include "ObjDumper.h" | |||
19 | #include "StackMapPrinter.h" | |||
20 | #include "llvm-readobj.h" | |||
21 | #include "llvm/ADT/ArrayRef.h" | |||
22 | #include "llvm/ADT/DenseMap.h" | |||
23 | #include "llvm/ADT/Optional.h" | |||
24 | #include "llvm/ADT/PointerIntPair.h" | |||
25 | #include "llvm/ADT/SmallString.h" | |||
26 | #include "llvm/ADT/SmallVector.h" | |||
27 | #include "llvm/ADT/STLExtras.h" | |||
28 | #include "llvm/ADT/StringExtras.h" | |||
29 | #include "llvm/ADT/StringRef.h" | |||
30 | #include "llvm/ADT/Twine.h" | |||
31 | #include "llvm/BinaryFormat/ELF.h" | |||
32 | #include "llvm/Object/ELF.h" | |||
33 | #include "llvm/Object/ELFObjectFile.h" | |||
34 | #include "llvm/Object/ELFTypes.h" | |||
35 | #include "llvm/Object/Error.h" | |||
36 | #include "llvm/Object/ObjectFile.h" | |||
37 | #include "llvm/Object/StackMapParser.h" | |||
38 | #include "llvm/Support/AMDGPUMetadata.h" | |||
39 | #include "llvm/Support/ARMAttributeParser.h" | |||
40 | #include "llvm/Support/ARMBuildAttributes.h" | |||
41 | #include "llvm/Support/Casting.h" | |||
42 | #include "llvm/Support/Compiler.h" | |||
43 | #include "llvm/Support/Endian.h" | |||
44 | #include "llvm/Support/ErrorHandling.h" | |||
45 | #include "llvm/Support/Format.h" | |||
46 | #include "llvm/Support/FormattedStream.h" | |||
47 | #include "llvm/Support/LEB128.h" | |||
48 | #include "llvm/Support/MathExtras.h" | |||
49 | #include "llvm/Support/MipsABIFlags.h" | |||
50 | #include "llvm/Support/ScopedPrinter.h" | |||
51 | #include "llvm/Support/raw_ostream.h" | |||
52 | #include <algorithm> | |||
53 | #include <cinttypes> | |||
54 | #include <cstddef> | |||
55 | #include <cstdint> | |||
56 | #include <cstdlib> | |||
57 | #include <iterator> | |||
58 | #include <memory> | |||
59 | #include <string> | |||
60 | #include <system_error> | |||
61 | #include <vector> | |||
62 | ||||
63 | using namespace llvm; | |||
64 | using namespace llvm::object; | |||
65 | using namespace ELF; | |||
66 | ||||
67 | #define LLVM_READOBJ_ENUM_CASE(ns, enum)case ns::enum: return "enum"; \ | |||
68 | case ns::enum: return #enum; | |||
69 | ||||
70 | #define ENUM_ENT(enum, altName){ "enum", altName, ELF::enum } \ | |||
71 | { #enum, altName, ELF::enum } | |||
72 | ||||
73 | #define ENUM_ENT_1(enum){ "enum", "enum", ELF::enum } \ | |||
74 | { #enum, #enum, ELF::enum } | |||
75 | ||||
76 | #define LLVM_READOBJ_PHDR_ENUM(ns, enum)case ns::enum: return std::string("enum").substr(3); \ | |||
77 | case ns::enum: \ | |||
78 | return std::string(#enum).substr(3); | |||
79 | ||||
80 | #define TYPEDEF_ELF_TYPES(ELFT)using ELFO = ELFFile<ELFT>; using Elf_Addr = typename ELFT ::Addr; using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; using Elf_Dyn = typename ELFT::Dyn; using Elf_Dyn_Range = typename ELFT::DynRange; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; using Elf_Relr = typename ELFT::Relr; using Elf_Rel_Range = typename ELFT:: RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr = typename ELFT::Phdr; using Elf_Half = typename ELFT::Half; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Word = typename ELFT::Word; using Elf_Hash = typename ELFT::Hash; using Elf_GnuHash = typename ELFT::GnuHash; using Elf_Note = typename ELFT::Note; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Versym = typename ELFT:: Versym; using Elf_Verneed = typename ELFT::Verneed; using Elf_Vernaux = typename ELFT::Vernaux; using Elf_Verdef = typename ELFT:: Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_CGProfile = typename ELFT::CGProfile; using uintX_t = typename ELFT::uint ; \ | |||
81 | using ELFO = ELFFile<ELFT>; \ | |||
82 | using Elf_Addr = typename ELFT::Addr; \ | |||
83 | using Elf_Shdr = typename ELFT::Shdr; \ | |||
84 | using Elf_Sym = typename ELFT::Sym; \ | |||
85 | using Elf_Dyn = typename ELFT::Dyn; \ | |||
86 | using Elf_Dyn_Range = typename ELFT::DynRange; \ | |||
87 | using Elf_Rel = typename ELFT::Rel; \ | |||
88 | using Elf_Rela = typename ELFT::Rela; \ | |||
89 | using Elf_Relr = typename ELFT::Relr; \ | |||
90 | using Elf_Rel_Range = typename ELFT::RelRange; \ | |||
91 | using Elf_Rela_Range = typename ELFT::RelaRange; \ | |||
92 | using Elf_Relr_Range = typename ELFT::RelrRange; \ | |||
93 | using Elf_Phdr = typename ELFT::Phdr; \ | |||
94 | using Elf_Half = typename ELFT::Half; \ | |||
95 | using Elf_Ehdr = typename ELFT::Ehdr; \ | |||
96 | using Elf_Word = typename ELFT::Word; \ | |||
97 | using Elf_Hash = typename ELFT::Hash; \ | |||
98 | using Elf_GnuHash = typename ELFT::GnuHash; \ | |||
99 | using Elf_Note = typename ELFT::Note; \ | |||
100 | using Elf_Sym_Range = typename ELFT::SymRange; \ | |||
101 | using Elf_Versym = typename ELFT::Versym; \ | |||
102 | using Elf_Verneed = typename ELFT::Verneed; \ | |||
103 | using Elf_Vernaux = typename ELFT::Vernaux; \ | |||
104 | using Elf_Verdef = typename ELFT::Verdef; \ | |||
105 | using Elf_Verdaux = typename ELFT::Verdaux; \ | |||
106 | using Elf_CGProfile = typename ELFT::CGProfile; \ | |||
107 | using uintX_t = typename ELFT::uint; | |||
108 | ||||
109 | namespace { | |||
110 | ||||
111 | template <class ELFT> class DumpStyle; | |||
112 | ||||
113 | /// Represents a contiguous uniform range in the file. We cannot just create a | |||
114 | /// range directly because when creating one of these from the .dynamic table | |||
115 | /// the size, entity size and virtual address are different entries in arbitrary | |||
116 | /// order (DT_REL, DT_RELSZ, DT_RELENT for example). | |||
117 | struct DynRegionInfo { | |||
118 | DynRegionInfo() = default; | |||
119 | DynRegionInfo(const void *A, uint64_t S, uint64_t ES) | |||
120 | : Addr(A), Size(S), EntSize(ES) {} | |||
121 | ||||
122 | /// Address in current address space. | |||
123 | const void *Addr = nullptr; | |||
124 | /// Size in bytes of the region. | |||
125 | uint64_t Size = 0; | |||
126 | /// Size of each entity in the region. | |||
127 | uint64_t EntSize = 0; | |||
128 | ||||
129 | template <typename Type> ArrayRef<Type> getAsArrayRef() const { | |||
130 | const Type *Start = reinterpret_cast<const Type *>(Addr); | |||
131 | if (!Start) | |||
132 | return {Start, Start}; | |||
133 | if (EntSize != sizeof(Type) || Size % EntSize) | |||
134 | reportError("Invalid entity size"); | |||
135 | return {Start, Start + (Size / EntSize)}; | |||
136 | } | |||
137 | }; | |||
138 | ||||
139 | template<typename ELFT> | |||
140 | class ELFDumper : public ObjDumper { | |||
141 | public: | |||
142 | ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer); | |||
143 | ||||
144 | void printFileHeaders() override; | |||
145 | void printSections() override; | |||
146 | void printRelocations() override; | |||
147 | void printDynamicRelocations() override; | |||
148 | void printSymbols() override; | |||
149 | void printDynamicSymbols() override; | |||
150 | void printUnwindInfo() override; | |||
151 | ||||
152 | void printDynamicTable() override; | |||
153 | void printNeededLibraries() override; | |||
154 | void printProgramHeaders() override; | |||
155 | void printHashTable() override; | |||
156 | void printGnuHashTable() override; | |||
157 | void printLoadName() override; | |||
158 | void printVersionInfo() override; | |||
159 | void printGroupSections() override; | |||
160 | ||||
161 | void printAttributes() override; | |||
162 | void printMipsPLTGOT() override; | |||
163 | void printMipsABIFlags() override; | |||
164 | void printMipsReginfo() override; | |||
165 | void printMipsOptions() override; | |||
166 | ||||
167 | void printStackMap() const override; | |||
168 | ||||
169 | void printHashHistogram() override; | |||
170 | ||||
171 | void printCGProfile() override; | |||
172 | void printAddrsig() override; | |||
173 | ||||
174 | void printNotes() override; | |||
175 | ||||
176 | void printELFLinkerOptions() override; | |||
177 | ||||
178 | private: | |||
179 | std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle; | |||
180 | ||||
181 | TYPEDEF_ELF_TYPES(ELFT)using ELFO = ELFFile<ELFT>; using Elf_Addr = typename ELFT ::Addr; using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; using Elf_Dyn = typename ELFT::Dyn; using Elf_Dyn_Range = typename ELFT::DynRange; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; using Elf_Relr = typename ELFT::Relr; using Elf_Rel_Range = typename ELFT:: RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr = typename ELFT::Phdr; using Elf_Half = typename ELFT::Half; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Word = typename ELFT::Word; using Elf_Hash = typename ELFT::Hash; using Elf_GnuHash = typename ELFT::GnuHash; using Elf_Note = typename ELFT::Note; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Versym = typename ELFT:: Versym; using Elf_Verneed = typename ELFT::Verneed; using Elf_Vernaux = typename ELFT::Vernaux; using Elf_Verdef = typename ELFT:: Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_CGProfile = typename ELFT::CGProfile; using uintX_t = typename ELFT::uint ; | |||
182 | ||||
183 | DynRegionInfo checkDRI(DynRegionInfo DRI) { | |||
184 | if (DRI.Addr < Obj->base() || | |||
185 | (const uint8_t *)DRI.Addr + DRI.Size > Obj->base() + Obj->getBufSize()) | |||
186 | error(llvm::object::object_error::parse_failed); | |||
187 | return DRI; | |||
188 | } | |||
189 | ||||
190 | DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) { | |||
191 | return checkDRI({Obj->base() + P->p_offset, P->p_filesz, EntSize}); | |||
192 | } | |||
193 | ||||
194 | DynRegionInfo createDRIFrom(const Elf_Shdr *S) { | |||
195 | return checkDRI({Obj->base() + S->sh_offset, S->sh_size, S->sh_entsize}); | |||
196 | } | |||
197 | ||||
198 | void parseDynamicTable(ArrayRef<const Elf_Phdr *> LoadSegments); | |||
199 | ||||
200 | void printValue(uint64_t Type, uint64_t Value); | |||
201 | ||||
202 | StringRef getDynamicString(uint64_t Offset) const; | |||
203 | StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, | |||
204 | bool &IsDefault) const; | |||
205 | void LoadVersionMap() const; | |||
206 | void LoadVersionNeeds(const Elf_Shdr *ec) const; | |||
207 | void LoadVersionDefs(const Elf_Shdr *sec) const; | |||
208 | ||||
209 | const ELFO *Obj; | |||
210 | DynRegionInfo DynRelRegion; | |||
211 | DynRegionInfo DynRelaRegion; | |||
212 | DynRegionInfo DynRelrRegion; | |||
213 | DynRegionInfo DynPLTRelRegion; | |||
214 | DynRegionInfo DynSymRegion; | |||
215 | DynRegionInfo DynamicTable; | |||
216 | StringRef DynamicStringTable; | |||
217 | StringRef SOName; | |||
218 | const Elf_Hash *HashTable = nullptr; | |||
219 | const Elf_GnuHash *GnuHashTable = nullptr; | |||
220 | const Elf_Shdr *DotSymtabSec = nullptr; | |||
221 | const Elf_Shdr *DotCGProfileSec = nullptr; | |||
222 | const Elf_Shdr *DotAddrsigSec = nullptr; | |||
223 | StringRef DynSymtabName; | |||
224 | ArrayRef<Elf_Word> ShndxTable; | |||
225 | ||||
226 | const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version | |||
227 | const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r | |||
228 | const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d | |||
229 | ||||
230 | // Records for each version index the corresponding Verdef or Vernaux entry. | |||
231 | // This is filled the first time LoadVersionMap() is called. | |||
232 | class VersionMapEntry : public PointerIntPair<const void *, 1> { | |||
233 | public: | |||
234 | // If the integer is 0, this is an Elf_Verdef*. | |||
235 | // If the integer is 1, this is an Elf_Vernaux*. | |||
236 | VersionMapEntry() : PointerIntPair<const void *, 1>(nullptr, 0) {} | |||
237 | VersionMapEntry(const Elf_Verdef *verdef) | |||
238 | : PointerIntPair<const void *, 1>(verdef, 0) {} | |||
239 | VersionMapEntry(const Elf_Vernaux *vernaux) | |||
240 | : PointerIntPair<const void *, 1>(vernaux, 1) {} | |||
241 | ||||
242 | bool isNull() const { return getPointer() == nullptr; } | |||
243 | bool isVerdef() const { return !isNull() && getInt() == 0; } | |||
244 | bool isVernaux() const { return !isNull() && getInt() == 1; } | |||
245 | const Elf_Verdef *getVerdef() const { | |||
246 | return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr; | |||
247 | } | |||
248 | const Elf_Vernaux *getVernaux() const { | |||
249 | return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr; | |||
250 | } | |||
251 | }; | |||
252 | mutable SmallVector<VersionMapEntry, 16> VersionMap; | |||
253 | ||||
254 | public: | |||
255 | Elf_Dyn_Range dynamic_table() const { | |||
256 | return DynamicTable.getAsArrayRef<Elf_Dyn>(); | |||
257 | } | |||
258 | ||||
259 | Elf_Sym_Range dynamic_symbols() const { | |||
260 | return DynSymRegion.getAsArrayRef<Elf_Sym>(); | |||
261 | } | |||
262 | ||||
263 | Elf_Rel_Range dyn_rels() const; | |||
264 | Elf_Rela_Range dyn_relas() const; | |||
265 | Elf_Relr_Range dyn_relrs() const; | |||
266 | std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, | |||
267 | bool IsDynamic) const; | |||
268 | void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, | |||
269 | StringRef &SectionName, | |||
270 | unsigned &SectionIndex) const; | |||
271 | StringRef getStaticSymbolName(uint32_t Index) const; | |||
272 | ||||
273 | void printSymbolsHelper(bool IsDynamic) const; | |||
274 | const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } | |||
275 | const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } | |||
276 | const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; } | |||
277 | ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; } | |||
278 | StringRef getDynamicStringTable() const { return DynamicStringTable; } | |||
279 | const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } | |||
280 | const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; } | |||
281 | const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; } | |||
282 | const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; } | |||
283 | const Elf_Hash *getHashTable() const { return HashTable; } | |||
284 | const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; } | |||
285 | }; | |||
286 | ||||
287 | template <class ELFT> | |||
288 | void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const { | |||
289 | StringRef StrTable, SymtabName; | |||
290 | size_t Entries = 0; | |||
291 | Elf_Sym_Range Syms(nullptr, nullptr); | |||
292 | if (IsDynamic) { | |||
293 | StrTable = DynamicStringTable; | |||
294 | Syms = dynamic_symbols(); | |||
295 | SymtabName = DynSymtabName; | |||
296 | if (DynSymRegion.Addr) | |||
297 | Entries = DynSymRegion.Size / DynSymRegion.EntSize; | |||
298 | } else { | |||
299 | if (!DotSymtabSec) | |||
300 | return; | |||
301 | StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); | |||
302 | Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); | |||
303 | SymtabName = unwrapOrError(Obj->getSectionName(DotSymtabSec)); | |||
304 | Entries = DotSymtabSec->getEntityCount(); | |||
305 | } | |||
306 | if (Syms.begin() == Syms.end()) | |||
307 | return; | |||
308 | ELFDumperStyle->printSymtabMessage(Obj, SymtabName, Entries); | |||
309 | for (const auto &Sym : Syms) | |||
310 | ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic); | |||
311 | } | |||
312 | ||||
313 | template <class ELFT> class MipsGOTParser; | |||
314 | ||||
315 | template <typename ELFT> class DumpStyle { | |||
316 | public: | |||
317 | using Elf_Shdr = typename ELFT::Shdr; | |||
318 | using Elf_Sym = typename ELFT::Sym; | |||
319 | ||||
320 | DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {} | |||
321 | virtual ~DumpStyle() = default; | |||
322 | ||||
323 | virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0; | |||
324 | virtual void printGroupSections(const ELFFile<ELFT> *Obj) = 0; | |||
325 | virtual void printRelocations(const ELFFile<ELFT> *Obj) = 0; | |||
326 | virtual void printSections(const ELFFile<ELFT> *Obj) = 0; | |||
327 | virtual void printSymbols(const ELFFile<ELFT> *Obj) = 0; | |||
328 | virtual void printDynamicSymbols(const ELFFile<ELFT> *Obj) = 0; | |||
329 | virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0; | |||
330 | virtual void printSymtabMessage(const ELFFile<ELFT> *obj, StringRef Name, | |||
331 | size_t Offset) {} | |||
332 | virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol, | |||
333 | const Elf_Sym *FirstSym, StringRef StrTable, | |||
334 | bool IsDynamic) = 0; | |||
335 | virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0; | |||
336 | virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0; | |||
337 | virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0; | |||
338 | virtual void printAddrsig(const ELFFile<ELFT> *Obj) = 0; | |||
339 | virtual void printNotes(const ELFFile<ELFT> *Obj) = 0; | |||
340 | virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0; | |||
341 | virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0; | |||
342 | virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0; | |||
343 | const ELFDumper<ELFT> *dumper() const { return Dumper; } | |||
344 | ||||
345 | private: | |||
346 | const ELFDumper<ELFT> *Dumper; | |||
347 | }; | |||
348 | ||||
349 | template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> { | |||
350 | formatted_raw_ostream OS; | |||
351 | ||||
352 | public: | |||
353 | TYPEDEF_ELF_TYPES(ELFT)using ELFO = ELFFile<ELFT>; using Elf_Addr = typename ELFT ::Addr; using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; using Elf_Dyn = typename ELFT::Dyn; using Elf_Dyn_Range = typename ELFT::DynRange; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; using Elf_Relr = typename ELFT::Relr; using Elf_Rel_Range = typename ELFT:: RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr = typename ELFT::Phdr; using Elf_Half = typename ELFT::Half; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Word = typename ELFT::Word; using Elf_Hash = typename ELFT::Hash; using Elf_GnuHash = typename ELFT::GnuHash; using Elf_Note = typename ELFT::Note; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Versym = typename ELFT:: Versym; using Elf_Verneed = typename ELFT::Verneed; using Elf_Vernaux = typename ELFT::Vernaux; using Elf_Verdef = typename ELFT:: Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_CGProfile = typename ELFT::CGProfile; using uintX_t = typename ELFT::uint ; | |||
354 | ||||
355 | GNUStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) | |||
356 | : DumpStyle<ELFT>(Dumper), OS(W.getOStream()) {} | |||
357 | ||||
358 | void printFileHeaders(const ELFO *Obj) override; | |||
359 | void printGroupSections(const ELFFile<ELFT> *Obj) override; | |||
360 | void printRelocations(const ELFO *Obj) override; | |||
361 | void printSections(const ELFO *Obj) override; | |||
362 | void printSymbols(const ELFO *Obj) override; | |||
363 | void printDynamicSymbols(const ELFO *Obj) override; | |||
364 | void printDynamicRelocations(const ELFO *Obj) override; | |||
365 | void printSymtabMessage(const ELFO *Obj, StringRef Name, | |||
366 | size_t Offset) override; | |||
367 | void printProgramHeaders(const ELFO *Obj) override; | |||
368 | void printHashHistogram(const ELFFile<ELFT> *Obj) override; | |||
369 | void printCGProfile(const ELFFile<ELFT> *Obj) override; | |||
370 | void printAddrsig(const ELFFile<ELFT> *Obj) override; | |||
371 | void printNotes(const ELFFile<ELFT> *Obj) override; | |||
372 | void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; | |||
373 | void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; | |||
374 | void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; | |||
375 | ||||
376 | private: | |||
377 | struct Field { | |||
378 | StringRef Str; | |||
379 | unsigned Column; | |||
380 | ||||
381 | Field(StringRef S, unsigned Col) : Str(S), Column(Col) {} | |||
382 | Field(unsigned Col) : Str(""), Column(Col) {} | |||
383 | }; | |||
384 | ||||
385 | template <typename T, typename TEnum> | |||
386 | std::string printEnum(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) { | |||
387 | for (const auto &EnumItem : EnumValues) | |||
388 | if (EnumItem.Value == Value) | |||
389 | return EnumItem.AltName; | |||
390 | return to_hexString(Value, false); | |||
391 | } | |||
392 | ||||
393 | template <typename T, typename TEnum> | |||
394 | std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues, | |||
395 | TEnum EnumMask1 = {}, TEnum EnumMask2 = {}, | |||
396 | TEnum EnumMask3 = {}) { | |||
397 | std::string Str; | |||
398 | for (const auto &Flag : EnumValues) { | |||
399 | if (Flag.Value == 0) | |||
400 | continue; | |||
401 | ||||
402 | TEnum EnumMask{}; | |||
403 | if (Flag.Value & EnumMask1) | |||
404 | EnumMask = EnumMask1; | |||
405 | else if (Flag.Value & EnumMask2) | |||
406 | EnumMask = EnumMask2; | |||
407 | else if (Flag.Value & EnumMask3) | |||
408 | EnumMask = EnumMask3; | |||
409 | bool IsEnum = (Flag.Value & EnumMask) != 0; | |||
410 | if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || | |||
411 | (IsEnum && (Value & EnumMask) == Flag.Value)) { | |||
412 | if (!Str.empty()) | |||
413 | Str += ", "; | |||
414 | Str += Flag.AltName; | |||
415 | } | |||
416 | } | |||
417 | return Str; | |||
418 | } | |||
419 | ||||
420 | formatted_raw_ostream &printField(struct Field F) { | |||
421 | if (F.Column != 0) | |||
422 | OS.PadToColumn(F.Column); | |||
423 | OS << F.Str; | |||
424 | OS.flush(); | |||
425 | return OS; | |||
426 | } | |||
427 | void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym, | |||
428 | StringRef StrTable, uint32_t Bucket); | |||
429 | void printRelocHeader(unsigned SType); | |||
430 | void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, | |||
431 | const Elf_Rela &R, bool IsRela); | |||
432 | void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, | |||
433 | StringRef StrTable, bool IsDynamic) override; | |||
434 | std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol, | |||
435 | const Elf_Sym *FirstSym); | |||
436 | void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela); | |||
437 | bool checkTLSSections(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | |||
438 | bool checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | |||
439 | bool checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | |||
440 | bool checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | |||
441 | }; | |||
442 | ||||
443 | template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> { | |||
444 | public: | |||
445 | TYPEDEF_ELF_TYPES(ELFT)using ELFO = ELFFile<ELFT>; using Elf_Addr = typename ELFT ::Addr; using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; using Elf_Dyn = typename ELFT::Dyn; using Elf_Dyn_Range = typename ELFT::DynRange; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; using Elf_Relr = typename ELFT::Relr; using Elf_Rel_Range = typename ELFT:: RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr = typename ELFT::Phdr; using Elf_Half = typename ELFT::Half; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Word = typename ELFT::Word; using Elf_Hash = typename ELFT::Hash; using Elf_GnuHash = typename ELFT::GnuHash; using Elf_Note = typename ELFT::Note; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Versym = typename ELFT:: Versym; using Elf_Verneed = typename ELFT::Verneed; using Elf_Vernaux = typename ELFT::Vernaux; using Elf_Verdef = typename ELFT:: Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_CGProfile = typename ELFT::CGProfile; using uintX_t = typename ELFT::uint ; | |||
446 | ||||
447 | LLVMStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) | |||
448 | : DumpStyle<ELFT>(Dumper), W(W) {} | |||
449 | ||||
450 | void printFileHeaders(const ELFO *Obj) override; | |||
451 | void printGroupSections(const ELFFile<ELFT> *Obj) override; | |||
452 | void printRelocations(const ELFO *Obj) override; | |||
453 | void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj); | |||
454 | void printSections(const ELFO *Obj) override; | |||
455 | void printSymbols(const ELFO *Obj) override; | |||
456 | void printDynamicSymbols(const ELFO *Obj) override; | |||
457 | void printDynamicRelocations(const ELFO *Obj) override; | |||
458 | void printProgramHeaders(const ELFO *Obj) override; | |||
459 | void printHashHistogram(const ELFFile<ELFT> *Obj) override; | |||
460 | void printCGProfile(const ELFFile<ELFT> *Obj) override; | |||
461 | void printAddrsig(const ELFFile<ELFT> *Obj) override; | |||
462 | void printNotes(const ELFFile<ELFT> *Obj) override; | |||
463 | void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; | |||
464 | void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; | |||
465 | void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; | |||
466 | ||||
467 | private: | |||
468 | void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab); | |||
469 | void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); | |||
470 | void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, | |||
471 | StringRef StrTable, bool IsDynamic) override; | |||
472 | ||||
473 | ScopedPrinter &W; | |||
474 | }; | |||
475 | ||||
476 | } // end anonymous namespace | |||
477 | ||||
478 | namespace llvm { | |||
479 | ||||
480 | template <class ELFT> | |||
481 | static std::error_code createELFDumper(const ELFFile<ELFT> *Obj, | |||
482 | ScopedPrinter &Writer, | |||
483 | std::unique_ptr<ObjDumper> &Result) { | |||
484 | Result.reset(new ELFDumper<ELFT>(Obj, Writer)); | |||
485 | return readobj_error::success; | |||
486 | } | |||
487 | ||||
488 | std::error_code createELFDumper(const object::ObjectFile *Obj, | |||
489 | ScopedPrinter &Writer, | |||
490 | std::unique_ptr<ObjDumper> &Result) { | |||
491 | // Little-endian 32-bit | |||
492 | if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) | |||
493 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
494 | ||||
495 | // Big-endian 32-bit | |||
496 | if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) | |||
497 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
498 | ||||
499 | // Little-endian 64-bit | |||
500 | if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) | |||
501 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
502 | ||||
503 | // Big-endian 64-bit | |||
504 | if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) | |||
505 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | |||
506 | ||||
507 | return readobj_error::unsupported_obj_file_format; | |||
508 | } | |||
509 | ||||
510 | } // end namespace llvm | |||
511 | ||||
512 | // Iterate through the versions needed section, and place each Elf_Vernaux | |||
513 | // in the VersionMap according to its index. | |||
514 | template <class ELFT> | |||
515 | void ELFDumper<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { | |||
516 | unsigned vn_size = sec->sh_size; // Size of section in bytes | |||
517 | unsigned vn_count = sec->sh_info; // Number of Verneed entries | |||
518 | const char *sec_start = (const char *)Obj->base() + sec->sh_offset; | |||
519 | const char *sec_end = sec_start + vn_size; | |||
520 | // The first Verneed entry is at the start of the section. | |||
521 | const char *p = sec_start; | |||
522 | for (unsigned i = 0; i < vn_count; i++) { | |||
523 | if (p + sizeof(Elf_Verneed) > sec_end) | |||
524 | report_fatal_error("Section ended unexpectedly while scanning " | |||
525 | "version needed records."); | |||
526 | const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p); | |||
527 | if (vn->vn_version != ELF::VER_NEED_CURRENT) | |||
528 | report_fatal_error("Unexpected verneed version"); | |||
529 | // Iterate through the Vernaux entries | |||
530 | const char *paux = p + vn->vn_aux; | |||
531 | for (unsigned j = 0; j < vn->vn_cnt; j++) { | |||
532 | if (paux + sizeof(Elf_Vernaux) > sec_end) | |||
533 | report_fatal_error("Section ended unexpected while scanning auxiliary " | |||
534 | "version needed records."); | |||
535 | const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux); | |||
536 | size_t index = vna->vna_other & ELF::VERSYM_VERSION; | |||
537 | if (index >= VersionMap.size()) | |||
538 | VersionMap.resize(index + 1); | |||
539 | VersionMap[index] = VersionMapEntry(vna); | |||
540 | paux += vna->vna_next; | |||
541 | } | |||
542 | p += vn->vn_next; | |||
543 | } | |||
544 | } | |||
545 | ||||
546 | // Iterate through the version definitions, and place each Elf_Verdef | |||
547 | // in the VersionMap according to its index. | |||
548 | template <class ELFT> | |||
549 | void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { | |||
550 | unsigned vd_size = sec->sh_size; // Size of section in bytes | |||
551 | unsigned vd_count = sec->sh_info; // Number of Verdef entries | |||
552 | const char *sec_start = (const char *)Obj->base() + sec->sh_offset; | |||
553 | const char *sec_end = sec_start + vd_size; | |||
554 | // The first Verdef entry is at the start of the section. | |||
555 | const char *p = sec_start; | |||
556 | for (unsigned i = 0; i < vd_count; i++) { | |||
557 | if (p + sizeof(Elf_Verdef) > sec_end) | |||
558 | report_fatal_error("Section ended unexpectedly while scanning " | |||
559 | "version definitions."); | |||
560 | const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p); | |||
561 | if (vd->vd_version != ELF::VER_DEF_CURRENT) | |||
562 | report_fatal_error("Unexpected verdef version"); | |||
563 | size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; | |||
564 | if (index >= VersionMap.size()) | |||
565 | VersionMap.resize(index + 1); | |||
566 | VersionMap[index] = VersionMapEntry(vd); | |||
567 | p += vd->vd_next; | |||
568 | } | |||
569 | } | |||
570 | ||||
571 | template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() const { | |||
572 | // If there is no dynamic symtab or version table, there is nothing to do. | |||
573 | if (!DynSymRegion.Addr || !dot_gnu_version_sec) | |||
574 | return; | |||
575 | ||||
576 | // Has the VersionMap already been loaded? | |||
577 | if (VersionMap.size() > 0) | |||
578 | return; | |||
579 | ||||
580 | // The first two version indexes are reserved. | |||
581 | // Index 0 is LOCAL, index 1 is GLOBAL. | |||
582 | VersionMap.push_back(VersionMapEntry()); | |||
583 | VersionMap.push_back(VersionMapEntry()); | |||
584 | ||||
585 | if (dot_gnu_version_d_sec) | |||
586 | LoadVersionDefs(dot_gnu_version_d_sec); | |||
587 | ||||
588 | if (dot_gnu_version_r_sec) | |||
589 | LoadVersionNeeds(dot_gnu_version_r_sec); | |||
590 | } | |||
591 | ||||
592 | template <typename ELFO, class ELFT> | |||
593 | static void printVersionSymbolSection(ELFDumper<ELFT> *Dumper, const ELFO *Obj, | |||
594 | const typename ELFO::Elf_Shdr *Sec, | |||
595 | ScopedPrinter &W) { | |||
596 | DictScope SS(W, "Version symbols"); | |||
597 | if (!Sec) | |||
598 | return; | |||
599 | StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); | |||
600 | W.printNumber("Section Name", Name, Sec->sh_name); | |||
601 | W.printHex("Address", Sec->sh_addr); | |||
602 | W.printHex("Offset", Sec->sh_offset); | |||
603 | W.printNumber("Link", Sec->sh_link); | |||
604 | ||||
605 | const uint8_t *P = (const uint8_t *)Obj->base() + Sec->sh_offset; | |||
606 | StringRef StrTable = Dumper->getDynamicStringTable(); | |||
607 | ||||
608 | // Same number of entries in the dynamic symbol table (DT_SYMTAB). | |||
609 | ListScope Syms(W, "Symbols"); | |||
610 | for (const typename ELFO::Elf_Sym &Sym : Dumper->dynamic_symbols()) { | |||
611 | DictScope S(W, "Symbol"); | |||
612 | std::string FullSymbolName = | |||
613 | Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */); | |||
614 | W.printNumber("Version", *P); | |||
615 | W.printString("Name", FullSymbolName); | |||
616 | P += sizeof(typename ELFO::Elf_Half); | |||
617 | } | |||
618 | } | |||
619 | ||||
620 | static const EnumEntry<unsigned> SymVersionFlags[] = { | |||
621 | {"Base", "BASE", VER_FLG_BASE}, | |||
622 | {"Weak", "WEAK", VER_FLG_WEAK}, | |||
623 | {"Info", "INFO", VER_FLG_INFO}}; | |||
624 | ||||
625 | template <typename ELFO, class ELFT> | |||
626 | static void printVersionDefinitionSection(ELFDumper<ELFT> *Dumper, | |||
627 | const ELFO *Obj, | |||
628 | const typename ELFO::Elf_Shdr *Sec, | |||
629 | ScopedPrinter &W) { | |||
630 | using VerDef = typename ELFO::Elf_Verdef; | |||
631 | using VerdAux = typename ELFO::Elf_Verdaux; | |||
632 | ||||
633 | DictScope SD(W, "SHT_GNU_verdef"); | |||
634 | if (!Sec) | |||
635 | return; | |||
636 | ||||
637 | // The number of entries in the section SHT_GNU_verdef | |||
638 | // is determined by DT_VERDEFNUM tag. | |||
639 | unsigned VerDefsNum = 0; | |||
640 | for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) { | |||
641 | if (Dyn.d_tag == DT_VERDEFNUM) | |||
642 | VerDefsNum = Dyn.d_un.d_val; | |||
643 | } | |||
644 | const uint8_t *SecStartAddress = | |||
645 | (const uint8_t *)Obj->base() + Sec->sh_offset; | |||
646 | const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size; | |||
647 | const uint8_t *P = SecStartAddress; | |||
648 | const typename ELFO::Elf_Shdr *StrTab = | |||
649 | unwrapOrError(Obj->getSection(Sec->sh_link)); | |||
650 | ||||
651 | while (VerDefsNum--) { | |||
652 | if (P + sizeof(VerDef) > SecEndAddress) | |||
653 | report_fatal_error("invalid offset in the section"); | |||
654 | ||||
655 | auto *VD = reinterpret_cast<const VerDef *>(P); | |||
656 | DictScope Def(W, "Definition"); | |||
657 | W.printNumber("Version", VD->vd_version); | |||
658 | W.printEnum("Flags", VD->vd_flags, makeArrayRef(SymVersionFlags)); | |||
659 | W.printNumber("Index", VD->vd_ndx); | |||
660 | W.printNumber("Hash", VD->vd_hash); | |||
661 | W.printString("Name", | |||
662 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | |||
663 | VD->getAux()->vda_name))); | |||
664 | if (!VD->vd_cnt) | |||
665 | report_fatal_error("at least one definition string must exist"); | |||
666 | if (VD->vd_cnt > 2) | |||
667 | report_fatal_error("more than one predecessor is not expected"); | |||
668 | ||||
669 | if (VD->vd_cnt == 2) { | |||
670 | const uint8_t *PAux = P + VD->vd_aux + VD->getAux()->vda_next; | |||
671 | const VerdAux *Aux = reinterpret_cast<const VerdAux *>(PAux); | |||
672 | W.printString("Predecessor", | |||
673 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | |||
674 | Aux->vda_name))); | |||
675 | } | |||
676 | ||||
677 | P += VD->vd_next; | |||
678 | } | |||
679 | } | |||
680 | ||||
681 | template <typename ELFO, class ELFT> | |||
682 | static void printVersionDependencySection(ELFDumper<ELFT> *Dumper, | |||
683 | const ELFO *Obj, | |||
684 | const typename ELFO::Elf_Shdr *Sec, | |||
685 | ScopedPrinter &W) { | |||
686 | using VerNeed = typename ELFO::Elf_Verneed; | |||
687 | using VernAux = typename ELFO::Elf_Vernaux; | |||
688 | ||||
689 | DictScope SD(W, "SHT_GNU_verneed"); | |||
690 | if (!Sec) | |||
691 | return; | |||
692 | ||||
693 | unsigned VerNeedNum = 0; | |||
694 | for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) | |||
695 | if (Dyn.d_tag == DT_VERNEEDNUM) | |||
696 | VerNeedNum = Dyn.d_un.d_val; | |||
697 | ||||
698 | const uint8_t *SecData = (const uint8_t *)Obj->base() + Sec->sh_offset; | |||
699 | const typename ELFO::Elf_Shdr *StrTab = | |||
700 | unwrapOrError(Obj->getSection(Sec->sh_link)); | |||
701 | ||||
702 | const uint8_t *P = SecData; | |||
703 | for (unsigned I = 0; I < VerNeedNum; ++I) { | |||
704 | const VerNeed *Need = reinterpret_cast<const VerNeed *>(P); | |||
705 | DictScope Entry(W, "Dependency"); | |||
706 | W.printNumber("Version", Need->vn_version); | |||
707 | W.printNumber("Count", Need->vn_cnt); | |||
708 | W.printString("FileName", | |||
709 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | |||
710 | Need->vn_file))); | |||
711 | ||||
712 | const uint8_t *PAux = P + Need->vn_aux; | |||
713 | for (unsigned J = 0; J < Need->vn_cnt; ++J) { | |||
714 | const VernAux *Aux = reinterpret_cast<const VernAux *>(PAux); | |||
715 | DictScope Entry(W, "Entry"); | |||
716 | W.printNumber("Hash", Aux->vna_hash); | |||
717 | W.printEnum("Flags", Aux->vna_flags, makeArrayRef(SymVersionFlags)); | |||
718 | W.printNumber("Index", Aux->vna_other); | |||
719 | W.printString("Name", | |||
720 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | |||
721 | Aux->vna_name))); | |||
722 | PAux += Aux->vna_next; | |||
723 | } | |||
724 | P += Need->vn_next; | |||
725 | } | |||
726 | } | |||
727 | ||||
728 | template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() { | |||
729 | // Dump version symbol section. | |||
730 | printVersionSymbolSection(this, Obj, dot_gnu_version_sec, W); | |||
731 | ||||
732 | // Dump version definition section. | |||
733 | printVersionDefinitionSection(this, Obj, dot_gnu_version_d_sec, W); | |||
734 | ||||
735 | // Dump version dependency section. | |||
736 | printVersionDependencySection(this, Obj, dot_gnu_version_r_sec, W); | |||
737 | } | |||
738 | ||||
739 | template <typename ELFT> | |||
740 | StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab, | |||
741 | const Elf_Sym *symb, | |||
742 | bool &IsDefault) const { | |||
743 | // This is a dynamic symbol. Look in the GNU symbol version table. | |||
744 | if (!dot_gnu_version_sec) { | |||
745 | // No version table. | |||
746 | IsDefault = false; | |||
747 | return StringRef(""); | |||
748 | } | |||
749 | ||||
750 | // Determine the position in the symbol table of this entry. | |||
751 | size_t entry_index = (reinterpret_cast<uintptr_t>(symb) - | |||
752 | reinterpret_cast<uintptr_t>(DynSymRegion.Addr)) / | |||
753 | sizeof(Elf_Sym); | |||
754 | ||||
755 | // Get the corresponding version index entry | |||
756 | const Elf_Versym *vs = unwrapOrError( | |||
757 | Obj->template getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index)); | |||
758 | size_t version_index = vs->vs_index & ELF::VERSYM_VERSION; | |||
759 | ||||
760 | // Special markers for unversioned symbols. | |||
761 | if (version_index == ELF::VER_NDX_LOCAL || | |||
762 | version_index == ELF::VER_NDX_GLOBAL) { | |||
763 | IsDefault = false; | |||
764 | return StringRef(""); | |||
765 | } | |||
766 | ||||
767 | // Lookup this symbol in the version table | |||
768 | LoadVersionMap(); | |||
769 | if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) | |||
770 | reportError("Invalid version entry"); | |||
771 | const VersionMapEntry &entry = VersionMap[version_index]; | |||
772 | ||||
773 | // Get the version name string | |||
774 | size_t name_offset; | |||
775 | if (entry.isVerdef()) { | |||
776 | // The first Verdaux entry holds the name. | |||
777 | name_offset = entry.getVerdef()->getAux()->vda_name; | |||
778 | IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN); | |||
779 | } else { | |||
780 | name_offset = entry.getVernaux()->vna_name; | |||
781 | IsDefault = false; | |||
782 | } | |||
783 | if (name_offset >= StrTab.size()) | |||
784 | reportError("Invalid string offset"); | |||
785 | return StringRef(StrTab.data() + name_offset); | |||
786 | } | |||
787 | ||||
788 | template <typename ELFT> | |||
789 | StringRef ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const { | |||
790 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); | |||
791 | Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); | |||
792 | if (Index >= Syms.size()) | |||
793 | reportError("Invalid symbol index"); | |||
794 | const Elf_Sym *Sym = &Syms[Index]; | |||
795 | return unwrapOrError(Sym->getName(StrTable)); | |||
796 | } | |||
797 | ||||
798 | template <typename ELFT> | |||
799 | std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol, | |||
800 | StringRef StrTable, | |||
801 | bool IsDynamic) const { | |||
802 | StringRef SymbolName = unwrapOrError(Symbol->getName(StrTable)); | |||
803 | if (!IsDynamic) | |||
804 | return SymbolName; | |||
805 | ||||
806 | std::string FullSymbolName(SymbolName); | |||
807 | ||||
808 | bool IsDefault; | |||
809 | StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault); | |||
810 | FullSymbolName += (IsDefault ? "@@" : "@"); | |||
811 | FullSymbolName += Version; | |||
812 | return FullSymbolName; | |||
813 | } | |||
814 | ||||
815 | template <typename ELFT> | |||
816 | void ELFDumper<ELFT>::getSectionNameIndex(const Elf_Sym *Symbol, | |||
817 | const Elf_Sym *FirstSym, | |||
818 | StringRef &SectionName, | |||
819 | unsigned &SectionIndex) const { | |||
820 | SectionIndex = Symbol->st_shndx; | |||
821 | if (Symbol->isUndefined()) | |||
822 | SectionName = "Undefined"; | |||
823 | else if (Symbol->isProcessorSpecific()) | |||
824 | SectionName = "Processor Specific"; | |||
825 | else if (Symbol->isOSSpecific()) | |||
826 | SectionName = "Operating System Specific"; | |||
827 | else if (Symbol->isAbsolute()) | |||
828 | SectionName = "Absolute"; | |||
829 | else if (Symbol->isCommon()) | |||
830 | SectionName = "Common"; | |||
831 | else if (Symbol->isReserved() && SectionIndex != SHN_XINDEX) | |||
832 | SectionName = "Reserved"; | |||
833 | else { | |||
834 | if (SectionIndex == SHN_XINDEX) | |||
835 | SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( | |||
836 | Symbol, FirstSym, ShndxTable)); | |||
837 | const typename ELFT::Shdr *Sec = | |||
838 | unwrapOrError(Obj->getSection(SectionIndex)); | |||
839 | SectionName = unwrapOrError(Obj->getSectionName(Sec)); | |||
840 | } | |||
841 | } | |||
842 | ||||
843 | template <class ELFO> | |||
844 | static const typename ELFO::Elf_Shdr * | |||
845 | findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) { | |||
846 | for (const auto &Shdr : unwrapOrError(Obj->sections())) | |||
847 | if (Shdr.sh_addr == Addr && Shdr.sh_size > 0) | |||
848 | return &Shdr; | |||
849 | return nullptr; | |||
850 | } | |||
851 | ||||
852 | template <class ELFO> | |||
853 | static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj, | |||
854 | StringRef Name) { | |||
855 | for (const auto &Shdr : unwrapOrError(Obj.sections())) { | |||
856 | if (Name == unwrapOrError(Obj.getSectionName(&Shdr))) | |||
857 | return &Shdr; | |||
858 | } | |||
859 | return nullptr; | |||
860 | } | |||
861 | ||||
862 | static const EnumEntry<unsigned> ElfClass[] = { | |||
863 | {"None", "none", ELF::ELFCLASSNONE}, | |||
864 | {"32-bit", "ELF32", ELF::ELFCLASS32}, | |||
865 | {"64-bit", "ELF64", ELF::ELFCLASS64}, | |||
866 | }; | |||
867 | ||||
868 | static const EnumEntry<unsigned> ElfDataEncoding[] = { | |||
869 | {"None", "none", ELF::ELFDATANONE}, | |||
870 | {"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB}, | |||
871 | {"BigEndian", "2's complement, big endian", ELF::ELFDATA2MSB}, | |||
872 | }; | |||
873 | ||||
874 | static const EnumEntry<unsigned> ElfObjectFileType[] = { | |||
875 | {"None", "NONE (none)", ELF::ET_NONE}, | |||
876 | {"Relocatable", "REL (Relocatable file)", ELF::ET_REL}, | |||
877 | {"Executable", "EXEC (Executable file)", ELF::ET_EXEC}, | |||
878 | {"SharedObject", "DYN (Shared object file)", ELF::ET_DYN}, | |||
879 | {"Core", "CORE (Core file)", ELF::ET_CORE}, | |||
880 | }; | |||
881 | ||||
882 | static const EnumEntry<unsigned> ElfOSABI[] = { | |||
883 | {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE}, | |||
884 | {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX}, | |||
885 | {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD}, | |||
886 | {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX}, | |||
887 | {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD}, | |||
888 | {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS}, | |||
889 | {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX}, | |||
890 | {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX}, | |||
891 | {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD}, | |||
892 | {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64}, | |||
893 | {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO}, | |||
894 | {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD}, | |||
895 | {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS}, | |||
896 | {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK}, | |||
897 | {"AROS", "AROS", ELF::ELFOSABI_AROS}, | |||
898 | {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS}, | |||
899 | {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI}, | |||
900 | {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE} | |||
901 | }; | |||
902 | ||||
903 | static const EnumEntry<unsigned> AMDGPUElfOSABI[] = { | |||
904 | {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA}, | |||
905 | {"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL}, | |||
906 | {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D} | |||
907 | }; | |||
908 | ||||
909 | static const EnumEntry<unsigned> ARMElfOSABI[] = { | |||
910 | {"ARM", "ARM", ELF::ELFOSABI_ARM} | |||
911 | }; | |||
912 | ||||
913 | static const EnumEntry<unsigned> C6000ElfOSABI[] = { | |||
914 | {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI}, | |||
915 | {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX} | |||
916 | }; | |||
917 | ||||
918 | static const EnumEntry<unsigned> ElfMachineType[] = { | |||
919 | ENUM_ENT(EM_NONE, "None"){ "EM_NONE", "None", ELF::EM_NONE }, | |||
920 | ENUM_ENT(EM_M32, "WE32100"){ "EM_M32", "WE32100", ELF::EM_M32 }, | |||
921 | ENUM_ENT(EM_SPARC, "Sparc"){ "EM_SPARC", "Sparc", ELF::EM_SPARC }, | |||
922 | ENUM_ENT(EM_386, "Intel 80386"){ "EM_386", "Intel 80386", ELF::EM_386 }, | |||
923 | ENUM_ENT(EM_68K, "MC68000"){ "EM_68K", "MC68000", ELF::EM_68K }, | |||
924 | ENUM_ENT(EM_88K, "MC88000"){ "EM_88K", "MC88000", ELF::EM_88K }, | |||
925 | ENUM_ENT(EM_IAMCU, "EM_IAMCU"){ "EM_IAMCU", "EM_IAMCU", ELF::EM_IAMCU }, | |||
926 | ENUM_ENT(EM_860, "Intel 80860"){ "EM_860", "Intel 80860", ELF::EM_860 }, | |||
927 | ENUM_ENT(EM_MIPS, "MIPS R3000"){ "EM_MIPS", "MIPS R3000", ELF::EM_MIPS }, | |||
928 | ENUM_ENT(EM_S370, "IBM System/370"){ "EM_S370", "IBM System/370", ELF::EM_S370 }, | |||
929 | ENUM_ENT(EM_MIPS_RS3_LE, "MIPS R3000 little-endian"){ "EM_MIPS_RS3_LE", "MIPS R3000 little-endian", ELF::EM_MIPS_RS3_LE }, | |||
930 | ENUM_ENT(EM_PARISC, "HPPA"){ "EM_PARISC", "HPPA", ELF::EM_PARISC }, | |||
931 | ENUM_ENT(EM_VPP500, "Fujitsu VPP500"){ "EM_VPP500", "Fujitsu VPP500", ELF::EM_VPP500 }, | |||
932 | ENUM_ENT(EM_SPARC32PLUS, "Sparc v8+"){ "EM_SPARC32PLUS", "Sparc v8+", ELF::EM_SPARC32PLUS }, | |||
933 | ENUM_ENT(EM_960, "Intel 80960"){ "EM_960", "Intel 80960", ELF::EM_960 }, | |||
934 | ENUM_ENT(EM_PPC, "PowerPC"){ "EM_PPC", "PowerPC", ELF::EM_PPC }, | |||
935 | ENUM_ENT(EM_PPC64, "PowerPC64"){ "EM_PPC64", "PowerPC64", ELF::EM_PPC64 }, | |||
936 | ENUM_ENT(EM_S390, "IBM S/390"){ "EM_S390", "IBM S/390", ELF::EM_S390 }, | |||
937 | ENUM_ENT(EM_SPU, "SPU"){ "EM_SPU", "SPU", ELF::EM_SPU }, | |||
938 | ENUM_ENT(EM_V800, "NEC V800 series"){ "EM_V800", "NEC V800 series", ELF::EM_V800 }, | |||
939 | ENUM_ENT(EM_FR20, "Fujistsu FR20"){ "EM_FR20", "Fujistsu FR20", ELF::EM_FR20 }, | |||
940 | ENUM_ENT(EM_RH32, "TRW RH-32"){ "EM_RH32", "TRW RH-32", ELF::EM_RH32 }, | |||
941 | ENUM_ENT(EM_RCE, "Motorola RCE"){ "EM_RCE", "Motorola RCE", ELF::EM_RCE }, | |||
942 | ENUM_ENT(EM_ARM, "ARM"){ "EM_ARM", "ARM", ELF::EM_ARM }, | |||
943 | ENUM_ENT(EM_ALPHA, "EM_ALPHA"){ "EM_ALPHA", "EM_ALPHA", ELF::EM_ALPHA }, | |||
944 | ENUM_ENT(EM_SH, "Hitachi SH"){ "EM_SH", "Hitachi SH", ELF::EM_SH }, | |||
945 | ENUM_ENT(EM_SPARCV9, "Sparc v9"){ "EM_SPARCV9", "Sparc v9", ELF::EM_SPARCV9 }, | |||
946 | ENUM_ENT(EM_TRICORE, "Siemens Tricore"){ "EM_TRICORE", "Siemens Tricore", ELF::EM_TRICORE }, | |||
947 | ENUM_ENT(EM_ARC, "ARC"){ "EM_ARC", "ARC", ELF::EM_ARC }, | |||
948 | ENUM_ENT(EM_H8_300, "Hitachi H8/300"){ "EM_H8_300", "Hitachi H8/300", ELF::EM_H8_300 }, | |||
949 | ENUM_ENT(EM_H8_300H, "Hitachi H8/300H"){ "EM_H8_300H", "Hitachi H8/300H", ELF::EM_H8_300H }, | |||
950 | ENUM_ENT(EM_H8S, "Hitachi H8S"){ "EM_H8S", "Hitachi H8S", ELF::EM_H8S }, | |||
951 | ENUM_ENT(EM_H8_500, "Hitachi H8/500"){ "EM_H8_500", "Hitachi H8/500", ELF::EM_H8_500 }, | |||
952 | ENUM_ENT(EM_IA_64, "Intel IA-64"){ "EM_IA_64", "Intel IA-64", ELF::EM_IA_64 }, | |||
953 | ENUM_ENT(EM_MIPS_X, "Stanford MIPS-X"){ "EM_MIPS_X", "Stanford MIPS-X", ELF::EM_MIPS_X }, | |||
954 | ENUM_ENT(EM_COLDFIRE, "Motorola Coldfire"){ "EM_COLDFIRE", "Motorola Coldfire", ELF::EM_COLDFIRE }, | |||
955 | ENUM_ENT(EM_68HC12, "Motorola MC68HC12 Microcontroller"){ "EM_68HC12", "Motorola MC68HC12 Microcontroller", ELF::EM_68HC12 }, | |||
956 | ENUM_ENT(EM_MMA, "Fujitsu Multimedia Accelerator"){ "EM_MMA", "Fujitsu Multimedia Accelerator", ELF::EM_MMA }, | |||
957 | ENUM_ENT(EM_PCP, "Siemens PCP"){ "EM_PCP", "Siemens PCP", ELF::EM_PCP }, | |||
958 | ENUM_ENT(EM_NCPU, "Sony nCPU embedded RISC processor"){ "EM_NCPU", "Sony nCPU embedded RISC processor", ELF::EM_NCPU }, | |||
959 | ENUM_ENT(EM_NDR1, "Denso NDR1 microprocesspr"){ "EM_NDR1", "Denso NDR1 microprocesspr", ELF::EM_NDR1 }, | |||
960 | ENUM_ENT(EM_STARCORE, "Motorola Star*Core processor"){ "EM_STARCORE", "Motorola Star*Core processor", ELF::EM_STARCORE }, | |||
961 | ENUM_ENT(EM_ME16, "Toyota ME16 processor"){ "EM_ME16", "Toyota ME16 processor", ELF::EM_ME16 }, | |||
962 | ENUM_ENT(EM_ST100, "STMicroelectronics ST100 processor"){ "EM_ST100", "STMicroelectronics ST100 processor", ELF::EM_ST100 }, | |||
963 | ENUM_ENT(EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor"){ "EM_TINYJ", "Advanced Logic Corp. TinyJ embedded processor" , ELF::EM_TINYJ }, | |||
964 | ENUM_ENT(EM_X86_64, "Advanced Micro Devices X86-64"){ "EM_X86_64", "Advanced Micro Devices X86-64", ELF::EM_X86_64 }, | |||
965 | ENUM_ENT(EM_PDSP, "Sony DSP processor"){ "EM_PDSP", "Sony DSP processor", ELF::EM_PDSP }, | |||
966 | ENUM_ENT(EM_PDP10, "Digital Equipment Corp. PDP-10"){ "EM_PDP10", "Digital Equipment Corp. PDP-10", ELF::EM_PDP10 }, | |||
967 | ENUM_ENT(EM_PDP11, "Digital Equipment Corp. PDP-11"){ "EM_PDP11", "Digital Equipment Corp. PDP-11", ELF::EM_PDP11 }, | |||
968 | ENUM_ENT(EM_FX66, "Siemens FX66 microcontroller"){ "EM_FX66", "Siemens FX66 microcontroller", ELF::EM_FX66 }, | |||
969 | ENUM_ENT(EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller"){ "EM_ST9PLUS", "STMicroelectronics ST9+ 8/16 bit microcontroller" , ELF::EM_ST9PLUS }, | |||
970 | ENUM_ENT(EM_ST7, "STMicroelectronics ST7 8-bit microcontroller"){ "EM_ST7", "STMicroelectronics ST7 8-bit microcontroller", ELF ::EM_ST7 }, | |||
971 | ENUM_ENT(EM_68HC16, "Motorola MC68HC16 Microcontroller"){ "EM_68HC16", "Motorola MC68HC16 Microcontroller", ELF::EM_68HC16 }, | |||
972 | ENUM_ENT(EM_68HC11, "Motorola MC68HC11 Microcontroller"){ "EM_68HC11", "Motorola MC68HC11 Microcontroller", ELF::EM_68HC11 }, | |||
973 | ENUM_ENT(EM_68HC08, "Motorola MC68HC08 Microcontroller"){ "EM_68HC08", "Motorola MC68HC08 Microcontroller", ELF::EM_68HC08 }, | |||
974 | ENUM_ENT(EM_68HC05, "Motorola MC68HC05 Microcontroller"){ "EM_68HC05", "Motorola MC68HC05 Microcontroller", ELF::EM_68HC05 }, | |||
975 | ENUM_ENT(EM_SVX, "Silicon Graphics SVx"){ "EM_SVX", "Silicon Graphics SVx", ELF::EM_SVX }, | |||
976 | ENUM_ENT(EM_ST19, "STMicroelectronics ST19 8-bit microcontroller"){ "EM_ST19", "STMicroelectronics ST19 8-bit microcontroller", ELF::EM_ST19 }, | |||
977 | ENUM_ENT(EM_VAX, "Digital VAX"){ "EM_VAX", "Digital VAX", ELF::EM_VAX }, | |||
978 | ENUM_ENT(EM_CRIS, "Axis Communications 32-bit embedded processor"){ "EM_CRIS", "Axis Communications 32-bit embedded processor", ELF::EM_CRIS }, | |||
979 | ENUM_ENT(EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu"){ "EM_JAVELIN", "Infineon Technologies 32-bit embedded cpu", ELF ::EM_JAVELIN }, | |||
980 | ENUM_ENT(EM_FIREPATH, "Element 14 64-bit DSP processor"){ "EM_FIREPATH", "Element 14 64-bit DSP processor", ELF::EM_FIREPATH }, | |||
981 | ENUM_ENT(EM_ZSP, "LSI Logic's 16-bit DSP processor"){ "EM_ZSP", "LSI Logic's 16-bit DSP processor", ELF::EM_ZSP }, | |||
982 | ENUM_ENT(EM_MMIX, "Donald Knuth's educational 64-bit processor"){ "EM_MMIX", "Donald Knuth's educational 64-bit processor", ELF ::EM_MMIX }, | |||
983 | ENUM_ENT(EM_HUANY, "Harvard Universitys's machine-independent object format"){ "EM_HUANY", "Harvard Universitys's machine-independent object format" , ELF::EM_HUANY }, | |||
984 | ENUM_ENT(EM_PRISM, "Vitesse Prism"){ "EM_PRISM", "Vitesse Prism", ELF::EM_PRISM }, | |||
985 | ENUM_ENT(EM_AVR, "Atmel AVR 8-bit microcontroller"){ "EM_AVR", "Atmel AVR 8-bit microcontroller", ELF::EM_AVR }, | |||
986 | ENUM_ENT(EM_FR30, "Fujitsu FR30"){ "EM_FR30", "Fujitsu FR30", ELF::EM_FR30 }, | |||
987 | ENUM_ENT(EM_D10V, "Mitsubishi D10V"){ "EM_D10V", "Mitsubishi D10V", ELF::EM_D10V }, | |||
988 | ENUM_ENT(EM_D30V, "Mitsubishi D30V"){ "EM_D30V", "Mitsubishi D30V", ELF::EM_D30V }, | |||
989 | ENUM_ENT(EM_V850, "NEC v850"){ "EM_V850", "NEC v850", ELF::EM_V850 }, | |||
990 | ENUM_ENT(EM_M32R, "Renesas M32R (formerly Mitsubishi M32r)"){ "EM_M32R", "Renesas M32R (formerly Mitsubishi M32r)", ELF:: EM_M32R }, | |||
991 | ENUM_ENT(EM_MN10300, "Matsushita MN10300"){ "EM_MN10300", "Matsushita MN10300", ELF::EM_MN10300 }, | |||
992 | ENUM_ENT(EM_MN10200, "Matsushita MN10200"){ "EM_MN10200", "Matsushita MN10200", ELF::EM_MN10200 }, | |||
993 | ENUM_ENT(EM_PJ, "picoJava"){ "EM_PJ", "picoJava", ELF::EM_PJ }, | |||
994 | ENUM_ENT(EM_OPENRISC, "OpenRISC 32-bit embedded processor"){ "EM_OPENRISC", "OpenRISC 32-bit embedded processor", ELF::EM_OPENRISC }, | |||
995 | ENUM_ENT(EM_ARC_COMPACT, "EM_ARC_COMPACT"){ "EM_ARC_COMPACT", "EM_ARC_COMPACT", ELF::EM_ARC_COMPACT }, | |||
996 | ENUM_ENT(EM_XTENSA, "Tensilica Xtensa Processor"){ "EM_XTENSA", "Tensilica Xtensa Processor", ELF::EM_XTENSA }, | |||
997 | ENUM_ENT(EM_VIDEOCORE, "Alphamosaic VideoCore processor"){ "EM_VIDEOCORE", "Alphamosaic VideoCore processor", ELF::EM_VIDEOCORE }, | |||
998 | ENUM_ENT(EM_TMM_GPP, "Thompson Multimedia General Purpose Processor"){ "EM_TMM_GPP", "Thompson Multimedia General Purpose Processor" , ELF::EM_TMM_GPP }, | |||
999 | ENUM_ENT(EM_NS32K, "National Semiconductor 32000 series"){ "EM_NS32K", "National Semiconductor 32000 series", ELF::EM_NS32K }, | |||
1000 | ENUM_ENT(EM_TPC, "Tenor Network TPC processor"){ "EM_TPC", "Tenor Network TPC processor", ELF::EM_TPC }, | |||
1001 | ENUM_ENT(EM_SNP1K, "EM_SNP1K"){ "EM_SNP1K", "EM_SNP1K", ELF::EM_SNP1K }, | |||
1002 | ENUM_ENT(EM_ST200, "STMicroelectronics ST200 microcontroller"){ "EM_ST200", "STMicroelectronics ST200 microcontroller", ELF ::EM_ST200 }, | |||
1003 | ENUM_ENT(EM_IP2K, "Ubicom IP2xxx 8-bit microcontrollers"){ "EM_IP2K", "Ubicom IP2xxx 8-bit microcontrollers", ELF::EM_IP2K }, | |||
1004 | ENUM_ENT(EM_MAX, "MAX Processor"){ "EM_MAX", "MAX Processor", ELF::EM_MAX }, | |||
1005 | ENUM_ENT(EM_CR, "National Semiconductor CompactRISC"){ "EM_CR", "National Semiconductor CompactRISC", ELF::EM_CR }, | |||
1006 | ENUM_ENT(EM_F2MC16, "Fujitsu F2MC16"){ "EM_F2MC16", "Fujitsu F2MC16", ELF::EM_F2MC16 }, | |||
1007 | ENUM_ENT(EM_MSP430, "Texas Instruments msp430 microcontroller"){ "EM_MSP430", "Texas Instruments msp430 microcontroller", ELF ::EM_MSP430 }, | |||
1008 | ENUM_ENT(EM_BLACKFIN, "Analog Devices Blackfin"){ "EM_BLACKFIN", "Analog Devices Blackfin", ELF::EM_BLACKFIN }, | |||
1009 | ENUM_ENT(EM_SE_C33, "S1C33 Family of Seiko Epson processors"){ "EM_SE_C33", "S1C33 Family of Seiko Epson processors", ELF:: EM_SE_C33 }, | |||
1010 | ENUM_ENT(EM_SEP, "Sharp embedded microprocessor"){ "EM_SEP", "Sharp embedded microprocessor", ELF::EM_SEP }, | |||
1011 | ENUM_ENT(EM_ARCA, "Arca RISC microprocessor"){ "EM_ARCA", "Arca RISC microprocessor", ELF::EM_ARCA }, | |||
1012 | ENUM_ENT(EM_UNICORE, "Unicore"){ "EM_UNICORE", "Unicore", ELF::EM_UNICORE }, | |||
1013 | ENUM_ENT(EM_EXCESS, "eXcess 16/32/64-bit configurable embedded CPU"){ "EM_EXCESS", "eXcess 16/32/64-bit configurable embedded CPU" , ELF::EM_EXCESS }, | |||
1014 | ENUM_ENT(EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor"){ "EM_DXP", "Icera Semiconductor Inc. Deep Execution Processor" , ELF::EM_DXP }, | |||
1015 | ENUM_ENT(EM_ALTERA_NIOS2, "Altera Nios"){ "EM_ALTERA_NIOS2", "Altera Nios", ELF::EM_ALTERA_NIOS2 }, | |||
1016 | ENUM_ENT(EM_CRX, "National Semiconductor CRX microprocessor"){ "EM_CRX", "National Semiconductor CRX microprocessor", ELF:: EM_CRX }, | |||
1017 | ENUM_ENT(EM_XGATE, "Motorola XGATE embedded processor"){ "EM_XGATE", "Motorola XGATE embedded processor", ELF::EM_XGATE }, | |||
1018 | ENUM_ENT(EM_C166, "Infineon Technologies xc16x"){ "EM_C166", "Infineon Technologies xc16x", ELF::EM_C166 }, | |||
1019 | ENUM_ENT(EM_M16C, "Renesas M16C"){ "EM_M16C", "Renesas M16C", ELF::EM_M16C }, | |||
1020 | ENUM_ENT(EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller"){ "EM_DSPIC30F", "Microchip Technology dsPIC30F Digital Signal Controller" , ELF::EM_DSPIC30F }, | |||
1021 | ENUM_ENT(EM_CE, "Freescale Communication Engine RISC core"){ "EM_CE", "Freescale Communication Engine RISC core", ELF::EM_CE }, | |||
1022 | ENUM_ENT(EM_M32C, "Renesas M32C"){ "EM_M32C", "Renesas M32C", ELF::EM_M32C }, | |||
1023 | ENUM_ENT(EM_TSK3000, "Altium TSK3000 core"){ "EM_TSK3000", "Altium TSK3000 core", ELF::EM_TSK3000 }, | |||
1024 | ENUM_ENT(EM_RS08, "Freescale RS08 embedded processor"){ "EM_RS08", "Freescale RS08 embedded processor", ELF::EM_RS08 }, | |||
1025 | ENUM_ENT(EM_SHARC, "EM_SHARC"){ "EM_SHARC", "EM_SHARC", ELF::EM_SHARC }, | |||
1026 | ENUM_ENT(EM_ECOG2, "Cyan Technology eCOG2 microprocessor"){ "EM_ECOG2", "Cyan Technology eCOG2 microprocessor", ELF::EM_ECOG2 }, | |||
1027 | ENUM_ENT(EM_SCORE7, "SUNPLUS S+Core"){ "EM_SCORE7", "SUNPLUS S+Core", ELF::EM_SCORE7 }, | |||
1028 | ENUM_ENT(EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor"){ "EM_DSP24", "New Japan Radio (NJR) 24-bit DSP Processor", ELF ::EM_DSP24 }, | |||
1029 | ENUM_ENT(EM_VIDEOCORE3, "Broadcom VideoCore III processor"){ "EM_VIDEOCORE3", "Broadcom VideoCore III processor", ELF::EM_VIDEOCORE3 }, | |||
1030 | ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"){ "EM_LATTICEMICO32", "Lattice Mico32", ELF::EM_LATTICEMICO32 }, | |||
1031 | ENUM_ENT(EM_SE_C17, "Seiko Epson C17 family"){ "EM_SE_C17", "Seiko Epson C17 family", ELF::EM_SE_C17 }, | |||
1032 | ENUM_ENT(EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family"){ "EM_TI_C6000", "Texas Instruments TMS320C6000 DSP family", ELF ::EM_TI_C6000 }, | |||
1033 | ENUM_ENT(EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family"){ "EM_TI_C2000", "Texas Instruments TMS320C2000 DSP family", ELF ::EM_TI_C2000 }, | |||
1034 | ENUM_ENT(EM_TI_C5500, "Texas Instruments TMS320C55x DSP family"){ "EM_TI_C5500", "Texas Instruments TMS320C55x DSP family", ELF ::EM_TI_C5500 }, | |||
1035 | ENUM_ENT(EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor"){ "EM_MMDSP_PLUS", "STMicroelectronics 64bit VLIW Data Signal Processor" , ELF::EM_MMDSP_PLUS }, | |||
1036 | ENUM_ENT(EM_CYPRESS_M8C, "Cypress M8C microprocessor"){ "EM_CYPRESS_M8C", "Cypress M8C microprocessor", ELF::EM_CYPRESS_M8C }, | |||
1037 | ENUM_ENT(EM_R32C, "Renesas R32C series microprocessors"){ "EM_R32C", "Renesas R32C series microprocessors", ELF::EM_R32C }, | |||
1038 | ENUM_ENT(EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family"){ "EM_TRIMEDIA", "NXP Semiconductors TriMedia architecture family" , ELF::EM_TRIMEDIA }, | |||
1039 | ENUM_ENT(EM_HEXAGON, "Qualcomm Hexagon"){ "EM_HEXAGON", "Qualcomm Hexagon", ELF::EM_HEXAGON }, | |||
1040 | ENUM_ENT(EM_8051, "Intel 8051 and variants"){ "EM_8051", "Intel 8051 and variants", ELF::EM_8051 }, | |||
1041 | ENUM_ENT(EM_STXP7X, "STMicroelectronics STxP7x family"){ "EM_STXP7X", "STMicroelectronics STxP7x family", ELF::EM_STXP7X }, | |||
1042 | ENUM_ENT(EM_NDS32, "Andes Technology compact code size embedded RISC processor family"){ "EM_NDS32", "Andes Technology compact code size embedded RISC processor family" , ELF::EM_NDS32 }, | |||
1043 | ENUM_ENT(EM_ECOG1, "Cyan Technology eCOG1 microprocessor"){ "EM_ECOG1", "Cyan Technology eCOG1 microprocessor", ELF::EM_ECOG1 }, | |||
1044 | ENUM_ENT(EM_ECOG1X, "Cyan Technology eCOG1X family"){ "EM_ECOG1X", "Cyan Technology eCOG1X family", ELF::EM_ECOG1X }, | |||
1045 | ENUM_ENT(EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core microcontrollers"){ "EM_MAXQ30", "Dallas Semiconductor MAXQ30 Core microcontrollers" , ELF::EM_MAXQ30 }, | |||
1046 | ENUM_ENT(EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor"){ "EM_XIMO16", "New Japan Radio (NJR) 16-bit DSP Processor", ELF ::EM_XIMO16 }, | |||
1047 | ENUM_ENT(EM_MANIK, "M2000 Reconfigurable RISC Microprocessor"){ "EM_MANIK", "M2000 Reconfigurable RISC Microprocessor", ELF ::EM_MANIK }, | |||
1048 | ENUM_ENT(EM_CRAYNV2, "Cray Inc. NV2 vector architecture"){ "EM_CRAYNV2", "Cray Inc. NV2 vector architecture", ELF::EM_CRAYNV2 }, | |||
1049 | ENUM_ENT(EM_RX, "Renesas RX"){ "EM_RX", "Renesas RX", ELF::EM_RX }, | |||
1050 | ENUM_ENT(EM_METAG, "Imagination Technologies Meta processor architecture"){ "EM_METAG", "Imagination Technologies Meta processor architecture" , ELF::EM_METAG }, | |||
1051 | ENUM_ENT(EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture"){ "EM_MCST_ELBRUS", "MCST Elbrus general purpose hardware architecture" , ELF::EM_MCST_ELBRUS }, | |||
1052 | ENUM_ENT(EM_ECOG16, "Cyan Technology eCOG16 family"){ "EM_ECOG16", "Cyan Technology eCOG16 family", ELF::EM_ECOG16 }, | |||
1053 | ENUM_ENT(EM_CR16, "Xilinx MicroBlaze"){ "EM_CR16", "Xilinx MicroBlaze", ELF::EM_CR16 }, | |||
1054 | ENUM_ENT(EM_ETPU, "Freescale Extended Time Processing Unit"){ "EM_ETPU", "Freescale Extended Time Processing Unit", ELF:: EM_ETPU }, | |||
1055 | ENUM_ENT(EM_SLE9X, "Infineon Technologies SLE9X core"){ "EM_SLE9X", "Infineon Technologies SLE9X core", ELF::EM_SLE9X }, | |||
1056 | ENUM_ENT(EM_L10M, "EM_L10M"){ "EM_L10M", "EM_L10M", ELF::EM_L10M }, | |||
1057 | ENUM_ENT(EM_K10M, "EM_K10M"){ "EM_K10M", "EM_K10M", ELF::EM_K10M }, | |||
1058 | ENUM_ENT(EM_AARCH64, "AArch64"){ "EM_AARCH64", "AArch64", ELF::EM_AARCH64 }, | |||
1059 | ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"){ "EM_AVR32", "Atmel Corporation 32-bit microprocessor family" , ELF::EM_AVR32 }, | |||
1060 | ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"){ "EM_STM8", "STMicroeletronics STM8 8-bit microcontroller", ELF ::EM_STM8 }, | |||
1061 | ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"){ "EM_TILE64", "Tilera TILE64 multicore architecture family", ELF::EM_TILE64 }, | |||
1062 | ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"){ "EM_TILEPRO", "Tilera TILEPro multicore architecture family" , ELF::EM_TILEPRO }, | |||
1063 | ENUM_ENT(EM_CUDA, "NVIDIA CUDA architecture"){ "EM_CUDA", "NVIDIA CUDA architecture", ELF::EM_CUDA }, | |||
1064 | ENUM_ENT(EM_TILEGX, "Tilera TILE-Gx multicore architecture family"){ "EM_TILEGX", "Tilera TILE-Gx multicore architecture family" , ELF::EM_TILEGX }, | |||
1065 | ENUM_ENT(EM_CLOUDSHIELD, "EM_CLOUDSHIELD"){ "EM_CLOUDSHIELD", "EM_CLOUDSHIELD", ELF::EM_CLOUDSHIELD }, | |||
1066 | ENUM_ENT(EM_COREA_1ST, "EM_COREA_1ST"){ "EM_COREA_1ST", "EM_COREA_1ST", ELF::EM_COREA_1ST }, | |||
1067 | ENUM_ENT(EM_COREA_2ND, "EM_COREA_2ND"){ "EM_COREA_2ND", "EM_COREA_2ND", ELF::EM_COREA_2ND }, | |||
1068 | ENUM_ENT(EM_ARC_COMPACT2, "EM_ARC_COMPACT2"){ "EM_ARC_COMPACT2", "EM_ARC_COMPACT2", ELF::EM_ARC_COMPACT2 }, | |||
1069 | ENUM_ENT(EM_OPEN8, "EM_OPEN8"){ "EM_OPEN8", "EM_OPEN8", ELF::EM_OPEN8 }, | |||
1070 | ENUM_ENT(EM_RL78, "Renesas RL78"){ "EM_RL78", "Renesas RL78", ELF::EM_RL78 }, | |||
1071 | ENUM_ENT(EM_VIDEOCORE5, "Broadcom VideoCore V processor"){ "EM_VIDEOCORE5", "Broadcom VideoCore V processor", ELF::EM_VIDEOCORE5 }, | |||
1072 | ENUM_ENT(EM_78KOR, "EM_78KOR"){ "EM_78KOR", "EM_78KOR", ELF::EM_78KOR }, | |||
1073 | ENUM_ENT(EM_56800EX, "EM_56800EX"){ "EM_56800EX", "EM_56800EX", ELF::EM_56800EX }, | |||
1074 | ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"){ "EM_AMDGPU", "EM_AMDGPU", ELF::EM_AMDGPU }, | |||
1075 | ENUM_ENT(EM_RISCV, "RISC-V"){ "EM_RISCV", "RISC-V", ELF::EM_RISCV }, | |||
1076 | ENUM_ENT(EM_LANAI, "EM_LANAI"){ "EM_LANAI", "EM_LANAI", ELF::EM_LANAI }, | |||
1077 | ENUM_ENT(EM_BPF, "EM_BPF"){ "EM_BPF", "EM_BPF", ELF::EM_BPF }, | |||
1078 | }; | |||
1079 | ||||
1080 | static const EnumEntry<unsigned> ElfSymbolBindings[] = { | |||
1081 | {"Local", "LOCAL", ELF::STB_LOCAL}, | |||
1082 | {"Global", "GLOBAL", ELF::STB_GLOBAL}, | |||
1083 | {"Weak", "WEAK", ELF::STB_WEAK}, | |||
1084 | {"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}}; | |||
1085 | ||||
1086 | static const EnumEntry<unsigned> ElfSymbolVisibilities[] = { | |||
1087 | {"DEFAULT", "DEFAULT", ELF::STV_DEFAULT}, | |||
1088 | {"INTERNAL", "INTERNAL", ELF::STV_INTERNAL}, | |||
1089 | {"HIDDEN", "HIDDEN", ELF::STV_HIDDEN}, | |||
1090 | {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}}; | |||
1091 | ||||
1092 | static const EnumEntry<unsigned> ElfSymbolTypes[] = { | |||
1093 | {"None", "NOTYPE", ELF::STT_NOTYPE}, | |||
1094 | {"Object", "OBJECT", ELF::STT_OBJECT}, | |||
1095 | {"Function", "FUNC", ELF::STT_FUNC}, | |||
1096 | {"Section", "SECTION", ELF::STT_SECTION}, | |||
1097 | {"File", "FILE", ELF::STT_FILE}, | |||
1098 | {"Common", "COMMON", ELF::STT_COMMON}, | |||
1099 | {"TLS", "TLS", ELF::STT_TLS}, | |||
1100 | {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}}; | |||
1101 | ||||
1102 | static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = { | |||
1103 | { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } | |||
1104 | }; | |||
1105 | ||||
1106 | static const char *getGroupType(uint32_t Flag) { | |||
1107 | if (Flag & ELF::GRP_COMDAT) | |||
1108 | return "COMDAT"; | |||
1109 | else | |||
1110 | return "(unknown)"; | |||
1111 | } | |||
1112 | ||||
1113 | static const EnumEntry<unsigned> ElfSectionFlags[] = { | |||
1114 | ENUM_ENT(SHF_WRITE, "W"){ "SHF_WRITE", "W", ELF::SHF_WRITE }, | |||
1115 | ENUM_ENT(SHF_ALLOC, "A"){ "SHF_ALLOC", "A", ELF::SHF_ALLOC }, | |||
1116 | ENUM_ENT(SHF_EXCLUDE, "E"){ "SHF_EXCLUDE", "E", ELF::SHF_EXCLUDE }, | |||
1117 | ENUM_ENT(SHF_EXECINSTR, "X"){ "SHF_EXECINSTR", "X", ELF::SHF_EXECINSTR }, | |||
1118 | ENUM_ENT(SHF_MERGE, "M"){ "SHF_MERGE", "M", ELF::SHF_MERGE }, | |||
1119 | ENUM_ENT(SHF_STRINGS, "S"){ "SHF_STRINGS", "S", ELF::SHF_STRINGS }, | |||
1120 | ENUM_ENT(SHF_INFO_LINK, "I"){ "SHF_INFO_LINK", "I", ELF::SHF_INFO_LINK }, | |||
1121 | ENUM_ENT(SHF_LINK_ORDER, "L"){ "SHF_LINK_ORDER", "L", ELF::SHF_LINK_ORDER }, | |||
1122 | ENUM_ENT(SHF_OS_NONCONFORMING, "o"){ "SHF_OS_NONCONFORMING", "o", ELF::SHF_OS_NONCONFORMING }, | |||
1123 | ENUM_ENT(SHF_GROUP, "G"){ "SHF_GROUP", "G", ELF::SHF_GROUP }, | |||
1124 | ENUM_ENT(SHF_TLS, "T"){ "SHF_TLS", "T", ELF::SHF_TLS }, | |||
1125 | ENUM_ENT(SHF_MASKOS, "o"){ "SHF_MASKOS", "o", ELF::SHF_MASKOS }, | |||
1126 | ENUM_ENT(SHF_MASKPROC, "p"){ "SHF_MASKPROC", "p", ELF::SHF_MASKPROC }, | |||
1127 | ENUM_ENT_1(SHF_COMPRESSED){ "SHF_COMPRESSED", "SHF_COMPRESSED", ELF::SHF_COMPRESSED }, | |||
1128 | }; | |||
1129 | ||||
1130 | static const EnumEntry<unsigned> ElfXCoreSectionFlags[] = { | |||
1131 | LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION){ "XCORE_SHF_CP_SECTION", ELF::XCORE_SHF_CP_SECTION }, | |||
1132 | LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION){ "XCORE_SHF_DP_SECTION", ELF::XCORE_SHF_DP_SECTION } | |||
1133 | }; | |||
1134 | ||||
1135 | static const EnumEntry<unsigned> ElfARMSectionFlags[] = { | |||
1136 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE){ "SHF_ARM_PURECODE", ELF::SHF_ARM_PURECODE } | |||
1137 | }; | |||
1138 | ||||
1139 | static const EnumEntry<unsigned> ElfHexagonSectionFlags[] = { | |||
1140 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL){ "SHF_HEX_GPREL", ELF::SHF_HEX_GPREL } | |||
1141 | }; | |||
1142 | ||||
1143 | static const EnumEntry<unsigned> ElfMipsSectionFlags[] = { | |||
1144 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NODUPES){ "SHF_MIPS_NODUPES", ELF::SHF_MIPS_NODUPES }, | |||
1145 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NAMES ){ "SHF_MIPS_NAMES", ELF::SHF_MIPS_NAMES }, | |||
1146 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_LOCAL ){ "SHF_MIPS_LOCAL", ELF::SHF_MIPS_LOCAL }, | |||
1147 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP){ "SHF_MIPS_NOSTRIP", ELF::SHF_MIPS_NOSTRIP }, | |||
1148 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_GPREL ){ "SHF_MIPS_GPREL", ELF::SHF_MIPS_GPREL }, | |||
1149 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_MERGE ){ "SHF_MIPS_MERGE", ELF::SHF_MIPS_MERGE }, | |||
1150 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_ADDR ){ "SHF_MIPS_ADDR", ELF::SHF_MIPS_ADDR }, | |||
1151 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_STRING ){ "SHF_MIPS_STRING", ELF::SHF_MIPS_STRING } | |||
1152 | }; | |||
1153 | ||||
1154 | static const EnumEntry<unsigned> ElfX86_64SectionFlags[] = { | |||
1155 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_X86_64_LARGE){ "SHF_X86_64_LARGE", ELF::SHF_X86_64_LARGE } | |||
1156 | }; | |||
1157 | ||||
1158 | static std::string getGNUFlags(uint64_t Flags) { | |||
1159 | std::string Str; | |||
1160 | for (auto Entry : ElfSectionFlags) { | |||
1161 | uint64_t Flag = Entry.Value & Flags; | |||
1162 | Flags &= ~Entry.Value; | |||
1163 | switch (Flag) { | |||
1164 | case ELF::SHF_WRITE: | |||
1165 | case ELF::SHF_ALLOC: | |||
1166 | case ELF::SHF_EXECINSTR: | |||
1167 | case ELF::SHF_MERGE: | |||
1168 | case ELF::SHF_STRINGS: | |||
1169 | case ELF::SHF_INFO_LINK: | |||
1170 | case ELF::SHF_LINK_ORDER: | |||
1171 | case ELF::SHF_OS_NONCONFORMING: | |||
1172 | case ELF::SHF_GROUP: | |||
1173 | case ELF::SHF_TLS: | |||
1174 | case ELF::SHF_EXCLUDE: | |||
1175 | Str += Entry.AltName; | |||
1176 | break; | |||
1177 | default: | |||
1178 | if (Flag & ELF::SHF_MASKOS) | |||
1179 | Str += "o"; | |||
1180 | else if (Flag & ELF::SHF_MASKPROC) | |||
1181 | Str += "p"; | |||
1182 | else if (Flag) | |||
1183 | Str += "x"; | |||
1184 | } | |||
1185 | } | |||
1186 | return Str; | |||
1187 | } | |||
1188 | ||||
1189 | static const char *getElfSegmentType(unsigned Arch, unsigned Type) { | |||
1190 | // Check potentially overlapped processor-specific | |||
1191 | // program header type. | |||
1192 | switch (Arch) { | |||
1193 | case ELF::EM_ARM: | |||
1194 | switch (Type) { | |||
1195 | LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX)case ELF::PT_ARM_EXIDX: return "PT_ARM_EXIDX";; | |||
1196 | } | |||
1197 | break; | |||
1198 | case ELF::EM_MIPS: | |||
1199 | case ELF::EM_MIPS_RS3_LE: | |||
1200 | switch (Type) { | |||
1201 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO)case ELF::PT_MIPS_REGINFO: return "PT_MIPS_REGINFO";; | |||
1202 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC)case ELF::PT_MIPS_RTPROC: return "PT_MIPS_RTPROC";; | |||
1203 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS)case ELF::PT_MIPS_OPTIONS: return "PT_MIPS_OPTIONS";; | |||
1204 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS)case ELF::PT_MIPS_ABIFLAGS: return "PT_MIPS_ABIFLAGS";; | |||
1205 | } | |||
1206 | break; | |||
1207 | } | |||
1208 | ||||
1209 | switch (Type) { | |||
1210 | LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL )case ELF::PT_NULL: return "PT_NULL";; | |||
1211 | LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD )case ELF::PT_LOAD: return "PT_LOAD";; | |||
1212 | LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC)case ELF::PT_DYNAMIC: return "PT_DYNAMIC";; | |||
1213 | LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP )case ELF::PT_INTERP: return "PT_INTERP";; | |||
1214 | LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE )case ELF::PT_NOTE: return "PT_NOTE";; | |||
1215 | LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB )case ELF::PT_SHLIB: return "PT_SHLIB";; | |||
1216 | LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR )case ELF::PT_PHDR: return "PT_PHDR";; | |||
1217 | LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS )case ELF::PT_TLS: return "PT_TLS";; | |||
1218 | ||||
1219 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME)case ELF::PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME";; | |||
1220 | LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND)case ELF::PT_SUNW_UNWIND: return "PT_SUNW_UNWIND";; | |||
1221 | ||||
1222 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK)case ELF::PT_GNU_STACK: return "PT_GNU_STACK";; | |||
1223 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO)case ELF::PT_GNU_RELRO: return "PT_GNU_RELRO";; | |||
1224 | ||||
1225 | LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE)case ELF::PT_OPENBSD_RANDOMIZE: return "PT_OPENBSD_RANDOMIZE" ;; | |||
1226 | LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED)case ELF::PT_OPENBSD_WXNEEDED: return "PT_OPENBSD_WXNEEDED";; | |||
1227 | LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA)case ELF::PT_OPENBSD_BOOTDATA: return "PT_OPENBSD_BOOTDATA";; | |||
1228 | ||||
1229 | default: return ""; | |||
1230 | } | |||
1231 | } | |||
1232 | ||||
1233 | static std::string getElfPtType(unsigned Arch, unsigned Type) { | |||
1234 | switch (Type) { | |||
1235 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_NULL)case ELF::PT_NULL: return std::string("PT_NULL").substr(3); | |||
1236 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_LOAD)case ELF::PT_LOAD: return std::string("PT_LOAD").substr(3); | |||
1237 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_DYNAMIC)case ELF::PT_DYNAMIC: return std::string("PT_DYNAMIC").substr (3); | |||
1238 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_INTERP)case ELF::PT_INTERP: return std::string("PT_INTERP").substr(3 ); | |||
1239 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_NOTE)case ELF::PT_NOTE: return std::string("PT_NOTE").substr(3); | |||
1240 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_SHLIB)case ELF::PT_SHLIB: return std::string("PT_SHLIB").substr(3); | |||
1241 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_PHDR)case ELF::PT_PHDR: return std::string("PT_PHDR").substr(3); | |||
1242 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_TLS)case ELF::PT_TLS: return std::string("PT_TLS").substr(3); | |||
1243 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_EH_FRAME)case ELF::PT_GNU_EH_FRAME: return std::string("PT_GNU_EH_FRAME" ).substr(3); | |||
1244 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_SUNW_UNWIND)case ELF::PT_SUNW_UNWIND: return std::string("PT_SUNW_UNWIND" ).substr(3); | |||
1245 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_STACK)case ELF::PT_GNU_STACK: return std::string("PT_GNU_STACK").substr (3); | |||
1246 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_RELRO)case ELF::PT_GNU_RELRO: return std::string("PT_GNU_RELRO").substr (3); | |||
1247 | default: | |||
1248 | // All machine specific PT_* types | |||
1249 | switch (Arch) { | |||
1250 | case ELF::EM_ARM: | |||
1251 | if (Type == ELF::PT_ARM_EXIDX) | |||
1252 | return "EXIDX"; | |||
1253 | break; | |||
1254 | case ELF::EM_MIPS: | |||
1255 | case ELF::EM_MIPS_RS3_LE: | |||
1256 | switch (Type) { | |||
1257 | case PT_MIPS_REGINFO: | |||
1258 | return "REGINFO"; | |||
1259 | case PT_MIPS_RTPROC: | |||
1260 | return "RTPROC"; | |||
1261 | case PT_MIPS_OPTIONS: | |||
1262 | return "OPTIONS"; | |||
1263 | case PT_MIPS_ABIFLAGS: | |||
1264 | return "ABIFLAGS"; | |||
1265 | } | |||
1266 | break; | |||
1267 | } | |||
1268 | } | |||
1269 | return std::string("<unknown>: ") + to_string(format_hex(Type, 1)); | |||
1270 | } | |||
1271 | ||||
1272 | static const EnumEntry<unsigned> ElfSegmentFlags[] = { | |||
1273 | LLVM_READOBJ_ENUM_ENT(ELF, PF_X){ "PF_X", ELF::PF_X }, | |||
1274 | LLVM_READOBJ_ENUM_ENT(ELF, PF_W){ "PF_W", ELF::PF_W }, | |||
1275 | LLVM_READOBJ_ENUM_ENT(ELF, PF_R){ "PF_R", ELF::PF_R } | |||
1276 | }; | |||
1277 | ||||
1278 | static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { | |||
1279 | ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"){ "EF_MIPS_NOREORDER", "noreorder", ELF::EF_MIPS_NOREORDER }, | |||
1280 | ENUM_ENT(EF_MIPS_PIC, "pic"){ "EF_MIPS_PIC", "pic", ELF::EF_MIPS_PIC }, | |||
1281 | ENUM_ENT(EF_MIPS_CPIC, "cpic"){ "EF_MIPS_CPIC", "cpic", ELF::EF_MIPS_CPIC }, | |||
1282 | ENUM_ENT(EF_MIPS_ABI2, "abi2"){ "EF_MIPS_ABI2", "abi2", ELF::EF_MIPS_ABI2 }, | |||
1283 | ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"){ "EF_MIPS_32BITMODE", "32bitmode", ELF::EF_MIPS_32BITMODE }, | |||
1284 | ENUM_ENT(EF_MIPS_FP64, "fp64"){ "EF_MIPS_FP64", "fp64", ELF::EF_MIPS_FP64 }, | |||
1285 | ENUM_ENT(EF_MIPS_NAN2008, "nan2008"){ "EF_MIPS_NAN2008", "nan2008", ELF::EF_MIPS_NAN2008 }, | |||
1286 | ENUM_ENT(EF_MIPS_ABI_O32, "o32"){ "EF_MIPS_ABI_O32", "o32", ELF::EF_MIPS_ABI_O32 }, | |||
1287 | ENUM_ENT(EF_MIPS_ABI_O64, "o64"){ "EF_MIPS_ABI_O64", "o64", ELF::EF_MIPS_ABI_O64 }, | |||
1288 | ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"){ "EF_MIPS_ABI_EABI32", "eabi32", ELF::EF_MIPS_ABI_EABI32 }, | |||
1289 | ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"){ "EF_MIPS_ABI_EABI64", "eabi64", ELF::EF_MIPS_ABI_EABI64 }, | |||
1290 | ENUM_ENT(EF_MIPS_MACH_3900, "3900"){ "EF_MIPS_MACH_3900", "3900", ELF::EF_MIPS_MACH_3900 }, | |||
1291 | ENUM_ENT(EF_MIPS_MACH_4010, "4010"){ "EF_MIPS_MACH_4010", "4010", ELF::EF_MIPS_MACH_4010 }, | |||
1292 | ENUM_ENT(EF_MIPS_MACH_4100, "4100"){ "EF_MIPS_MACH_4100", "4100", ELF::EF_MIPS_MACH_4100 }, | |||
1293 | ENUM_ENT(EF_MIPS_MACH_4650, "4650"){ "EF_MIPS_MACH_4650", "4650", ELF::EF_MIPS_MACH_4650 }, | |||
1294 | ENUM_ENT(EF_MIPS_MACH_4120, "4120"){ "EF_MIPS_MACH_4120", "4120", ELF::EF_MIPS_MACH_4120 }, | |||
1295 | ENUM_ENT(EF_MIPS_MACH_4111, "4111"){ "EF_MIPS_MACH_4111", "4111", ELF::EF_MIPS_MACH_4111 }, | |||
1296 | ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"){ "EF_MIPS_MACH_SB1", "sb1", ELF::EF_MIPS_MACH_SB1 }, | |||
1297 | ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"){ "EF_MIPS_MACH_OCTEON", "octeon", ELF::EF_MIPS_MACH_OCTEON }, | |||
1298 | ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"){ "EF_MIPS_MACH_XLR", "xlr", ELF::EF_MIPS_MACH_XLR }, | |||
1299 | ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"){ "EF_MIPS_MACH_OCTEON2", "octeon2", ELF::EF_MIPS_MACH_OCTEON2 }, | |||
1300 | ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"){ "EF_MIPS_MACH_OCTEON3", "octeon3", ELF::EF_MIPS_MACH_OCTEON3 }, | |||
1301 | ENUM_ENT(EF_MIPS_MACH_5400, "5400"){ "EF_MIPS_MACH_5400", "5400", ELF::EF_MIPS_MACH_5400 }, | |||
1302 | ENUM_ENT(EF_MIPS_MACH_5900, "5900"){ "EF_MIPS_MACH_5900", "5900", ELF::EF_MIPS_MACH_5900 }, | |||
1303 | ENUM_ENT(EF_MIPS_MACH_5500, "5500"){ "EF_MIPS_MACH_5500", "5500", ELF::EF_MIPS_MACH_5500 }, | |||
1304 | ENUM_ENT(EF_MIPS_MACH_9000, "9000"){ "EF_MIPS_MACH_9000", "9000", ELF::EF_MIPS_MACH_9000 }, | |||
1305 | ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"){ "EF_MIPS_MACH_LS2E", "loongson-2e", ELF::EF_MIPS_MACH_LS2E }, | |||
1306 | ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"){ "EF_MIPS_MACH_LS2F", "loongson-2f", ELF::EF_MIPS_MACH_LS2F }, | |||
1307 | ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"){ "EF_MIPS_MACH_LS3A", "loongson-3a", ELF::EF_MIPS_MACH_LS3A }, | |||
1308 | ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"){ "EF_MIPS_MICROMIPS", "micromips", ELF::EF_MIPS_MICROMIPS }, | |||
1309 | ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"){ "EF_MIPS_ARCH_ASE_M16", "mips16", ELF::EF_MIPS_ARCH_ASE_M16 }, | |||
1310 | ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"){ "EF_MIPS_ARCH_ASE_MDMX", "mdmx", ELF::EF_MIPS_ARCH_ASE_MDMX }, | |||
1311 | ENUM_ENT(EF_MIPS_ARCH_1, "mips1"){ "EF_MIPS_ARCH_1", "mips1", ELF::EF_MIPS_ARCH_1 }, | |||
1312 | ENUM_ENT(EF_MIPS_ARCH_2, "mips2"){ "EF_MIPS_ARCH_2", "mips2", ELF::EF_MIPS_ARCH_2 }, | |||
1313 | ENUM_ENT(EF_MIPS_ARCH_3, "mips3"){ "EF_MIPS_ARCH_3", "mips3", ELF::EF_MIPS_ARCH_3 }, | |||
1314 | ENUM_ENT(EF_MIPS_ARCH_4, "mips4"){ "EF_MIPS_ARCH_4", "mips4", ELF::EF_MIPS_ARCH_4 }, | |||
1315 | ENUM_ENT(EF_MIPS_ARCH_5, "mips5"){ "EF_MIPS_ARCH_5", "mips5", ELF::EF_MIPS_ARCH_5 }, | |||
1316 | ENUM_ENT(EF_MIPS_ARCH_32, "mips32"){ "EF_MIPS_ARCH_32", "mips32", ELF::EF_MIPS_ARCH_32 }, | |||
1317 | ENUM_ENT(EF_MIPS_ARCH_64, "mips64"){ "EF_MIPS_ARCH_64", "mips64", ELF::EF_MIPS_ARCH_64 }, | |||
1318 | ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"){ "EF_MIPS_ARCH_32R2", "mips32r2", ELF::EF_MIPS_ARCH_32R2 }, | |||
1319 | ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"){ "EF_MIPS_ARCH_64R2", "mips64r2", ELF::EF_MIPS_ARCH_64R2 }, | |||
1320 | ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"){ "EF_MIPS_ARCH_32R6", "mips32r6", ELF::EF_MIPS_ARCH_32R6 }, | |||
1321 | ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6"){ "EF_MIPS_ARCH_64R6", "mips64r6", ELF::EF_MIPS_ARCH_64R6 } | |||
1322 | }; | |||
1323 | ||||
1324 | static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = { | |||
1325 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE){ "EF_AMDGPU_MACH_NONE", ELF::EF_AMDGPU_MACH_NONE }, | |||
1326 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600){ "EF_AMDGPU_MACH_R600_R600", ELF::EF_AMDGPU_MACH_R600_R600 }, | |||
1327 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630){ "EF_AMDGPU_MACH_R600_R630", ELF::EF_AMDGPU_MACH_R600_R630 }, | |||
1328 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880){ "EF_AMDGPU_MACH_R600_RS880", ELF::EF_AMDGPU_MACH_R600_RS880 }, | |||
1329 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670){ "EF_AMDGPU_MACH_R600_RV670", ELF::EF_AMDGPU_MACH_R600_RV670 }, | |||
1330 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710){ "EF_AMDGPU_MACH_R600_RV710", ELF::EF_AMDGPU_MACH_R600_RV710 }, | |||
1331 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730){ "EF_AMDGPU_MACH_R600_RV730", ELF::EF_AMDGPU_MACH_R600_RV730 }, | |||
1332 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770){ "EF_AMDGPU_MACH_R600_RV770", ELF::EF_AMDGPU_MACH_R600_RV770 }, | |||
1333 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR){ "EF_AMDGPU_MACH_R600_CEDAR", ELF::EF_AMDGPU_MACH_R600_CEDAR }, | |||
1334 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS){ "EF_AMDGPU_MACH_R600_CYPRESS", ELF::EF_AMDGPU_MACH_R600_CYPRESS }, | |||
1335 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER){ "EF_AMDGPU_MACH_R600_JUNIPER", ELF::EF_AMDGPU_MACH_R600_JUNIPER }, | |||
1336 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD){ "EF_AMDGPU_MACH_R600_REDWOOD", ELF::EF_AMDGPU_MACH_R600_REDWOOD }, | |||
1337 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO){ "EF_AMDGPU_MACH_R600_SUMO", ELF::EF_AMDGPU_MACH_R600_SUMO }, | |||
1338 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS){ "EF_AMDGPU_MACH_R600_BARTS", ELF::EF_AMDGPU_MACH_R600_BARTS }, | |||
1339 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS){ "EF_AMDGPU_MACH_R600_CAICOS", ELF::EF_AMDGPU_MACH_R600_CAICOS }, | |||
1340 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN){ "EF_AMDGPU_MACH_R600_CAYMAN", ELF::EF_AMDGPU_MACH_R600_CAYMAN }, | |||
1341 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS){ "EF_AMDGPU_MACH_R600_TURKS", ELF::EF_AMDGPU_MACH_R600_TURKS }, | |||
1342 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600){ "EF_AMDGPU_MACH_AMDGCN_GFX600", ELF::EF_AMDGPU_MACH_AMDGCN_GFX600 }, | |||
1343 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601){ "EF_AMDGPU_MACH_AMDGCN_GFX601", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601 }, | |||
1344 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700){ "EF_AMDGPU_MACH_AMDGCN_GFX700", ELF::EF_AMDGPU_MACH_AMDGCN_GFX700 }, | |||
1345 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701){ "EF_AMDGPU_MACH_AMDGCN_GFX701", ELF::EF_AMDGPU_MACH_AMDGCN_GFX701 }, | |||
1346 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702){ "EF_AMDGPU_MACH_AMDGCN_GFX702", ELF::EF_AMDGPU_MACH_AMDGCN_GFX702 }, | |||
1347 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703){ "EF_AMDGPU_MACH_AMDGCN_GFX703", ELF::EF_AMDGPU_MACH_AMDGCN_GFX703 }, | |||
1348 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704){ "EF_AMDGPU_MACH_AMDGCN_GFX704", ELF::EF_AMDGPU_MACH_AMDGCN_GFX704 }, | |||
1349 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801){ "EF_AMDGPU_MACH_AMDGCN_GFX801", ELF::EF_AMDGPU_MACH_AMDGCN_GFX801 }, | |||
1350 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802){ "EF_AMDGPU_MACH_AMDGCN_GFX802", ELF::EF_AMDGPU_MACH_AMDGCN_GFX802 }, | |||
1351 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803){ "EF_AMDGPU_MACH_AMDGCN_GFX803", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803 }, | |||
1352 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810){ "EF_AMDGPU_MACH_AMDGCN_GFX810", ELF::EF_AMDGPU_MACH_AMDGCN_GFX810 }, | |||
1353 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900){ "EF_AMDGPU_MACH_AMDGCN_GFX900", ELF::EF_AMDGPU_MACH_AMDGCN_GFX900 }, | |||
1354 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902){ "EF_AMDGPU_MACH_AMDGCN_GFX902", ELF::EF_AMDGPU_MACH_AMDGCN_GFX902 }, | |||
1355 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904){ "EF_AMDGPU_MACH_AMDGCN_GFX904", ELF::EF_AMDGPU_MACH_AMDGCN_GFX904 }, | |||
1356 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906){ "EF_AMDGPU_MACH_AMDGCN_GFX906", ELF::EF_AMDGPU_MACH_AMDGCN_GFX906 }, | |||
1357 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909){ "EF_AMDGPU_MACH_AMDGCN_GFX909", ELF::EF_AMDGPU_MACH_AMDGCN_GFX909 }, | |||
1358 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_XNACK){ "EF_AMDGPU_XNACK", ELF::EF_AMDGPU_XNACK } | |||
1359 | }; | |||
1360 | ||||
1361 | static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = { | |||
1362 | ENUM_ENT(EF_RISCV_RVC, "RVC"){ "EF_RISCV_RVC", "RVC", ELF::EF_RISCV_RVC }, | |||
1363 | ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"){ "EF_RISCV_FLOAT_ABI_SINGLE", "single-float ABI", ELF::EF_RISCV_FLOAT_ABI_SINGLE }, | |||
1364 | ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"){ "EF_RISCV_FLOAT_ABI_DOUBLE", "double-float ABI", ELF::EF_RISCV_FLOAT_ABI_DOUBLE }, | |||
1365 | ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"){ "EF_RISCV_FLOAT_ABI_QUAD", "quad-float ABI", ELF::EF_RISCV_FLOAT_ABI_QUAD }, | |||
1366 | ENUM_ENT(EF_RISCV_RVE, "RVE"){ "EF_RISCV_RVE", "RVE", ELF::EF_RISCV_RVE } | |||
1367 | }; | |||
1368 | ||||
1369 | static const EnumEntry<unsigned> ElfSymOtherFlags[] = { | |||
1370 | LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL){ "STV_INTERNAL", ELF::STV_INTERNAL }, | |||
1371 | LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN){ "STV_HIDDEN", ELF::STV_HIDDEN }, | |||
1372 | LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED){ "STV_PROTECTED", ELF::STV_PROTECTED } | |||
1373 | }; | |||
1374 | ||||
1375 | static const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = { | |||
1376 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL){ "STO_MIPS_OPTIONAL", ELF::STO_MIPS_OPTIONAL }, | |||
1377 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT){ "STO_MIPS_PLT", ELF::STO_MIPS_PLT }, | |||
1378 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC){ "STO_MIPS_PIC", ELF::STO_MIPS_PIC }, | |||
1379 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS){ "STO_MIPS_MICROMIPS", ELF::STO_MIPS_MICROMIPS } | |||
1380 | }; | |||
1381 | ||||
1382 | static const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = { | |||
1383 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL){ "STO_MIPS_OPTIONAL", ELF::STO_MIPS_OPTIONAL }, | |||
1384 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT){ "STO_MIPS_PLT", ELF::STO_MIPS_PLT }, | |||
1385 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16){ "STO_MIPS_MIPS16", ELF::STO_MIPS_MIPS16 } | |||
1386 | }; | |||
1387 | ||||
1388 | static const char *getElfMipsOptionsOdkType(unsigned Odk) { | |||
1389 | switch (Odk) { | |||
1390 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL)case ELF::ODK_NULL: return "ODK_NULL";; | |||
1391 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO)case ELF::ODK_REGINFO: return "ODK_REGINFO";; | |||
1392 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS)case ELF::ODK_EXCEPTIONS: return "ODK_EXCEPTIONS";; | |||
1393 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD)case ELF::ODK_PAD: return "ODK_PAD";; | |||
1394 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH)case ELF::ODK_HWPATCH: return "ODK_HWPATCH";; | |||
1395 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL)case ELF::ODK_FILL: return "ODK_FILL";; | |||
1396 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS)case ELF::ODK_TAGS: return "ODK_TAGS";; | |||
1397 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND)case ELF::ODK_HWAND: return "ODK_HWAND";; | |||
1398 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR)case ELF::ODK_HWOR: return "ODK_HWOR";; | |||
1399 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP)case ELF::ODK_GP_GROUP: return "ODK_GP_GROUP";; | |||
1400 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT)case ELF::ODK_IDENT: return "ODK_IDENT";; | |||
1401 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE)case ELF::ODK_PAGESIZE: return "ODK_PAGESIZE";; | |||
1402 | default: | |||
1403 | return "Unknown"; | |||
1404 | } | |||
1405 | } | |||
1406 | ||||
1407 | template <typename ELFT> | |||
1408 | ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer) | |||
1409 | : ObjDumper(Writer), Obj(Obj) { | |||
1410 | SmallVector<const Elf_Phdr *, 4> LoadSegments; | |||
1411 | for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { | |||
1412 | if (Phdr.p_type == ELF::PT_DYNAMIC) { | |||
1413 | DynamicTable = createDRIFrom(&Phdr, sizeof(Elf_Dyn)); | |||
1414 | continue; | |||
1415 | } | |||
1416 | if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) | |||
1417 | continue; | |||
1418 | LoadSegments.push_back(&Phdr); | |||
1419 | } | |||
1420 | ||||
1421 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | |||
1422 | switch (Sec.sh_type) { | |||
1423 | case ELF::SHT_SYMTAB: | |||
1424 | if (DotSymtabSec != nullptr) | |||
1425 | reportError("Multiple SHT_SYMTAB"); | |||
1426 | DotSymtabSec = &Sec; | |||
1427 | break; | |||
1428 | case ELF::SHT_DYNSYM: | |||
1429 | if (DynSymRegion.Size) | |||
1430 | reportError("Multiple SHT_DYNSYM"); | |||
1431 | DynSymRegion = createDRIFrom(&Sec); | |||
1432 | // This is only used (if Elf_Shdr present)for naming section in GNU style | |||
1433 | DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec)); | |||
1434 | DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec)); | |||
1435 | break; | |||
1436 | case ELF::SHT_SYMTAB_SHNDX: | |||
1437 | ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec)); | |||
1438 | break; | |||
1439 | case ELF::SHT_GNU_versym: | |||
1440 | if (dot_gnu_version_sec != nullptr) | |||
1441 | reportError("Multiple SHT_GNU_versym"); | |||
1442 | dot_gnu_version_sec = &Sec; | |||
1443 | break; | |||
1444 | case ELF::SHT_GNU_verdef: | |||
1445 | if (dot_gnu_version_d_sec != nullptr) | |||
1446 | reportError("Multiple SHT_GNU_verdef"); | |||
1447 | dot_gnu_version_d_sec = &Sec; | |||
1448 | break; | |||
1449 | case ELF::SHT_GNU_verneed: | |||
1450 | if (dot_gnu_version_r_sec != nullptr) | |||
1451 | reportError("Multiple SHT_GNU_verneed"); | |||
1452 | dot_gnu_version_r_sec = &Sec; | |||
1453 | break; | |||
1454 | case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: | |||
1455 | if (DotCGProfileSec != nullptr) | |||
1456 | reportError("Multiple .llvm.call-graph-profile"); | |||
1457 | DotCGProfileSec = &Sec; | |||
1458 | break; | |||
1459 | case ELF::SHT_LLVM_ADDRSIG: | |||
1460 | if (DotAddrsigSec != nullptr) | |||
1461 | reportError("Multiple .llvm_addrsig"); | |||
1462 | DotAddrsigSec = &Sec; | |||
1463 | break; | |||
1464 | } | |||
1465 | } | |||
1466 | ||||
1467 | parseDynamicTable(LoadSegments); | |||
1468 | ||||
1469 | if (opts::Output == opts::GNU) | |||
1470 | ELFDumperStyle.reset(new GNUStyle<ELFT>(Writer, this)); | |||
1471 | else | |||
1472 | ELFDumperStyle.reset(new LLVMStyle<ELFT>(Writer, this)); | |||
1473 | } | |||
1474 | ||||
1475 | template <typename ELFT> | |||
1476 | void ELFDumper<ELFT>::parseDynamicTable( | |||
1477 | ArrayRef<const Elf_Phdr *> LoadSegments) { | |||
1478 | auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * { | |||
1479 | const Elf_Phdr *const *I = | |||
1480 | std::upper_bound(LoadSegments.begin(), LoadSegments.end(), VAddr, | |||
1481 | [](uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { | |||
1482 | return VAddr < Phdr->p_vaddr; | |||
1483 | }); | |||
1484 | if (I == LoadSegments.begin()) | |||
1485 | report_fatal_error("Virtual address is not in any segment"); | |||
1486 | --I; | |||
1487 | const Elf_Phdr &Phdr = **I; | |||
1488 | uint64_t Delta = VAddr - Phdr.p_vaddr; | |||
1489 | if (Delta >= Phdr.p_filesz) | |||
1490 | report_fatal_error("Virtual address is not in any segment"); | |||
1491 | return Obj->base() + Phdr.p_offset + Delta; | |||
1492 | }; | |||
1493 | ||||
1494 | uint64_t SONameOffset = 0; | |||
1495 | const char *StringTableBegin = nullptr; | |||
1496 | uint64_t StringTableSize = 0; | |||
1497 | for (const Elf_Dyn &Dyn : dynamic_table()) { | |||
1498 | switch (Dyn.d_tag) { | |||
1499 | case ELF::DT_HASH: | |||
1500 | HashTable = | |||
1501 | reinterpret_cast<const Elf_Hash *>(toMappedAddr(Dyn.getPtr())); | |||
1502 | break; | |||
1503 | case ELF::DT_GNU_HASH: | |||
1504 | GnuHashTable = | |||
1505 | reinterpret_cast<const Elf_GnuHash *>(toMappedAddr(Dyn.getPtr())); | |||
1506 | break; | |||
1507 | case ELF::DT_STRTAB: | |||
1508 | StringTableBegin = (const char *)toMappedAddr(Dyn.getPtr()); | |||
1509 | break; | |||
1510 | case ELF::DT_STRSZ: | |||
1511 | StringTableSize = Dyn.getVal(); | |||
1512 | break; | |||
1513 | case ELF::DT_SYMTAB: | |||
1514 | DynSymRegion.Addr = toMappedAddr(Dyn.getPtr()); | |||
1515 | DynSymRegion.EntSize = sizeof(Elf_Sym); | |||
1516 | break; | |||
1517 | case ELF::DT_RELA: | |||
1518 | DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr()); | |||
1519 | break; | |||
1520 | case ELF::DT_RELASZ: | |||
1521 | DynRelaRegion.Size = Dyn.getVal(); | |||
1522 | break; | |||
1523 | case ELF::DT_RELAENT: | |||
1524 | DynRelaRegion.EntSize = Dyn.getVal(); | |||
1525 | break; | |||
1526 | case ELF::DT_SONAME: | |||
1527 | SONameOffset = Dyn.getVal(); | |||
1528 | break; | |||
1529 | case ELF::DT_REL: | |||
1530 | DynRelRegion.Addr = toMappedAddr(Dyn.getPtr()); | |||
1531 | break; | |||
1532 | case ELF::DT_RELSZ: | |||
1533 | DynRelRegion.Size = Dyn.getVal(); | |||
1534 | break; | |||
1535 | case ELF::DT_RELENT: | |||
1536 | DynRelRegion.EntSize = Dyn.getVal(); | |||
1537 | break; | |||
1538 | case ELF::DT_RELR: | |||
1539 | case ELF::DT_ANDROID_RELR: | |||
1540 | DynRelrRegion.Addr = toMappedAddr(Dyn.getPtr()); | |||
1541 | break; | |||
1542 | case ELF::DT_RELRSZ: | |||
1543 | case ELF::DT_ANDROID_RELRSZ: | |||
1544 | DynRelrRegion.Size = Dyn.getVal(); | |||
1545 | break; | |||
1546 | case ELF::DT_RELRENT: | |||
1547 | case ELF::DT_ANDROID_RELRENT: | |||
1548 | DynRelrRegion.EntSize = Dyn.getVal(); | |||
1549 | break; | |||
1550 | case ELF::DT_PLTREL: | |||
1551 | if (Dyn.getVal() == DT_REL) | |||
1552 | DynPLTRelRegion.EntSize = sizeof(Elf_Rel); | |||
1553 | else if (Dyn.getVal() == DT_RELA) | |||
1554 | DynPLTRelRegion.EntSize = sizeof(Elf_Rela); | |||
1555 | else | |||
1556 | reportError(Twine("unknown DT_PLTREL value of ") + | |||
1557 | Twine((uint64_t)Dyn.getVal())); | |||
1558 | break; | |||
1559 | case ELF::DT_JMPREL: | |||
1560 | DynPLTRelRegion.Addr = toMappedAddr(Dyn.getPtr()); | |||
1561 | break; | |||
1562 | case ELF::DT_PLTRELSZ: | |||
1563 | DynPLTRelRegion.Size = Dyn.getVal(); | |||
1564 | break; | |||
1565 | } | |||
1566 | } | |||
1567 | if (StringTableBegin) | |||
1568 | DynamicStringTable = StringRef(StringTableBegin, StringTableSize); | |||
1569 | if (SONameOffset) | |||
1570 | SOName = getDynamicString(SONameOffset); | |||
1571 | } | |||
1572 | ||||
1573 | template <typename ELFT> | |||
1574 | typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const { | |||
1575 | return DynRelRegion.getAsArrayRef<Elf_Rel>(); | |||
1576 | } | |||
1577 | ||||
1578 | template <typename ELFT> | |||
1579 | typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const { | |||
1580 | return DynRelaRegion.getAsArrayRef<Elf_Rela>(); | |||
1581 | } | |||
1582 | ||||
1583 | template <typename ELFT> | |||
1584 | typename ELFDumper<ELFT>::Elf_Relr_Range ELFDumper<ELFT>::dyn_relrs() const { | |||
1585 | return DynRelrRegion.getAsArrayRef<Elf_Relr>(); | |||
1586 | } | |||
1587 | ||||
1588 | template<class ELFT> | |||
1589 | void ELFDumper<ELFT>::printFileHeaders() { | |||
1590 | ELFDumperStyle->printFileHeaders(Obj); | |||
1591 | } | |||
1592 | ||||
1593 | template<class ELFT> | |||
1594 | void ELFDumper<ELFT>::printSections() { | |||
1595 | ELFDumperStyle->printSections(Obj); | |||
1596 | } | |||
1597 | ||||
1598 | template<class ELFT> | |||
1599 | void ELFDumper<ELFT>::printRelocations() { | |||
1600 | ELFDumperStyle->printRelocations(Obj); | |||
1601 | } | |||
1602 | ||||
1603 | template <class ELFT> void ELFDumper<ELFT>::printProgramHeaders() { | |||
1604 | ELFDumperStyle->printProgramHeaders(Obj); | |||
1605 | } | |||
1606 | ||||
1607 | template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() { | |||
1608 | ELFDumperStyle->printDynamicRelocations(Obj); | |||
1609 | } | |||
1610 | ||||
1611 | template<class ELFT> | |||
1612 | void ELFDumper<ELFT>::printSymbols() { | |||
1613 | ELFDumperStyle->printSymbols(Obj); | |||
1614 | } | |||
1615 | ||||
1616 | template<class ELFT> | |||
1617 | void ELFDumper<ELFT>::printDynamicSymbols() { | |||
1618 | ELFDumperStyle->printDynamicSymbols(Obj); | |||
1619 | } | |||
1620 | ||||
1621 | template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() { | |||
1622 | ELFDumperStyle->printHashHistogram(Obj); | |||
1623 | } | |||
1624 | ||||
1625 | template <class ELFT> void ELFDumper<ELFT>::printCGProfile() { | |||
1626 | ELFDumperStyle->printCGProfile(Obj); | |||
1627 | } | |||
1628 | ||||
1629 | template <class ELFT> void ELFDumper<ELFT>::printNotes() { | |||
1630 | ELFDumperStyle->printNotes(Obj); | |||
1631 | } | |||
1632 | ||||
1633 | template <class ELFT> void ELFDumper<ELFT>::printELFLinkerOptions() { | |||
1634 | ELFDumperStyle->printELFLinkerOptions(Obj); | |||
1635 | } | |||
1636 | ||||
1637 | static const char *getTypeString(unsigned Arch, uint64_t Type) { | |||
1638 | #define DYNAMIC_TAG(n, v) | |||
1639 | switch (Arch) { | |||
1640 | case EM_HEXAGON: | |||
1641 | switch (Type) { | |||
1642 | #define HEXAGON_DYNAMIC_TAG(name, value) \ | |||
1643 | case DT_##name: \ | |||
1644 | return #name; | |||
1645 | #include "llvm/BinaryFormat/DynamicTags.def" | |||
1646 | #undef HEXAGON_DYNAMIC_TAG | |||
1647 | } | |||
1648 | break; | |||
1649 | ||||
1650 | case EM_MIPS: | |||
1651 | switch (Type) { | |||
1652 | #define MIPS_DYNAMIC_TAG(name, value) \ | |||
1653 | case DT_##name: \ | |||
1654 | return #name; | |||
1655 | #include "llvm/BinaryFormat/DynamicTags.def" | |||
1656 | #undef MIPS_DYNAMIC_TAG | |||
1657 | } | |||
1658 | break; | |||
1659 | ||||
1660 | case EM_PPC64: | |||
1661 | switch(Type) { | |||
1662 | #define PPC64_DYNAMIC_TAG(name, value) \ | |||
1663 | case DT_##name: \ | |||
1664 | return #name; | |||
1665 | #include "llvm/BinaryFormat/DynamicTags.def" | |||
1666 | #undef PPC64_DYNAMIC_TAG | |||
1667 | } | |||
1668 | break; | |||
1669 | } | |||
1670 | #undef DYNAMIC_TAG | |||
1671 | switch (Type) { | |||
1672 | // Now handle all dynamic tags except the architecture specific ones | |||
1673 | #define MIPS_DYNAMIC_TAG(name, value) | |||
1674 | #define HEXAGON_DYNAMIC_TAG(name, value) | |||
1675 | #define PPC64_DYNAMIC_TAG(name, value) | |||
1676 | // Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. | |||
1677 | #define DYNAMIC_TAG_MARKER(name, value) | |||
1678 | #define DYNAMIC_TAG(name, value) \ | |||
1679 | case DT_##name: \ | |||
1680 | return #name; | |||
1681 | #include "llvm/BinaryFormat/DynamicTags.def" | |||
1682 | #undef DYNAMIC_TAG | |||
1683 | #undef MIPS_DYNAMIC_TAG | |||
1684 | #undef HEXAGON_DYNAMIC_TAG | |||
1685 | #undef PPC64_DYNAMIC_TAG | |||
1686 | #undef DYNAMIC_TAG_MARKER | |||
1687 | default: return "unknown"; | |||
1688 | } | |||
1689 | } | |||
1690 | ||||
1691 | #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ | |||
1692 | { #enum, prefix##_##enum } | |||
1693 | ||||
1694 | static const EnumEntry<unsigned> ElfDynamicDTFlags[] = { | |||
1695 | LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), | |||
1696 | LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), | |||
1697 | LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), | |||
1698 | LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), | |||
1699 | LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) | |||
1700 | }; | |||
1701 | ||||
1702 | static const EnumEntry<unsigned> ElfDynamicDTFlags1[] = { | |||
1703 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW), | |||
1704 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL), | |||
1705 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP), | |||
1706 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE), | |||
1707 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR), | |||
1708 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST), | |||
1709 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN), | |||
1710 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN), | |||
1711 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT), | |||
1712 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS), | |||
1713 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE), | |||
1714 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB), | |||
1715 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP), | |||
1716 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT), | |||
1717 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE), | |||
1718 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE), | |||
1719 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT), | |||
1720 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF), | |||
1721 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS), | |||
1722 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR), | |||
1723 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED), | |||
1724 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC), | |||
1725 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE), | |||
1726 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT), | |||
1727 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON) | |||
1728 | }; | |||
1729 | ||||
1730 | static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { | |||
1731 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), | |||
1732 | LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), | |||
1733 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), | |||
1734 | LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), | |||
1735 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), | |||
1736 | LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), | |||
1737 | LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), | |||
1738 | LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), | |||
1739 | LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), | |||
1740 | LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), | |||
1741 | LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), | |||
1742 | LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), | |||
1743 | LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), | |||
1744 | LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), | |||
1745 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), | |||
1746 | LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) | |||
1747 | }; | |||
1748 | ||||
1749 | #undef LLVM_READOBJ_DT_FLAG_ENT | |||
1750 | ||||
1751 | template <typename T, typename TFlag> | |||
1752 | void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { | |||
1753 | using FlagEntry = EnumEntry<TFlag>; | |||
1754 | using FlagVector = SmallVector<FlagEntry, 10>; | |||
1755 | FlagVector SetFlags; | |||
1756 | ||||
1757 | for (const auto &Flag : Flags) { | |||
1758 | if (Flag.Value == 0) | |||
1759 | continue; | |||
1760 | ||||
1761 | if ((Value & Flag.Value) == Flag.Value) | |||
1762 | SetFlags.push_back(Flag); | |||
1763 | } | |||
1764 | ||||
1765 | for (const auto &Flag : SetFlags) { | |||
1766 | OS << Flag.Name << " "; | |||
1767 | } | |||
1768 | } | |||
1769 | ||||
1770 | template <class ELFT> | |||
1771 | StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const { | |||
1772 | if (Value >= DynamicStringTable.size()) | |||
1773 | reportError("Invalid dynamic string table reference"); | |||
1774 | return StringRef(DynamicStringTable.data() + Value); | |||
1775 | } | |||
1776 | ||||
1777 | static void printLibrary(raw_ostream &OS, const Twine &Tag, const Twine &Name) { | |||
1778 | OS << Tag << ": [" << Name << "]"; | |||
1779 | } | |||
1780 | ||||
1781 | template <class ELFT> | |||
1782 | void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { | |||
1783 | raw_ostream &OS = W.getOStream(); | |||
1784 | const char* ConvChar = (opts::Output == opts::GNU) ? "0x%" PRIx64"l" "x" : "0x%" PRIX64"l" "X"; | |||
1785 | switch (Type) { | |||
1786 | case DT_PLTREL: | |||
1787 | if (Value == DT_REL) { | |||
1788 | OS << "REL"; | |||
1789 | break; | |||
1790 | } else if (Value == DT_RELA) { | |||
1791 | OS << "RELA"; | |||
1792 | break; | |||
1793 | } | |||
1794 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
1795 | case DT_PLTGOT: | |||
1796 | case DT_HASH: | |||
1797 | case DT_STRTAB: | |||
1798 | case DT_SYMTAB: | |||
1799 | case DT_RELA: | |||
1800 | case DT_INIT: | |||
1801 | case DT_FINI: | |||
1802 | case DT_REL: | |||
1803 | case DT_JMPREL: | |||
1804 | case DT_INIT_ARRAY: | |||
1805 | case DT_FINI_ARRAY: | |||
1806 | case DT_PREINIT_ARRAY: | |||
1807 | case DT_DEBUG: | |||
1808 | case DT_VERDEF: | |||
1809 | case DT_VERNEED: | |||
1810 | case DT_VERSYM: | |||
1811 | case DT_GNU_HASH: | |||
1812 | case DT_NULL: | |||
1813 | case DT_MIPS_BASE_ADDRESS: | |||
1814 | case DT_MIPS_GOTSYM: | |||
1815 | case DT_MIPS_RLD_MAP: | |||
1816 | case DT_MIPS_RLD_MAP_REL: | |||
1817 | case DT_MIPS_PLTGOT: | |||
1818 | case DT_MIPS_OPTIONS: | |||
1819 | OS << format(ConvChar, Value); | |||
1820 | break; | |||
1821 | case DT_RELACOUNT: | |||
1822 | case DT_RELCOUNT: | |||
1823 | case DT_VERDEFNUM: | |||
1824 | case DT_VERNEEDNUM: | |||
1825 | case DT_MIPS_RLD_VERSION: | |||
1826 | case DT_MIPS_LOCAL_GOTNO: | |||
1827 | case DT_MIPS_SYMTABNO: | |||
1828 | case DT_MIPS_UNREFEXTNO: | |||
1829 | OS << Value; | |||
1830 | break; | |||
1831 | case DT_PLTRELSZ: | |||
1832 | case DT_RELASZ: | |||
1833 | case DT_RELAENT: | |||
1834 | case DT_STRSZ: | |||
1835 | case DT_SYMENT: | |||
1836 | case DT_RELSZ: | |||
1837 | case DT_RELENT: | |||
1838 | case DT_INIT_ARRAYSZ: | |||
1839 | case DT_FINI_ARRAYSZ: | |||
1840 | case DT_PREINIT_ARRAYSZ: | |||
1841 | case DT_ANDROID_RELSZ: | |||
1842 | case DT_ANDROID_RELASZ: | |||
1843 | OS << Value << " (bytes)"; | |||
1844 | break; | |||
1845 | case DT_NEEDED: | |||
1846 | printLibrary(OS, "Shared library", getDynamicString(Value)); | |||
1847 | break; | |||
1848 | case DT_SONAME: | |||
1849 | printLibrary(OS, "Library soname", getDynamicString(Value)); | |||
1850 | break; | |||
1851 | case DT_AUXILIARY: | |||
1852 | printLibrary(OS, "Auxiliary library", getDynamicString(Value)); | |||
1853 | break; | |||
1854 | case DT_FILTER: | |||
1855 | printLibrary(OS, "Filter library", getDynamicString(Value)); | |||
1856 | break; | |||
1857 | case DT_RPATH: | |||
1858 | case DT_RUNPATH: | |||
1859 | OS << getDynamicString(Value); | |||
1860 | break; | |||
1861 | case DT_MIPS_FLAGS: | |||
1862 | printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS); | |||
1863 | break; | |||
1864 | case DT_FLAGS: | |||
1865 | printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS); | |||
1866 | break; | |||
1867 | case DT_FLAGS_1: | |||
1868 | printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS); | |||
1869 | break; | |||
1870 | default: | |||
1871 | OS << format(ConvChar, Value); | |||
1872 | break; | |||
1873 | } | |||
1874 | } | |||
1875 | ||||
1876 | template<class ELFT> | |||
1877 | void ELFDumper<ELFT>::printUnwindInfo() { | |||
1878 | const unsigned Machine = Obj->getHeader()->e_machine; | |||
1879 | if (Machine == EM_386 || Machine == EM_X86_64) { | |||
1880 | DwarfCFIEH::PrinterContext<ELFT> Ctx(W, Obj); | |||
1881 | return Ctx.printUnwindInformation(); | |||
1882 | } | |||
1883 | W.startLine() << "UnwindInfo not implemented.\n"; | |||
1884 | } | |||
1885 | ||||
1886 | namespace { | |||
1887 | ||||
1888 | template <> void ELFDumper<ELF32LE>::printUnwindInfo() { | |||
1889 | const unsigned Machine = Obj->getHeader()->e_machine; | |||
1890 | if (Machine == EM_ARM) { | |||
1891 | ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, DotSymtabSec); | |||
1892 | return Ctx.PrintUnwindInformation(); | |||
1893 | } | |||
1894 | W.startLine() << "UnwindInfo not implemented.\n"; | |||
1895 | } | |||
1896 | ||||
1897 | } // end anonymous namespace | |||
1898 | ||||
1899 | template<class ELFT> | |||
1900 | void ELFDumper<ELFT>::printDynamicTable() { | |||
1901 | auto I = dynamic_table().begin(); | |||
1902 | auto E = dynamic_table().end(); | |||
1903 | ||||
1904 | if (I == E) | |||
1905 | return; | |||
1906 | ||||
1907 | --E; | |||
1908 | while (I != E && E->getTag() == ELF::DT_NULL) | |||
1909 | --E; | |||
1910 | if (E->getTag() != ELF::DT_NULL) | |||
1911 | ++E; | |||
1912 | ++E; | |||
1913 | ||||
1914 | ptrdiff_t Total = std::distance(I, E); | |||
1915 | if (Total == 0) | |||
1916 | return; | |||
1917 | ||||
1918 | raw_ostream &OS = W.getOStream(); | |||
1919 | W.startLine() << "DynamicSection [ (" << Total << " entries)\n"; | |||
1920 | ||||
1921 | bool Is64 = ELFT::Is64Bits; | |||
1922 | ||||
1923 | W.startLine() | |||
1924 | << " Tag" << (Is64 ? " " : " ") << "Type" | |||
1925 | << " " << "Name/Value\n"; | |||
1926 | while (I != E) { | |||
1927 | const Elf_Dyn &Entry = *I; | |||
1928 | uintX_t Tag = Entry.getTag(); | |||
1929 | ++I; | |||
1930 | W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, opts::Output != opts::GNU) << " " | |||
1931 | << format("%-21s", getTypeString(Obj->getHeader()->e_machine, Tag)); | |||
1932 | printValue(Tag, Entry.getVal()); | |||
1933 | OS << "\n"; | |||
1934 | } | |||
1935 | ||||
1936 | W.startLine() << "]\n"; | |||
1937 | } | |||
1938 | ||||
1939 | template<class ELFT> | |||
1940 | void ELFDumper<ELFT>::printNeededLibraries() { | |||
1941 | ListScope D(W, "NeededLibraries"); | |||
1942 | ||||
1943 | using LibsTy = std::vector<StringRef>; | |||
1944 | LibsTy Libs; | |||
1945 | ||||
1946 | for (const auto &Entry : dynamic_table()) | |||
1947 | if (Entry.d_tag == ELF::DT_NEEDED) | |||
1948 | Libs.push_back(getDynamicString(Entry.d_un.d_val)); | |||
1949 | ||||
1950 | std::stable_sort(Libs.begin(), Libs.end()); | |||
1951 | ||||
1952 | for (const auto &L : Libs) | |||
1953 | W.startLine() << L << "\n"; | |||
1954 | } | |||
1955 | ||||
1956 | ||||
1957 | template <typename ELFT> | |||
1958 | void ELFDumper<ELFT>::printHashTable() { | |||
1959 | DictScope D(W, "HashTable"); | |||
1960 | if (!HashTable) | |||
1961 | return; | |||
1962 | W.printNumber("Num Buckets", HashTable->nbucket); | |||
1963 | W.printNumber("Num Chains", HashTable->nchain); | |||
1964 | W.printList("Buckets", HashTable->buckets()); | |||
1965 | W.printList("Chains", HashTable->chains()); | |||
1966 | } | |||
1967 | ||||
1968 | template <typename ELFT> | |||
1969 | void ELFDumper<ELFT>::printGnuHashTable() { | |||
1970 | DictScope D(W, "GnuHashTable"); | |||
1971 | if (!GnuHashTable) | |||
1972 | return; | |||
1973 | W.printNumber("Num Buckets", GnuHashTable->nbuckets); | |||
1974 | W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx); | |||
1975 | W.printNumber("Num Mask Words", GnuHashTable->maskwords); | |||
1976 | W.printNumber("Shift Count", GnuHashTable->shift2); | |||
1977 | W.printHexList("Bloom Filter", GnuHashTable->filter()); | |||
1978 | W.printList("Buckets", GnuHashTable->buckets()); | |||
1979 | Elf_Sym_Range Syms = dynamic_symbols(); | |||
1980 | unsigned NumSyms = std::distance(Syms.begin(), Syms.end()); | |||
1981 | if (!NumSyms) | |||
1982 | reportError("No dynamic symbol section"); | |||
1983 | W.printHexList("Values", GnuHashTable->values(NumSyms)); | |||
1984 | } | |||
1985 | ||||
1986 | template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { | |||
1987 | W.printString("LoadName", SOName); | |||
1988 | } | |||
1989 | ||||
1990 | template <class ELFT> | |||
1991 | void ELFDumper<ELFT>::printAttributes() { | |||
1992 | W.startLine() << "Attributes not implemented.\n"; | |||
1993 | } | |||
1994 | ||||
1995 | namespace { | |||
1996 | ||||
1997 | template <> void ELFDumper<ELF32LE>::printAttributes() { | |||
1998 | if (Obj->getHeader()->e_machine != EM_ARM) { | |||
1999 | W.startLine() << "Attributes not implemented.\n"; | |||
2000 | return; | |||
2001 | } | |||
2002 | ||||
2003 | DictScope BA(W, "BuildAttributes"); | |||
2004 | for (const ELFO::Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | |||
2005 | if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES) | |||
2006 | continue; | |||
2007 | ||||
2008 | ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Sec)); | |||
2009 | if (Contents[0] != ARMBuildAttrs::Format_Version) { | |||
2010 | errs() << "unrecognised FormatVersion: 0x" | |||
2011 | << Twine::utohexstr(Contents[0]) << '\n'; | |||
2012 | continue; | |||
2013 | } | |||
2014 | ||||
2015 | W.printHex("FormatVersion", Contents[0]); | |||
2016 | if (Contents.size() == 1) | |||
2017 | continue; | |||
2018 | ||||
2019 | ARMAttributeParser(&W).Parse(Contents, true); | |||
2020 | } | |||
2021 | } | |||
2022 | ||||
2023 | template <class ELFT> class MipsGOTParser { | |||
2024 | public: | |||
2025 | TYPEDEF_ELF_TYPES(ELFT)using ELFO = ELFFile<ELFT>; using Elf_Addr = typename ELFT ::Addr; using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; using Elf_Dyn = typename ELFT::Dyn; using Elf_Dyn_Range = typename ELFT::DynRange; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; using Elf_Relr = typename ELFT::Relr; using Elf_Rel_Range = typename ELFT:: RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr = typename ELFT::Phdr; using Elf_Half = typename ELFT::Half; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Word = typename ELFT::Word; using Elf_Hash = typename ELFT::Hash; using Elf_GnuHash = typename ELFT::GnuHash; using Elf_Note = typename ELFT::Note; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Versym = typename ELFT:: Versym; using Elf_Verneed = typename ELFT::Verneed; using Elf_Vernaux = typename ELFT::Vernaux; using Elf_Verdef = typename ELFT:: Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_CGProfile = typename ELFT::CGProfile; using uintX_t = typename ELFT::uint ; | |||
2026 | using Entry = typename ELFO::Elf_Addr; | |||
2027 | using Entries = ArrayRef<Entry>; | |||
2028 | ||||
2029 | const bool IsStatic; | |||
2030 | const ELFO * const Obj; | |||
2031 | ||||
2032 | MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms); | |||
2033 | ||||
2034 | bool hasGot() const { return !GotEntries.empty(); } | |||
2035 | bool hasPlt() const { return !PltEntries.empty(); } | |||
2036 | ||||
2037 | uint64_t getGp() const; | |||
2038 | ||||
2039 | const Entry *getGotLazyResolver() const; | |||
2040 | const Entry *getGotModulePointer() const; | |||
2041 | const Entry *getPltLazyResolver() const; | |||
2042 | const Entry *getPltModulePointer() const; | |||
2043 | ||||
2044 | Entries getLocalEntries() const; | |||
2045 | Entries getGlobalEntries() const; | |||
2046 | Entries getOtherEntries() const; | |||
2047 | Entries getPltEntries() const; | |||
2048 | ||||
2049 | uint64_t getGotAddress(const Entry * E) const; | |||
2050 | int64_t getGotOffset(const Entry * E) const; | |||
2051 | const Elf_Sym *getGotSym(const Entry *E) const; | |||
2052 | ||||
2053 | uint64_t getPltAddress(const Entry * E) const; | |||
2054 | const Elf_Sym *getPltSym(const Entry *E) const; | |||
2055 | ||||
2056 | StringRef getPltStrTable() const { return PltStrTable; } | |||
2057 | ||||
2058 | private: | |||
2059 | const Elf_Shdr *GotSec; | |||
2060 | size_t LocalNum; | |||
2061 | size_t GlobalNum; | |||
2062 | ||||
2063 | const Elf_Shdr *PltSec; | |||
2064 | const Elf_Shdr *PltRelSec; | |||
2065 | const Elf_Shdr *PltSymTable; | |||
2066 | Elf_Sym_Range GotDynSyms; | |||
2067 | StringRef PltStrTable; | |||
2068 | ||||
2069 | Entries GotEntries; | |||
2070 | Entries PltEntries; | |||
2071 | }; | |||
2072 | ||||
2073 | } // end anonymous namespace | |||
2074 | ||||
2075 | template <class ELFT> | |||
2076 | MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, | |||
2077 | Elf_Sym_Range DynSyms) | |||
2078 | : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0), | |||
2079 | GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) { | |||
2080 | // See "Global Offset Table" in Chapter 5 in the following document | |||
2081 | // for detailed GOT description. | |||
2082 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | |||
2083 | ||||
2084 | // Find static GOT secton. | |||
2085 | if (IsStatic) { | |||
2086 | GotSec = findSectionByName(*Obj, ".got"); | |||
2087 | if (!GotSec) | |||
2088 | reportError("Cannot find .got section"); | |||
2089 | ||||
2090 | ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); | |||
2091 | GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), | |||
2092 | Content.size() / sizeof(Entry)); | |||
2093 | LocalNum = GotEntries.size(); | |||
2094 | return; | |||
2095 | } | |||
2096 | ||||
2097 | // Lookup dynamic table tags which define GOT/PLT layouts. | |||
2098 | Optional<uint64_t> DtPltGot; | |||
2099 | Optional<uint64_t> DtLocalGotNum; | |||
2100 | Optional<uint64_t> DtGotSym; | |||
2101 | Optional<uint64_t> DtMipsPltGot; | |||
2102 | Optional<uint64_t> DtJmpRel; | |||
2103 | for (const auto &Entry : DynTable) { | |||
2104 | switch (Entry.getTag()) { | |||
2105 | case ELF::DT_PLTGOT: | |||
2106 | DtPltGot = Entry.getVal(); | |||
2107 | break; | |||
2108 | case ELF::DT_MIPS_LOCAL_GOTNO: | |||
2109 | DtLocalGotNum = Entry.getVal(); | |||
2110 | break; | |||
2111 | case ELF::DT_MIPS_GOTSYM: | |||
2112 | DtGotSym = Entry.getVal(); | |||
2113 | break; | |||
2114 | case ELF::DT_MIPS_PLTGOT: | |||
2115 | DtMipsPltGot = Entry.getVal(); | |||
2116 | break; | |||
2117 | case ELF::DT_JMPREL: | |||
2118 | DtJmpRel = Entry.getVal(); | |||
2119 | break; | |||
2120 | } | |||
2121 | } | |||
2122 | ||||
2123 | // Find dynamic GOT section. | |||
2124 | if (DtPltGot || DtLocalGotNum || DtGotSym) { | |||
2125 | if (!DtPltGot) | |||
2126 | report_fatal_error("Cannot find PLTGOT dynamic table tag."); | |||
2127 | if (!DtLocalGotNum) | |||
2128 | report_fatal_error("Cannot find MIPS_LOCAL_GOTNO dynamic table tag."); | |||
2129 | if (!DtGotSym) | |||
2130 | report_fatal_error("Cannot find MIPS_GOTSYM dynamic table tag."); | |||
2131 | ||||
2132 | size_t DynSymTotal = DynSyms.size(); | |||
2133 | if (*DtGotSym > DynSymTotal) | |||
2134 | reportError("MIPS_GOTSYM exceeds a number of dynamic symbols"); | |||
2135 | ||||
2136 | GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot); | |||
2137 | if (!GotSec) | |||
2138 | reportError("There is no not empty GOT section at 0x" + | |||
2139 | Twine::utohexstr(*DtPltGot)); | |||
2140 | ||||
2141 | LocalNum = *DtLocalGotNum; | |||
2142 | GlobalNum = DynSymTotal - *DtGotSym; | |||
2143 | ||||
2144 | ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); | |||
2145 | GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), | |||
2146 | Content.size() / sizeof(Entry)); | |||
2147 | GotDynSyms = DynSyms.drop_front(*DtGotSym); | |||
2148 | } | |||
2149 | ||||
2150 | // Find PLT section. | |||
2151 | if (DtMipsPltGot || DtJmpRel) { | |||
2152 | if (!DtMipsPltGot) | |||
2153 | report_fatal_error("Cannot find MIPS_PLTGOT dynamic table tag."); | |||
2154 | if (!DtJmpRel) | |||
2155 | report_fatal_error("Cannot find JMPREL dynamic table tag."); | |||
2156 | ||||
2157 | PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot); | |||
2158 | if (!PltSec) | |||
2159 | report_fatal_error("There is no not empty PLTGOT section at 0x " + | |||
2160 | Twine::utohexstr(*DtMipsPltGot)); | |||
2161 | ||||
2162 | PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel); | |||
2163 | if (!PltRelSec) | |||
2164 | report_fatal_error("There is no not empty RELPLT section at 0x" + | |||
2165 | Twine::utohexstr(*DtJmpRel)); | |||
2166 | ||||
2167 | ArrayRef<uint8_t> PltContent = | |||
2168 | unwrapOrError(Obj->getSectionContents(PltSec)); | |||
2169 | PltEntries = Entries(reinterpret_cast<const Entry *>(PltContent.data()), | |||
2170 | PltContent.size() / sizeof(Entry)); | |||
2171 | ||||
2172 | PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link)); | |||
2173 | PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable)); | |||
2174 | } | |||
2175 | } | |||
2176 | ||||
2177 | template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const { | |||
2178 | return GotSec->sh_addr + 0x7ff0; | |||
2179 | } | |||
2180 | ||||
2181 | template <class ELFT> | |||
2182 | const typename MipsGOTParser<ELFT>::Entry * | |||
2183 | MipsGOTParser<ELFT>::getGotLazyResolver() const { | |||
2184 | return LocalNum > 0 ? &GotEntries[0] : nullptr; | |||
2185 | } | |||
2186 | ||||
2187 | template <class ELFT> | |||
2188 | const typename MipsGOTParser<ELFT>::Entry * | |||
2189 | MipsGOTParser<ELFT>::getGotModulePointer() const { | |||
2190 | if (LocalNum < 2) | |||
2191 | return nullptr; | |||
2192 | const Entry &E = GotEntries[1]; | |||
2193 | if ((E >> (sizeof(Entry) * 8 - 1)) == 0) | |||
2194 | return nullptr; | |||
2195 | return &E; | |||
2196 | } | |||
2197 | ||||
2198 | template <class ELFT> | |||
2199 | typename MipsGOTParser<ELFT>::Entries | |||
2200 | MipsGOTParser<ELFT>::getLocalEntries() const { | |||
2201 | size_t Skip = getGotModulePointer() ? 2 : 1; | |||
2202 | if (LocalNum - Skip <= 0) | |||
2203 | return Entries(); | |||
2204 | return GotEntries.slice(Skip, LocalNum - Skip); | |||
2205 | } | |||
2206 | ||||
2207 | template <class ELFT> | |||
2208 | typename MipsGOTParser<ELFT>::Entries | |||
2209 | MipsGOTParser<ELFT>::getGlobalEntries() const { | |||
2210 | if (GlobalNum == 0) | |||
2211 | return Entries(); | |||
2212 | return GotEntries.slice(LocalNum, GlobalNum); | |||
2213 | } | |||
2214 | ||||
2215 | template <class ELFT> | |||
2216 | typename MipsGOTParser<ELFT>::Entries | |||
2217 | MipsGOTParser<ELFT>::getOtherEntries() const { | |||
2218 | size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum; | |||
2219 | if (OtherNum == 0) | |||
2220 | return Entries(); | |||
2221 | return GotEntries.slice(LocalNum + GlobalNum, OtherNum); | |||
2222 | } | |||
2223 | ||||
2224 | template <class ELFT> | |||
2225 | uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const { | |||
2226 | int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); | |||
2227 | return GotSec->sh_addr + Offset; | |||
2228 | } | |||
2229 | ||||
2230 | template <class ELFT> | |||
2231 | int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const { | |||
2232 | int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); | |||
2233 | return Offset - 0x7ff0; | |||
2234 | } | |||
2235 | ||||
2236 | template <class ELFT> | |||
2237 | const typename MipsGOTParser<ELFT>::Elf_Sym * | |||
2238 | MipsGOTParser<ELFT>::getGotSym(const Entry *E) const { | |||
2239 | int64_t Offset = std::distance(GotEntries.data(), E); | |||
2240 | return &GotDynSyms[Offset - LocalNum]; | |||
2241 | } | |||
2242 | ||||
2243 | template <class ELFT> | |||
2244 | const typename MipsGOTParser<ELFT>::Entry * | |||
2245 | MipsGOTParser<ELFT>::getPltLazyResolver() const { | |||
2246 | return PltEntries.empty() ? nullptr : &PltEntries[0]; | |||
2247 | } | |||
2248 | ||||
2249 | template <class ELFT> | |||
2250 | const typename MipsGOTParser<ELFT>::Entry * | |||
2251 | MipsGOTParser<ELFT>::getPltModulePointer() const { | |||
2252 | return PltEntries.size() < 2 ? nullptr : &PltEntries[1]; | |||
2253 | } | |||
2254 | ||||
2255 | template <class ELFT> | |||
2256 | typename MipsGOTParser<ELFT>::Entries | |||
2257 | MipsGOTParser<ELFT>::getPltEntries() const { | |||
2258 | if (PltEntries.size() <= 2) | |||
2259 | return Entries(); | |||
2260 | return PltEntries.slice(2, PltEntries.size() - 2); | |||
2261 | } | |||
2262 | ||||
2263 | template <class ELFT> | |||
2264 | uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const { | |||
2265 | int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry); | |||
2266 | return PltSec->sh_addr + Offset; | |||
2267 | } | |||
2268 | ||||
2269 | template <class ELFT> | |||
2270 | const typename MipsGOTParser<ELFT>::Elf_Sym * | |||
2271 | MipsGOTParser<ELFT>::getPltSym(const Entry *E) const { | |||
2272 | int64_t Offset = std::distance(getPltEntries().data(), E); | |||
2273 | if (PltRelSec->sh_type == ELF::SHT_REL) { | |||
2274 | Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec)); | |||
2275 | return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable)); | |||
2276 | } else { | |||
2277 | Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec)); | |||
2278 | return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable)); | |||
2279 | } | |||
2280 | } | |||
2281 | ||||
2282 | template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { | |||
2283 | if (Obj->getHeader()->e_machine != EM_MIPS) | |||
2284 | reportError("MIPS PLT GOT is available for MIPS targets only"); | |||
2285 | ||||
2286 | MipsGOTParser<ELFT> Parser(Obj, dynamic_table(), dynamic_symbols()); | |||
2287 | if (Parser.hasGot()) | |||
2288 | ELFDumperStyle->printMipsGOT(Parser); | |||
2289 | if (Parser.hasPlt()) | |||
2290 | ELFDumperStyle->printMipsPLT(Parser); | |||
2291 | } | |||
2292 | ||||
2293 | static const EnumEntry<unsigned> ElfMipsISAExtType[] = { | |||
2294 | {"None", Mips::AFL_EXT_NONE}, | |||
2295 | {"Broadcom SB-1", Mips::AFL_EXT_SB1}, | |||
2296 | {"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON}, | |||
2297 | {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2}, | |||
2298 | {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP}, | |||
2299 | {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3}, | |||
2300 | {"LSI R4010", Mips::AFL_EXT_4010}, | |||
2301 | {"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E}, | |||
2302 | {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F}, | |||
2303 | {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A}, | |||
2304 | {"MIPS R4650", Mips::AFL_EXT_4650}, | |||
2305 | {"MIPS R5900", Mips::AFL_EXT_5900}, | |||
2306 | {"MIPS R10000", Mips::AFL_EXT_10000}, | |||
2307 | {"NEC VR4100", Mips::AFL_EXT_4100}, | |||
2308 | {"NEC VR4111/VR4181", Mips::AFL_EXT_4111}, | |||
2309 | {"NEC VR4120", Mips::AFL_EXT_4120}, | |||
2310 | {"NEC VR5400", Mips::AFL_EXT_5400}, | |||
2311 | {"NEC VR5500", Mips::AFL_EXT_5500}, | |||
2312 | {"RMI Xlr", Mips::AFL_EXT_XLR}, | |||
2313 | {"Toshiba R3900", Mips::AFL_EXT_3900} | |||
2314 | }; | |||
2315 | ||||
2316 | static const EnumEntry<unsigned> ElfMipsASEFlags[] = { | |||
2317 | {"DSP", Mips::AFL_ASE_DSP}, | |||
2318 | {"DSPR2", Mips::AFL_ASE_DSPR2}, | |||
2319 | {"Enhanced VA Scheme", Mips::AFL_ASE_EVA}, | |||
2320 | {"MCU", Mips::AFL_ASE_MCU}, | |||
2321 | {"MDMX", Mips::AFL_ASE_MDMX}, | |||
2322 | {"MIPS-3D", Mips::AFL_ASE_MIPS3D}, | |||
2323 | {"MT", Mips::AFL_ASE_MT}, | |||
2324 | {"SmartMIPS", Mips::AFL_ASE_SMARTMIPS}, | |||
2325 | {"VZ", Mips::AFL_ASE_VIRT}, | |||
2326 | {"MSA", Mips::AFL_ASE_MSA}, | |||
2327 | {"MIPS16", Mips::AFL_ASE_MIPS16}, | |||
2328 | {"microMIPS", Mips::AFL_ASE_MICROMIPS}, | |||
2329 | {"XPA", Mips::AFL_ASE_XPA}, | |||
2330 | {"CRC", Mips::AFL_ASE_CRC}, | |||
2331 | {"GINV", Mips::AFL_ASE_GINV}, | |||
2332 | }; | |||
2333 | ||||
2334 | static const EnumEntry<unsigned> ElfMipsFpABIType[] = { | |||
2335 | {"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY}, | |||
2336 | {"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE}, | |||
2337 | {"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE}, | |||
2338 | {"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT}, | |||
2339 | {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)", | |||
2340 | Mips::Val_GNU_MIPS_ABI_FP_OLD_64}, | |||
2341 | {"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX}, | |||
2342 | {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64}, | |||
2343 | {"Hard float compat (32-bit CPU, 64-bit FPU)", | |||
2344 | Mips::Val_GNU_MIPS_ABI_FP_64A} | |||
2345 | }; | |||
2346 | ||||
2347 | static const EnumEntry<unsigned> ElfMipsFlags1[] { | |||
2348 | {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG}, | |||
2349 | }; | |||
2350 | ||||
2351 | static int getMipsRegisterSize(uint8_t Flag) { | |||
2352 | switch (Flag) { | |||
2353 | case Mips::AFL_REG_NONE: | |||
2354 | return 0; | |||
2355 | case Mips::AFL_REG_32: | |||
2356 | return 32; | |||
2357 | case Mips::AFL_REG_64: | |||
2358 | return 64; | |||
2359 | case Mips::AFL_REG_128: | |||
2360 | return 128; | |||
2361 | default: | |||
2362 | return -1; | |||
2363 | } | |||
2364 | } | |||
2365 | ||||
2366 | template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() { | |||
2367 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags"); | |||
2368 | if (!Shdr) { | |||
2369 | W.startLine() << "There is no .MIPS.abiflags section in the file.\n"; | |||
2370 | return; | |||
2371 | } | |||
2372 | ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); | |||
2373 | if (Sec.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) { | |||
2374 | W.startLine() << "The .MIPS.abiflags section has a wrong size.\n"; | |||
2375 | return; | |||
2376 | } | |||
2377 | ||||
2378 | auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec.data()); | |||
2379 | ||||
2380 | raw_ostream &OS = W.getOStream(); | |||
2381 | DictScope GS(W, "MIPS ABI Flags"); | |||
2382 | ||||
2383 | W.printNumber("Version", Flags->version); | |||
2384 | W.startLine() << "ISA: "; | |||
2385 | if (Flags->isa_rev <= 1) | |||
2386 | OS << format("MIPS%u", Flags->isa_level); | |||
2387 | else | |||
2388 | OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev); | |||
2389 | OS << "\n"; | |||
2390 | W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType)); | |||
2391 | W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags)); | |||
2392 | W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType)); | |||
2393 | W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size)); | |||
2394 | W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size)); | |||
2395 | W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size)); | |||
2396 | W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1)); | |||
2397 | W.printHex("Flags 2", Flags->flags2); | |||
2398 | } | |||
2399 | ||||
2400 | template <class ELFT> | |||
2401 | static void printMipsReginfoData(ScopedPrinter &W, | |||
2402 | const Elf_Mips_RegInfo<ELFT> &Reginfo) { | |||
2403 | W.printHex("GP", Reginfo.ri_gp_value); | |||
2404 | W.printHex("General Mask", Reginfo.ri_gprmask); | |||
2405 | W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]); | |||
2406 | W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]); | |||
2407 | W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]); | |||
2408 | W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]); | |||
2409 | } | |||
2410 | ||||
2411 | template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() { | |||
2412 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".reginfo"); | |||
2413 | if (!Shdr) { | |||
2414 | W.startLine() << "There is no .reginfo section in the file.\n"; | |||
2415 | return; | |||
2416 | } | |||
2417 | ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); | |||
2418 | if (Sec.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) { | |||
2419 | W.startLine() << "The .reginfo section has a wrong size.\n"; | |||
2420 | return; | |||
2421 | } | |||
2422 | ||||
2423 | DictScope GS(W, "MIPS RegInfo"); | |||
2424 | auto *Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(Sec.data()); | |||
2425 | printMipsReginfoData(W, *Reginfo); | |||
2426 | } | |||
2427 | ||||
2428 | template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() { | |||
2429 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.options"); | |||
2430 | if (!Shdr) { | |||
2431 | W.startLine() << "There is no .MIPS.options section in the file.\n"; | |||
2432 | return; | |||
2433 | } | |||
2434 | ||||
2435 | DictScope GS(W, "MIPS Options"); | |||
2436 | ||||
2437 | ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); | |||
2438 | while (!Sec.empty()) { | |||
2439 | if (Sec.size() < sizeof(Elf_Mips_Options<ELFT>)) { | |||
2440 | W.startLine() << "The .MIPS.options section has a wrong size.\n"; | |||
2441 | return; | |||
2442 | } | |||
2443 | auto *O = reinterpret_cast<const Elf_Mips_Options<ELFT> *>(Sec.data()); | |||
2444 | DictScope GS(W, getElfMipsOptionsOdkType(O->kind)); | |||
2445 | switch (O->kind) { | |||
2446 | case ODK_REGINFO: | |||
2447 | printMipsReginfoData(W, O->getRegInfo()); | |||
2448 | break; | |||
2449 | default: | |||
2450 | W.startLine() << "Unsupported MIPS options tag.\n"; | |||
2451 | break; | |||
2452 | } | |||
2453 | Sec = Sec.slice(O->size); | |||
2454 | } | |||
2455 | } | |||
2456 | ||||
2457 | template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { | |||
2458 | const Elf_Shdr *StackMapSection = nullptr; | |||
2459 | for (const auto &Sec : unwrapOrError(Obj->sections())) { | |||
2460 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | |||
2461 | if (Name == ".llvm_stackmaps") { | |||
2462 | StackMapSection = &Sec; | |||
2463 | break; | |||
2464 | } | |||
2465 | } | |||
2466 | ||||
2467 | if (!StackMapSection) | |||
2468 | return; | |||
2469 | ||||
2470 | ArrayRef<uint8_t> StackMapContentsArray = | |||
2471 | unwrapOrError(Obj->getSectionContents(StackMapSection)); | |||
2472 | ||||
2473 | prettyPrintStackMap( | |||
2474 | W, StackMapV2Parser<ELFT::TargetEndianness>(StackMapContentsArray)); | |||
2475 | } | |||
2476 | ||||
2477 | template <class ELFT> void ELFDumper<ELFT>::printGroupSections() { | |||
2478 | ELFDumperStyle->printGroupSections(Obj); | |||
2479 | } | |||
2480 | ||||
2481 | template <class ELFT> void ELFDumper<ELFT>::printAddrsig() { | |||
2482 | ELFDumperStyle->printAddrsig(Obj); | |||
2483 | } | |||
2484 | ||||
2485 | static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, | |||
2486 | StringRef Str2) { | |||
2487 | OS.PadToColumn(2u); | |||
2488 | OS << Str1; | |||
2489 | OS.PadToColumn(37u); | |||
2490 | OS << Str2 << "\n"; | |||
2491 | OS.flush(); | |||
2492 | } | |||
2493 | ||||
2494 | template <class ELFT> | |||
2495 | static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj) { | |||
2496 | const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); | |||
2497 | if (ElfHeader->e_shnum != 0) | |||
2498 | return to_string(ElfHeader->e_shnum); | |||
2499 | ||||
2500 | ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); | |||
2501 | if (Arr.empty()) | |||
2502 | return "0"; | |||
2503 | return "0 (" + to_string(Arr[0].sh_size) + ")"; | |||
2504 | } | |||
2505 | ||||
2506 | template <class ELFT> | |||
2507 | static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj) { | |||
2508 | const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); | |||
2509 | if (ElfHeader->e_shstrndx != SHN_XINDEX) | |||
2510 | return to_string(ElfHeader->e_shstrndx); | |||
2511 | ||||
2512 | ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); | |||
2513 | if (Arr.empty()) | |||
2514 | return "65535 (corrupt: out of range)"; | |||
2515 | return to_string(ElfHeader->e_shstrndx) + " (" + to_string(Arr[0].sh_link) + ")"; | |||
2516 | } | |||
2517 | ||||
2518 | template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) { | |||
2519 | const Elf_Ehdr *e = Obj->getHeader(); | |||
2520 | OS << "ELF Header:\n"; | |||
2521 | OS << " Magic: "; | |||
2522 | std::string Str; | |||
2523 | for (int i = 0; i < ELF::EI_NIDENT; i++) | |||
2524 | OS << format(" %02x", static_cast<int>(e->e_ident[i])); | |||
2525 | OS << "\n"; | |||
2526 | Str = printEnum(e->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass)); | |||
2527 | printFields(OS, "Class:", Str); | |||
2528 | Str = printEnum(e->e_ident[ELF::EI_DATA], makeArrayRef(ElfDataEncoding)); | |||
2529 | printFields(OS, "Data:", Str); | |||
2530 | OS.PadToColumn(2u); | |||
2531 | OS << "Version:"; | |||
2532 | OS.PadToColumn(37u); | |||
2533 | OS << to_hexString(e->e_ident[ELF::EI_VERSION]); | |||
2534 | if (e->e_version == ELF::EV_CURRENT) | |||
2535 | OS << " (current)"; | |||
2536 | OS << "\n"; | |||
2537 | Str = printEnum(e->e_ident[ELF::EI_OSABI], makeArrayRef(ElfOSABI)); | |||
2538 | printFields(OS, "OS/ABI:", Str); | |||
2539 | Str = "0x" + to_hexString(e->e_ident[ELF::EI_ABIVERSION]); | |||
2540 | printFields(OS, "ABI Version:", Str); | |||
2541 | Str = printEnum(e->e_type, makeArrayRef(ElfObjectFileType)); | |||
2542 | printFields(OS, "Type:", Str); | |||
2543 | Str = printEnum(e->e_machine, makeArrayRef(ElfMachineType)); | |||
2544 | printFields(OS, "Machine:", Str); | |||
2545 | Str = "0x" + to_hexString(e->e_version); | |||
2546 | printFields(OS, "Version:", Str); | |||
2547 | Str = "0x" + to_hexString(e->e_entry); | |||
2548 | printFields(OS, "Entry point address:", Str); | |||
2549 | Str = to_string(e->e_phoff) + " (bytes into file)"; | |||
2550 | printFields(OS, "Start of program headers:", Str); | |||
2551 | Str = to_string(e->e_shoff) + " (bytes into file)"; | |||
2552 | printFields(OS, "Start of section headers:", Str); | |||
2553 | std::string ElfFlags; | |||
2554 | if (e->e_machine == EM_MIPS) | |||
2555 | ElfFlags = | |||
2556 | printFlags(e->e_flags, makeArrayRef(ElfHeaderMipsFlags), | |||
2557 | unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), | |||
2558 | unsigned(ELF::EF_MIPS_MACH)); | |||
2559 | else if (e->e_machine == EM_RISCV) | |||
2560 | ElfFlags = printFlags(e->e_flags, makeArrayRef(ElfHeaderRISCVFlags)); | |||
2561 | Str = "0x" + to_hexString(e->e_flags); | |||
2562 | if (!ElfFlags.empty()) | |||
2563 | Str = Str + ", " + ElfFlags; | |||
2564 | printFields(OS, "Flags:", Str); | |||
2565 | Str = to_string(e->e_ehsize) + " (bytes)"; | |||
2566 | printFields(OS, "Size of this header:", Str); | |||
2567 | Str = to_string(e->e_phentsize) + " (bytes)"; | |||
2568 | printFields(OS, "Size of program headers:", Str); | |||
2569 | Str = to_string(e->e_phnum); | |||
2570 | printFields(OS, "Number of program headers:", Str); | |||
2571 | Str = to_string(e->e_shentsize) + " (bytes)"; | |||
2572 | printFields(OS, "Size of section headers:", Str); | |||
2573 | Str = getSectionHeadersNumString(Obj); | |||
2574 | printFields(OS, "Number of section headers:", Str); | |||
2575 | Str = getSectionHeaderTableIndexString(Obj); | |||
2576 | printFields(OS, "Section header string table index:", Str); | |||
2577 | } | |||
2578 | ||||
2579 | namespace { | |||
2580 | struct GroupMember { | |||
2581 | StringRef Name; | |||
2582 | uint64_t Index; | |||
2583 | }; | |||
2584 | ||||
2585 | struct GroupSection { | |||
2586 | StringRef Name; | |||
2587 | StringRef Signature; | |||
2588 | uint64_t ShName; | |||
2589 | uint64_t Index; | |||
2590 | uint32_t Link; | |||
2591 | uint32_t Info; | |||
2592 | uint32_t Type; | |||
2593 | std::vector<GroupMember> Members; | |||
2594 | }; | |||
2595 | ||||
2596 | template <class ELFT> | |||
2597 | std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) { | |||
2598 | using Elf_Shdr = typename ELFT::Shdr; | |||
2599 | using Elf_Sym = typename ELFT::Sym; | |||
2600 | using Elf_Word = typename ELFT::Word; | |||
2601 | ||||
2602 | std::vector<GroupSection> Ret; | |||
2603 | uint64_t I = 0; | |||
2604 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | |||
2605 | ++I; | |||
2606 | if (Sec.sh_type != ELF::SHT_GROUP) | |||
2607 | continue; | |||
2608 | ||||
2609 | const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); | |||
2610 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); | |||
2611 | const Elf_Sym *Sym = | |||
2612 | unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info)); | |||
2613 | auto Data = | |||
2614 | unwrapOrError(Obj->template getSectionContentsAsArray<Elf_Word>(&Sec)); | |||
2615 | ||||
2616 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | |||
2617 | StringRef Signature = StrTable.data() + Sym->st_name; | |||
2618 | Ret.push_back({Name, | |||
2619 | Signature, | |||
2620 | Sec.sh_name, | |||
2621 | I - 1, | |||
2622 | Sec.sh_link, | |||
2623 | Sec.sh_info, | |||
2624 | Data[0], | |||
2625 | {}}); | |||
2626 | ||||
2627 | std::vector<GroupMember> &GM = Ret.back().Members; | |||
2628 | for (uint32_t Ndx : Data.slice(1)) { | |||
2629 | auto Sec = unwrapOrError(Obj->getSection(Ndx)); | |||
2630 | const StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); | |||
2631 | GM.push_back({Name, Ndx}); | |||
2632 | } | |||
2633 | } | |||
2634 | return Ret; | |||
2635 | } | |||
2636 | ||||
2637 | DenseMap<uint64_t, const GroupSection *> | |||
2638 | mapSectionsToGroups(ArrayRef<GroupSection> Groups) { | |||
2639 | DenseMap<uint64_t, const GroupSection *> Ret; | |||
2640 | for (const GroupSection &G : Groups) | |||
2641 | for (const GroupMember &GM : G.Members) | |||
2642 | Ret.insert({GM.Index, &G}); | |||
2643 | return Ret; | |||
2644 | } | |||
2645 | ||||
2646 | } // namespace | |||
2647 | ||||
2648 | template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) { | |||
2649 | std::vector<GroupSection> V = getGroups<ELFT>(Obj); | |||
2650 | DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); | |||
2651 | for (const GroupSection &G : V) { | |||
2652 | OS << "\n" | |||
2653 | << getGroupType(G.Type) << " group section [" | |||
2654 | << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature | |||
2655 | << "] contains " << G.Members.size() << " sections:\n" | |||
2656 | << " [Index] Name\n"; | |||
2657 | for (const GroupMember &GM : G.Members) { | |||
2658 | const GroupSection *MainGroup = Map[GM.Index]; | |||
2659 | if (MainGroup != &G) { | |||
2660 | OS.flush(); | |||
2661 | errs() << "Error: section [" << format_decimal(GM.Index, 5) | |||
2662 | << "] in group section [" << format_decimal(G.Index, 5) | |||
2663 | << "] already in group section [" | |||
2664 | << format_decimal(MainGroup->Index, 5) << "]"; | |||
2665 | errs().flush(); | |||
2666 | continue; | |||
2667 | } | |||
2668 | OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n"; | |||
2669 | } | |||
2670 | } | |||
2671 | ||||
2672 | if (V.empty()) | |||
2673 | OS << "There are no section groups in this file.\n"; | |||
2674 | } | |||
2675 | ||||
2676 | template <class ELFT> | |||
2677 | void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, | |||
2678 | const Elf_Rela &R, bool IsRela) { | |||
2679 | std::string Offset, Info, Addend, Value; | |||
2680 | SmallString<32> RelocName; | |||
2681 | StringRef TargetName; | |||
2682 | const Elf_Sym *Sym = nullptr; | |||
2683 | unsigned Width = ELFT::Is64Bits ? 16 : 8; | |||
2684 | unsigned Bias = ELFT::Is64Bits ? 8 : 0; | |||
2685 | ||||
2686 | // First two fields are bit width dependent. The rest of them are after are | |||
2687 | // fixed width. | |||
2688 | Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; | |||
2689 | Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); | |||
2690 | Sym = unwrapOrError(Obj->getRelocationSymbol(&R, SymTab)); | |||
2691 | if (Sym && Sym->getType() == ELF::STT_SECTION) { | |||
2692 | const Elf_Shdr *Sec = unwrapOrError( | |||
2693 | Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); | |||
2694 | TargetName = unwrapOrError(Obj->getSectionName(Sec)); | |||
2695 | } else if (Sym) { | |||
2696 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); | |||
2697 | TargetName = unwrapOrError(Sym->getName(StrTable)); | |||
2698 | } | |||
2699 | ||||
2700 | if (Sym && IsRela) { | |||
2701 | if (R.r_addend < 0) | |||
2702 | Addend = " - "; | |||
2703 | else | |||
2704 | Addend = " + "; | |||
2705 | } | |||
2706 | ||||
2707 | Offset = to_string(format_hex_no_prefix(R.r_offset, Width)); | |||
2708 | Info = to_string(format_hex_no_prefix(R.r_info, Width)); | |||
2709 | ||||
2710 | int64_t RelAddend = R.r_addend; | |||
2711 | if (IsRela) | |||
2712 | Addend += to_hexString(std::abs(RelAddend), false); | |||
2713 | ||||
2714 | if (Sym) | |||
2715 | Value = to_string(format_hex_no_prefix(Sym->getValue(), Width)); | |||
2716 | ||||
2717 | Fields[0].Str = Offset; | |||
2718 | Fields[1].Str = Info; | |||
2719 | Fields[2].Str = RelocName; | |||
2720 | Fields[3].Str = Value; | |||
2721 | Fields[4].Str = TargetName; | |||
2722 | for (auto &field : Fields) | |||
2723 | printField(field); | |||
2724 | OS << Addend; | |||
2725 | OS << "\n"; | |||
2726 | } | |||
2727 | ||||
2728 | template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) { | |||
2729 | bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; | |||
2730 | bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; | |||
2731 | if (ELFT::Is64Bits) | |||
2732 | OS << " "; | |||
2733 | else | |||
2734 | OS << " "; | |||
2735 | if (IsRelr && opts::RawRelr) | |||
2736 | OS << "Data "; | |||
2737 | else | |||
2738 | OS << "Offset"; | |||
2739 | if (ELFT::Is64Bits) | |||
2740 | OS << " Info Type" | |||
2741 | << " Symbol's Value Symbol's Name"; | |||
2742 | else | |||
2743 | OS << " Info Type Sym. Value Symbol's Name"; | |||
2744 | if (IsRela) | |||
2745 | OS << " + Addend"; | |||
2746 | OS << "\n"; | |||
2747 | } | |||
2748 | ||||
2749 | template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { | |||
2750 | bool HasRelocSections = false; | |||
2751 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | |||
2752 | if (Sec.sh_type != ELF::SHT_REL && | |||
2753 | Sec.sh_type != ELF::SHT_RELA && | |||
2754 | Sec.sh_type != ELF::SHT_RELR && | |||
2755 | Sec.sh_type != ELF::SHT_ANDROID_REL && | |||
2756 | Sec.sh_type != ELF::SHT_ANDROID_RELA && | |||
2757 | Sec.sh_type != ELF::SHT_ANDROID_RELR) | |||
2758 | continue; | |||
2759 | HasRelocSections = true; | |||
2760 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | |||
2761 | unsigned Entries = Sec.getEntityCount(); | |||
2762 | std::vector<Elf_Rela> AndroidRelas; | |||
2763 | if (Sec.sh_type == ELF::SHT_ANDROID_REL || | |||
2764 | Sec.sh_type == ELF::SHT_ANDROID_RELA) { | |||
2765 | // Android's packed relocation section needs to be unpacked first | |||
2766 | // to get the actual number of entries. | |||
2767 | AndroidRelas = unwrapOrError(Obj->android_relas(&Sec)); | |||
2768 | Entries = AndroidRelas.size(); | |||
2769 | } | |||
2770 | std::vector<Elf_Rela> RelrRelas; | |||
2771 | if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || | |||
2772 | Sec.sh_type == ELF::SHT_ANDROID_RELR)) { | |||
2773 | // .relr.dyn relative relocation section needs to be unpacked first | |||
2774 | // to get the actual number of entries. | |||
2775 | Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec)); | |||
2776 | RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | |||
2777 | Entries = RelrRelas.size(); | |||
2778 | } | |||
2779 | uintX_t Offset = Sec.sh_offset; | |||
2780 | OS << "\nRelocation section '" << Name << "' at offset 0x" | |||
2781 | << to_hexString(Offset, false) << " contains " << Entries | |||
2782 | << " entries:\n"; | |||
2783 | printRelocHeader(Sec.sh_type); | |||
2784 | const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link)); | |||
2785 | switch (Sec.sh_type) { | |||
2786 | case ELF::SHT_REL: | |||
2787 | for (const auto &R : unwrapOrError(Obj->rels(&Sec))) { | |||
2788 | Elf_Rela Rela; | |||
2789 | Rela.r_offset = R.r_offset; | |||
2790 | Rela.r_info = R.r_info; | |||
2791 | Rela.r_addend = 0; | |||
2792 | printRelocation(Obj, SymTab, Rela, false); | |||
2793 | } | |||
2794 | break; | |||
2795 | case ELF::SHT_RELA: | |||
2796 | for (const auto &R : unwrapOrError(Obj->relas(&Sec))) | |||
2797 | printRelocation(Obj, SymTab, R, true); | |||
2798 | break; | |||
2799 | case ELF::SHT_RELR: | |||
2800 | case ELF::SHT_ANDROID_RELR: | |||
2801 | if (opts::RawRelr) | |||
2802 | for (const auto &R : unwrapOrError(Obj->relrs(&Sec))) | |||
2803 | OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) | |||
2804 | << "\n"; | |||
2805 | else | |||
2806 | for (const auto &R : RelrRelas) | |||
2807 | printRelocation(Obj, SymTab, R, false); | |||
2808 | break; | |||
2809 | case ELF::SHT_ANDROID_REL: | |||
2810 | case ELF::SHT_ANDROID_RELA: | |||
2811 | for (const auto &R : AndroidRelas) | |||
2812 | printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA); | |||
2813 | break; | |||
2814 | } | |||
2815 | } | |||
2816 | if (!HasRelocSections) | |||
2817 | OS << "\nThere are no relocations in this file.\n"; | |||
2818 | } | |||
2819 | ||||
2820 | std::string getSectionTypeString(unsigned Arch, unsigned Type) { | |||
2821 | using namespace ELF; | |||
2822 | ||||
2823 | switch (Arch) { | |||
2824 | case EM_ARM: | |||
2825 | switch (Type) { | |||
2826 | case SHT_ARM_EXIDX: | |||
2827 | return "ARM_EXIDX"; | |||
2828 | case SHT_ARM_PREEMPTMAP: | |||
2829 | return "ARM_PREEMPTMAP"; | |||
2830 | case SHT_ARM_ATTRIBUTES: | |||
2831 | return "ARM_ATTRIBUTES"; | |||
2832 | case SHT_ARM_DEBUGOVERLAY: | |||
2833 | return "ARM_DEBUGOVERLAY"; | |||
2834 | case SHT_ARM_OVERLAYSECTION: | |||
2835 | return "ARM_OVERLAYSECTION"; | |||
2836 | } | |||
2837 | break; | |||
2838 | case EM_X86_64: | |||
2839 | switch (Type) { | |||
2840 | case SHT_X86_64_UNWIND: | |||
2841 | return "X86_64_UNWIND"; | |||
2842 | } | |||
2843 | break; | |||
2844 | case EM_MIPS: | |||
2845 | case EM_MIPS_RS3_LE: | |||
2846 | switch (Type) { | |||
2847 | case SHT_MIPS_REGINFO: | |||
2848 | return "MIPS_REGINFO"; | |||
2849 | case SHT_MIPS_OPTIONS: | |||
2850 | return "MIPS_OPTIONS"; | |||
2851 | case SHT_MIPS_ABIFLAGS: | |||
2852 | return "MIPS_ABIFLAGS"; | |||
2853 | case SHT_MIPS_DWARF: | |||
2854 | return "SHT_MIPS_DWARF"; | |||
2855 | } | |||
2856 | break; | |||
2857 | } | |||
2858 | switch (Type) { | |||
2859 | case SHT_NULL: | |||
2860 | return "NULL"; | |||
2861 | case SHT_PROGBITS: | |||
2862 | return "PROGBITS"; | |||
2863 | case SHT_SYMTAB: | |||
2864 | return "SYMTAB"; | |||
2865 | case SHT_STRTAB: | |||
2866 | return "STRTAB"; | |||
2867 | case SHT_RELA: | |||
2868 | return "RELA"; | |||
2869 | case SHT_HASH: | |||
2870 | return "HASH"; | |||
2871 | case SHT_DYNAMIC: | |||
2872 | return "DYNAMIC"; | |||
2873 | case SHT_NOTE: | |||
2874 | return "NOTE"; | |||
2875 | case SHT_NOBITS: | |||
2876 | return "NOBITS"; | |||
2877 | case SHT_REL: | |||
2878 | return "REL"; | |||
2879 | case SHT_SHLIB: | |||
2880 | return "SHLIB"; | |||
2881 | case SHT_DYNSYM: | |||
2882 | return "DYNSYM"; | |||
2883 | case SHT_INIT_ARRAY: | |||
2884 | return "INIT_ARRAY"; | |||
2885 | case SHT_FINI_ARRAY: | |||
2886 | return "FINI_ARRAY"; | |||
2887 | case SHT_PREINIT_ARRAY: | |||
2888 | return "PREINIT_ARRAY"; | |||
2889 | case SHT_GROUP: | |||
2890 | return "GROUP"; | |||
2891 | case SHT_SYMTAB_SHNDX: | |||
2892 | return "SYMTAB SECTION INDICES"; | |||
2893 | case SHT_RELR: | |||
2894 | case SHT_ANDROID_RELR: | |||
2895 | return "RELR"; | |||
2896 | case SHT_LLVM_ODRTAB: | |||
2897 | return "LLVM_ODRTAB"; | |||
2898 | case SHT_LLVM_LINKER_OPTIONS: | |||
2899 | return "LLVM_LINKER_OPTIONS"; | |||
2900 | case SHT_LLVM_CALL_GRAPH_PROFILE: | |||
2901 | return "LLVM_CALL_GRAPH_PROFILE"; | |||
2902 | case SHT_LLVM_ADDRSIG: | |||
2903 | return "LLVM_ADDRSIG"; | |||
2904 | // FIXME: Parse processor specific GNU attributes | |||
2905 | case SHT_GNU_ATTRIBUTES: | |||
2906 | return "ATTRIBUTES"; | |||
2907 | case SHT_GNU_HASH: | |||
2908 | return "GNU_HASH"; | |||
2909 | case SHT_GNU_verdef: | |||
2910 | return "VERDEF"; | |||
2911 | case SHT_GNU_verneed: | |||
2912 | return "VERNEED"; | |||
2913 | case SHT_GNU_versym: | |||
2914 | return "VERSYM"; | |||
2915 | default: | |||
2916 | return ""; | |||
2917 | } | |||
2918 | return ""; | |||
2919 | } | |||
2920 | ||||
2921 | template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) { | |||
2922 | size_t SectionIndex = 0; | |||
2923 | std::string Number, Type, Size, Address, Offset, Flags, Link, Info, EntrySize, | |||
2924 | Alignment; | |||
2925 | unsigned Bias; | |||
2926 | unsigned Width; | |||
2927 | ||||
2928 | if (ELFT::Is64Bits) { | |||
2929 | Bias = 0; | |||
2930 | Width = 16; | |||
2931 | } else { | |||
2932 | Bias = 8; | |||
2933 | Width = 8; | |||
2934 | } | |||
2935 | ||||
2936 | ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections()); | |||
2937 | OS << "There are " << to_string(Sections.size()) | |||
2938 | << " section headers, starting at offset " | |||
2939 | << "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n"; | |||
2940 | OS << "Section Headers:\n"; | |||
2941 | Field Fields[11] = {{"[Nr]", 2}, | |||
2942 | {"Name", 7}, | |||
2943 | {"Type", 25}, | |||
2944 | {"Address", 41}, | |||
2945 | {"Off", 58 - Bias}, | |||
2946 | {"Size", 65 - Bias}, | |||
2947 | {"ES", 72 - Bias}, | |||
2948 | {"Flg", 75 - Bias}, | |||
2949 | {"Lk", 79 - Bias}, | |||
2950 | {"Inf", 82 - Bias}, | |||
2951 | {"Al", 86 - Bias}}; | |||
2952 | for (auto &f : Fields) | |||
2953 | printField(f); | |||
2954 | OS << "\n"; | |||
2955 | ||||
2956 | for (const Elf_Shdr &Sec : Sections) { | |||
2957 | Number = to_string(SectionIndex); | |||
2958 | Fields[0].Str = Number; | |||
2959 | Fields[1].Str = unwrapOrError(Obj->getSectionName(&Sec)); | |||
2960 | Type = getSectionTypeString(Obj->getHeader()->e_machine, Sec.sh_type); | |||
2961 | Fields[2].Str = Type; | |||
2962 | Address = to_string(format_hex_no_prefix(Sec.sh_addr, Width)); | |||
2963 | Fields[3].Str = Address; | |||
2964 | Offset = to_string(format_hex_no_prefix(Sec.sh_offset, 6)); | |||
2965 | Fields[4].Str = Offset; | |||
2966 | Size = to_string(format_hex_no_prefix(Sec.sh_size, 6)); | |||
2967 | Fields[5].Str = Size; | |||
2968 | EntrySize = to_string(format_hex_no_prefix(Sec.sh_entsize, 2)); | |||
2969 | Fields[6].Str = EntrySize; | |||
2970 | Flags = getGNUFlags(Sec.sh_flags); | |||
2971 | Fields[7].Str = Flags; | |||
2972 | Link = to_string(Sec.sh_link); | |||
2973 | Fields[8].Str = Link; | |||
2974 | Info = to_string(Sec.sh_info); | |||
2975 | Fields[9].Str = Info; | |||
2976 | Alignment = to_string(Sec.sh_addralign); | |||
2977 | Fields[10].Str = Alignment; | |||
2978 | OS.PadToColumn(Fields[0].Column); | |||
2979 | OS << "[" << right_justify(Fields[0].Str, 2) << "]"; | |||
2980 | for (int i = 1; i < 7; i++) | |||
2981 | printField(Fields[i]); | |||
2982 | OS.PadToColumn(Fields[7].Column); | |||
2983 | OS << right_justify(Fields[7].Str, 3); | |||
2984 | OS.PadToColumn(Fields[8].Column); | |||
2985 | OS << right_justify(Fields[8].Str, 2); | |||
2986 | OS.PadToColumn(Fields[9].Column); | |||
2987 | OS << right_justify(Fields[9].Str, 3); | |||
2988 | OS.PadToColumn(Fields[10].Column); | |||
2989 | OS << right_justify(Fields[10].Str, 2); | |||
2990 | OS << "\n"; | |||
2991 | ++SectionIndex; | |||
2992 | } | |||
2993 | OS << "Key to Flags:\n" | |||
2994 | << " W (write), A (alloc), X (execute), M (merge), S (strings), l " | |||
2995 | "(large)\n" | |||
2996 | << " I (info), L (link order), G (group), T (TLS), E (exclude),\ | |||
2997 | x (unknown)\n" | |||
2998 | << " O (extra OS processing required) o (OS specific),\ | |||
2999 | p (processor specific)\n"; | |||
3000 | } | |||
3001 | ||||
3002 | template <class ELFT> | |||
3003 | void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name, | |||
3004 | size_t Entries) { | |||
3005 | if (!Name.empty()) | |||
3006 | OS << "\nSymbol table '" << Name << "' contains " << Entries | |||
3007 | << " entries:\n"; | |||
3008 | else | |||
3009 | OS << "\n Symbol table for image:\n"; | |||
3010 | ||||
3011 | if (ELFT::Is64Bits) | |||
3012 | OS << " Num: Value Size Type Bind Vis Ndx Name\n"; | |||
3013 | else | |||
3014 | OS << " Num: Value Size Type Bind Vis Ndx Name\n"; | |||
3015 | } | |||
3016 | ||||
3017 | template <class ELFT> | |||
3018 | std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj, | |||
3019 | const Elf_Sym *Symbol, | |||
3020 | const Elf_Sym *FirstSym) { | |||
3021 | unsigned SectionIndex = Symbol->st_shndx; | |||
3022 | switch (SectionIndex) { | |||
3023 | case ELF::SHN_UNDEF: | |||
3024 | return "UND"; | |||
3025 | case ELF::SHN_ABS: | |||
3026 | return "ABS"; | |||
3027 | case ELF::SHN_COMMON: | |||
3028 | return "COM"; | |||
3029 | case ELF::SHN_XINDEX: | |||
3030 | SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( | |||
3031 | Symbol, FirstSym, this->dumper()->getShndxTable())); | |||
3032 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
3033 | default: | |||
3034 | // Find if: | |||
3035 | // Processor specific | |||
3036 | if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC) | |||
3037 | return std::string("PRC[0x") + | |||
3038 | to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; | |||
3039 | // OS specific | |||
3040 | if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS) | |||
3041 | return std::string("OS[0x") + | |||
3042 | to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; | |||
3043 | // Architecture reserved: | |||
3044 | if (SectionIndex >= ELF::SHN_LORESERVE && | |||
3045 | SectionIndex <= ELF::SHN_HIRESERVE) | |||
3046 | return std::string("RSV[0x") + | |||
3047 | to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; | |||
3048 | // A normal section with an index | |||
3049 | return to_string(format_decimal(SectionIndex, 3)); | |||
3050 | } | |||
3051 | } | |||
3052 | ||||
3053 | template <class ELFT> | |||
3054 | void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, | |||
3055 | const Elf_Sym *FirstSym, StringRef StrTable, | |||
3056 | bool IsDynamic) { | |||
3057 | static int Idx = 0; | |||
3058 | static bool Dynamic = true; | |||
3059 | size_t Width; | |||
3060 | ||||
3061 | // If this function was called with a different value from IsDynamic | |||
3062 | // from last call, happens when we move from dynamic to static symbol | |||
3063 | // table, "Num" field should be reset. | |||
3064 | if (!Dynamic != !IsDynamic) { | |||
3065 | Idx = 0; | |||
3066 | Dynamic = false; | |||
3067 | } | |||
3068 | std::string Num, Name, Value, Size, Binding, Type, Visibility, Section; | |||
3069 | unsigned Bias = 0; | |||
3070 | if (ELFT::Is64Bits) { | |||
3071 | Bias = 8; | |||
3072 | Width = 16; | |||
3073 | } else { | |||
3074 | Bias = 0; | |||
3075 | Width = 8; | |||
3076 | } | |||
3077 | Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias, | |||
3078 | 31 + Bias, 38 + Bias, 47 + Bias, 51 + Bias}; | |||
3079 | Num = to_string(format_decimal(Idx++, 6)) + ":"; | |||
3080 | Value = to_string(format_hex_no_prefix(Symbol->st_value, Width)); | |||
3081 | Size = to_string(format_decimal(Symbol->st_size, 5)); | |||
3082 | unsigned char SymbolType = Symbol->getType(); | |||
3083 | if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && | |||
3084 | SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) | |||
3085 | Type = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes)); | |||
3086 | else | |||
3087 | Type = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes)); | |||
3088 | unsigned Vis = Symbol->getVisibility(); | |||
3089 | Binding = printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); | |||
3090 | Visibility = printEnum(Vis, makeArrayRef(ElfSymbolVisibilities)); | |||
3091 | Section = getSymbolSectionNdx(Obj, Symbol, FirstSym); | |||
3092 | Name = this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic); | |||
3093 | Fields[0].Str = Num; | |||
3094 | Fields[1].Str = Value; | |||
3095 | Fields[2].Str = Size; | |||
3096 | Fields[3].Str = Type; | |||
3097 | Fields[4].Str = Binding; | |||
3098 | Fields[5].Str = Visibility; | |||
3099 | Fields[6].Str = Section; | |||
3100 | Fields[7].Str = Name; | |||
3101 | for (auto &Entry : Fields) | |||
3102 | printField(Entry); | |||
3103 | OS << "\n"; | |||
3104 | } | |||
3105 | template <class ELFT> | |||
3106 | void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, | |||
3107 | uint32_t Sym, StringRef StrTable, | |||
3108 | uint32_t Bucket) { | |||
3109 | std::string Num, Buc, Name, Value, Size, Binding, Type, Visibility, Section; | |||
3110 | unsigned Width, Bias = 0; | |||
3111 | if (ELFT::Is64Bits) { | |||
3112 | Bias = 8; | |||
3113 | Width = 16; | |||
3114 | } else { | |||
3115 | Bias = 0; | |||
3116 | Width = 8; | |||
3117 | } | |||
3118 | Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias, | |||
3119 | 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias}; | |||
3120 | Num = to_string(format_decimal(Sym, 5)); | |||
3121 | Buc = to_string(format_decimal(Bucket, 3)) + ":"; | |||
3122 | ||||
3123 | const auto Symbol = FirstSym + Sym; | |||
3124 | Value = to_string(format_hex_no_prefix(Symbol->st_value, Width)); | |||
3125 | Size = to_string(format_decimal(Symbol->st_size, 5)); | |||
3126 | unsigned char SymbolType = Symbol->getType(); | |||
3127 | if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && | |||
3128 | SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) | |||
3129 | Type = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes)); | |||
3130 | else | |||
3131 | Type = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes)); | |||
3132 | unsigned Vis = Symbol->getVisibility(); | |||
3133 | Binding = printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); | |||
3134 | Visibility = printEnum(Vis, makeArrayRef(ElfSymbolVisibilities)); | |||
3135 | Section = getSymbolSectionNdx(Obj, Symbol, FirstSym); | |||
3136 | Name = this->dumper()->getFullSymbolName(Symbol, StrTable, true); | |||
3137 | Fields[0].Str = Num; | |||
3138 | Fields[1].Str = Buc; | |||
3139 | Fields[2].Str = Value; | |||
3140 | Fields[3].Str = Size; | |||
3141 | Fields[4].Str = Type; | |||
3142 | Fields[5].Str = Binding; | |||
3143 | Fields[6].Str = Visibility; | |||
3144 | Fields[7].Str = Section; | |||
3145 | Fields[8].Str = Name; | |||
3146 | for (auto &Entry : Fields) | |||
3147 | printField(Entry); | |||
3148 | OS << "\n"; | |||
3149 | } | |||
3150 | ||||
3151 | template <class ELFT> void GNUStyle<ELFT>::printSymbols(const ELFO *Obj) { | |||
3152 | if (opts::DynamicSymbols) | |||
3153 | return; | |||
3154 | this->dumper()->printSymbolsHelper(true); | |||
3155 | this->dumper()->printSymbolsHelper(false); | |||
3156 | } | |||
3157 | ||||
3158 | template <class ELFT> | |||
3159 | void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) { | |||
3160 | if (this->dumper()->getDynamicStringTable().empty()) | |||
| ||||
3161 | return; | |||
3162 | auto StringTable = this->dumper()->getDynamicStringTable(); | |||
3163 | auto DynSyms = this->dumper()->dynamic_symbols(); | |||
3164 | auto GnuHash = this->dumper()->getGnuHashTable(); | |||
3165 | auto SysVHash = this->dumper()->getHashTable(); | |||
3166 | ||||
3167 | // If no hash or .gnu.hash found, try using symbol table | |||
3168 | if (GnuHash == nullptr && SysVHash == nullptr) | |||
3169 | this->dumper()->printSymbolsHelper(true); | |||
3170 | ||||
3171 | // Try printing .hash | |||
3172 | if (this->dumper()->getHashTable()) { | |||
3173 | OS << "\n Symbol table of .hash for image:\n"; | |||
3174 | if (ELFT::Is64Bits) | |||
3175 | OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; | |||
3176 | else | |||
3177 | OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; | |||
3178 | OS << "\n"; | |||
3179 | ||||
3180 | uint32_t NBuckets = SysVHash->nbucket; | |||
| ||||
3181 | uint32_t NChains = SysVHash->nchain; | |||
3182 | auto Buckets = SysVHash->buckets(); | |||
3183 | auto Chains = SysVHash->chains(); | |||
3184 | for (uint32_t Buc = 0; Buc < NBuckets; Buc++) { | |||
3185 | if (Buckets[Buc] == ELF::STN_UNDEF) | |||
3186 | continue; | |||
3187 | for (uint32_t Ch = Buckets[Buc]; Ch < NChains; Ch = Chains[Ch]) { | |||
3188 | if (Ch == ELF::STN_UNDEF) | |||
3189 | break; | |||
3190 | printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc); | |||
3191 | } | |||
3192 | } | |||
3193 | } | |||
3194 | ||||
3195 | // Try printing .gnu.hash | |||
3196 | if (GnuHash) { | |||
3197 | OS << "\n Symbol table of .gnu.hash for image:\n"; | |||
3198 | if (ELFT::Is64Bits) | |||
3199 | OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; | |||
3200 | else | |||
3201 | OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; | |||
3202 | OS << "\n"; | |||
3203 | uint32_t NBuckets = GnuHash->nbuckets; | |||
3204 | auto Buckets = GnuHash->buckets(); | |||
3205 | for (uint32_t Buc = 0; Buc < NBuckets; Buc++) { | |||
3206 | if (Buckets[Buc] == ELF::STN_UNDEF) | |||
3207 | continue; | |||
3208 | uint32_t Index = Buckets[Buc]; | |||
3209 | uint32_t GnuHashable = Index - GnuHash->symndx; | |||
3210 | // Print whole chain | |||
3211 | while (true) { | |||
3212 | printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc); | |||
3213 | // Chain ends at symbol with stopper bit | |||
3214 | if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1) | |||
3215 | break; | |||
3216 | } | |||
3217 | } | |||
3218 | } | |||
3219 | } | |||
3220 | ||||
3221 | static inline std::string printPhdrFlags(unsigned Flag) { | |||
3222 | std::string Str; | |||
3223 | Str = (Flag & PF_R) ? "R" : " "; | |||
3224 | Str += (Flag & PF_W) ? "W" : " "; | |||
3225 | Str += (Flag & PF_X) ? "E" : " "; | |||
3226 | return Str; | |||
3227 | } | |||
3228 | ||||
3229 | // SHF_TLS sections are only in PT_TLS, PT_LOAD or PT_GNU_RELRO | |||
3230 | // PT_TLS must only have SHF_TLS sections | |||
3231 | template <class ELFT> | |||
3232 | bool GNUStyle<ELFT>::checkTLSSections(const Elf_Phdr &Phdr, | |||
3233 | const Elf_Shdr &Sec) { | |||
3234 | return (((Sec.sh_flags & ELF::SHF_TLS) && | |||
3235 | ((Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) || | |||
3236 | (Phdr.p_type == ELF::PT_GNU_RELRO))) || | |||
3237 | (!(Sec.sh_flags & ELF::SHF_TLS) && Phdr.p_type != ELF::PT_TLS)); | |||
3238 | } | |||
3239 | ||||
3240 | // Non-SHT_NOBITS must have its offset inside the segment | |||
3241 | // Only non-zero section can be at end of segment | |||
3242 | template <class ELFT> | |||
3243 | bool GNUStyle<ELFT>::checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { | |||
3244 | if (Sec.sh_type == ELF::SHT_NOBITS) | |||
3245 | return true; | |||
3246 | bool IsSpecial = | |||
3247 | (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); | |||
3248 | // .tbss is special, it only has memory in PT_TLS and has NOBITS properties | |||
3249 | auto SectionSize = | |||
3250 | (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size; | |||
3251 | if (Sec.sh_offset >= Phdr.p_offset) | |||
3252 | return ((Sec.sh_offset + SectionSize <= Phdr.p_filesz + Phdr.p_offset) | |||
3253 | /*only non-zero sized sections at end*/ && | |||
3254 | (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz)); | |||
3255 | return false; | |||
3256 | } | |||
3257 | ||||
3258 | // SHF_ALLOC must have VMA inside segment | |||
3259 | // Only non-zero section can be at end of segment | |||
3260 | template <class ELFT> | |||
3261 | bool GNUStyle<ELFT>::checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { | |||
3262 | if (!(Sec.sh_flags & ELF::SHF_ALLOC)) | |||
3263 | return true; | |||
3264 | bool IsSpecial = | |||
3265 | (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); | |||
3266 | // .tbss is special, it only has memory in PT_TLS and has NOBITS properties | |||
3267 | auto SectionSize = | |||
3268 | (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size; | |||
3269 | if (Sec.sh_addr >= Phdr.p_vaddr) | |||
3270 | return ((Sec.sh_addr + SectionSize <= Phdr.p_vaddr + Phdr.p_memsz) && | |||
3271 | (Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz)); | |||
3272 | return false; | |||
3273 | } | |||
3274 | ||||
3275 | // No section with zero size must be at start or end of PT_DYNAMIC | |||
3276 | template <class ELFT> | |||
3277 | bool GNUStyle<ELFT>::checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { | |||
3278 | if (Phdr.p_type != ELF::PT_DYNAMIC || Sec.sh_size != 0 || Phdr.p_memsz == 0) | |||
3279 | return true; | |||
3280 | // Is section within the phdr both based on offset and VMA ? | |||
3281 | return ((Sec.sh_type == ELF::SHT_NOBITS) || | |||
3282 | (Sec.sh_offset > Phdr.p_offset && | |||
3283 | Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz)) && | |||
3284 | (!(Sec.sh_flags & ELF::SHF_ALLOC) || | |||
3285 | (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz)); | |||
3286 | } | |||
3287 | ||||
3288 | template <class ELFT> | |||
3289 | void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { | |||
3290 | unsigned Bias = ELFT::Is64Bits ? 8 : 0; | |||
3291 | unsigned Width = ELFT::Is64Bits ? 18 : 10; | |||
3292 | unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7; | |||
3293 | std::string Type, Offset, VMA, LMA, FileSz, MemSz, Flag, Align; | |||
3294 | ||||
3295 | const Elf_Ehdr *Header = Obj->getHeader(); | |||
3296 | Field Fields[8] = {2, 17, 26, 37 + Bias, | |||
3297 | 48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias}; | |||
3298 | OS << "\nElf file type is " | |||
3299 | << printEnum(Header->e_type, makeArrayRef(ElfObjectFileType)) << "\n" | |||
3300 | << "Entry point " << format_hex(Header->e_entry, 3) << "\n" | |||
3301 | << "There are " << Header->e_phnum << " program headers," | |||
3302 | << " starting at offset " << Header->e_phoff << "\n\n" | |||
3303 | << "Program Headers:\n"; | |||
3304 | if (ELFT::Is64Bits) | |||
3305 | OS << " Type Offset VirtAddr PhysAddr " | |||
3306 | << " FileSiz MemSiz Flg Align\n"; | |||
3307 | else | |||
3308 | OS << " Type Offset VirtAddr PhysAddr FileSiz " | |||
3309 | << "MemSiz Flg Align\n"; | |||
3310 | for (const auto &Phdr : unwrapOrError(Obj->program_headers())) { | |||
3311 | Type = getElfPtType(Header->e_machine, Phdr.p_type); | |||
3312 | Offset = to_string(format_hex(Phdr.p_offset, 8)); | |||
3313 | VMA = to_string(format_hex(Phdr.p_vaddr, Width)); | |||
3314 | LMA = to_string(format_hex(Phdr.p_paddr, Width)); | |||
3315 | FileSz = to_string(format_hex(Phdr.p_filesz, SizeWidth)); | |||
3316 | MemSz = to_string(format_hex(Phdr.p_memsz, SizeWidth)); | |||
3317 | Flag = printPhdrFlags(Phdr.p_flags); | |||
3318 | Align = to_string(format_hex(Phdr.p_align, 1)); | |||
3319 | Fields[0].Str = Type; | |||
3320 | Fields[1].Str = Offset; | |||
3321 | Fields[2].Str = VMA; | |||
3322 | Fields[3].Str = LMA; | |||
3323 | Fields[4].Str = FileSz; | |||
3324 | Fields[5].Str = MemSz; | |||
3325 | Fields[6].Str = Flag; | |||
3326 | Fields[7].Str = Align; | |||
3327 | for (auto Field : Fields) | |||
3328 | printField(Field); | |||
3329 | if (Phdr.p_type == ELF::PT_INTERP) { | |||
3330 | OS << "\n [Requesting program interpreter: "; | |||
3331 | OS << reinterpret_cast<const char *>(Obj->base()) + Phdr.p_offset << "]"; | |||
3332 | } | |||
3333 | OS << "\n"; | |||
3334 | } | |||
3335 | OS << "\n Section to Segment mapping:\n Segment Sections...\n"; | |||
3336 | int Phnum = 0; | |||
3337 | for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { | |||
3338 | std::string Sections; | |||
3339 | OS << format(" %2.2d ", Phnum++); | |||
3340 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | |||
3341 | // Check if each section is in a segment and then print mapping. | |||
3342 | // readelf additionally makes sure it does not print zero sized sections | |||
3343 | // at end of segments and for PT_DYNAMIC both start and end of section | |||
3344 | // .tbss must only be shown in PT_TLS section. | |||
3345 | bool TbssInNonTLS = (Sec.sh_type == ELF::SHT_NOBITS) && | |||
3346 | ((Sec.sh_flags & ELF::SHF_TLS) != 0) && | |||
3347 | Phdr.p_type != ELF::PT_TLS; | |||
3348 | if (!TbssInNonTLS && checkTLSSections(Phdr, Sec) && | |||
3349 | checkoffsets(Phdr, Sec) && checkVMA(Phdr, Sec) && | |||
3350 | checkPTDynamic(Phdr, Sec) && (Sec.sh_type != ELF::SHT_NULL)) | |||
3351 | Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + " "; | |||
3352 | } | |||
3353 | OS << Sections << "\n"; | |||
3354 | OS.flush(); | |||
3355 | } | |||
3356 | } | |||
3357 | ||||
3358 | template <class ELFT> | |||
3359 | void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, | |||
3360 | bool IsRela) { | |||
3361 | SmallString<32> RelocName; | |||
3362 | StringRef SymbolName; | |||
3363 | unsigned Width = ELFT::Is64Bits ? 16 : 8; | |||
3364 | unsigned Bias = ELFT::Is64Bits ? 8 : 0; | |||
3365 | // First two fields are bit width dependent. The rest of them are after are | |||
3366 | // fixed width. | |||
3367 | Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; | |||
3368 | ||||
3369 | uint32_t SymIndex = R.getSymbol(Obj->isMips64EL()); | |||
3370 | const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; | |||
3371 | Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); | |||
3372 | SymbolName = | |||
3373 | unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); | |||
3374 | std::string Addend, Info, Offset, Value; | |||
3375 | Offset = to_string(format_hex_no_prefix(R.r_offset, Width)); | |||
3376 | Info = to_string(format_hex_no_prefix(R.r_info, Width)); | |||
3377 | Value = to_string(format_hex_no_prefix(Sym->getValue(), Width)); | |||
3378 | int64_t RelAddend = R.r_addend; | |||
3379 | if (!SymbolName.empty() && IsRela) { | |||
3380 | if (R.r_addend < 0) | |||
3381 | Addend = " - "; | |||
3382 | else | |||
3383 | Addend = " + "; | |||
3384 | } | |||
3385 | ||||
3386 | if (SymbolName.empty() && Sym->getValue() == 0) | |||
3387 | Value = ""; | |||
3388 | ||||
3389 | if (IsRela) | |||
3390 | Addend += to_string(format_hex_no_prefix(std::abs(RelAddend), 1)); | |||
3391 | ||||
3392 | ||||
3393 | Fields[0].Str = Offset; | |||
3394 | Fields[1].Str = Info; | |||
3395 | Fields[2].Str = RelocName.c_str(); | |||
3396 | Fields[3].Str = Value; | |||
3397 | Fields[4].Str = SymbolName; | |||
3398 | for (auto &Field : Fields) | |||
3399 | printField(Field); | |||
3400 | OS << Addend; | |||
3401 | OS << "\n"; | |||
3402 | } | |||
3403 | ||||
3404 | template <class ELFT> | |||
3405 | void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { | |||
3406 | const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); | |||
3407 | const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); | |||
3408 | const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); | |||
3409 | const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); | |||
3410 | if (DynRelaRegion.Size > 0) { | |||
3411 | OS << "\n'RELA' relocation section at offset " | |||
3412 | << format_hex(reinterpret_cast<const uint8_t *>(DynRelaRegion.Addr) - | |||
3413 | Obj->base(), | |||
3414 | 1) << " contains " << DynRelaRegion.Size << " bytes:\n"; | |||
3415 | printRelocHeader(ELF::SHT_RELA); | |||
3416 | for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) | |||
3417 | printDynamicRelocation(Obj, Rela, true); | |||
3418 | } | |||
3419 | if (DynRelRegion.Size > 0) { | |||
3420 | OS << "\n'REL' relocation section at offset " | |||
3421 | << format_hex(reinterpret_cast<const uint8_t *>(DynRelRegion.Addr) - | |||
3422 | Obj->base(), | |||
3423 | 1) << " contains " << DynRelRegion.Size << " bytes:\n"; | |||
3424 | printRelocHeader(ELF::SHT_REL); | |||
3425 | for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { | |||
3426 | Elf_Rela Rela; | |||
3427 | Rela.r_offset = Rel.r_offset; | |||
3428 | Rela.r_info = Rel.r_info; | |||
3429 | Rela.r_addend = 0; | |||
3430 | printDynamicRelocation(Obj, Rela, false); | |||
3431 | } | |||
3432 | } | |||
3433 | if (DynRelrRegion.Size > 0) { | |||
3434 | OS << "\n'RELR' relocation section at offset " | |||
3435 | << format_hex(reinterpret_cast<const uint8_t *>(DynRelrRegion.Addr) - | |||
3436 | Obj->base(), | |||
3437 | 1) << " contains " << DynRelrRegion.Size << " bytes:\n"; | |||
3438 | printRelocHeader(ELF::SHT_REL); | |||
3439 | Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); | |||
3440 | std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | |||
3441 | for (const Elf_Rela &Rela : RelrRelas) { | |||
3442 | printDynamicRelocation(Obj, Rela, false); | |||
3443 | } | |||
3444 | } | |||
3445 | if (DynPLTRelRegion.Size) { | |||
3446 | OS << "\n'PLT' relocation section at offset " | |||
3447 | << format_hex(reinterpret_cast<const uint8_t *>(DynPLTRelRegion.Addr) - | |||
3448 | Obj->base(), | |||
3449 | 1) << " contains " << DynPLTRelRegion.Size << " bytes:\n"; | |||
3450 | } | |||
3451 | if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { | |||
3452 | printRelocHeader(ELF::SHT_RELA); | |||
3453 | for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) | |||
3454 | printDynamicRelocation(Obj, Rela, true); | |||
3455 | } else { | |||
3456 | printRelocHeader(ELF::SHT_REL); | |||
3457 | for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) { | |||
3458 | Elf_Rela Rela; | |||
3459 | Rela.r_offset = Rel.r_offset; | |||
3460 | Rela.r_info = Rel.r_info; | |||
3461 | Rela.r_addend = 0; | |||
3462 | printDynamicRelocation(Obj, Rela, false); | |||
3463 | } | |||
3464 | } | |||
3465 | } | |||
3466 | ||||
3467 | // Hash histogram shows statistics of how efficient the hash was for the | |||
3468 | // dynamic symbol table. The table shows number of hash buckets for different | |||
3469 | // lengths of chains as absolute number and percentage of the total buckets. | |||
3470 | // Additionally cumulative coverage of symbols for each set of buckets. | |||
3471 | template <class ELFT> | |||
3472 | void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { | |||
3473 | ||||
3474 | const Elf_Hash *HashTable = this->dumper()->getHashTable(); | |||
3475 | const Elf_GnuHash *GnuHashTable = this->dumper()->getGnuHashTable(); | |||
3476 | ||||
3477 | // Print histogram for .hash section | |||
3478 | if (HashTable) { | |||
3479 | size_t NBucket = HashTable->nbucket; | |||
3480 | size_t NChain = HashTable->nchain; | |||
3481 | ArrayRef<Elf_Word> Buckets = HashTable->buckets(); | |||
3482 | ArrayRef<Elf_Word> Chains = HashTable->chains(); | |||
3483 | size_t TotalSyms = 0; | |||
3484 | // If hash table is correct, we have at least chains with 0 length | |||
3485 | size_t MaxChain = 1; | |||
3486 | size_t CumulativeNonZero = 0; | |||
3487 | ||||
3488 | if (NChain == 0 || NBucket == 0) | |||
3489 | return; | |||
3490 | ||||
3491 | std::vector<size_t> ChainLen(NBucket, 0); | |||
3492 | // Go over all buckets and and note chain lengths of each bucket (total | |||
3493 | // unique chain lengths). | |||
3494 | for (size_t B = 0; B < NBucket; B++) { | |||
3495 | for (size_t C = Buckets[B]; C > 0 && C < NChain; C = Chains[C]) | |||
3496 | if (MaxChain <= ++ChainLen[B]) | |||
3497 | MaxChain++; | |||
3498 | TotalSyms += ChainLen[B]; | |||
3499 | } | |||
3500 | ||||
3501 | if (!TotalSyms) | |||
3502 | return; | |||
3503 | ||||
3504 | std::vector<size_t> Count(MaxChain, 0) ; | |||
3505 | // Count how long is the chain for each bucket | |||
3506 | for (size_t B = 0; B < NBucket; B++) | |||
3507 | ++Count[ChainLen[B]]; | |||
3508 | // Print Number of buckets with each chain lengths and their cumulative | |||
3509 | // coverage of the symbols | |||
3510 | OS << "Histogram for bucket list length (total of " << NBucket | |||
3511 | << " buckets)\n" | |||
3512 | << " Length Number % of total Coverage\n"; | |||
3513 | for (size_t I = 0; I < MaxChain; I++) { | |||
3514 | CumulativeNonZero += Count[I] * I; | |||
3515 | OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I], | |||
3516 | (Count[I] * 100.0) / NBucket, | |||
3517 | (CumulativeNonZero * 100.0) / TotalSyms); | |||
3518 | } | |||
3519 | } | |||
3520 | ||||
3521 | // Print histogram for .gnu.hash section | |||
3522 | if (GnuHashTable) { | |||
3523 | size_t NBucket = GnuHashTable->nbuckets; | |||
3524 | ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets(); | |||
3525 | unsigned NumSyms = this->dumper()->dynamic_symbols().size(); | |||
3526 | if (!NumSyms) | |||
3527 | return; | |||
3528 | ArrayRef<Elf_Word> Chains = GnuHashTable->values(NumSyms); | |||
3529 | size_t Symndx = GnuHashTable->symndx; | |||
3530 | size_t TotalSyms = 0; | |||
3531 | size_t MaxChain = 1; | |||
3532 | size_t CumulativeNonZero = 0; | |||
3533 | ||||
3534 | if (Chains.empty() || NBucket == 0) | |||
3535 | return; | |||
3536 | ||||
3537 | std::vector<size_t> ChainLen(NBucket, 0); | |||
3538 | ||||
3539 | for (size_t B = 0; B < NBucket; B++) { | |||
3540 | if (!Buckets[B]) | |||
3541 | continue; | |||
3542 | size_t Len = 1; | |||
3543 | for (size_t C = Buckets[B] - Symndx; | |||
3544 | C < Chains.size() && (Chains[C] & 1) == 0; C++) | |||
3545 | if (MaxChain < ++Len) | |||
3546 | MaxChain++; | |||
3547 | ChainLen[B] = Len; | |||
3548 | TotalSyms += Len; | |||
3549 | } | |||
3550 | MaxChain++; | |||
3551 | ||||
3552 | if (!TotalSyms) | |||
3553 | return; | |||
3554 | ||||
3555 | std::vector<size_t> Count(MaxChain, 0) ; | |||
3556 | for (size_t B = 0; B < NBucket; B++) | |||
3557 | ++Count[ChainLen[B]]; | |||
3558 | // Print Number of buckets with each chain lengths and their cumulative | |||
3559 | // coverage of the symbols | |||
3560 | OS << "Histogram for `.gnu.hash' bucket list length (total of " << NBucket | |||
3561 | << " buckets)\n" | |||
3562 | << " Length Number % of total Coverage\n"; | |||
3563 | for (size_t I = 0; I <MaxChain; I++) { | |||
3564 | CumulativeNonZero += Count[I] * I; | |||
3565 | OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I], | |||
3566 | (Count[I] * 100.0) / NBucket, | |||
3567 | (CumulativeNonZero * 100.0) / TotalSyms); | |||
3568 | } | |||
3569 | } | |||
3570 | } | |||
3571 | ||||
3572 | template <class ELFT> | |||
3573 | void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { | |||
3574 | OS << "GNUStyle::printCGProfile not implemented\n"; | |||
3575 | } | |||
3576 | ||||
3577 | template <class ELFT> | |||
3578 | void GNUStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { | |||
3579 | OS << "GNUStyle::printAddrsig not implemented\n"; | |||
3580 | } | |||
3581 | ||||
3582 | static std::string getGNUNoteTypeName(const uint32_t NT) { | |||
3583 | static const struct { | |||
3584 | uint32_t ID; | |||
3585 | const char *Name; | |||
3586 | } Notes[] = { | |||
3587 | {ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"}, | |||
3588 | {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, | |||
3589 | {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, | |||
3590 | {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, | |||
3591 | {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"}, | |||
3592 | }; | |||
3593 | ||||
3594 | for (const auto &Note : Notes) | |||
3595 | if (Note.ID == NT) | |||
3596 | return std::string(Note.Name); | |||
3597 | ||||
3598 | std::string string; | |||
3599 | raw_string_ostream OS(string); | |||
3600 | OS << format("Unknown note type (0x%08x)", NT); | |||
3601 | return OS.str(); | |||
3602 | } | |||
3603 | ||||
3604 | static std::string getFreeBSDNoteTypeName(const uint32_t NT) { | |||
3605 | static const struct { | |||
3606 | uint32_t ID; | |||
3607 | const char *Name; | |||
3608 | } Notes[] = { | |||
3609 | {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, | |||
3610 | {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, | |||
3611 | {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, | |||
3612 | {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, | |||
3613 | {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, | |||
3614 | {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, | |||
3615 | {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, | |||
3616 | {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"}, | |||
3617 | {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, | |||
3618 | "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, | |||
3619 | {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, | |||
3620 | }; | |||
3621 | ||||
3622 | for (const auto &Note : Notes) | |||
3623 | if (Note.ID == NT) | |||
3624 | return std::string(Note.Name); | |||
3625 | ||||
3626 | std::string string; | |||
3627 | raw_string_ostream OS(string); | |||
3628 | OS << format("Unknown note type (0x%08x)", NT); | |||
3629 | return OS.str(); | |||
3630 | } | |||
3631 | ||||
3632 | static std::string getAMDGPUNoteTypeName(const uint32_t NT) { | |||
3633 | static const struct { | |||
3634 | uint32_t ID; | |||
3635 | const char *Name; | |||
3636 | } Notes[] = { | |||
3637 | {ELF::NT_AMD_AMDGPU_HSA_METADATA, | |||
3638 | "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"}, | |||
3639 | {ELF::NT_AMD_AMDGPU_ISA, | |||
3640 | "NT_AMD_AMDGPU_ISA (ISA Version)"}, | |||
3641 | {ELF::NT_AMD_AMDGPU_PAL_METADATA, | |||
3642 | "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"} | |||
3643 | }; | |||
3644 | ||||
3645 | for (const auto &Note : Notes) | |||
3646 | if (Note.ID == NT) | |||
3647 | return std::string(Note.Name); | |||
3648 | ||||
3649 | std::string string; | |||
3650 | raw_string_ostream OS(string); | |||
3651 | OS << format("Unknown note type (0x%08x)", NT); | |||
3652 | return OS.str(); | |||
3653 | } | |||
3654 | ||||
3655 | template <typename ELFT> | |||
3656 | static void printGNUProperty(raw_ostream &OS, uint32_t Type, uint32_t DataSize, | |||
3657 | ArrayRef<uint8_t> Data) { | |||
3658 | switch (Type) { | |||
3659 | default: | |||
3660 | OS << format(" <application-specific type 0x%x>\n", Type); | |||
3661 | return; | |||
3662 | case GNU_PROPERTY_STACK_SIZE: { | |||
3663 | OS << " stack size: "; | |||
3664 | if (DataSize == sizeof(typename ELFT::uint)) | |||
3665 | OS << format("0x%llx\n", | |||
3666 | (uint64_t)(*(const typename ELFT::Addr *)Data.data())); | |||
3667 | else | |||
3668 | OS << format("<corrupt length: 0x%x>\n", DataSize); | |||
3669 | break; | |||
3670 | } | |||
3671 | case GNU_PROPERTY_NO_COPY_ON_PROTECTED: | |||
3672 | OS << " no copy on protected"; | |||
3673 | if (DataSize) | |||
3674 | OS << format(" <corrupt length: 0x%x>", DataSize); | |||
3675 | OS << "\n"; | |||
3676 | break; | |||
3677 | case GNU_PROPERTY_X86_FEATURE_1_AND: | |||
3678 | OS << " X86 features: "; | |||
3679 | if (DataSize != 4 && DataSize != 8) { | |||
3680 | OS << format("<corrupt length: 0x%x>\n", DataSize); | |||
3681 | break; | |||
3682 | } | |||
3683 | uint64_t CFProtection = | |||
3684 | (DataSize == 4) | |||
3685 | ? support::endian::read32<ELFT::TargetEndianness>(Data.data()) | |||
3686 | : support::endian::read64<ELFT::TargetEndianness>(Data.data()); | |||
3687 | if (CFProtection == 0) { | |||
3688 | OS << "none\n"; | |||
3689 | break; | |||
3690 | } | |||
3691 | if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_IBT) { | |||
3692 | OS << "IBT"; | |||
3693 | CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_IBT; | |||
3694 | if (CFProtection) | |||
3695 | OS << ", "; | |||
3696 | } | |||
3697 | if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_SHSTK) { | |||
3698 | OS << "SHSTK"; | |||
3699 | CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK; | |||
3700 | if (CFProtection) | |||
3701 | OS << ", "; | |||
3702 | } | |||
3703 | if (CFProtection) | |||
3704 | OS << format("<unknown flags: 0x%llx>", CFProtection); | |||
3705 | OS << "\n"; | |||
3706 | break; | |||
3707 | } | |||
3708 | } | |||
3709 | ||||
3710 | template <typename ELFT> | |||
3711 | static void printGNUNote(raw_ostream &OS, uint32_t NoteType, | |||
3712 | ArrayRef<typename ELFT::Word> Words, size_t Size) { | |||
3713 | using Elf_Word = typename ELFT::Word; | |||
3714 | ||||
3715 | switch (NoteType) { | |||
3716 | default: | |||
3717 | return; | |||
3718 | case ELF::NT_GNU_ABI_TAG: { | |||
3719 | static const char *OSNames[] = { | |||
3720 | "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl", | |||
3721 | }; | |||
3722 | ||||
3723 | StringRef OSName = "Unknown"; | |||
3724 | if (Words[0] < array_lengthof(OSNames)) | |||
3725 | OSName = OSNames[Words[0]]; | |||
3726 | uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3]; | |||
3727 | ||||
3728 | if (Words.size() < 4) | |||
3729 | OS << " <corrupt GNU_ABI_TAG>"; | |||
3730 | else | |||
3731 | OS << " OS: " << OSName << ", ABI: " << Major << "." << Minor << "." | |||
3732 | << Patch; | |||
3733 | break; | |||
3734 | } | |||
3735 | case ELF::NT_GNU_BUILD_ID: { | |||
3736 | OS << " Build ID: "; | |||
3737 | ArrayRef<uint8_t> ID(reinterpret_cast<const uint8_t *>(Words.data()), Size); | |||
3738 | for (const auto &B : ID) | |||
3739 | OS << format_hex_no_prefix(B, 2); | |||
3740 | break; | |||
3741 | } | |||
3742 | case ELF::NT_GNU_GOLD_VERSION: | |||
3743 | OS << " Version: " | |||
3744 | << StringRef(reinterpret_cast<const char *>(Words.data()), Size); | |||
3745 | break; | |||
3746 | case ELF::NT_GNU_PROPERTY_TYPE_0: | |||
3747 | OS << " Properties:"; | |||
3748 | ||||
3749 | ArrayRef<uint8_t> Arr(reinterpret_cast<const uint8_t *>(Words.data()), | |||
3750 | Size); | |||
3751 | while (Arr.size() >= 8) { | |||
3752 | uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data()); | |||
3753 | uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4); | |||
3754 | Arr = Arr.drop_front(8); | |||
3755 | ||||
3756 | // Take padding size into account if present. | |||
3757 | uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint)); | |||
3758 | if (Arr.size() < PaddedSize) { | |||
3759 | OS << format(" <corrupt type (0x%x) datasz: 0x%x>\n", Type, | |||
3760 | DataSize); | |||
3761 | break; | |||
3762 | } | |||
3763 | printGNUProperty<ELFT>(OS, Type, DataSize, Arr.take_front(PaddedSize)); | |||
3764 | Arr = Arr.drop_front(PaddedSize); | |||
3765 | } | |||
3766 | ||||
3767 | if (!Arr.empty()) | |||
3768 | OS << " <corrupted GNU_PROPERTY_TYPE_0>"; | |||
3769 | break; | |||
3770 | } | |||
3771 | OS << '\n'; | |||
3772 | } | |||
3773 | ||||
3774 | template <typename ELFT> | |||
3775 | static void printAMDGPUNote(raw_ostream &OS, uint32_t NoteType, | |||
3776 | ArrayRef<typename ELFT::Word> Words, size_t Size) { | |||
3777 | switch (NoteType) { | |||
3778 | default: | |||
3779 | return; | |||
3780 | case ELF::NT_AMD_AMDGPU_HSA_METADATA: | |||
3781 | OS << " HSA Metadata:\n" | |||
3782 | << StringRef(reinterpret_cast<const char *>(Words.data()), Size); | |||
3783 | break; | |||
3784 | case ELF::NT_AMD_AMDGPU_ISA: | |||
3785 | OS << " ISA Version:\n" | |||
3786 | << " " | |||
3787 | << StringRef(reinterpret_cast<const char *>(Words.data()), Size); | |||
3788 | break; | |||
3789 | case ELF::NT_AMD_AMDGPU_PAL_METADATA: | |||
3790 | const uint32_t *PALMetadataBegin = reinterpret_cast<const uint32_t *>(Words.data()); | |||
3791 | const uint32_t *PALMetadataEnd = PALMetadataBegin + Size; | |||
3792 | std::vector<uint32_t> PALMetadata(PALMetadataBegin, PALMetadataEnd); | |||
3793 | std::string PALMetadataString; | |||
3794 | auto Error = AMDGPU::PALMD::toString(PALMetadata, PALMetadataString); | |||
3795 | OS << " PAL Metadata:\n"; | |||
3796 | if (Error) { | |||
3797 | OS << " Invalid"; | |||
3798 | return; | |||
3799 | } | |||
3800 | OS << PALMetadataString; | |||
3801 | break; | |||
3802 | } | |||
3803 | OS.flush(); | |||
3804 | } | |||
3805 | ||||
3806 | template <class ELFT> | |||
3807 | void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { | |||
3808 | const Elf_Ehdr *e = Obj->getHeader(); | |||
3809 | bool IsCore = e->e_type == ELF::ET_CORE; | |||
3810 | ||||
3811 | auto PrintHeader = [&](const typename ELFT::Off Offset, | |||
3812 | const typename ELFT::Addr Size) { | |||
3813 | OS << "Displaying notes found at file offset " << format_hex(Offset, 10) | |||
3814 | << " with length " << format_hex(Size, 10) << ":\n" | |||
3815 | << " Owner Data size\tDescription\n"; | |||
3816 | }; | |||
3817 | ||||
3818 | auto ProcessNote = [&](const Elf_Note &Note) { | |||
3819 | StringRef Name = Note.getName(); | |||
3820 | ArrayRef<Elf_Word> Descriptor = Note.getDesc(); | |||
3821 | Elf_Word Type = Note.getType(); | |||
3822 | ||||
3823 | OS << " " << Name << std::string(22 - Name.size(), ' ') | |||
3824 | << format_hex(Descriptor.size(), 10) << '\t'; | |||
3825 | ||||
3826 | if (Name == "GNU") { | |||
3827 | OS << getGNUNoteTypeName(Type) << '\n'; | |||
3828 | printGNUNote<ELFT>(OS, Type, Descriptor, Descriptor.size()); | |||
3829 | } else if (Name == "FreeBSD") { | |||
3830 | OS << getFreeBSDNoteTypeName(Type) << '\n'; | |||
3831 | } else if (Name == "AMD") { | |||
3832 | OS << getAMDGPUNoteTypeName(Type) << '\n'; | |||
3833 | printAMDGPUNote<ELFT>(OS, Type, Descriptor, Descriptor.size()); | |||
3834 | } else { | |||
3835 | OS << "Unknown note type: (" << format_hex(Type, 10) << ')'; | |||
3836 | } | |||
3837 | OS << '\n'; | |||
3838 | }; | |||
3839 | ||||
3840 | if (IsCore) { | |||
3841 | for (const auto &P : unwrapOrError(Obj->program_headers())) { | |||
3842 | if (P.p_type != PT_NOTE) | |||
3843 | continue; | |||
3844 | PrintHeader(P.p_offset, P.p_filesz); | |||
3845 | Error Err = Error::success(); | |||
3846 | for (const auto &Note : Obj->notes(P, Err)) | |||
3847 | ProcessNote(Note); | |||
3848 | if (Err) | |||
3849 | error(std::move(Err)); | |||
3850 | } | |||
3851 | } else { | |||
3852 | for (const auto &S : unwrapOrError(Obj->sections())) { | |||
3853 | if (S.sh_type != SHT_NOTE) | |||
3854 | continue; | |||
3855 | PrintHeader(S.sh_offset, S.sh_size); | |||
3856 | Error Err = Error::success(); | |||
3857 | for (const auto &Note : Obj->notes(S, Err)) | |||
3858 | ProcessNote(Note); | |||
3859 | if (Err) | |||
3860 | error(std::move(Err)); | |||
3861 | } | |||
3862 | } | |||
3863 | } | |||
3864 | ||||
3865 | template <class ELFT> | |||
3866 | void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { | |||
3867 | OS << "printELFLinkerOptions not implemented!\n"; | |||
3868 | } | |||
3869 | ||||
3870 | template <class ELFT> | |||
3871 | void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { | |||
3872 | size_t Bias = ELFT::Is64Bits ? 8 : 0; | |||
3873 | auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { | |||
3874 | OS.PadToColumn(2); | |||
3875 | OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); | |||
3876 | OS.PadToColumn(11 + Bias); | |||
3877 | OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)"; | |||
3878 | OS.PadToColumn(22 + Bias); | |||
3879 | OS << format_hex_no_prefix(*E, 8 + Bias); | |||
3880 | OS.PadToColumn(31 + 2 * Bias); | |||
3881 | OS << Purpose << "\n"; | |||
3882 | }; | |||
3883 | ||||
3884 | OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n"); | |||
3885 | OS << " Canonical gp value: " | |||
3886 | << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n"; | |||
3887 | ||||
3888 | OS << " Reserved entries:\n"; | |||
3889 | OS << " Address Access Initial Purpose\n"; | |||
3890 | PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver"); | |||
3891 | if (Parser.getGotModulePointer()) | |||
3892 | PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)"); | |||
3893 | ||||
3894 | if (!Parser.getLocalEntries().empty()) { | |||
3895 | OS << "\n"; | |||
3896 | OS << " Local entries:\n"; | |||
3897 | OS << " Address Access Initial\n"; | |||
3898 | for (auto &E : Parser.getLocalEntries()) | |||
3899 | PrintEntry(&E, ""); | |||
3900 | } | |||
3901 | ||||
3902 | if (Parser.IsStatic) | |||
3903 | return; | |||
3904 | ||||
3905 | if (!Parser.getGlobalEntries().empty()) { | |||
3906 | OS << "\n"; | |||
3907 | OS << " Global entries:\n"; | |||
3908 | OS << " Address Access Initial Sym.Val. Type Ndx Name\n"; | |||
3909 | for (auto &E : Parser.getGlobalEntries()) { | |||
3910 | const Elf_Sym *Sym = Parser.getGotSym(&E); | |||
3911 | std::string SymName = this->dumper()->getFullSymbolName( | |||
3912 | Sym, this->dumper()->getDynamicStringTable(), false); | |||
3913 | ||||
3914 | OS.PadToColumn(2); | |||
3915 | OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); | |||
3916 | OS.PadToColumn(11 + Bias); | |||
3917 | OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)"; | |||
3918 | OS.PadToColumn(22 + Bias); | |||
3919 | OS << to_string(format_hex_no_prefix(E, 8 + Bias)); | |||
3920 | OS.PadToColumn(31 + 2 * Bias); | |||
3921 | OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); | |||
3922 | OS.PadToColumn(40 + 3 * Bias); | |||
3923 | OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); | |||
3924 | OS.PadToColumn(48 + 3 * Bias); | |||
3925 | OS << getSymbolSectionNdx(Parser.Obj, Sym, | |||
3926 | this->dumper()->dynamic_symbols().begin()); | |||
3927 | OS.PadToColumn(52 + 3 * Bias); | |||
3928 | OS << SymName << "\n"; | |||
3929 | } | |||
3930 | } | |||
3931 | ||||
3932 | if (!Parser.getOtherEntries().empty()) | |||
3933 | OS << "\n Number of TLS and multi-GOT entries " | |||
3934 | << Parser.getOtherEntries().size() << "\n"; | |||
3935 | } | |||
3936 | ||||
3937 | template <class ELFT> | |||
3938 | void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { | |||
3939 | size_t Bias = ELFT::Is64Bits ? 8 : 0; | |||
3940 | auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { | |||
3941 | OS.PadToColumn(2); | |||
3942 | OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); | |||
3943 | OS.PadToColumn(11 + Bias); | |||
3944 | OS << format_hex_no_prefix(*E, 8 + Bias); | |||
3945 | OS.PadToColumn(20 + 2 * Bias); | |||
3946 | OS << Purpose << "\n"; | |||
3947 | }; | |||
3948 | ||||
3949 | OS << "PLT GOT:\n\n"; | |||
3950 | ||||
3951 | OS << " Reserved entries:\n"; | |||
3952 | OS << " Address Initial Purpose\n"; | |||
3953 | PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver"); | |||
3954 | if (Parser.getPltModulePointer()) | |||
3955 | PrintEntry(Parser.getGotModulePointer(), "Module pointer"); | |||
3956 | ||||
3957 | if (!Parser.getPltEntries().empty()) { | |||
3958 | OS << "\n"; | |||
3959 | OS << " Entries:\n"; | |||
3960 | OS << " Address Initial Sym.Val. Type Ndx Name\n"; | |||
3961 | for (auto &E : Parser.getPltEntries()) { | |||
3962 | const Elf_Sym *Sym = Parser.getPltSym(&E); | |||
3963 | std::string SymName = this->dumper()->getFullSymbolName( | |||
3964 | Sym, this->dumper()->getDynamicStringTable(), false); | |||
3965 | ||||
3966 | OS.PadToColumn(2); | |||
3967 | OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); | |||
3968 | OS.PadToColumn(11 + Bias); | |||
3969 | OS << to_string(format_hex_no_prefix(E, 8 + Bias)); | |||
3970 | OS.PadToColumn(20 + 2 * Bias); | |||
3971 | OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); | |||
3972 | OS.PadToColumn(29 + 3 * Bias); | |||
3973 | OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); | |||
3974 | OS.PadToColumn(37 + 3 * Bias); | |||
3975 | OS << getSymbolSectionNdx(Parser.Obj, Sym, | |||
3976 | this->dumper()->dynamic_symbols().begin()); | |||
3977 | OS.PadToColumn(41 + 3 * Bias); | |||
3978 | OS << SymName << "\n"; | |||
3979 | } | |||
3980 | } | |||
3981 | } | |||
3982 | ||||
3983 | template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) { | |||
3984 | const Elf_Ehdr *e = Obj->getHeader(); | |||
3985 | { | |||
3986 | DictScope D(W, "ElfHeader"); | |||
3987 | { | |||
3988 | DictScope D(W, "Ident"); | |||
3989 | W.printBinary("Magic", makeArrayRef(e->e_ident).slice(ELF::EI_MAG0, 4)); | |||
3990 | W.printEnum("Class", e->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass)); | |||
3991 | W.printEnum("DataEncoding", e->e_ident[ELF::EI_DATA], | |||
3992 | makeArrayRef(ElfDataEncoding)); | |||
3993 | W.printNumber("FileVersion", e->e_ident[ELF::EI_VERSION]); | |||
3994 | ||||
3995 | auto OSABI = makeArrayRef(ElfOSABI); | |||
3996 | if (e->e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH && | |||
3997 | e->e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) { | |||
3998 | switch (e->e_machine) { | |||
3999 | case ELF::EM_AMDGPU: | |||
4000 | OSABI = makeArrayRef(AMDGPUElfOSABI); | |||
4001 | break; | |||
4002 | case ELF::EM_ARM: | |||
4003 | OSABI = makeArrayRef(ARMElfOSABI); | |||
4004 | break; | |||
4005 | case ELF::EM_TI_C6000: | |||
4006 | OSABI = makeArrayRef(C6000ElfOSABI); | |||
4007 | break; | |||
4008 | } | |||
4009 | } | |||
4010 | W.printEnum("OS/ABI", e->e_ident[ELF::EI_OSABI], OSABI); | |||
4011 | W.printNumber("ABIVersion", e->e_ident[ELF::EI_ABIVERSION]); | |||
4012 | W.printBinary("Unused", makeArrayRef(e->e_ident).slice(ELF::EI_PAD)); | |||
4013 | } | |||
4014 | ||||
4015 | W.printEnum("Type", e->e_type, makeArrayRef(ElfObjectFileType)); | |||
4016 | W.printEnum("Machine", e->e_machine, makeArrayRef(ElfMachineType)); | |||
4017 | W.printNumber("Version", e->e_version); | |||
4018 | W.printHex("Entry", e->e_entry); | |||
4019 | W.printHex("ProgramHeaderOffset", e->e_phoff); | |||
4020 | W.printHex("SectionHeaderOffset", e->e_shoff); | |||
4021 | if (e->e_machine == EM_MIPS) | |||
4022 | W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderMipsFlags), | |||
4023 | unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), | |||
4024 | unsigned(ELF::EF_MIPS_MACH)); | |||
4025 | else if (e->e_machine == EM_AMDGPU) | |||
4026 | W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderAMDGPUFlags), | |||
4027 | unsigned(ELF::EF_AMDGPU_MACH)); | |||
4028 | else if (e->e_machine == EM_RISCV) | |||
4029 | W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderRISCVFlags)); | |||
4030 | else | |||
4031 | W.printFlags("Flags", e->e_flags); | |||
4032 | W.printNumber("HeaderSize", e->e_ehsize); | |||
4033 | W.printNumber("ProgramHeaderEntrySize", e->e_phentsize); | |||
4034 | W.printNumber("ProgramHeaderCount", e->e_phnum); | |||
4035 | W.printNumber("SectionHeaderEntrySize", e->e_shentsize); | |||
4036 | W.printString("SectionHeaderCount", getSectionHeadersNumString(Obj)); | |||
4037 | W.printString("StringTableSectionIndex", getSectionHeaderTableIndexString(Obj)); | |||
4038 | } | |||
4039 | } | |||
4040 | ||||
4041 | template <class ELFT> | |||
4042 | void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) { | |||
4043 | DictScope Lists(W, "Groups"); | |||
4044 | std::vector<GroupSection> V = getGroups<ELFT>(Obj); | |||
4045 | DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); | |||
4046 | for (const GroupSection &G : V) { | |||
4047 | DictScope D(W, "Group"); | |||
4048 | W.printNumber("Name", G.Name, G.ShName); | |||
4049 | W.printNumber("Index", G.Index); | |||
4050 | W.printNumber("Link", G.Link); | |||
4051 | W.printNumber("Info", G.Info); | |||
4052 | W.printHex("Type", getGroupType(G.Type), G.Type); | |||
4053 | W.startLine() << "Signature: " << G.Signature << "\n"; | |||
4054 | ||||
4055 | ListScope L(W, "Section(s) in group"); | |||
4056 | for (const GroupMember &GM : G.Members) { | |||
4057 | const GroupSection *MainGroup = Map[GM.Index]; | |||
4058 | if (MainGroup != &G) { | |||
4059 | W.flush(); | |||
4060 | errs() << "Error: " << GM.Name << " (" << GM.Index | |||
4061 | << ") in a group " + G.Name + " (" << G.Index | |||
4062 | << ") is already in a group " + MainGroup->Name + " (" | |||
4063 | << MainGroup->Index << ")\n"; | |||
4064 | errs().flush(); | |||
4065 | continue; | |||
4066 | } | |||
4067 | W.startLine() << GM.Name << " (" << GM.Index << ")\n"; | |||
4068 | } | |||
4069 | } | |||
4070 | ||||
4071 | if (V.empty()) | |||
4072 | W.startLine() << "There are no group sections in the file.\n"; | |||
4073 | } | |||
4074 | ||||
4075 | template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) { | |||
4076 | ListScope D(W, "Relocations"); | |||
4077 | ||||
4078 | int SectionNumber = -1; | |||
4079 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | |||
4080 | ++SectionNumber; | |||
4081 | ||||
4082 | if (Sec.sh_type != ELF::SHT_REL && | |||
4083 | Sec.sh_type != ELF::SHT_RELA && | |||
4084 | Sec.sh_type != ELF::SHT_RELR && | |||
4085 | Sec.sh_type != ELF::SHT_ANDROID_REL && | |||
4086 | Sec.sh_type != ELF::SHT_ANDROID_RELA && | |||
4087 | Sec.sh_type != ELF::SHT_ANDROID_RELR) | |||
4088 | continue; | |||
4089 | ||||
4090 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | |||
4091 | ||||
4092 | W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; | |||
4093 | W.indent(); | |||
4094 | ||||
4095 | printRelocations(&Sec, Obj); | |||
4096 | ||||
4097 | W.unindent(); | |||
4098 | W.startLine() << "}\n"; | |||
4099 | } | |||
4100 | } | |||
4101 | ||||
4102 | template <class ELFT> | |||
4103 | void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { | |||
4104 | const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link)); | |||
4105 | ||||
4106 | switch (Sec->sh_type) { | |||
4107 | case ELF::SHT_REL: | |||
4108 | for (const Elf_Rel &R : unwrapOrError(Obj->rels(Sec))) { | |||
4109 | Elf_Rela Rela; | |||
4110 | Rela.r_offset = R.r_offset; | |||
4111 | Rela.r_info = R.r_info; | |||
4112 | Rela.r_addend = 0; | |||
4113 | printRelocation(Obj, Rela, SymTab); | |||
4114 | } | |||
4115 | break; | |||
4116 | case ELF::SHT_RELA: | |||
4117 | for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec))) | |||
4118 | printRelocation(Obj, R, SymTab); | |||
4119 | break; | |||
4120 | case ELF::SHT_RELR: | |||
4121 | case ELF::SHT_ANDROID_RELR: { | |||
4122 | Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec)); | |||
4123 | if (opts::RawRelr) { | |||
4124 | for (const Elf_Relr &R : Relrs) | |||
4125 | W.startLine() << W.hex(R) << "\n"; | |||
4126 | } else { | |||
4127 | std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | |||
4128 | for (const Elf_Rela &R : RelrRelas) | |||
4129 | printRelocation(Obj, R, SymTab); | |||
4130 | } | |||
4131 | break; | |||
4132 | } | |||
4133 | case ELF::SHT_ANDROID_REL: | |||
4134 | case ELF::SHT_ANDROID_RELA: | |||
4135 | for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec))) | |||
4136 | printRelocation(Obj, R, SymTab); | |||
4137 | break; | |||
4138 | } | |||
4139 | } | |||
4140 | ||||
4141 | template <class ELFT> | |||
4142 | void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel, | |||
4143 | const Elf_Shdr *SymTab) { | |||
4144 | SmallString<32> RelocName; | |||
4145 | Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); | |||
4146 | StringRef TargetName; | |||
4147 | const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab)); | |||
4148 | if (Sym && Sym->getType() == ELF::STT_SECTION) { | |||
4149 | const Elf_Shdr *Sec = unwrapOrError( | |||
4150 | Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); | |||
4151 | TargetName = unwrapOrError(Obj->getSectionName(Sec)); | |||
4152 | } else if (Sym) { | |||
4153 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); | |||
4154 | TargetName = unwrapOrError(Sym->getName(StrTable)); | |||
4155 | } | |||
4156 | ||||
4157 | if (opts::ExpandRelocs) { | |||
4158 | DictScope Group(W, "Relocation"); | |||
4159 | W.printHex("Offset", Rel.r_offset); | |||
4160 | W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); | |||
4161 | W.printNumber("Symbol", !TargetName.empty() ? TargetName : "-", | |||
4162 | Rel.getSymbol(Obj->isMips64EL())); | |||
4163 | W.printHex("Addend", Rel.r_addend); | |||
4164 | } else { | |||
4165 | raw_ostream &OS = W.startLine(); | |||
4166 | OS << W.hex(Rel.r_offset) << " " << RelocName << " " | |||
4167 | << (!TargetName.empty() ? TargetName : "-") << " " | |||
4168 | << W.hex(Rel.r_addend) << "\n"; | |||
4169 | } | |||
4170 | } | |||
4171 | ||||
4172 | template <class ELFT> void LLVMStyle<ELFT>::printSections(const ELFO *Obj) { | |||
4173 | ListScope SectionsD(W, "Sections"); | |||
4174 | ||||
4175 | int SectionIndex = -1; | |||
4176 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | |||
4177 | ++SectionIndex; | |||
4178 | ||||
4179 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | |||
4180 | ||||
4181 | DictScope SectionD(W, "Section"); | |||
4182 | W.printNumber("Index", SectionIndex); | |||
4183 | W.printNumber("Name", Name, Sec.sh_name); | |||
4184 | W.printHex( | |||
4185 | "Type", | |||
4186 | object::getELFSectionTypeName(Obj->getHeader()->e_machine, Sec.sh_type), | |||
4187 | Sec.sh_type); | |||
4188 | std::vector<EnumEntry<unsigned>> SectionFlags(std::begin(ElfSectionFlags), | |||
4189 | std::end(ElfSectionFlags)); | |||
4190 | switch (Obj->getHeader()->e_machine) { | |||
4191 | case EM_ARM: | |||
4192 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags), | |||
4193 | std::end(ElfARMSectionFlags)); | |||
4194 | break; | |||
4195 | case EM_HEXAGON: | |||
4196 | SectionFlags.insert(SectionFlags.end(), | |||
4197 | std::begin(ElfHexagonSectionFlags), | |||
4198 | std::end(ElfHexagonSectionFlags)); | |||
4199 | break; | |||
4200 | case EM_MIPS: | |||
4201 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfMipsSectionFlags), | |||
4202 | std::end(ElfMipsSectionFlags)); | |||
4203 | break; | |||
4204 | case EM_X86_64: | |||
4205 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfX86_64SectionFlags), | |||
4206 | std::end(ElfX86_64SectionFlags)); | |||
4207 | break; | |||
4208 | case EM_XCORE: | |||
4209 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfXCoreSectionFlags), | |||
4210 | std::end(ElfXCoreSectionFlags)); | |||
4211 | break; | |||
4212 | default: | |||
4213 | // Nothing to do. | |||
4214 | break; | |||
4215 | } | |||
4216 | W.printFlags("Flags", Sec.sh_flags, makeArrayRef(SectionFlags)); | |||
4217 | W.printHex("Address", Sec.sh_addr); | |||
4218 | W.printHex("Offset", Sec.sh_offset); | |||
4219 | W.printNumber("Size", Sec.sh_size); | |||
4220 | W.printNumber("Link", Sec.sh_link); | |||
4221 | W.printNumber("Info", Sec.sh_info); | |||
4222 | W.printNumber("AddressAlignment", Sec.sh_addralign); | |||
4223 | W.printNumber("EntrySize", Sec.sh_entsize); | |||
4224 | ||||
4225 | if (opts::SectionRelocations) { | |||
4226 | ListScope D(W, "Relocations"); | |||
4227 | printRelocations(&Sec, Obj); | |||
4228 | } | |||
4229 | ||||
4230 | if (opts::SectionSymbols) { | |||
4231 | ListScope D(W, "Symbols"); | |||
4232 | const Elf_Shdr *Symtab = this->dumper()->getDotSymtabSec(); | |||
4233 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); | |||
4234 | ||||
4235 | for (const Elf_Sym &Sym : unwrapOrError(Obj->symbols(Symtab))) { | |||
4236 | const Elf_Shdr *SymSec = unwrapOrError( | |||
4237 | Obj->getSection(&Sym, Symtab, this->dumper()->getShndxTable())); | |||
4238 | if (SymSec == &Sec) | |||
4239 | printSymbol(Obj, &Sym, unwrapOrError(Obj->symbols(Symtab)).begin(), | |||
4240 | StrTable, false); | |||
4241 | } | |||
4242 | } | |||
4243 | ||||
4244 | if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { | |||
4245 | ArrayRef<uint8_t> Data = unwrapOrError(Obj->getSectionContents(&Sec)); | |||
4246 | W.printBinaryBlock("SectionData", | |||
4247 | StringRef((const char *)Data.data(), Data.size())); | |||
4248 | } | |||
4249 | } | |||
4250 | } | |||
4251 | ||||
4252 | template <class ELFT> | |||
4253 | void LLVMStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, | |||
4254 | const Elf_Sym *First, StringRef StrTable, | |||
4255 | bool IsDynamic) { | |||
4256 | unsigned SectionIndex = 0; | |||
4257 | StringRef SectionName; | |||
4258 | this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex); | |||
4259 | std::string FullSymbolName = | |||
4260 | this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic); | |||
4261 | unsigned char SymbolType = Symbol->getType(); | |||
4262 | ||||
4263 | DictScope D(W, "Symbol"); | |||
4264 | W.printNumber("Name", FullSymbolName, Symbol->st_name); | |||
4265 | W.printHex("Value", Symbol->st_value); | |||
4266 | W.printNumber("Size", Symbol->st_size); | |||
4267 | W.printEnum("Binding", Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); | |||
4268 | if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && | |||
4269 | SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) | |||
4270 | W.printEnum("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); | |||
4271 | else | |||
4272 | W.printEnum("Type", SymbolType, makeArrayRef(ElfSymbolTypes)); | |||
4273 | if (Symbol->st_other == 0) | |||
4274 | // Usually st_other flag is zero. Do not pollute the output | |||
4275 | // by flags enumeration in that case. | |||
4276 | W.printNumber("Other", 0); | |||
4277 | else { | |||
4278 | std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags), | |||
4279 | std::end(ElfSymOtherFlags)); | |||
4280 | if (Obj->getHeader()->e_machine == EM_MIPS) { | |||
4281 | // Someones in their infinite wisdom decided to make STO_MIPS_MIPS16 | |||
4282 | // flag overlapped with other ST_MIPS_xxx flags. So consider both | |||
4283 | // cases separately. | |||
4284 | if ((Symbol->st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16) | |||
4285 | SymOtherFlags.insert(SymOtherFlags.end(), | |||
4286 | std::begin(ElfMips16SymOtherFlags), | |||
4287 | std::end(ElfMips16SymOtherFlags)); | |||
4288 | else | |||
4289 | SymOtherFlags.insert(SymOtherFlags.end(), | |||
4290 | std::begin(ElfMipsSymOtherFlags), | |||
4291 | std::end(ElfMipsSymOtherFlags)); | |||
4292 | } | |||
4293 | W.printFlags("Other", Symbol->st_other, makeArrayRef(SymOtherFlags), 0x3u); | |||
4294 | } | |||
4295 | W.printHex("Section", SectionName, SectionIndex); | |||
4296 | } | |||
4297 | ||||
4298 | template <class ELFT> void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj) { | |||
4299 | ListScope Group(W, "Symbols"); | |||
4300 | this->dumper()->printSymbolsHelper(false); | |||
4301 | } | |||
4302 | ||||
4303 | template <class ELFT> | |||
4304 | void LLVMStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) { | |||
4305 | ListScope Group(W, "DynamicSymbols"); | |||
4306 | this->dumper()->printSymbolsHelper(true); | |||
4307 | } | |||
4308 | ||||
4309 | template <class ELFT> | |||
4310 | void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { | |||
4311 | const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); | |||
4312 | const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); | |||
4313 | const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); | |||
4314 | const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); | |||
4315 | if (DynRelRegion.Size && DynRelaRegion.Size) | |||
4316 | report_fatal_error("There are both REL and RELA dynamic relocations"); | |||
4317 | W.startLine() << "Dynamic Relocations {\n"; | |||
4318 | W.indent(); | |||
4319 | if (DynRelaRegion.Size > 0) | |||
4320 | for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) | |||
4321 | printDynamicRelocation(Obj, Rela); | |||
4322 | else | |||
4323 | for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { | |||
4324 | Elf_Rela Rela; | |||
4325 | Rela.r_offset = Rel.r_offset; | |||
4326 | Rela.r_info = Rel.r_info; | |||
4327 | Rela.r_addend = 0; | |||
4328 | printDynamicRelocation(Obj, Rela); | |||
4329 | } | |||
4330 | if (DynRelrRegion.Size > 0) { | |||
4331 | Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); | |||
4332 | std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | |||
4333 | for (const Elf_Rela &Rela : RelrRelas) | |||
4334 | printDynamicRelocation(Obj, Rela); | |||
4335 | } | |||
4336 | if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) | |||
4337 | for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) | |||
4338 | printDynamicRelocation(Obj, Rela); | |||
4339 | else | |||
4340 | for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) { | |||
4341 | Elf_Rela Rela; | |||
4342 | Rela.r_offset = Rel.r_offset; | |||
4343 | Rela.r_info = Rel.r_info; | |||
4344 | Rela.r_addend = 0; | |||
4345 | printDynamicRelocation(Obj, Rela); | |||
4346 | } | |||
4347 | W.unindent(); | |||
4348 | W.startLine() << "}\n"; | |||
4349 | } | |||
4350 | ||||
4351 | template <class ELFT> | |||
4352 | void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { | |||
4353 | SmallString<32> RelocName; | |||
4354 | Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); | |||
4355 | StringRef SymbolName; | |||
4356 | uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); | |||
4357 | const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; | |||
4358 | SymbolName = | |||
4359 | unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); | |||
4360 | if (opts::ExpandRelocs) { | |||
4361 | DictScope Group(W, "Relocation"); | |||
4362 | W.printHex("Offset", Rel.r_offset); | |||
4363 | W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); | |||
4364 | W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-"); | |||
4365 | W.printHex("Addend", Rel.r_addend); | |||
4366 | } else { | |||
4367 | raw_ostream &OS = W.startLine(); | |||
4368 | OS << W.hex(Rel.r_offset) << " " << RelocName << " " | |||
4369 | << (!SymbolName.empty() ? SymbolName : "-") << " " | |||
4370 | << W.hex(Rel.r_addend) << "\n"; | |||
4371 | } | |||
4372 | } | |||
4373 | ||||
4374 | template <class ELFT> | |||
4375 | void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { | |||
4376 | ListScope L(W, "ProgramHeaders"); | |||
4377 | ||||
4378 | for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { | |||
4379 | DictScope P(W, "ProgramHeader"); | |||
4380 | W.printHex("Type", | |||
4381 | getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type), | |||
4382 | Phdr.p_type); | |||
4383 | W.printHex("Offset", Phdr.p_offset); | |||
4384 | W.printHex("VirtualAddress", Phdr.p_vaddr); | |||
4385 | W.printHex("PhysicalAddress", Phdr.p_paddr); | |||
4386 | W.printNumber("FileSize", Phdr.p_filesz); | |||
4387 | W.printNumber("MemSize", Phdr.p_memsz); | |||
4388 | W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags)); | |||
4389 | W.printNumber("Alignment", Phdr.p_align); | |||
4390 | } | |||
4391 | } | |||
4392 | ||||
4393 | template <class ELFT> | |||
4394 | void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { | |||
4395 | W.startLine() << "Hash Histogram not implemented!\n"; | |||
4396 | } | |||
4397 | ||||
4398 | template <class ELFT> | |||
4399 | void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { | |||
4400 | ListScope L(W, "CGProfile"); | |||
4401 | if (!this->dumper()->getDotCGProfileSec()) | |||
4402 | return; | |||
4403 | auto CGProfile = | |||
4404 | unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>( | |||
4405 | this->dumper()->getDotCGProfileSec())); | |||
4406 | for (const Elf_CGProfile &CGPE : CGProfile) { | |||
4407 | DictScope D(W, "CGProfileEntry"); | |||
4408 | W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from), | |||
4409 | CGPE.cgp_from); | |||
4410 | W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to), | |||
4411 | CGPE.cgp_to); | |||
4412 | W.printNumber("Weight", CGPE.cgp_weight); | |||
4413 | } | |||
4414 | } | |||
4415 | ||||
4416 | template <class ELFT> | |||
4417 | void LLVMStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { | |||
4418 | ListScope L(W, "Addrsig"); | |||
4419 | if (!this->dumper()->getDotAddrsigSec()) | |||
4420 | return; | |||
4421 | ArrayRef<uint8_t> Contents = unwrapOrError( | |||
4422 | Obj->getSectionContents(this->dumper()->getDotAddrsigSec())); | |||
4423 | const uint8_t *Cur = Contents.begin(); | |||
4424 | const uint8_t *End = Contents.end(); | |||
4425 | while (Cur != End) { | |||
4426 | unsigned Size; | |||
4427 | const char *Err; | |||
4428 | uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err); | |||
4429 | if (Err) | |||
4430 | reportError(Err); | |||
4431 | W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex), | |||
4432 | SymIndex); | |||
4433 | Cur += Size; | |||
4434 | } | |||
4435 | } | |||
4436 | ||||
4437 | template <class ELFT> | |||
4438 | void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { | |||
4439 | W.startLine() << "printNotes not implemented!\n"; | |||
4440 | } | |||
4441 | ||||
4442 | template <class ELFT> | |||
4443 | void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { | |||
4444 | ListScope L(W, "LinkerOptions"); | |||
4445 | ||||
4446 | for (const Elf_Shdr &Shdr : unwrapOrError(Obj->sections())) { | |||
4447 | if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS) | |||
4448 | continue; | |||
4449 | ||||
4450 | ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Shdr)); | |||
4451 | for (const uint8_t *P = Contents.begin(), *E = Contents.end(); P < E; ) { | |||
4452 | StringRef Key = StringRef(reinterpret_cast<const char *>(P)); | |||
4453 | StringRef Value = | |||
4454 | StringRef(reinterpret_cast<const char *>(P) + Key.size() + 1); | |||
4455 | ||||
4456 | W.printString(Key, Value); | |||
4457 | ||||
4458 | P = P + Key.size() + Value.size() + 2; | |||
4459 | } | |||
4460 | } | |||
4461 | } | |||
4462 | ||||
4463 | template <class ELFT> | |||
4464 | void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { | |||
4465 | auto PrintEntry = [&](const Elf_Addr *E) { | |||
4466 | W.printHex("Address", Parser.getGotAddress(E)); | |||
4467 | W.printNumber("Access", Parser.getGotOffset(E)); | |||
4468 | W.printHex("Initial", *E); | |||
4469 | }; | |||
4470 | ||||
4471 | DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT"); | |||
4472 | ||||
4473 | W.printHex("Canonical gp value", Parser.getGp()); | |||
4474 | { | |||
4475 | ListScope RS(W, "Reserved entries"); | |||
4476 | { | |||
4477 | DictScope D(W, "Entry"); | |||
4478 | PrintEntry(Parser.getGotLazyResolver()); | |||
4479 | W.printString("Purpose", StringRef("Lazy resolver")); | |||
4480 | } | |||
4481 | ||||
4482 | if (Parser.getGotModulePointer()) { | |||
4483 | DictScope D(W, "Entry"); | |||
4484 | PrintEntry(Parser.getGotModulePointer()); | |||
4485 | W.printString("Purpose", StringRef("Module pointer (GNU extension)")); | |||
4486 | } | |||
4487 | } | |||
4488 | { | |||
4489 | ListScope LS(W, "Local entries"); | |||
4490 | for (auto &E : Parser.getLocalEntries()) { | |||
4491 | DictScope D(W, "Entry"); | |||
4492 | PrintEntry(&E); | |||
4493 | } | |||
4494 | } | |||
4495 | ||||
4496 | if (Parser.IsStatic) | |||
4497 | return; | |||
4498 | ||||
4499 | { | |||
4500 | ListScope GS(W, "Global entries"); | |||
4501 | for (auto &E : Parser.getGlobalEntries()) { | |||
4502 | DictScope D(W, "Entry"); | |||
4503 | ||||
4504 | PrintEntry(&E); | |||
4505 | ||||
4506 | const Elf_Sym *Sym = Parser.getGotSym(&E); | |||
4507 | W.printHex("Value", Sym->st_value); | |||
4508 | W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); | |||
4509 | ||||
4510 | unsigned SectionIndex = 0; | |||
4511 | StringRef SectionName; | |||
4512 | this->dumper()->getSectionNameIndex( | |||
4513 | Sym, this->dumper()->dynamic_symbols().begin(), SectionName, | |||
4514 | SectionIndex); | |||
4515 | W.printHex("Section", SectionName, SectionIndex); | |||
4516 | ||||
4517 | std::string SymName = this->dumper()->getFullSymbolName( | |||
4518 | Sym, this->dumper()->getDynamicStringTable(), true); | |||
4519 | W.printNumber("Name", SymName, Sym->st_name); | |||
4520 | } | |||
4521 | } | |||
4522 | ||||
4523 | W.printNumber("Number of TLS and multi-GOT entries", | |||
4524 | uint64_t(Parser.getOtherEntries().size())); | |||
4525 | } | |||
4526 | ||||
4527 | template <class ELFT> | |||
4528 | void LLVMStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { | |||
4529 | auto PrintEntry = [&](const Elf_Addr *E) { | |||
4530 | W.printHex("Address", Parser.getPltAddress(E)); | |||
4531 | W.printHex("Initial", *E); | |||
4532 | }; | |||
4533 | ||||
4534 | DictScope GS(W, "PLT GOT"); | |||
4535 | ||||
4536 | { | |||
4537 | ListScope RS(W, "Reserved entries"); | |||
4538 | { | |||
4539 | DictScope D(W, "Entry"); | |||
4540 | PrintEntry(Parser.getPltLazyResolver()); | |||
4541 | W.printString("Purpose", StringRef("PLT lazy resolver")); | |||
4542 | } | |||
4543 | ||||
4544 | if (auto E = Parser.getPltModulePointer()) { | |||
4545 | DictScope D(W, "Entry"); | |||
4546 | PrintEntry(E); | |||
4547 | W.printString("Purpose", StringRef("Module pointer")); | |||
4548 | } | |||
4549 | } | |||
4550 | { | |||
4551 | ListScope LS(W, "Entries"); | |||
4552 | for (auto &E : Parser.getPltEntries()) { | |||
4553 | DictScope D(W, "Entry"); | |||
4554 | PrintEntry(&E); | |||
4555 | ||||
4556 | const Elf_Sym *Sym = Parser.getPltSym(&E); | |||
4557 | W.printHex("Value", Sym->st_value); | |||
4558 | W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); | |||
4559 | ||||
4560 | unsigned SectionIndex = 0; | |||
4561 | StringRef SectionName; | |||
4562 | this->dumper()->getSectionNameIndex( | |||
4563 | Sym, this->dumper()->dynamic_symbols().begin(), SectionName, | |||
4564 | SectionIndex); | |||
4565 | W.printHex("Section", SectionName, SectionIndex); | |||
4566 | ||||
4567 | std::string SymName = | |||
4568 | this->dumper()->getFullSymbolName(Sym, Parser.getPltStrTable(), true); | |||
4569 | W.printNumber("Name", SymName, Sym->st_name); | |||
4570 | } | |||
4571 | } | |||
4572 | } |