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