X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=tools%2Fllvm-objdump%2FMachODump.cpp;h=258c0b520a3d4f6ecfcb9f864d9bf9668679fcf7;hp=cda28c48611616def0aba2782e40b7244cb12c7e;hb=ed7a4ba53481007a5d80e5588b5a9191950349f0;hpb=e84d8c12d5157a926db15976389f703809c49aa5 diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index cda28c48611..258c0b520a3 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -13,6 +13,7 @@ #include "llvm-objdump.h" #include "llvm-c/Disassembler.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" @@ -133,6 +134,7 @@ static cl::opt NoSymbolicOperands( static cl::list ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), cl::ZeroOrMore); + bool ArchAll = false; static std::string ThumbTripleName; @@ -205,19 +207,19 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, case MachO::DICE_KIND_DATA: if (Length >= 4) { if (!NoShowRawInsn) - dumpBytes(ArrayRef(bytes, 4), outs()); + dumpBytes(makeArrayRef(bytes, 4), outs()); Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; outs() << "\t.long " << Value; Size = 4; } else if (Length >= 2) { if (!NoShowRawInsn) - dumpBytes(ArrayRef(bytes, 2), outs()); + dumpBytes(makeArrayRef(bytes, 2), outs()); Value = bytes[1] << 8 | bytes[0]; outs() << "\t.short " << Value; Size = 2; } else { if (!NoShowRawInsn) - dumpBytes(ArrayRef(bytes, 2), outs()); + dumpBytes(makeArrayRef(bytes, 2), outs()); Value = bytes[0]; outs() << "\t.byte " << Value; Size = 1; @@ -229,14 +231,14 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, break; case MachO::DICE_KIND_JUMP_TABLE8: if (!NoShowRawInsn) - dumpBytes(ArrayRef(bytes, 1), outs()); + dumpBytes(makeArrayRef(bytes, 1), outs()); Value = bytes[0]; outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; Size = 1; break; case MachO::DICE_KIND_JUMP_TABLE16: if (!NoShowRawInsn) - dumpBytes(ArrayRef(bytes, 2), outs()); + dumpBytes(makeArrayRef(bytes, 2), outs()); Value = bytes[1] << 8 | bytes[0]; outs() << "\t.short " << format("%5u", Value & 0xffff) << "\t@ KIND_JUMP_TABLE16\n"; @@ -245,7 +247,7 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, case MachO::DICE_KIND_JUMP_TABLE32: case MachO::DICE_KIND_ABS_JUMP_TABLE32: if (!NoShowRawInsn) - dumpBytes(ArrayRef(bytes, 4), outs()); + dumpBytes(makeArrayRef(bytes, 4), outs()); Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; outs() << "\t.long " << Value; if (Kind == MachO::DICE_KIND_JUMP_TABLE32) @@ -665,13 +667,9 @@ static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, double d) { outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); uint32_t Hi, Lo; - if (O->isLittleEndian()) { - Hi = l1; - Lo = l0; - } else { - Hi = l0; - Lo = l1; - } + Hi = (O->isLittleEndian()) ? l1 : l0; + Lo = (O->isLittleEndian()) ? l0 : l1; + // Hi is the high word, so this is equivalent to if(isfinite(d)) if ((Hi & 0x7ff00000) != 0x7ff00000) outs() << format(" (%.16e)\n", d); @@ -916,10 +914,7 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect, SymbolAddressMap *AddrMap, bool verbose) { uint32_t stride; - if (O->is64Bit()) - stride = sizeof(uint64_t); - else - stride = sizeof(uint32_t); + stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); for (uint32_t i = 0; i < sect_size; i += stride) { const char *SymbolName = nullptr; if (O->is64Bit()) { @@ -1201,7 +1196,11 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, PrintSymbolTable(MachOOF); if (UnwindInfo) printMachOUnwindInfo(MachOOF); - if (PrivateHeaders) + if (PrivateHeaders) { + printMachOFileHeader(MachOOF); + printMachOLoadCommands(MachOOF); + } + if (FirstPrivateHeader) printMachOFileHeader(MachOOF); if (ObjcMetaData) printObjcMetaData(MachOOF, !NonVerbose); @@ -1390,7 +1389,7 @@ static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, } } -static void printArchiveChild(Archive::Child &C, bool verbose, +static void printArchiveChild(const Archive::Child &C, bool verbose, bool print_offset) { if (print_offset) outs() << C.getChildOffset() << "\t"; @@ -1399,42 +1398,15 @@ static void printArchiveChild(Archive::Child &C, bool verbose, // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. outs() << "-"; - if (Mode & sys::fs::owner_read) - outs() << "r"; - else - outs() << "-"; - if (Mode & sys::fs::owner_write) - outs() << "w"; - else - outs() << "-"; - if (Mode & sys::fs::owner_exe) - outs() << "x"; - else - outs() << "-"; - if (Mode & sys::fs::group_read) - outs() << "r"; - else - outs() << "-"; - if (Mode & sys::fs::group_write) - outs() << "w"; - else - outs() << "-"; - if (Mode & sys::fs::group_exe) - outs() << "x"; - else - outs() << "-"; - if (Mode & sys::fs::others_read) - outs() << "r"; - else - outs() << "-"; - if (Mode & sys::fs::others_write) - outs() << "w"; - else - outs() << "-"; - if (Mode & sys::fs::others_exe) - outs() << "x"; - else - outs() << "-"; + outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); + outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); + outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); + outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); + outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); + outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); + outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); + outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); + outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); } else { outs() << format("0%o ", Mode); } @@ -1443,8 +1415,10 @@ static void printArchiveChild(Archive::Child &C, bool verbose, outs() << format("%3d/", UID); unsigned GID = C.getGID(); outs() << format("%-3d ", GID); - uint64_t Size = C.getRawSize(); - outs() << format("%5" PRId64, Size) << " "; + ErrorOr Size = C.getRawSize(); + if (std::error_code EC = Size.getError()) + report_fatal_error(EC.message()); + outs() << format("%5" PRId64, Size.get()) << " "; StringRef RawLastModified = C.getRawLastModified(); if (verbose) { @@ -1478,14 +1452,11 @@ static void printArchiveChild(Archive::Child &C, bool verbose, } static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) { - if (A->hasSymbolTable()) { - Archive::child_iterator S = A->getSymbolTableChild(); - Archive::Child C = *S; - printArchiveChild(C, verbose, print_offset); - } - for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; - ++I) { - Archive::Child C = *I; + for (Archive::child_iterator I = A->child_begin(false), E = A->child_end(); + I != E; ++I) { + if (std::error_code EC = I->getError()) + report_fatal_error(EC.message()); + const Archive::Child &C = **I; printArchiveChild(C, verbose, print_offset); } } @@ -1510,10 +1481,8 @@ void llvm::ParseInputMachO(StringRef Filename) { // Attempt to open the binary. ErrorOr> BinaryOrErr = createBinary(Filename); - if (std::error_code EC = BinaryOrErr.getError()) { - errs() << "llvm-objdump: '" << Filename << "': " << EC.message() << ".\n"; - return; - } + if (std::error_code EC = BinaryOrErr.getError()) + report_error(Filename, EC); Binary &Bin = *BinaryOrErr.get().getBinary(); if (Archive *A = dyn_cast(&Bin)) { @@ -1522,7 +1491,10 @@ void llvm::ParseInputMachO(StringRef Filename) { printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets); for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; ++I) { - ErrorOr> ChildOrErr = I->getAsBinary(); + if (std::error_code EC = I->getError()) + report_error(Filename, EC); + auto &C = I->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = dyn_cast(&*ChildOrErr.get())) { @@ -1570,7 +1542,10 @@ void llvm::ParseInputMachO(StringRef Filename) { for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (std::error_code EC = AI->getError()) + report_error(Filename, EC); + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = @@ -1612,7 +1587,10 @@ void llvm::ParseInputMachO(StringRef Filename) { for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (std::error_code EC = AI->getError()) + report_error(Filename, EC); + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = @@ -1648,7 +1626,10 @@ void llvm::ParseInputMachO(StringRef Filename) { printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets); for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (std::error_code EC = AI->getError()) + report_error(Filename, EC); + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = @@ -1670,9 +1651,9 @@ void llvm::ParseInputMachO(StringRef Filename) { } else errs() << "llvm-objdump: '" << Filename << "': " << "Object is not a Mach-O file type.\n"; - } else - errs() << "llvm-objdump: '" << Filename << "': " - << "Unrecognized file type.\n"; + return; + } + llvm_unreachable("Input object can't be invalid at this point"); } typedef std::pair BindInfoEntry; @@ -1693,6 +1674,7 @@ struct DisassembleInfo { uint64_t adrp_addr; uint32_t adrp_inst; BindTable *bindtable; + uint32_t depth; }; // SymbolizerGetOpInfo() is the operand information call back function. @@ -1730,8 +1712,15 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, if (Arch == Triple::x86) { if (Size != 1 && Size != 2 && Size != 4 && Size != 0) return 0; - // First search the section's relocation entries (if any) for an entry - // for this section offset. + if (info->O->getHeader().filetype != MachO::MH_OBJECT) { + // TODO: + // Search the external relocation entries of a fully linked image + // (if any) for an entry that matches this segment offset. + // uint32_t seg_offset = (Pc + Offset); + return 0; + } + // In MH_OBJECT filetypes search the section's relocation entries (if any) + // for an entry for this section offset. uint32_t sect_addr = info->S.getAddress(); uint32_t sect_offset = (Pc + Offset) - sect_addr; bool reloc_found = false; @@ -1801,17 +1790,20 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, op_info->Value = offset; return 1; } - // TODO: - // Second search the external relocation entries of a fully linked image - // (if any) for an entry that matches this segment offset. - // uint32_t seg_offset = (Pc + Offset); return 0; } if (Arch == Triple::x86_64) { if (Size != 1 && Size != 2 && Size != 4 && Size != 0) return 0; - // First search the section's relocation entries (if any) for an entry - // for this section offset. + if (info->O->getHeader().filetype != MachO::MH_OBJECT) { + // TODO: + // Search the external relocation entries of a fully linked image + // (if any) for an entry that matches this segment offset. + // uint64_t seg_offset = (Pc + Offset); + return 0; + } + // In MH_OBJECT filetypes search the section's relocation entries (if any) + // for an entry for this section offset. uint64_t sect_addr = info->S.getAddress(); uint64_t sect_offset = (Pc + Offset) - sect_addr; bool reloc_found = false; @@ -1869,17 +1861,20 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, op_info->AddSymbol.Name = name; return 1; } - // TODO: - // Second search the external relocation entries of a fully linked image - // (if any) for an entry that matches this segment offset. - // uint64_t seg_offset = (Pc + Offset); return 0; } if (Arch == Triple::arm) { if (Offset != 0 || (Size != 4 && Size != 2)) return 0; - // First search the section's relocation entries (if any) for an entry - // for this section offset. + if (info->O->getHeader().filetype != MachO::MH_OBJECT) { + // TODO: + // Search the external relocation entries of a fully linked image + // (if any) for an entry that matches this segment offset. + // uint32_t seg_offset = (Pc + Offset); + return 0; + } + // In MH_OBJECT filetypes search the section's relocation entries (if any) + // for an entry for this section offset. uint32_t sect_addr = info->S.getAddress(); uint32_t sect_offset = (Pc + Offset) - sect_addr; DataRefImpl Rel; @@ -2011,8 +2006,15 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, if (Arch == Triple::aarch64) { if (Offset != 0 || Size != 4) return 0; - // First search the section's relocation entries (if any) for an entry - // for this section offset. + if (info->O->getHeader().filetype != MachO::MH_OBJECT) { + // TODO: + // Search the external relocation entries of a fully linked image + // (if any) for an entry that matches this segment offset. + // uint64_t seg_offset = (Pc + Offset); + return 0; + } + // In MH_OBJECT filetypes search the section's relocation entries (if any) + // for an entry for this section offset. uint64_t sect_addr = info->S.getAddress(); uint64_t sect_offset = (Pc + Offset) - sect_addr; auto Reloc = @@ -2365,6 +2367,8 @@ static const char *get_pointer_64(uint64_t Address, uint32_t &offset, for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); + if (SectSize == 0) + continue; if (objc_only) { StringRef SectName; ((*(info->Sections))[SectIdx]).getName(SectName); @@ -3262,6 +3266,8 @@ walk_pointer_list_32(const char *listname, const SectionRef S, } static void print_layout_map(const char *layout_map, uint32_t left) { + if (layout_map == nullptr) + return; outs() << " layout map: "; do { outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; @@ -3325,8 +3331,8 @@ static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, return; memset(&m, '\0', sizeof(struct method64_t)); if (left < sizeof(struct method64_t)) { - memcpy(&ml, r, left); - outs() << indent << " (method_t entends past the end of the section)\n"; + memcpy(&m, r, left); + outs() << indent << " (method_t extends past the end of the section)\n"; } else memcpy(&m, r, sizeof(struct method64_t)); if (info->O->isLittleEndian() != sys::IsLittleEndianHost) @@ -4217,7 +4223,7 @@ static void print_objc_property_list32(uint32_t p, } } -static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, +static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, bool &is_meta_class) { struct class_ro64_t cro; const char *r; @@ -4228,7 +4234,7 @@ static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, r = get_pointer_64(p, offset, left, S, info); if (r == nullptr || left < sizeof(struct class_ro64_t)) - return; + return false; memset(&cro, '\0', sizeof(struct class_ro64_t)); if (left < sizeof(struct class_ro64_t)) { memcpy(&cro, r, left); @@ -4352,10 +4358,11 @@ static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, if (cro.baseProperties + n_value != 0) print_objc_property_list64(cro.baseProperties + n_value, info); - is_meta_class = (cro.flags & RO_META) ? true : false; + is_meta_class = (cro.flags & RO_META) != 0; + return true; } -static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, +static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, bool &is_meta_class) { struct class_ro32_t cro; const char *r; @@ -4365,7 +4372,7 @@ static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, r = get_pointer_32(p, offset, left, S, info); if (r == nullptr) - return; + return false; memset(&cro, '\0', sizeof(struct class_ro32_t)); if (left < sizeof(struct class_ro32_t)) { memcpy(&cro, r, left); @@ -4415,7 +4422,8 @@ static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, << format("0x%" PRIx32, cro.baseProperties) << "\n"; if (cro.baseProperties != 0) print_objc_property_list32(cro.baseProperties, info); - is_meta_class = (cro.flags & RO_META) ? true : false; + is_meta_class = (cro.flags & RO_META) != 0; + return true; } static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { @@ -4485,11 +4493,16 @@ static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { outs() << " Swift class"; outs() << "\n"; bool is_meta_class; - print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class); + if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) + return; - if (is_meta_class == false) { - outs() << "Meta Class\n"; - print_class64_t(c.isa + isa_n_value, info); + if (!is_meta_class && + c.isa + isa_n_value != p && + c.isa + isa_n_value != 0 && + info->depth < 100) { + info->depth++; + outs() << "Meta Class\n"; + print_class64_t(c.isa + isa_n_value, info); } } @@ -4550,9 +4563,10 @@ static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { outs() << " Swift class"; outs() << "\n"; bool is_meta_class; - print_class_ro32_t(c.data & ~0x3, info, is_meta_class); + if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) + return; - if (is_meta_class == false) { + if (!is_meta_class) { outs() << "Meta Class\n"; print_class32_t(c.isa, info); } @@ -4860,7 +4874,7 @@ static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { outs() << " name " << format("0x%" PRIx32, c.name); name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, c.name); - if (name != NULL) + if (name) outs() << " " << name; outs() << "\n"; @@ -5001,6 +5015,9 @@ static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { struct objc_image_info64 o; const char *r; + if (S == SectionRef()) + return; + StringRef SectName; S.getName(SectName); DataRefImpl Ref = S.getRawDataRefImpl(); @@ -5137,75 +5154,48 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { info.adrp_addr = 0; info.adrp_inst = 0; - const SectionRef CL = get_section(O, "__OBJC2", "__class_list"); - if (CL != SectionRef()) { - info.S = CL; - walk_pointer_list_64("class", CL, O, &info, print_class64_t); - } else { - const SectionRef CL = get_section(O, "__DATA", "__objc_classlist"); - info.S = CL; - walk_pointer_list_64("class", CL, O, &info, print_class64_t); - } - - const SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); - if (CR != SectionRef()) { - info.S = CR; - walk_pointer_list_64("class refs", CR, O, &info, nullptr); - } else { - const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs"); - info.S = CR; - walk_pointer_list_64("class refs", CR, O, &info, nullptr); - } - - const SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); - if (SR != SectionRef()) { - info.S = SR; - walk_pointer_list_64("super refs", SR, O, &info, nullptr); - } else { - const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs"); - info.S = SR; - walk_pointer_list_64("super refs", SR, O, &info, nullptr); - } - - const SectionRef CA = get_section(O, "__OBJC2", "__category_list"); - if (CA != SectionRef()) { - info.S = CA; - walk_pointer_list_64("category", CA, O, &info, print_category64_t); - } else { - const SectionRef CA = get_section(O, "__DATA", "__objc_catlist"); - info.S = CA; - walk_pointer_list_64("category", CA, O, &info, print_category64_t); - } - - const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); - if (PL != SectionRef()) { - info.S = PL; - walk_pointer_list_64("protocol", PL, O, &info, nullptr); - } else { - const SectionRef PL = get_section(O, "__DATA", "__objc_protolist"); - info.S = PL; - walk_pointer_list_64("protocol", PL, O, &info, nullptr); - } - - const SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); - if (MR != SectionRef()) { - info.S = MR; - print_message_refs64(MR, &info); - } else { - const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs"); - info.S = MR; - print_message_refs64(MR, &info); - } - - const SectionRef II = get_section(O, "__OBJC2", "__image_info"); - if (II != SectionRef()) { - info.S = II; - print_image_info64(II, &info); - } else { - const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo"); - info.S = II; - print_image_info64(II, &info); - } + info.depth = 0; + SectionRef CL = get_section(O, "__OBJC2", "__class_list"); + if (CL == SectionRef()) + CL = get_section(O, "__DATA", "__objc_classlist"); + info.S = CL; + walk_pointer_list_64("class", CL, O, &info, print_class64_t); + + SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); + if (CR == SectionRef()) + CR = get_section(O, "__DATA", "__objc_classrefs"); + info.S = CR; + walk_pointer_list_64("class refs", CR, O, &info, nullptr); + + SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); + if (SR == SectionRef()) + SR = get_section(O, "__DATA", "__objc_superrefs"); + info.S = SR; + walk_pointer_list_64("super refs", SR, O, &info, nullptr); + + SectionRef CA = get_section(O, "__OBJC2", "__category_list"); + if (CA == SectionRef()) + CA = get_section(O, "__DATA", "__objc_catlist"); + info.S = CA; + walk_pointer_list_64("category", CA, O, &info, print_category64_t); + + SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); + if (PL == SectionRef()) + PL = get_section(O, "__DATA", "__objc_protolist"); + info.S = PL; + walk_pointer_list_64("protocol", PL, O, &info, nullptr); + + SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); + if (MR == SectionRef()) + MR = get_section(O, "__DATA", "__objc_msgrefs"); + info.S = MR; + print_message_refs64(MR, &info); + + SectionRef II = get_section(O, "__OBJC2", "__image_info"); + if (II == SectionRef()) + II = get_section(O, "__DATA", "__objc_imageinfo"); + info.S = II; + print_image_info64(II, &info); if (info.bindtable != nullptr) delete info.bindtable; @@ -5554,7 +5544,7 @@ static void printObjcMetaData(MachOObjectFile *O, bool verbose) { // binary for the iOS simulator which is the second Objective-C // ABI. In that case printObjc1_32bit_MetaData() will determine that // and return false. - if (printObjc1_32bit_MetaData(O, verbose) == false) + if (!printObjc1_32bit_MetaData(O, verbose)) printObjc2_32bit_MetaData(O, verbose); } } @@ -5583,36 +5573,38 @@ static const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t *ReferenceType, struct DisassembleInfo *info) { // First see if there is an external relocation entry at the ReferencePC. - uint64_t sect_addr = info->S.getAddress(); - uint64_t sect_offset = ReferencePC - sect_addr; - bool reloc_found = false; - DataRefImpl Rel; - MachO::any_relocation_info RE; - bool isExtern = false; - SymbolRef Symbol; - for (const RelocationRef &Reloc : info->S.relocations()) { - uint64_t RelocOffset = Reloc.getOffset(); - if (RelocOffset == sect_offset) { - Rel = Reloc.getRawDataRefImpl(); - RE = info->O->getRelocation(Rel); - if (info->O->isRelocationScattered(RE)) - continue; - isExtern = info->O->getPlainRelocationExternal(RE); - if (isExtern) { - symbol_iterator RelocSym = Reloc.getSymbol(); - Symbol = *RelocSym; + if (info->O->getHeader().filetype == MachO::MH_OBJECT) { + uint64_t sect_addr = info->S.getAddress(); + uint64_t sect_offset = ReferencePC - sect_addr; + bool reloc_found = false; + DataRefImpl Rel; + MachO::any_relocation_info RE; + bool isExtern = false; + SymbolRef Symbol; + for (const RelocationRef &Reloc : info->S.relocations()) { + uint64_t RelocOffset = Reloc.getOffset(); + if (RelocOffset == sect_offset) { + Rel = Reloc.getRawDataRefImpl(); + RE = info->O->getRelocation(Rel); + if (info->O->isRelocationScattered(RE)) + continue; + isExtern = info->O->getPlainRelocationExternal(RE); + if (isExtern) { + symbol_iterator RelocSym = Reloc.getSymbol(); + Symbol = *RelocSym; + } + reloc_found = true; + break; } - reloc_found = true; - break; } - } - // If there is an external relocation entry for a symbol in a section - // then used that symbol's value for the value of the reference. - if (reloc_found && isExtern) { - if (info->O->getAnyRelocationPCRel(RE)) { - unsigned Type = info->O->getAnyRelocationType(RE); - if (Type == MachO::X86_64_RELOC_SIGNED) { - ReferenceValue = Symbol.getValue(); + // If there is an external relocation entry for a symbol in a section + // then used that symbol's value for the value of the reference. + if (reloc_found && isExtern) { + if (info->O->getAnyRelocationPCRel(RE)) { + unsigned Type = info->O->getAnyRelocationType(RE); + if (Type == MachO::X86_64_RELOC_SIGNED) { + ReferenceValue = Symbol.getValue(); + } } } } @@ -5867,7 +5859,6 @@ static void emitComments(raw_svector_ostream &CommentStream, formatted_raw_ostream &FormattedOS, const MCAsmInfo &MAI) { // Flush the stream before taking its content. - CommentStream.flush(); StringRef Comments = CommentsToEmit.str(); // Get the default information for printing a comment. const char *CommentBegin = MAI.getCommentString(); @@ -5888,7 +5879,6 @@ static void emitComments(raw_svector_ostream &CommentStream, // Tell the comment stream that the vector changed underneath it. CommentsToEmit.clear(); - CommentStream.resync(); } static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, @@ -6082,19 +6072,6 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, bool symbolTableWorked = false; - // Parse relocations. - std::vector> Relocs; - for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) { - uint64_t RelocOffset = Reloc.getOffset(); - uint64_t SectionAddress = Sections[SectIdx].getAddress(); - RelocOffset -= SectionAddress; - - symbol_iterator RelocSym = Reloc.getSymbol(); - - Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); - } - array_pod_sort(Relocs.begin(), Relocs.end()); - // Create a map of symbol addresses to symbol names for use by // the SymbolizerSymbolLookUp() routine. SymbolAddressMap AddrMap; @@ -6152,7 +6129,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, StringRef SymName = *SymNameOrErr; SymbolRef::Type ST = Symbols[SymIdx].getType(); - if (ST != SymbolRef::ST_Function) + if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) continue; // Make sure the symbol is defined in this section. @@ -6246,10 +6223,9 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, DebugOut, Annotations); if (gotInst) { if (!NoShowRawInsn) { - dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs()); + dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); } formatted_raw_ostream FormattedOS(outs()); - Annotations.flush(); StringRef AnnotationsStr = Annotations.str(); if (isThumb) ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI); @@ -6311,7 +6287,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, } if (!NoShowRawInsn) { outs() << "\t"; - dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs()); + dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); } IP->printInst(&Inst, outs(), "", *STI); outs() << "\n"; @@ -6774,6 +6750,262 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, } } +static unsigned getSizeForEncoding(bool is64Bit, + unsigned symbolEncoding) { + unsigned format = symbolEncoding & 0x0f; + switch (format) { + default: llvm_unreachable("Unknown Encoding"); + case dwarf::DW_EH_PE_absptr: + case dwarf::DW_EH_PE_signed: + return is64Bit ? 8 : 4; + case dwarf::DW_EH_PE_udata2: + case dwarf::DW_EH_PE_sdata2: + return 2; + case dwarf::DW_EH_PE_udata4: + case dwarf::DW_EH_PE_sdata4: + return 4; + case dwarf::DW_EH_PE_udata8: + case dwarf::DW_EH_PE_sdata8: + return 8; + } +} + +static uint64_t readPointer(const char *&Pos, bool is64Bit, unsigned Encoding) { + switch (getSizeForEncoding(is64Bit, Encoding)) { + case 2: + return readNext(Pos); + break; + case 4: + return readNext(Pos); + break; + case 8: + return readNext(Pos); + break; + default: + llvm_unreachable("Illegal data size"); + } +} + +static void printMachOEHFrameSection(const MachOObjectFile *Obj, + std::map &Symbols, + const SectionRef &EHFrame) { + if (!Obj->isLittleEndian()) { + outs() << "warning: cannot handle big endian __eh_frame section\n"; + return; + } + + bool is64Bit = Obj->is64Bit(); + + outs() << "Contents of __eh_frame section:\n"; + + StringRef Contents; + EHFrame.getContents(Contents); + + /// A few fields of the CIE are used when decoding the FDE's. This struct + /// will cache those fields we need so that we don't have to decode it + /// repeatedly for each FDE that references it. + struct DecodedCIE { + Optional FDEPointerEncoding; + Optional LSDAPointerEncoding; + bool hasAugmentationLength; + }; + + // Map from the start offset of the CIE to the cached data for that CIE. + DenseMap CachedCIEs; + + for (const char *Pos = Contents.data(), *End = Contents.end(); Pos != End; ) { + + const char *EntryStartPos = Pos; + + uint64_t Length = readNext(Pos); + if (Length == 0xffffffff) + Length = readNext(Pos); + + // Save the Pos so that we can check the length we encoded against what we + // end up decoding. + const char *PosAfterLength = Pos; + const char *EntryEndPos = PosAfterLength + Length; + + assert(EntryEndPos <= End && + "__eh_frame entry length exceeds section size"); + + uint32_t ID = readNext(Pos); + if (ID == 0) { + // This is a CIE. + + uint32_t Version = readNext(Pos); + + // Parse a null terminated augmentation string + SmallString<8> AugmentationString; + for (uint8_t Char = readNext(Pos); Char; + Char = readNext(Pos)) + AugmentationString.push_back(Char); + + // Optionally parse the EH data if the augmentation string says it's there. + Optional EHData; + if (StringRef(AugmentationString).count("eh")) + EHData = is64Bit ? readNext(Pos) : readNext(Pos); + + unsigned ULEBByteCount; + uint64_t CodeAlignmentFactor = decodeULEB128((const uint8_t *)Pos, + &ULEBByteCount); + Pos += ULEBByteCount; + + int64_t DataAlignmentFactor = decodeSLEB128((const uint8_t *)Pos, + &ULEBByteCount); + Pos += ULEBByteCount; + + uint32_t ReturnAddressRegister = readNext(Pos); + + Optional AugmentationLength; + Optional LSDAPointerEncoding; + Optional PersonalityEncoding; + Optional Personality; + Optional FDEPointerEncoding; + if (!AugmentationString.empty() && AugmentationString.front() == 'z') { + AugmentationLength = decodeULEB128((const uint8_t *)Pos, + &ULEBByteCount); + Pos += ULEBByteCount; + + // Walk the augmentation string to get all the augmentation data. + for (unsigned i = 1, e = AugmentationString.size(); i != e; ++i) { + char Char = AugmentationString[i]; + switch (Char) { + case 'e': + assert((i + 1) != e && AugmentationString[i + 1] == 'h' && + "Expected 'eh' in augmentation string"); + break; + case 'L': + assert(!LSDAPointerEncoding && "Duplicate LSDA encoding"); + LSDAPointerEncoding = readNext(Pos); + break; + case 'P': { + assert(!Personality && "Duplicate personality"); + PersonalityEncoding = readNext(Pos); + Personality = readPointer(Pos, is64Bit, *PersonalityEncoding); + break; + } + case 'R': + assert(!FDEPointerEncoding && "Duplicate FDE encoding"); + FDEPointerEncoding = readNext(Pos); + break; + case 'z': + llvm_unreachable("'z' must be first in the augmentation string"); + } + } + } + + outs() << "CIE:\n"; + outs() << " Length: " << Length << "\n"; + outs() << " CIE ID: " << ID << "\n"; + outs() << " Version: " << Version << "\n"; + outs() << " Augmentation String: " << AugmentationString << "\n"; + if (EHData) + outs() << " EHData: " << *EHData << "\n"; + outs() << " Code Alignment Factor: " << CodeAlignmentFactor << "\n"; + outs() << " Data Alignment Factor: " << DataAlignmentFactor << "\n"; + outs() << " Return Address Register: " << ReturnAddressRegister << "\n"; + if (AugmentationLength) { + outs() << " Augmentation Data Length: " << *AugmentationLength << "\n"; + if (LSDAPointerEncoding) { + outs() << " FDE LSDA Pointer Encoding: " + << *LSDAPointerEncoding << "\n"; + } + if (Personality) { + outs() << " Personality Encoding: " << *PersonalityEncoding << "\n"; + outs() << " Personality: " << *Personality << "\n"; + } + if (FDEPointerEncoding) { + outs() << " FDE Address Pointer Encoding: " + << *FDEPointerEncoding << "\n"; + } + } + // FIXME: Handle instructions. + // For now just emit some bytes + outs() << " Instructions:\n "; + dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos), + outs()); + outs() << "\n"; + Pos = EntryEndPos; + + // Cache this entry. + uint64_t Offset = EntryStartPos - Contents.data(); + CachedCIEs[Offset] = { FDEPointerEncoding, LSDAPointerEncoding, + AugmentationLength.hasValue() }; + continue; + } + + // This is an FDE. + // The CIE pointer for an FDE is the same location as the ID which we + // already read. + uint32_t CIEPointer = ID; + + const char *CIEStart = PosAfterLength - CIEPointer; + assert(CIEStart >= Contents.data() && + "FDE points to CIE before the __eh_frame start"); + + uint64_t CIEOffset = CIEStart - Contents.data(); + auto CIEIt = CachedCIEs.find(CIEOffset); + if (CIEIt == CachedCIEs.end()) + llvm_unreachable("Couldn't find CIE at offset in to __eh_frame section"); + + const DecodedCIE &CIE = CIEIt->getSecond(); + assert(CIE.FDEPointerEncoding && + "FDE references CIE which did not set pointer encoding"); + + uint64_t PCPointerSize = getSizeForEncoding(is64Bit, + *CIE.FDEPointerEncoding); + + uint64_t PCBegin = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding); + uint64_t PCRange = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding); + + Optional AugmentationLength; + uint32_t LSDAPointerSize; + Optional LSDAPointer; + if (CIE.hasAugmentationLength) { + unsigned ULEBByteCount; + AugmentationLength = decodeULEB128((const uint8_t *)Pos, + &ULEBByteCount); + Pos += ULEBByteCount; + + // Decode the LSDA if the CIE augmentation string said we should. + if (CIE.LSDAPointerEncoding) { + LSDAPointerSize = getSizeForEncoding(is64Bit, *CIE.LSDAPointerEncoding); + LSDAPointer = readPointer(Pos, is64Bit, *CIE.LSDAPointerEncoding); + } + } + + outs() << "FDE:\n"; + outs() << " Length: " << Length << "\n"; + outs() << " CIE Offset: " << CIEOffset << "\n"; + + if (PCPointerSize == 8) { + outs() << format(" PC Begin: %016" PRIx64, PCBegin) << "\n"; + outs() << format(" PC Range: %016" PRIx64, PCRange) << "\n"; + } else { + outs() << format(" PC Begin: %08" PRIx64, PCBegin) << "\n"; + outs() << format(" PC Range: %08" PRIx64, PCRange) << "\n"; + } + if (AugmentationLength) { + outs() << " Augmentation Data Length: " << *AugmentationLength << "\n"; + if (LSDAPointer) { + if (LSDAPointerSize == 8) + outs() << format(" LSDA Pointer: %016\n" PRIx64, *LSDAPointer); + else + outs() << format(" LSDA Pointer: %08\n" PRIx64, *LSDAPointer); + } + } + + // FIXME: Handle instructions. + // For now just emit some bytes + outs() << " Instructions:\n "; + dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos), + outs()); + outs() << "\n"; + Pos = EntryEndPos; + } +} + void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { std::map Symbols; for (const SymbolRef &SymRef : Obj->symbols()) { @@ -6795,7 +7027,7 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { else if (SectName == "__unwind_info") printMachOUnwindInfoSection(Obj, Symbols, Section); else if (SectName == "__eh_frame") - outs() << "llvm-objdump: warning: unhandled __eh_frame section\n"; + printMachOEHFrameSection(Obj, Symbols, Section); } } @@ -7121,36 +7353,20 @@ static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, MachO::VM_PROT_EXECUTE)) != 0) outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; else { - if (maxprot & MachO::VM_PROT_READ) - outs() << " maxprot r"; - else - outs() << " maxprot -"; - if (maxprot & MachO::VM_PROT_WRITE) - outs() << "w"; - else - outs() << "-"; - if (maxprot & MachO::VM_PROT_EXECUTE) - outs() << "x\n"; - else - outs() << "-\n"; + outs() << " maxprot "; + outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); + outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); + outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); } if ((initprot & ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE)) != 0) outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; else { - if (initprot & MachO::VM_PROT_READ) - outs() << " initprot r"; - else - outs() << " initprot -"; - if (initprot & MachO::VM_PROT_WRITE) - outs() << "w"; - else - outs() << "-"; - if (initprot & MachO::VM_PROT_EXECUTE) - outs() << "x\n"; - else - outs() << "-\n"; + outs() << " initprot "; + outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); + outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); + outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); } } else { outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; @@ -7604,26 +7820,11 @@ static void PrintUuidLoadCommand(MachO::uuid_command uuid) { else outs() << "\n"; outs() << " uuid "; - outs() << format("%02" PRIX32, uuid.uuid[0]); - outs() << format("%02" PRIX32, uuid.uuid[1]); - outs() << format("%02" PRIX32, uuid.uuid[2]); - outs() << format("%02" PRIX32, uuid.uuid[3]); - outs() << "-"; - outs() << format("%02" PRIX32, uuid.uuid[4]); - outs() << format("%02" PRIX32, uuid.uuid[5]); - outs() << "-"; - outs() << format("%02" PRIX32, uuid.uuid[6]); - outs() << format("%02" PRIX32, uuid.uuid[7]); - outs() << "-"; - outs() << format("%02" PRIX32, uuid.uuid[8]); - outs() << format("%02" PRIX32, uuid.uuid[9]); - outs() << "-"; - outs() << format("%02" PRIX32, uuid.uuid[10]); - outs() << format("%02" PRIX32, uuid.uuid[11]); - outs() << format("%02" PRIX32, uuid.uuid[12]); - outs() << format("%02" PRIX32, uuid.uuid[13]); - outs() << format("%02" PRIX32, uuid.uuid[14]); - outs() << format("%02" PRIX32, uuid.uuid[15]); + for (int i = 0; i < 16; ++i) { + outs() << format("%02" PRIX32, uuid.uuid[i]); + if (i == 3 || i == 5 || i == 7 || i == 9) + outs() << "-"; + } outs() << "\n"; } @@ -7643,30 +7844,47 @@ static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { } static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { - if (vd.cmd == MachO::LC_VERSION_MIN_MACOSX) - outs() << " cmd LC_VERSION_MIN_MACOSX\n"; - else if (vd.cmd == MachO::LC_VERSION_MIN_IPHONEOS) - outs() << " cmd LC_VERSION_MIN_IPHONEOS\n"; - else - outs() << " cmd " << vd.cmd << " (?)\n"; + StringRef LoadCmdName; + switch (vd.cmd) { + case MachO::LC_VERSION_MIN_MACOSX: + LoadCmdName = "LC_VERSION_MIN_MACOSX"; + break; + case MachO::LC_VERSION_MIN_IPHONEOS: + LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; + break; + case MachO::LC_VERSION_MIN_TVOS: + LoadCmdName = "LC_VERSION_MIN_TVOS"; + break; + case MachO::LC_VERSION_MIN_WATCHOS: + LoadCmdName = "LC_VERSION_MIN_WATCHOS"; + break; + default: + llvm_unreachable("Unknown version min load command"); + } + + outs() << " cmd " << LoadCmdName << '\n'; outs() << " cmdsize " << vd.cmdsize; if (vd.cmdsize != sizeof(struct MachO::version_min_command)) outs() << " Incorrect size\n"; else outs() << "\n"; - outs() << " version " << ((vd.version >> 16) & 0xffff) << "." - << ((vd.version >> 8) & 0xff); - if ((vd.version & 0xff) != 0) - outs() << "." << (vd.version & 0xff); + outs() << " version " + << MachOObjectFile::getVersionMinMajor(vd, false) << "." + << MachOObjectFile::getVersionMinMinor(vd, false); + uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); + if (Update != 0) + outs() << "." << Update; outs() << "\n"; if (vd.sdk == 0) outs() << " sdk n/a"; else { - outs() << " sdk " << ((vd.sdk >> 16) & 0xffff) << "." - << ((vd.sdk >> 8) & 0xff); + outs() << " sdk " + << MachOObjectFile::getVersionMinMajor(vd, true) << "." + << MachOObjectFile::getVersionMinMinor(vd, true); } - if ((vd.sdk & 0xff) != 0) - outs() << "." << (vd.sdk & 0xff); + Update = MachOObjectFile::getVersionMinUpdate(vd, true); + if (Update != 0) + outs() << "." << Update; outs() << "\n"; } @@ -8359,7 +8577,9 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, MachO::rpath_command Rpath = Obj->getRpathCommand(Command); PrintRpathLoadCommand(Rpath, Command.Ptr); } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || - Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) { + Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || + Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || + Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); PrintVersionMinLoadCommand(Vd); } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { @@ -8429,31 +8649,40 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, } } -static void getAndPrintMachHeader(const MachOObjectFile *Obj, - uint32_t &filetype, uint32_t &cputype, - bool verbose) { +static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { if (Obj->is64Bit()) { MachO::mach_header_64 H_64; H_64 = Obj->getHeader64(); PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); - filetype = H_64.filetype; - cputype = H_64.cputype; } else { MachO::mach_header H; H = Obj->getHeader(); PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, H.sizeofcmds, H.flags, verbose); - filetype = H.filetype; - cputype = H.cputype; } } void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { + const MachOObjectFile *file = dyn_cast(Obj); + PrintMachHeader(file, !NonVerbose); +} + +void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) { const MachOObjectFile *file = dyn_cast(Obj); uint32_t filetype = 0; uint32_t cputype = 0; - getAndPrintMachHeader(file, filetype, cputype, !NonVerbose); + if (file->is64Bit()) { + MachO::mach_header_64 H_64; + H_64 = file->getHeader64(); + filetype = H_64.filetype; + cputype = H_64.cputype; + } else { + MachO::mach_header H; + H = file->getHeader(); + filetype = H.filetype; + cputype = H.cputype; + } PrintLoadCommands(file, filetype, cputype, !NonVerbose); } @@ -8529,6 +8758,7 @@ public: StringRef segmentName(uint32_t SegIndex); StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset); uint64_t address(uint32_t SegIndex, uint64_t SegOffset); + bool isValidSegIndexAndOffset(uint32_t SegIndex, uint64_t SegOffset); private: struct SectionInfo { @@ -8577,6 +8807,20 @@ StringRef SegInfo::segmentName(uint32_t SegIndex) { llvm_unreachable("invalid segIndex"); } +bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex, + uint64_t OffsetInSeg) { + for (const SectionInfo &SI : Sections) { + if (SI.SegmentIndex != SegIndex) + continue; + if (SI.OffsetInSegment > OffsetInSeg) + continue; + if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size)) + continue; + return true; + } + return false; +} + const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex, uint64_t OffsetInSeg) { for (const SectionInfo &SI : Sections) { @@ -8745,6 +8989,8 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) { uint32_t SegIndex = Entry.segmentIndex(); uint64_t OffsetInSeg = Entry.segmentOffset(); + if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg)) + continue; uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); const char *SymbolName = nullptr; StringRef name = Entry.symbolName();