Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 1 | //===-- macho-dump.cpp - Mach Object Dumping Tool -------------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This is a testing tool for use with the MC/Mach-O LLVM components. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 14 | #include "llvm/Object/MachOObject.h" |
Daniel Dunbar | 71130f8 | 2010-11-27 13:58:16 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/StringExtras.h" |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 16 | #include "llvm/ADT/Twine.h" |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 17 | #include "llvm/Support/CommandLine.h" |
Daniel Dunbar | 4c55e0d | 2010-11-27 13:26:12 +0000 | [diff] [blame] | 18 | #include "llvm/Support/Format.h" |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 19 | #include "llvm/Support/ManagedStatic.h" |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 20 | #include "llvm/Support/MemoryBuffer.h" |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 21 | #include "llvm/Support/raw_ostream.h" |
Michael J. Spencer | 333fb04 | 2010-12-09 17:36:48 +0000 | [diff] [blame] | 22 | #include "llvm/Support/system_error.h" |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 23 | using namespace llvm; |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 24 | using namespace llvm::object; |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 25 | |
| 26 | static cl::opt<std::string> |
| 27 | InputFile(cl::Positional, cl::desc("<input file>"), cl::init("-")); |
| 28 | |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 29 | static cl::opt<bool> |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 30 | ShowSectionData("dump-section-data", cl::desc("Dump the contents of sections"), |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 31 | cl::init(false)); |
| 32 | |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 33 | /// |
| 34 | |
| 35 | static const char *ProgramName; |
| 36 | |
| 37 | static void Message(const char *Type, const Twine &Msg) { |
| 38 | errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; |
| 39 | } |
| 40 | |
| 41 | static int Error(const Twine &Msg) { |
| 42 | Message("error", Msg); |
| 43 | return 1; |
| 44 | } |
| 45 | |
| 46 | static void Warning(const Twine &Msg) { |
| 47 | Message("warning", Msg); |
| 48 | } |
| 49 | |
| 50 | /// |
| 51 | |
| 52 | static int DumpHeader(MachOObject &Obj) { |
| 53 | // Read the header. |
| 54 | const macho::Header &Hdr = Obj.getHeader(); |
| 55 | outs() << "('cputype', " << Hdr.CPUType << ")\n"; |
| 56 | outs() << "('cpusubtype', " << Hdr.CPUSubtype << ")\n"; |
| 57 | outs() << "('filetype', " << Hdr.FileType << ")\n"; |
| 58 | outs() << "('num_load_commands', " << Hdr.NumLoadCommands << ")\n"; |
| 59 | outs() << "('load_commands_size', " << Hdr.SizeOfLoadCommands << ")\n"; |
| 60 | outs() << "('flag', " << Hdr.Flags << ")\n"; |
| 61 | |
| 62 | // Print extended header if 64-bit. |
| 63 | if (Obj.is64Bit()) { |
| 64 | const macho::Header64Ext &Hdr64 = Obj.getHeader64Ext(); |
| 65 | outs() << "('reserved', " << Hdr64.Reserved << ")\n"; |
| 66 | } |
| 67 | |
| 68 | return 0; |
| 69 | } |
| 70 | |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 71 | static void DumpSegmentCommandData(StringRef Name, |
| 72 | uint64_t VMAddr, uint64_t VMSize, |
| 73 | uint64_t FileOffset, uint64_t FileSize, |
| 74 | uint32_t MaxProt, uint32_t InitProt, |
| 75 | uint32_t NumSections, uint32_t Flags) { |
| 76 | outs() << " ('segment_name', '"; |
| 77 | outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; |
| 78 | outs() << " ('vm_addr', " << VMAddr << ")\n"; |
| 79 | outs() << " ('vm_size', " << VMSize << ")\n"; |
| 80 | outs() << " ('file_offset', " << FileOffset << ")\n"; |
| 81 | outs() << " ('file_size', " << FileSize << ")\n"; |
| 82 | outs() << " ('maxprot', " << MaxProt << ")\n"; |
| 83 | outs() << " ('initprot', " << InitProt << ")\n"; |
| 84 | outs() << " ('num_sections', " << NumSections << ")\n"; |
| 85 | outs() << " ('flags', " << Flags << ")\n"; |
| 86 | } |
| 87 | |
Daniel Dunbar | 90e3e3a | 2010-11-27 13:39:48 +0000 | [diff] [blame] | 88 | static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, |
| 89 | StringRef SegmentName, uint64_t Address, |
| 90 | uint64_t Size, uint32_t Offset, |
| 91 | uint32_t Align, uint32_t RelocationTableOffset, |
| 92 | uint32_t NumRelocationTableEntries, |
| 93 | uint32_t Flags, uint32_t Reserved1, |
| 94 | uint32_t Reserved2, uint64_t Reserved3 = ~0ULL) { |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 95 | outs() << " # Section " << Index << "\n"; |
| 96 | outs() << " (('section_name', '"; |
| 97 | outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; |
| 98 | outs() << " ('segment_name', '"; |
| 99 | outs().write_escaped(SegmentName, /*UseHexEscapes=*/true) << "')\n"; |
| 100 | outs() << " ('address', " << Address << ")\n"; |
| 101 | outs() << " ('size', " << Size << ")\n"; |
| 102 | outs() << " ('offset', " << Offset << ")\n"; |
| 103 | outs() << " ('alignment', " << Align << ")\n"; |
| 104 | outs() << " ('reloc_offset', " << RelocationTableOffset << ")\n"; |
| 105 | outs() << " ('num_reloc', " << NumRelocationTableEntries << ")\n"; |
Daniel Dunbar | 71130f8 | 2010-11-27 13:58:16 +0000 | [diff] [blame] | 106 | outs() << " ('flags', " << format("0x%x", Flags) << ")\n"; |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 107 | outs() << " ('reserved1', " << Reserved1 << ")\n"; |
| 108 | outs() << " ('reserved2', " << Reserved2 << ")\n"; |
| 109 | if (Reserved3 != ~0ULL) |
| 110 | outs() << " ('reserved3', " << Reserved3 << ")\n"; |
Daniel Dunbar | 90e3e3a | 2010-11-27 13:39:48 +0000 | [diff] [blame] | 111 | outs() << " ),\n"; |
| 112 | |
| 113 | // Dump the relocation entries. |
| 114 | int Res = 0; |
| 115 | outs() << " ('_relocations', [\n"; |
| 116 | for (unsigned i = 0; i != NumRelocationTableEntries; ++i) { |
| 117 | InMemoryStruct<macho::RelocationEntry> RE; |
| 118 | Obj.ReadRelocationEntry(RelocationTableOffset, i, RE); |
| 119 | if (!RE) { |
| 120 | Res = Error("unable to read relocation table entry '" + Twine(i) + "'"); |
| 121 | break; |
| 122 | } |
| 123 | |
| 124 | outs() << " # Relocation " << i << "\n"; |
Daniel Dunbar | 71130f8 | 2010-11-27 13:58:16 +0000 | [diff] [blame] | 125 | outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n"; |
| 126 | outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n"; |
Daniel Dunbar | 90e3e3a | 2010-11-27 13:39:48 +0000 | [diff] [blame] | 127 | } |
| 128 | outs() << " ])\n"; |
| 129 | |
Daniel Dunbar | 71130f8 | 2010-11-27 13:58:16 +0000 | [diff] [blame] | 130 | // Dump the section data, if requested. |
| 131 | if (ShowSectionData) { |
| 132 | outs() << " ('_section_data', '"; |
| 133 | StringRef Data = Obj.getData(Offset, Size); |
| 134 | for (unsigned i = 0; i != Data.size(); ++i) { |
| 135 | if (i && (i % 4) == 0) |
| 136 | outs() << ' '; |
| 137 | outs() << hexdigit((Data[i] >> 4) & 0xF, /*LowerCase=*/true); |
| 138 | outs() << hexdigit((Data[i] >> 0) & 0xF, /*LowerCase=*/true); |
| 139 | } |
| 140 | outs() << "')\n"; |
| 141 | } |
| 142 | |
Daniel Dunbar | 90e3e3a | 2010-11-27 13:39:48 +0000 | [diff] [blame] | 143 | return Res; |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 144 | } |
| 145 | |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 146 | static int DumpSegmentCommand(MachOObject &Obj, |
| 147 | const MachOObject::LoadCommandInfo &LCI) { |
| 148 | InMemoryStruct<macho::SegmentLoadCommand> SLC; |
| 149 | Obj.ReadSegmentLoadCommand(LCI, SLC); |
| 150 | if (!SLC) |
| 151 | return Error("unable to read segment load command"); |
| 152 | |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 153 | DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, |
| 154 | SLC->VMSize, SLC->FileOffset, SLC->FileSize, |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 155 | SLC->MaxVMProtection, SLC->InitialVMProtection, |
| 156 | SLC->NumSections, SLC->Flags); |
| 157 | |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 158 | // Dump the sections. |
| 159 | int Res = 0; |
| 160 | outs() << " ('sections', [\n"; |
| 161 | for (unsigned i = 0; i != SLC->NumSections; ++i) { |
| 162 | InMemoryStruct<macho::Section> Sect; |
| 163 | Obj.ReadSection(LCI, i, Sect); |
| 164 | if (!SLC) { |
| 165 | Res = Error("unable to read section '" + Twine(i) + "'"); |
| 166 | break; |
| 167 | } |
| 168 | |
Daniel Dunbar | 90e3e3a | 2010-11-27 13:39:48 +0000 | [diff] [blame] | 169 | if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), |
| 170 | StringRef(Sect->SegmentName, 16), Sect->Address, |
| 171 | Sect->Size, Sect->Offset, Sect->Align, |
| 172 | Sect->RelocationTableOffset, |
| 173 | Sect->NumRelocationTableEntries, Sect->Flags, |
| 174 | Sect->Reserved1, Sect->Reserved2))) |
| 175 | break; |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 176 | } |
| 177 | outs() << " ])\n"; |
| 178 | |
| 179 | return Res; |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 180 | } |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 181 | |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 182 | static int DumpSegment64Command(MachOObject &Obj, |
| 183 | const MachOObject::LoadCommandInfo &LCI) { |
| 184 | InMemoryStruct<macho::Segment64LoadCommand> SLC; |
| 185 | Obj.ReadSegment64LoadCommand(LCI, SLC); |
| 186 | if (!SLC) |
| 187 | return Error("unable to read segment load command"); |
| 188 | |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 189 | DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, |
| 190 | SLC->VMSize, SLC->FileOffset, SLC->FileSize, |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 191 | SLC->MaxVMProtection, SLC->InitialVMProtection, |
| 192 | SLC->NumSections, SLC->Flags); |
| 193 | |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 194 | // Dump the sections. |
| 195 | int Res = 0; |
| 196 | outs() << " ('sections', [\n"; |
| 197 | for (unsigned i = 0; i != SLC->NumSections; ++i) { |
| 198 | InMemoryStruct<macho::Section64> Sect; |
| 199 | Obj.ReadSection64(LCI, i, Sect); |
| 200 | if (!SLC) { |
| 201 | Res = Error("unable to read section '" + Twine(i) + "'"); |
| 202 | break; |
| 203 | } |
| 204 | |
Daniel Dunbar | 90e3e3a | 2010-11-27 13:39:48 +0000 | [diff] [blame] | 205 | if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), |
| 206 | StringRef(Sect->SegmentName, 16), Sect->Address, |
| 207 | Sect->Size, Sect->Offset, Sect->Align, |
| 208 | Sect->RelocationTableOffset, |
| 209 | Sect->NumRelocationTableEntries, Sect->Flags, |
| 210 | Sect->Reserved1, Sect->Reserved2, |
| 211 | Sect->Reserved3))) |
| 212 | break; |
Daniel Dunbar | 2acadbd | 2010-11-27 13:33:15 +0000 | [diff] [blame] | 213 | } |
| 214 | outs() << " ])\n"; |
| 215 | |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 216 | return 0; |
| 217 | } |
| 218 | |
Daniel Dunbar | 2208b58 | 2010-11-27 13:52:53 +0000 | [diff] [blame] | 219 | static void DumpSymbolTableEntryData(MachOObject &Obj, |
| 220 | unsigned Index, uint32_t StringIndex, |
| 221 | uint8_t Type, uint8_t SectionIndex, |
| 222 | uint16_t Flags, uint64_t Value) { |
| 223 | outs() << " # Symbol " << Index << "\n"; |
| 224 | outs() << " (('n_strx', " << StringIndex << ")\n"; |
Daniel Dunbar | 71130f8 | 2010-11-27 13:58:16 +0000 | [diff] [blame] | 225 | outs() << " ('n_type', " << format("0x%x", Type) << ")\n"; |
Daniel Dunbar | 2208b58 | 2010-11-27 13:52:53 +0000 | [diff] [blame] | 226 | outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n"; |
| 227 | outs() << " ('n_desc', " << Flags << ")\n"; |
| 228 | outs() << " ('n_value', " << Value << ")\n"; |
| 229 | outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n"; |
| 230 | outs() << " ),\n"; |
| 231 | } |
| 232 | |
Daniel Dunbar | f879f14 | 2010-11-27 08:33:44 +0000 | [diff] [blame] | 233 | static int DumpSymtabCommand(MachOObject &Obj, |
| 234 | const MachOObject::LoadCommandInfo &LCI) { |
| 235 | InMemoryStruct<macho::SymtabLoadCommand> SLC; |
| 236 | Obj.ReadSymtabLoadCommand(LCI, SLC); |
| 237 | if (!SLC) |
| 238 | return Error("unable to read segment load command"); |
| 239 | |
| 240 | outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n"; |
| 241 | outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n"; |
| 242 | outs() << " ('stroff', " << SLC->StringTableOffset << ")\n"; |
| 243 | outs() << " ('strsize', " << SLC->StringTableSize << ")\n"; |
| 244 | |
Daniel Dunbar | f2e2a5f | 2010-11-27 13:46:11 +0000 | [diff] [blame] | 245 | // Cache the string table data. |
| 246 | Obj.RegisterStringTable(*SLC); |
| 247 | |
| 248 | // Dump the string data. |
| 249 | outs() << " ('_string_data', '"; |
| 250 | outs().write_escaped(Obj.getStringTableData(), |
| 251 | /*UseHexEscapes=*/true) << "')\n"; |
| 252 | |
Daniel Dunbar | 2208b58 | 2010-11-27 13:52:53 +0000 | [diff] [blame] | 253 | // Dump the symbol table. |
| 254 | int Res = 0; |
| 255 | outs() << " ('_symbols', [\n"; |
| 256 | for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) { |
| 257 | if (Obj.is64Bit()) { |
| 258 | InMemoryStruct<macho::Symbol64TableEntry> STE; |
| 259 | Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE); |
| 260 | if (!STE) { |
| 261 | Res = Error("unable to read symbol: '" + Twine(i) + "'"); |
| 262 | break; |
| 263 | } |
| 264 | |
| 265 | DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, |
| 266 | STE->SectionIndex, STE->Flags, STE->Value); |
| 267 | } else { |
| 268 | InMemoryStruct<macho::SymbolTableEntry> STE; |
| 269 | Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE); |
| 270 | if (!SLC) { |
| 271 | Res = Error("unable to read symbol: '" + Twine(i) + "'"); |
| 272 | break; |
| 273 | } |
| 274 | |
| 275 | DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, |
| 276 | STE->SectionIndex, STE->Flags, STE->Value); |
| 277 | } |
| 278 | } |
| 279 | outs() << " ])\n"; |
| 280 | |
| 281 | return Res; |
Daniel Dunbar | f879f14 | 2010-11-27 08:33:44 +0000 | [diff] [blame] | 282 | } |
| 283 | |
| 284 | static int DumpDysymtabCommand(MachOObject &Obj, |
| 285 | const MachOObject::LoadCommandInfo &LCI) { |
| 286 | InMemoryStruct<macho::DysymtabLoadCommand> DLC; |
| 287 | Obj.ReadDysymtabLoadCommand(LCI, DLC); |
| 288 | if (!DLC) |
| 289 | return Error("unable to read segment load command"); |
| 290 | |
Daniel Dunbar | a87d7ec | 2010-12-10 06:19:39 +0000 | [diff] [blame] | 291 | outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n"; |
Daniel Dunbar | f879f14 | 2010-11-27 08:33:44 +0000 | [diff] [blame] | 292 | outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n"; |
| 293 | outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n"; |
| 294 | outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n"; |
| 295 | outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n"; |
| 296 | outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n"; |
| 297 | outs() << " ('tocoff', " << DLC->TOCOffset << ")\n"; |
| 298 | outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n"; |
| 299 | outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n"; |
| 300 | outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n"; |
| 301 | outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n"; |
| 302 | outs() << " ('nextrefsyms', " |
| 303 | << DLC->NumReferencedSymbolTableEntries << ")\n"; |
| 304 | outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n"; |
| 305 | outs() << " ('nindirectsyms', " |
| 306 | << DLC->NumIndirectSymbolTableEntries << ")\n"; |
| 307 | outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n"; |
| 308 | outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n"; |
| 309 | outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n"; |
| 310 | outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n"; |
| 311 | |
Daniel Dunbar | 4c55e0d | 2010-11-27 13:26:12 +0000 | [diff] [blame] | 312 | // Dump the indirect symbol table. |
| 313 | int Res = 0; |
| 314 | outs() << " ('_indirect_symbols', [\n"; |
| 315 | for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) { |
| 316 | InMemoryStruct<macho::IndirectSymbolTableEntry> ISTE; |
| 317 | Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE); |
| 318 | if (!ISTE) { |
| 319 | Res = Error("unable to read segment load command"); |
| 320 | break; |
| 321 | } |
| 322 | |
| 323 | outs() << " # Indirect Symbol " << i << "\n"; |
| 324 | outs() << " (('symbol_index', " |
Daniel Dunbar | 71130f8 | 2010-11-27 13:58:16 +0000 | [diff] [blame] | 325 | << format("0x%x", ISTE->Index) << "),),\n"; |
Daniel Dunbar | 4c55e0d | 2010-11-27 13:26:12 +0000 | [diff] [blame] | 326 | } |
| 327 | outs() << " ])\n"; |
| 328 | |
| 329 | return Res; |
Daniel Dunbar | f879f14 | 2010-11-27 08:33:44 +0000 | [diff] [blame] | 330 | } |
| 331 | |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 332 | static int DumpLoadCommand(MachOObject &Obj, unsigned Index) { |
| 333 | const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index); |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 334 | int Res = 0; |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 335 | |
| 336 | outs() << " # Load Command " << Index << "\n" |
| 337 | << " (('command', " << LCI.Command.Type << ")\n" |
| 338 | << " ('size', " << LCI.Command.Size << ")\n"; |
| 339 | switch (LCI.Command.Type) { |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 340 | case macho::LCT_Segment: |
| 341 | Res = DumpSegmentCommand(Obj, LCI); |
| 342 | break; |
| 343 | case macho::LCT_Segment64: |
| 344 | Res = DumpSegment64Command(Obj, LCI); |
| 345 | break; |
Daniel Dunbar | f879f14 | 2010-11-27 08:33:44 +0000 | [diff] [blame] | 346 | case macho::LCT_Symtab: |
| 347 | Res = DumpSymtabCommand(Obj, LCI); |
| 348 | break; |
| 349 | case macho::LCT_Dysymtab: |
| 350 | Res = DumpDysymtabCommand(Obj, LCI); |
| 351 | break; |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 352 | default: |
| 353 | Warning("unknown load command: " + Twine(LCI.Command.Type)); |
| 354 | break; |
| 355 | } |
| 356 | outs() << " ),\n"; |
| 357 | |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 358 | return Res; |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 359 | } |
| 360 | |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 361 | int main(int argc, char **argv) { |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 362 | ProgramName = argv[0]; |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 363 | llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. |
| 364 | |
| 365 | cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n"); |
| 366 | |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 367 | // Load the input file. |
| 368 | std::string ErrorStr; |
Michael J. Spencer | 3ff9563 | 2010-12-16 03:29:14 +0000 | [diff] [blame] | 369 | OwningPtr<MemoryBuffer> InputBuffer; |
| 370 | if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) |
Michael J. Spencer | 333fb04 | 2010-12-09 17:36:48 +0000 | [diff] [blame] | 371 | return Error("unable to read input: '" + ec.message() + "'"); |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 372 | |
| 373 | // Construct the Mach-O wrapper object. |
| 374 | OwningPtr<MachOObject> InputObject( |
| 375 | MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr)); |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 376 | if (!InputObject) |
| 377 | return Error("unable to load object: '" + ErrorStr + "'"); |
Daniel Dunbar | ad12524 | 2010-11-27 06:19:17 +0000 | [diff] [blame] | 378 | |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 379 | if (int Res = DumpHeader(*InputObject)) |
| 380 | return Res; |
| 381 | |
| 382 | // Print the load commands. |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 383 | int Res = 0; |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 384 | outs() << "('load_commands', [\n"; |
| 385 | for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i) |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 386 | if ((Res = DumpLoadCommand(*InputObject, i))) |
| 387 | break; |
Daniel Dunbar | a956d8b | 2010-11-27 07:19:41 +0000 | [diff] [blame] | 388 | outs() << "])\n"; |
| 389 | |
Daniel Dunbar | 4ba1f5e | 2010-11-27 08:22:29 +0000 | [diff] [blame] | 390 | return Res; |
Daniel Dunbar | 75373ac | 2010-11-27 05:58:44 +0000 | [diff] [blame] | 391 | } |