Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
35231 views
//===- MachODumper.cpp - Object file dumping utility for llvm -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the MachO-specific dumper for llvm-readobj.9//10//===----------------------------------------------------------------------===//1112#include "ObjDumper.h"13#include "StackMapPrinter.h"14#include "llvm-readobj.h"15#include "llvm/ADT/SmallString.h"16#include "llvm/ADT/StringExtras.h"17#include "llvm/Object/MachO.h"18#include "llvm/Support/BinaryStreamReader.h"19#include "llvm/Support/Casting.h"20#include "llvm/Support/ScopedPrinter.h"2122using namespace llvm;23using namespace object;2425namespace {2627class MachODumper : public ObjDumper {28public:29MachODumper(const MachOObjectFile *Obj, ScopedPrinter &Writer)30: ObjDumper(Writer, Obj->getFileName()), Obj(Obj) {}3132void printFileHeaders() override;33void printSectionHeaders() override;34void printRelocations() override;35void printUnwindInfo() override;36void printStackMap() const override;37void printCGProfile() override;3839void printNeededLibraries() override;4041bool canCompareSymbols() const override { return true; }42bool compareSymbolsByName(object::SymbolRef LHS,43object::SymbolRef RHS) const override;44bool compareSymbolsByType(object::SymbolRef LHS,45object::SymbolRef RHS) const override;46// MachO-specific.47void printMachODataInCode() override;48void printMachOVersionMin() override;49void printMachODysymtab() override;50void printMachOSegment() override;51void printMachOIndirectSymbols() override;52void printMachOLinkerOptions () override;5354private:55template<class MachHeader>56void printFileHeaders(const MachHeader &Header);5758StringRef getSymbolName(const SymbolRef &Symbol) const;59uint8_t getSymbolType(const SymbolRef &Symbol) const;6061void printSymbols(bool ExtraSymInfo) override;62void printSymbols(std::optional<SymbolComparator> SymComp) override;63void printDynamicSymbols() override;64void printDynamicSymbols(std::optional<SymbolComparator> SymComp) override;65void printSymbol(const SymbolRef &Symbol, ScopedPrinter &W);66void printSymbol(const SymbolRef &Symbol);6768void printRelocation(const RelocationRef &Reloc);6970void printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc);7172void printSectionHeaders(const MachOObjectFile *Obj);7374const MachOObjectFile *Obj;75};7677} // namespace787980namespace llvm {8182std::unique_ptr<ObjDumper> createMachODumper(const object::MachOObjectFile &Obj,83ScopedPrinter &Writer) {84return std::make_unique<MachODumper>(&Obj, Writer);85}8687} // namespace llvm8889const EnumEntry<uint32_t> MachOMagics[] = {90{ "Magic", MachO::MH_MAGIC },91{ "Cigam", MachO::MH_CIGAM },92{ "Magic64", MachO::MH_MAGIC_64 },93{ "Cigam64", MachO::MH_CIGAM_64 },94{ "FatMagic", MachO::FAT_MAGIC },95{ "FatCigam", MachO::FAT_CIGAM },96};9798const EnumEntry<uint32_t> MachOHeaderFileTypes[] = {99{ "Relocatable", MachO::MH_OBJECT },100{ "Executable", MachO::MH_EXECUTE },101{ "FixedVMLibrary", MachO::MH_FVMLIB },102{ "Core", MachO::MH_CORE },103{ "PreloadedExecutable", MachO::MH_PRELOAD },104{ "DynamicLibrary", MachO::MH_DYLIB },105{ "DynamicLinker", MachO::MH_DYLINKER },106{ "Bundle", MachO::MH_BUNDLE },107{ "DynamicLibraryStub", MachO::MH_DYLIB_STUB },108{ "DWARFSymbol", MachO::MH_DSYM },109{ "KextBundle", MachO::MH_KEXT_BUNDLE },110};111112const EnumEntry<uint32_t> MachOHeaderCpuTypes[] = {113{ "Any" , static_cast<uint32_t>(MachO::CPU_TYPE_ANY) },114{ "X86" , MachO::CPU_TYPE_X86 },115{ "X86-64" , MachO::CPU_TYPE_X86_64 },116{ "Mc98000" , MachO::CPU_TYPE_MC98000 },117{ "Arm" , MachO::CPU_TYPE_ARM },118{ "Arm64" , MachO::CPU_TYPE_ARM64 },119{ "Sparc" , MachO::CPU_TYPE_SPARC },120{ "PowerPC" , MachO::CPU_TYPE_POWERPC },121{ "PowerPC64" , MachO::CPU_TYPE_POWERPC64 },122};123124const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX86[] = {125LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL),126LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_386),127LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486),128LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486SX),129LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_586),130LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTPRO),131LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M3),132LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M5),133LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON),134LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON_MOBILE),135LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3),136LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_M),137LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_XEON),138LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_M),139LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4),140LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4_M),141LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM),142LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM_2),143LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON),144LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON_MP),145};146147const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX64[] = {148LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_ALL),149LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_ARCH1),150LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_H),151};152153const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM[] = {154LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_ALL),155LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V4T),156LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6),157LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5),158LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5TEJ),159LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_XSCALE),160LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7),161LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7S),162LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7K),163LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6M),164LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7M),165LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM),166};167168const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM64[] = {169LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL),170LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_V8),171LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64E),172};173174const EnumEntry<uint32_t> MachOHeaderCpuSubtypesSPARC[] = {175LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_SPARC_ALL),176};177178const EnumEntry<uint32_t> MachOHeaderCpuSubtypesPPC[] = {179LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_ALL),180LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_601),181LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_602),182LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603),183LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603e),184LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603ev),185LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604),186LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604e),187LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_620),188LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_750),189LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7400),190LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7450),191LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_970),192};193194const EnumEntry<uint32_t> MachOHeaderFlags[] = {195LLVM_READOBJ_ENUM_ENT(MachO, MH_NOUNDEFS),196LLVM_READOBJ_ENUM_ENT(MachO, MH_INCRLINK),197LLVM_READOBJ_ENUM_ENT(MachO, MH_DYLDLINK),198LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDATLOAD),199LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBOUND),200LLVM_READOBJ_ENUM_ENT(MachO, MH_SPLIT_SEGS),201LLVM_READOBJ_ENUM_ENT(MachO, MH_LAZY_INIT),202LLVM_READOBJ_ENUM_ENT(MachO, MH_TWOLEVEL),203LLVM_READOBJ_ENUM_ENT(MachO, MH_FORCE_FLAT),204LLVM_READOBJ_ENUM_ENT(MachO, MH_NOMULTIDEFS),205LLVM_READOBJ_ENUM_ENT(MachO, MH_NOFIXPREBINDING),206LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBINDABLE),207LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLMODSBOUND),208LLVM_READOBJ_ENUM_ENT(MachO, MH_SUBSECTIONS_VIA_SYMBOLS),209LLVM_READOBJ_ENUM_ENT(MachO, MH_CANONICAL),210LLVM_READOBJ_ENUM_ENT(MachO, MH_WEAK_DEFINES),211LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDS_TO_WEAK),212LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLOW_STACK_EXECUTION),213LLVM_READOBJ_ENUM_ENT(MachO, MH_ROOT_SAFE),214LLVM_READOBJ_ENUM_ENT(MachO, MH_SETUID_SAFE),215LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_REEXPORTED_DYLIBS),216LLVM_READOBJ_ENUM_ENT(MachO, MH_PIE),217LLVM_READOBJ_ENUM_ENT(MachO, MH_DEAD_STRIPPABLE_DYLIB),218LLVM_READOBJ_ENUM_ENT(MachO, MH_HAS_TLV_DESCRIPTORS),219LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_HEAP_EXECUTION),220LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE),221};222223const EnumEntry<unsigned> MachOSectionTypes[] = {224{ "Regular" , MachO::S_REGULAR },225{ "ZeroFill" , MachO::S_ZEROFILL },226{ "CStringLiterals" , MachO::S_CSTRING_LITERALS },227{ "4ByteLiterals" , MachO::S_4BYTE_LITERALS },228{ "8ByteLiterals" , MachO::S_8BYTE_LITERALS },229{ "LiteralPointers" , MachO::S_LITERAL_POINTERS },230{ "NonLazySymbolPointers" , MachO::S_NON_LAZY_SYMBOL_POINTERS },231{ "LazySymbolPointers" , MachO::S_LAZY_SYMBOL_POINTERS },232{ "SymbolStubs" , MachO::S_SYMBOL_STUBS },233{ "ModInitFuncPointers" , MachO::S_MOD_INIT_FUNC_POINTERS },234{ "ModTermFuncPointers" , MachO::S_MOD_TERM_FUNC_POINTERS },235{ "Coalesced" , MachO::S_COALESCED },236{ "GBZeroFill" , MachO::S_GB_ZEROFILL },237{ "Interposing" , MachO::S_INTERPOSING },238{ "16ByteLiterals" , MachO::S_16BYTE_LITERALS },239{ "DTraceDOF" , MachO::S_DTRACE_DOF },240{ "LazyDylibSymbolPointers" , MachO::S_LAZY_DYLIB_SYMBOL_POINTERS },241{ "ThreadLocalRegular" , MachO::S_THREAD_LOCAL_REGULAR },242{ "ThreadLocalZerofill" , MachO::S_THREAD_LOCAL_ZEROFILL },243{ "ThreadLocalVariables" , MachO::S_THREAD_LOCAL_VARIABLES },244{ "ThreadLocalVariablePointers" , MachO::S_THREAD_LOCAL_VARIABLE_POINTERS },245{ "ThreadLocalInitFunctionPointers", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS }246};247248const EnumEntry<unsigned> MachOSectionAttributes[] = {249{ "LocReloc" , 1 << 0 /*S_ATTR_LOC_RELOC */ },250{ "ExtReloc" , 1 << 1 /*S_ATTR_EXT_RELOC */ },251{ "SomeInstructions" , 1 << 2 /*S_ATTR_SOME_INSTRUCTIONS */ },252{ "Debug" , 1 << 17 /*S_ATTR_DEBUG */ },253{ "SelfModifyingCode", 1 << 18 /*S_ATTR_SELF_MODIFYING_CODE*/ },254{ "LiveSupport" , 1 << 19 /*S_ATTR_LIVE_SUPPORT */ },255{ "NoDeadStrip" , 1 << 20 /*S_ATTR_NO_DEAD_STRIP */ },256{ "StripStaticSyms" , 1 << 21 /*S_ATTR_STRIP_STATIC_SYMS */ },257{ "NoTOC" , 1 << 22 /*S_ATTR_NO_TOC */ },258{ "PureInstructions" , 1 << 23 /*S_ATTR_PURE_INSTRUCTIONS */ },259};260261const EnumEntry<unsigned> MachOSymbolRefTypes[] = {262{ "UndefinedNonLazy", 0 },263{ "ReferenceFlagUndefinedLazy", 1 },264{ "ReferenceFlagDefined", 2 },265{ "ReferenceFlagPrivateDefined", 3 },266{ "ReferenceFlagPrivateUndefinedNonLazy", 4 },267{ "ReferenceFlagPrivateUndefinedLazy", 5 }268};269270const EnumEntry<unsigned> MachOSymbolFlags[] = {271{ "ThumbDef", 0x8 },272{ "ReferencedDynamically", 0x10 },273{ "NoDeadStrip", 0x20 },274{ "WeakRef", 0x40 },275{ "WeakDef", 0x80 },276{ "SymbolResolver", 0x100 },277{ "AltEntry", 0x200 },278{ "ColdFunc", 0x400 },279};280281const EnumEntry<unsigned> MachOSymbolTypes[] = {282{ "Undef", 0x0 },283{ "Abs", 0x2 },284{ "Indirect", 0xA },285{ "PreboundUndef", 0xC },286{ "Section", 0xE }287};288289namespace {290struct MachOSection {291ArrayRef<char> Name;292ArrayRef<char> SegmentName;293uint64_t Address;294uint64_t Size;295uint32_t Offset;296uint32_t Alignment;297uint32_t RelocationTableOffset;298uint32_t NumRelocationTableEntries;299uint32_t Flags;300uint32_t Reserved1;301uint32_t Reserved2;302uint32_t Reserved3;303};304305struct MachOSegment {306std::string CmdName;307std::string SegName;308uint64_t cmdsize;309uint64_t vmaddr;310uint64_t vmsize;311uint64_t fileoff;312uint64_t filesize;313uint32_t maxprot;314uint32_t initprot;315uint32_t nsects;316uint32_t flags;317};318319struct MachOSymbol {320uint32_t StringIndex;321uint8_t Type;322uint8_t SectionIndex;323uint16_t Flags;324uint64_t Value;325};326}327328static std::string getMask(uint32_t prot)329{330// TODO (davide): This always assumes prot is valid.331// Catch mistakes and report if needed.332std::string Prot;333Prot = "";334Prot += (prot & MachO::VM_PROT_READ) ? "r" : "-";335Prot += (prot & MachO::VM_PROT_WRITE) ? "w" : "-";336Prot += (prot & MachO::VM_PROT_EXECUTE) ? "x" : "-";337return Prot;338}339340static void getSection(const MachOObjectFile *Obj,341DataRefImpl Sec,342MachOSection &Section) {343if (!Obj->is64Bit()) {344MachO::section Sect = Obj->getSection(Sec);345Section.Address = Sect.addr;346Section.Size = Sect.size;347Section.Offset = Sect.offset;348Section.Alignment = Sect.align;349Section.RelocationTableOffset = Sect.reloff;350Section.NumRelocationTableEntries = Sect.nreloc;351Section.Flags = Sect.flags;352Section.Reserved1 = Sect.reserved1;353Section.Reserved2 = Sect.reserved2;354return;355}356MachO::section_64 Sect = Obj->getSection64(Sec);357Section.Address = Sect.addr;358Section.Size = Sect.size;359Section.Offset = Sect.offset;360Section.Alignment = Sect.align;361Section.RelocationTableOffset = Sect.reloff;362Section.NumRelocationTableEntries = Sect.nreloc;363Section.Flags = Sect.flags;364Section.Reserved1 = Sect.reserved1;365Section.Reserved2 = Sect.reserved2;366Section.Reserved3 = Sect.reserved3;367}368369static void getSegment(const MachOObjectFile *Obj,370const MachOObjectFile::LoadCommandInfo &L,371MachOSegment &Segment) {372if (!Obj->is64Bit()) {373MachO::segment_command SC = Obj->getSegmentLoadCommand(L);374Segment.CmdName = "LC_SEGMENT";375Segment.SegName = SC.segname;376Segment.cmdsize = SC.cmdsize;377Segment.vmaddr = SC.vmaddr;378Segment.vmsize = SC.vmsize;379Segment.fileoff = SC.fileoff;380Segment.filesize = SC.filesize;381Segment.maxprot = SC.maxprot;382Segment.initprot = SC.initprot;383Segment.nsects = SC.nsects;384Segment.flags = SC.flags;385return;386}387MachO::segment_command_64 SC = Obj->getSegment64LoadCommand(L);388Segment.CmdName = "LC_SEGMENT_64";389Segment.SegName = SC.segname;390Segment.cmdsize = SC.cmdsize;391Segment.vmaddr = SC.vmaddr;392Segment.vmsize = SC.vmsize;393Segment.fileoff = SC.fileoff;394Segment.filesize = SC.filesize;395Segment.maxprot = SC.maxprot;396Segment.initprot = SC.initprot;397Segment.nsects = SC.nsects;398Segment.flags = SC.flags;399}400401static void getSymbol(const MachOObjectFile *Obj,402DataRefImpl DRI,403MachOSymbol &Symbol) {404if (!Obj->is64Bit()) {405MachO::nlist Entry = Obj->getSymbolTableEntry(DRI);406Symbol.StringIndex = Entry.n_strx;407Symbol.Type = Entry.n_type;408Symbol.SectionIndex = Entry.n_sect;409Symbol.Flags = Entry.n_desc;410Symbol.Value = Entry.n_value;411return;412}413MachO::nlist_64 Entry = Obj->getSymbol64TableEntry(DRI);414Symbol.StringIndex = Entry.n_strx;415Symbol.Type = Entry.n_type;416Symbol.SectionIndex = Entry.n_sect;417Symbol.Flags = Entry.n_desc;418Symbol.Value = Entry.n_value;419}420421void MachODumper::printFileHeaders() {422DictScope H(W, "MachHeader");423if (!Obj->is64Bit()) {424printFileHeaders(Obj->getHeader());425} else {426printFileHeaders(Obj->getHeader64());427W.printHex("Reserved", Obj->getHeader64().reserved);428}429}430431template<class MachHeader>432void MachODumper::printFileHeaders(const MachHeader &Header) {433W.printEnum("Magic", Header.magic, ArrayRef(MachOMagics));434W.printEnum("CpuType", Header.cputype, ArrayRef(MachOHeaderCpuTypes));435uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK;436switch (Header.cputype) {437case MachO::CPU_TYPE_X86:438W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesX86));439break;440case MachO::CPU_TYPE_X86_64:441W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesX64));442break;443case MachO::CPU_TYPE_ARM:444W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesARM));445break;446case MachO::CPU_TYPE_POWERPC:447W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesPPC));448break;449case MachO::CPU_TYPE_SPARC:450W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesSPARC));451break;452case MachO::CPU_TYPE_ARM64:453W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesARM64));454break;455case MachO::CPU_TYPE_POWERPC64:456default:457W.printHex("CpuSubtype", subtype);458}459W.printEnum("FileType", Header.filetype, ArrayRef(MachOHeaderFileTypes));460W.printNumber("NumOfLoadCommands", Header.ncmds);461W.printNumber("SizeOfLoadCommands", Header.sizeofcmds);462W.printFlags("Flags", Header.flags, ArrayRef(MachOHeaderFlags));463}464465void MachODumper::printSectionHeaders() { return printSectionHeaders(Obj); }466467void MachODumper::printSectionHeaders(const MachOObjectFile *Obj) {468ListScope Group(W, "Sections");469470int SectionIndex = -1;471for (const SectionRef &Section : Obj->sections()) {472++SectionIndex;473474MachOSection MOSection;475getSection(Obj, Section.getRawDataRefImpl(), MOSection);476DataRefImpl DR = Section.getRawDataRefImpl();477StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());478ArrayRef<char> RawName = Obj->getSectionRawName(DR);479StringRef SegmentName = Obj->getSectionFinalSegmentName(DR);480ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR);481482DictScope SectionD(W, "Section");483W.printNumber("Index", SectionIndex);484W.printBinary("Name", Name, RawName);485W.printBinary("Segment", SegmentName, RawSegmentName);486W.printHex("Address", MOSection.Address);487W.printHex("Size", MOSection.Size);488W.printNumber("Offset", MOSection.Offset);489W.printNumber("Alignment", MOSection.Alignment);490W.printHex("RelocationOffset", MOSection.RelocationTableOffset);491W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries);492W.printEnum("Type", MOSection.Flags & 0xFF, ArrayRef(MachOSectionTypes));493W.printFlags("Attributes", MOSection.Flags >> 8,494ArrayRef(MachOSectionAttributes));495W.printHex("Reserved1", MOSection.Reserved1);496W.printHex("Reserved2", MOSection.Reserved2);497if (Obj->is64Bit())498W.printHex("Reserved3", MOSection.Reserved3);499500if (opts::SectionRelocations) {501ListScope D(W, "Relocations");502for (const RelocationRef &Reloc : Section.relocations())503printRelocation(Reloc);504}505506if (opts::SectionSymbols) {507ListScope D(W, "Symbols");508for (const SymbolRef &Symbol : Obj->symbols()) {509if (!Section.containsSymbol(Symbol))510continue;511512printSymbol(Symbol);513}514}515516if (opts::SectionData && !Section.isBSS())517W.printBinaryBlock("SectionData", unwrapOrError(Obj->getFileName(),518Section.getContents()));519}520}521522void MachODumper::printRelocations() {523ListScope D(W, "Relocations");524525std::error_code EC;526for (const SectionRef &Section : Obj->sections()) {527StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());528bool PrintedGroup = false;529for (const RelocationRef &Reloc : Section.relocations()) {530if (!PrintedGroup) {531W.startLine() << "Section " << Name << " {\n";532W.indent();533PrintedGroup = true;534}535536printRelocation(Reloc);537}538539if (PrintedGroup) {540W.unindent();541W.startLine() << "}\n";542}543}544}545546void MachODumper::printRelocation(const RelocationRef &Reloc) {547return printRelocation(Obj, Reloc);548}549550void MachODumper::printRelocation(const MachOObjectFile *Obj,551const RelocationRef &Reloc) {552uint64_t Offset = Reloc.getOffset();553SmallString<32> RelocName;554Reloc.getTypeName(RelocName);555556DataRefImpl DR = Reloc.getRawDataRefImpl();557MachO::any_relocation_info RE = Obj->getRelocation(DR);558bool IsScattered = Obj->isRelocationScattered(RE);559bool IsExtern = !IsScattered && Obj->getPlainRelocationExternal(RE);560561StringRef TargetName;562if (IsExtern) {563symbol_iterator Symbol = Reloc.getSymbol();564if (Symbol != Obj->symbol_end()) {565TargetName = getSymbolName(*Symbol);566}567} else if (!IsScattered) {568section_iterator SecI = Obj->getRelocationSection(DR);569if (SecI != Obj->section_end())570TargetName = unwrapOrError(Obj->getFileName(), SecI->getName());571}572if (TargetName.empty())573TargetName = "-";574575if (opts::ExpandRelocs) {576DictScope Group(W, "Relocation");577W.printHex("Offset", Offset);578W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE));579W.printNumber("Length", Obj->getAnyRelocationLength(RE));580W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE));581if (IsScattered) {582W.printHex("Value", Obj->getScatteredRelocationValue(RE));583} else {584const char *Kind = IsExtern ? "Symbol" : "Section";585W.printNumber(Kind, TargetName, Obj->getPlainRelocationSymbolNum(RE));586}587} else {588SmallString<32> SymbolNameOrOffset("0x");589if (IsScattered) {590// Scattered relocations don't really have an associated symbol for some591// reason, even if one exists in the symtab at the correct address.592SymbolNameOrOffset += utohexstr(Obj->getScatteredRelocationValue(RE));593} else {594SymbolNameOrOffset = TargetName;595}596597raw_ostream& OS = W.startLine();598OS << W.hex(Offset)599<< " " << Obj->getAnyRelocationPCRel(RE)600<< " " << Obj->getAnyRelocationLength(RE);601if (IsScattered)602OS << " n/a";603else604OS << " " << Obj->getPlainRelocationExternal(RE);605OS << " " << RelocName606<< " " << IsScattered607<< " " << SymbolNameOrOffset608<< "\n";609}610}611612StringRef MachODumper::getSymbolName(const SymbolRef &Symbol) const {613Expected<StringRef> SymbolNameOrErr = Symbol.getName();614if (!SymbolNameOrErr) {615reportError(SymbolNameOrErr.takeError(), Obj->getFileName());616}617return *SymbolNameOrErr;618}619620uint8_t MachODumper::getSymbolType(const SymbolRef &Symbol) const {621return Obj->is64Bit()622? Obj->getSymbol64TableEntry(Symbol.getRawDataRefImpl()).n_type623: Obj->getSymbolTableEntry(Symbol.getRawDataRefImpl()).n_type;624}625626bool MachODumper::compareSymbolsByName(SymbolRef LHS, SymbolRef RHS) const {627return getSymbolName(LHS).str().compare(getSymbolName(RHS).str()) < 0;628}629630bool MachODumper::compareSymbolsByType(SymbolRef LHS, SymbolRef RHS) const {631return getSymbolType(LHS) < getSymbolType(RHS);632}633634void MachODumper::printSymbols(bool /*ExtraSymInfo*/) {635printSymbols(std::nullopt);636}637638void MachODumper::printSymbols(std::optional<SymbolComparator> SymComp) {639ListScope Group(W, "Symbols");640if (SymComp) {641auto SymbolRange = Obj->symbols();642std::vector<SymbolRef> SortedSymbols(SymbolRange.begin(),643SymbolRange.end());644llvm::stable_sort(SortedSymbols, *SymComp);645for (SymbolRef Symbol : SortedSymbols)646printSymbol(Symbol);647} else {648for (const SymbolRef &Symbol : Obj->symbols()) {649printSymbol(Symbol);650}651}652}653654void MachODumper::printDynamicSymbols() {655ListScope Group(W, "DynamicSymbols");656}657void MachODumper::printDynamicSymbols(std::optional<SymbolComparator> SymComp) {658ListScope Group(W, "DynamicSymbols");659}660661void MachODumper::printSymbol(const SymbolRef &Symbol) {662printSymbol(Symbol, W);663}664665void MachODumper::printSymbol(const SymbolRef &Symbol, ScopedPrinter &W) {666StringRef SymbolName = getSymbolName(Symbol);667668MachOSymbol MOSymbol;669getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol);670671StringRef SectionName = "";672// Don't ask a Mach-O STABS symbol for its section unless we know that673// STAB symbol's section field refers to a valid section index. Otherwise674// the symbol may error trying to load a section that does not exist.675// TODO: Add a whitelist of STABS symbol types that contain valid section676// indices.677if (!(MOSymbol.Type & MachO::N_STAB)) {678Expected<section_iterator> SecIOrErr = Symbol.getSection();679if (!SecIOrErr)680reportError(SecIOrErr.takeError(), Obj->getFileName());681682section_iterator SecI = *SecIOrErr;683if (SecI != Obj->section_end())684SectionName = unwrapOrError(Obj->getFileName(), SecI->getName());685}686687DictScope D(W, "Symbol");688W.printNumber("Name", SymbolName, MOSymbol.StringIndex);689if (MOSymbol.Type & MachO::N_STAB) {690W.printHex("Type", "SymDebugTable", MOSymbol.Type);691} else {692if (MOSymbol.Type & MachO::N_PEXT)693W.startLine() << "PrivateExtern\n";694if (MOSymbol.Type & MachO::N_EXT)695W.startLine() << "Extern\n";696W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE),697ArrayRef(MachOSymbolTypes));698}699W.printHex("Section", SectionName, MOSymbol.SectionIndex);700W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0x7),701ArrayRef(MachOSymbolRefTypes));702W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0x7),703ArrayRef(MachOSymbolFlags));704W.printHex("Value", MOSymbol.Value);705}706707void MachODumper::printUnwindInfo() {708W.startLine() << "UnwindInfo not implemented.\n";709}710711void MachODumper::printStackMap() const {712object::SectionRef StackMapSection;713for (auto Sec : Obj->sections()) {714StringRef Name;715if (Expected<StringRef> NameOrErr = Sec.getName())716Name = *NameOrErr;717else718consumeError(NameOrErr.takeError());719720if (Name == "__llvm_stackmaps") {721StackMapSection = Sec;722break;723}724}725726if (StackMapSection == object::SectionRef())727return;728729StringRef StackMapContents =730unwrapOrError(Obj->getFileName(), StackMapSection.getContents());731ArrayRef<uint8_t> StackMapContentsArray =732arrayRefFromStringRef(StackMapContents);733734if (Obj->isLittleEndian())735prettyPrintStackMap(736W, StackMapParser<llvm::endianness::little>(StackMapContentsArray));737else738prettyPrintStackMap(739W, StackMapParser<llvm::endianness::big>(StackMapContentsArray));740}741742void MachODumper::printCGProfile() {743object::SectionRef CGProfileSection;744for (auto Sec : Obj->sections()) {745StringRef Name;746if (Expected<StringRef> NameOrErr = Sec.getName())747Name = *NameOrErr;748else749consumeError(NameOrErr.takeError());750751if (Name == "__cg_profile") {752CGProfileSection = Sec;753break;754}755}756if (CGProfileSection == object::SectionRef())757return;758759StringRef CGProfileContents =760unwrapOrError(Obj->getFileName(), CGProfileSection.getContents());761BinaryStreamReader Reader(CGProfileContents, Obj->isLittleEndian()762? llvm::endianness::little763: llvm::endianness::big);764765ListScope L(W, "CGProfile");766while (!Reader.empty()) {767uint32_t FromIndex, ToIndex;768uint64_t Count;769if (Error Err = Reader.readInteger(FromIndex))770reportError(std::move(Err), Obj->getFileName());771if (Error Err = Reader.readInteger(ToIndex))772reportError(std::move(Err), Obj->getFileName());773if (Error Err = Reader.readInteger(Count))774reportError(std::move(Err), Obj->getFileName());775DictScope D(W, "CGProfileEntry");776W.printNumber("From", getSymbolName(*Obj->getSymbolByIndex(FromIndex)),777FromIndex);778W.printNumber("To", getSymbolName(*Obj->getSymbolByIndex(ToIndex)),779ToIndex);780W.printNumber("Weight", Count);781}782}783784void MachODumper::printNeededLibraries() {785ListScope D(W, "NeededLibraries");786787using LibsTy = std::vector<StringRef>;788LibsTy Libs;789790for (const auto &Command : Obj->load_commands()) {791if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||792Command.C.cmd == MachO::LC_ID_DYLIB ||793Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||794Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||795Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||796Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {797MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);798if (Dl.dylib.name < Dl.cmdsize) {799auto *P = static_cast<const char*>(Command.Ptr) + Dl.dylib.name;800Libs.push_back(P);801}802}803}804805llvm::stable_sort(Libs);806807for (const auto &L : Libs) {808W.startLine() << L << "\n";809}810}811812void MachODumper::printMachODataInCode() {813for (const auto &Load : Obj->load_commands()) {814if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {815MachO::linkedit_data_command LLC = Obj->getLinkeditDataLoadCommand(Load);816DictScope Group(W, "DataInCode");817W.printNumber("Data offset", LLC.dataoff);818W.printNumber("Data size", LLC.datasize);819ListScope D(W, "Data entries");820unsigned NumRegions = LLC.datasize / sizeof(MachO::data_in_code_entry);821for (unsigned i = 0; i < NumRegions; ++i) {822MachO::data_in_code_entry DICE = Obj->getDataInCodeTableEntry(823LLC.dataoff, i);824DictScope Group(W, "Entry");825W.printNumber("Index", i);826W.printNumber("Offset", DICE.offset);827W.printNumber("Length", DICE.length);828W.printNumber("Kind", DICE.kind);829}830}831}832}833834void MachODumper::printMachOVersionMin() {835for (const auto &Load : Obj->load_commands()) {836StringRef Cmd;837switch (Load.C.cmd) {838case MachO::LC_VERSION_MIN_MACOSX:839Cmd = "LC_VERSION_MIN_MACOSX";840break;841case MachO::LC_VERSION_MIN_IPHONEOS:842Cmd = "LC_VERSION_MIN_IPHONEOS";843break;844case MachO::LC_VERSION_MIN_TVOS:845Cmd = "LC_VERSION_MIN_TVOS";846break;847case MachO::LC_VERSION_MIN_WATCHOS:848Cmd = "LC_VERSION_MIN_WATCHOS";849break;850case MachO::LC_BUILD_VERSION:851Cmd = "LC_BUILD_VERSION";852break;853default:854continue;855}856857DictScope Group(W, "MinVersion");858// Handle LC_BUILD_VERSION.859if (Load.C.cmd == MachO::LC_BUILD_VERSION) {860MachO::build_version_command BVC = Obj->getBuildVersionLoadCommand(Load);861W.printString("Cmd", Cmd);862W.printNumber("Size", BVC.cmdsize);863W.printString("Platform",864MachOObjectFile::getBuildPlatform(BVC.platform));865W.printString("Version", MachOObjectFile::getVersionString(BVC.minos));866if (BVC.sdk)867W.printString("SDK", MachOObjectFile::getVersionString(BVC.sdk));868else869W.printString("SDK", StringRef("n/a"));870continue;871}872873MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load);874W.printString("Cmd", Cmd);875W.printNumber("Size", VMC.cmdsize);876SmallString<32> Version;877Version = utostr(MachOObjectFile::getVersionMinMajor(VMC, false)) + "." +878utostr(MachOObjectFile::getVersionMinMinor(VMC, false));879uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, false);880if (Update != 0)881Version += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, false));882W.printString("Version", Version);883SmallString<32> SDK;884if (VMC.sdk == 0)885SDK = "n/a";886else {887SDK = utostr(MachOObjectFile::getVersionMinMajor(VMC, true)) + "." +888utostr(MachOObjectFile::getVersionMinMinor(VMC, true));889uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, true);890if (Update != 0)891SDK += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, true));892}893W.printString("SDK", SDK);894}895}896897void MachODumper::printMachODysymtab() {898for (const auto &Load : Obj->load_commands()) {899if (Load.C.cmd == MachO::LC_DYSYMTAB) {900MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand();901DictScope Group(W, "Dysymtab");902W.printNumber("ilocalsym", DLC.ilocalsym);903W.printNumber("nlocalsym", DLC.nlocalsym);904W.printNumber("iextdefsym", DLC.iextdefsym);905W.printNumber("nextdefsym", DLC.nextdefsym);906W.printNumber("iundefsym", DLC.iundefsym);907W.printNumber("nundefsym", DLC.nundefsym);908W.printNumber("tocoff", DLC.tocoff);909W.printNumber("ntoc", DLC.ntoc);910W.printNumber("modtaboff", DLC.modtaboff);911W.printNumber("nmodtab", DLC.nmodtab);912W.printNumber("extrefsymoff", DLC.extrefsymoff);913W.printNumber("nextrefsyms", DLC.nextrefsyms);914W.printNumber("indirectsymoff", DLC.indirectsymoff);915W.printNumber("nindirectsyms", DLC.nindirectsyms);916W.printNumber("extreloff", DLC.extreloff);917W.printNumber("nextrel", DLC.nextrel);918W.printNumber("locreloff", DLC.locreloff);919W.printNumber("nlocrel", DLC.nlocrel);920}921}922}923924void MachODumper::printMachOSegment() {925for (const auto &Load : Obj->load_commands()) {926if (Load.C.cmd == MachO::LC_SEGMENT || Load.C.cmd == MachO::LC_SEGMENT_64) {927MachOSegment MOSegment;928getSegment(Obj, Load, MOSegment);929DictScope Group(W, "Segment");930W.printString("Cmd", MOSegment.CmdName);931W.printString("Name", MOSegment.SegName);932W.printNumber("Size", MOSegment.cmdsize);933W.printHex("vmaddr", MOSegment.vmaddr);934W.printHex("vmsize", MOSegment.vmsize);935W.printNumber("fileoff", MOSegment.fileoff);936W.printNumber("filesize", MOSegment.filesize);937W.printString("maxprot", getMask(MOSegment.maxprot));938W.printString("initprot", getMask(MOSegment.initprot));939W.printNumber("nsects", MOSegment.nsects);940W.printHex("flags", MOSegment.flags);941}942}943}944945void MachODumper::printMachOIndirectSymbols() {946for (const auto &Load : Obj->load_commands()) {947if (Load.C.cmd == MachO::LC_DYSYMTAB) {948MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand();949DictScope Group(W, "Indirect Symbols");950W.printNumber("Number", DLC.nindirectsyms);951ListScope D(W, "Symbols");952for (unsigned i = 0; i < DLC.nindirectsyms; ++i) {953DictScope Group(W, "Entry");954W.printNumber("Entry Index", i);955W.printHex("Symbol Index", Obj->getIndirectSymbolTableEntry(DLC, i));956}957}958}959}960961void MachODumper::printMachOLinkerOptions() {962for (const auto &Load : Obj->load_commands()) {963if (Load.C.cmd == MachO::LC_LINKER_OPTION) {964MachO::linker_option_command LOLC = Obj->getLinkerOptionLoadCommand(Load);965DictScope Group(W, "Linker Options");966W.printNumber("Size", LOLC.cmdsize);967ListScope D(W, "Strings");968uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_option_command);969const char *P = Load.Ptr + sizeof(MachO::linker_option_command);970StringRef Data(P, DataSize);971for (unsigned i = 0; i < LOLC.count; ++i) {972std::pair<StringRef,StringRef> Split = Data.split('\0');973W.printString("Value", Split.first);974Data = Split.second;975}976}977}978}979980981