File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/include/llvm/Object/ObjectFile.h |
Warning: | line 474, column 7 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- MachODumper.cpp - Object file dumping utility for llvm -------------===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file implements the MachO-specific dumper for llvm-readobj. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #include "ObjDumper.h" | |||
14 | #include "StackMapPrinter.h" | |||
15 | #include "llvm-readobj.h" | |||
16 | #include "llvm/ADT/Optional.h" | |||
17 | #include "llvm/ADT/SmallString.h" | |||
18 | #include "llvm/ADT/StringExtras.h" | |||
19 | #include "llvm/Object/MachO.h" | |||
20 | #include "llvm/Support/BinaryStreamReader.h" | |||
21 | #include "llvm/Support/Casting.h" | |||
22 | #include "llvm/Support/ScopedPrinter.h" | |||
23 | ||||
24 | using namespace llvm; | |||
25 | using namespace object; | |||
26 | ||||
27 | namespace { | |||
28 | ||||
29 | class MachODumper : public ObjDumper { | |||
30 | public: | |||
31 | MachODumper(const MachOObjectFile *Obj, ScopedPrinter &Writer) | |||
32 | : ObjDumper(Writer, Obj->getFileName()), Obj(Obj) {} | |||
33 | ||||
34 | void printFileHeaders() override; | |||
35 | void printSectionHeaders() override; | |||
36 | void printRelocations() override; | |||
37 | void printUnwindInfo() override; | |||
38 | void printStackMap() const override; | |||
39 | void printCGProfile() override; | |||
40 | ||||
41 | void printNeededLibraries() override; | |||
42 | ||||
43 | bool canCompareSymbols() const override { return true; } | |||
44 | bool compareSymbolsByName(object::SymbolRef LHS, | |||
45 | object::SymbolRef RHS) const override; | |||
46 | bool compareSymbolsByType(object::SymbolRef LHS, | |||
47 | object::SymbolRef RHS) const override; | |||
48 | // MachO-specific. | |||
49 | void printMachODataInCode() override; | |||
50 | void printMachOVersionMin() override; | |||
51 | void printMachODysymtab() override; | |||
52 | void printMachOSegment() override; | |||
53 | void printMachOIndirectSymbols() override; | |||
54 | void printMachOLinkerOptions () override; | |||
55 | ||||
56 | private: | |||
57 | template<class MachHeader> | |||
58 | void printFileHeaders(const MachHeader &Header); | |||
59 | ||||
60 | StringRef getSymbolName(const SymbolRef &Symbol) const; | |||
61 | uint8_t getSymbolType(const SymbolRef &Symbol) const; | |||
62 | ||||
63 | void printSymbols() override; | |||
64 | void printSymbols(Optional<SymbolComparator> SymComp) override; | |||
65 | void printDynamicSymbols() override; | |||
66 | void printDynamicSymbols(Optional<SymbolComparator> SymComp) override; | |||
67 | void printSymbol(const SymbolRef &Symbol, ScopedPrinter &W); | |||
68 | void printSymbol(const SymbolRef &Symbol); | |||
69 | ||||
70 | void printRelocation(const RelocationRef &Reloc); | |||
71 | ||||
72 | void printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc); | |||
73 | ||||
74 | void printSectionHeaders(const MachOObjectFile *Obj); | |||
75 | ||||
76 | const MachOObjectFile *Obj; | |||
77 | }; | |||
78 | ||||
79 | } // namespace | |||
80 | ||||
81 | ||||
82 | namespace llvm { | |||
83 | ||||
84 | std::unique_ptr<ObjDumper> createMachODumper(const object::MachOObjectFile &Obj, | |||
85 | ScopedPrinter &Writer) { | |||
86 | return std::make_unique<MachODumper>(&Obj, Writer); | |||
87 | } | |||
88 | ||||
89 | } // namespace llvm | |||
90 | ||||
91 | const EnumEntry<uint32_t> MachOMagics[] = { | |||
92 | { "Magic", MachO::MH_MAGIC }, | |||
93 | { "Cigam", MachO::MH_CIGAM }, | |||
94 | { "Magic64", MachO::MH_MAGIC_64 }, | |||
95 | { "Cigam64", MachO::MH_CIGAM_64 }, | |||
96 | { "FatMagic", MachO::FAT_MAGIC }, | |||
97 | { "FatCigam", MachO::FAT_CIGAM }, | |||
98 | }; | |||
99 | ||||
100 | const EnumEntry<uint32_t> MachOHeaderFileTypes[] = { | |||
101 | { "Relocatable", MachO::MH_OBJECT }, | |||
102 | { "Executable", MachO::MH_EXECUTE }, | |||
103 | { "FixedVMLibrary", MachO::MH_FVMLIB }, | |||
104 | { "Core", MachO::MH_CORE }, | |||
105 | { "PreloadedExecutable", MachO::MH_PRELOAD }, | |||
106 | { "DynamicLibrary", MachO::MH_DYLIB }, | |||
107 | { "DynamicLinker", MachO::MH_DYLINKER }, | |||
108 | { "Bundle", MachO::MH_BUNDLE }, | |||
109 | { "DynamicLibraryStub", MachO::MH_DYLIB_STUB }, | |||
110 | { "DWARFSymbol", MachO::MH_DSYM }, | |||
111 | { "KextBundle", MachO::MH_KEXT_BUNDLE }, | |||
112 | }; | |||
113 | ||||
114 | const EnumEntry<uint32_t> MachOHeaderCpuTypes[] = { | |||
115 | { "Any" , static_cast<uint32_t>(MachO::CPU_TYPE_ANY) }, | |||
116 | { "X86" , MachO::CPU_TYPE_X86 }, | |||
117 | { "X86-64" , MachO::CPU_TYPE_X86_64 }, | |||
118 | { "Mc98000" , MachO::CPU_TYPE_MC98000 }, | |||
119 | { "Arm" , MachO::CPU_TYPE_ARM }, | |||
120 | { "Arm64" , MachO::CPU_TYPE_ARM64 }, | |||
121 | { "Sparc" , MachO::CPU_TYPE_SPARC }, | |||
122 | { "PowerPC" , MachO::CPU_TYPE_POWERPC }, | |||
123 | { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 }, | |||
124 | }; | |||
125 | ||||
126 | const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX86[] = { | |||
127 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL){ "CPU_SUBTYPE_I386_ALL", MachO::CPU_SUBTYPE_I386_ALL }, | |||
128 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_386){ "CPU_SUBTYPE_386", MachO::CPU_SUBTYPE_386 }, | |||
129 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486){ "CPU_SUBTYPE_486", MachO::CPU_SUBTYPE_486 }, | |||
130 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486SX){ "CPU_SUBTYPE_486SX", MachO::CPU_SUBTYPE_486SX }, | |||
131 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_586){ "CPU_SUBTYPE_586", MachO::CPU_SUBTYPE_586 }, | |||
132 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTPRO){ "CPU_SUBTYPE_PENTPRO", MachO::CPU_SUBTYPE_PENTPRO }, | |||
133 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M3){ "CPU_SUBTYPE_PENTII_M3", MachO::CPU_SUBTYPE_PENTII_M3 }, | |||
134 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M5){ "CPU_SUBTYPE_PENTII_M5", MachO::CPU_SUBTYPE_PENTII_M5 }, | |||
135 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON){ "CPU_SUBTYPE_CELERON", MachO::CPU_SUBTYPE_CELERON }, | |||
136 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON_MOBILE){ "CPU_SUBTYPE_CELERON_MOBILE", MachO::CPU_SUBTYPE_CELERON_MOBILE }, | |||
137 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3){ "CPU_SUBTYPE_PENTIUM_3", MachO::CPU_SUBTYPE_PENTIUM_3 }, | |||
138 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_M){ "CPU_SUBTYPE_PENTIUM_3_M", MachO::CPU_SUBTYPE_PENTIUM_3_M }, | |||
139 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_XEON){ "CPU_SUBTYPE_PENTIUM_3_XEON", MachO::CPU_SUBTYPE_PENTIUM_3_XEON }, | |||
140 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_M){ "CPU_SUBTYPE_PENTIUM_M", MachO::CPU_SUBTYPE_PENTIUM_M }, | |||
141 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4){ "CPU_SUBTYPE_PENTIUM_4", MachO::CPU_SUBTYPE_PENTIUM_4 }, | |||
142 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4_M){ "CPU_SUBTYPE_PENTIUM_4_M", MachO::CPU_SUBTYPE_PENTIUM_4_M }, | |||
143 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM){ "CPU_SUBTYPE_ITANIUM", MachO::CPU_SUBTYPE_ITANIUM }, | |||
144 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM_2){ "CPU_SUBTYPE_ITANIUM_2", MachO::CPU_SUBTYPE_ITANIUM_2 }, | |||
145 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON){ "CPU_SUBTYPE_XEON", MachO::CPU_SUBTYPE_XEON }, | |||
146 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON_MP){ "CPU_SUBTYPE_XEON_MP", MachO::CPU_SUBTYPE_XEON_MP }, | |||
147 | }; | |||
148 | ||||
149 | const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX64[] = { | |||
150 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_ALL){ "CPU_SUBTYPE_X86_64_ALL", MachO::CPU_SUBTYPE_X86_64_ALL }, | |||
151 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_ARCH1){ "CPU_SUBTYPE_X86_ARCH1", MachO::CPU_SUBTYPE_X86_ARCH1 }, | |||
152 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_H){ "CPU_SUBTYPE_X86_64_H", MachO::CPU_SUBTYPE_X86_64_H }, | |||
153 | }; | |||
154 | ||||
155 | const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM[] = { | |||
156 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_ALL){ "CPU_SUBTYPE_ARM_ALL", MachO::CPU_SUBTYPE_ARM_ALL }, | |||
157 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V4T){ "CPU_SUBTYPE_ARM_V4T", MachO::CPU_SUBTYPE_ARM_V4T }, | |||
158 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6){ "CPU_SUBTYPE_ARM_V6", MachO::CPU_SUBTYPE_ARM_V6 }, | |||
159 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5){ "CPU_SUBTYPE_ARM_V5", MachO::CPU_SUBTYPE_ARM_V5 }, | |||
160 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5TEJ){ "CPU_SUBTYPE_ARM_V5TEJ", MachO::CPU_SUBTYPE_ARM_V5TEJ }, | |||
161 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_XSCALE){ "CPU_SUBTYPE_ARM_XSCALE", MachO::CPU_SUBTYPE_ARM_XSCALE }, | |||
162 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7){ "CPU_SUBTYPE_ARM_V7", MachO::CPU_SUBTYPE_ARM_V7 }, | |||
163 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7S){ "CPU_SUBTYPE_ARM_V7S", MachO::CPU_SUBTYPE_ARM_V7S }, | |||
164 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7K){ "CPU_SUBTYPE_ARM_V7K", MachO::CPU_SUBTYPE_ARM_V7K }, | |||
165 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6M){ "CPU_SUBTYPE_ARM_V6M", MachO::CPU_SUBTYPE_ARM_V6M }, | |||
166 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7M){ "CPU_SUBTYPE_ARM_V7M", MachO::CPU_SUBTYPE_ARM_V7M }, | |||
167 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM){ "CPU_SUBTYPE_ARM_V7EM", MachO::CPU_SUBTYPE_ARM_V7EM }, | |||
168 | }; | |||
169 | ||||
170 | const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM64[] = { | |||
171 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL){ "CPU_SUBTYPE_ARM64_ALL", MachO::CPU_SUBTYPE_ARM64_ALL }, | |||
172 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_V8){ "CPU_SUBTYPE_ARM64_V8", MachO::CPU_SUBTYPE_ARM64_V8 }, | |||
173 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64E){ "CPU_SUBTYPE_ARM64E", MachO::CPU_SUBTYPE_ARM64E }, | |||
174 | }; | |||
175 | ||||
176 | const EnumEntry<uint32_t> MachOHeaderCpuSubtypesSPARC[] = { | |||
177 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_SPARC_ALL){ "CPU_SUBTYPE_SPARC_ALL", MachO::CPU_SUBTYPE_SPARC_ALL }, | |||
178 | }; | |||
179 | ||||
180 | const EnumEntry<uint32_t> MachOHeaderCpuSubtypesPPC[] = { | |||
181 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_ALL){ "CPU_SUBTYPE_POWERPC_ALL", MachO::CPU_SUBTYPE_POWERPC_ALL }, | |||
182 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_601){ "CPU_SUBTYPE_POWERPC_601", MachO::CPU_SUBTYPE_POWERPC_601 }, | |||
183 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_602){ "CPU_SUBTYPE_POWERPC_602", MachO::CPU_SUBTYPE_POWERPC_602 }, | |||
184 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603){ "CPU_SUBTYPE_POWERPC_603", MachO::CPU_SUBTYPE_POWERPC_603 }, | |||
185 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603e){ "CPU_SUBTYPE_POWERPC_603e", MachO::CPU_SUBTYPE_POWERPC_603e }, | |||
186 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603ev){ "CPU_SUBTYPE_POWERPC_603ev", MachO::CPU_SUBTYPE_POWERPC_603ev }, | |||
187 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604){ "CPU_SUBTYPE_POWERPC_604", MachO::CPU_SUBTYPE_POWERPC_604 }, | |||
188 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604e){ "CPU_SUBTYPE_POWERPC_604e", MachO::CPU_SUBTYPE_POWERPC_604e }, | |||
189 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_620){ "CPU_SUBTYPE_POWERPC_620", MachO::CPU_SUBTYPE_POWERPC_620 }, | |||
190 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_750){ "CPU_SUBTYPE_POWERPC_750", MachO::CPU_SUBTYPE_POWERPC_750 }, | |||
191 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7400){ "CPU_SUBTYPE_POWERPC_7400", MachO::CPU_SUBTYPE_POWERPC_7400 }, | |||
192 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7450){ "CPU_SUBTYPE_POWERPC_7450", MachO::CPU_SUBTYPE_POWERPC_7450 }, | |||
193 | LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_970){ "CPU_SUBTYPE_POWERPC_970", MachO::CPU_SUBTYPE_POWERPC_970 }, | |||
194 | }; | |||
195 | ||||
196 | const EnumEntry<uint32_t> MachOHeaderFlags[] = { | |||
197 | LLVM_READOBJ_ENUM_ENT(MachO, MH_NOUNDEFS){ "MH_NOUNDEFS", MachO::MH_NOUNDEFS }, | |||
198 | LLVM_READOBJ_ENUM_ENT(MachO, MH_INCRLINK){ "MH_INCRLINK", MachO::MH_INCRLINK }, | |||
199 | LLVM_READOBJ_ENUM_ENT(MachO, MH_DYLDLINK){ "MH_DYLDLINK", MachO::MH_DYLDLINK }, | |||
200 | LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDATLOAD){ "MH_BINDATLOAD", MachO::MH_BINDATLOAD }, | |||
201 | LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBOUND){ "MH_PREBOUND", MachO::MH_PREBOUND }, | |||
202 | LLVM_READOBJ_ENUM_ENT(MachO, MH_SPLIT_SEGS){ "MH_SPLIT_SEGS", MachO::MH_SPLIT_SEGS }, | |||
203 | LLVM_READOBJ_ENUM_ENT(MachO, MH_LAZY_INIT){ "MH_LAZY_INIT", MachO::MH_LAZY_INIT }, | |||
204 | LLVM_READOBJ_ENUM_ENT(MachO, MH_TWOLEVEL){ "MH_TWOLEVEL", MachO::MH_TWOLEVEL }, | |||
205 | LLVM_READOBJ_ENUM_ENT(MachO, MH_FORCE_FLAT){ "MH_FORCE_FLAT", MachO::MH_FORCE_FLAT }, | |||
206 | LLVM_READOBJ_ENUM_ENT(MachO, MH_NOMULTIDEFS){ "MH_NOMULTIDEFS", MachO::MH_NOMULTIDEFS }, | |||
207 | LLVM_READOBJ_ENUM_ENT(MachO, MH_NOFIXPREBINDING){ "MH_NOFIXPREBINDING", MachO::MH_NOFIXPREBINDING }, | |||
208 | LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBINDABLE){ "MH_PREBINDABLE", MachO::MH_PREBINDABLE }, | |||
209 | LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLMODSBOUND){ "MH_ALLMODSBOUND", MachO::MH_ALLMODSBOUND }, | |||
210 | LLVM_READOBJ_ENUM_ENT(MachO, MH_SUBSECTIONS_VIA_SYMBOLS){ "MH_SUBSECTIONS_VIA_SYMBOLS", MachO::MH_SUBSECTIONS_VIA_SYMBOLS }, | |||
211 | LLVM_READOBJ_ENUM_ENT(MachO, MH_CANONICAL){ "MH_CANONICAL", MachO::MH_CANONICAL }, | |||
212 | LLVM_READOBJ_ENUM_ENT(MachO, MH_WEAK_DEFINES){ "MH_WEAK_DEFINES", MachO::MH_WEAK_DEFINES }, | |||
213 | LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDS_TO_WEAK){ "MH_BINDS_TO_WEAK", MachO::MH_BINDS_TO_WEAK }, | |||
214 | LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLOW_STACK_EXECUTION){ "MH_ALLOW_STACK_EXECUTION", MachO::MH_ALLOW_STACK_EXECUTION }, | |||
215 | LLVM_READOBJ_ENUM_ENT(MachO, MH_ROOT_SAFE){ "MH_ROOT_SAFE", MachO::MH_ROOT_SAFE }, | |||
216 | LLVM_READOBJ_ENUM_ENT(MachO, MH_SETUID_SAFE){ "MH_SETUID_SAFE", MachO::MH_SETUID_SAFE }, | |||
217 | LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_REEXPORTED_DYLIBS){ "MH_NO_REEXPORTED_DYLIBS", MachO::MH_NO_REEXPORTED_DYLIBS }, | |||
218 | LLVM_READOBJ_ENUM_ENT(MachO, MH_PIE){ "MH_PIE", MachO::MH_PIE }, | |||
219 | LLVM_READOBJ_ENUM_ENT(MachO, MH_DEAD_STRIPPABLE_DYLIB){ "MH_DEAD_STRIPPABLE_DYLIB", MachO::MH_DEAD_STRIPPABLE_DYLIB }, | |||
220 | LLVM_READOBJ_ENUM_ENT(MachO, MH_HAS_TLV_DESCRIPTORS){ "MH_HAS_TLV_DESCRIPTORS", MachO::MH_HAS_TLV_DESCRIPTORS }, | |||
221 | LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_HEAP_EXECUTION){ "MH_NO_HEAP_EXECUTION", MachO::MH_NO_HEAP_EXECUTION }, | |||
222 | LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE){ "MH_APP_EXTENSION_SAFE", MachO::MH_APP_EXTENSION_SAFE }, | |||
223 | }; | |||
224 | ||||
225 | const EnumEntry<unsigned> MachOSectionTypes[] = { | |||
226 | { "Regular" , MachO::S_REGULAR }, | |||
227 | { "ZeroFill" , MachO::S_ZEROFILL }, | |||
228 | { "CStringLiterals" , MachO::S_CSTRING_LITERALS }, | |||
229 | { "4ByteLiterals" , MachO::S_4BYTE_LITERALS }, | |||
230 | { "8ByteLiterals" , MachO::S_8BYTE_LITERALS }, | |||
231 | { "LiteralPointers" , MachO::S_LITERAL_POINTERS }, | |||
232 | { "NonLazySymbolPointers" , MachO::S_NON_LAZY_SYMBOL_POINTERS }, | |||
233 | { "LazySymbolPointers" , MachO::S_LAZY_SYMBOL_POINTERS }, | |||
234 | { "SymbolStubs" , MachO::S_SYMBOL_STUBS }, | |||
235 | { "ModInitFuncPointers" , MachO::S_MOD_INIT_FUNC_POINTERS }, | |||
236 | { "ModTermFuncPointers" , MachO::S_MOD_TERM_FUNC_POINTERS }, | |||
237 | { "Coalesced" , MachO::S_COALESCED }, | |||
238 | { "GBZeroFill" , MachO::S_GB_ZEROFILL }, | |||
239 | { "Interposing" , MachO::S_INTERPOSING }, | |||
240 | { "16ByteLiterals" , MachO::S_16BYTE_LITERALS }, | |||
241 | { "DTraceDOF" , MachO::S_DTRACE_DOF }, | |||
242 | { "LazyDylibSymbolPointers" , MachO::S_LAZY_DYLIB_SYMBOL_POINTERS }, | |||
243 | { "ThreadLocalRegular" , MachO::S_THREAD_LOCAL_REGULAR }, | |||
244 | { "ThreadLocalZerofill" , MachO::S_THREAD_LOCAL_ZEROFILL }, | |||
245 | { "ThreadLocalVariables" , MachO::S_THREAD_LOCAL_VARIABLES }, | |||
246 | { "ThreadLocalVariablePointers" , MachO::S_THREAD_LOCAL_VARIABLE_POINTERS }, | |||
247 | { "ThreadLocalInitFunctionPointers", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS } | |||
248 | }; | |||
249 | ||||
250 | const EnumEntry<unsigned> MachOSectionAttributes[] = { | |||
251 | { "LocReloc" , 1 << 0 /*S_ATTR_LOC_RELOC */ }, | |||
252 | { "ExtReloc" , 1 << 1 /*S_ATTR_EXT_RELOC */ }, | |||
253 | { "SomeInstructions" , 1 << 2 /*S_ATTR_SOME_INSTRUCTIONS */ }, | |||
254 | { "Debug" , 1 << 17 /*S_ATTR_DEBUG */ }, | |||
255 | { "SelfModifyingCode", 1 << 18 /*S_ATTR_SELF_MODIFYING_CODE*/ }, | |||
256 | { "LiveSupport" , 1 << 19 /*S_ATTR_LIVE_SUPPORT */ }, | |||
257 | { "NoDeadStrip" , 1 << 20 /*S_ATTR_NO_DEAD_STRIP */ }, | |||
258 | { "StripStaticSyms" , 1 << 21 /*S_ATTR_STRIP_STATIC_SYMS */ }, | |||
259 | { "NoTOC" , 1 << 22 /*S_ATTR_NO_TOC */ }, | |||
260 | { "PureInstructions" , 1 << 23 /*S_ATTR_PURE_INSTRUCTIONS */ }, | |||
261 | }; | |||
262 | ||||
263 | const EnumEntry<unsigned> MachOSymbolRefTypes[] = { | |||
264 | { "UndefinedNonLazy", 0 }, | |||
265 | { "ReferenceFlagUndefinedLazy", 1 }, | |||
266 | { "ReferenceFlagDefined", 2 }, | |||
267 | { "ReferenceFlagPrivateDefined", 3 }, | |||
268 | { "ReferenceFlagPrivateUndefinedNonLazy", 4 }, | |||
269 | { "ReferenceFlagPrivateUndefinedLazy", 5 } | |||
270 | }; | |||
271 | ||||
272 | const EnumEntry<unsigned> MachOSymbolFlags[] = { | |||
273 | { "ThumbDef", 0x8 }, | |||
274 | { "ReferencedDynamically", 0x10 }, | |||
275 | { "NoDeadStrip", 0x20 }, | |||
276 | { "WeakRef", 0x40 }, | |||
277 | { "WeakDef", 0x80 }, | |||
278 | { "SymbolResolver", 0x100 }, | |||
279 | { "AltEntry", 0x200 }, | |||
280 | { "ColdFunc", 0x400 }, | |||
281 | }; | |||
282 | ||||
283 | const EnumEntry<unsigned> MachOSymbolTypes[] = { | |||
284 | { "Undef", 0x0 }, | |||
285 | { "Abs", 0x2 }, | |||
286 | { "Indirect", 0xA }, | |||
287 | { "PreboundUndef", 0xC }, | |||
288 | { "Section", 0xE } | |||
289 | }; | |||
290 | ||||
291 | namespace { | |||
292 | struct MachOSection { | |||
293 | ArrayRef<char> Name; | |||
294 | ArrayRef<char> SegmentName; | |||
295 | uint64_t Address; | |||
296 | uint64_t Size; | |||
297 | uint32_t Offset; | |||
298 | uint32_t Alignment; | |||
299 | uint32_t RelocationTableOffset; | |||
300 | uint32_t NumRelocationTableEntries; | |||
301 | uint32_t Flags; | |||
302 | uint32_t Reserved1; | |||
303 | uint32_t Reserved2; | |||
304 | uint32_t Reserved3; | |||
305 | }; | |||
306 | ||||
307 | struct MachOSegment { | |||
308 | std::string CmdName; | |||
309 | std::string SegName; | |||
310 | uint64_t cmdsize; | |||
311 | uint64_t vmaddr; | |||
312 | uint64_t vmsize; | |||
313 | uint64_t fileoff; | |||
314 | uint64_t filesize; | |||
315 | uint32_t maxprot; | |||
316 | uint32_t initprot; | |||
317 | uint32_t nsects; | |||
318 | uint32_t flags; | |||
319 | }; | |||
320 | ||||
321 | struct MachOSymbol { | |||
322 | uint32_t StringIndex; | |||
323 | uint8_t Type; | |||
324 | uint8_t SectionIndex; | |||
325 | uint16_t Flags; | |||
326 | uint64_t Value; | |||
327 | }; | |||
328 | } | |||
329 | ||||
330 | static std::string getMask(uint32_t prot) | |||
331 | { | |||
332 | // TODO (davide): This always assumes prot is valid. | |||
333 | // Catch mistakes and report if needed. | |||
334 | std::string Prot; | |||
335 | Prot = ""; | |||
336 | Prot += (prot & MachO::VM_PROT_READ) ? "r" : "-"; | |||
337 | Prot += (prot & MachO::VM_PROT_WRITE) ? "w" : "-"; | |||
338 | Prot += (prot & MachO::VM_PROT_EXECUTE) ? "x" : "-"; | |||
339 | return Prot; | |||
340 | } | |||
341 | ||||
342 | static void getSection(const MachOObjectFile *Obj, | |||
343 | DataRefImpl Sec, | |||
344 | MachOSection &Section) { | |||
345 | if (!Obj->is64Bit()) { | |||
346 | MachO::section Sect = Obj->getSection(Sec); | |||
347 | Section.Address = Sect.addr; | |||
348 | Section.Size = Sect.size; | |||
349 | Section.Offset = Sect.offset; | |||
350 | Section.Alignment = Sect.align; | |||
351 | Section.RelocationTableOffset = Sect.reloff; | |||
352 | Section.NumRelocationTableEntries = Sect.nreloc; | |||
353 | Section.Flags = Sect.flags; | |||
354 | Section.Reserved1 = Sect.reserved1; | |||
355 | Section.Reserved2 = Sect.reserved2; | |||
356 | return; | |||
357 | } | |||
358 | MachO::section_64 Sect = Obj->getSection64(Sec); | |||
359 | Section.Address = Sect.addr; | |||
360 | Section.Size = Sect.size; | |||
361 | Section.Offset = Sect.offset; | |||
362 | Section.Alignment = Sect.align; | |||
363 | Section.RelocationTableOffset = Sect.reloff; | |||
364 | Section.NumRelocationTableEntries = Sect.nreloc; | |||
365 | Section.Flags = Sect.flags; | |||
366 | Section.Reserved1 = Sect.reserved1; | |||
367 | Section.Reserved2 = Sect.reserved2; | |||
368 | Section.Reserved3 = Sect.reserved3; | |||
369 | } | |||
370 | ||||
371 | static void getSegment(const MachOObjectFile *Obj, | |||
372 | const MachOObjectFile::LoadCommandInfo &L, | |||
373 | MachOSegment &Segment) { | |||
374 | if (!Obj->is64Bit()) { | |||
375 | MachO::segment_command SC = Obj->getSegmentLoadCommand(L); | |||
376 | Segment.CmdName = "LC_SEGMENT"; | |||
377 | Segment.SegName = SC.segname; | |||
378 | Segment.cmdsize = SC.cmdsize; | |||
379 | Segment.vmaddr = SC.vmaddr; | |||
380 | Segment.vmsize = SC.vmsize; | |||
381 | Segment.fileoff = SC.fileoff; | |||
382 | Segment.filesize = SC.filesize; | |||
383 | Segment.maxprot = SC.maxprot; | |||
384 | Segment.initprot = SC.initprot; | |||
385 | Segment.nsects = SC.nsects; | |||
386 | Segment.flags = SC.flags; | |||
387 | return; | |||
388 | } | |||
389 | MachO::segment_command_64 SC = Obj->getSegment64LoadCommand(L); | |||
390 | Segment.CmdName = "LC_SEGMENT_64"; | |||
391 | Segment.SegName = SC.segname; | |||
392 | Segment.cmdsize = SC.cmdsize; | |||
393 | Segment.vmaddr = SC.vmaddr; | |||
394 | Segment.vmsize = SC.vmsize; | |||
395 | Segment.fileoff = SC.fileoff; | |||
396 | Segment.filesize = SC.filesize; | |||
397 | Segment.maxprot = SC.maxprot; | |||
398 | Segment.initprot = SC.initprot; | |||
399 | Segment.nsects = SC.nsects; | |||
400 | Segment.flags = SC.flags; | |||
401 | } | |||
402 | ||||
403 | static void getSymbol(const MachOObjectFile *Obj, | |||
404 | DataRefImpl DRI, | |||
405 | MachOSymbol &Symbol) { | |||
406 | if (!Obj->is64Bit()) { | |||
407 | MachO::nlist Entry = Obj->getSymbolTableEntry(DRI); | |||
408 | Symbol.StringIndex = Entry.n_strx; | |||
409 | Symbol.Type = Entry.n_type; | |||
410 | Symbol.SectionIndex = Entry.n_sect; | |||
411 | Symbol.Flags = Entry.n_desc; | |||
412 | Symbol.Value = Entry.n_value; | |||
413 | return; | |||
414 | } | |||
415 | MachO::nlist_64 Entry = Obj->getSymbol64TableEntry(DRI); | |||
416 | Symbol.StringIndex = Entry.n_strx; | |||
417 | Symbol.Type = Entry.n_type; | |||
418 | Symbol.SectionIndex = Entry.n_sect; | |||
419 | Symbol.Flags = Entry.n_desc; | |||
420 | Symbol.Value = Entry.n_value; | |||
421 | } | |||
422 | ||||
423 | void MachODumper::printFileHeaders() { | |||
424 | DictScope H(W, "MachHeader"); | |||
425 | if (!Obj->is64Bit()) { | |||
426 | printFileHeaders(Obj->getHeader()); | |||
427 | } else { | |||
428 | printFileHeaders(Obj->getHeader64()); | |||
429 | W.printHex("Reserved", Obj->getHeader64().reserved); | |||
430 | } | |||
431 | } | |||
432 | ||||
433 | template<class MachHeader> | |||
434 | void MachODumper::printFileHeaders(const MachHeader &Header) { | |||
435 | W.printEnum("Magic", Header.magic, makeArrayRef(MachOMagics)); | |||
436 | W.printEnum("CpuType", Header.cputype, makeArrayRef(MachOHeaderCpuTypes)); | |||
437 | uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK; | |||
438 | switch (Header.cputype) { | |||
439 | case MachO::CPU_TYPE_X86: | |||
440 | W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX86)); | |||
441 | break; | |||
442 | case MachO::CPU_TYPE_X86_64: | |||
443 | W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX64)); | |||
444 | break; | |||
445 | case MachO::CPU_TYPE_ARM: | |||
446 | W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM)); | |||
447 | break; | |||
448 | case MachO::CPU_TYPE_POWERPC: | |||
449 | W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesPPC)); | |||
450 | break; | |||
451 | case MachO::CPU_TYPE_SPARC: | |||
452 | W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesSPARC)); | |||
453 | break; | |||
454 | case MachO::CPU_TYPE_ARM64: | |||
455 | W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM64)); | |||
456 | break; | |||
457 | case MachO::CPU_TYPE_POWERPC64: | |||
458 | default: | |||
459 | W.printHex("CpuSubtype", subtype); | |||
460 | } | |||
461 | W.printEnum("FileType", Header.filetype, makeArrayRef(MachOHeaderFileTypes)); | |||
462 | W.printNumber("NumOfLoadCommands", Header.ncmds); | |||
463 | W.printNumber("SizeOfLoadCommands", Header.sizeofcmds); | |||
464 | W.printFlags("Flags", Header.flags, makeArrayRef(MachOHeaderFlags)); | |||
465 | } | |||
466 | ||||
467 | void MachODumper::printSectionHeaders() { return printSectionHeaders(Obj); } | |||
468 | ||||
469 | void MachODumper::printSectionHeaders(const MachOObjectFile *Obj) { | |||
470 | ListScope Group(W, "Sections"); | |||
471 | ||||
472 | int SectionIndex = -1; | |||
473 | for (const SectionRef &Section : Obj->sections()) { | |||
474 | ++SectionIndex; | |||
475 | ||||
476 | MachOSection MOSection; | |||
477 | getSection(Obj, Section.getRawDataRefImpl(), MOSection); | |||
478 | DataRefImpl DR = Section.getRawDataRefImpl(); | |||
479 | StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName()); | |||
480 | ArrayRef<char> RawName = Obj->getSectionRawName(DR); | |||
481 | StringRef SegmentName = Obj->getSectionFinalSegmentName(DR); | |||
482 | ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR); | |||
483 | ||||
484 | DictScope SectionD(W, "Section"); | |||
485 | W.printNumber("Index", SectionIndex); | |||
486 | W.printBinary("Name", Name, RawName); | |||
487 | W.printBinary("Segment", SegmentName, RawSegmentName); | |||
488 | W.printHex("Address", MOSection.Address); | |||
489 | W.printHex("Size", MOSection.Size); | |||
490 | W.printNumber("Offset", MOSection.Offset); | |||
491 | W.printNumber("Alignment", MOSection.Alignment); | |||
492 | W.printHex("RelocationOffset", MOSection.RelocationTableOffset); | |||
493 | W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries); | |||
494 | W.printEnum("Type", MOSection.Flags & 0xFF, | |||
495 | makeArrayRef(MachOSectionTypes)); | |||
496 | W.printFlags("Attributes", MOSection.Flags >> 8, | |||
497 | makeArrayRef(MachOSectionAttributes)); | |||
498 | W.printHex("Reserved1", MOSection.Reserved1); | |||
499 | W.printHex("Reserved2", MOSection.Reserved2); | |||
500 | if (Obj->is64Bit()) | |||
501 | W.printHex("Reserved3", MOSection.Reserved3); | |||
502 | ||||
503 | if (opts::SectionRelocations) { | |||
504 | ListScope D(W, "Relocations"); | |||
505 | for (const RelocationRef &Reloc : Section.relocations()) | |||
506 | printRelocation(Reloc); | |||
507 | } | |||
508 | ||||
509 | if (opts::SectionSymbols) { | |||
510 | ListScope D(W, "Symbols"); | |||
511 | for (const SymbolRef &Symbol : Obj->symbols()) { | |||
512 | if (!Section.containsSymbol(Symbol)) | |||
513 | continue; | |||
514 | ||||
515 | printSymbol(Symbol); | |||
516 | } | |||
517 | } | |||
518 | ||||
519 | if (opts::SectionData && !Section.isBSS()) | |||
520 | W.printBinaryBlock("SectionData", unwrapOrError(Obj->getFileName(), | |||
521 | Section.getContents())); | |||
522 | } | |||
523 | } | |||
524 | ||||
525 | void MachODumper::printRelocations() { | |||
526 | ListScope D(W, "Relocations"); | |||
527 | ||||
528 | std::error_code EC; | |||
529 | for (const SectionRef &Section : Obj->sections()) { | |||
530 | StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName()); | |||
531 | bool PrintedGroup = false; | |||
532 | for (const RelocationRef &Reloc : Section.relocations()) { | |||
533 | if (!PrintedGroup) { | |||
534 | W.startLine() << "Section " << Name << " {\n"; | |||
535 | W.indent(); | |||
536 | PrintedGroup = true; | |||
537 | } | |||
538 | ||||
539 | printRelocation(Reloc); | |||
540 | } | |||
541 | ||||
542 | if (PrintedGroup) { | |||
543 | W.unindent(); | |||
544 | W.startLine() << "}\n"; | |||
545 | } | |||
546 | } | |||
547 | } | |||
548 | ||||
549 | void MachODumper::printRelocation(const RelocationRef &Reloc) { | |||
550 | return printRelocation(Obj, Reloc); | |||
551 | } | |||
552 | ||||
553 | void MachODumper::printRelocation(const MachOObjectFile *Obj, | |||
554 | const RelocationRef &Reloc) { | |||
555 | uint64_t Offset = Reloc.getOffset(); | |||
556 | SmallString<32> RelocName; | |||
557 | Reloc.getTypeName(RelocName); | |||
558 | ||||
559 | DataRefImpl DR = Reloc.getRawDataRefImpl(); | |||
560 | MachO::any_relocation_info RE = Obj->getRelocation(DR); | |||
561 | bool IsScattered = Obj->isRelocationScattered(RE); | |||
562 | bool IsExtern = !IsScattered && Obj->getPlainRelocationExternal(RE); | |||
563 | ||||
564 | StringRef TargetName; | |||
565 | if (IsExtern) { | |||
566 | symbol_iterator Symbol = Reloc.getSymbol(); | |||
567 | if (Symbol != Obj->symbol_end()) { | |||
568 | TargetName = getSymbolName(*Symbol); | |||
569 | } | |||
570 | } else if (!IsScattered) { | |||
571 | section_iterator SecI = Obj->getRelocationSection(DR); | |||
572 | if (SecI != Obj->section_end()) | |||
573 | TargetName = unwrapOrError(Obj->getFileName(), SecI->getName()); | |||
574 | } | |||
575 | if (TargetName.empty()) | |||
576 | TargetName = "-"; | |||
577 | ||||
578 | if (opts::ExpandRelocs) { | |||
579 | DictScope Group(W, "Relocation"); | |||
580 | W.printHex("Offset", Offset); | |||
581 | W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE)); | |||
582 | W.printNumber("Length", Obj->getAnyRelocationLength(RE)); | |||
583 | W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE)); | |||
584 | if (IsScattered) { | |||
585 | W.printHex("Value", Obj->getScatteredRelocationValue(RE)); | |||
586 | } else { | |||
587 | const char *Kind = IsExtern ? "Symbol" : "Section"; | |||
588 | W.printNumber(Kind, TargetName, Obj->getPlainRelocationSymbolNum(RE)); | |||
589 | } | |||
590 | } else { | |||
591 | SmallString<32> SymbolNameOrOffset("0x"); | |||
592 | if (IsScattered) { | |||
593 | // Scattered relocations don't really have an associated symbol for some | |||
594 | // reason, even if one exists in the symtab at the correct address. | |||
595 | SymbolNameOrOffset += utohexstr(Obj->getScatteredRelocationValue(RE)); | |||
596 | } else { | |||
597 | SymbolNameOrOffset = TargetName; | |||
598 | } | |||
599 | ||||
600 | raw_ostream& OS = W.startLine(); | |||
601 | OS << W.hex(Offset) | |||
602 | << " " << Obj->getAnyRelocationPCRel(RE) | |||
603 | << " " << Obj->getAnyRelocationLength(RE); | |||
604 | if (IsScattered) | |||
605 | OS << " n/a"; | |||
606 | else | |||
607 | OS << " " << Obj->getPlainRelocationExternal(RE); | |||
608 | OS << " " << RelocName | |||
609 | << " " << IsScattered | |||
610 | << " " << SymbolNameOrOffset | |||
611 | << "\n"; | |||
612 | } | |||
613 | } | |||
614 | ||||
615 | StringRef MachODumper::getSymbolName(const SymbolRef &Symbol) const { | |||
616 | Expected<StringRef> SymbolNameOrErr = Symbol.getName(); | |||
617 | if (!SymbolNameOrErr) { | |||
618 | reportError(SymbolNameOrErr.takeError(), Obj->getFileName()); | |||
619 | } | |||
620 | return *SymbolNameOrErr; | |||
621 | } | |||
622 | ||||
623 | uint8_t MachODumper::getSymbolType(const SymbolRef &Symbol) const { | |||
624 | return Obj->is64Bit() | |||
625 | ? Obj->getSymbol64TableEntry(Symbol.getRawDataRefImpl()).n_type | |||
626 | : Obj->getSymbolTableEntry(Symbol.getRawDataRefImpl()).n_type; | |||
627 | } | |||
628 | ||||
629 | bool MachODumper::compareSymbolsByName(SymbolRef LHS, SymbolRef RHS) const { | |||
630 | return getSymbolName(LHS).str().compare(getSymbolName(RHS).str()) < 0; | |||
631 | } | |||
632 | ||||
633 | bool MachODumper::compareSymbolsByType(SymbolRef LHS, SymbolRef RHS) const { | |||
634 | return getSymbolType(LHS) < getSymbolType(RHS); | |||
635 | } | |||
636 | ||||
637 | void MachODumper::printSymbols() { printSymbols(None); } | |||
638 | ||||
639 | void MachODumper::printSymbols(Optional<SymbolComparator> SymComp) { | |||
640 | ListScope Group(W, "Symbols"); | |||
641 | if (SymComp) { | |||
642 | auto SymbolRange = Obj->symbols(); | |||
643 | std::vector<SymbolRef> SortedSymbols(SymbolRange.begin(), | |||
644 | SymbolRange.end()); | |||
645 | llvm::stable_sort(SortedSymbols, *SymComp); | |||
646 | for (SymbolRef Symbol : SortedSymbols) | |||
647 | printSymbol(Symbol); | |||
648 | } else { | |||
649 | for (const SymbolRef &Symbol : Obj->symbols()) { | |||
650 | printSymbol(Symbol); | |||
651 | } | |||
652 | } | |||
653 | } | |||
654 | ||||
655 | void MachODumper::printDynamicSymbols() { | |||
656 | ListScope Group(W, "DynamicSymbols"); | |||
657 | } | |||
658 | void MachODumper::printDynamicSymbols(Optional<SymbolComparator> SymComp) { | |||
659 | ListScope Group(W, "DynamicSymbols"); | |||
660 | } | |||
661 | ||||
662 | void MachODumper::printSymbol(const SymbolRef &Symbol) { | |||
663 | printSymbol(Symbol, W); | |||
664 | } | |||
665 | ||||
666 | void MachODumper::printSymbol(const SymbolRef &Symbol, ScopedPrinter &W) { | |||
667 | StringRef SymbolName = getSymbolName(Symbol); | |||
668 | ||||
669 | MachOSymbol MOSymbol; | |||
670 | getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol); | |||
671 | ||||
672 | StringRef SectionName = ""; | |||
673 | // Don't ask a Mach-O STABS symbol for its section unless we know that | |||
674 | // STAB symbol's section field refers to a valid section index. Otherwise | |||
675 | // the symbol may error trying to load a section that does not exist. | |||
676 | // TODO: Add a whitelist of STABS symbol types that contain valid section | |||
677 | // indices. | |||
678 | if (!(MOSymbol.Type & MachO::N_STAB)) { | |||
679 | Expected<section_iterator> SecIOrErr = Symbol.getSection(); | |||
680 | if (!SecIOrErr) | |||
681 | reportError(SecIOrErr.takeError(), Obj->getFileName()); | |||
682 | ||||
683 | section_iterator SecI = *SecIOrErr; | |||
684 | if (SecI != Obj->section_end()) | |||
685 | SectionName = unwrapOrError(Obj->getFileName(), SecI->getName()); | |||
686 | } | |||
687 | ||||
688 | DictScope D(W, "Symbol"); | |||
689 | W.printNumber("Name", SymbolName, MOSymbol.StringIndex); | |||
690 | if (MOSymbol.Type & MachO::N_STAB) { | |||
691 | W.printHex("Type", "SymDebugTable", MOSymbol.Type); | |||
692 | } else { | |||
693 | if (MOSymbol.Type & MachO::N_PEXT) | |||
694 | W.startLine() << "PrivateExtern\n"; | |||
695 | if (MOSymbol.Type & MachO::N_EXT) | |||
696 | W.startLine() << "Extern\n"; | |||
697 | W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE), | |||
698 | makeArrayRef(MachOSymbolTypes)); | |||
699 | } | |||
700 | W.printHex("Section", SectionName, MOSymbol.SectionIndex); | |||
701 | W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0x7), | |||
702 | makeArrayRef(MachOSymbolRefTypes)); | |||
703 | W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0x7), | |||
704 | makeArrayRef(MachOSymbolFlags)); | |||
705 | W.printHex("Value", MOSymbol.Value); | |||
706 | } | |||
707 | ||||
708 | void MachODumper::printUnwindInfo() { | |||
709 | W.startLine() << "UnwindInfo not implemented.\n"; | |||
710 | } | |||
711 | ||||
712 | void MachODumper::printStackMap() const { | |||
713 | object::SectionRef StackMapSection; | |||
714 | for (auto Sec : Obj->sections()) { | |||
715 | StringRef Name; | |||
716 | if (Expected<StringRef> NameOrErr = Sec.getName()) | |||
717 | Name = *NameOrErr; | |||
718 | else | |||
719 | consumeError(NameOrErr.takeError()); | |||
720 | ||||
721 | if (Name == "__llvm_stackmaps") { | |||
722 | StackMapSection = Sec; | |||
723 | break; | |||
724 | } | |||
725 | } | |||
726 | ||||
727 | if (StackMapSection == object::SectionRef()) | |||
728 | return; | |||
729 | ||||
730 | StringRef StackMapContents = | |||
731 | unwrapOrError(Obj->getFileName(), StackMapSection.getContents()); | |||
732 | ArrayRef<uint8_t> StackMapContentsArray = | |||
733 | arrayRefFromStringRef(StackMapContents); | |||
734 | ||||
735 | if (Obj->isLittleEndian()) | |||
736 | prettyPrintStackMap( | |||
737 | W, StackMapParser<support::little>(StackMapContentsArray)); | |||
738 | else | |||
739 | prettyPrintStackMap( | |||
740 | W, StackMapParser<support::big>(StackMapContentsArray)); | |||
741 | } | |||
742 | ||||
743 | void MachODumper::printCGProfile() { | |||
744 | object::SectionRef CGProfileSection; | |||
| ||||
745 | for (auto Sec : Obj->sections()) { | |||
746 | StringRef Name; | |||
747 | if (Expected<StringRef> NameOrErr = Sec.getName()) | |||
748 | Name = *NameOrErr; | |||
749 | else | |||
750 | consumeError(NameOrErr.takeError()); | |||
751 | ||||
752 | if (Name == "__cg_profile") { | |||
753 | CGProfileSection = Sec; | |||
754 | break; | |||
755 | } | |||
756 | } | |||
757 | if (CGProfileSection == object::SectionRef()) | |||
758 | return; | |||
759 | ||||
760 | StringRef CGProfileContents = | |||
761 | unwrapOrError(Obj->getFileName(), CGProfileSection.getContents()); | |||
762 | BinaryStreamReader Reader(CGProfileContents, Obj->isLittleEndian() | |||
763 | ? llvm::support::little | |||
764 | : llvm::support::big); | |||
765 | ||||
766 | ListScope L(W, "CGProfile"); | |||
767 | while (!Reader.empty()) { | |||
768 | uint32_t FromIndex, ToIndex; | |||
769 | uint64_t Count; | |||
770 | if (Error Err = Reader.readInteger(FromIndex)) | |||
771 | reportError(std::move(Err), Obj->getFileName()); | |||
772 | if (Error Err = Reader.readInteger(ToIndex)) | |||
773 | reportError(std::move(Err), Obj->getFileName()); | |||
774 | if (Error Err = Reader.readInteger(Count)) | |||
775 | reportError(std::move(Err), Obj->getFileName()); | |||
776 | DictScope D(W, "CGProfileEntry"); | |||
777 | W.printNumber("From", getSymbolName(*Obj->getSymbolByIndex(FromIndex)), | |||
778 | FromIndex); | |||
779 | W.printNumber("To", getSymbolName(*Obj->getSymbolByIndex(ToIndex)), | |||
780 | ToIndex); | |||
781 | W.printNumber("Weight", Count); | |||
782 | } | |||
783 | } | |||
784 | ||||
785 | void MachODumper::printNeededLibraries() { | |||
786 | ListScope D(W, "NeededLibraries"); | |||
787 | ||||
788 | using LibsTy = std::vector<StringRef>; | |||
789 | LibsTy Libs; | |||
790 | ||||
791 | for (const auto &Command : Obj->load_commands()) { | |||
792 | if (Command.C.cmd == MachO::LC_LOAD_DYLIB || | |||
793 | Command.C.cmd == MachO::LC_ID_DYLIB || | |||
794 | Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || | |||
795 | Command.C.cmd == MachO::LC_REEXPORT_DYLIB || | |||
796 | Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || | |||
797 | Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { | |||
798 | MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); | |||
799 | if (Dl.dylib.name < Dl.cmdsize) { | |||
800 | auto *P = static_cast<const char*>(Command.Ptr) + Dl.dylib.name; | |||
801 | Libs.push_back(P); | |||
802 | } | |||
803 | } | |||
804 | } | |||
805 | ||||
806 | llvm::stable_sort(Libs); | |||
807 | ||||
808 | for (const auto &L : Libs) { | |||
809 | W.startLine() << L << "\n"; | |||
810 | } | |||
811 | } | |||
812 | ||||
813 | void MachODumper::printMachODataInCode() { | |||
814 | for (const auto &Load : Obj->load_commands()) { | |||
815 | if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { | |||
816 | MachO::linkedit_data_command LLC = Obj->getLinkeditDataLoadCommand(Load); | |||
817 | DictScope Group(W, "DataInCode"); | |||
818 | W.printNumber("Data offset", LLC.dataoff); | |||
819 | W.printNumber("Data size", LLC.datasize); | |||
820 | ListScope D(W, "Data entries"); | |||
821 | unsigned NumRegions = LLC.datasize / sizeof(MachO::data_in_code_entry); | |||
822 | for (unsigned i = 0; i < NumRegions; ++i) { | |||
823 | MachO::data_in_code_entry DICE = Obj->getDataInCodeTableEntry( | |||
824 | LLC.dataoff, i); | |||
825 | DictScope Group(W, "Entry"); | |||
826 | W.printNumber("Index", i); | |||
827 | W.printNumber("Offset", DICE.offset); | |||
828 | W.printNumber("Length", DICE.length); | |||
829 | W.printNumber("Kind", DICE.kind); | |||
830 | } | |||
831 | } | |||
832 | } | |||
833 | } | |||
834 | ||||
835 | void MachODumper::printMachOVersionMin() { | |||
836 | for (const auto &Load : Obj->load_commands()) { | |||
837 | StringRef Cmd; | |||
838 | switch (Load.C.cmd) { | |||
839 | case MachO::LC_VERSION_MIN_MACOSX: | |||
840 | Cmd = "LC_VERSION_MIN_MACOSX"; | |||
841 | break; | |||
842 | case MachO::LC_VERSION_MIN_IPHONEOS: | |||
843 | Cmd = "LC_VERSION_MIN_IPHONEOS"; | |||
844 | break; | |||
845 | case MachO::LC_VERSION_MIN_TVOS: | |||
846 | Cmd = "LC_VERSION_MIN_TVOS"; | |||
847 | break; | |||
848 | case MachO::LC_VERSION_MIN_WATCHOS: | |||
849 | Cmd = "LC_VERSION_MIN_WATCHOS"; | |||
850 | break; | |||
851 | case MachO::LC_BUILD_VERSION: | |||
852 | Cmd = "LC_BUILD_VERSION"; | |||
853 | break; | |||
854 | default: | |||
855 | continue; | |||
856 | } | |||
857 | ||||
858 | DictScope Group(W, "MinVersion"); | |||
859 | // Handle LC_BUILD_VERSION. | |||
860 | if (Load.C.cmd == MachO::LC_BUILD_VERSION) { | |||
861 | MachO::build_version_command BVC = Obj->getBuildVersionLoadCommand(Load); | |||
862 | W.printString("Cmd", Cmd); | |||
863 | W.printNumber("Size", BVC.cmdsize); | |||
864 | W.printString("Platform", | |||
865 | MachOObjectFile::getBuildPlatform(BVC.platform)); | |||
866 | W.printString("Version", MachOObjectFile::getVersionString(BVC.minos)); | |||
867 | if (BVC.sdk) | |||
868 | W.printString("SDK", MachOObjectFile::getVersionString(BVC.sdk)); | |||
869 | else | |||
870 | W.printString("SDK", StringRef("n/a")); | |||
871 | continue; | |||
872 | } | |||
873 | ||||
874 | MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load); | |||
875 | W.printString("Cmd", Cmd); | |||
876 | W.printNumber("Size", VMC.cmdsize); | |||
877 | SmallString<32> Version; | |||
878 | Version = utostr(MachOObjectFile::getVersionMinMajor(VMC, false)) + "." + | |||
879 | utostr(MachOObjectFile::getVersionMinMinor(VMC, false)); | |||
880 | uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, false); | |||
881 | if (Update != 0) | |||
882 | Version += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, false)); | |||
883 | W.printString("Version", Version); | |||
884 | SmallString<32> SDK; | |||
885 | if (VMC.sdk == 0) | |||
886 | SDK = "n/a"; | |||
887 | else { | |||
888 | SDK = utostr(MachOObjectFile::getVersionMinMajor(VMC, true)) + "." + | |||
889 | utostr(MachOObjectFile::getVersionMinMinor(VMC, true)); | |||
890 | uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, true); | |||
891 | if (Update != 0) | |||
892 | SDK += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, true)); | |||
893 | } | |||
894 | W.printString("SDK", SDK); | |||
895 | } | |||
896 | } | |||
897 | ||||
898 | void MachODumper::printMachODysymtab() { | |||
899 | for (const auto &Load : Obj->load_commands()) { | |||
900 | if (Load.C.cmd == MachO::LC_DYSYMTAB) { | |||
901 | MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand(); | |||
902 | DictScope Group(W, "Dysymtab"); | |||
903 | W.printNumber("ilocalsym", DLC.ilocalsym); | |||
904 | W.printNumber("nlocalsym", DLC.nlocalsym); | |||
905 | W.printNumber("iextdefsym", DLC.iextdefsym); | |||
906 | W.printNumber("nextdefsym", DLC.nextdefsym); | |||
907 | W.printNumber("iundefsym", DLC.iundefsym); | |||
908 | W.printNumber("nundefsym", DLC.nundefsym); | |||
909 | W.printNumber("tocoff", DLC.tocoff); | |||
910 | W.printNumber("ntoc", DLC.ntoc); | |||
911 | W.printNumber("modtaboff", DLC.modtaboff); | |||
912 | W.printNumber("nmodtab", DLC.nmodtab); | |||
913 | W.printNumber("extrefsymoff", DLC.extrefsymoff); | |||
914 | W.printNumber("nextrefsyms", DLC.nextrefsyms); | |||
915 | W.printNumber("indirectsymoff", DLC.indirectsymoff); | |||
916 | W.printNumber("nindirectsyms", DLC.nindirectsyms); | |||
917 | W.printNumber("extreloff", DLC.extreloff); | |||
918 | W.printNumber("nextrel", DLC.nextrel); | |||
919 | W.printNumber("locreloff", DLC.locreloff); | |||
920 | W.printNumber("nlocrel", DLC.nlocrel); | |||
921 | } | |||
922 | } | |||
923 | } | |||
924 | ||||
925 | void MachODumper::printMachOSegment() { | |||
926 | for (const auto &Load : Obj->load_commands()) { | |||
927 | if (Load.C.cmd == MachO::LC_SEGMENT || Load.C.cmd == MachO::LC_SEGMENT_64) { | |||
928 | MachOSegment MOSegment; | |||
929 | getSegment(Obj, Load, MOSegment); | |||
930 | DictScope Group(W, "Segment"); | |||
931 | W.printString("Cmd", MOSegment.CmdName); | |||
932 | W.printString("Name", MOSegment.SegName); | |||
933 | W.printNumber("Size", MOSegment.cmdsize); | |||
934 | W.printHex("vmaddr", MOSegment.vmaddr); | |||
935 | W.printHex("vmsize", MOSegment.vmsize); | |||
936 | W.printNumber("fileoff", MOSegment.fileoff); | |||
937 | W.printNumber("filesize", MOSegment.filesize); | |||
938 | W.printString("maxprot", getMask(MOSegment.maxprot)); | |||
939 | W.printString("initprot", getMask(MOSegment.initprot)); | |||
940 | W.printNumber("nsects", MOSegment.nsects); | |||
941 | W.printHex("flags", MOSegment.flags); | |||
942 | } | |||
943 | } | |||
944 | } | |||
945 | ||||
946 | void MachODumper::printMachOIndirectSymbols() { | |||
947 | for (const auto &Load : Obj->load_commands()) { | |||
948 | if (Load.C.cmd == MachO::LC_DYSYMTAB) { | |||
949 | MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand(); | |||
950 | DictScope Group(W, "Indirect Symbols"); | |||
951 | W.printNumber("Number", DLC.nindirectsyms); | |||
952 | ListScope D(W, "Symbols"); | |||
953 | for (unsigned i = 0; i < DLC.nindirectsyms; ++i) { | |||
954 | DictScope Group(W, "Entry"); | |||
955 | W.printNumber("Entry Index", i); | |||
956 | W.printHex("Symbol Index", Obj->getIndirectSymbolTableEntry(DLC, i)); | |||
957 | } | |||
958 | } | |||
959 | } | |||
960 | } | |||
961 | ||||
962 | void MachODumper::printMachOLinkerOptions() { | |||
963 | for (const auto &Load : Obj->load_commands()) { | |||
964 | if (Load.C.cmd == MachO::LC_LINKER_OPTION) { | |||
965 | MachO::linker_option_command LOLC = Obj->getLinkerOptionLoadCommand(Load); | |||
966 | DictScope Group(W, "Linker Options"); | |||
967 | W.printNumber("Size", LOLC.cmdsize); | |||
968 | ListScope D(W, "Strings"); | |||
969 | uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_option_command); | |||
970 | const char *P = Load.Ptr + sizeof(MachO::linker_option_command); | |||
971 | StringRef Data(P, DataSize); | |||
972 | for (unsigned i = 0; i < LOLC.count; ++i) { | |||
973 | std::pair<StringRef,StringRef> Split = Data.split('\0'); | |||
974 | W.printString("Value", Split.first); | |||
975 | Data = Split.second; | |||
976 | } | |||
977 | } | |||
978 | } | |||
979 | } |
1 | //===- ObjectFile.h - File format independent object file -------*- C++ -*-===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file declares a file format independent ObjectFile class. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #ifndef LLVM_OBJECT_OBJECTFILE_H | |||
14 | #define LLVM_OBJECT_OBJECTFILE_H | |||
15 | ||||
16 | #include "llvm/ADT/ArrayRef.h" | |||
17 | #include "llvm/ADT/Hashing.h" | |||
18 | #include "llvm/ADT/StringRef.h" | |||
19 | #include "llvm/ADT/Triple.h" | |||
20 | #include "llvm/ADT/iterator_range.h" | |||
21 | #include "llvm/BinaryFormat/Magic.h" | |||
22 | #include "llvm/BinaryFormat/Swift.h" | |||
23 | #include "llvm/Object/Binary.h" | |||
24 | #include "llvm/Object/Error.h" | |||
25 | #include "llvm/Object/SymbolicFile.h" | |||
26 | #include "llvm/Support/Casting.h" | |||
27 | #include "llvm/Support/Error.h" | |||
28 | #include "llvm/Support/MemoryBufferRef.h" | |||
29 | #include <cassert> | |||
30 | #include <cstdint> | |||
31 | #include <memory> | |||
32 | ||||
33 | namespace llvm { | |||
34 | ||||
35 | class SubtargetFeatures; | |||
36 | ||||
37 | namespace object { | |||
38 | ||||
39 | class COFFObjectFile; | |||
40 | class MachOObjectFile; | |||
41 | class ObjectFile; | |||
42 | class SectionRef; | |||
43 | class SymbolRef; | |||
44 | class symbol_iterator; | |||
45 | class WasmObjectFile; | |||
46 | ||||
47 | using section_iterator = content_iterator<SectionRef>; | |||
48 | ||||
49 | /// This is a value type class that represents a single relocation in the list | |||
50 | /// of relocations in the object file. | |||
51 | class RelocationRef { | |||
52 | DataRefImpl RelocationPimpl; | |||
53 | const ObjectFile *OwningObject = nullptr; | |||
54 | ||||
55 | public: | |||
56 | RelocationRef() = default; | |||
57 | RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); | |||
58 | ||||
59 | bool operator==(const RelocationRef &Other) const; | |||
60 | ||||
61 | void moveNext(); | |||
62 | ||||
63 | uint64_t getOffset() const; | |||
64 | symbol_iterator getSymbol() const; | |||
65 | uint64_t getType() const; | |||
66 | ||||
67 | /// Get a string that represents the type of this relocation. | |||
68 | /// | |||
69 | /// This is for display purposes only. | |||
70 | void getTypeName(SmallVectorImpl<char> &Result) const; | |||
71 | ||||
72 | DataRefImpl getRawDataRefImpl() const; | |||
73 | const ObjectFile *getObject() const; | |||
74 | }; | |||
75 | ||||
76 | using relocation_iterator = content_iterator<RelocationRef>; | |||
77 | ||||
78 | /// This is a value type class that represents a single section in the list of | |||
79 | /// sections in the object file. | |||
80 | class SectionRef { | |||
81 | friend class SymbolRef; | |||
82 | ||||
83 | DataRefImpl SectionPimpl; | |||
84 | const ObjectFile *OwningObject = nullptr; | |||
85 | ||||
86 | public: | |||
87 | SectionRef() = default; | |||
88 | SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); | |||
89 | ||||
90 | bool operator==(const SectionRef &Other) const; | |||
91 | bool operator!=(const SectionRef &Other) const; | |||
92 | bool operator<(const SectionRef &Other) const; | |||
93 | ||||
94 | void moveNext(); | |||
95 | ||||
96 | Expected<StringRef> getName() const; | |||
97 | uint64_t getAddress() const; | |||
98 | uint64_t getIndex() const; | |||
99 | uint64_t getSize() const; | |||
100 | Expected<StringRef> getContents() const; | |||
101 | ||||
102 | /// Get the alignment of this section as the actual value (not log 2). | |||
103 | uint64_t getAlignment() const; | |||
104 | ||||
105 | bool isCompressed() const; | |||
106 | /// Whether this section contains instructions. | |||
107 | bool isText() const; | |||
108 | /// Whether this section contains data, not instructions. | |||
109 | bool isData() const; | |||
110 | /// Whether this section contains BSS uninitialized data. | |||
111 | bool isBSS() const; | |||
112 | bool isVirtual() const; | |||
113 | bool isBitcode() const; | |||
114 | bool isStripped() const; | |||
115 | ||||
116 | /// Whether this section will be placed in the text segment, according to the | |||
117 | /// Berkeley size format. This is true if the section is allocatable, and | |||
118 | /// contains either code or readonly data. | |||
119 | bool isBerkeleyText() const; | |||
120 | /// Whether this section will be placed in the data segment, according to the | |||
121 | /// Berkeley size format. This is true if the section is allocatable and | |||
122 | /// contains data (e.g. PROGBITS), but is not text. | |||
123 | bool isBerkeleyData() const; | |||
124 | ||||
125 | /// Whether this section is a debug section. | |||
126 | bool isDebugSection() const; | |||
127 | ||||
128 | bool containsSymbol(SymbolRef S) const; | |||
129 | ||||
130 | relocation_iterator relocation_begin() const; | |||
131 | relocation_iterator relocation_end() const; | |||
132 | iterator_range<relocation_iterator> relocations() const { | |||
133 | return make_range(relocation_begin(), relocation_end()); | |||
134 | } | |||
135 | ||||
136 | /// Returns the related section if this section contains relocations. The | |||
137 | /// returned section may or may not have applied its relocations. | |||
138 | Expected<section_iterator> getRelocatedSection() const; | |||
139 | ||||
140 | DataRefImpl getRawDataRefImpl() const; | |||
141 | const ObjectFile *getObject() const; | |||
142 | }; | |||
143 | ||||
144 | struct SectionedAddress { | |||
145 | const static uint64_t UndefSection = UINT64_MAX(18446744073709551615UL); | |||
146 | ||||
147 | uint64_t Address = 0; | |||
148 | uint64_t SectionIndex = UndefSection; | |||
149 | }; | |||
150 | ||||
151 | inline bool operator<(const SectionedAddress &LHS, | |||
152 | const SectionedAddress &RHS) { | |||
153 | return std::tie(LHS.SectionIndex, LHS.Address) < | |||
154 | std::tie(RHS.SectionIndex, RHS.Address); | |||
155 | } | |||
156 | ||||
157 | inline bool operator==(const SectionedAddress &LHS, | |||
158 | const SectionedAddress &RHS) { | |||
159 | return std::tie(LHS.SectionIndex, LHS.Address) == | |||
160 | std::tie(RHS.SectionIndex, RHS.Address); | |||
161 | } | |||
162 | ||||
163 | raw_ostream &operator<<(raw_ostream &OS, const SectionedAddress &Addr); | |||
164 | ||||
165 | /// This is a value type class that represents a single symbol in the list of | |||
166 | /// symbols in the object file. | |||
167 | class SymbolRef : public BasicSymbolRef { | |||
168 | friend class SectionRef; | |||
169 | ||||
170 | public: | |||
171 | enum Type { | |||
172 | ST_Unknown, // Type not specified | |||
173 | ST_Other, | |||
174 | ST_Data, | |||
175 | ST_Debug, | |||
176 | ST_File, | |||
177 | ST_Function, | |||
178 | }; | |||
179 | ||||
180 | SymbolRef() = default; | |||
181 | SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); | |||
182 | SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) { | |||
183 | assert(isa<ObjectFile>(BasicSymbolRef::getObject()))(static_cast <bool> (isa<ObjectFile>(BasicSymbolRef ::getObject())) ? void (0) : __assert_fail ("isa<ObjectFile>(BasicSymbolRef::getObject())" , "llvm/include/llvm/Object/ObjectFile.h", 183, __extension__ __PRETTY_FUNCTION__)); | |||
184 | } | |||
185 | ||||
186 | Expected<StringRef> getName() const; | |||
187 | /// Returns the symbol virtual address (i.e. address at which it will be | |||
188 | /// mapped). | |||
189 | Expected<uint64_t> getAddress() const; | |||
190 | ||||
191 | /// Return the value of the symbol depending on the object this can be an | |||
192 | /// offset or a virtual address. | |||
193 | Expected<uint64_t> getValue() const; | |||
194 | ||||
195 | /// Get the alignment of this symbol as the actual value (not log 2). | |||
196 | uint32_t getAlignment() const; | |||
197 | uint64_t getCommonSize() const; | |||
198 | Expected<SymbolRef::Type> getType() const; | |||
199 | ||||
200 | /// Get section this symbol is defined in reference to. Result is | |||
201 | /// end_sections() if it is undefined or is an absolute symbol. | |||
202 | Expected<section_iterator> getSection() const; | |||
203 | ||||
204 | const ObjectFile *getObject() const; | |||
205 | }; | |||
206 | ||||
207 | class symbol_iterator : public basic_symbol_iterator { | |||
208 | public: | |||
209 | symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {} | |||
210 | symbol_iterator(const basic_symbol_iterator &B) | |||
211 | : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(), | |||
212 | cast<ObjectFile>(B->getObject()))) {} | |||
213 | ||||
214 | const SymbolRef *operator->() const { | |||
215 | const BasicSymbolRef &P = basic_symbol_iterator::operator *(); | |||
216 | return static_cast<const SymbolRef*>(&P); | |||
217 | } | |||
218 | ||||
219 | const SymbolRef &operator*() const { | |||
220 | const BasicSymbolRef &P = basic_symbol_iterator::operator *(); | |||
221 | return static_cast<const SymbolRef&>(P); | |||
222 | } | |||
223 | }; | |||
224 | ||||
225 | /// This class is the base class for all object file types. Concrete instances | |||
226 | /// of this object are created by createObjectFile, which figures out which type | |||
227 | /// to create. | |||
228 | class ObjectFile : public SymbolicFile { | |||
229 | virtual void anchor(); | |||
230 | ||||
231 | protected: | |||
232 | ObjectFile(unsigned int Type, MemoryBufferRef Source); | |||
233 | ||||
234 | const uint8_t *base() const { | |||
235 | return reinterpret_cast<const uint8_t *>(Data.getBufferStart()); | |||
236 | } | |||
237 | ||||
238 | // These functions are for SymbolRef to call internally. The main goal of | |||
239 | // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol | |||
240 | // entry in the memory mapped object file. SymbolPimpl cannot contain any | |||
241 | // virtual functions because then it could not point into the memory mapped | |||
242 | // file. | |||
243 | // | |||
244 | // Implementations assume that the DataRefImpl is valid and has not been | |||
245 | // modified externally. It's UB otherwise. | |||
246 | friend class SymbolRef; | |||
247 | ||||
248 | virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0; | |||
249 | Error printSymbolName(raw_ostream &OS, | |||
250 | DataRefImpl Symb) const override; | |||
251 | virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0; | |||
252 | virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0; | |||
253 | virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const; | |||
254 | virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0; | |||
255 | virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0; | |||
256 | virtual Expected<section_iterator> | |||
257 | getSymbolSection(DataRefImpl Symb) const = 0; | |||
258 | ||||
259 | // Same as above for SectionRef. | |||
260 | friend class SectionRef; | |||
261 | ||||
262 | virtual void moveSectionNext(DataRefImpl &Sec) const = 0; | |||
263 | virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const = 0; | |||
264 | virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; | |||
265 | virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0; | |||
266 | virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; | |||
267 | virtual Expected<ArrayRef<uint8_t>> | |||
268 | getSectionContents(DataRefImpl Sec) const = 0; | |||
269 | virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; | |||
270 | virtual bool isSectionCompressed(DataRefImpl Sec) const = 0; | |||
271 | virtual bool isSectionText(DataRefImpl Sec) const = 0; | |||
272 | virtual bool isSectionData(DataRefImpl Sec) const = 0; | |||
273 | virtual bool isSectionBSS(DataRefImpl Sec) const = 0; | |||
274 | // A section is 'virtual' if its contents aren't present in the object image. | |||
275 | virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; | |||
276 | virtual bool isSectionBitcode(DataRefImpl Sec) const; | |||
277 | virtual bool isSectionStripped(DataRefImpl Sec) const; | |||
278 | virtual bool isBerkeleyText(DataRefImpl Sec) const; | |||
279 | virtual bool isBerkeleyData(DataRefImpl Sec) const; | |||
280 | virtual bool isDebugSection(DataRefImpl Sec) const; | |||
281 | virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; | |||
282 | virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; | |||
283 | virtual Expected<section_iterator> getRelocatedSection(DataRefImpl Sec) const; | |||
284 | ||||
285 | // Same as above for RelocationRef. | |||
286 | friend class RelocationRef; | |||
287 | virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; | |||
288 | virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0; | |||
289 | virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; | |||
290 | virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0; | |||
291 | virtual void getRelocationTypeName(DataRefImpl Rel, | |||
292 | SmallVectorImpl<char> &Result) const = 0; | |||
293 | ||||
294 | virtual llvm::binaryformat::Swift5ReflectionSectionKind | |||
295 | mapReflectionSectionNameToEnumValue(StringRef SectionName) const { | |||
296 | return llvm::binaryformat::Swift5ReflectionSectionKind::unknown; | |||
297 | }; | |||
298 | ||||
299 | Expected<uint64_t> getSymbolValue(DataRefImpl Symb) const; | |||
300 | ||||
301 | public: | |||
302 | ObjectFile() = delete; | |||
303 | ObjectFile(const ObjectFile &other) = delete; | |||
304 | ||||
305 | uint64_t getCommonSymbolSize(DataRefImpl Symb) const { | |||
306 | Expected<uint32_t> SymbolFlagsOrErr = getSymbolFlags(Symb); | |||
307 | if (!SymbolFlagsOrErr) | |||
308 | // TODO: Actually report errors helpfully. | |||
309 | report_fatal_error(SymbolFlagsOrErr.takeError()); | |||
310 | assert(*SymbolFlagsOrErr & SymbolRef::SF_Common)(static_cast <bool> (*SymbolFlagsOrErr & SymbolRef:: SF_Common) ? void (0) : __assert_fail ("*SymbolFlagsOrErr & SymbolRef::SF_Common" , "llvm/include/llvm/Object/ObjectFile.h", 310, __extension__ __PRETTY_FUNCTION__)); | |||
311 | return getCommonSymbolSizeImpl(Symb); | |||
312 | } | |||
313 | ||||
314 | virtual std::vector<SectionRef> dynamic_relocation_sections() const { | |||
315 | return std::vector<SectionRef>(); | |||
316 | } | |||
317 | ||||
318 | using symbol_iterator_range = iterator_range<symbol_iterator>; | |||
319 | symbol_iterator_range symbols() const { | |||
320 | return symbol_iterator_range(symbol_begin(), symbol_end()); | |||
321 | } | |||
322 | ||||
323 | virtual section_iterator section_begin() const = 0; | |||
324 | virtual section_iterator section_end() const = 0; | |||
325 | ||||
326 | using section_iterator_range = iterator_range<section_iterator>; | |||
327 | section_iterator_range sections() const { | |||
328 | return section_iterator_range(section_begin(), section_end()); | |||
329 | } | |||
330 | ||||
331 | /// The number of bytes used to represent an address in this object | |||
332 | /// file format. | |||
333 | virtual uint8_t getBytesInAddress() const = 0; | |||
334 | ||||
335 | virtual StringRef getFileFormatName() const = 0; | |||
336 | virtual Triple::ArchType getArch() const = 0; | |||
337 | virtual SubtargetFeatures getFeatures() const = 0; | |||
338 | virtual Optional<StringRef> tryGetCPUName() const { return None; }; | |||
339 | virtual void setARMSubArch(Triple &TheTriple) const { } | |||
340 | virtual Expected<uint64_t> getStartAddress() const { | |||
341 | return errorCodeToError(object_error::parse_failed); | |||
342 | }; | |||
343 | ||||
344 | /// Create a triple from the data in this object file. | |||
345 | Triple makeTriple() const; | |||
346 | ||||
347 | /// Maps a debug section name to a standard DWARF section name. | |||
348 | virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; } | |||
349 | ||||
350 | /// True if this is a relocatable object (.o/.obj). | |||
351 | virtual bool isRelocatableObject() const = 0; | |||
352 | ||||
353 | /// True if the reflection section can be stripped by the linker. | |||
354 | bool isReflectionSectionStrippable( | |||
355 | llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind) | |||
356 | const; | |||
357 | ||||
358 | /// @returns Pointer to ObjectFile subclass to handle this type of object. | |||
359 | /// @param ObjectPath The path to the object file. ObjectPath.isObject must | |||
360 | /// return true. | |||
361 | /// Create ObjectFile from path. | |||
362 | static Expected<OwningBinary<ObjectFile>> | |||
363 | createObjectFile(StringRef ObjectPath); | |||
364 | ||||
365 | static Expected<std::unique_ptr<ObjectFile>> | |||
366 | createObjectFile(MemoryBufferRef Object, llvm::file_magic Type, | |||
367 | bool InitContent = true); | |||
368 | static Expected<std::unique_ptr<ObjectFile>> | |||
369 | createObjectFile(MemoryBufferRef Object) { | |||
370 | return createObjectFile(Object, llvm::file_magic::unknown); | |||
371 | } | |||
372 | ||||
373 | static bool classof(const Binary *v) { | |||
374 | return v->isObject(); | |||
375 | } | |||
376 | ||||
377 | static Expected<std::unique_ptr<COFFObjectFile>> | |||
378 | createCOFFObjectFile(MemoryBufferRef Object); | |||
379 | ||||
380 | static Expected<std::unique_ptr<ObjectFile>> | |||
381 | createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); | |||
382 | ||||
383 | static Expected<std::unique_ptr<ObjectFile>> | |||
384 | createELFObjectFile(MemoryBufferRef Object, bool InitContent = true); | |||
385 | ||||
386 | static Expected<std::unique_ptr<MachOObjectFile>> | |||
387 | createMachOObjectFile(MemoryBufferRef Object, | |||
388 | uint32_t UniversalCputype = 0, | |||
389 | uint32_t UniversalIndex = 0); | |||
390 | ||||
391 | static Expected<std::unique_ptr<WasmObjectFile>> | |||
392 | createWasmObjectFile(MemoryBufferRef Object); | |||
393 | }; | |||
394 | ||||
395 | // Inline function definitions. | |||
396 | inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) | |||
397 | : BasicSymbolRef(SymbolP, Owner) {} | |||
398 | ||||
399 | inline Expected<StringRef> SymbolRef::getName() const { | |||
400 | return getObject()->getSymbolName(getRawDataRefImpl()); | |||
401 | } | |||
402 | ||||
403 | inline Expected<uint64_t> SymbolRef::getAddress() const { | |||
404 | return getObject()->getSymbolAddress(getRawDataRefImpl()); | |||
405 | } | |||
406 | ||||
407 | inline Expected<uint64_t> SymbolRef::getValue() const { | |||
408 | return getObject()->getSymbolValue(getRawDataRefImpl()); | |||
409 | } | |||
410 | ||||
411 | inline uint32_t SymbolRef::getAlignment() const { | |||
412 | return getObject()->getSymbolAlignment(getRawDataRefImpl()); | |||
413 | } | |||
414 | ||||
415 | inline uint64_t SymbolRef::getCommonSize() const { | |||
416 | return getObject()->getCommonSymbolSize(getRawDataRefImpl()); | |||
417 | } | |||
418 | ||||
419 | inline Expected<section_iterator> SymbolRef::getSection() const { | |||
420 | return getObject()->getSymbolSection(getRawDataRefImpl()); | |||
421 | } | |||
422 | ||||
423 | inline Expected<SymbolRef::Type> SymbolRef::getType() const { | |||
424 | return getObject()->getSymbolType(getRawDataRefImpl()); | |||
425 | } | |||
426 | ||||
427 | inline const ObjectFile *SymbolRef::getObject() const { | |||
428 | const SymbolicFile *O = BasicSymbolRef::getObject(); | |||
429 | return cast<ObjectFile>(O); | |||
430 | } | |||
431 | ||||
432 | /// SectionRef | |||
433 | inline SectionRef::SectionRef(DataRefImpl SectionP, | |||
434 | const ObjectFile *Owner) | |||
435 | : SectionPimpl(SectionP) | |||
436 | , OwningObject(Owner) {} | |||
437 | ||||
438 | inline bool SectionRef::operator==(const SectionRef &Other) const { | |||
439 | return OwningObject == Other.OwningObject && | |||
440 | SectionPimpl == Other.SectionPimpl; | |||
441 | } | |||
442 | ||||
443 | inline bool SectionRef::operator!=(const SectionRef &Other) const { | |||
444 | return !(*this == Other); | |||
445 | } | |||
446 | ||||
447 | inline bool SectionRef::operator<(const SectionRef &Other) const { | |||
448 | assert(OwningObject == Other.OwningObject)(static_cast <bool> (OwningObject == Other.OwningObject ) ? void (0) : __assert_fail ("OwningObject == Other.OwningObject" , "llvm/include/llvm/Object/ObjectFile.h", 448, __extension__ __PRETTY_FUNCTION__)); | |||
449 | return SectionPimpl < Other.SectionPimpl; | |||
450 | } | |||
451 | ||||
452 | inline void SectionRef::moveNext() { | |||
453 | return OwningObject->moveSectionNext(SectionPimpl); | |||
454 | } | |||
455 | ||||
456 | inline Expected<StringRef> SectionRef::getName() const { | |||
457 | return OwningObject->getSectionName(SectionPimpl); | |||
458 | } | |||
459 | ||||
460 | inline uint64_t SectionRef::getAddress() const { | |||
461 | return OwningObject->getSectionAddress(SectionPimpl); | |||
462 | } | |||
463 | ||||
464 | inline uint64_t SectionRef::getIndex() const { | |||
465 | return OwningObject->getSectionIndex(SectionPimpl); | |||
466 | } | |||
467 | ||||
468 | inline uint64_t SectionRef::getSize() const { | |||
469 | return OwningObject->getSectionSize(SectionPimpl); | |||
470 | } | |||
471 | ||||
472 | inline Expected<StringRef> SectionRef::getContents() const { | |||
473 | Expected<ArrayRef<uint8_t>> Res = | |||
474 | OwningObject->getSectionContents(SectionPimpl); | |||
| ||||
475 | if (!Res) | |||
476 | return Res.takeError(); | |||
477 | return StringRef(reinterpret_cast<const char *>(Res->data()), Res->size()); | |||
478 | } | |||
479 | ||||
480 | inline uint64_t SectionRef::getAlignment() const { | |||
481 | return OwningObject->getSectionAlignment(SectionPimpl); | |||
482 | } | |||
483 | ||||
484 | inline bool SectionRef::isCompressed() const { | |||
485 | return OwningObject->isSectionCompressed(SectionPimpl); | |||
486 | } | |||
487 | ||||
488 | inline bool SectionRef::isText() const { | |||
489 | return OwningObject->isSectionText(SectionPimpl); | |||
490 | } | |||
491 | ||||
492 | inline bool SectionRef::isData() const { | |||
493 | return OwningObject->isSectionData(SectionPimpl); | |||
494 | } | |||
495 | ||||
496 | inline bool SectionRef::isBSS() const { | |||
497 | return OwningObject->isSectionBSS(SectionPimpl); | |||
498 | } | |||
499 | ||||
500 | inline bool SectionRef::isVirtual() const { | |||
501 | return OwningObject->isSectionVirtual(SectionPimpl); | |||
502 | } | |||
503 | ||||
504 | inline bool SectionRef::isBitcode() const { | |||
505 | return OwningObject->isSectionBitcode(SectionPimpl); | |||
506 | } | |||
507 | ||||
508 | inline bool SectionRef::isStripped() const { | |||
509 | return OwningObject->isSectionStripped(SectionPimpl); | |||
510 | } | |||
511 | ||||
512 | inline bool SectionRef::isBerkeleyText() const { | |||
513 | return OwningObject->isBerkeleyText(SectionPimpl); | |||
514 | } | |||
515 | ||||
516 | inline bool SectionRef::isBerkeleyData() const { | |||
517 | return OwningObject->isBerkeleyData(SectionPimpl); | |||
518 | } | |||
519 | ||||
520 | inline bool SectionRef::isDebugSection() const { | |||
521 | return OwningObject->isDebugSection(SectionPimpl); | |||
522 | } | |||
523 | ||||
524 | inline relocation_iterator SectionRef::relocation_begin() const { | |||
525 | return OwningObject->section_rel_begin(SectionPimpl); | |||
526 | } | |||
527 | ||||
528 | inline relocation_iterator SectionRef::relocation_end() const { | |||
529 | return OwningObject->section_rel_end(SectionPimpl); | |||
530 | } | |||
531 | ||||
532 | inline Expected<section_iterator> SectionRef::getRelocatedSection() const { | |||
533 | return OwningObject->getRelocatedSection(SectionPimpl); | |||
534 | } | |||
535 | ||||
536 | inline DataRefImpl SectionRef::getRawDataRefImpl() const { | |||
537 | return SectionPimpl; | |||
538 | } | |||
539 | ||||
540 | inline const ObjectFile *SectionRef::getObject() const { | |||
541 | return OwningObject; | |||
542 | } | |||
543 | ||||
544 | /// RelocationRef | |||
545 | inline RelocationRef::RelocationRef(DataRefImpl RelocationP, | |||
546 | const ObjectFile *Owner) | |||
547 | : RelocationPimpl(RelocationP) | |||
548 | , OwningObject(Owner) {} | |||
549 | ||||
550 | inline bool RelocationRef::operator==(const RelocationRef &Other) const { | |||
551 | return RelocationPimpl == Other.RelocationPimpl; | |||
552 | } | |||
553 | ||||
554 | inline void RelocationRef::moveNext() { | |||
555 | return OwningObject->moveRelocationNext(RelocationPimpl); | |||
556 | } | |||
557 | ||||
558 | inline uint64_t RelocationRef::getOffset() const { | |||
559 | return OwningObject->getRelocationOffset(RelocationPimpl); | |||
560 | } | |||
561 | ||||
562 | inline symbol_iterator RelocationRef::getSymbol() const { | |||
563 | return OwningObject->getRelocationSymbol(RelocationPimpl); | |||
564 | } | |||
565 | ||||
566 | inline uint64_t RelocationRef::getType() const { | |||
567 | return OwningObject->getRelocationType(RelocationPimpl); | |||
568 | } | |||
569 | ||||
570 | inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const { | |||
571 | return OwningObject->getRelocationTypeName(RelocationPimpl, Result); | |||
572 | } | |||
573 | ||||
574 | inline DataRefImpl RelocationRef::getRawDataRefImpl() const { | |||
575 | return RelocationPimpl; | |||
576 | } | |||
577 | ||||
578 | inline const ObjectFile *RelocationRef::getObject() const { | |||
579 | return OwningObject; | |||
580 | } | |||
581 | ||||
582 | } // end namespace object | |||
583 | ||||
584 | template <> struct DenseMapInfo<object::SectionRef> { | |||
585 | static bool isEqual(const object::SectionRef &A, | |||
586 | const object::SectionRef &B) { | |||
587 | return A == B; | |||
588 | } | |||
589 | static object::SectionRef getEmptyKey() { | |||
590 | return object::SectionRef({}, nullptr); | |||
591 | } | |||
592 | static object::SectionRef getTombstoneKey() { | |||
593 | object::DataRefImpl TS; | |||
594 | TS.p = (uintptr_t)-1; | |||
595 | return object::SectionRef(TS, nullptr); | |||
596 | } | |||
597 | static unsigned getHashValue(const object::SectionRef &Sec) { | |||
598 | object::DataRefImpl Raw = Sec.getRawDataRefImpl(); | |||
599 | return hash_combine(Raw.p, Raw.d.a, Raw.d.b); | |||
600 | } | |||
601 | }; | |||
602 | ||||
603 | } // end namespace llvm | |||
604 | ||||
605 | #endif // LLVM_OBJECT_OBJECTFILE_H |