1218885Sdim//===-- macho-dump.cpp - Mach Object Dumping Tool -------------------------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This is a testing tool for use with the MC/Mach-O LLVM components. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14251662Sdim#include "llvm/Object/MachO.h" 15218885Sdim#include "llvm/ADT/StringExtras.h" 16218885Sdim#include "llvm/ADT/Twine.h" 17251662Sdim#include "llvm/Support/Casting.h" 18218885Sdim#include "llvm/Support/CommandLine.h" 19218885Sdim#include "llvm/Support/Format.h" 20218885Sdim#include "llvm/Support/ManagedStatic.h" 21218885Sdim#include "llvm/Support/MemoryBuffer.h" 22218885Sdim#include "llvm/Support/raw_ostream.h" 23218885Sdim#include "llvm/Support/system_error.h" 24218885Sdimusing namespace llvm; 25218885Sdimusing namespace llvm::object; 26218885Sdim 27218885Sdimstatic cl::opt<std::string> 28218885SdimInputFile(cl::Positional, cl::desc("<input file>"), cl::init("-")); 29218885Sdim 30218885Sdimstatic cl::opt<bool> 31218885SdimShowSectionData("dump-section-data", cl::desc("Dump the contents of sections"), 32218885Sdim cl::init(false)); 33218885Sdim 34218885Sdim/// 35218885Sdim 36218885Sdimstatic const char *ProgramName; 37218885Sdim 38218885Sdimstatic void Message(const char *Type, const Twine &Msg) { 39218885Sdim errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; 40218885Sdim} 41218885Sdim 42218885Sdimstatic int Error(const Twine &Msg) { 43218885Sdim Message("error", Msg); 44218885Sdim return 1; 45218885Sdim} 46218885Sdim 47218885Sdimstatic void Warning(const Twine &Msg) { 48218885Sdim Message("warning", Msg); 49218885Sdim} 50218885Sdim 51218885Sdim/// 52218885Sdim 53218885Sdimstatic void DumpSegmentCommandData(StringRef Name, 54218885Sdim uint64_t VMAddr, uint64_t VMSize, 55218885Sdim uint64_t FileOffset, uint64_t FileSize, 56218885Sdim uint32_t MaxProt, uint32_t InitProt, 57218885Sdim uint32_t NumSections, uint32_t Flags) { 58218885Sdim outs() << " ('segment_name', '"; 59218885Sdim outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; 60218885Sdim outs() << " ('vm_addr', " << VMAddr << ")\n"; 61218885Sdim outs() << " ('vm_size', " << VMSize << ")\n"; 62218885Sdim outs() << " ('file_offset', " << FileOffset << ")\n"; 63218885Sdim outs() << " ('file_size', " << FileSize << ")\n"; 64218885Sdim outs() << " ('maxprot', " << MaxProt << ")\n"; 65218885Sdim outs() << " ('initprot', " << InitProt << ")\n"; 66218885Sdim outs() << " ('num_sections', " << NumSections << ")\n"; 67218885Sdim outs() << " ('flags', " << Flags << ")\n"; 68218885Sdim} 69218885Sdim 70251662Sdimstatic int DumpSectionData(const MachOObjectFile &Obj, unsigned Index, 71251662Sdim StringRef Name, 72218885Sdim StringRef SegmentName, uint64_t Address, 73218885Sdim uint64_t Size, uint32_t Offset, 74218885Sdim uint32_t Align, uint32_t RelocationTableOffset, 75218885Sdim uint32_t NumRelocationTableEntries, 76218885Sdim uint32_t Flags, uint32_t Reserved1, 77218885Sdim uint32_t Reserved2, uint64_t Reserved3 = ~0ULL) { 78218885Sdim outs() << " # Section " << Index << "\n"; 79218885Sdim outs() << " (('section_name', '"; 80218885Sdim outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; 81218885Sdim outs() << " ('segment_name', '"; 82218885Sdim outs().write_escaped(SegmentName, /*UseHexEscapes=*/true) << "')\n"; 83218885Sdim outs() << " ('address', " << Address << ")\n"; 84218885Sdim outs() << " ('size', " << Size << ")\n"; 85218885Sdim outs() << " ('offset', " << Offset << ")\n"; 86218885Sdim outs() << " ('alignment', " << Align << ")\n"; 87218885Sdim outs() << " ('reloc_offset', " << RelocationTableOffset << ")\n"; 88218885Sdim outs() << " ('num_reloc', " << NumRelocationTableEntries << ")\n"; 89218885Sdim outs() << " ('flags', " << format("0x%x", Flags) << ")\n"; 90218885Sdim outs() << " ('reserved1', " << Reserved1 << ")\n"; 91218885Sdim outs() << " ('reserved2', " << Reserved2 << ")\n"; 92218885Sdim if (Reserved3 != ~0ULL) 93218885Sdim outs() << " ('reserved3', " << Reserved3 << ")\n"; 94218885Sdim outs() << " ),\n"; 95218885Sdim 96218885Sdim // Dump the relocation entries. 97218885Sdim outs() << " ('_relocations', [\n"; 98251662Sdim unsigned RelNum = 0; 99251662Sdim error_code EC; 100251662Sdim for (relocation_iterator I = Obj.getSectionRelBegin(Index), 101251662Sdim E = Obj.getSectionRelEnd(Index); I != E; I.increment(EC), ++RelNum) { 102251662Sdim macho::RelocationEntry RE = Obj.getRelocation(I->getRawDataRefImpl()); 103251662Sdim outs() << " # Relocation " << RelNum << "\n"; 104251662Sdim outs() << " (('word-0', " << format("0x%x", RE.Word0) << "),\n"; 105251662Sdim outs() << " ('word-1', " << format("0x%x", RE.Word1) << ")),\n"; 106218885Sdim } 107218885Sdim outs() << " ])\n"; 108218885Sdim 109218885Sdim // Dump the section data, if requested. 110218885Sdim if (ShowSectionData) { 111218885Sdim outs() << " ('_section_data', '"; 112251662Sdim StringRef Data = Obj.getData().substr(Offset, Size); 113218885Sdim for (unsigned i = 0; i != Data.size(); ++i) { 114218885Sdim if (i && (i % 4) == 0) 115218885Sdim outs() << ' '; 116218885Sdim outs() << hexdigit((Data[i] >> 4) & 0xF, /*LowerCase=*/true); 117218885Sdim outs() << hexdigit((Data[i] >> 0) & 0xF, /*LowerCase=*/true); 118218885Sdim } 119218885Sdim outs() << "')\n"; 120218885Sdim } 121218885Sdim 122251662Sdim return 0; 123218885Sdim} 124218885Sdim 125251662Sdimstatic int DumpSegmentCommand(const MachOObjectFile &Obj, 126251662Sdim const MachOObjectFile::LoadCommandInfo &LCI) { 127251662Sdim macho::SegmentLoadCommand SLC = Obj.getSegmentLoadCommand(LCI); 128218885Sdim 129251662Sdim DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress, 130251662Sdim SLC.VMSize, SLC.FileOffset, SLC.FileSize, 131251662Sdim SLC.MaxVMProtection, SLC.InitialVMProtection, 132251662Sdim SLC.NumSections, SLC.Flags); 133218885Sdim 134218885Sdim // Dump the sections. 135218885Sdim outs() << " ('sections', [\n"; 136251662Sdim for (unsigned i = 0; i != SLC.NumSections; ++i) { 137251662Sdim macho::Section Sect = Obj.getSection(LCI, i); 138251662Sdim DumpSectionData(Obj, i, StringRef(Sect.Name, 16), 139251662Sdim StringRef(Sect.SegmentName, 16), Sect.Address, 140251662Sdim Sect.Size, Sect.Offset, Sect.Align, 141251662Sdim Sect.RelocationTableOffset, 142251662Sdim Sect.NumRelocationTableEntries, Sect.Flags, 143251662Sdim Sect.Reserved1, Sect.Reserved2); 144218885Sdim } 145218885Sdim outs() << " ])\n"; 146218885Sdim 147251662Sdim return 0; 148218885Sdim} 149218885Sdim 150251662Sdimstatic int DumpSegment64Command(const MachOObjectFile &Obj, 151251662Sdim const MachOObjectFile::LoadCommandInfo &LCI) { 152251662Sdim macho::Segment64LoadCommand SLC = Obj.getSegment64LoadCommand(LCI); 153251662Sdim DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress, 154251662Sdim SLC.VMSize, SLC.FileOffset, SLC.FileSize, 155251662Sdim SLC.MaxVMProtection, SLC.InitialVMProtection, 156251662Sdim SLC.NumSections, SLC.Flags); 157218885Sdim 158218885Sdim // Dump the sections. 159218885Sdim outs() << " ('sections', [\n"; 160251662Sdim for (unsigned i = 0; i != SLC.NumSections; ++i) { 161251662Sdim macho::Section64 Sect = Obj.getSection64(LCI, i); 162218885Sdim 163251662Sdim DumpSectionData(Obj, i, StringRef(Sect.Name, 16), 164251662Sdim StringRef(Sect.SegmentName, 16), Sect.Address, 165251662Sdim Sect.Size, Sect.Offset, Sect.Align, 166251662Sdim Sect.RelocationTableOffset, 167251662Sdim Sect.NumRelocationTableEntries, Sect.Flags, 168251662Sdim Sect.Reserved1, Sect.Reserved2, 169251662Sdim Sect.Reserved3); 170218885Sdim } 171218885Sdim outs() << " ])\n"; 172218885Sdim 173251662Sdim return 0; 174218885Sdim} 175218885Sdim 176251662Sdimstatic void DumpSymbolTableEntryData(const MachOObjectFile &Obj, 177218885Sdim unsigned Index, uint32_t StringIndex, 178218885Sdim uint8_t Type, uint8_t SectionIndex, 179251662Sdim uint16_t Flags, uint64_t Value, 180251662Sdim StringRef StringTable) { 181251662Sdim const char *Name = &StringTable.data()[StringIndex]; 182218885Sdim outs() << " # Symbol " << Index << "\n"; 183218885Sdim outs() << " (('n_strx', " << StringIndex << ")\n"; 184218885Sdim outs() << " ('n_type', " << format("0x%x", Type) << ")\n"; 185218885Sdim outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n"; 186218885Sdim outs() << " ('n_desc', " << Flags << ")\n"; 187218885Sdim outs() << " ('n_value', " << Value << ")\n"; 188251662Sdim outs() << " ('_string', '" << Name << "')\n"; 189218885Sdim outs() << " ),\n"; 190218885Sdim} 191218885Sdim 192251662Sdimstatic int DumpSymtabCommand(const MachOObjectFile &Obj) { 193251662Sdim macho::SymtabLoadCommand SLC = Obj.getSymtabLoadCommand(); 194218885Sdim 195251662Sdim outs() << " ('symoff', " << SLC.SymbolTableOffset << ")\n"; 196251662Sdim outs() << " ('nsyms', " << SLC.NumSymbolTableEntries << ")\n"; 197251662Sdim outs() << " ('stroff', " << SLC.StringTableOffset << ")\n"; 198251662Sdim outs() << " ('strsize', " << SLC.StringTableSize << ")\n"; 199218885Sdim 200218885Sdim // Dump the string data. 201218885Sdim outs() << " ('_string_data', '"; 202251662Sdim StringRef StringTable = Obj.getStringTableData(); 203251662Sdim outs().write_escaped(StringTable, 204218885Sdim /*UseHexEscapes=*/true) << "')\n"; 205218885Sdim 206218885Sdim // Dump the symbol table. 207218885Sdim outs() << " ('_symbols', [\n"; 208251662Sdim error_code EC; 209251662Sdim unsigned SymNum = 0; 210251662Sdim for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; 211251662Sdim I.increment(EC), ++SymNum) { 212251662Sdim DataRefImpl DRI = I->getRawDataRefImpl(); 213218885Sdim if (Obj.is64Bit()) { 214251662Sdim macho::Symbol64TableEntry STE = Obj.getSymbol64TableEntry(DRI); 215251662Sdim DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type, 216251662Sdim STE.SectionIndex, STE.Flags, STE.Value, 217251662Sdim StringTable); 218218885Sdim } else { 219251662Sdim macho::SymbolTableEntry STE = Obj.getSymbolTableEntry(DRI); 220251662Sdim DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type, 221251662Sdim STE.SectionIndex, STE.Flags, STE.Value, 222251662Sdim StringTable); 223218885Sdim } 224218885Sdim } 225218885Sdim outs() << " ])\n"; 226218885Sdim 227251662Sdim return 0; 228218885Sdim} 229218885Sdim 230251662Sdimstatic int DumpDysymtabCommand(const MachOObjectFile &Obj) { 231251662Sdim macho::DysymtabLoadCommand DLC = Obj.getDysymtabLoadCommand(); 232218885Sdim 233251662Sdim outs() << " ('ilocalsym', " << DLC.LocalSymbolsIndex << ")\n"; 234251662Sdim outs() << " ('nlocalsym', " << DLC.NumLocalSymbols << ")\n"; 235251662Sdim outs() << " ('iextdefsym', " << DLC.ExternalSymbolsIndex << ")\n"; 236251662Sdim outs() << " ('nextdefsym', " << DLC.NumExternalSymbols << ")\n"; 237251662Sdim outs() << " ('iundefsym', " << DLC.UndefinedSymbolsIndex << ")\n"; 238251662Sdim outs() << " ('nundefsym', " << DLC.NumUndefinedSymbols << ")\n"; 239251662Sdim outs() << " ('tocoff', " << DLC.TOCOffset << ")\n"; 240251662Sdim outs() << " ('ntoc', " << DLC.NumTOCEntries << ")\n"; 241251662Sdim outs() << " ('modtaboff', " << DLC.ModuleTableOffset << ")\n"; 242251662Sdim outs() << " ('nmodtab', " << DLC.NumModuleTableEntries << ")\n"; 243251662Sdim outs() << " ('extrefsymoff', " << DLC.ReferenceSymbolTableOffset << ")\n"; 244218885Sdim outs() << " ('nextrefsyms', " 245251662Sdim << DLC.NumReferencedSymbolTableEntries << ")\n"; 246251662Sdim outs() << " ('indirectsymoff', " << DLC.IndirectSymbolTableOffset << ")\n"; 247218885Sdim outs() << " ('nindirectsyms', " 248251662Sdim << DLC.NumIndirectSymbolTableEntries << ")\n"; 249251662Sdim outs() << " ('extreloff', " << DLC.ExternalRelocationTableOffset << ")\n"; 250251662Sdim outs() << " ('nextrel', " << DLC.NumExternalRelocationTableEntries << ")\n"; 251251662Sdim outs() << " ('locreloff', " << DLC.LocalRelocationTableOffset << ")\n"; 252251662Sdim outs() << " ('nlocrel', " << DLC.NumLocalRelocationTableEntries << ")\n"; 253218885Sdim 254218885Sdim // Dump the indirect symbol table. 255218885Sdim outs() << " ('_indirect_symbols', [\n"; 256251662Sdim for (unsigned i = 0; i != DLC.NumIndirectSymbolTableEntries; ++i) { 257251662Sdim macho::IndirectSymbolTableEntry ISTE = 258251662Sdim Obj.getIndirectSymbolTableEntry(DLC, i); 259218885Sdim outs() << " # Indirect Symbol " << i << "\n"; 260218885Sdim outs() << " (('symbol_index', " 261251662Sdim << format("0x%x", ISTE.Index) << "),),\n"; 262218885Sdim } 263218885Sdim outs() << " ])\n"; 264218885Sdim 265251662Sdim return 0; 266218885Sdim} 267218885Sdim 268251662Sdimstatic int 269251662SdimDumpLinkeditDataCommand(const MachOObjectFile &Obj, 270251662Sdim const MachOObjectFile::LoadCommandInfo &LCI) { 271251662Sdim macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI); 272251662Sdim outs() << " ('dataoff', " << LLC.DataOffset << ")\n" 273251662Sdim << " ('datasize', " << LLC.DataSize << ")\n" 274226584Sdim << " ('_addresses', [\n"; 275226584Sdim 276226584Sdim SmallVector<uint64_t, 8> Addresses; 277251662Sdim Obj.ReadULEB128s(LLC.DataOffset, Addresses); 278226584Sdim for (unsigned i = 0, e = Addresses.size(); i != e; ++i) 279226584Sdim outs() << " # Address " << i << '\n' 280226584Sdim << " ('address', " << format("0x%x", Addresses[i]) << "),\n"; 281226584Sdim 282226584Sdim outs() << " ])\n"; 283226584Sdim 284226584Sdim return 0; 285226584Sdim} 286226584Sdim 287251662Sdimstatic int 288251662SdimDumpDataInCodeDataCommand(const MachOObjectFile &Obj, 289251662Sdim const MachOObjectFile::LoadCommandInfo &LCI) { 290251662Sdim macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI); 291251662Sdim outs() << " ('dataoff', " << LLC.DataOffset << ")\n" 292251662Sdim << " ('datasize', " << LLC.DataSize << ")\n" 293239462Sdim << " ('_data_regions', [\n"; 294239462Sdim 295251662Sdim unsigned NumRegions = LLC.DataSize / 8; 296239462Sdim for (unsigned i = 0; i < NumRegions; ++i) { 297251662Sdim macho::DataInCodeTableEntry DICE = 298251662Sdim Obj.getDataInCodeTableEntry(LLC.DataOffset, i); 299239462Sdim outs() << " # DICE " << i << "\n" 300251662Sdim << " ('offset', " << DICE.Offset << ")\n" 301251662Sdim << " ('length', " << DICE.Length << ")\n" 302251662Sdim << " ('kind', " << DICE.Kind << ")\n"; 303239462Sdim } 304239462Sdim 305239462Sdim outs() <<" ])\n"; 306239462Sdim 307239462Sdim return 0; 308239462Sdim} 309239462Sdim 310251662Sdimstatic int 311251662SdimDumpLinkerOptionsCommand(const MachOObjectFile &Obj, 312251662Sdim const MachOObjectFile::LoadCommandInfo &LCI) { 313251662Sdim macho::LinkerOptionsLoadCommand LOLC = Obj.getLinkerOptionsLoadCommand(LCI); 314251662Sdim outs() << " ('count', " << LOLC.Count << ")\n" 315251662Sdim << " ('_strings', [\n"; 316239462Sdim 317251662Sdim uint64_t DataSize = LOLC.Size - sizeof(macho::LinkerOptionsLoadCommand); 318251662Sdim const char *P = LCI.Ptr + sizeof(macho::LinkerOptionsLoadCommand); 319251662Sdim StringRef Data(P, DataSize); 320251662Sdim for (unsigned i = 0; i != LOLC.Count; ++i) { 321251662Sdim std::pair<StringRef,StringRef> Split = Data.split('\0'); 322251662Sdim outs() << "\t\""; 323251662Sdim outs().write_escaped(Split.first); 324251662Sdim outs() << "\",\n"; 325251662Sdim Data = Split.second; 326251662Sdim } 327251662Sdim outs() <<" ])\n"; 328249423Sdim 329249423Sdim return 0; 330249423Sdim} 331249423Sdim 332251662Sdimstatic int DumpLoadCommand(const MachOObjectFile &Obj, 333251662Sdim MachOObjectFile::LoadCommandInfo &LCI) { 334251662Sdim switch (LCI.C.Type) { 335218885Sdim case macho::LCT_Segment: 336251662Sdim return DumpSegmentCommand(Obj, LCI); 337218885Sdim case macho::LCT_Segment64: 338251662Sdim return DumpSegment64Command(Obj, LCI); 339218885Sdim case macho::LCT_Symtab: 340251662Sdim return DumpSymtabCommand(Obj); 341218885Sdim case macho::LCT_Dysymtab: 342251662Sdim return DumpDysymtabCommand(Obj); 343226584Sdim case macho::LCT_CodeSignature: 344226584Sdim case macho::LCT_SegmentSplitInfo: 345226584Sdim case macho::LCT_FunctionStarts: 346251662Sdim return DumpLinkeditDataCommand(Obj, LCI); 347239462Sdim case macho::LCT_DataInCode: 348251662Sdim return DumpDataInCodeDataCommand(Obj, LCI); 349249423Sdim case macho::LCT_LinkerOptions: 350251662Sdim return DumpLinkerOptionsCommand(Obj, LCI); 351218885Sdim default: 352251662Sdim Warning("unknown load command: " + Twine(LCI.C.Type)); 353251662Sdim return 0; 354218885Sdim } 355251662Sdim} 356251662Sdim 357251662Sdim 358251662Sdimstatic int DumpLoadCommand(const MachOObjectFile &Obj, unsigned Index, 359251662Sdim MachOObjectFile::LoadCommandInfo &LCI) { 360251662Sdim outs() << " # Load Command " << Index << "\n" 361251662Sdim << " (('command', " << LCI.C.Type << ")\n" 362251662Sdim << " ('size', " << LCI.C.Size << ")\n"; 363251662Sdim int Res = DumpLoadCommand(Obj, LCI); 364218885Sdim outs() << " ),\n"; 365218885Sdim return Res; 366218885Sdim} 367218885Sdim 368251662Sdimstatic void printHeader(const MachOObjectFile *Obj, 369251662Sdim const macho::Header &Header) { 370251662Sdim outs() << "('cputype', " << Header.CPUType << ")\n"; 371251662Sdim outs() << "('cpusubtype', " << Header.CPUSubtype << ")\n"; 372251662Sdim outs() << "('filetype', " << Header.FileType << ")\n"; 373251662Sdim outs() << "('num_load_commands', " << Header.NumLoadCommands << ")\n"; 374251662Sdim outs() << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n"; 375251662Sdim outs() << "('flag', " << Header.Flags << ")\n"; 376251662Sdim 377251662Sdim // Print extended header if 64-bit. 378251662Sdim if (Obj->is64Bit()) { 379251662Sdim macho::Header64Ext Header64Ext = Obj->getHeader64Ext(); 380251662Sdim outs() << "('reserved', " << Header64Ext.Reserved << ")\n"; 381251662Sdim } 382251662Sdim} 383251662Sdim 384218885Sdimint main(int argc, char **argv) { 385218885Sdim ProgramName = argv[0]; 386218885Sdim llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 387218885Sdim 388218885Sdim cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n"); 389218885Sdim 390251662Sdim OwningPtr<Binary> Binary; 391251662Sdim if (error_code EC = createBinary(InputFile, Binary)) 392251662Sdim return Error("unable to read input: '" + EC.message() + "'"); 393218885Sdim 394251662Sdim const MachOObjectFile *InputObject = dyn_cast<MachOObjectFile>(Binary.get()); 395218885Sdim if (!InputObject) 396251662Sdim return Error("Not a MachO object"); 397218885Sdim 398221337Sdim // Print the header 399251662Sdim macho::Header Header = InputObject->getHeader(); 400251662Sdim printHeader(InputObject, Header); 401218885Sdim 402218885Sdim // Print the load commands. 403218885Sdim int Res = 0; 404251662Sdim MachOObjectFile::LoadCommandInfo Command = 405251662Sdim InputObject->getFirstLoadCommandInfo(); 406218885Sdim outs() << "('load_commands', [\n"; 407251662Sdim for (unsigned i = 0; ; ++i) { 408251662Sdim if (DumpLoadCommand(*InputObject, i, Command)) 409218885Sdim break; 410251662Sdim 411251662Sdim if (i == Header.NumLoadCommands - 1) 412251662Sdim break; 413251662Sdim Command = InputObject->getNextLoadCommandInfo(Command); 414251662Sdim } 415218885Sdim outs() << "])\n"; 416218885Sdim 417218885Sdim return Res; 418218885Sdim} 419