X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-readobj%2FMachODumper.cpp;h=b226e5f35b55434166139957a3ae3ea0698f5fe3;hb=310e6c3606ecb8847600b5ed0be455ac31d76731;hp=2fd5d4acaa844afd5f6981deff8387cc2607e0b1;hpb=133aacf0dd1d7d8c7828594e5cd2e9595e0331ed;p=oota-llvm.git diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 2fd5d4acaa8..b226e5f35b5 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -14,8 +14,10 @@ #include "llvm-readobj.h" #include "Error.h" #include "ObjDumper.h" +#include "StackMapPrinter.h" #include "StreamWriter.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Casting.h" @@ -30,14 +32,18 @@ public: : ObjDumper(Writer) , Obj(Obj) { } - virtual void printFileHeaders() override; - virtual void printSections() override; - virtual void printRelocations() override; - virtual void printSymbols() override; - virtual void printDynamicSymbols() override; - virtual void printUnwindInfo() override; + void printFileHeaders() override; + void printSections() override; + void printRelocations() override; + void printSymbols() override; + void printDynamicSymbols() override; + void printUnwindInfo() override; + void printStackMap() const override; private: + template + void printFileHeaders(const MachHeader &Header); + void printSymbol(const SymbolRef &Symbol); void printRelocation(const RelocationRef &Reloc); @@ -54,9 +60,9 @@ private: namespace llvm { -error_code createMachODumper(const object::ObjectFile *Obj, - StreamWriter &Writer, - std::unique_ptr &Result) { +std::error_code createMachODumper(const object::ObjectFile *Obj, + StreamWriter &Writer, + std::unique_ptr &Result) { const MachOObjectFile *MachOObj = dyn_cast(Obj); if (!MachOObj) return readobj_error::unsupported_obj_file_format; @@ -67,30 +73,136 @@ error_code createMachODumper(const object::ObjectFile *Obj, } // namespace llvm +static const EnumEntry MachOMagics[] = { + { "Magic", MachO::MH_MAGIC }, + { "Cigam", MachO::MH_CIGAM }, + { "Magic64", MachO::MH_MAGIC_64 }, + { "Cigam64", MachO::MH_CIGAM_64 }, + { "FatMagic", MachO::FAT_MAGIC }, + { "FatCigam", MachO::FAT_CIGAM }, +}; + +static const EnumEntry MachOHeaderFileTypes[] = { + { "Relocatable", MachO::MH_OBJECT }, + { "Executable", MachO::MH_EXECUTE }, + { "FixedVMLibrary", MachO::MH_FVMLIB }, + { "Core", MachO::MH_CORE }, + { "PreloadedExecutable", MachO::MH_PRELOAD }, + { "DynamicLibrary", MachO::MH_DYLIB }, + { "DynamicLinker", MachO::MH_DYLINKER }, + { "Bundle", MachO::MH_BUNDLE }, + { "DynamicLibraryStub", MachO::MH_DYLIB_STUB }, + { "DWARFSymbol", MachO::MH_DSYM }, + { "KextBundle", MachO::MH_KEXT_BUNDLE }, +}; + +static const EnumEntry MachOHeaderCpuTypes[] = { + { "Any" , static_cast(MachO::CPU_TYPE_ANY) }, + { "X86" , MachO::CPU_TYPE_X86 }, + { "X86-64" , MachO::CPU_TYPE_X86_64 }, + { "Mc98000" , MachO::CPU_TYPE_MC98000 }, + { "Arm" , MachO::CPU_TYPE_ARM }, + { "Arm64" , MachO::CPU_TYPE_ARM64 }, + { "Sparc" , MachO::CPU_TYPE_SPARC }, + { "PowerPC" , MachO::CPU_TYPE_POWERPC }, + { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 }, +}; + +static const EnumEntry MachOHeaderCpuSubtypesX86[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_386), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486SX), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_586), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTPRO), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M3), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M5), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON_MOBILE), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_XEON), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4_M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM_2), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON_MP), +}; + +static const EnumEntry MachOHeaderCpuSubtypesX64[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_ARCH1), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_H), +}; + +static const EnumEntry MachOHeaderCpuSubtypesARM[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V4T), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5TEJ), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_XSCALE), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7S), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7K), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM), +}; -static const EnumEntry MachOSectionTypes[] = { - { "Regular" , 0x00 }, - { "ZeroFill" , 0x01 }, - { "CStringLiterals" , 0x02 }, - { "4ByteLiterals" , 0x03 }, - { "8ByteLiterals" , 0x04 }, - { "LiteralPointers" , 0x05 }, - { "NonLazySymbolPointers" , 0x06 }, - { "LazySymbolPointers" , 0x07 }, - { "SymbolStubs" , 0x08 }, - { "ModInitFuncs" , 0x09 }, - { "ModTermFuncs" , 0x0A }, - { "Coalesced" , 0x0B }, - { "GBZeroFill" , 0x0C }, - { "Interposing" , 0x0D }, - { "16ByteLiterals" , 0x0E }, - { "DTraceDOF" , 0x0F }, - { "LazyDylibSymbolPoints" , 0x10 }, - { "ThreadLocalRegular" , 0x11 }, - { "ThreadLocalZerofill" , 0x12 }, - { "ThreadLocalVariables" , 0x13 }, - { "ThreadLocalVariablePointers" , 0x14 }, - { "ThreadLocalInitFunctionPointers", 0x15 } +static const EnumEntry MachOHeaderCpuSubtypesARM64[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL), +}; + +static const EnumEntry MachOHeaderCpuSubtypesSPARC[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_SPARC_ALL), +}; + +static const EnumEntry MachOHeaderCpuSubtypesPPC[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_601), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_602), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603e), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603ev), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604e), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_620), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_750), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7400), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7450), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_970), +}; + +static const EnumEntry MachOHeaderFlags[] = { + LLVM_READOBJ_ENUM_ENT(MachO, MH_NOUNDEFS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_INCRLINK), + LLVM_READOBJ_ENUM_ENT(MachO, MH_DYLDLINK), + LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDATLOAD), + LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBOUND), + LLVM_READOBJ_ENUM_ENT(MachO, MH_SPLIT_SEGS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_LAZY_INIT), + LLVM_READOBJ_ENUM_ENT(MachO, MH_TWOLEVEL), + LLVM_READOBJ_ENUM_ENT(MachO, MH_FORCE_FLAT), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NOMULTIDEFS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NOFIXPREBINDING), + LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBINDABLE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLMODSBOUND), + LLVM_READOBJ_ENUM_ENT(MachO, MH_SUBSECTIONS_VIA_SYMBOLS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_CANONICAL), + LLVM_READOBJ_ENUM_ENT(MachO, MH_WEAK_DEFINES), + LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDS_TO_WEAK), + LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLOW_STACK_EXECUTION), + LLVM_READOBJ_ENUM_ENT(MachO, MH_ROOT_SAFE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_SETUID_SAFE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_REEXPORTED_DYLIBS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_PIE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_DEAD_STRIPPABLE_DYLIB), + LLVM_READOBJ_ENUM_ENT(MachO, MH_HAS_TLV_DESCRIPTORS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_HEAP_EXECUTION), + LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE), }; static const EnumEntry MachOSectionAttributes[] = { @@ -204,7 +316,47 @@ static void getSymbol(const MachOObjectFile *Obj, } void MachODumper::printFileHeaders() { - W.startLine() << "FileHeaders not implemented.\n"; + DictScope H(W, "MachHeader"); + if (!Obj->is64Bit()) { + printFileHeaders(Obj->getHeader()); + } else { + printFileHeaders(Obj->getHeader64()); + W.printHex("Reserved", Obj->getHeader64().reserved); + } +} + +template +void MachODumper::printFileHeaders(const MachHeader &Header) { + W.printEnum("Magic", Header.magic, makeArrayRef(MachOMagics)); + W.printEnum("CpuType", Header.cputype, makeArrayRef(MachOHeaderCpuTypes)); + uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK; + switch (Header.cputype) { + case MachO::CPU_TYPE_X86: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX86)); + break; + case MachO::CPU_TYPE_X86_64: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX64)); + break; + case MachO::CPU_TYPE_ARM: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM)); + break; + case MachO::CPU_TYPE_POWERPC: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesPPC)); + break; + case MachO::CPU_TYPE_SPARC: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesSPARC)); + break; + case MachO::CPU_TYPE_ARM64: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM64)); + break; + case MachO::CPU_TYPE_POWERPC64: + default: + W.printHex("CpuSubtype", subtype); + } + W.printEnum("FileType", Header.filetype, makeArrayRef(MachOHeaderFileTypes)); + W.printNumber("NumOfLoadCommands", Header.ncmds); + W.printNumber("SizeOfLoadCommands", Header.sizeofcmds); + W.printFlags("Flags", Header.flags, makeArrayRef(MachOHeaderFlags)); } void MachODumper::printSections() { @@ -223,8 +375,7 @@ void MachODumper::printSections(const MachOObjectFile *Obj) { DataRefImpl DR = Section.getRawDataRefImpl(); StringRef Name; - if (error(Section.getName(Name))) - Name = ""; + error(Section.getName(Name)); ArrayRef RawName = Obj->getSectionRawName(DR); StringRef SegmentName = Obj->getSectionFinalSegmentName(DR); @@ -256,8 +407,7 @@ void MachODumper::printSections(const MachOObjectFile *Obj) { if (opts::SectionSymbols) { ListScope D(W, "Symbols"); for (const SymbolRef &Symbol : Obj->symbols()) { - bool Contained = false; - if (Section.containsSymbol(Symbol, Contained) || !Contained) + if (!Section.containsSymbol(Symbol)) continue; printSymbol(Symbol); @@ -265,11 +415,13 @@ void MachODumper::printSections(const MachOObjectFile *Obj) { } if (opts::SectionData) { - StringRef Data; - if (error(Section.getContents(Data))) - break; + bool IsBSS = Section.isBSS(); + if (!IsBSS) { + StringRef Data; + error(Section.getContents(Data)); - W.printBinaryBlock("SectionData", Data); + W.printBinaryBlock("SectionData", Data); + } } } } @@ -277,11 +429,10 @@ void MachODumper::printSections(const MachOObjectFile *Obj) { void MachODumper::printRelocations() { ListScope D(W, "Relocations"); - error_code EC; + std::error_code EC; for (const SectionRef &Section : Obj->sections()) { StringRef Name; - if (error(Section.getName(Name))) - continue; + error(Section.getName(Name)); bool PrintedGroup = false; for (const RelocationRef &Reloc : Section.relocations()) { @@ -307,34 +458,54 @@ void MachODumper::printRelocation(const RelocationRef &Reloc) { void MachODumper::printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc) { - uint64_t Offset; + uint64_t Offset = Reloc.getOffset(); SmallString<32> RelocName; - StringRef SymbolName; - if (error(Reloc.getOffset(Offset))) - return; - if (error(Reloc.getTypeName(RelocName))) - return; - symbol_iterator Symbol = Reloc.getSymbol(); - if (Symbol != Obj->symbol_end() && error(Symbol->getName(SymbolName))) - return; + Reloc.getTypeName(RelocName); DataRefImpl DR = Reloc.getRawDataRefImpl(); MachO::any_relocation_info RE = Obj->getRelocation(DR); bool IsScattered = Obj->isRelocationScattered(RE); + bool IsExtern = !IsScattered && Obj->getPlainRelocationExternal(RE); + + StringRef TargetName; + if (IsExtern) { + symbol_iterator Symbol = Reloc.getSymbol(); + if (Symbol != Obj->symbol_end()) { + ErrorOr TargetNameOrErr = Symbol->getName(); + error(TargetNameOrErr.getError()); + TargetName = *TargetNameOrErr; + } + } else if (!IsScattered) { + section_iterator SecI = Obj->getRelocationSection(DR); + if (SecI != Obj->section_end()) { + error(SecI->getName(TargetName)); + } + } + if (TargetName.empty()) + TargetName = "-"; if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Offset); W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE)); W.printNumber("Length", Obj->getAnyRelocationLength(RE)); - if (IsScattered) - W.printString("Extern", StringRef("N/A")); - else - W.printNumber("Extern", Obj->getPlainRelocationExternal(RE)); W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE)); - W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); - W.printNumber("Scattered", IsScattered); + if (IsScattered) { + W.printHex("Value", Obj->getScatteredRelocationValue(RE)); + } else { + const char *Kind = IsExtern ? "Symbol" : "Section"; + W.printNumber(Kind, TargetName, Obj->getPlainRelocationSymbolNum(RE)); + } } else { + SmallString<32> SymbolNameOrOffset("0x"); + if (IsScattered) { + // Scattered relocations don't really have an associated symbol for some + // reason, even if one exists in the symtab at the correct address. + SymbolNameOrOffset += utohexstr(Obj->getScatteredRelocationValue(RE)); + } else { + SymbolNameOrOffset = TargetName; + } + raw_ostream& OS = W.startLine(); OS << W.hex(Offset) << " " << Obj->getAnyRelocationPCRel(RE) @@ -345,7 +516,7 @@ void MachODumper::printRelocation(const MachOObjectFile *Obj, OS << " " << Obj->getPlainRelocationExternal(RE); OS << " " << RelocName << " " << IsScattered - << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << " " << SymbolNameOrOffset << "\n"; } } @@ -364,15 +535,16 @@ void MachODumper::printDynamicSymbols() { void MachODumper::printSymbol(const SymbolRef &Symbol) { StringRef SymbolName; - if (Symbol.getName(SymbolName)) - SymbolName = ""; + if (ErrorOr SymbolNameOrErr = Symbol.getName()) + SymbolName = *SymbolNameOrErr; MachOSymbol MOSymbol; getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol); StringRef SectionName = ""; section_iterator SecI(Obj->section_begin()); - if (!error(Symbol.getSection(SecI)) && SecI != Obj->section_end()) + error(Symbol.getSection(SecI)); + if (SecI != Obj->section_end()) error(SecI->getName(SectionName)); DictScope D(W, "Symbol"); @@ -398,3 +570,32 @@ void MachODumper::printSymbol(const SymbolRef &Symbol) { void MachODumper::printUnwindInfo() { W.startLine() << "UnwindInfo not implemented.\n"; } + +void MachODumper::printStackMap() const { + object::SectionRef StackMapSection; + for (auto Sec : Obj->sections()) { + StringRef Name; + Sec.getName(Name); + if (Name == "__llvm_stackmaps") { + StackMapSection = Sec; + break; + } + } + + if (StackMapSection == object::SectionRef()) + return; + + StringRef StackMapContents; + StackMapSection.getContents(StackMapContents); + ArrayRef StackMapContentsArray( + reinterpret_cast(StackMapContents.data()), + StackMapContents.size()); + + if (Obj->isLittleEndian()) + prettyPrintStackMap( + llvm::outs(), + StackMapV1Parser(StackMapContentsArray)); + else + prettyPrintStackMap(llvm::outs(), + StackMapV1Parser(StackMapContentsArray)); +}