MachODumper.cpp revision 261991
1249259Sdim//===-- MachODump.cpp - Object file dumping utility for llvm --------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file implements the MachO-specific dumper for llvm-readobj. 11249259Sdim// 12249259Sdim//===----------------------------------------------------------------------===// 13249259Sdim 14249259Sdim#include "llvm-readobj.h" 15249259Sdim#include "Error.h" 16249259Sdim#include "ObjDumper.h" 17249259Sdim#include "StreamWriter.h" 18249259Sdim 19249259Sdim#include "llvm/ADT/SmallString.h" 20249259Sdim#include "llvm/Object/MachO.h" 21249259Sdim#include "llvm/Support/Casting.h" 22249259Sdim 23249259Sdimusing namespace llvm; 24249259Sdimusing namespace object; 25249259Sdim 26249259Sdimnamespace { 27249259Sdim 28249259Sdimclass MachODumper : public ObjDumper { 29249259Sdimpublic: 30251662Sdim MachODumper(const MachOObjectFile *Obj, StreamWriter& Writer) 31249259Sdim : ObjDumper(Writer) 32249259Sdim , Obj(Obj) { } 33249259Sdim 34249259Sdim virtual void printFileHeaders() LLVM_OVERRIDE; 35249259Sdim virtual void printSections() LLVM_OVERRIDE; 36249259Sdim virtual void printRelocations() LLVM_OVERRIDE; 37249259Sdim virtual void printSymbols() LLVM_OVERRIDE; 38249259Sdim virtual void printDynamicSymbols() LLVM_OVERRIDE; 39249259Sdim virtual void printUnwindInfo() LLVM_OVERRIDE; 40249259Sdim 41249259Sdimprivate: 42249259Sdim void printSymbol(symbol_iterator SymI); 43249259Sdim 44249259Sdim void printRelocation(section_iterator SecI, relocation_iterator RelI); 45249259Sdim 46251662Sdim void printRelocation(const MachOObjectFile *Obj, 47251662Sdim section_iterator SecI, relocation_iterator RelI); 48251662Sdim 49251662Sdim void printSections(const MachOObjectFile *Obj); 50251662Sdim 51251662Sdim const MachOObjectFile *Obj; 52249259Sdim}; 53249259Sdim 54249259Sdim} // namespace 55249259Sdim 56249259Sdim 57249259Sdimnamespace llvm { 58249259Sdim 59249259Sdimerror_code createMachODumper(const object::ObjectFile *Obj, 60249259Sdim StreamWriter& Writer, 61249259Sdim OwningPtr<ObjDumper> &Result) { 62249259Sdim const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(Obj); 63249259Sdim if (!MachOObj) 64249259Sdim return readobj_error::unsupported_obj_file_format; 65249259Sdim 66249259Sdim Result.reset(new MachODumper(MachOObj, Writer)); 67249259Sdim return readobj_error::success; 68249259Sdim} 69249259Sdim 70249259Sdim} // namespace llvm 71249259Sdim 72249259Sdim 73249259Sdimstatic const EnumEntry<unsigned> MachOSectionTypes[] = { 74249259Sdim { "Regular" , 0x00 }, 75249259Sdim { "ZeroFill" , 0x01 }, 76249259Sdim { "CStringLiterals" , 0x02 }, 77249259Sdim { "4ByteLiterals" , 0x03 }, 78249259Sdim { "8ByteLiterals" , 0x04 }, 79249259Sdim { "LiteralPointers" , 0x05 }, 80249259Sdim { "NonLazySymbolPointers" , 0x06 }, 81249259Sdim { "LazySymbolPointers" , 0x07 }, 82249259Sdim { "SymbolStubs" , 0x08 }, 83249259Sdim { "ModInitFuncs" , 0x09 }, 84249259Sdim { "ModTermFuncs" , 0x0A }, 85249259Sdim { "Coalesced" , 0x0B }, 86249259Sdim { "GBZeroFill" , 0x0C }, 87249259Sdim { "Interposing" , 0x0D }, 88249259Sdim { "16ByteLiterals" , 0x0E }, 89249259Sdim { "DTraceDOF" , 0x0F }, 90249259Sdim { "LazyDylibSymbolPoints" , 0x10 }, 91249259Sdim { "ThreadLocalRegular" , 0x11 }, 92249259Sdim { "ThreadLocalZerofill" , 0x12 }, 93249259Sdim { "ThreadLocalVariables" , 0x13 }, 94249259Sdim { "ThreadLocalVariablePointers" , 0x14 }, 95249259Sdim { "ThreadLocalInitFunctionPointers", 0x15 } 96249259Sdim}; 97249259Sdim 98249259Sdimstatic const EnumEntry<unsigned> MachOSectionAttributes[] = { 99249259Sdim { "LocReloc" , 1 << 0 /*S_ATTR_LOC_RELOC */ }, 100249259Sdim { "ExtReloc" , 1 << 1 /*S_ATTR_EXT_RELOC */ }, 101249259Sdim { "SomeInstructions" , 1 << 2 /*S_ATTR_SOME_INSTRUCTIONS */ }, 102249259Sdim { "Debug" , 1 << 17 /*S_ATTR_DEBUG */ }, 103249259Sdim { "SelfModifyingCode", 1 << 18 /*S_ATTR_SELF_MODIFYING_CODE*/ }, 104249259Sdim { "LiveSupport" , 1 << 19 /*S_ATTR_LIVE_SUPPORT */ }, 105249259Sdim { "NoDeadStrip" , 1 << 20 /*S_ATTR_NO_DEAD_STRIP */ }, 106249259Sdim { "StripStaticSyms" , 1 << 21 /*S_ATTR_STRIP_STATIC_SYMS */ }, 107249259Sdim { "NoTOC" , 1 << 22 /*S_ATTR_NO_TOC */ }, 108249259Sdim { "PureInstructions" , 1 << 23 /*S_ATTR_PURE_INSTRUCTIONS */ }, 109249259Sdim}; 110249259Sdim 111249259Sdimstatic const EnumEntry<unsigned> MachOSymbolRefTypes[] = { 112249259Sdim { "UndefinedNonLazy", 0 }, 113249259Sdim { "ReferenceFlagUndefinedLazy", 1 }, 114249259Sdim { "ReferenceFlagDefined", 2 }, 115249259Sdim { "ReferenceFlagPrivateDefined", 3 }, 116249259Sdim { "ReferenceFlagPrivateUndefinedNonLazy", 4 }, 117249259Sdim { "ReferenceFlagPrivateUndefinedLazy", 5 } 118249259Sdim}; 119249259Sdim 120249259Sdimstatic const EnumEntry<unsigned> MachOSymbolFlags[] = { 121249259Sdim { "ReferencedDynamically", 0x10 }, 122249259Sdim { "NoDeadStrip", 0x20 }, 123249259Sdim { "WeakRef", 0x40 }, 124249259Sdim { "WeakDef", 0x80 } 125249259Sdim}; 126249259Sdim 127249259Sdimstatic const EnumEntry<unsigned> MachOSymbolTypes[] = { 128249259Sdim { "Undef", 0x0 }, 129249259Sdim { "External", 0x1 }, 130249259Sdim { "Abs", 0x2 }, 131249259Sdim { "Indirect", 0xA }, 132249259Sdim { "PreboundUndef", 0xC }, 133249259Sdim { "Section", 0xE }, 134249259Sdim { "PrivateExternal", 0x10 } 135249259Sdim}; 136249259Sdim 137249259Sdimnamespace { 138249259Sdim enum { 139249259Sdim N_STAB = 0xE0 140249259Sdim }; 141249259Sdim 142249259Sdim struct MachOSection { 143249259Sdim ArrayRef<char> Name; 144249259Sdim ArrayRef<char> SegmentName; 145249259Sdim uint64_t Address; 146249259Sdim uint64_t Size; 147249259Sdim uint32_t Offset; 148249259Sdim uint32_t Alignment; 149249259Sdim uint32_t RelocationTableOffset; 150249259Sdim uint32_t NumRelocationTableEntries; 151249259Sdim uint32_t Flags; 152249259Sdim uint32_t Reserved1; 153249259Sdim uint32_t Reserved2; 154249259Sdim }; 155249259Sdim 156249259Sdim struct MachOSymbol { 157249259Sdim uint32_t StringIndex; 158249259Sdim uint8_t Type; 159249259Sdim uint8_t SectionIndex; 160249259Sdim uint16_t Flags; 161249259Sdim uint64_t Value; 162249259Sdim }; 163249259Sdim} 164249259Sdim 165251662Sdimstatic void getSection(const MachOObjectFile *Obj, 166251662Sdim DataRefImpl Sec, 167249259Sdim MachOSection &Section) { 168251662Sdim if (!Obj->is64Bit()) { 169261991Sdim MachO::section Sect = Obj->getSection(Sec); 170261991Sdim Section.Address = Sect.addr; 171261991Sdim Section.Size = Sect.size; 172261991Sdim Section.Offset = Sect.offset; 173261991Sdim Section.Alignment = Sect.align; 174261991Sdim Section.RelocationTableOffset = Sect.reloff; 175261991Sdim Section.NumRelocationTableEntries = Sect.nreloc; 176261991Sdim Section.Flags = Sect.flags; 177261991Sdim Section.Reserved1 = Sect.reserved1; 178261991Sdim Section.Reserved2 = Sect.reserved2; 179251662Sdim return; 180249259Sdim } 181261991Sdim MachO::section_64 Sect = Obj->getSection64(Sec); 182261991Sdim Section.Address = Sect.addr; 183261991Sdim Section.Size = Sect.size; 184261991Sdim Section.Offset = Sect.offset; 185261991Sdim Section.Alignment = Sect.align; 186261991Sdim Section.RelocationTableOffset = Sect.reloff; 187261991Sdim Section.NumRelocationTableEntries = Sect.nreloc; 188261991Sdim Section.Flags = Sect.flags; 189261991Sdim Section.Reserved1 = Sect.reserved1; 190261991Sdim Section.Reserved2 = Sect.reserved2; 191249259Sdim} 192249259Sdim 193249259Sdim 194251662Sdimstatic void getSymbol(const MachOObjectFile *Obj, 195249259Sdim DataRefImpl DRI, 196249259Sdim MachOSymbol &Symbol) { 197251662Sdim if (!Obj->is64Bit()) { 198261991Sdim MachO::nlist Entry = Obj->getSymbolTableEntry(DRI); 199261991Sdim Symbol.StringIndex = Entry.n_strx; 200261991Sdim Symbol.Type = Entry.n_type; 201261991Sdim Symbol.SectionIndex = Entry.n_sect; 202261991Sdim Symbol.Flags = Entry.n_desc; 203261991Sdim Symbol.Value = Entry.n_value; 204251662Sdim return; 205249259Sdim } 206261991Sdim MachO::nlist_64 Entry = Obj->getSymbol64TableEntry(DRI); 207261991Sdim Symbol.StringIndex = Entry.n_strx; 208261991Sdim Symbol.Type = Entry.n_type; 209261991Sdim Symbol.SectionIndex = Entry.n_sect; 210261991Sdim Symbol.Flags = Entry.n_desc; 211261991Sdim Symbol.Value = Entry.n_value; 212249259Sdim} 213249259Sdim 214249259Sdimvoid MachODumper::printFileHeaders() { 215249259Sdim W.startLine() << "FileHeaders not implemented.\n"; 216249259Sdim} 217249259Sdim 218249259Sdimvoid MachODumper::printSections() { 219251662Sdim return printSections(Obj); 220251662Sdim} 221251662Sdim 222251662Sdimvoid MachODumper::printSections(const MachOObjectFile *Obj) { 223249259Sdim ListScope Group(W, "Sections"); 224249259Sdim 225249259Sdim int SectionIndex = -1; 226249259Sdim error_code EC; 227249259Sdim for (section_iterator SecI = Obj->begin_sections(), 228249259Sdim SecE = Obj->end_sections(); 229249259Sdim SecI != SecE; SecI.increment(EC)) { 230249259Sdim if (error(EC)) break; 231249259Sdim 232249259Sdim ++SectionIndex; 233249259Sdim 234251662Sdim MachOSection Section; 235251662Sdim getSection(Obj, SecI->getRawDataRefImpl(), Section); 236251662Sdim DataRefImpl DR = SecI->getRawDataRefImpl(); 237249259Sdim 238249259Sdim StringRef Name; 239249259Sdim if (error(SecI->getName(Name))) 240249259Sdim Name = ""; 241249259Sdim 242251662Sdim ArrayRef<char> RawName = Obj->getSectionRawName(DR); 243251662Sdim StringRef SegmentName = Obj->getSectionFinalSegmentName(DR); 244251662Sdim ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR); 245251662Sdim 246249259Sdim DictScope SectionD(W, "Section"); 247249259Sdim W.printNumber("Index", SectionIndex); 248251662Sdim W.printBinary("Name", Name, RawName); 249251662Sdim W.printBinary("Segment", SegmentName, RawSegmentName); 250249259Sdim W.printHex ("Address", Section.Address); 251249259Sdim W.printHex ("Size", Section.Size); 252249259Sdim W.printNumber("Offset", Section.Offset); 253249259Sdim W.printNumber("Alignment", Section.Alignment); 254249259Sdim W.printHex ("RelocationOffset", Section.RelocationTableOffset); 255249259Sdim W.printNumber("RelocationCount", Section.NumRelocationTableEntries); 256249259Sdim W.printEnum ("Type", Section.Flags & 0xFF, 257249259Sdim makeArrayRef(MachOSectionAttributes)); 258249259Sdim W.printFlags ("Attributes", Section.Flags >> 8, 259249259Sdim makeArrayRef(MachOSectionAttributes)); 260249259Sdim W.printHex ("Reserved1", Section.Reserved1); 261249259Sdim W.printHex ("Reserved2", Section.Reserved2); 262249259Sdim 263249259Sdim if (opts::SectionRelocations) { 264249259Sdim ListScope D(W, "Relocations"); 265249259Sdim for (relocation_iterator RelI = SecI->begin_relocations(), 266249259Sdim RelE = SecI->end_relocations(); 267249259Sdim RelI != RelE; RelI.increment(EC)) { 268249259Sdim if (error(EC)) break; 269249259Sdim 270249259Sdim printRelocation(SecI, RelI); 271249259Sdim } 272249259Sdim } 273249259Sdim 274249259Sdim if (opts::SectionSymbols) { 275249259Sdim ListScope D(W, "Symbols"); 276249259Sdim for (symbol_iterator SymI = Obj->begin_symbols(), 277249259Sdim SymE = Obj->end_symbols(); 278249259Sdim SymI != SymE; SymI.increment(EC)) { 279249259Sdim if (error(EC)) break; 280249259Sdim 281249259Sdim bool Contained = false; 282249259Sdim if (SecI->containsSymbol(*SymI, Contained) || !Contained) 283249259Sdim continue; 284249259Sdim 285249259Sdim printSymbol(SymI); 286249259Sdim } 287249259Sdim } 288249259Sdim 289249259Sdim if (opts::SectionData) { 290249259Sdim StringRef Data; 291249259Sdim if (error(SecI->getContents(Data))) break; 292249259Sdim 293249259Sdim W.printBinaryBlock("SectionData", Data); 294249259Sdim } 295249259Sdim } 296249259Sdim} 297249259Sdim 298249259Sdimvoid MachODumper::printRelocations() { 299249259Sdim ListScope D(W, "Relocations"); 300249259Sdim 301249259Sdim error_code EC; 302249259Sdim for (section_iterator SecI = Obj->begin_sections(), 303249259Sdim SecE = Obj->end_sections(); 304249259Sdim SecI != SecE; SecI.increment(EC)) { 305249259Sdim if (error(EC)) break; 306249259Sdim 307249259Sdim StringRef Name; 308249259Sdim if (error(SecI->getName(Name))) 309249259Sdim continue; 310249259Sdim 311249259Sdim bool PrintedGroup = false; 312249259Sdim for (relocation_iterator RelI = SecI->begin_relocations(), 313249259Sdim RelE = SecI->end_relocations(); 314249259Sdim RelI != RelE; RelI.increment(EC)) { 315249259Sdim if (error(EC)) break; 316249259Sdim 317249259Sdim if (!PrintedGroup) { 318249259Sdim W.startLine() << "Section " << Name << " {\n"; 319249259Sdim W.indent(); 320249259Sdim PrintedGroup = true; 321249259Sdim } 322249259Sdim 323249259Sdim printRelocation(SecI, RelI); 324249259Sdim } 325249259Sdim 326249259Sdim if (PrintedGroup) { 327249259Sdim W.unindent(); 328249259Sdim W.startLine() << "}\n"; 329249259Sdim } 330249259Sdim } 331249259Sdim} 332249259Sdim 333249259Sdimvoid MachODumper::printRelocation(section_iterator SecI, 334249259Sdim relocation_iterator RelI) { 335251662Sdim return printRelocation(Obj, SecI, RelI); 336251662Sdim} 337251662Sdim 338251662Sdimvoid MachODumper::printRelocation(const MachOObjectFile *Obj, 339251662Sdim section_iterator SecI, 340251662Sdim relocation_iterator RelI) { 341249259Sdim uint64_t Offset; 342249259Sdim SmallString<32> RelocName; 343249259Sdim StringRef SymbolName; 344249259Sdim if (error(RelI->getOffset(Offset))) return; 345249259Sdim if (error(RelI->getTypeName(RelocName))) return; 346261991Sdim symbol_iterator Symbol = RelI->getSymbol(); 347261991Sdim if (Symbol != Obj->end_symbols() && 348261991Sdim error(Symbol->getName(SymbolName))) 349251662Sdim return; 350249259Sdim 351251662Sdim DataRefImpl DR = RelI->getRawDataRefImpl(); 352261991Sdim MachO::any_relocation_info RE = Obj->getRelocation(DR); 353251662Sdim bool IsScattered = Obj->isRelocationScattered(RE); 354251662Sdim 355251662Sdim if (opts::ExpandRelocs) { 356251662Sdim DictScope Group(W, "Relocation"); 357251662Sdim W.printHex("Offset", Offset); 358251662Sdim W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE)); 359251662Sdim W.printNumber("Length", Obj->getAnyRelocationLength(RE)); 360251662Sdim if (IsScattered) 361251662Sdim W.printString("Extern", StringRef("N/A")); 362251662Sdim else 363251662Sdim W.printNumber("Extern", Obj->getPlainRelocationExternal(RE)); 364251662Sdim W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE)); 365251662Sdim W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); 366251662Sdim W.printNumber("Scattered", IsScattered); 367251662Sdim } else { 368251662Sdim raw_ostream& OS = W.startLine(); 369251662Sdim OS << W.hex(Offset) 370251662Sdim << " " << Obj->getAnyRelocationPCRel(RE) 371251662Sdim << " " << Obj->getAnyRelocationLength(RE); 372251662Sdim if (IsScattered) 373251662Sdim OS << " n/a"; 374251662Sdim else 375251662Sdim OS << " " << Obj->getPlainRelocationExternal(RE); 376251662Sdim OS << " " << RelocName 377251662Sdim << " " << IsScattered 378251662Sdim << " " << (SymbolName.size() > 0 ? SymbolName : "-") 379251662Sdim << "\n"; 380251662Sdim } 381249259Sdim} 382249259Sdim 383249259Sdimvoid MachODumper::printSymbols() { 384249259Sdim ListScope Group(W, "Symbols"); 385249259Sdim 386249259Sdim error_code EC; 387249259Sdim for (symbol_iterator SymI = Obj->begin_symbols(), 388249259Sdim SymE = Obj->end_symbols(); 389249259Sdim SymI != SymE; SymI.increment(EC)) { 390249259Sdim if (error(EC)) break; 391249259Sdim 392249259Sdim printSymbol(SymI); 393249259Sdim } 394249259Sdim} 395249259Sdim 396249259Sdimvoid MachODumper::printDynamicSymbols() { 397249259Sdim ListScope Group(W, "DynamicSymbols"); 398249259Sdim} 399249259Sdim 400249259Sdimvoid MachODumper::printSymbol(symbol_iterator SymI) { 401249259Sdim StringRef SymbolName; 402249259Sdim if (SymI->getName(SymbolName)) 403249259Sdim SymbolName = ""; 404249259Sdim 405249259Sdim MachOSymbol Symbol; 406251662Sdim getSymbol(Obj, SymI->getRawDataRefImpl(), Symbol); 407249259Sdim 408251662Sdim StringRef SectionName = ""; 409249259Sdim section_iterator SecI(Obj->end_sections()); 410251662Sdim if (!error(SymI->getSection(SecI)) && 411251662Sdim SecI != Obj->end_sections()) 412251662Sdim error(SecI->getName(SectionName)); 413249259Sdim 414249259Sdim DictScope D(W, "Symbol"); 415249259Sdim W.printNumber("Name", SymbolName, Symbol.StringIndex); 416249259Sdim if (Symbol.Type & N_STAB) { 417249259Sdim W.printHex ("Type", "SymDebugTable", Symbol.Type); 418249259Sdim } else { 419249259Sdim W.printEnum("Type", Symbol.Type, makeArrayRef(MachOSymbolTypes)); 420249259Sdim } 421249259Sdim W.printHex ("Section", SectionName, Symbol.SectionIndex); 422249259Sdim W.printEnum ("RefType", static_cast<uint16_t>(Symbol.Flags & 0xF), 423249259Sdim makeArrayRef(MachOSymbolRefTypes)); 424249259Sdim W.printFlags ("Flags", static_cast<uint16_t>(Symbol.Flags & ~0xF), 425249259Sdim makeArrayRef(MachOSymbolFlags)); 426249259Sdim W.printHex ("Value", Symbol.Value); 427249259Sdim} 428249259Sdim 429249259Sdimvoid MachODumper::printUnwindInfo() { 430249259Sdim W.startLine() << "UnwindInfo not implemented.\n"; 431249259Sdim} 432