diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/tools/llvm-objdump/MachODump.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/tools/llvm-objdump/MachODump.cpp')
-rw-r--r-- | llvm/tools/llvm-objdump/MachODump.cpp | 488 |
1 files changed, 381 insertions, 107 deletions
diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index cdbecd5ec243..fadc8367a8c1 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -78,9 +78,11 @@ bool objdump::UniversalHeaders; static bool ArchiveMemberOffsets; bool objdump::IndirectSymbols; bool objdump::DataInCode; -bool objdump::FunctionStarts; +FunctionStartsMode objdump::FunctionStartsType = + objdump::FunctionStartsMode::None; bool objdump::LinkOptHints; bool objdump::InfoPlist; +bool objdump::ChainedFixups; bool objdump::DyldInfo; bool objdump::DylibsUsed; bool objdump::DylibId; @@ -93,6 +95,8 @@ static std::vector<std::string> ArchFlags; static bool ArchAll = false; static std::string ThumbTripleName; +static StringRef ordinalName(const object::MachOObjectFile *, int); + void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) { FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header); ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie); @@ -109,9 +113,18 @@ void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) { ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets); IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols); DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code); - FunctionStarts = InputArgs.hasArg(OBJDUMP_function_starts); + if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_function_starts_EQ)) { + FunctionStartsType = StringSwitch<FunctionStartsMode>(A->getValue()) + .Case("addrs", FunctionStartsMode::Addrs) + .Case("names", FunctionStartsMode::Names) + .Case("both", FunctionStartsMode::Both) + .Default(FunctionStartsMode::None); + if (FunctionStartsType == FunctionStartsMode::None) + invalidArgValue(A); + } LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints); InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist); + ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups); DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info); DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used); DylibId = InputArgs.hasArg(OBJDUMP_dylib_id); @@ -242,19 +255,19 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, case MachO::DICE_KIND_DATA: if (Length >= 4) { if (ShowRawInsn) - dumpBytes(makeArrayRef(bytes, 4), outs()); + dumpBytes(ArrayRef(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 (ShowRawInsn) - dumpBytes(makeArrayRef(bytes, 2), outs()); + dumpBytes(ArrayRef(bytes, 2), outs()); Value = bytes[1] << 8 | bytes[0]; outs() << "\t.short " << Value; Size = 2; } else { if (ShowRawInsn) - dumpBytes(makeArrayRef(bytes, 2), outs()); + dumpBytes(ArrayRef(bytes, 2), outs()); Value = bytes[0]; outs() << "\t.byte " << Value; Size = 1; @@ -266,14 +279,14 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, break; case MachO::DICE_KIND_JUMP_TABLE8: if (ShowRawInsn) - dumpBytes(makeArrayRef(bytes, 1), outs()); + dumpBytes(ArrayRef(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 (ShowRawInsn) - dumpBytes(makeArrayRef(bytes, 2), outs()); + dumpBytes(ArrayRef(bytes, 2), outs()); Value = bytes[1] << 8 | bytes[0]; outs() << "\t.short " << format("%5u", Value & 0xffff) << "\t@ KIND_JUMP_TABLE16\n"; @@ -282,7 +295,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 (ShowRawInsn) - dumpBytes(makeArrayRef(bytes, 4), outs()); + dumpBytes(ArrayRef(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) @@ -1076,12 +1089,39 @@ static void PrintFunctionStarts(MachOObjectFile *O) { } } + DenseMap<uint64_t, StringRef> SymbolNames; + if (FunctionStartsType == FunctionStartsMode::Names || + FunctionStartsType == FunctionStartsMode::Both) { + for (SymbolRef Sym : O->symbols()) { + if (Expected<uint64_t> Addr = Sym.getAddress()) { + if (Expected<StringRef> Name = Sym.getName()) { + SymbolNames[*Addr] = *Name; + } + } + } + } + for (uint64_t S : FunctionStarts) { uint64_t Addr = BaseSegmentAddress + S; - if (O->is64Bit()) - outs() << format("%016" PRIx64, Addr) << "\n"; - else - outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)) << "\n"; + if (FunctionStartsType == FunctionStartsMode::Names) { + auto It = SymbolNames.find(Addr); + if (It != SymbolNames.end()) + outs() << It->second << "\n"; + } else { + if (O->is64Bit()) + outs() << format("%016" PRIx64, Addr); + else + outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)); + + if (FunctionStartsType == FunctionStartsMode::Both) { + auto It = SymbolNames.find(Addr); + if (It != SymbolNames.end()) + outs() << " " << It->second; + else + outs() << " ?"; + } + outs() << "\n"; + } } } @@ -1184,18 +1224,209 @@ static void PrintLinkOptHints(MachOObjectFile *O) { } } -static void printMachOChainedFixups(object::MachOObjectFile *Obj) { - Error Err = Error::success(); - for (const object::MachOChainedFixupEntry &Entry : Obj->fixupTable(Err)) { - (void)Entry; +static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) { + SmallVector<std::string> Ret; + for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) { + if (Command.C.cmd == MachO::LC_SEGMENT) { + MachO::segment_command SLC = O->getSegmentLoadCommand(Command); + Ret.push_back(SLC.segname); + } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { + MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command); + Ret.push_back(SLC.segname); + } } - if (Err) - reportError(std::move(Err), Obj->getFileName()); + return Ret; +} + +static void +PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) { + outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n"; + outs() << " fixups_version = " << H.fixups_version << '\n'; + outs() << " starts_offset = " << H.starts_offset << '\n'; + outs() << " imports_offset = " << H.imports_offset << '\n'; + outs() << " symbols_offset = " << H.symbols_offset << '\n'; + outs() << " imports_count = " << H.imports_count << '\n'; + + outs() << " imports_format = " << H.imports_format; + switch (H.imports_format) { + case llvm::MachO::DYLD_CHAINED_IMPORT: + outs() << " (DYLD_CHAINED_IMPORT)"; + break; + case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND: + outs() << " (DYLD_CHAINED_IMPORT_ADDEND)"; + break; + case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64: + outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)"; + break; + } + outs() << '\n'; + + outs() << " symbols_format = " << H.symbols_format; + if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB) + outs() << " (zlib compressed)"; + outs() << '\n'; +} + +static constexpr std::array<StringRef, 13> PointerFormats{ + "DYLD_CHAINED_PTR_ARM64E", + "DYLD_CHAINED_PTR_64", + "DYLD_CHAINED_PTR_32", + "DYLD_CHAINED_PTR_32_CACHE", + "DYLD_CHAINED_PTR_32_FIRMWARE", + "DYLD_CHAINED_PTR_64_OFFSET", + "DYLD_CHAINED_PTR_ARM64E_KERNEL", + "DYLD_CHAINED_PTR_64_KERNEL_CACHE", + "DYLD_CHAINED_PTR_ARM64E_USERLAND", + "DYLD_CHAINED_PTR_ARM64E_FIRMWARE", + "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE", + "DYLD_CHAINED_PTR_ARM64E_USERLAND24", +}; + +static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment, + StringRef SegName) { + outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName + << ")\n"; + outs() << " size = " << Segment.Header.size << '\n'; + outs() << " page_size = " << format("0x%0" PRIx16, Segment.Header.page_size) + << '\n'; + + outs() << " pointer_format = " << Segment.Header.pointer_format; + if ((Segment.Header.pointer_format - 1) < + MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24) + outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")"; + outs() << '\n'; + + outs() << " segment_offset = " + << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n'; + outs() << " max_valid_pointer = " << Segment.Header.max_valid_pointer + << '\n'; + outs() << " page_count = " << Segment.Header.page_count << '\n'; + for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) { + outs() << " page_start[" << Index << "] = " << PageStart; + // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only) + if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE) + outs() << " (DYLD_CHAINED_PTR_START_NONE)"; + outs() << '\n'; + } +} + +static void PrintChainedFixupTarget(ChainedFixupTarget &Target, size_t Idx, + int Format, MachOObjectFile *O) { + if (Format == MachO::DYLD_CHAINED_IMPORT) + outs() << "dyld chained import"; + else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND) + outs() << "dyld chained import addend"; + else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) + outs() << "dyld chained import addend64"; + // FIXME: otool prints the encoded value as well. + outs() << '[' << Idx << "]\n"; + + outs() << " lib_ordinal = " << Target.libOrdinal() << " (" + << ordinalName(O, Target.libOrdinal()) << ")\n"; + outs() << " weak_import = " << Target.weakImport() << '\n'; + outs() << " name_offset = " << Target.nameOffset() << " (" + << Target.symbolName() << ")\n"; + if (Format != MachO::DYLD_CHAINED_IMPORT) + outs() << " addend = " << (int64_t)Target.addend() << '\n'; +} + +static void PrintChainedFixups(MachOObjectFile *O) { + // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS. + // FIXME: Support chained fixups in __TEXT,__chain_starts section too. + auto ChainedFixupHeader = + unwrapOrError(O->getChainedFixupsHeader(), O->getFileName()); + if (!ChainedFixupHeader) + return; + + PrintChainedFixupsHeader(*ChainedFixupHeader); + + auto [SegCount, Segments] = + unwrapOrError(O->getChainedFixupsSegments(), O->getFileName()); + + auto SegNames = GetSegmentNames(O); + + size_t StartsIdx = 0; + outs() << "chained starts in image\n"; + outs() << " seg_count = " << SegCount << '\n'; + for (size_t I = 0; I < SegCount; ++I) { + uint64_t SegOffset = 0; + if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) { + SegOffset = Segments[StartsIdx].Offset; + ++StartsIdx; + } + + outs() << " seg_offset[" << I << "] = " << SegOffset << " (" + << SegNames[I] << ")\n"; + } + + for (const ChainedFixupsSegment &S : Segments) + PrintChainedFixupsSegment(S, SegNames[S.SegIdx]); + + auto FixupTargets = + unwrapOrError(O->getDyldChainedFixupTargets(), O->getFileName()); + + uint32_t ImportsFormat = ChainedFixupHeader->imports_format; + for (auto [Idx, Target] : enumerate(FixupTargets)) + PrintChainedFixupTarget(Target, Idx, ImportsFormat, O); } static void PrintDyldInfo(MachOObjectFile *O) { - outs() << "dyld information:" << '\n'; - printMachOChainedFixups(O); + Error Err = Error::success(); + + size_t SegmentWidth = strlen("segment"); + size_t SectionWidth = strlen("section"); + size_t AddressWidth = strlen("address"); + size_t AddendWidth = strlen("addend"); + size_t DylibWidth = strlen("dylib"); + const size_t PointerWidth = 2 + O->getBytesInAddress() * 2; + + auto HexLength = [](uint64_t Num) { + return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1; + }; + for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) { + SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size()); + SectionWidth = std::max(SectionWidth, Entry.sectionName().size()); + AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2); + if (Entry.isBind()) { + AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2); + DylibWidth = std::max(DylibWidth, Entry.symbolName().size()); + } + } + // Errors will be handled when printing the table. + if (Err) + consumeError(std::move(Err)); + + outs() << "dyld information:\n"; + outs() << left_justify("segment", SegmentWidth) << ' ' + << left_justify("section", SectionWidth) << ' ' + << left_justify("address", AddressWidth) << ' ' + << left_justify("pointer", PointerWidth) << " type " + << left_justify("addend", AddendWidth) << ' ' + << left_justify("dylib", DylibWidth) << " symbol/vm address\n"; + for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) { + outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' ' + << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x" + << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' ' + << format_hex(Entry.rawValue(), PointerWidth, true) << ' '; + if (Entry.isBind()) { + outs() << "bind " + << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2) + << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth) + << ' ' << Entry.symbolName(); + if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) + outs() << " (weak import)"; + outs() << '\n'; + } else { + assert(Entry.isRebase()); + outs() << "rebase"; + outs().indent(AddendWidth + DylibWidth + 2); + outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n'; + } + } + if (Err) + reportError(std::move(Err), O->getFileName()); + + // TODO: Print opcode-based fixups if the object uses those. } static void PrintDylibs(MachOObjectFile *O, bool JustId) { @@ -1916,8 +2147,9 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, // UniversalHeaders or ArchiveHeaders. if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || - DataInCode || FunctionStarts || LinkOptHints || DyldInfo || DylibsUsed || - DylibId || Rpaths || ObjcMetaData || (!FilterSections.empty())) { + DataInCode || FunctionStartsType != FunctionStartsMode::None || + LinkOptHints || ChainedFixups || DyldInfo || DylibsUsed || DylibId || + Rpaths || ObjcMetaData || (!FilterSections.empty())) { if (LeadingHeaders) { outs() << Name; if (!ArchiveMemberName.empty()) @@ -1972,7 +2204,7 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, PrintIndirectSymbols(MachOOF, Verbose); if (DataInCode) PrintDataInCodeTable(MachOOF, Verbose); - if (FunctionStarts) + if (FunctionStartsType != FunctionStartsMode::None) PrintFunctionStarts(MachOOF); if (LinkOptHints) PrintLinkOptHints(MachOOF); @@ -1988,6 +2220,8 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, DumpInfoPlistSectionContents(FileName, MachOOF); if (DyldInfo) PrintDyldInfo(MachOOF); + if (ChainedFixups) + PrintChainedFixups(MachOOF); if (DylibsUsed) PrintDylibs(MachOOF, false); if (DylibId) @@ -7189,6 +7423,108 @@ static void emitComments(raw_svector_ostream &CommentStream, CommentsToEmit.clear(); } +const MachOObjectFile * +objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename, + std::unique_ptr<Binary> &DSYMBinary, + std::unique_ptr<MemoryBuffer> &DSYMBuf) { + const MachOObjectFile *DbgObj = MachOOF; + std::string DSYMPath; + + // Auto-detect w/o --dsym. + if (DSYMFile.empty()) { + sys::fs::file_status DSYMStatus; + Twine FilenameDSYM = Filename + ".dSYM"; + if (!status(FilenameDSYM, DSYMStatus)) { + if (sys::fs::is_directory(DSYMStatus)) { + SmallString<1024> Path; + FilenameDSYM.toVector(Path); + sys::path::append(Path, "Contents", "Resources", "DWARF", + sys::path::filename(Filename)); + DSYMPath = std::string(Path); + } else if (sys::fs::is_regular_file(DSYMStatus)) { + DSYMPath = FilenameDSYM.str(); + } + } + } + + if (DSYMPath.empty() && !DSYMFile.empty()) { + // If DSYMPath is a .dSYM directory, append the Mach-O file. + if (sys::fs::is_directory(DSYMFile) && + sys::path::extension(DSYMFile) == ".dSYM") { + SmallString<128> ShortName(sys::path::filename(DSYMFile)); + sys::path::replace_extension(ShortName, ""); + SmallString<1024> FullPath(DSYMFile); + sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName); + DSYMPath = FullPath.str(); + } else { + DSYMPath = DSYMFile; + } + } + + if (!DSYMPath.empty()) { + // Load the file. + ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = + MemoryBuffer::getFileOrSTDIN(DSYMPath); + if (std::error_code EC = BufOrErr.getError()) { + reportError(errorCodeToError(EC), DSYMPath); + return nullptr; + } + + // We need to keep the file alive, because we're replacing DbgObj with it. + DSYMBuf = std::move(BufOrErr.get()); + + Expected<std::unique_ptr<Binary>> BinaryOrErr = + createBinary(DSYMBuf.get()->getMemBufferRef()); + if (!BinaryOrErr) { + reportError(BinaryOrErr.takeError(), DSYMPath); + return nullptr; + } + + // We need to keep the Binary alive with the buffer + DSYMBinary = std::move(BinaryOrErr.get()); + if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) { + // this is a Mach-O object file, use it + if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) { + DbgObj = MachDSYM; + } else { + WithColor::error(errs(), "llvm-objdump") + << DSYMPath << " is not a Mach-O file type.\n"; + return nullptr; + } + } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) { + // this is a Universal Binary, find a Mach-O for this architecture + uint32_t CPUType, CPUSubType; + const char *ArchFlag; + if (MachOOF->is64Bit()) { + const MachO::mach_header_64 H_64 = MachOOF->getHeader64(); + CPUType = H_64.cputype; + CPUSubType = H_64.cpusubtype; + } else { + const MachO::mach_header H = MachOOF->getHeader(); + CPUType = H.cputype; + CPUSubType = H.cpusubtype; + } + Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr, + &ArchFlag); + Expected<std::unique_ptr<MachOObjectFile>> MachDSYM = + UB->getMachOObjectForArch(ArchFlag); + if (!MachDSYM) { + reportError(MachDSYM.takeError(), DSYMPath); + return nullptr; + } + + // We need to keep the Binary alive with the buffer + DbgObj = &*MachDSYM.get(); + DSYMBinary = std::move(*MachDSYM); + } else { + WithColor::error(errs(), "llvm-objdump") + << DSYMPath << " is not a Mach-O or Universal file type.\n"; + return nullptr; + } + } + return DbgObj; +} + static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, StringRef DisSegName, StringRef DisSectName) { const char *McpuDefault = nullptr; @@ -7363,90 +7699,15 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, std::unique_ptr<Binary> DSYMBinary; std::unique_ptr<MemoryBuffer> DSYMBuf; if (UseDbg) { - ObjectFile *DbgObj = MachOOF; - - // A separate DSym file path was specified, parse it as a macho file, + // If separate DSym file path was specified, parse it as a macho file, // get the sections and supply it to the section name parsing machinery. - if (!DSYMFile.empty()) { - std::string DSYMPath(DSYMFile); - - // If DSYMPath is a .dSYM directory, append the Mach-O file. - if (llvm::sys::fs::is_directory(DSYMPath) && - llvm::sys::path::extension(DSYMPath) == ".dSYM") { - SmallString<128> ShortName(llvm::sys::path::filename(DSYMPath)); - llvm::sys::path::replace_extension(ShortName, ""); - SmallString<1024> FullPath(DSYMPath); - llvm::sys::path::append(FullPath, "Contents", "Resources", "DWARF", - ShortName); - DSYMPath = std::string(FullPath.str()); - } - - // Load the file. - ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = - MemoryBuffer::getFileOrSTDIN(DSYMPath); - if (std::error_code EC = BufOrErr.getError()) { - reportError(errorCodeToError(EC), DSYMPath); - return; - } - - // We need to keep the file alive, because we're replacing DbgObj with it. - DSYMBuf = std::move(BufOrErr.get()); - - Expected<std::unique_ptr<Binary>> BinaryOrErr = - createBinary(DSYMBuf.get()->getMemBufferRef()); - if (!BinaryOrErr) { - reportError(BinaryOrErr.takeError(), DSYMPath); - return; - } - - // We need to keep the Binary alive with the buffer - DSYMBinary = std::move(BinaryOrErr.get()); - if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) { - // this is a Mach-O object file, use it - if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) { - DbgObj = MachDSYM; - } - else { - WithColor::error(errs(), "llvm-objdump") - << DSYMPath << " is not a Mach-O file type.\n"; - return; - } - } - else if (auto UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())){ - // this is a Universal Binary, find a Mach-O for this architecture - uint32_t CPUType, CPUSubType; - const char *ArchFlag; - if (MachOOF->is64Bit()) { - const MachO::mach_header_64 H_64 = MachOOF->getHeader64(); - CPUType = H_64.cputype; - CPUSubType = H_64.cpusubtype; - } else { - const MachO::mach_header H = MachOOF->getHeader(); - CPUType = H.cputype; - CPUSubType = H.cpusubtype; - } - Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr, - &ArchFlag); - Expected<std::unique_ptr<MachOObjectFile>> MachDSYM = - UB->getMachOObjectForArch(ArchFlag); - if (!MachDSYM) { - reportError(MachDSYM.takeError(), DSYMPath); - return; - } - - // We need to keep the Binary alive with the buffer - DbgObj = &*MachDSYM.get(); - DSYMBinary = std::move(*MachDSYM); - } - else { - WithColor::error(errs(), "llvm-objdump") - << DSYMPath << " is not a Mach-O or Universal file type.\n"; - return; - } + if (const ObjectFile *DbgObj = + getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) { + // Setup the DIContext + diContext = DWARFContext::create(*DbgObj); + } else { + return; } - - // Setup the DIContext - diContext = DWARFContext::create(*DbgObj); } if (FilterSections.empty()) @@ -7655,7 +7916,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, Annotations); if (gotInst) { if (ShowRawInsn || Arch == Triple::arm) { - dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); + dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs()); } formatted_raw_ostream FormattedOS(outs()); StringRef AnnotationsStr = Annotations.str(); @@ -7736,7 +7997,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, } if (ShowRawInsn || Arch == Triple::arm) { outs() << "\t"; - dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); + dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs()); } StringRef AnnotationsStr = Annotations.str(); IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs()); @@ -8445,6 +8706,9 @@ static void PrintMachHeader(uint32_t magic, uint32_t cputype, case MachO::MH_KEXT_BUNDLE: outs() << " KEXTBUNDLE"; break; + case MachO::MH_FILESET: + outs() << " FILESET"; + break; default: outs() << format(" %10u", filetype); break; @@ -8657,6 +8921,12 @@ static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, outs() << " PROTECTED_VERSION_1"; flags &= ~MachO::SG_PROTECTED_VERSION_1; } + if (flags & MachO::SG_READ_ONLY) { + // Apple's otool prints the SG_ prefix for this flag, but not for the + // others. + outs() << " SG_READ_ONLY"; + flags &= ~MachO::SG_READ_ONLY; + } if (flags) outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; else @@ -8754,6 +9024,8 @@ static void PrintSection(const char *sectname, const char *segname, outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; + else if (section_type == MachO::S_INIT_FUNC_OFFSETS) + outs() << " S_INIT_FUNC_OFFSETS\n"; else outs() << format("0x%08" PRIx32, section_type) << "\n"; outs() << "attributes"; @@ -10381,6 +10653,8 @@ static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { return "main-executable"; case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: return "flat-namespace"; + case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP: + return "weak"; default: if (Ordinal > 0) { std::error_code EC = |