File: | include/llvm/Support/Error.h |
Warning: | line 201, column 5 Potential leak of memory pointed to by 'Payload._M_t._M_head_impl' |
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 | } |
1 | //===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer -----===// |
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 | #ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H |
11 | #define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H |
12 | |
13 | #include "Error.h" |
14 | #include "llvm-readobj.h" |
15 | #include "llvm/ADT/STLExtras.h" |
16 | #include "llvm/BinaryFormat/Dwarf.h" |
17 | #include "llvm/Object/ELF.h" |
18 | #include "llvm/Object/ELFTypes.h" |
19 | #include "llvm/Support/Casting.h" |
20 | #include "llvm/Support/ScopedPrinter.h" |
21 | #include "llvm/Support/Debug.h" |
22 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" |
23 | #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" |
24 | #include "llvm/Support/Endian.h" |
25 | #include "llvm/Support/Format.h" |
26 | #include "llvm/Support/type_traits.h" |
27 | |
28 | namespace llvm { |
29 | namespace DwarfCFIEH { |
30 | |
31 | template <typename ELFT> |
32 | class PrinterContext { |
33 | ScopedPrinter &W; |
34 | const object::ELFFile<ELFT> *Obj; |
35 | |
36 | void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size) const; |
37 | |
38 | void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const; |
39 | |
40 | public: |
41 | PrinterContext(ScopedPrinter &W, const object::ELFFile<ELFT> *Obj) |
42 | : W(W), Obj(Obj) {} |
43 | |
44 | void printUnwindInformation() const; |
45 | }; |
46 | |
47 | template <class ELFO> |
48 | static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj, |
49 | uint64_t Addr) { |
50 | auto Sections = Obj->sections(); |
51 | if (Error E = Sections.takeError()) |
52 | reportError(toString(std::move(E))); |
53 | |
54 | for (const auto &Shdr : *Sections) |
55 | if (Shdr.sh_addr == Addr) |
56 | return &Shdr; |
57 | return nullptr; |
58 | } |
59 | |
60 | template <typename ELFT> |
61 | void PrinterContext<ELFT>::printUnwindInformation() const { |
62 | const typename ELFT::Phdr *EHFramePhdr = nullptr; |
63 | |
64 | auto PHs = Obj->program_headers(); |
65 | if (Error E = PHs.takeError()) |
66 | reportError(toString(std::move(E))); |
67 | |
68 | for (const auto &Phdr : *PHs) { |
69 | if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) { |
70 | EHFramePhdr = &Phdr; |
71 | if (Phdr.p_memsz != Phdr.p_filesz) |
72 | reportError("p_memsz does not match p_filesz for GNU_EH_FRAME"); |
73 | break; |
74 | } |
75 | } |
76 | |
77 | if (EHFramePhdr) |
78 | printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr, |
79 | EHFramePhdr->p_memsz); |
80 | |
81 | auto Sections = Obj->sections(); |
82 | if (Error E = Sections.takeError()) |
83 | reportError(toString(std::move(E))); |
84 | |
85 | for (const auto &Shdr : *Sections) { |
86 | auto SectionName = Obj->getSectionName(&Shdr); |
87 | if (Error E = SectionName.takeError()) |
88 | reportError(toString(std::move(E))); |
89 | |
90 | if (*SectionName == ".eh_frame") |
91 | printEHFrame(&Shdr); |
92 | } |
93 | } |
94 | |
95 | template <typename ELFT> |
96 | void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset, |
97 | uint64_t EHFrameHdrAddress, |
98 | uint64_t EHFrameHdrSize) const { |
99 | ListScope L(W, "EH_FRAME Header"); |
100 | W.startLine() << format("Address: 0x%" PRIx64"l" "x" "\n", EHFrameHdrAddress); |
101 | W.startLine() << format("Offset: 0x%" PRIx64"l" "x" "\n", EHFrameHdrOffset); |
102 | W.startLine() << format("Size: 0x%" PRIx64"l" "x" "\n", EHFrameHdrSize); |
103 | |
104 | const auto *EHFrameHdrShdr = findSectionByAddress(Obj, EHFrameHdrAddress); |
105 | if (EHFrameHdrShdr) { |
106 | auto SectionName = Obj->getSectionName(EHFrameHdrShdr); |
107 | if (Error E = SectionName.takeError()) |
108 | reportError(toString(std::move(E))); |
109 | |
110 | W.printString("Corresponding Section", *SectionName); |
111 | } |
112 | |
113 | DataExtractor DE( |
114 | StringRef(reinterpret_cast<const char *>(Obj->base()) + EHFrameHdrOffset, |
115 | EHFrameHdrSize), |
116 | ELFT::TargetEndianness == support::endianness::little, |
117 | ELFT::Is64Bits ? 8 : 4); |
118 | |
119 | DictScope D(W, "Header"); |
120 | uint32_t Offset = 0; |
121 | |
122 | auto Version = DE.getU8(&Offset); |
123 | W.printNumber("version", Version); |
124 | if (Version != 1) |
125 | reportError("only version 1 of .eh_frame_hdr is supported"); |
126 | |
127 | uint64_t EHFramePtrEnc = DE.getU8(&Offset); |
128 | W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64"l" "x" "\n", EHFramePtrEnc); |
129 | if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4)) |
130 | reportError("unexpected encoding eh_frame_ptr_enc"); |
131 | |
132 | uint64_t FDECountEnc = DE.getU8(&Offset); |
133 | W.startLine() << format("fde_count_enc: 0x%" PRIx64"l" "x" "\n", FDECountEnc); |
134 | if (FDECountEnc != dwarf::DW_EH_PE_udata4) |
135 | reportError("unexpected encoding fde_count_enc"); |
136 | |
137 | uint64_t TableEnc = DE.getU8(&Offset); |
138 | W.startLine() << format("table_enc: 0x%" PRIx64"l" "x" "\n", TableEnc); |
139 | if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4)) |
140 | reportError("unexpected encoding table_enc"); |
141 | |
142 | auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4; |
143 | W.startLine() << format("eh_frame_ptr: 0x%" PRIx64"l" "x" "\n", EHFramePtr); |
144 | |
145 | auto FDECount = DE.getUnsigned(&Offset, 4); |
146 | W.printNumber("fde_count", FDECount); |
147 | |
148 | unsigned NumEntries = 0; |
149 | uint64_t PrevPC = 0; |
150 | while (Offset + 8 <= EHFrameHdrSize && NumEntries < FDECount) { |
151 | DictScope D(W, std::string("entry ") + std::to_string(NumEntries)); |
152 | |
153 | auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress; |
154 | W.startLine() << format("initial_location: 0x%" PRIx64"l" "x" "\n", InitialPC); |
155 | auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress; |
156 | W.startLine() << format("address: 0x%" PRIx64"l" "x" "\n", Address); |
157 | |
158 | if (InitialPC < PrevPC) |
159 | reportError("initial_location is out of order"); |
160 | |
161 | PrevPC = InitialPC; |
162 | ++NumEntries; |
163 | } |
164 | } |
165 | |
166 | template <typename ELFT> |
167 | void PrinterContext<ELFT>::printEHFrame( |
168 | const typename ELFT::Shdr *EHFrameShdr) const { |
169 | uint64_t Address = EHFrameShdr->sh_addr; |
170 | uint64_t ShOffset = EHFrameShdr->sh_offset; |
171 | W.startLine() << format(".eh_frame section at offset 0x%" PRIx64"l" "x" |
172 | " address 0x%" PRIx64"l" "x" ":\n", |
173 | ShOffset, Address); |
174 | W.indent(); |
175 | |
176 | auto Result = Obj->getSectionContents(EHFrameShdr); |
177 | if (Error E = Result.takeError()) |
178 | reportError(toString(std::move(E))); |
179 | |
180 | auto Contents = Result.get(); |
181 | DWARFDataExtractor DE( |
182 | StringRef(reinterpret_cast<const char *>(Contents.data()), |
183 | Contents.size()), |
184 | ELFT::TargetEndianness == support::endianness::little, |
185 | ELFT::Is64Bits ? 8 : 4); |
186 | DWARFDebugFrame EHFrame(/*IsEH=*/true, /*EHFrameAddress=*/Address); |
187 | EHFrame.parse(DE); |
188 | |
189 | for (const auto &Entry : EHFrame) { |
190 | if (const auto *CIE = dyn_cast<dwarf::CIE>(&Entry)) { |
191 | W.startLine() << format("[0x%" PRIx64"l" "x" "] CIE length=%" PRIu64"l" "u" "\n", |
192 | Address + CIE->getOffset(), |
193 | CIE->getLength()); |
194 | W.indent(); |
195 | |
196 | W.printNumber("version", CIE->getVersion()); |
197 | W.printString("augmentation", CIE->getAugmentationString()); |
198 | W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor()); |
199 | W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor()); |
200 | W.printNumber("return_address_register", CIE->getReturnAddressRegister()); |
201 | |
202 | W.getOStream() << "\n"; |
203 | W.startLine() << "Program:\n"; |
204 | W.indent(); |
205 | CIE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel()); |
206 | W.unindent(); |
207 | |
208 | W.unindent(); |
209 | W.getOStream() << "\n"; |
210 | |
211 | } else if (const auto *FDE = dyn_cast<dwarf::FDE>(&Entry)) { |
212 | W.startLine() << format("[0x%" PRIx64"l" "x" "] FDE length=%" PRIu64"l" "u" |
213 | " cie=[0x%" PRIx64"l" "x" "]\n", |
214 | Address + FDE->getOffset(), |
215 | FDE->getLength(), |
216 | Address + FDE->getLinkedCIE()->getOffset()); |
217 | W.indent(); |
218 | |
219 | W.startLine() << format("initial_location: 0x%" PRIx64"l" "x" "\n", |
220 | FDE->getInitialLocation()); |
221 | W.startLine() |
222 | << format("address_range: 0x%" PRIx64"l" "x" " (end : 0x%" PRIx64"l" "x" ")\n", |
223 | FDE->getAddressRange(), |
224 | FDE->getInitialLocation() + FDE->getAddressRange()); |
225 | |
226 | W.getOStream() << "\n"; |
227 | W.startLine() << "Program:\n"; |
228 | W.indent(); |
229 | FDE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel()); |
230 | W.unindent(); |
231 | |
232 | W.unindent(); |
233 | W.getOStream() << "\n"; |
234 | } else { |
235 | llvm_unreachable("unexpected DWARF frame kind")::llvm::llvm_unreachable_internal("unexpected DWARF frame kind" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-readobj/DwarfCFIEHPrinter.h" , 235); |
236 | } |
237 | } |
238 | |
239 | W.unindent(); |
240 | } |
241 | |
242 | } |
243 | } |
244 | |
245 | #endif |
1 | //===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file declares the ELFFile template class. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_OBJECT_ELF_H |
15 | #define LLVM_OBJECT_ELF_H |
16 | |
17 | #include "llvm/ADT/ArrayRef.h" |
18 | #include "llvm/ADT/SmallVector.h" |
19 | #include "llvm/ADT/StringRef.h" |
20 | #include "llvm/BinaryFormat/ELF.h" |
21 | #include "llvm/Object/ELFTypes.h" |
22 | #include "llvm/Object/Error.h" |
23 | #include "llvm/Support/Endian.h" |
24 | #include "llvm/Support/Error.h" |
25 | #include <cassert> |
26 | #include <cstddef> |
27 | #include <cstdint> |
28 | #include <limits> |
29 | #include <utility> |
30 | |
31 | namespace llvm { |
32 | namespace object { |
33 | |
34 | StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); |
35 | uint32_t getELFRelrRelocationType(uint32_t Machine); |
36 | StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type); |
37 | |
38 | // Subclasses of ELFFile may need this for template instantiation |
39 | inline std::pair<unsigned char, unsigned char> |
40 | getElfArchType(StringRef Object) { |
41 | if (Object.size() < ELF::EI_NIDENT) |
42 | return std::make_pair((uint8_t)ELF::ELFCLASSNONE, |
43 | (uint8_t)ELF::ELFDATANONE); |
44 | return std::make_pair((uint8_t)Object[ELF::EI_CLASS], |
45 | (uint8_t)Object[ELF::EI_DATA]); |
46 | } |
47 | |
48 | static inline Error createError(StringRef Err) { |
49 | return make_error<StringError>(Err, object_error::parse_failed); |
50 | } |
51 | |
52 | template <class ELFT> |
53 | class ELFFile { |
54 | public: |
55 | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)using Elf_Addr = typename ELFT::Addr; using Elf_Off = typename ELFT::Off; using Elf_Half = typename ELFT::Half; using Elf_Word = typename ELFT::Word; using Elf_Sword = typename ELFT::Sword ; using Elf_Xword = typename ELFT::Xword; using Elf_Sxword = typename ELFT::Sxword; |
56 | using uintX_t = typename ELFT::uint; |
57 | using Elf_Ehdr = typename ELFT::Ehdr; |
58 | using Elf_Shdr = typename ELFT::Shdr; |
59 | using Elf_Sym = typename ELFT::Sym; |
60 | using Elf_Dyn = typename ELFT::Dyn; |
61 | using Elf_Phdr = typename ELFT::Phdr; |
62 | using Elf_Rel = typename ELFT::Rel; |
63 | using Elf_Rela = typename ELFT::Rela; |
64 | using Elf_Relr = typename ELFT::Relr; |
65 | using Elf_Verdef = typename ELFT::Verdef; |
66 | using Elf_Verdaux = typename ELFT::Verdaux; |
67 | using Elf_Verneed = typename ELFT::Verneed; |
68 | using Elf_Vernaux = typename ELFT::Vernaux; |
69 | using Elf_Versym = typename ELFT::Versym; |
70 | using Elf_Hash = typename ELFT::Hash; |
71 | using Elf_GnuHash = typename ELFT::GnuHash; |
72 | using Elf_Nhdr = typename ELFT::Nhdr; |
73 | using Elf_Note = typename ELFT::Note; |
74 | using Elf_Note_Iterator = typename ELFT::NoteIterator; |
75 | using Elf_Dyn_Range = typename ELFT::DynRange; |
76 | using Elf_Shdr_Range = typename ELFT::ShdrRange; |
77 | using Elf_Sym_Range = typename ELFT::SymRange; |
78 | using Elf_Rel_Range = typename ELFT::RelRange; |
79 | using Elf_Rela_Range = typename ELFT::RelaRange; |
80 | using Elf_Relr_Range = typename ELFT::RelrRange; |
81 | using Elf_Phdr_Range = typename ELFT::PhdrRange; |
82 | |
83 | const uint8_t *base() const { |
84 | return reinterpret_cast<const uint8_t *>(Buf.data()); |
85 | } |
86 | |
87 | size_t getBufSize() const { return Buf.size(); } |
88 | |
89 | private: |
90 | StringRef Buf; |
91 | |
92 | ELFFile(StringRef Object); |
93 | |
94 | public: |
95 | const Elf_Ehdr *getHeader() const { |
96 | return reinterpret_cast<const Elf_Ehdr *>(base()); |
97 | } |
98 | |
99 | template <typename T> |
100 | Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const; |
101 | template <typename T> |
102 | Expected<const T *> getEntry(const Elf_Shdr *Section, uint32_t Entry) const; |
103 | |
104 | Expected<StringRef> getStringTable(const Elf_Shdr *Section) const; |
105 | Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; |
106 | Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section, |
107 | Elf_Shdr_Range Sections) const; |
108 | |
109 | Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; |
110 | Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, |
111 | Elf_Shdr_Range Sections) const; |
112 | |
113 | StringRef getRelocationTypeName(uint32_t Type) const; |
114 | void getRelocationTypeName(uint32_t Type, |
115 | SmallVectorImpl<char> &Result) const; |
116 | uint32_t getRelrRelocationType() const; |
117 | |
118 | const char *getDynamicTagAsString(unsigned Arch, uint64_t Type) const; |
119 | const char *getDynamicTagAsString(uint64_t Type) const; |
120 | |
121 | /// Get the symbol for a given relocation. |
122 | Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel, |
123 | const Elf_Shdr *SymTab) const; |
124 | |
125 | static Expected<ELFFile> create(StringRef Object); |
126 | |
127 | bool isMipsELF64() const { |
128 | return getHeader()->e_machine == ELF::EM_MIPS && |
129 | getHeader()->getFileClass() == ELF::ELFCLASS64; |
130 | } |
131 | |
132 | bool isMips64EL() const { |
133 | return isMipsELF64() && |
134 | getHeader()->getDataEncoding() == ELF::ELFDATA2LSB; |
135 | } |
136 | |
137 | Expected<Elf_Shdr_Range> sections() const; |
138 | |
139 | Expected<Elf_Dyn_Range> dynamicEntries() const; |
140 | |
141 | Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const; |
142 | |
143 | Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { |
144 | if (!Sec) |
145 | return makeArrayRef<Elf_Sym>(nullptr, nullptr); |
146 | return getSectionContentsAsArray<Elf_Sym>(Sec); |
147 | } |
148 | |
149 | Expected<Elf_Rela_Range> relas(const Elf_Shdr *Sec) const { |
150 | return getSectionContentsAsArray<Elf_Rela>(Sec); |
151 | } |
152 | |
153 | Expected<Elf_Rel_Range> rels(const Elf_Shdr *Sec) const { |
154 | return getSectionContentsAsArray<Elf_Rel>(Sec); |
155 | } |
156 | |
157 | Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const { |
158 | return getSectionContentsAsArray<Elf_Relr>(Sec); |
159 | } |
160 | |
161 | Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const; |
162 | |
163 | Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const; |
164 | |
165 | /// Iterate over program header table. |
166 | Expected<Elf_Phdr_Range> program_headers() const { |
167 | if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr)) |
168 | return createError("invalid e_phentsize"); |
169 | if (getHeader()->e_phoff + |
170 | (getHeader()->e_phnum * getHeader()->e_phentsize) > |
171 | getBufSize()) |
172 | return createError("program headers longer than binary"); |
173 | auto *Begin = |
174 | reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff); |
175 | return makeArrayRef(Begin, Begin + getHeader()->e_phnum); |
176 | } |
177 | |
178 | /// Get an iterator over notes in a program header. |
179 | /// |
180 | /// The program header must be of type \c PT_NOTE. |
181 | /// |
182 | /// \param Phdr the program header to iterate over. |
183 | /// \param Err [out] an error to support fallible iteration, which should |
184 | /// be checked after iteration ends. |
185 | Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const { |
186 | if (Phdr.p_type != ELF::PT_NOTE) { |
187 | Err = createError("attempt to iterate notes of non-note program header"); |
188 | return Elf_Note_Iterator(Err); |
189 | } |
190 | if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) { |
191 | Err = createError("invalid program header offset/size"); |
192 | return Elf_Note_Iterator(Err); |
193 | } |
194 | return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err); |
195 | } |
196 | |
197 | /// Get an iterator over notes in a section. |
198 | /// |
199 | /// The section must be of type \c SHT_NOTE. |
200 | /// |
201 | /// \param Shdr the section to iterate over. |
202 | /// \param Err [out] an error to support fallible iteration, which should |
203 | /// be checked after iteration ends. |
204 | Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const { |
205 | if (Shdr.sh_type != ELF::SHT_NOTE) { |
206 | Err = createError("attempt to iterate notes of non-note section"); |
207 | return Elf_Note_Iterator(Err); |
208 | } |
209 | if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) { |
210 | Err = createError("invalid section offset/size"); |
211 | return Elf_Note_Iterator(Err); |
212 | } |
213 | return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err); |
214 | } |
215 | |
216 | /// Get the end iterator for notes. |
217 | Elf_Note_Iterator notes_end() const { |
218 | return Elf_Note_Iterator(); |
219 | } |
220 | |
221 | /// Get an iterator range over notes of a program header. |
222 | /// |
223 | /// The program header must be of type \c PT_NOTE. |
224 | /// |
225 | /// \param Phdr the program header to iterate over. |
226 | /// \param Err [out] an error to support fallible iteration, which should |
227 | /// be checked after iteration ends. |
228 | iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr, |
229 | Error &Err) const { |
230 | return make_range(notes_begin(Phdr, Err), notes_end()); |
231 | } |
232 | |
233 | /// Get an iterator range over notes of a section. |
234 | /// |
235 | /// The section must be of type \c SHT_NOTE. |
236 | /// |
237 | /// \param Shdr the section to iterate over. |
238 | /// \param Err [out] an error to support fallible iteration, which should |
239 | /// be checked after iteration ends. |
240 | iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr, |
241 | Error &Err) const { |
242 | return make_range(notes_begin(Shdr, Err), notes_end()); |
243 | } |
244 | |
245 | Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const; |
246 | Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, |
247 | ArrayRef<Elf_Word> ShndxTable) const; |
248 | Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, |
249 | const Elf_Shdr *SymTab, |
250 | ArrayRef<Elf_Word> ShndxTable) const; |
251 | Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym, |
252 | Elf_Sym_Range Symtab, |
253 | ArrayRef<Elf_Word> ShndxTable) const; |
254 | Expected<const Elf_Shdr *> getSection(uint32_t Index) const; |
255 | Expected<const Elf_Shdr *> getSection(const StringRef SectionName) const; |
256 | |
257 | Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, |
258 | uint32_t Index) const; |
259 | |
260 | Expected<StringRef> getSectionName(const Elf_Shdr *Section) const; |
261 | Expected<StringRef> getSectionName(const Elf_Shdr *Section, |
262 | StringRef DotShstrtab) const; |
263 | template <typename T> |
264 | Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const; |
265 | Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const; |
266 | }; |
267 | |
268 | using ELF32LEFile = ELFFile<ELF32LE>; |
269 | using ELF64LEFile = ELFFile<ELF64LE>; |
270 | using ELF32BEFile = ELFFile<ELF32BE>; |
271 | using ELF64BEFile = ELFFile<ELF64BE>; |
272 | |
273 | template <class ELFT> |
274 | inline Expected<const typename ELFT::Shdr *> |
275 | getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { |
276 | if (Index >= Sections.size()) |
277 | return createError("invalid section index"); |
278 | return &Sections[Index]; |
279 | } |
280 | |
281 | template <class ELFT> |
282 | inline Expected<uint32_t> |
283 | getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym, |
284 | const typename ELFT::Sym *FirstSym, |
285 | ArrayRef<typename ELFT::Word> ShndxTable) { |
286 | assert(Sym->st_shndx == ELF::SHN_XINDEX)((Sym->st_shndx == ELF::SHN_XINDEX) ? static_cast<void> (0) : __assert_fail ("Sym->st_shndx == ELF::SHN_XINDEX", "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Object/ELF.h" , 286, __PRETTY_FUNCTION__)); |
287 | unsigned Index = Sym - FirstSym; |
288 | if (Index >= ShndxTable.size()) |
289 | return createError("index past the end of the symbol table"); |
290 | |
291 | // The size of the table was checked in getSHNDXTable. |
292 | return ShndxTable[Index]; |
293 | } |
294 | |
295 | template <class ELFT> |
296 | Expected<uint32_t> |
297 | ELFFile<ELFT>::getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, |
298 | ArrayRef<Elf_Word> ShndxTable) const { |
299 | uint32_t Index = Sym->st_shndx; |
300 | if (Index == ELF::SHN_XINDEX) { |
301 | auto ErrorOrIndex = getExtendedSymbolTableIndex<ELFT>( |
302 | Sym, Syms.begin(), ShndxTable); |
303 | if (!ErrorOrIndex) |
304 | return ErrorOrIndex.takeError(); |
305 | return *ErrorOrIndex; |
306 | } |
307 | if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) |
308 | return 0; |
309 | return Index; |
310 | } |
311 | |
312 | template <class ELFT> |
313 | Expected<const typename ELFT::Shdr *> |
314 | ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, |
315 | ArrayRef<Elf_Word> ShndxTable) const { |
316 | auto SymsOrErr = symbols(SymTab); |
317 | if (!SymsOrErr) |
318 | return SymsOrErr.takeError(); |
319 | return getSection(Sym, *SymsOrErr, ShndxTable); |
320 | } |
321 | |
322 | template <class ELFT> |
323 | Expected<const typename ELFT::Shdr *> |
324 | ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols, |
325 | ArrayRef<Elf_Word> ShndxTable) const { |
326 | auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable); |
327 | if (!IndexOrErr) |
328 | return IndexOrErr.takeError(); |
329 | uint32_t Index = *IndexOrErr; |
330 | if (Index == 0) |
331 | return nullptr; |
332 | return getSection(Index); |
333 | } |
334 | |
335 | template <class ELFT> |
336 | inline Expected<const typename ELFT::Sym *> |
337 | getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) { |
338 | if (Index >= Symbols.size()) |
339 | return createError("invalid symbol index"); |
340 | return &Symbols[Index]; |
341 | } |
342 | |
343 | template <class ELFT> |
344 | Expected<const typename ELFT::Sym *> |
345 | ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { |
346 | auto SymtabOrErr = symbols(Sec); |
347 | if (!SymtabOrErr) |
348 | return SymtabOrErr.takeError(); |
349 | return object::getSymbol<ELFT>(*SymtabOrErr, Index); |
350 | } |
351 | |
352 | template <class ELFT> |
353 | template <typename T> |
354 | Expected<ArrayRef<T>> |
355 | ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const { |
356 | if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1) |
357 | return createError("invalid sh_entsize"); |
358 | |
359 | uintX_t Offset = Sec->sh_offset; |
360 | uintX_t Size = Sec->sh_size; |
361 | |
362 | if (Size % sizeof(T)) |
363 | return createError("size is not a multiple of sh_entsize"); |
364 | if ((std::numeric_limits<uintX_t>::max() - Offset < Size) || |
365 | Offset + Size > Buf.size()) |
366 | return createError("invalid section offset"); |
367 | |
368 | if (Offset % alignof(T)) |
369 | return createError("unaligned data"); |
370 | |
371 | const T *Start = reinterpret_cast<const T *>(base() + Offset); |
372 | return makeArrayRef(Start, Size / sizeof(T)); |
373 | } |
374 | |
375 | template <class ELFT> |
376 | Expected<ArrayRef<uint8_t>> |
377 | ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { |
378 | return getSectionContentsAsArray<uint8_t>(Sec); |
379 | } |
380 | |
381 | template <class ELFT> |
382 | StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { |
383 | return getELFRelocationTypeName(getHeader()->e_machine, Type); |
384 | } |
385 | |
386 | template <class ELFT> |
387 | void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, |
388 | SmallVectorImpl<char> &Result) const { |
389 | if (!isMipsELF64()) { |
390 | StringRef Name = getRelocationTypeName(Type); |
391 | Result.append(Name.begin(), Name.end()); |
392 | } else { |
393 | // The Mips N64 ABI allows up to three operations to be specified per |
394 | // relocation record. Unfortunately there's no easy way to test for the |
395 | // presence of N64 ELFs as they have no special flag that identifies them |
396 | // as being N64. We can safely assume at the moment that all Mips |
397 | // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough |
398 | // information to disambiguate between old vs new ABIs. |
399 | uint8_t Type1 = (Type >> 0) & 0xFF; |
400 | uint8_t Type2 = (Type >> 8) & 0xFF; |
401 | uint8_t Type3 = (Type >> 16) & 0xFF; |
402 | |
403 | // Concat all three relocation type names. |
404 | StringRef Name = getRelocationTypeName(Type1); |
405 | Result.append(Name.begin(), Name.end()); |
406 | |
407 | Name = getRelocationTypeName(Type2); |
408 | Result.append(1, '/'); |
409 | Result.append(Name.begin(), Name.end()); |
410 | |
411 | Name = getRelocationTypeName(Type3); |
412 | Result.append(1, '/'); |
413 | Result.append(Name.begin(), Name.end()); |
414 | } |
415 | } |
416 | |
417 | template <class ELFT> |
418 | uint32_t ELFFile<ELFT>::getRelrRelocationType() const { |
419 | return getELFRelrRelocationType(getHeader()->e_machine); |
420 | } |
421 | |
422 | template <class ELFT> |
423 | Expected<const typename ELFT::Sym *> |
424 | ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel, |
425 | const Elf_Shdr *SymTab) const { |
426 | uint32_t Index = Rel->getSymbol(isMips64EL()); |
427 | if (Index == 0) |
428 | return nullptr; |
429 | return getEntry<Elf_Sym>(SymTab, Index); |
430 | } |
431 | |
432 | template <class ELFT> |
433 | Expected<StringRef> |
434 | ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const { |
435 | uint32_t Index = getHeader()->e_shstrndx; |
436 | if (Index == ELF::SHN_XINDEX) |
437 | Index = Sections[0].sh_link; |
438 | |
439 | if (!Index) // no section string table. |
440 | return ""; |
441 | if (Index >= Sections.size()) |
442 | return createError("invalid section index"); |
443 | return getStringTable(&Sections[Index]); |
444 | } |
445 | |
446 | template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} |
447 | |
448 | template <class ELFT> |
449 | Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { |
450 | if (sizeof(Elf_Ehdr) > Object.size()) |
451 | return createError("Invalid buffer"); |
452 | return ELFFile(Object); |
453 | } |
454 | |
455 | template <class ELFT> |
456 | Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { |
457 | const uintX_t SectionTableOffset = getHeader()->e_shoff; |
458 | if (SectionTableOffset == 0) |
459 | return ArrayRef<Elf_Shdr>(); |
460 | |
461 | if (getHeader()->e_shentsize != sizeof(Elf_Shdr)) |
462 | return createError( |
463 | "invalid section header entry size (e_shentsize) in ELF header"); |
464 | |
465 | const uint64_t FileSize = Buf.size(); |
466 | |
467 | if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) |
468 | return createError("section header table goes past the end of the file"); |
469 | |
470 | // Invalid address alignment of section headers |
471 | if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) |
472 | return createError("invalid alignment of section headers"); |
473 | |
474 | const Elf_Shdr *First = |
475 | reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); |
476 | |
477 | uintX_t NumSections = getHeader()->e_shnum; |
478 | if (NumSections == 0) |
479 | NumSections = First->sh_size; |
480 | |
481 | if (NumSections > UINT64_MAX(18446744073709551615UL) / sizeof(Elf_Shdr)) |
482 | return createError("section table goes past the end of file"); |
483 | |
484 | const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); |
485 | |
486 | // Section table goes past end of file! |
487 | if (SectionTableOffset + SectionTableSize > FileSize) |
488 | return createError("section table goes past the end of file"); |
489 | |
490 | return makeArrayRef(First, NumSections); |
491 | } |
492 | |
493 | template <class ELFT> |
494 | template <typename T> |
495 | Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section, |
496 | uint32_t Entry) const { |
497 | auto SecOrErr = getSection(Section); |
498 | if (!SecOrErr) |
499 | return SecOrErr.takeError(); |
500 | return getEntry<T>(*SecOrErr, Entry); |
501 | } |
502 | |
503 | template <class ELFT> |
504 | template <typename T> |
505 | Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, |
506 | uint32_t Entry) const { |
507 | if (sizeof(T) != Section->sh_entsize) |
508 | return createError("invalid sh_entsize"); |
509 | size_t Pos = Section->sh_offset + Entry * sizeof(T); |
510 | if (Pos + sizeof(T) > Buf.size()) |
511 | return createError("invalid section offset"); |
512 | return reinterpret_cast<const T *>(base() + Pos); |
513 | } |
514 | |
515 | template <class ELFT> |
516 | Expected<const typename ELFT::Shdr *> |
517 | ELFFile<ELFT>::getSection(uint32_t Index) const { |
518 | auto TableOrErr = sections(); |
519 | if (!TableOrErr) |
520 | return TableOrErr.takeError(); |
521 | return object::getSection<ELFT>(*TableOrErr, Index); |
522 | } |
523 | |
524 | template <class ELFT> |
525 | Expected<const typename ELFT::Shdr *> |
526 | ELFFile<ELFT>::getSection(const StringRef SectionName) const { |
527 | auto TableOrErr = sections(); |
528 | if (!TableOrErr) |
529 | return TableOrErr.takeError(); |
530 | for (auto &Sec : *TableOrErr) { |
531 | auto SecNameOrErr = getSectionName(&Sec); |
532 | if (!SecNameOrErr) |
533 | return SecNameOrErr.takeError(); |
534 | if (*SecNameOrErr == SectionName) |
535 | return &Sec; |
536 | } |
537 | return createError("invalid section name"); |
538 | } |
539 | |
540 | template <class ELFT> |
541 | Expected<StringRef> |
542 | ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { |
543 | if (Section->sh_type != ELF::SHT_STRTAB) |
544 | return createError("invalid sh_type for string table, expected SHT_STRTAB"); |
545 | auto V = getSectionContentsAsArray<char>(Section); |
546 | if (!V) |
547 | return V.takeError(); |
548 | ArrayRef<char> Data = *V; |
549 | if (Data.empty()) |
550 | return createError("empty string table"); |
551 | if (Data.back() != '\0') |
552 | return createError("string table non-null terminated"); |
553 | return StringRef(Data.begin(), Data.size()); |
554 | } |
555 | |
556 | template <class ELFT> |
557 | Expected<ArrayRef<typename ELFT::Word>> |
558 | ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { |
559 | auto SectionsOrErr = sections(); |
560 | if (!SectionsOrErr) |
561 | return SectionsOrErr.takeError(); |
562 | return getSHNDXTable(Section, *SectionsOrErr); |
563 | } |
564 | |
565 | template <class ELFT> |
566 | Expected<ArrayRef<typename ELFT::Word>> |
567 | ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, |
568 | Elf_Shdr_Range Sections) const { |
569 | assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX)((Section.sh_type == ELF::SHT_SYMTAB_SHNDX) ? static_cast< void> (0) : __assert_fail ("Section.sh_type == ELF::SHT_SYMTAB_SHNDX" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Object/ELF.h" , 569, __PRETTY_FUNCTION__)); |
570 | auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section); |
571 | if (!VOrErr) |
572 | return VOrErr.takeError(); |
573 | ArrayRef<Elf_Word> V = *VOrErr; |
574 | auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link); |
575 | if (!SymTableOrErr) |
576 | return SymTableOrErr.takeError(); |
577 | const Elf_Shdr &SymTable = **SymTableOrErr; |
578 | if (SymTable.sh_type != ELF::SHT_SYMTAB && |
579 | SymTable.sh_type != ELF::SHT_DYNSYM) |
580 | return createError("invalid sh_type"); |
581 | if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym))) |
582 | return createError("invalid section contents size"); |
583 | return V; |
584 | } |
585 | |
586 | template <class ELFT> |
587 | Expected<StringRef> |
588 | ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { |
589 | auto SectionsOrErr = sections(); |
590 | if (!SectionsOrErr) |
591 | return SectionsOrErr.takeError(); |
592 | return getStringTableForSymtab(Sec, *SectionsOrErr); |
593 | } |
594 | |
595 | template <class ELFT> |
596 | Expected<StringRef> |
597 | ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, |
598 | Elf_Shdr_Range Sections) const { |
599 | |
600 | if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) |
601 | return createError( |
602 | "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM"); |
603 | auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link); |
604 | if (!SectionOrErr) |
605 | return SectionOrErr.takeError(); |
606 | return getStringTable(*SectionOrErr); |
607 | } |
608 | |
609 | template <class ELFT> |
610 | Expected<StringRef> |
611 | ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const { |
612 | auto SectionsOrErr = sections(); |
613 | if (!SectionsOrErr) |
614 | return SectionsOrErr.takeError(); |
615 | auto Table = getSectionStringTable(*SectionsOrErr); |
616 | if (!Table) |
617 | return Table.takeError(); |
618 | return getSectionName(Section, *Table); |
619 | } |
620 | |
621 | template <class ELFT> |
622 | Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section, |
623 | StringRef DotShstrtab) const { |
624 | uint32_t Offset = Section->sh_name; |
625 | if (Offset == 0) |
626 | return StringRef(); |
627 | if (Offset >= DotShstrtab.size()) |
628 | return createError("invalid string offset"); |
629 | return StringRef(DotShstrtab.data() + Offset); |
630 | } |
631 | |
632 | /// This function returns the hash value for a symbol in the .dynsym section |
633 | /// Name of the API remains consistent as specified in the libelf |
634 | /// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash |
635 | inline unsigned hashSysV(StringRef SymbolName) { |
636 | unsigned h = 0, g; |
637 | for (char C : SymbolName) { |
638 | h = (h << 4) + C; |
639 | g = h & 0xf0000000L; |
640 | if (g != 0) |
641 | h ^= g >> 24; |
642 | h &= ~g; |
643 | } |
644 | return h; |
645 | } |
646 | |
647 | } // end namespace object |
648 | } // end namespace llvm |
649 | |
650 | #endif // LLVM_OBJECT_ELF_H |
1 | //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This file defines an API used to report recoverable errors. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #ifndef LLVM_SUPPORT_ERROR_H | |||
15 | #define LLVM_SUPPORT_ERROR_H | |||
16 | ||||
17 | #include "llvm-c/Error.h" | |||
18 | #include "llvm/ADT/STLExtras.h" | |||
19 | #include "llvm/ADT/SmallVector.h" | |||
20 | #include "llvm/ADT/StringExtras.h" | |||
21 | #include "llvm/ADT/Twine.h" | |||
22 | #include "llvm/Config/abi-breaking.h" | |||
23 | #include "llvm/Support/AlignOf.h" | |||
24 | #include "llvm/Support/Compiler.h" | |||
25 | #include "llvm/Support/Debug.h" | |||
26 | #include "llvm/Support/ErrorHandling.h" | |||
27 | #include "llvm/Support/ErrorOr.h" | |||
28 | #include "llvm/Support/Format.h" | |||
29 | #include "llvm/Support/raw_ostream.h" | |||
30 | #include <algorithm> | |||
31 | #include <cassert> | |||
32 | #include <cstdint> | |||
33 | #include <cstdlib> | |||
34 | #include <functional> | |||
35 | #include <memory> | |||
36 | #include <new> | |||
37 | #include <string> | |||
38 | #include <system_error> | |||
39 | #include <type_traits> | |||
40 | #include <utility> | |||
41 | #include <vector> | |||
42 | ||||
43 | namespace llvm { | |||
44 | ||||
45 | class ErrorSuccess; | |||
46 | ||||
47 | /// Base class for error info classes. Do not extend this directly: Extend | |||
48 | /// the ErrorInfo template subclass instead. | |||
49 | class ErrorInfoBase { | |||
50 | public: | |||
51 | virtual ~ErrorInfoBase() = default; | |||
52 | ||||
53 | /// Print an error message to an output stream. | |||
54 | virtual void log(raw_ostream &OS) const = 0; | |||
55 | ||||
56 | /// Return the error message as a string. | |||
57 | virtual std::string message() const { | |||
58 | std::string Msg; | |||
59 | raw_string_ostream OS(Msg); | |||
60 | log(OS); | |||
61 | return OS.str(); | |||
62 | } | |||
63 | ||||
64 | /// Convert this error to a std::error_code. | |||
65 | /// | |||
66 | /// This is a temporary crutch to enable interaction with code still | |||
67 | /// using std::error_code. It will be removed in the future. | |||
68 | virtual std::error_code convertToErrorCode() const = 0; | |||
69 | ||||
70 | // Returns the class ID for this type. | |||
71 | static const void *classID() { return &ID; } | |||
72 | ||||
73 | // Returns the class ID for the dynamic type of this ErrorInfoBase instance. | |||
74 | virtual const void *dynamicClassID() const = 0; | |||
75 | ||||
76 | // Check whether this instance is a subclass of the class identified by | |||
77 | // ClassID. | |||
78 | virtual bool isA(const void *const ClassID) const { | |||
79 | return ClassID == classID(); | |||
80 | } | |||
81 | ||||
82 | // Check whether this instance is a subclass of ErrorInfoT. | |||
83 | template <typename ErrorInfoT> bool isA() const { | |||
84 | return isA(ErrorInfoT::classID()); | |||
85 | } | |||
86 | ||||
87 | private: | |||
88 | virtual void anchor(); | |||
89 | ||||
90 | static char ID; | |||
91 | }; | |||
92 | ||||
93 | /// Lightweight error class with error context and mandatory checking. | |||
94 | /// | |||
95 | /// Instances of this class wrap a ErrorInfoBase pointer. Failure states | |||
96 | /// are represented by setting the pointer to a ErrorInfoBase subclass | |||
97 | /// instance containing information describing the failure. Success is | |||
98 | /// represented by a null pointer value. | |||
99 | /// | |||
100 | /// Instances of Error also contains a 'Checked' flag, which must be set | |||
101 | /// before the destructor is called, otherwise the destructor will trigger a | |||
102 | /// runtime error. This enforces at runtime the requirement that all Error | |||
103 | /// instances be checked or returned to the caller. | |||
104 | /// | |||
105 | /// There are two ways to set the checked flag, depending on what state the | |||
106 | /// Error instance is in. For Error instances indicating success, it | |||
107 | /// is sufficient to invoke the boolean conversion operator. E.g.: | |||
108 | /// | |||
109 | /// @code{.cpp} | |||
110 | /// Error foo(<...>); | |||
111 | /// | |||
112 | /// if (auto E = foo(<...>)) | |||
113 | /// return E; // <- Return E if it is in the error state. | |||
114 | /// // We have verified that E was in the success state. It can now be safely | |||
115 | /// // destroyed. | |||
116 | /// @endcode | |||
117 | /// | |||
118 | /// A success value *can not* be dropped. For example, just calling 'foo(<...>)' | |||
119 | /// without testing the return value will raise a runtime error, even if foo | |||
120 | /// returns success. | |||
121 | /// | |||
122 | /// For Error instances representing failure, you must use either the | |||
123 | /// handleErrors or handleAllErrors function with a typed handler. E.g.: | |||
124 | /// | |||
125 | /// @code{.cpp} | |||
126 | /// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { | |||
127 | /// // Custom error info. | |||
128 | /// }; | |||
129 | /// | |||
130 | /// Error foo(<...>) { return make_error<MyErrorInfo>(...); } | |||
131 | /// | |||
132 | /// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. | |||
133 | /// auto NewE = | |||
134 | /// handleErrors(E, | |||
135 | /// [](const MyErrorInfo &M) { | |||
136 | /// // Deal with the error. | |||
137 | /// }, | |||
138 | /// [](std::unique_ptr<OtherError> M) -> Error { | |||
139 | /// if (canHandle(*M)) { | |||
140 | /// // handle error. | |||
141 | /// return Error::success(); | |||
142 | /// } | |||
143 | /// // Couldn't handle this error instance. Pass it up the stack. | |||
144 | /// return Error(std::move(M)); | |||
145 | /// ); | |||
146 | /// // Note - we must check or return NewE in case any of the handlers | |||
147 | /// // returned a new error. | |||
148 | /// @endcode | |||
149 | /// | |||
150 | /// The handleAllErrors function is identical to handleErrors, except | |||
151 | /// that it has a void return type, and requires all errors to be handled and | |||
152 | /// no new errors be returned. It prevents errors (assuming they can all be | |||
153 | /// handled) from having to be bubbled all the way to the top-level. | |||
154 | /// | |||
155 | /// *All* Error instances must be checked before destruction, even if | |||
156 | /// they're moved-assigned or constructed from Success values that have already | |||
157 | /// been checked. This enforces checking through all levels of the call stack. | |||
158 | class LLVM_NODISCARD[[clang::warn_unused_result]] Error { | |||
159 | // Both ErrorList and FileError need to be able to yank ErrorInfoBase | |||
160 | // pointers out of this class to add to the error list. | |||
161 | friend class ErrorList; | |||
162 | friend class FileError; | |||
163 | ||||
164 | // handleErrors needs to be able to set the Checked flag. | |||
165 | template <typename... HandlerTs> | |||
166 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); | |||
167 | ||||
168 | // Expected<T> needs to be able to steal the payload when constructed from an | |||
169 | // error. | |||
170 | template <typename T> friend class Expected; | |||
171 | ||||
172 | // wrap needs to be able to steal the payload. | |||
173 | friend LLVMErrorRef wrap(Error); | |||
174 | ||||
175 | protected: | |||
176 | /// Create a success value. Prefer using 'Error::success()' for readability | |||
177 | Error() { | |||
178 | setPtr(nullptr); | |||
179 | setChecked(false); | |||
180 | } | |||
181 | ||||
182 | public: | |||
183 | /// Create a success value. | |||
184 | static ErrorSuccess success(); | |||
185 | ||||
186 | // Errors are not copy-constructable. | |||
187 | Error(const Error &Other) = delete; | |||
188 | ||||
189 | /// Move-construct an error value. The newly constructed error is considered | |||
190 | /// unchecked, even if the source error had been checked. The original error | |||
191 | /// becomes a checked Success value, regardless of its original state. | |||
192 | Error(Error &&Other) { | |||
193 | setChecked(true); | |||
194 | *this = std::move(Other); | |||
195 | } | |||
196 | ||||
197 | /// Create an error value. Prefer using the 'make_error' function, but | |||
198 | /// this constructor can be useful when "re-throwing" errors from handlers. | |||
199 | Error(std::unique_ptr<ErrorInfoBase> Payload) { | |||
200 | setPtr(Payload.release()); | |||
201 | setChecked(false); | |||
| ||||
202 | } | |||
203 | ||||
204 | // Errors are not copy-assignable. | |||
205 | Error &operator=(const Error &Other) = delete; | |||
206 | ||||
207 | /// Move-assign an error value. The current error must represent success, you | |||
208 | /// you cannot overwrite an unhandled error. The current error is then | |||
209 | /// considered unchecked. The source error becomes a checked success value, | |||
210 | /// regardless of its original state. | |||
211 | Error &operator=(Error &&Other) { | |||
212 | // Don't allow overwriting of unchecked values. | |||
213 | assertIsChecked(); | |||
214 | setPtr(Other.getPtr()); | |||
215 | ||||
216 | // This Error is unchecked, even if the source error was checked. | |||
217 | setChecked(false); | |||
218 | ||||
219 | // Null out Other's payload and set its checked bit. | |||
220 | Other.setPtr(nullptr); | |||
221 | Other.setChecked(true); | |||
222 | ||||
223 | return *this; | |||
224 | } | |||
225 | ||||
226 | /// Destroy a Error. Fails with a call to abort() if the error is | |||
227 | /// unchecked. | |||
228 | ~Error() { | |||
229 | assertIsChecked(); | |||
230 | delete getPtr(); | |||
231 | } | |||
232 | ||||
233 | /// Bool conversion. Returns true if this Error is in a failure state, | |||
234 | /// and false if it is in an accept state. If the error is in a Success state | |||
235 | /// it will be considered checked. | |||
236 | explicit operator bool() { | |||
237 | setChecked(getPtr() == nullptr); | |||
238 | return getPtr() != nullptr; | |||
239 | } | |||
240 | ||||
241 | /// Check whether one error is a subclass of another. | |||
242 | template <typename ErrT> bool isA() const { | |||
243 | return getPtr() && getPtr()->isA(ErrT::classID()); | |||
244 | } | |||
245 | ||||
246 | /// Returns the dynamic class id of this error, or null if this is a success | |||
247 | /// value. | |||
248 | const void* dynamicClassID() const { | |||
249 | if (!getPtr()) | |||
250 | return nullptr; | |||
251 | return getPtr()->dynamicClassID(); | |||
252 | } | |||
253 | ||||
254 | private: | |||
255 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
256 | // assertIsChecked() happens very frequently, but under normal circumstances | |||
257 | // is supposed to be a no-op. So we want it to be inlined, but having a bunch | |||
258 | // of debug prints can cause the function to be too large for inlining. So | |||
259 | // it's important that we define this function out of line so that it can't be | |||
260 | // inlined. | |||
261 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) | |||
262 | void fatalUncheckedError() const; | |||
263 | #endif | |||
264 | ||||
265 | void assertIsChecked() { | |||
266 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
267 | if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false)) | |||
268 | fatalUncheckedError(); | |||
269 | #endif | |||
270 | } | |||
271 | ||||
272 | ErrorInfoBase *getPtr() const { | |||
273 | return reinterpret_cast<ErrorInfoBase*>( | |||
274 | reinterpret_cast<uintptr_t>(Payload) & | |||
275 | ~static_cast<uintptr_t>(0x1)); | |||
276 | } | |||
277 | ||||
278 | void setPtr(ErrorInfoBase *EI) { | |||
279 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
280 | Payload = reinterpret_cast<ErrorInfoBase*>( | |||
281 | (reinterpret_cast<uintptr_t>(EI) & | |||
282 | ~static_cast<uintptr_t>(0x1)) | | |||
283 | (reinterpret_cast<uintptr_t>(Payload) & 0x1)); | |||
284 | #else | |||
285 | Payload = EI; | |||
286 | #endif | |||
287 | } | |||
288 | ||||
289 | bool getChecked() const { | |||
290 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
291 | return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0; | |||
292 | #else | |||
293 | return true; | |||
294 | #endif | |||
295 | } | |||
296 | ||||
297 | void setChecked(bool V) { | |||
298 | Payload = reinterpret_cast<ErrorInfoBase*>( | |||
299 | (reinterpret_cast<uintptr_t>(Payload) & | |||
300 | ~static_cast<uintptr_t>(0x1)) | | |||
301 | (V ? 0 : 1)); | |||
302 | } | |||
303 | ||||
304 | std::unique_ptr<ErrorInfoBase> takePayload() { | |||
305 | std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); | |||
306 | setPtr(nullptr); | |||
307 | setChecked(true); | |||
308 | return Tmp; | |||
309 | } | |||
310 | ||||
311 | friend raw_ostream &operator<<(raw_ostream &OS, const Error &E) { | |||
312 | if (auto P = E.getPtr()) | |||
313 | P->log(OS); | |||
314 | else | |||
315 | OS << "success"; | |||
316 | return OS; | |||
317 | } | |||
318 | ||||
319 | ErrorInfoBase *Payload = nullptr; | |||
320 | }; | |||
321 | ||||
322 | /// Subclass of Error for the sole purpose of identifying the success path in | |||
323 | /// the type system. This allows to catch invalid conversion to Expected<T> at | |||
324 | /// compile time. | |||
325 | class ErrorSuccess final : public Error {}; | |||
326 | ||||
327 | inline ErrorSuccess Error::success() { return ErrorSuccess(); } | |||
328 | ||||
329 | /// Make a Error instance representing failure using the given error info | |||
330 | /// type. | |||
331 | template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { | |||
332 | return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); | |||
333 | } | |||
334 | ||||
335 | /// Base class for user error types. Users should declare their error types | |||
336 | /// like: | |||
337 | /// | |||
338 | /// class MyError : public ErrorInfo<MyError> { | |||
339 | /// .... | |||
340 | /// }; | |||
341 | /// | |||
342 | /// This class provides an implementation of the ErrorInfoBase::kind | |||
343 | /// method, which is used by the Error RTTI system. | |||
344 | template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> | |||
345 | class ErrorInfo : public ParentErrT { | |||
346 | public: | |||
347 | using ParentErrT::ParentErrT; // inherit constructors | |||
348 | ||||
349 | static const void *classID() { return &ThisErrT::ID; } | |||
350 | ||||
351 | const void *dynamicClassID() const override { return &ThisErrT::ID; } | |||
352 | ||||
353 | bool isA(const void *const ClassID) const override { | |||
354 | return ClassID == classID() || ParentErrT::isA(ClassID); | |||
355 | } | |||
356 | }; | |||
357 | ||||
358 | /// Special ErrorInfo subclass representing a list of ErrorInfos. | |||
359 | /// Instances of this class are constructed by joinError. | |||
360 | class ErrorList final : public ErrorInfo<ErrorList> { | |||
361 | // handleErrors needs to be able to iterate the payload list of an | |||
362 | // ErrorList. | |||
363 | template <typename... HandlerTs> | |||
364 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); | |||
365 | ||||
366 | // joinErrors is implemented in terms of join. | |||
367 | friend Error joinErrors(Error, Error); | |||
368 | ||||
369 | public: | |||
370 | void log(raw_ostream &OS) const override { | |||
371 | OS << "Multiple errors:\n"; | |||
372 | for (auto &ErrPayload : Payloads) { | |||
373 | ErrPayload->log(OS); | |||
374 | OS << "\n"; | |||
375 | } | |||
376 | } | |||
377 | ||||
378 | std::error_code convertToErrorCode() const override; | |||
379 | ||||
380 | // Used by ErrorInfo::classID. | |||
381 | static char ID; | |||
382 | ||||
383 | private: | |||
384 | ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, | |||
385 | std::unique_ptr<ErrorInfoBase> Payload2) { | |||
386 | assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&((!Payload1->isA<ErrorList>() && !Payload2-> isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors" ) ? static_cast<void> (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 387, __PRETTY_FUNCTION__)) | |||
387 | "ErrorList constructor payloads should be singleton errors")((!Payload1->isA<ErrorList>() && !Payload2-> isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors" ) ? static_cast<void> (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 387, __PRETTY_FUNCTION__)); | |||
388 | Payloads.push_back(std::move(Payload1)); | |||
389 | Payloads.push_back(std::move(Payload2)); | |||
390 | } | |||
391 | ||||
392 | static Error join(Error E1, Error E2) { | |||
393 | if (!E1) | |||
394 | return E2; | |||
395 | if (!E2) | |||
396 | return E1; | |||
397 | if (E1.isA<ErrorList>()) { | |||
398 | auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); | |||
399 | if (E2.isA<ErrorList>()) { | |||
400 | auto E2Payload = E2.takePayload(); | |||
401 | auto &E2List = static_cast<ErrorList &>(*E2Payload); | |||
402 | for (auto &Payload : E2List.Payloads) | |||
403 | E1List.Payloads.push_back(std::move(Payload)); | |||
404 | } else | |||
405 | E1List.Payloads.push_back(E2.takePayload()); | |||
406 | ||||
407 | return E1; | |||
408 | } | |||
409 | if (E2.isA<ErrorList>()) { | |||
410 | auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); | |||
411 | E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); | |||
412 | return E2; | |||
413 | } | |||
414 | return Error(std::unique_ptr<ErrorList>( | |||
415 | new ErrorList(E1.takePayload(), E2.takePayload()))); | |||
416 | } | |||
417 | ||||
418 | std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; | |||
419 | }; | |||
420 | ||||
421 | /// Concatenate errors. The resulting Error is unchecked, and contains the | |||
422 | /// ErrorInfo(s), if any, contained in E1, followed by the | |||
423 | /// ErrorInfo(s), if any, contained in E2. | |||
424 | inline Error joinErrors(Error E1, Error E2) { | |||
425 | return ErrorList::join(std::move(E1), std::move(E2)); | |||
426 | } | |||
427 | ||||
428 | /// Tagged union holding either a T or a Error. | |||
429 | /// | |||
430 | /// This class parallels ErrorOr, but replaces error_code with Error. Since | |||
431 | /// Error cannot be copied, this class replaces getError() with | |||
432 | /// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the | |||
433 | /// error class type. | |||
434 | template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected { | |||
435 | template <class T1> friend class ExpectedAsOutParameter; | |||
436 | template <class OtherT> friend class Expected; | |||
437 | ||||
438 | static const bool isRef = std::is_reference<T>::value; | |||
439 | ||||
440 | using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>; | |||
441 | ||||
442 | using error_type = std::unique_ptr<ErrorInfoBase>; | |||
443 | ||||
444 | public: | |||
445 | using storage_type = typename std::conditional<isRef, wrap, T>::type; | |||
446 | using value_type = T; | |||
447 | ||||
448 | private: | |||
449 | using reference = typename std::remove_reference<T>::type &; | |||
450 | using const_reference = const typename std::remove_reference<T>::type &; | |||
451 | using pointer = typename std::remove_reference<T>::type *; | |||
452 | using const_pointer = const typename std::remove_reference<T>::type *; | |||
453 | ||||
454 | public: | |||
455 | /// Create an Expected<T> error value from the given Error. | |||
456 | Expected(Error Err) | |||
457 | : HasError(true) | |||
458 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
459 | // Expected is unchecked upon construction in Debug builds. | |||
460 | , Unchecked(true) | |||
461 | #endif | |||
462 | { | |||
463 | assert(Err && "Cannot create Expected<T> from Error success value.")((Err && "Cannot create Expected<T> from Error success value." ) ? static_cast<void> (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 463, __PRETTY_FUNCTION__)); | |||
464 | new (getErrorStorage()) error_type(Err.takePayload()); | |||
465 | } | |||
466 | ||||
467 | /// Forbid to convert from Error::success() implicitly, this avoids having | |||
468 | /// Expected<T> foo() { return Error::success(); } which compiles otherwise | |||
469 | /// but triggers the assertion above. | |||
470 | Expected(ErrorSuccess) = delete; | |||
471 | ||||
472 | /// Create an Expected<T> success value from the given OtherT value, which | |||
473 | /// must be convertible to T. | |||
474 | template <typename OtherT> | |||
475 | Expected(OtherT &&Val, | |||
476 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type | |||
477 | * = nullptr) | |||
478 | : HasError(false) | |||
479 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
480 | // Expected is unchecked upon construction in Debug builds. | |||
481 | , Unchecked(true) | |||
482 | #endif | |||
483 | { | |||
484 | new (getStorage()) storage_type(std::forward<OtherT>(Val)); | |||
485 | } | |||
486 | ||||
487 | /// Move construct an Expected<T> value. | |||
488 | Expected(Expected &&Other) { moveConstruct(std::move(Other)); } | |||
489 | ||||
490 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT | |||
491 | /// must be convertible to T. | |||
492 | template <class OtherT> | |||
493 | Expected(Expected<OtherT> &&Other, | |||
494 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type | |||
495 | * = nullptr) { | |||
496 | moveConstruct(std::move(Other)); | |||
497 | } | |||
498 | ||||
499 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT | |||
500 | /// isn't convertible to T. | |||
501 | template <class OtherT> | |||
502 | explicit Expected( | |||
503 | Expected<OtherT> &&Other, | |||
504 | typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = | |||
505 | nullptr) { | |||
506 | moveConstruct(std::move(Other)); | |||
507 | } | |||
508 | ||||
509 | /// Move-assign from another Expected<T>. | |||
510 | Expected &operator=(Expected &&Other) { | |||
511 | moveAssign(std::move(Other)); | |||
512 | return *this; | |||
513 | } | |||
514 | ||||
515 | /// Destroy an Expected<T>. | |||
516 | ~Expected() { | |||
517 | assertIsChecked(); | |||
518 | if (!HasError) | |||
519 | getStorage()->~storage_type(); | |||
520 | else | |||
521 | getErrorStorage()->~error_type(); | |||
522 | } | |||
523 | ||||
524 | /// Return false if there is an error. | |||
525 | explicit operator bool() { | |||
526 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
527 | Unchecked = HasError; | |||
528 | #endif | |||
529 | return !HasError; | |||
530 | } | |||
531 | ||||
532 | /// Returns a reference to the stored T value. | |||
533 | reference get() { | |||
534 | assertIsChecked(); | |||
535 | return *getStorage(); | |||
536 | } | |||
537 | ||||
538 | /// Returns a const reference to the stored T value. | |||
539 | const_reference get() const { | |||
540 | assertIsChecked(); | |||
541 | return const_cast<Expected<T> *>(this)->get(); | |||
542 | } | |||
543 | ||||
544 | /// Check that this Expected<T> is an error of type ErrT. | |||
545 | template <typename ErrT> bool errorIsA() const { | |||
546 | return HasError && (*getErrorStorage())->template isA<ErrT>(); | |||
547 | } | |||
548 | ||||
549 | /// Take ownership of the stored error. | |||
550 | /// After calling this the Expected<T> is in an indeterminate state that can | |||
551 | /// only be safely destructed. No further calls (beside the destructor) should | |||
552 | /// be made on the Expected<T> vaule. | |||
553 | Error takeError() { | |||
554 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
555 | Unchecked = false; | |||
556 | #endif | |||
557 | return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); | |||
558 | } | |||
559 | ||||
560 | /// Returns a pointer to the stored T value. | |||
561 | pointer operator->() { | |||
562 | assertIsChecked(); | |||
563 | return toPointer(getStorage()); | |||
564 | } | |||
565 | ||||
566 | /// Returns a const pointer to the stored T value. | |||
567 | const_pointer operator->() const { | |||
568 | assertIsChecked(); | |||
569 | return toPointer(getStorage()); | |||
570 | } | |||
571 | ||||
572 | /// Returns a reference to the stored T value. | |||
573 | reference operator*() { | |||
574 | assertIsChecked(); | |||
575 | return *getStorage(); | |||
576 | } | |||
577 | ||||
578 | /// Returns a const reference to the stored T value. | |||
579 | const_reference operator*() const { | |||
580 | assertIsChecked(); | |||
581 | return *getStorage(); | |||
582 | } | |||
583 | ||||
584 | private: | |||
585 | template <class T1> | |||
586 | static bool compareThisIfSameType(const T1 &a, const T1 &b) { | |||
587 | return &a == &b; | |||
588 | } | |||
589 | ||||
590 | template <class T1, class T2> | |||
591 | static bool compareThisIfSameType(const T1 &a, const T2 &b) { | |||
592 | return false; | |||
593 | } | |||
594 | ||||
595 | template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { | |||
596 | HasError = Other.HasError; | |||
597 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
598 | Unchecked = true; | |||
599 | Other.Unchecked = false; | |||
600 | #endif | |||
601 | ||||
602 | if (!HasError) | |||
603 | new (getStorage()) storage_type(std::move(*Other.getStorage())); | |||
604 | else | |||
605 | new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); | |||
606 | } | |||
607 | ||||
608 | template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { | |||
609 | assertIsChecked(); | |||
610 | ||||
611 | if (compareThisIfSameType(*this, Other)) | |||
612 | return; | |||
613 | ||||
614 | this->~Expected(); | |||
615 | new (this) Expected(std::move(Other)); | |||
616 | } | |||
617 | ||||
618 | pointer toPointer(pointer Val) { return Val; } | |||
619 | ||||
620 | const_pointer toPointer(const_pointer Val) const { return Val; } | |||
621 | ||||
622 | pointer toPointer(wrap *Val) { return &Val->get(); } | |||
623 | ||||
624 | const_pointer toPointer(const wrap *Val) const { return &Val->get(); } | |||
625 | ||||
626 | storage_type *getStorage() { | |||
627 | assert(!HasError && "Cannot get value when an error exists!")((!HasError && "Cannot get value when an error exists!" ) ? static_cast<void> (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 627, __PRETTY_FUNCTION__)); | |||
628 | return reinterpret_cast<storage_type *>(TStorage.buffer); | |||
629 | } | |||
630 | ||||
631 | const storage_type *getStorage() const { | |||
632 | assert(!HasError && "Cannot get value when an error exists!")((!HasError && "Cannot get value when an error exists!" ) ? static_cast<void> (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 632, __PRETTY_FUNCTION__)); | |||
633 | return reinterpret_cast<const storage_type *>(TStorage.buffer); | |||
634 | } | |||
635 | ||||
636 | error_type *getErrorStorage() { | |||
637 | assert(HasError && "Cannot get error when a value exists!")((HasError && "Cannot get error when a value exists!" ) ? static_cast<void> (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 637, __PRETTY_FUNCTION__)); | |||
638 | return reinterpret_cast<error_type *>(ErrorStorage.buffer); | |||
639 | } | |||
640 | ||||
641 | const error_type *getErrorStorage() const { | |||
642 | assert(HasError && "Cannot get error when a value exists!")((HasError && "Cannot get error when a value exists!" ) ? static_cast<void> (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 642, __PRETTY_FUNCTION__)); | |||
643 | return reinterpret_cast<const error_type *>(ErrorStorage.buffer); | |||
644 | } | |||
645 | ||||
646 | // Used by ExpectedAsOutParameter to reset the checked flag. | |||
647 | void setUnchecked() { | |||
648 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
649 | Unchecked = true; | |||
650 | #endif | |||
651 | } | |||
652 | ||||
653 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
654 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) | |||
655 | LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) | |||
656 | void fatalUncheckedExpected() const { | |||
657 | dbgs() << "Expected<T> must be checked before access or destruction.\n"; | |||
658 | if (HasError) { | |||
659 | dbgs() << "Unchecked Expected<T> contained error:\n"; | |||
660 | (*getErrorStorage())->log(dbgs()); | |||
661 | } else | |||
662 | dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " | |||
663 | "values in success mode must still be checked prior to being " | |||
664 | "destroyed).\n"; | |||
665 | abort(); | |||
666 | } | |||
667 | #endif | |||
668 | ||||
669 | void assertIsChecked() { | |||
670 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
671 | if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false)) | |||
672 | fatalUncheckedExpected(); | |||
673 | #endif | |||
674 | } | |||
675 | ||||
676 | union { | |||
677 | AlignedCharArrayUnion<storage_type> TStorage; | |||
678 | AlignedCharArrayUnion<error_type> ErrorStorage; | |||
679 | }; | |||
680 | bool HasError : 1; | |||
681 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
682 | bool Unchecked : 1; | |||
683 | #endif | |||
684 | }; | |||
685 | ||||
686 | /// Report a serious error, calling any installed error handler. See | |||
687 | /// ErrorHandling.h. | |||
688 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err, | |||
689 | bool gen_crash_diag = true); | |||
690 | ||||
691 | /// Report a fatal error if Err is a failure value. | |||
692 | /// | |||
693 | /// This function can be used to wrap calls to fallible functions ONLY when it | |||
694 | /// is known that the Error will always be a success value. E.g. | |||
695 | /// | |||
696 | /// @code{.cpp} | |||
697 | /// // foo only attempts the fallible operation if DoFallibleOperation is | |||
698 | /// // true. If DoFallibleOperation is false then foo always returns | |||
699 | /// // Error::success(). | |||
700 | /// Error foo(bool DoFallibleOperation); | |||
701 | /// | |||
702 | /// cantFail(foo(false)); | |||
703 | /// @endcode | |||
704 | inline void cantFail(Error Err, const char *Msg = nullptr) { | |||
705 | if (Err) { | |||
706 | if (!Msg) | |||
707 | Msg = "Failure value returned from cantFail wrapped call"; | |||
708 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 708); | |||
709 | } | |||
710 | } | |||
711 | ||||
712 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and | |||
713 | /// returns the contained value. | |||
714 | /// | |||
715 | /// This function can be used to wrap calls to fallible functions ONLY when it | |||
716 | /// is known that the Error will always be a success value. E.g. | |||
717 | /// | |||
718 | /// @code{.cpp} | |||
719 | /// // foo only attempts the fallible operation if DoFallibleOperation is | |||
720 | /// // true. If DoFallibleOperation is false then foo always returns an int. | |||
721 | /// Expected<int> foo(bool DoFallibleOperation); | |||
722 | /// | |||
723 | /// int X = cantFail(foo(false)); | |||
724 | /// @endcode | |||
725 | template <typename T> | |||
726 | T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) { | |||
727 | if (ValOrErr) | |||
728 | return std::move(*ValOrErr); | |||
729 | else { | |||
730 | if (!Msg) | |||
731 | Msg = "Failure value returned from cantFail wrapped call"; | |||
732 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 732); | |||
733 | } | |||
734 | } | |||
735 | ||||
736 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and | |||
737 | /// returns the contained reference. | |||
738 | /// | |||
739 | /// This function can be used to wrap calls to fallible functions ONLY when it | |||
740 | /// is known that the Error will always be a success value. E.g. | |||
741 | /// | |||
742 | /// @code{.cpp} | |||
743 | /// // foo only attempts the fallible operation if DoFallibleOperation is | |||
744 | /// // true. If DoFallibleOperation is false then foo always returns a Bar&. | |||
745 | /// Expected<Bar&> foo(bool DoFallibleOperation); | |||
746 | /// | |||
747 | /// Bar &X = cantFail(foo(false)); | |||
748 | /// @endcode | |||
749 | template <typename T> | |||
750 | T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) { | |||
751 | if (ValOrErr) | |||
752 | return *ValOrErr; | |||
753 | else { | |||
754 | if (!Msg) | |||
755 | Msg = "Failure value returned from cantFail wrapped call"; | |||
756 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 756); | |||
757 | } | |||
758 | } | |||
759 | ||||
760 | /// Helper for testing applicability of, and applying, handlers for | |||
761 | /// ErrorInfo types. | |||
762 | template <typename HandlerT> | |||
763 | class ErrorHandlerTraits | |||
764 | : public ErrorHandlerTraits<decltype( | |||
765 | &std::remove_reference<HandlerT>::type::operator())> {}; | |||
766 | ||||
767 | // Specialization functions of the form 'Error (const ErrT&)'. | |||
768 | template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { | |||
769 | public: | |||
770 | static bool appliesTo(const ErrorInfoBase &E) { | |||
771 | return E.template isA<ErrT>(); | |||
772 | } | |||
773 | ||||
774 | template <typename HandlerT> | |||
775 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
776 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 776, __PRETTY_FUNCTION__)); | |||
777 | return H(static_cast<ErrT &>(*E)); | |||
778 | } | |||
779 | }; | |||
780 | ||||
781 | // Specialization functions of the form 'void (const ErrT&)'. | |||
782 | template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { | |||
783 | public: | |||
784 | static bool appliesTo(const ErrorInfoBase &E) { | |||
785 | return E.template isA<ErrT>(); | |||
786 | } | |||
787 | ||||
788 | template <typename HandlerT> | |||
789 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
790 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 790, __PRETTY_FUNCTION__)); | |||
791 | H(static_cast<ErrT &>(*E)); | |||
792 | return Error::success(); | |||
793 | } | |||
794 | }; | |||
795 | ||||
796 | /// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. | |||
797 | template <typename ErrT> | |||
798 | class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { | |||
799 | public: | |||
800 | static bool appliesTo(const ErrorInfoBase &E) { | |||
801 | return E.template isA<ErrT>(); | |||
802 | } | |||
803 | ||||
804 | template <typename HandlerT> | |||
805 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
806 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 806, __PRETTY_FUNCTION__)); | |||
807 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); | |||
808 | return H(std::move(SubE)); | |||
809 | } | |||
810 | }; | |||
811 | ||||
812 | /// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'. | |||
813 | template <typename ErrT> | |||
814 | class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { | |||
815 | public: | |||
816 | static bool appliesTo(const ErrorInfoBase &E) { | |||
817 | return E.template isA<ErrT>(); | |||
818 | } | |||
819 | ||||
820 | template <typename HandlerT> | |||
821 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
822 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 822, __PRETTY_FUNCTION__)); | |||
823 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); | |||
824 | H(std::move(SubE)); | |||
825 | return Error::success(); | |||
826 | } | |||
827 | }; | |||
828 | ||||
829 | // Specialization for member functions of the form 'RetT (const ErrT&)'. | |||
830 | template <typename C, typename RetT, typename ErrT> | |||
831 | class ErrorHandlerTraits<RetT (C::*)(ErrT &)> | |||
832 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
833 | ||||
834 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. | |||
835 | template <typename C, typename RetT, typename ErrT> | |||
836 | class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> | |||
837 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
838 | ||||
839 | // Specialization for member functions of the form 'RetT (const ErrT&)'. | |||
840 | template <typename C, typename RetT, typename ErrT> | |||
841 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> | |||
842 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
843 | ||||
844 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. | |||
845 | template <typename C, typename RetT, typename ErrT> | |||
846 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> | |||
847 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
848 | ||||
849 | /// Specialization for member functions of the form | |||
850 | /// 'RetT (std::unique_ptr<ErrT>)'. | |||
851 | template <typename C, typename RetT, typename ErrT> | |||
852 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> | |||
853 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; | |||
854 | ||||
855 | /// Specialization for member functions of the form | |||
856 | /// 'RetT (std::unique_ptr<ErrT>) const'. | |||
857 | template <typename C, typename RetT, typename ErrT> | |||
858 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> | |||
859 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; | |||
860 | ||||
861 | inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { | |||
862 | return Error(std::move(Payload)); | |||
863 | } | |||
864 | ||||
865 | template <typename HandlerT, typename... HandlerTs> | |||
866 | Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, | |||
867 | HandlerT &&Handler, HandlerTs &&... Handlers) { | |||
868 | if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) | |||
869 | return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), | |||
870 | std::move(Payload)); | |||
871 | return handleErrorImpl(std::move(Payload), | |||
872 | std::forward<HandlerTs>(Handlers)...); | |||
873 | } | |||
874 | ||||
875 | /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any | |||
876 | /// unhandled errors (or Errors returned by handlers) are re-concatenated and | |||
877 | /// returned. | |||
878 | /// Because this function returns an error, its result must also be checked | |||
879 | /// or returned. If you intend to handle all errors use handleAllErrors | |||
880 | /// (which returns void, and will abort() on unhandled errors) instead. | |||
881 | template <typename... HandlerTs> | |||
882 | Error handleErrors(Error E, HandlerTs &&... Hs) { | |||
883 | if (!E) | |||
884 | return Error::success(); | |||
885 | ||||
886 | std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); | |||
887 | ||||
888 | if (Payload->isA<ErrorList>()) { | |||
889 | ErrorList &List = static_cast<ErrorList &>(*Payload); | |||
890 | Error R; | |||
891 | for (auto &P : List.Payloads) | |||
892 | R = ErrorList::join( | |||
893 | std::move(R), | |||
894 | handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); | |||
895 | return R; | |||
896 | } | |||
897 | ||||
898 | return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); | |||
899 | } | |||
900 | ||||
901 | /// Behaves the same as handleErrors, except that by contract all errors | |||
902 | /// *must* be handled by the given handlers (i.e. there must be no remaining | |||
903 | /// errors after running the handlers, or llvm_unreachable is called). | |||
904 | template <typename... HandlerTs> | |||
905 | void handleAllErrors(Error E, HandlerTs &&... Handlers) { | |||
906 | cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); | |||
907 | } | |||
908 | ||||
909 | /// Check that E is a non-error, then drop it. | |||
910 | /// If E is an error, llvm_unreachable will be called. | |||
911 | inline void handleAllErrors(Error E) { | |||
912 | cantFail(std::move(E)); | |||
913 | } | |||
914 | ||||
915 | /// Handle any errors (if present) in an Expected<T>, then try a recovery path. | |||
916 | /// | |||
917 | /// If the incoming value is a success value it is returned unmodified. If it | |||
918 | /// is a failure value then it the contained error is passed to handleErrors. | |||
919 | /// If handleErrors is able to handle the error then the RecoveryPath functor | |||
920 | /// is called to supply the final result. If handleErrors is not able to | |||
921 | /// handle all errors then the unhandled errors are returned. | |||
922 | /// | |||
923 | /// This utility enables the follow pattern: | |||
924 | /// | |||
925 | /// @code{.cpp} | |||
926 | /// enum FooStrategy { Aggressive, Conservative }; | |||
927 | /// Expected<Foo> foo(FooStrategy S); | |||
928 | /// | |||
929 | /// auto ResultOrErr = | |||
930 | /// handleExpected( | |||
931 | /// foo(Aggressive), | |||
932 | /// []() { return foo(Conservative); }, | |||
933 | /// [](AggressiveStrategyError&) { | |||
934 | /// // Implicitly conusme this - we'll recover by using a conservative | |||
935 | /// // strategy. | |||
936 | /// }); | |||
937 | /// | |||
938 | /// @endcode | |||
939 | template <typename T, typename RecoveryFtor, typename... HandlerTs> | |||
940 | Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath, | |||
941 | HandlerTs &&... Handlers) { | |||
942 | if (ValOrErr) | |||
943 | return ValOrErr; | |||
944 | ||||
945 | if (auto Err = handleErrors(ValOrErr.takeError(), | |||
946 | std::forward<HandlerTs>(Handlers)...)) | |||
947 | return std::move(Err); | |||
948 | ||||
949 | return RecoveryPath(); | |||
950 | } | |||
951 | ||||
952 | /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner | |||
953 | /// will be printed before the first one is logged. A newline will be printed | |||
954 | /// after each error. | |||
955 | /// | |||
956 | /// This is useful in the base level of your program to allow clean termination | |||
957 | /// (allowing clean deallocation of resources, etc.), while reporting error | |||
958 | /// information to the user. | |||
959 | void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); | |||
960 | ||||
961 | /// Write all error messages (if any) in E to a string. The newline character | |||
962 | /// is used to separate error messages. | |||
963 | inline std::string toString(Error E) { | |||
964 | SmallVector<std::string, 2> Errors; | |||
965 | handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { | |||
966 | Errors.push_back(EI.message()); | |||
967 | }); | |||
968 | return join(Errors.begin(), Errors.end(), "\n"); | |||
969 | } | |||
970 | ||||
971 | /// Consume a Error without doing anything. This method should be used | |||
972 | /// only where an error can be considered a reasonable and expected return | |||
973 | /// value. | |||
974 | /// | |||
975 | /// Uses of this method are potentially indicative of design problems: If it's | |||
976 | /// legitimate to do nothing while processing an "error", the error-producer | |||
977 | /// might be more clearly refactored to return an Optional<T>. | |||
978 | inline void consumeError(Error Err) { | |||
979 | handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); | |||
980 | } | |||
981 | ||||
982 | /// Helper for converting an Error to a bool. | |||
983 | /// | |||
984 | /// This method returns true if Err is in an error state, or false if it is | |||
985 | /// in a success state. Puts Err in a checked state in both cases (unlike | |||
986 | /// Error::operator bool(), which only does this for success states). | |||
987 | inline bool errorToBool(Error Err) { | |||
988 | bool IsError = static_cast<bool>(Err); | |||
989 | if (IsError) | |||
990 | consumeError(std::move(Err)); | |||
991 | return IsError; | |||
992 | } | |||
993 | ||||
994 | /// Helper for Errors used as out-parameters. | |||
995 | /// | |||
996 | /// This helper is for use with the Error-as-out-parameter idiom, where an error | |||
997 | /// is passed to a function or method by reference, rather than being returned. | |||
998 | /// In such cases it is helpful to set the checked bit on entry to the function | |||
999 | /// so that the error can be written to (unchecked Errors abort on assignment) | |||
1000 | /// and clear the checked bit on exit so that clients cannot accidentally forget | |||
1001 | /// to check the result. This helper performs these actions automatically using | |||
1002 | /// RAII: | |||
1003 | /// | |||
1004 | /// @code{.cpp} | |||
1005 | /// Result foo(Error &Err) { | |||
1006 | /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set | |||
1007 | /// // <body of foo> | |||
1008 | /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. | |||
1009 | /// } | |||
1010 | /// @endcode | |||
1011 | /// | |||
1012 | /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be | |||
1013 | /// used with optional Errors (Error pointers that are allowed to be null). If | |||
1014 | /// ErrorAsOutParameter took an Error reference, an instance would have to be | |||
1015 | /// created inside every condition that verified that Error was non-null. By | |||
1016 | /// taking an Error pointer we can just create one instance at the top of the | |||
1017 | /// function. | |||
1018 | class ErrorAsOutParameter { | |||
1019 | public: | |||
1020 | ErrorAsOutParameter(Error *Err) : Err(Err) { | |||
1021 | // Raise the checked bit if Err is success. | |||
1022 | if (Err) | |||
1023 | (void)!!*Err; | |||
1024 | } | |||
1025 | ||||
1026 | ~ErrorAsOutParameter() { | |||
1027 | // Clear the checked bit. | |||
1028 | if (Err && !*Err) | |||
1029 | *Err = Error::success(); | |||
1030 | } | |||
1031 | ||||
1032 | private: | |||
1033 | Error *Err; | |||
1034 | }; | |||
1035 | ||||
1036 | /// Helper for Expected<T>s used as out-parameters. | |||
1037 | /// | |||
1038 | /// See ErrorAsOutParameter. | |||
1039 | template <typename T> | |||
1040 | class ExpectedAsOutParameter { | |||
1041 | public: | |||
1042 | ExpectedAsOutParameter(Expected<T> *ValOrErr) | |||
1043 | : ValOrErr(ValOrErr) { | |||
1044 | if (ValOrErr) | |||
1045 | (void)!!*ValOrErr; | |||
1046 | } | |||
1047 | ||||
1048 | ~ExpectedAsOutParameter() { | |||
1049 | if (ValOrErr) | |||
1050 | ValOrErr->setUnchecked(); | |||
1051 | } | |||
1052 | ||||
1053 | private: | |||
1054 | Expected<T> *ValOrErr; | |||
1055 | }; | |||
1056 | ||||
1057 | /// This class wraps a std::error_code in a Error. | |||
1058 | /// | |||
1059 | /// This is useful if you're writing an interface that returns a Error | |||
1060 | /// (or Expected) and you want to call code that still returns | |||
1061 | /// std::error_codes. | |||
1062 | class ECError : public ErrorInfo<ECError> { | |||
1063 | friend Error errorCodeToError(std::error_code); | |||
1064 | ||||
1065 | public: | |||
1066 | void setErrorCode(std::error_code EC) { this->EC = EC; } | |||
1067 | std::error_code convertToErrorCode() const override { return EC; } | |||
1068 | void log(raw_ostream &OS) const override { OS << EC.message(); } | |||
1069 | ||||
1070 | // Used by ErrorInfo::classID. | |||
1071 | static char ID; | |||
1072 | ||||
1073 | protected: | |||
1074 | ECError() = default; | |||
1075 | ECError(std::error_code EC) : EC(EC) {} | |||
1076 | ||||
1077 | std::error_code EC; | |||
1078 | }; | |||
1079 | ||||
1080 | /// The value returned by this function can be returned from convertToErrorCode | |||
1081 | /// for Error values where no sensible translation to std::error_code exists. | |||
1082 | /// It should only be used in this situation, and should never be used where a | |||
1083 | /// sensible conversion to std::error_code is available, as attempts to convert | |||
1084 | /// to/from this error will result in a fatal error. (i.e. it is a programmatic | |||
1085 | ///error to try to convert such a value). | |||
1086 | std::error_code inconvertibleErrorCode(); | |||
1087 | ||||
1088 | /// Helper for converting an std::error_code to a Error. | |||
1089 | Error errorCodeToError(std::error_code EC); | |||
1090 | ||||
1091 | /// Helper for converting an ECError to a std::error_code. | |||
1092 | /// | |||
1093 | /// This method requires that Err be Error() or an ECError, otherwise it | |||
1094 | /// will trigger a call to abort(). | |||
1095 | std::error_code errorToErrorCode(Error Err); | |||
1096 | ||||
1097 | /// Convert an ErrorOr<T> to an Expected<T>. | |||
1098 | template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { | |||
1099 | if (auto EC = EO.getError()) | |||
1100 | return errorCodeToError(EC); | |||
1101 | return std::move(*EO); | |||
1102 | } | |||
1103 | ||||
1104 | /// Convert an Expected<T> to an ErrorOr<T>. | |||
1105 | template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { | |||
1106 | if (auto Err = E.takeError()) | |||
1107 | return errorToErrorCode(std::move(Err)); | |||
1108 | return std::move(*E); | |||
1109 | } | |||
1110 | ||||
1111 | /// This class wraps a string in an Error. | |||
1112 | /// | |||
1113 | /// StringError is useful in cases where the client is not expected to be able | |||
1114 | /// to consume the specific error message programmatically (for example, if the | |||
1115 | /// error message is to be presented to the user). | |||
1116 | /// | |||
1117 | /// StringError can also be used when additional information is to be printed | |||
1118 | /// along with a error_code message. Depending on the constructor called, this | |||
1119 | /// class can either display: | |||
1120 | /// 1. the error_code message (ECError behavior) | |||
1121 | /// 2. a string | |||
1122 | /// 3. the error_code message and a string | |||
1123 | /// | |||
1124 | /// These behaviors are useful when subtyping is required; for example, when a | |||
1125 | /// specific library needs an explicit error type. In the example below, | |||
1126 | /// PDBError is derived from StringError: | |||
1127 | /// | |||
1128 | /// @code{.cpp} | |||
1129 | /// Expected<int> foo() { | |||
1130 | /// return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading, | |||
1131 | /// "Additional information"); | |||
1132 | /// } | |||
1133 | /// @endcode | |||
1134 | /// | |||
1135 | class StringError : public ErrorInfo<StringError> { | |||
1136 | public: | |||
1137 | static char ID; | |||
1138 | ||||
1139 | // Prints EC + S and converts to EC | |||
1140 | StringError(std::error_code EC, const Twine &S = Twine()); | |||
1141 | ||||
1142 | // Prints S and converts to EC | |||
1143 | StringError(const Twine &S, std::error_code EC); | |||
1144 | ||||
1145 | void log(raw_ostream &OS) const override; | |||
1146 | std::error_code convertToErrorCode() const override; | |||
1147 | ||||
1148 | const std::string &getMessage() const { return Msg; } | |||
1149 | ||||
1150 | private: | |||
1151 | std::string Msg; | |||
1152 | std::error_code EC; | |||
1153 | const bool PrintMsgOnly = false; | |||
1154 | }; | |||
1155 | ||||
1156 | /// Create formatted StringError object. | |||
1157 | template <typename... Ts> | |||
1158 | Error createStringError(std::error_code EC, char const *Fmt, | |||
1159 | const Ts &... Vals) { | |||
1160 | std::string Buffer; | |||
1161 | raw_string_ostream Stream(Buffer); | |||
1162 | Stream << format(Fmt, Vals...); | |||
1163 | return make_error<StringError>(Stream.str(), EC); | |||
1164 | } | |||
1165 | ||||
1166 | Error createStringError(std::error_code EC, char const *Msg); | |||
1167 | ||||
1168 | /// This class wraps a filename and another Error. | |||
1169 | /// | |||
1170 | /// In some cases, an error needs to live along a 'source' name, in order to | |||
1171 | /// show more detailed information to the user. | |||
1172 | class FileError final : public ErrorInfo<FileError> { | |||
1173 | ||||
1174 | friend Error createFileError(std::string, Error); | |||
1175 | ||||
1176 | public: | |||
1177 | void log(raw_ostream &OS) const override { | |||
1178 | assert(Err && !FileName.empty() && "Trying to log after takeError().")((Err && !FileName.empty() && "Trying to log after takeError()." ) ? static_cast<void> (0) : __assert_fail ("Err && !FileName.empty() && \"Trying to log after takeError().\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1178, __PRETTY_FUNCTION__)); | |||
1179 | OS << "'" << FileName << "': "; | |||
1180 | Err->log(OS); | |||
1181 | } | |||
1182 | ||||
1183 | Error takeError() { return Error(std::move(Err)); } | |||
1184 | ||||
1185 | std::error_code convertToErrorCode() const override; | |||
1186 | ||||
1187 | // Used by ErrorInfo::classID. | |||
1188 | static char ID; | |||
1189 | ||||
1190 | private: | |||
1191 | FileError(std::string F, std::unique_ptr<ErrorInfoBase> E) { | |||
1192 | assert(E && "Cannot create FileError from Error success value.")((E && "Cannot create FileError from Error success value." ) ? static_cast<void> (0) : __assert_fail ("E && \"Cannot create FileError from Error success value.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1192, __PRETTY_FUNCTION__)); | |||
1193 | assert(!F.empty() &&((!F.empty() && "The file name provided to FileError must not be empty." ) ? static_cast<void> (0) : __assert_fail ("!F.empty() && \"The file name provided to FileError must not be empty.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1194, __PRETTY_FUNCTION__)) | |||
1194 | "The file name provided to FileError must not be empty.")((!F.empty() && "The file name provided to FileError must not be empty." ) ? static_cast<void> (0) : __assert_fail ("!F.empty() && \"The file name provided to FileError must not be empty.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1194, __PRETTY_FUNCTION__)); | |||
1195 | FileName = F; | |||
1196 | Err = std::move(E); | |||
1197 | } | |||
1198 | ||||
1199 | static Error build(std::string F, Error E) { | |||
1200 | return Error(std::unique_ptr<FileError>(new FileError(F, E.takePayload()))); | |||
1201 | } | |||
1202 | ||||
1203 | std::string FileName; | |||
1204 | std::unique_ptr<ErrorInfoBase> Err; | |||
1205 | }; | |||
1206 | ||||
1207 | /// Concatenate a source file path and/or name with an Error. The resulting | |||
1208 | /// Error is unchecked. | |||
1209 | inline Error createFileError(std::string F, Error E) { | |||
1210 | return FileError::build(F, std::move(E)); | |||
1211 | } | |||
1212 | ||||
1213 | Error createFileError(std::string F, ErrorSuccess) = delete; | |||
1214 | ||||
1215 | /// Helper for check-and-exit error handling. | |||
1216 | /// | |||
1217 | /// For tool use only. NOT FOR USE IN LIBRARY CODE. | |||
1218 | /// | |||
1219 | class ExitOnError { | |||
1220 | public: | |||
1221 | /// Create an error on exit helper. | |||
1222 | ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) | |||
1223 | : Banner(std::move(Banner)), | |||
1224 | GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} | |||
1225 | ||||
1226 | /// Set the banner string for any errors caught by operator(). | |||
1227 | void setBanner(std::string Banner) { this->Banner = std::move(Banner); } | |||
1228 | ||||
1229 | /// Set the exit-code mapper function. | |||
1230 | void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { | |||
1231 | this->GetExitCode = std::move(GetExitCode); | |||
1232 | } | |||
1233 | ||||
1234 | /// Check Err. If it's in a failure state log the error(s) and exit. | |||
1235 | void operator()(Error Err) const { checkError(std::move(Err)); } | |||
1236 | ||||
1237 | /// Check E. If it's in a success state then return the contained value. If | |||
1238 | /// it's in a failure state log the error(s) and exit. | |||
1239 | template <typename T> T operator()(Expected<T> &&E) const { | |||
1240 | checkError(E.takeError()); | |||
1241 | return std::move(*E); | |||
1242 | } | |||
1243 | ||||
1244 | /// Check E. If it's in a success state then return the contained reference. If | |||
1245 | /// it's in a failure state log the error(s) and exit. | |||
1246 | template <typename T> T& operator()(Expected<T&> &&E) const { | |||
1247 | checkError(E.takeError()); | |||
1248 | return *E; | |||
1249 | } | |||
1250 | ||||
1251 | private: | |||
1252 | void checkError(Error Err) const { | |||
1253 | if (Err) { | |||
1254 | int ExitCode = GetExitCode(Err); | |||
1255 | logAllUnhandledErrors(std::move(Err), errs(), Banner); | |||
1256 | exit(ExitCode); | |||
1257 | } | |||
1258 | } | |||
1259 | ||||
1260 | std::string Banner; | |||
1261 | std::function<int(const Error &)> GetExitCode; | |||
1262 | }; | |||
1263 | ||||
1264 | /// Conversion from Error to LLVMErrorRef for C error bindings. | |||
1265 | inline LLVMErrorRef wrap(Error Err) { | |||
1266 | return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release()); | |||
1267 | } | |||
1268 | ||||
1269 | /// Conversion from LLVMErrorRef to Error for C error bindings. | |||
1270 | inline Error unwrap(LLVMErrorRef ErrRef) { | |||
1271 | return Error(std::unique_ptr<ErrorInfoBase>( | |||
1272 | reinterpret_cast<ErrorInfoBase *>(ErrRef))); | |||
1273 | } | |||
1274 | ||||
1275 | } // end namespace llvm | |||
1276 | ||||
1277 | #endif // LLVM_SUPPORT_ERROR_H |
1 | //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file contains some templates that are useful if you are working with the |
11 | // STL at all. |
12 | // |
13 | // No library is required when using these functions. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef LLVM_ADT_STLEXTRAS_H |
18 | #define LLVM_ADT_STLEXTRAS_H |
19 | |
20 | #include "llvm/ADT/Optional.h" |
21 | #include "llvm/ADT/SmallVector.h" |
22 | #include "llvm/ADT/iterator.h" |
23 | #include "llvm/ADT/iterator_range.h" |
24 | #include "llvm/Config/abi-breaking.h" |
25 | #include "llvm/Support/ErrorHandling.h" |
26 | #include <algorithm> |
27 | #include <cassert> |
28 | #include <cstddef> |
29 | #include <cstdint> |
30 | #include <cstdlib> |
31 | #include <functional> |
32 | #include <initializer_list> |
33 | #include <iterator> |
34 | #include <limits> |
35 | #include <memory> |
36 | #include <tuple> |
37 | #include <type_traits> |
38 | #include <utility> |
39 | |
40 | #ifdef EXPENSIVE_CHECKS |
41 | #include <random> // for std::mt19937 |
42 | #endif |
43 | |
44 | namespace llvm { |
45 | |
46 | // Only used by compiler if both template types are the same. Useful when |
47 | // using SFINAE to test for the existence of member functions. |
48 | template <typename T, T> struct SameType; |
49 | |
50 | namespace detail { |
51 | |
52 | template <typename RangeT> |
53 | using IterOfRange = decltype(std::begin(std::declval<RangeT &>())); |
54 | |
55 | template <typename RangeT> |
56 | using ValueOfRange = typename std::remove_reference<decltype( |
57 | *std::begin(std::declval<RangeT &>()))>::type; |
58 | |
59 | } // end namespace detail |
60 | |
61 | //===----------------------------------------------------------------------===// |
62 | // Extra additions to <type_traits> |
63 | //===----------------------------------------------------------------------===// |
64 | |
65 | template <typename T> |
66 | struct negation : std::integral_constant<bool, !bool(T::value)> {}; |
67 | |
68 | template <typename...> struct conjunction : std::true_type {}; |
69 | template <typename B1> struct conjunction<B1> : B1 {}; |
70 | template <typename B1, typename... Bn> |
71 | struct conjunction<B1, Bn...> |
72 | : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {}; |
73 | |
74 | //===----------------------------------------------------------------------===// |
75 | // Extra additions to <functional> |
76 | //===----------------------------------------------------------------------===// |
77 | |
78 | template <class Ty> struct identity { |
79 | using argument_type = Ty; |
80 | |
81 | Ty &operator()(Ty &self) const { |
82 | return self; |
83 | } |
84 | const Ty &operator()(const Ty &self) const { |
85 | return self; |
86 | } |
87 | }; |
88 | |
89 | template <class Ty> struct less_ptr { |
90 | bool operator()(const Ty* left, const Ty* right) const { |
91 | return *left < *right; |
92 | } |
93 | }; |
94 | |
95 | template <class Ty> struct greater_ptr { |
96 | bool operator()(const Ty* left, const Ty* right) const { |
97 | return *right < *left; |
98 | } |
99 | }; |
100 | |
101 | /// An efficient, type-erasing, non-owning reference to a callable. This is |
102 | /// intended for use as the type of a function parameter that is not used |
103 | /// after the function in question returns. |
104 | /// |
105 | /// This class does not own the callable, so it is not in general safe to store |
106 | /// a function_ref. |
107 | template<typename Fn> class function_ref; |
108 | |
109 | template<typename Ret, typename ...Params> |
110 | class function_ref<Ret(Params...)> { |
111 | Ret (*callback)(intptr_t callable, Params ...params) = nullptr; |
112 | intptr_t callable; |
113 | |
114 | template<typename Callable> |
115 | static Ret callback_fn(intptr_t callable, Params ...params) { |
116 | return (*reinterpret_cast<Callable*>(callable))( |
117 | std::forward<Params>(params)...); |
118 | } |
119 | |
120 | public: |
121 | function_ref() = default; |
122 | function_ref(std::nullptr_t) {} |
123 | |
124 | template <typename Callable> |
125 | function_ref(Callable &&callable, |
126 | typename std::enable_if< |
127 | !std::is_same<typename std::remove_reference<Callable>::type, |
128 | function_ref>::value>::type * = nullptr) |
129 | : callback(callback_fn<typename std::remove_reference<Callable>::type>), |
130 | callable(reinterpret_cast<intptr_t>(&callable)) {} |
131 | |
132 | Ret operator()(Params ...params) const { |
133 | return callback(callable, std::forward<Params>(params)...); |
134 | } |
135 | |
136 | operator bool() const { return callback; } |
137 | }; |
138 | |
139 | // deleter - Very very very simple method that is used to invoke operator |
140 | // delete on something. It is used like this: |
141 | // |
142 | // for_each(V.begin(), B.end(), deleter<Interval>); |
143 | template <class T> |
144 | inline void deleter(T *Ptr) { |
145 | delete Ptr; |
146 | } |
147 | |
148 | //===----------------------------------------------------------------------===// |
149 | // Extra additions to <iterator> |
150 | //===----------------------------------------------------------------------===// |
151 | |
152 | namespace adl_detail { |
153 | |
154 | using std::begin; |
155 | |
156 | template <typename ContainerTy> |
157 | auto adl_begin(ContainerTy &&container) |
158 | -> decltype(begin(std::forward<ContainerTy>(container))) { |
159 | return begin(std::forward<ContainerTy>(container)); |
160 | } |
161 | |
162 | using std::end; |
163 | |
164 | template <typename ContainerTy> |
165 | auto adl_end(ContainerTy &&container) |
166 | -> decltype(end(std::forward<ContainerTy>(container))) { |
167 | return end(std::forward<ContainerTy>(container)); |
168 | } |
169 | |
170 | using std::swap; |
171 | |
172 | template <typename T> |
173 | void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(), |
174 | std::declval<T>()))) { |
175 | swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
176 | } |
177 | |
178 | } // end namespace adl_detail |
179 | |
180 | template <typename ContainerTy> |
181 | auto adl_begin(ContainerTy &&container) |
182 | -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) { |
183 | return adl_detail::adl_begin(std::forward<ContainerTy>(container)); |
184 | } |
185 | |
186 | template <typename ContainerTy> |
187 | auto adl_end(ContainerTy &&container) |
188 | -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) { |
189 | return adl_detail::adl_end(std::forward<ContainerTy>(container)); |
190 | } |
191 | |
192 | template <typename T> |
193 | void adl_swap(T &&lhs, T &&rhs) noexcept( |
194 | noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) { |
195 | adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
196 | } |
197 | |
198 | // mapped_iterator - This is a simple iterator adapter that causes a function to |
199 | // be applied whenever operator* is invoked on the iterator. |
200 | |
201 | template <typename ItTy, typename FuncTy, |
202 | typename FuncReturnTy = |
203 | decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))> |
204 | class mapped_iterator |
205 | : public iterator_adaptor_base< |
206 | mapped_iterator<ItTy, FuncTy>, ItTy, |
207 | typename std::iterator_traits<ItTy>::iterator_category, |
208 | typename std::remove_reference<FuncReturnTy>::type> { |
209 | public: |
210 | mapped_iterator(ItTy U, FuncTy F) |
211 | : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} |
212 | |
213 | ItTy getCurrent() { return this->I; } |
214 | |
215 | FuncReturnTy operator*() { return F(*this->I); } |
216 | |
217 | private: |
218 | FuncTy F; |
219 | }; |
220 | |
221 | // map_iterator - Provide a convenient way to create mapped_iterators, just like |
222 | // make_pair is useful for creating pairs... |
223 | template <class ItTy, class FuncTy> |
224 | inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) { |
225 | return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F)); |
226 | } |
227 | |
228 | /// Helper to determine if type T has a member called rbegin(). |
229 | template <typename Ty> class has_rbegin_impl { |
230 | using yes = char[1]; |
231 | using no = char[2]; |
232 | |
233 | template <typename Inner> |
234 | static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); |
235 | |
236 | template <typename> |
237 | static no& test(...); |
238 | |
239 | public: |
240 | static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); |
241 | }; |
242 | |
243 | /// Metafunction to determine if T& or T has a member called rbegin(). |
244 | template <typename Ty> |
245 | struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { |
246 | }; |
247 | |
248 | // Returns an iterator_range over the given container which iterates in reverse. |
249 | // Note that the container must have rbegin()/rend() methods for this to work. |
250 | template <typename ContainerTy> |
251 | auto reverse(ContainerTy &&C, |
252 | typename std::enable_if<has_rbegin<ContainerTy>::value>::type * = |
253 | nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { |
254 | return make_range(C.rbegin(), C.rend()); |
255 | } |
256 | |
257 | // Returns a std::reverse_iterator wrapped around the given iterator. |
258 | template <typename IteratorTy> |
259 | std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { |
260 | return std::reverse_iterator<IteratorTy>(It); |
261 | } |
262 | |
263 | // Returns an iterator_range over the given container which iterates in reverse. |
264 | // Note that the container must have begin()/end() methods which return |
265 | // bidirectional iterators for this to work. |
266 | template <typename ContainerTy> |
267 | auto reverse( |
268 | ContainerTy &&C, |
269 | typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr) |
270 | -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), |
271 | llvm::make_reverse_iterator(std::begin(C)))) { |
272 | return make_range(llvm::make_reverse_iterator(std::end(C)), |
273 | llvm::make_reverse_iterator(std::begin(C))); |
274 | } |
275 | |
276 | /// An iterator adaptor that filters the elements of given inner iterators. |
277 | /// |
278 | /// The predicate parameter should be a callable object that accepts the wrapped |
279 | /// iterator's reference type and returns a bool. When incrementing or |
280 | /// decrementing the iterator, it will call the predicate on each element and |
281 | /// skip any where it returns false. |
282 | /// |
283 | /// \code |
284 | /// int A[] = { 1, 2, 3, 4 }; |
285 | /// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); |
286 | /// // R contains { 1, 3 }. |
287 | /// \endcode |
288 | /// |
289 | /// Note: filter_iterator_base implements support for forward iteration. |
290 | /// filter_iterator_impl exists to provide support for bidirectional iteration, |
291 | /// conditional on whether the wrapped iterator supports it. |
292 | template <typename WrappedIteratorT, typename PredicateT, typename IterTag> |
293 | class filter_iterator_base |
294 | : public iterator_adaptor_base< |
295 | filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, |
296 | WrappedIteratorT, |
297 | typename std::common_type< |
298 | IterTag, typename std::iterator_traits< |
299 | WrappedIteratorT>::iterator_category>::type> { |
300 | using BaseT = iterator_adaptor_base< |
301 | filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, |
302 | WrappedIteratorT, |
303 | typename std::common_type< |
304 | IterTag, typename std::iterator_traits< |
305 | WrappedIteratorT>::iterator_category>::type>; |
306 | |
307 | protected: |
308 | WrappedIteratorT End; |
309 | PredicateT Pred; |
310 | |
311 | void findNextValid() { |
312 | while (this->I != End && !Pred(*this->I)) |
313 | BaseT::operator++(); |
314 | } |
315 | |
316 | // Construct the iterator. The begin iterator needs to know where the end |
317 | // is, so that it can properly stop when it gets there. The end iterator only |
318 | // needs the predicate to support bidirectional iteration. |
319 | filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End, |
320 | PredicateT Pred) |
321 | : BaseT(Begin), End(End), Pred(Pred) { |
322 | findNextValid(); |
323 | } |
324 | |
325 | public: |
326 | using BaseT::operator++; |
327 | |
328 | filter_iterator_base &operator++() { |
329 | BaseT::operator++(); |
330 | findNextValid(); |
331 | return *this; |
332 | } |
333 | }; |
334 | |
335 | /// Specialization of filter_iterator_base for forward iteration only. |
336 | template <typename WrappedIteratorT, typename PredicateT, |
337 | typename IterTag = std::forward_iterator_tag> |
338 | class filter_iterator_impl |
339 | : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> { |
340 | using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>; |
341 | |
342 | public: |
343 | filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, |
344 | PredicateT Pred) |
345 | : BaseT(Begin, End, Pred) {} |
346 | }; |
347 | |
348 | /// Specialization of filter_iterator_base for bidirectional iteration. |
349 | template <typename WrappedIteratorT, typename PredicateT> |
350 | class filter_iterator_impl<WrappedIteratorT, PredicateT, |
351 | std::bidirectional_iterator_tag> |
352 | : public filter_iterator_base<WrappedIteratorT, PredicateT, |
353 | std::bidirectional_iterator_tag> { |
354 | using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, |
355 | std::bidirectional_iterator_tag>; |
356 | void findPrevValid() { |
357 | while (!this->Pred(*this->I)) |
358 | BaseT::operator--(); |
359 | } |
360 | |
361 | public: |
362 | using BaseT::operator--; |
363 | |
364 | filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, |
365 | PredicateT Pred) |
366 | : BaseT(Begin, End, Pred) {} |
367 | |
368 | filter_iterator_impl &operator--() { |
369 | BaseT::operator--(); |
370 | findPrevValid(); |
371 | return *this; |
372 | } |
373 | }; |
374 | |
375 | namespace detail { |
376 | |
377 | template <bool is_bidirectional> struct fwd_or_bidi_tag_impl { |
378 | using type = std::forward_iterator_tag; |
379 | }; |
380 | |
381 | template <> struct fwd_or_bidi_tag_impl<true> { |
382 | using type = std::bidirectional_iterator_tag; |
383 | }; |
384 | |
385 | /// Helper which sets its type member to forward_iterator_tag if the category |
386 | /// of \p IterT does not derive from bidirectional_iterator_tag, and to |
387 | /// bidirectional_iterator_tag otherwise. |
388 | template <typename IterT> struct fwd_or_bidi_tag { |
389 | using type = typename fwd_or_bidi_tag_impl<std::is_base_of< |
390 | std::bidirectional_iterator_tag, |
391 | typename std::iterator_traits<IterT>::iterator_category>::value>::type; |
392 | }; |
393 | |
394 | } // namespace detail |
395 | |
396 | /// Defines filter_iterator to a suitable specialization of |
397 | /// filter_iterator_impl, based on the underlying iterator's category. |
398 | template <typename WrappedIteratorT, typename PredicateT> |
399 | using filter_iterator = filter_iterator_impl< |
400 | WrappedIteratorT, PredicateT, |
401 | typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>; |
402 | |
403 | /// Convenience function that takes a range of elements and a predicate, |
404 | /// and return a new filter_iterator range. |
405 | /// |
406 | /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the |
407 | /// lifetime of that temporary is not kept by the returned range object, and the |
408 | /// temporary is going to be dropped on the floor after the make_iterator_range |
409 | /// full expression that contains this function call. |
410 | template <typename RangeT, typename PredicateT> |
411 | iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> |
412 | make_filter_range(RangeT &&Range, PredicateT Pred) { |
413 | using FilterIteratorT = |
414 | filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; |
415 | return make_range( |
416 | FilterIteratorT(std::begin(std::forward<RangeT>(Range)), |
417 | std::end(std::forward<RangeT>(Range)), Pred), |
418 | FilterIteratorT(std::end(std::forward<RangeT>(Range)), |
419 | std::end(std::forward<RangeT>(Range)), Pred)); |
420 | } |
421 | |
422 | /// A pseudo-iterator adaptor that is designed to implement "early increment" |
423 | /// style loops. |
424 | /// |
425 | /// This is *not a normal iterator* and should almost never be used directly. It |
426 | /// is intended primarily to be used with range based for loops and some range |
427 | /// algorithms. |
428 | /// |
429 | /// The iterator isn't quite an `OutputIterator` or an `InputIterator` but |
430 | /// somewhere between them. The constraints of these iterators are: |
431 | /// |
432 | /// - On construction or after being incremented, it is comparable and |
433 | /// dereferencable. It is *not* incrementable. |
434 | /// - After being dereferenced, it is neither comparable nor dereferencable, it |
435 | /// is only incrementable. |
436 | /// |
437 | /// This means you can only dereference the iterator once, and you can only |
438 | /// increment it once between dereferences. |
439 | template <typename WrappedIteratorT> |
440 | class early_inc_iterator_impl |
441 | : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, |
442 | WrappedIteratorT, std::input_iterator_tag> { |
443 | using BaseT = |
444 | iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, |
445 | WrappedIteratorT, std::input_iterator_tag>; |
446 | |
447 | using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer; |
448 | |
449 | protected: |
450 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
451 | bool IsEarlyIncremented = false; |
452 | #endif |
453 | |
454 | public: |
455 | early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {} |
456 | |
457 | using BaseT::operator*; |
458 | typename BaseT::reference operator*() { |
459 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
460 | assert(!IsEarlyIncremented && "Cannot dereference twice!")((!IsEarlyIncremented && "Cannot dereference twice!") ? static_cast<void> (0) : __assert_fail ("!IsEarlyIncremented && \"Cannot dereference twice!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 460, __PRETTY_FUNCTION__)); |
461 | IsEarlyIncremented = true; |
462 | #endif |
463 | return *(this->I)++; |
464 | } |
465 | |
466 | using BaseT::operator++; |
467 | early_inc_iterator_impl &operator++() { |
468 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
469 | assert(IsEarlyIncremented && "Cannot increment before dereferencing!")((IsEarlyIncremented && "Cannot increment before dereferencing!" ) ? static_cast<void> (0) : __assert_fail ("IsEarlyIncremented && \"Cannot increment before dereferencing!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 469, __PRETTY_FUNCTION__)); |
470 | IsEarlyIncremented = false; |
471 | #endif |
472 | return *this; |
473 | } |
474 | |
475 | using BaseT::operator==; |
476 | bool operator==(const early_inc_iterator_impl &RHS) const { |
477 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
478 | assert(!IsEarlyIncremented && "Cannot compare after dereferencing!")((!IsEarlyIncremented && "Cannot compare after dereferencing!" ) ? static_cast<void> (0) : __assert_fail ("!IsEarlyIncremented && \"Cannot compare after dereferencing!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 478, __PRETTY_FUNCTION__)); |
479 | #endif |
480 | return BaseT::operator==(RHS); |
481 | } |
482 | }; |
483 | |
484 | /// Make a range that does early increment to allow mutation of the underlying |
485 | /// range without disrupting iteration. |
486 | /// |
487 | /// The underlying iterator will be incremented immediately after it is |
488 | /// dereferenced, allowing deletion of the current node or insertion of nodes to |
489 | /// not disrupt iteration provided they do not invalidate the *next* iterator -- |
490 | /// the current iterator can be invalidated. |
491 | /// |
492 | /// This requires a very exact pattern of use that is only really suitable to |
493 | /// range based for loops and other range algorithms that explicitly guarantee |
494 | /// to dereference exactly once each element, and to increment exactly once each |
495 | /// element. |
496 | template <typename RangeT> |
497 | iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>> |
498 | make_early_inc_range(RangeT &&Range) { |
499 | using EarlyIncIteratorT = |
500 | early_inc_iterator_impl<detail::IterOfRange<RangeT>>; |
501 | return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))), |
502 | EarlyIncIteratorT(std::end(std::forward<RangeT>(Range)))); |
503 | } |
504 | |
505 | // forward declarations required by zip_shortest/zip_first |
506 | template <typename R, typename UnaryPredicate> |
507 | bool all_of(R &&range, UnaryPredicate P); |
508 | |
509 | template <size_t... I> struct index_sequence; |
510 | |
511 | template <class... Ts> struct index_sequence_for; |
512 | |
513 | namespace detail { |
514 | |
515 | using std::declval; |
516 | |
517 | // We have to alias this since inlining the actual type at the usage site |
518 | // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. |
519 | template<typename... Iters> struct ZipTupleType { |
520 | using type = std::tuple<decltype(*declval<Iters>())...>; |
521 | }; |
522 | |
523 | template <typename ZipType, typename... Iters> |
524 | using zip_traits = iterator_facade_base< |
525 | ZipType, typename std::common_type<std::bidirectional_iterator_tag, |
526 | typename std::iterator_traits< |
527 | Iters>::iterator_category...>::type, |
528 | // ^ TODO: Implement random access methods. |
529 | typename ZipTupleType<Iters...>::type, |
530 | typename std::iterator_traits<typename std::tuple_element< |
531 | 0, std::tuple<Iters...>>::type>::difference_type, |
532 | // ^ FIXME: This follows boost::make_zip_iterator's assumption that all |
533 | // inner iterators have the same difference_type. It would fail if, for |
534 | // instance, the second field's difference_type were non-numeric while the |
535 | // first is. |
536 | typename ZipTupleType<Iters...>::type *, |
537 | typename ZipTupleType<Iters...>::type>; |
538 | |
539 | template <typename ZipType, typename... Iters> |
540 | struct zip_common : public zip_traits<ZipType, Iters...> { |
541 | using Base = zip_traits<ZipType, Iters...>; |
542 | using value_type = typename Base::value_type; |
543 | |
544 | std::tuple<Iters...> iterators; |
545 | |
546 | protected: |
547 | template <size_t... Ns> value_type deref(index_sequence<Ns...>) const { |
548 | return value_type(*std::get<Ns>(iterators)...); |
549 | } |
550 | |
551 | template <size_t... Ns> |
552 | decltype(iterators) tup_inc(index_sequence<Ns...>) const { |
553 | return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...); |
554 | } |
555 | |
556 | template <size_t... Ns> |
557 | decltype(iterators) tup_dec(index_sequence<Ns...>) const { |
558 | return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...); |
559 | } |
560 | |
561 | public: |
562 | zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} |
563 | |
564 | value_type operator*() { return deref(index_sequence_for<Iters...>{}); } |
565 | |
566 | const value_type operator*() const { |
567 | return deref(index_sequence_for<Iters...>{}); |
568 | } |
569 | |
570 | ZipType &operator++() { |
571 | iterators = tup_inc(index_sequence_for<Iters...>{}); |
572 | return *reinterpret_cast<ZipType *>(this); |
573 | } |
574 | |
575 | ZipType &operator--() { |
576 | static_assert(Base::IsBidirectional, |
577 | "All inner iterators must be at least bidirectional."); |
578 | iterators = tup_dec(index_sequence_for<Iters...>{}); |
579 | return *reinterpret_cast<ZipType *>(this); |
580 | } |
581 | }; |
582 | |
583 | template <typename... Iters> |
584 | struct zip_first : public zip_common<zip_first<Iters...>, Iters...> { |
585 | using Base = zip_common<zip_first<Iters...>, Iters...>; |
586 | |
587 | bool operator==(const zip_first<Iters...> &other) const { |
588 | return std::get<0>(this->iterators) == std::get<0>(other.iterators); |
589 | } |
590 | |
591 | zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} |
592 | }; |
593 | |
594 | template <typename... Iters> |
595 | class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> { |
596 | template <size_t... Ns> |
597 | bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const { |
598 | return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) != |
599 | std::get<Ns>(other.iterators)...}, |
600 | identity<bool>{}); |
601 | } |
602 | |
603 | public: |
604 | using Base = zip_common<zip_shortest<Iters...>, Iters...>; |
605 | |
606 | zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} |
607 | |
608 | bool operator==(const zip_shortest<Iters...> &other) const { |
609 | return !test(other, index_sequence_for<Iters...>{}); |
610 | } |
611 | }; |
612 | |
613 | template <template <typename...> class ItType, typename... Args> class zippy { |
614 | public: |
615 | using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>; |
616 | using iterator_category = typename iterator::iterator_category; |
617 | using value_type = typename iterator::value_type; |
618 | using difference_type = typename iterator::difference_type; |
619 | using pointer = typename iterator::pointer; |
620 | using reference = typename iterator::reference; |
621 | |
622 | private: |
623 | std::tuple<Args...> ts; |
624 | |
625 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const { |
626 | return iterator(std::begin(std::get<Ns>(ts))...); |
627 | } |
628 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const { |
629 | return iterator(std::end(std::get<Ns>(ts))...); |
630 | } |
631 | |
632 | public: |
633 | zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} |
634 | |
635 | iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); } |
636 | iterator end() const { return end_impl(index_sequence_for<Args...>{}); } |
637 | }; |
638 | |
639 | } // end namespace detail |
640 | |
641 | /// zip iterator for two or more iteratable types. |
642 | template <typename T, typename U, typename... Args> |
643 | detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u, |
644 | Args &&... args) { |
645 | return detail::zippy<detail::zip_shortest, T, U, Args...>( |
646 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); |
647 | } |
648 | |
649 | /// zip iterator that, for the sake of efficiency, assumes the first iteratee to |
650 | /// be the shortest. |
651 | template <typename T, typename U, typename... Args> |
652 | detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, |
653 | Args &&... args) { |
654 | return detail::zippy<detail::zip_first, T, U, Args...>( |
655 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); |
656 | } |
657 | |
658 | /// Iterator wrapper that concatenates sequences together. |
659 | /// |
660 | /// This can concatenate different iterators, even with different types, into |
661 | /// a single iterator provided the value types of all the concatenated |
662 | /// iterators expose `reference` and `pointer` types that can be converted to |
663 | /// `ValueT &` and `ValueT *` respectively. It doesn't support more |
664 | /// interesting/customized pointer or reference types. |
665 | /// |
666 | /// Currently this only supports forward or higher iterator categories as |
667 | /// inputs and always exposes a forward iterator interface. |
668 | template <typename ValueT, typename... IterTs> |
669 | class concat_iterator |
670 | : public iterator_facade_base<concat_iterator<ValueT, IterTs...>, |
671 | std::forward_iterator_tag, ValueT> { |
672 | using BaseT = typename concat_iterator::iterator_facade_base; |
673 | |
674 | /// We store both the current and end iterators for each concatenated |
675 | /// sequence in a tuple of pairs. |
676 | /// |
677 | /// Note that something like iterator_range seems nice at first here, but the |
678 | /// range properties are of little benefit and end up getting in the way |
679 | /// because we need to do mutation on the current iterators. |
680 | std::tuple<IterTs...> Begins; |
681 | std::tuple<IterTs...> Ends; |
682 | |
683 | /// Attempts to increment a specific iterator. |
684 | /// |
685 | /// Returns true if it was able to increment the iterator. Returns false if |
686 | /// the iterator is already at the end iterator. |
687 | template <size_t Index> bool incrementHelper() { |
688 | auto &Begin = std::get<Index>(Begins); |
689 | auto &End = std::get<Index>(Ends); |
690 | if (Begin == End) |
691 | return false; |
692 | |
693 | ++Begin; |
694 | return true; |
695 | } |
696 | |
697 | /// Increments the first non-end iterator. |
698 | /// |
699 | /// It is an error to call this with all iterators at the end. |
700 | template <size_t... Ns> void increment(index_sequence<Ns...>) { |
701 | // Build a sequence of functions to increment each iterator if possible. |
702 | bool (concat_iterator::*IncrementHelperFns[])() = { |
703 | &concat_iterator::incrementHelper<Ns>...}; |
704 | |
705 | // Loop over them, and stop as soon as we succeed at incrementing one. |
706 | for (auto &IncrementHelperFn : IncrementHelperFns) |
707 | if ((this->*IncrementHelperFn)()) |
708 | return; |
709 | |
710 | llvm_unreachable("Attempted to increment an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to increment an end concat iterator!" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 710); |
711 | } |
712 | |
713 | /// Returns null if the specified iterator is at the end. Otherwise, |
714 | /// dereferences the iterator and returns the address of the resulting |
715 | /// reference. |
716 | template <size_t Index> ValueT *getHelper() const { |
717 | auto &Begin = std::get<Index>(Begins); |
718 | auto &End = std::get<Index>(Ends); |
719 | if (Begin == End) |
720 | return nullptr; |
721 | |
722 | return &*Begin; |
723 | } |
724 | |
725 | /// Finds the first non-end iterator, dereferences, and returns the resulting |
726 | /// reference. |
727 | /// |
728 | /// It is an error to call this with all iterators at the end. |
729 | template <size_t... Ns> ValueT &get(index_sequence<Ns...>) const { |
730 | // Build a sequence of functions to get from iterator if possible. |
731 | ValueT *(concat_iterator::*GetHelperFns[])() const = { |
732 | &concat_iterator::getHelper<Ns>...}; |
733 | |
734 | // Loop over them, and return the first result we find. |
735 | for (auto &GetHelperFn : GetHelperFns) |
736 | if (ValueT *P = (this->*GetHelperFn)()) |
737 | return *P; |
738 | |
739 | llvm_unreachable("Attempted to get a pointer from an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to get a pointer from an end concat iterator!" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 739); |
740 | } |
741 | |
742 | public: |
743 | /// Constructs an iterator from a squence of ranges. |
744 | /// |
745 | /// We need the full range to know how to switch between each of the |
746 | /// iterators. |
747 | template <typename... RangeTs> |
748 | explicit concat_iterator(RangeTs &&... Ranges) |
749 | : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {} |
750 | |
751 | using BaseT::operator++; |
752 | |
753 | concat_iterator &operator++() { |
754 | increment(index_sequence_for<IterTs...>()); |
755 | return *this; |
756 | } |
757 | |
758 | ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); } |
759 | |
760 | bool operator==(const concat_iterator &RHS) const { |
761 | return Begins == RHS.Begins && Ends == RHS.Ends; |
762 | } |
763 | }; |
764 | |
765 | namespace detail { |
766 | |
767 | /// Helper to store a sequence of ranges being concatenated and access them. |
768 | /// |
769 | /// This is designed to facilitate providing actual storage when temporaries |
770 | /// are passed into the constructor such that we can use it as part of range |
771 | /// based for loops. |
772 | template <typename ValueT, typename... RangeTs> class concat_range { |
773 | public: |
774 | using iterator = |
775 | concat_iterator<ValueT, |
776 | decltype(std::begin(std::declval<RangeTs &>()))...>; |
777 | |
778 | private: |
779 | std::tuple<RangeTs...> Ranges; |
780 | |
781 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) { |
782 | return iterator(std::get<Ns>(Ranges)...); |
783 | } |
784 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) { |
785 | return iterator(make_range(std::end(std::get<Ns>(Ranges)), |
786 | std::end(std::get<Ns>(Ranges)))...); |
787 | } |
788 | |
789 | public: |
790 | concat_range(RangeTs &&... Ranges) |
791 | : Ranges(std::forward<RangeTs>(Ranges)...) {} |
792 | |
793 | iterator begin() { return begin_impl(index_sequence_for<RangeTs...>{}); } |
794 | iterator end() { return end_impl(index_sequence_for<RangeTs...>{}); } |
795 | }; |
796 | |
797 | } // end namespace detail |
798 | |
799 | /// Concatenated range across two or more ranges. |
800 | /// |
801 | /// The desired value type must be explicitly specified. |
802 | template <typename ValueT, typename... RangeTs> |
803 | detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { |
804 | static_assert(sizeof...(RangeTs) > 1, |
805 | "Need more than one range to concatenate!"); |
806 | return detail::concat_range<ValueT, RangeTs...>( |
807 | std::forward<RangeTs>(Ranges)...); |
808 | } |
809 | |
810 | //===----------------------------------------------------------------------===// |
811 | // Extra additions to <utility> |
812 | //===----------------------------------------------------------------------===// |
813 | |
814 | /// Function object to check whether the first component of a std::pair |
815 | /// compares less than the first component of another std::pair. |
816 | struct less_first { |
817 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { |
818 | return lhs.first < rhs.first; |
819 | } |
820 | }; |
821 | |
822 | /// Function object to check whether the second component of a std::pair |
823 | /// compares less than the second component of another std::pair. |
824 | struct less_second { |
825 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { |
826 | return lhs.second < rhs.second; |
827 | } |
828 | }; |
829 | |
830 | /// \brief Function object to apply a binary function to the first component of |
831 | /// a std::pair. |
832 | template<typename FuncTy> |
833 | struct on_first { |
834 | FuncTy func; |
835 | |
836 | template <typename T> |
837 | auto operator()(const T &lhs, const T &rhs) const |
838 | -> decltype(func(lhs.first, rhs.first)) { |
839 | return func(lhs.first, rhs.first); |
840 | } |
841 | }; |
842 | |
843 | // A subset of N3658. More stuff can be added as-needed. |
844 | |
845 | /// Represents a compile-time sequence of integers. |
846 | template <class T, T... I> struct integer_sequence { |
847 | using value_type = T; |
848 | |
849 | static constexpr size_t size() { return sizeof...(I); } |
850 | }; |
851 | |
852 | /// Alias for the common case of a sequence of size_ts. |
853 | template <size_t... I> |
854 | struct index_sequence : integer_sequence<std::size_t, I...> {}; |
855 | |
856 | template <std::size_t N, std::size_t... I> |
857 | struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {}; |
858 | template <std::size_t... I> |
859 | struct build_index_impl<0, I...> : index_sequence<I...> {}; |
860 | |
861 | /// Creates a compile-time integer sequence for a parameter pack. |
862 | template <class... Ts> |
863 | struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; |
864 | |
865 | /// Utility type to build an inheritance chain that makes it easy to rank |
866 | /// overload candidates. |
867 | template <int N> struct rank : rank<N - 1> {}; |
868 | template <> struct rank<0> {}; |
869 | |
870 | /// traits class for checking whether type T is one of any of the given |
871 | /// types in the variadic list. |
872 | template <typename T, typename... Ts> struct is_one_of { |
873 | static const bool value = false; |
874 | }; |
875 | |
876 | template <typename T, typename U, typename... Ts> |
877 | struct is_one_of<T, U, Ts...> { |
878 | static const bool value = |
879 | std::is_same<T, U>::value || is_one_of<T, Ts...>::value; |
880 | }; |
881 | |
882 | /// traits class for checking whether type T is a base class for all |
883 | /// the given types in the variadic list. |
884 | template <typename T, typename... Ts> struct are_base_of { |
885 | static const bool value = true; |
886 | }; |
887 | |
888 | template <typename T, typename U, typename... Ts> |
889 | struct are_base_of<T, U, Ts...> { |
890 | static const bool value = |
891 | std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value; |
892 | }; |
893 | |
894 | //===----------------------------------------------------------------------===// |
895 | // Extra additions for arrays |
896 | //===----------------------------------------------------------------------===// |
897 | |
898 | /// Find the length of an array. |
899 | template <class T, std::size_t N> |
900 | constexpr inline size_t array_lengthof(T (&)[N]) { |
901 | return N; |
902 | } |
903 | |
904 | /// Adapt std::less<T> for array_pod_sort. |
905 | template<typename T> |
906 | inline int array_pod_sort_comparator(const void *P1, const void *P2) { |
907 | if (std::less<T>()(*reinterpret_cast<const T*>(P1), |
908 | *reinterpret_cast<const T*>(P2))) |
909 | return -1; |
910 | if (std::less<T>()(*reinterpret_cast<const T*>(P2), |
911 | *reinterpret_cast<const T*>(P1))) |
912 | return 1; |
913 | return 0; |
914 | } |
915 | |
916 | /// get_array_pod_sort_comparator - This is an internal helper function used to |
917 | /// get type deduction of T right. |
918 | template<typename T> |
919 | inline int (*get_array_pod_sort_comparator(const T &)) |
920 | (const void*, const void*) { |
921 | return array_pod_sort_comparator<T>; |
922 | } |
923 | |
924 | /// array_pod_sort - This sorts an array with the specified start and end |
925 | /// extent. This is just like std::sort, except that it calls qsort instead of |
926 | /// using an inlined template. qsort is slightly slower than std::sort, but |
927 | /// most sorts are not performance critical in LLVM and std::sort has to be |
928 | /// template instantiated for each type, leading to significant measured code |
929 | /// bloat. This function should generally be used instead of std::sort where |
930 | /// possible. |
931 | /// |
932 | /// This function assumes that you have simple POD-like types that can be |
933 | /// compared with std::less and can be moved with memcpy. If this isn't true, |
934 | /// you should use std::sort. |
935 | /// |
936 | /// NOTE: If qsort_r were portable, we could allow a custom comparator and |
937 | /// default to std::less. |
938 | template<class IteratorTy> |
939 | inline void array_pod_sort(IteratorTy Start, IteratorTy End) { |
940 | // Don't inefficiently call qsort with one element or trigger undefined |
941 | // behavior with an empty sequence. |
942 | auto NElts = End - Start; |
943 | if (NElts <= 1) return; |
944 | #ifdef EXPENSIVE_CHECKS |
945 | std::mt19937 Generator(std::random_device{}()); |
946 | std::shuffle(Start, End, Generator); |
947 | #endif |
948 | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); |
949 | } |
950 | |
951 | template <class IteratorTy> |
952 | inline void array_pod_sort( |
953 | IteratorTy Start, IteratorTy End, |
954 | int (*Compare)( |
955 | const typename std::iterator_traits<IteratorTy>::value_type *, |
956 | const typename std::iterator_traits<IteratorTy>::value_type *)) { |
957 | // Don't inefficiently call qsort with one element or trigger undefined |
958 | // behavior with an empty sequence. |
959 | auto NElts = End - Start; |
960 | if (NElts <= 1) return; |
961 | #ifdef EXPENSIVE_CHECKS |
962 | std::mt19937 Generator(std::random_device{}()); |
963 | std::shuffle(Start, End, Generator); |
964 | #endif |
965 | qsort(&*Start, NElts, sizeof(*Start), |
966 | reinterpret_cast<int (*)(const void *, const void *)>(Compare)); |
967 | } |
968 | |
969 | // Provide wrappers to std::sort which shuffle the elements before sorting |
970 | // to help uncover non-deterministic behavior (PR35135). |
971 | template <typename IteratorTy> |
972 | inline void sort(IteratorTy Start, IteratorTy End) { |
973 | #ifdef EXPENSIVE_CHECKS |
974 | std::mt19937 Generator(std::random_device{}()); |
975 | std::shuffle(Start, End, Generator); |
976 | #endif |
977 | std::sort(Start, End); |
978 | } |
979 | |
980 | template <typename Container> inline void sort(Container &&C) { |
981 | llvm::sort(adl_begin(C), adl_end(C)); |
982 | } |
983 | |
984 | template <typename IteratorTy, typename Compare> |
985 | inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { |
986 | #ifdef EXPENSIVE_CHECKS |
987 | std::mt19937 Generator(std::random_device{}()); |
988 | std::shuffle(Start, End, Generator); |
989 | #endif |
990 | std::sort(Start, End, Comp); |
991 | } |
992 | |
993 | template <typename Container, typename Compare> |
994 | inline void sort(Container &&C, Compare Comp) { |
995 | llvm::sort(adl_begin(C), adl_end(C), Comp); |
996 | } |
997 | |
998 | //===----------------------------------------------------------------------===// |
999 | // Extra additions to <algorithm> |
1000 | //===----------------------------------------------------------------------===// |
1001 | |
1002 | /// For a container of pointers, deletes the pointers and then clears the |
1003 | /// container. |
1004 | template<typename Container> |
1005 | void DeleteContainerPointers(Container &C) { |
1006 | for (auto V : C) |
1007 | delete V; |
1008 | C.clear(); |
1009 | } |
1010 | |
1011 | /// In a container of pairs (usually a map) whose second element is a pointer, |
1012 | /// deletes the second elements and then clears the container. |
1013 | template<typename Container> |
1014 | void DeleteContainerSeconds(Container &C) { |
1015 | for (auto &V : C) |
1016 | delete V.second; |
1017 | C.clear(); |
1018 | } |
1019 | |
1020 | /// Get the size of a range. This is a wrapper function around std::distance |
1021 | /// which is only enabled when the operation is O(1). |
1022 | template <typename R> |
1023 | auto size(R &&Range, typename std::enable_if< |
1024 | std::is_same<typename std::iterator_traits<decltype( |
1025 | Range.begin())>::iterator_category, |
1026 | std::random_access_iterator_tag>::value, |
1027 | void>::type * = nullptr) |
1028 | -> decltype(std::distance(Range.begin(), Range.end())) { |
1029 | return std::distance(Range.begin(), Range.end()); |
1030 | } |
1031 | |
1032 | /// Provide wrappers to std::for_each which take ranges instead of having to |
1033 | /// pass begin/end explicitly. |
1034 | template <typename R, typename UnaryPredicate> |
1035 | UnaryPredicate for_each(R &&Range, UnaryPredicate P) { |
1036 | return std::for_each(adl_begin(Range), adl_end(Range), P); |
1037 | } |
1038 | |
1039 | /// Provide wrappers to std::all_of which take ranges instead of having to pass |
1040 | /// begin/end explicitly. |
1041 | template <typename R, typename UnaryPredicate> |
1042 | bool all_of(R &&Range, UnaryPredicate P) { |
1043 | return std::all_of(adl_begin(Range), adl_end(Range), P); |
1044 | } |
1045 | |
1046 | /// Provide wrappers to std::any_of which take ranges instead of having to pass |
1047 | /// begin/end explicitly. |
1048 | template <typename R, typename UnaryPredicate> |
1049 | bool any_of(R &&Range, UnaryPredicate P) { |
1050 | return std::any_of(adl_begin(Range), adl_end(Range), P); |
1051 | } |
1052 | |
1053 | /// Provide wrappers to std::none_of which take ranges instead of having to pass |
1054 | /// begin/end explicitly. |
1055 | template <typename R, typename UnaryPredicate> |
1056 | bool none_of(R &&Range, UnaryPredicate P) { |
1057 | return std::none_of(adl_begin(Range), adl_end(Range), P); |
1058 | } |
1059 | |
1060 | /// Provide wrappers to std::find which take ranges instead of having to pass |
1061 | /// begin/end explicitly. |
1062 | template <typename R, typename T> |
1063 | auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) { |
1064 | return std::find(adl_begin(Range), adl_end(Range), Val); |
1065 | } |
1066 | |
1067 | /// Provide wrappers to std::find_if which take ranges instead of having to pass |
1068 | /// begin/end explicitly. |
1069 | template <typename R, typename UnaryPredicate> |
1070 | auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
1071 | return std::find_if(adl_begin(Range), adl_end(Range), P); |
1072 | } |
1073 | |
1074 | template <typename R, typename UnaryPredicate> |
1075 | auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
1076 | return std::find_if_not(adl_begin(Range), adl_end(Range), P); |
1077 | } |
1078 | |
1079 | /// Provide wrappers to std::remove_if which take ranges instead of having to |
1080 | /// pass begin/end explicitly. |
1081 | template <typename R, typename UnaryPredicate> |
1082 | auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
1083 | return std::remove_if(adl_begin(Range), adl_end(Range), P); |
1084 | } |
1085 | |
1086 | /// Provide wrappers to std::copy_if which take ranges instead of having to |
1087 | /// pass begin/end explicitly. |
1088 | template <typename R, typename OutputIt, typename UnaryPredicate> |
1089 | OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { |
1090 | return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); |
1091 | } |
1092 | |
1093 | template <typename R, typename OutputIt> |
1094 | OutputIt copy(R &&Range, OutputIt Out) { |
1095 | return std::copy(adl_begin(Range), adl_end(Range), Out); |
1096 | } |
1097 | |
1098 | /// Wrapper function around std::find to detect if an element exists |
1099 | /// in a container. |
1100 | template <typename R, typename E> |
1101 | bool is_contained(R &&Range, const E &Element) { |
1102 | return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); |
1103 | } |
1104 | |
1105 | /// Wrapper function around std::count to count the number of times an element |
1106 | /// \p Element occurs in the given range \p Range. |
1107 | template <typename R, typename E> |
1108 | auto count(R &&Range, const E &Element) -> |
1109 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { |
1110 | return std::count(adl_begin(Range), adl_end(Range), Element); |
1111 | } |
1112 | |
1113 | /// Wrapper function around std::count_if to count the number of times an |
1114 | /// element satisfying a given predicate occurs in a range. |
1115 | template <typename R, typename UnaryPredicate> |
1116 | auto count_if(R &&Range, UnaryPredicate P) -> |
1117 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { |
1118 | return std::count_if(adl_begin(Range), adl_end(Range), P); |
1119 | } |
1120 | |
1121 | /// Wrapper function around std::transform to apply a function to a range and |
1122 | /// store the result elsewhere. |
1123 | template <typename R, typename OutputIt, typename UnaryPredicate> |
1124 | OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) { |
1125 | return std::transform(adl_begin(Range), adl_end(Range), d_first, P); |
1126 | } |
1127 | |
1128 | /// Provide wrappers to std::partition which take ranges instead of having to |
1129 | /// pass begin/end explicitly. |
1130 | template <typename R, typename UnaryPredicate> |
1131 | auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
1132 | return std::partition(adl_begin(Range), adl_end(Range), P); |
1133 | } |
1134 | |
1135 | /// Provide wrappers to std::lower_bound which take ranges instead of having to |
1136 | /// pass begin/end explicitly. |
1137 | template <typename R, typename ForwardIt> |
1138 | auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { |
1139 | return std::lower_bound(adl_begin(Range), adl_end(Range), I); |
1140 | } |
1141 | |
1142 | template <typename R, typename ForwardIt, typename Compare> |
1143 | auto lower_bound(R &&Range, ForwardIt I, Compare C) |
1144 | -> decltype(adl_begin(Range)) { |
1145 | return std::lower_bound(adl_begin(Range), adl_end(Range), I, C); |
1146 | } |
1147 | |
1148 | /// Provide wrappers to std::upper_bound which take ranges instead of having to |
1149 | /// pass begin/end explicitly. |
1150 | template <typename R, typename ForwardIt> |
1151 | auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { |
1152 | return std::upper_bound(adl_begin(Range), adl_end(Range), I); |
1153 | } |
1154 | |
1155 | template <typename R, typename ForwardIt, typename Compare> |
1156 | auto upper_bound(R &&Range, ForwardIt I, Compare C) |
1157 | -> decltype(adl_begin(Range)) { |
1158 | return std::upper_bound(adl_begin(Range), adl_end(Range), I, C); |
1159 | } |
1160 | /// Wrapper function around std::equal to detect if all elements |
1161 | /// in a container are same. |
1162 | template <typename R> |
1163 | bool is_splat(R &&Range) { |
1164 | size_t range_size = size(Range); |
1165 | return range_size != 0 && (range_size == 1 || |
1166 | std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); |
1167 | } |
1168 | |
1169 | /// Given a range of type R, iterate the entire range and return a |
1170 | /// SmallVector with elements of the vector. This is useful, for example, |
1171 | /// when you want to iterate a range and then sort the results. |
1172 | template <unsigned Size, typename R> |
1173 | SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size> |
1174 | to_vector(R &&Range) { |
1175 | return {adl_begin(Range), adl_end(Range)}; |
1176 | } |
1177 | |
1178 | /// Provide a container algorithm similar to C++ Library Fundamentals v2's |
1179 | /// `erase_if` which is equivalent to: |
1180 | /// |
1181 | /// C.erase(remove_if(C, pred), C.end()); |
1182 | /// |
1183 | /// This version works for any container with an erase method call accepting |
1184 | /// two iterators. |
1185 | template <typename Container, typename UnaryPredicate> |
1186 | void erase_if(Container &C, UnaryPredicate P) { |
1187 | C.erase(remove_if(C, P), C.end()); |
1188 | } |
1189 | |
1190 | //===----------------------------------------------------------------------===// |
1191 | // Extra additions to <memory> |
1192 | //===----------------------------------------------------------------------===// |
1193 | |
1194 | // Implement make_unique according to N3656. |
1195 | |
1196 | /// Constructs a `new T()` with the given args and returns a |
1197 | /// `unique_ptr<T>` which owns the object. |
1198 | /// |
1199 | /// Example: |
1200 | /// |
1201 | /// auto p = make_unique<int>(); |
1202 | /// auto p = make_unique<std::tuple<int, int>>(0, 1); |
1203 | template <class T, class... Args> |
1204 | typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type |
1205 | make_unique(Args &&... args) { |
1206 | return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); |
1207 | } |
1208 | |
1209 | /// Constructs a `new T[n]` with the given args and returns a |
1210 | /// `unique_ptr<T[]>` which owns the object. |
1211 | /// |
1212 | /// \param n size of the new array. |
1213 | /// |
1214 | /// Example: |
1215 | /// |
1216 | /// auto p = make_unique<int[]>(2); // value-initializes the array with 0's. |
1217 | template <class T> |
1218 | typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, |
1219 | std::unique_ptr<T>>::type |
1220 | make_unique(size_t n) { |
1221 | return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); |
1222 | } |
1223 | |
1224 | /// This function isn't used and is only here to provide better compile errors. |
1225 | template <class T, class... Args> |
1226 | typename std::enable_if<std::extent<T>::value != 0>::type |
1227 | make_unique(Args &&...) = delete; |
1228 | |
1229 | struct FreeDeleter { |
1230 | void operator()(void* v) { |
1231 | ::free(v); |
1232 | } |
1233 | }; |
1234 | |
1235 | template<typename First, typename Second> |
1236 | struct pair_hash { |
1237 | size_t operator()(const std::pair<First, Second> &P) const { |
1238 | return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); |
1239 | } |
1240 | }; |
1241 | |
1242 | /// A functor like C++14's std::less<void> in its absence. |
1243 | struct less { |
1244 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { |
1245 | return std::forward<A>(a) < std::forward<B>(b); |
1246 | } |
1247 | }; |
1248 | |
1249 | /// A functor like C++14's std::equal<void> in its absence. |
1250 | struct equal { |
1251 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { |
1252 | return std::forward<A>(a) == std::forward<B>(b); |
1253 | } |
1254 | }; |
1255 | |
1256 | /// Binary functor that adapts to any other binary functor after dereferencing |
1257 | /// operands. |
1258 | template <typename T> struct deref { |
1259 | T func; |
1260 | |
1261 | // Could be further improved to cope with non-derivable functors and |
1262 | // non-binary functors (should be a variadic template member function |
1263 | // operator()). |
1264 | template <typename A, typename B> |
1265 | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { |
1266 | assert(lhs)((lhs) ? static_cast<void> (0) : __assert_fail ("lhs", "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 1266, __PRETTY_FUNCTION__)); |
1267 | assert(rhs)((rhs) ? static_cast<void> (0) : __assert_fail ("rhs", "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 1267, __PRETTY_FUNCTION__)); |
1268 | return func(*lhs, *rhs); |
1269 | } |
1270 | }; |
1271 | |
1272 | namespace detail { |
1273 | |
1274 | template <typename R> class enumerator_iter; |
1275 | |
1276 | template <typename R> struct result_pair { |
1277 | friend class enumerator_iter<R>; |
1278 | |
1279 | result_pair() = default; |
1280 | result_pair(std::size_t Index, IterOfRange<R> Iter) |
1281 | : Index(Index), Iter(Iter) {} |
1282 | |
1283 | result_pair<R> &operator=(const result_pair<R> &Other) { |
1284 | Index = Other.Index; |
1285 | Iter = Other.Iter; |
1286 | return *this; |
1287 | } |
1288 | |
1289 | std::size_t index() const { return Index; } |
1290 | const ValueOfRange<R> &value() const { return *Iter; } |
1291 | ValueOfRange<R> &value() { return *Iter; } |
1292 | |
1293 | private: |
1294 | std::size_t Index = std::numeric_limits<std::size_t>::max(); |
1295 | IterOfRange<R> Iter; |
1296 | }; |
1297 | |
1298 | template <typename R> |
1299 | class enumerator_iter |
1300 | : public iterator_facade_base< |
1301 | enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>, |
1302 | typename std::iterator_traits<IterOfRange<R>>::difference_type, |
1303 | typename std::iterator_traits<IterOfRange<R>>::pointer, |
1304 | typename std::iterator_traits<IterOfRange<R>>::reference> { |
1305 | using result_type = result_pair<R>; |
1306 | |
1307 | public: |
1308 | explicit enumerator_iter(IterOfRange<R> EndIter) |
1309 | : Result(std::numeric_limits<size_t>::max(), EndIter) {} |
1310 | |
1311 | enumerator_iter(std::size_t Index, IterOfRange<R> Iter) |
1312 | : Result(Index, Iter) {} |
1313 | |
1314 | result_type &operator*() { return Result; } |
1315 | const result_type &operator*() const { return Result; } |
1316 | |
1317 | enumerator_iter<R> &operator++() { |
1318 | assert(Result.Index != std::numeric_limits<size_t>::max())((Result.Index != std::numeric_limits<size_t>::max()) ? static_cast<void> (0) : __assert_fail ("Result.Index != std::numeric_limits<size_t>::max()" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/ADT/STLExtras.h" , 1318, __PRETTY_FUNCTION__)); |
1319 | ++Result.Iter; |
1320 | ++Result.Index; |
1321 | return *this; |
1322 | } |
1323 | |
1324 | bool operator==(const enumerator_iter<R> &RHS) const { |
1325 | // Don't compare indices here, only iterators. It's possible for an end |
1326 | // iterator to have different indices depending on whether it was created |
1327 | // by calling std::end() versus incrementing a valid iterator. |
1328 | return Result.Iter == RHS.Result.Iter; |
1329 | } |
1330 | |
1331 | enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) { |
1332 | Result = Other.Result; |
1333 | return *this; |
1334 | } |
1335 | |
1336 | private: |
1337 | result_type Result; |
1338 | }; |
1339 | |
1340 | template <typename R> class enumerator { |
1341 | public: |
1342 | explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {} |
1343 | |
1344 | enumerator_iter<R> begin() { |
1345 | return enumerator_iter<R>(0, std::begin(TheRange)); |
1346 | } |
1347 | |
1348 | enumerator_iter<R> end() { |
1349 | return enumerator_iter<R>(std::end(TheRange)); |
1350 | } |
1351 | |
1352 | private: |
1353 | R TheRange; |
1354 | }; |
1355 | |
1356 | } // end namespace detail |
1357 | |
1358 | /// Given an input range, returns a new range whose values are are pair (A,B) |
1359 | /// such that A is the 0-based index of the item in the sequence, and B is |
1360 | /// the value from the original sequence. Example: |
1361 | /// |
1362 | /// std::vector<char> Items = {'A', 'B', 'C', 'D'}; |
1363 | /// for (auto X : enumerate(Items)) { |
1364 | /// printf("Item %d - %c\n", X.index(), X.value()); |
1365 | /// } |
1366 | /// |
1367 | /// Output: |
1368 | /// Item 0 - A |
1369 | /// Item 1 - B |
1370 | /// Item 2 - C |
1371 | /// Item 3 - D |
1372 | /// |
1373 | template <typename R> detail::enumerator<R> enumerate(R &&TheRange) { |
1374 | return detail::enumerator<R>(std::forward<R>(TheRange)); |
1375 | } |
1376 | |
1377 | namespace detail { |
1378 | |
1379 | template <typename F, typename Tuple, std::size_t... I> |
1380 | auto apply_tuple_impl(F &&f, Tuple &&t, index_sequence<I...>) |
1381 | -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) { |
1382 | return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...); |
1383 | } |
1384 | |
1385 | } // end namespace detail |
1386 | |
1387 | /// Given an input tuple (a1, a2, ..., an), pass the arguments of the |
1388 | /// tuple variadically to f as if by calling f(a1, a2, ..., an) and |
1389 | /// return the result. |
1390 | template <typename F, typename Tuple> |
1391 | auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( |
1392 | std::forward<F>(f), std::forward<Tuple>(t), |
1393 | build_index_impl< |
1394 | std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { |
1395 | using Indices = build_index_impl< |
1396 | std::tuple_size<typename std::decay<Tuple>::type>::value>; |
1397 | |
1398 | return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t), |
1399 | Indices{}); |
1400 | } |
1401 | |
1402 | } // end namespace llvm |
1403 | |
1404 | #endif // LLVM_ADT_STLEXTRAS_H |