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