diff options
Diffstat (limited to 'tools/llvm-objdump/MachODump.cpp')
-rw-r--r-- | tools/llvm-objdump/MachODump.cpp | 532 |
1 files changed, 319 insertions, 213 deletions
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 563084856f6f8..9e02951a4a93f 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -68,9 +68,6 @@ static cl::opt<std::string> DSYMFile("dsym", static cl::opt<bool> FullLeadingAddr("full-leading-addr", cl::desc("Print full leading address")); -static cl::opt<bool> NoLeadingAddr("no-leading-addr", - cl::desc("Print no leading address")); - static cl::opt<bool> NoLeadingHeaders("no-leading-headers", cl::desc("Print no leading headers")); @@ -1142,7 +1139,7 @@ static void DumpInfoPlistSectionContents(StringRef Filename, StringRef BytesStr; Section.getContents(BytesStr); const char *sect = reinterpret_cast<const char *>(BytesStr.data()); - outs() << sect; + outs() << format("%.*s", BytesStr.size(), sect) << "\n"; return; } } @@ -1566,8 +1563,13 @@ void llvm::ParseInputMachO(StringRef Filename) { // Attempt to open the binary. Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); - if (!BinaryOrErr) - report_error(Filename, BinaryOrErr.takeError()); + if (!BinaryOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) + report_error(Filename, std::move(E)); + else + outs() << Filename << ": is not an object file\n"; + return; + } Binary &Bin = *BinaryOrErr.get().getBinary(); if (Archive *A = dyn_cast<Archive>(&Bin)) { @@ -5269,42 +5271,70 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { SectionRef CL = get_section(O, "__OBJC2", "__class_list"); if (CL == SectionRef()) CL = get_section(O, "__DATA", "__objc_classlist"); + if (CL == SectionRef()) + CL = get_section(O, "__DATA_CONST", "__objc_classlist"); + if (CL == SectionRef()) + CL = get_section(O, "__DATA_DIRTY", "__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"); + if (CR == SectionRef()) + CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); + if (CR == SectionRef()) + CR = get_section(O, "__DATA_DIRTY", "__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"); + if (SR == SectionRef()) + SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); + if (SR == SectionRef()) + SR = get_section(O, "__DATA_DIRTY", "__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"); + if (CA == SectionRef()) + CA = get_section(O, "__DATA_CONST", "__objc_catlist"); + if (CA == SectionRef()) + CA = get_section(O, "__DATA_DIRTY", "__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"); + if (PL == SectionRef()) + PL = get_section(O, "__DATA_CONST", "__objc_protolist"); + if (PL == SectionRef()) + PL = get_section(O, "__DATA_DIRTY", "__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"); + if (MR == SectionRef()) + MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); + if (MR == SectionRef()) + MR = get_section(O, "__DATA_DIRTY", "__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"); + if (II == SectionRef()) + II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); + if (II == SectionRef()) + II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); info.S = II; print_image_info64(II, &info); } @@ -5335,75 +5365,75 @@ static void printObjc2_32bit_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_32("class", CL, O, &info, print_class32_t); - } else { - const SectionRef CL = get_section(O, "__DATA", "__objc_classlist"); - info.S = CL; - walk_pointer_list_32("class", CL, O, &info, print_class32_t); - } + SectionRef CL = get_section(O, "__OBJC2", "__class_list"); + if (CL == SectionRef()) + CL = get_section(O, "__DATA", "__objc_classlist"); + if (CL == SectionRef()) + CL = get_section(O, "__DATA_CONST", "__objc_classlist"); + if (CL == SectionRef()) + CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); + info.S = CL; + walk_pointer_list_32("class", CL, O, &info, print_class32_t); - const SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); - if (CR != SectionRef()) { - info.S = CR; - walk_pointer_list_32("class refs", CR, O, &info, nullptr); - } else { - const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs"); - info.S = CR; - walk_pointer_list_32("class refs", CR, O, &info, nullptr); - } + SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); + if (CR == SectionRef()) + CR = get_section(O, "__DATA", "__objc_classrefs"); + if (CR == SectionRef()) + CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); + if (CR == SectionRef()) + CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); + info.S = CR; + walk_pointer_list_32("class refs", CR, O, &info, nullptr); - const SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); - if (SR != SectionRef()) { - info.S = SR; - walk_pointer_list_32("super refs", SR, O, &info, nullptr); - } else { - const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs"); - info.S = SR; - walk_pointer_list_32("super refs", SR, O, &info, nullptr); - } + SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); + if (SR == SectionRef()) + SR = get_section(O, "__DATA", "__objc_superrefs"); + if (SR == SectionRef()) + SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); + if (SR == SectionRef()) + SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); + info.S = SR; + walk_pointer_list_32("super refs", SR, O, &info, nullptr); - const SectionRef CA = get_section(O, "__OBJC2", "__category_list"); - if (CA != SectionRef()) { - info.S = CA; - walk_pointer_list_32("category", CA, O, &info, print_category32_t); - } else { - const SectionRef CA = get_section(O, "__DATA", "__objc_catlist"); - info.S = CA; - walk_pointer_list_32("category", CA, O, &info, print_category32_t); - } + SectionRef CA = get_section(O, "__OBJC2", "__category_list"); + if (CA == SectionRef()) + CA = get_section(O, "__DATA", "__objc_catlist"); + if (CA == SectionRef()) + CA = get_section(O, "__DATA_CONST", "__objc_catlist"); + if (CA == SectionRef()) + CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); + info.S = CA; + walk_pointer_list_32("category", CA, O, &info, print_category32_t); - const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); - if (PL != SectionRef()) { - info.S = PL; - walk_pointer_list_32("protocol", PL, O, &info, nullptr); - } else { - const SectionRef PL = get_section(O, "__DATA", "__objc_protolist"); - info.S = PL; - walk_pointer_list_32("protocol", PL, O, &info, nullptr); - } + SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); + if (PL == SectionRef()) + PL = get_section(O, "__DATA", "__objc_protolist"); + if (PL == SectionRef()) + PL = get_section(O, "__DATA_CONST", "__objc_protolist"); + if (PL == SectionRef()) + PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); + info.S = PL; + walk_pointer_list_32("protocol", PL, O, &info, nullptr); - const SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); - if (MR != SectionRef()) { - info.S = MR; - print_message_refs32(MR, &info); - } else { - const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs"); - info.S = MR; - print_message_refs32(MR, &info); - } + SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); + if (MR == SectionRef()) + MR = get_section(O, "__DATA", "__objc_msgrefs"); + if (MR == SectionRef()) + MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); + if (MR == SectionRef()) + MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); + info.S = MR; + print_message_refs32(MR, &info); - const SectionRef II = get_section(O, "__OBJC2", "__image_info"); - if (II != SectionRef()) { - info.S = II; - print_image_info32(II, &info); - } else { - const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo"); - info.S = II; - print_image_info32(II, &info); - } + SectionRef II = get_section(O, "__OBJC2", "__image_info"); + if (II == SectionRef()) + II = get_section(O, "__DATA", "__objc_imageinfo"); + if (II == SectionRef()) + II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); + if (II == SectionRef()) + II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); + info.S = II; + print_image_info32(II, &info); } static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { @@ -6597,6 +6627,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, if (Bytes.size() == 0) return; + // If the section has symbols but no symbol at the start of the section + // these are used to make sure the bytes before the first symbol are + // disassembled. + bool FirstSymbol = true; + bool FirstSymbolAtSectionStart = true; + // Disassemble symbol by symbol. for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName(); @@ -6686,11 +6722,29 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, // (i.e. we're not targeting M-class) and the function is Thumb. bool UseThumbTarget = IsThumb && ThumbTarget; - outs() << SymName << ":\n"; + // If we are not specifying a symbol to start disassembly with and this + // is the first symbol in the section but not at the start of the section + // then move the disassembly index to the start of the section and + // don't print the symbol name just yet. This is so the bytes before the + // first symbol are disassembled. + uint64_t SymbolStart = Start; + if (DisSymName.empty() && FirstSymbol && Start != 0) { + FirstSymbolAtSectionStart = false; + Start = 0; + } + else + outs() << SymName << ":\n"; + DILineInfo lastLine; for (uint64_t Index = Start; Index < End; Index += Size) { MCInst Inst; + // If this is the first symbol in the section and it was not at the + // start of the section, see if we are at its Index now and if so print + // the symbol name. + if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) + outs() << SymName << ":\n"; + uint64_t PC = SectAddress + Index; if (!NoLeadingAddr) { if (FullLeadingAddr) { @@ -6783,6 +6837,9 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, } } } + // Now that we are done disassembled the first symbol set the bool that + // were doing this to false. + FirstSymbol = false; } if (!symbolTableWorked) { // Reading the symbol table didn't work, disassemble the whole section. @@ -6793,8 +6850,10 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, MCInst Inst; uint64_t PC = SectAddress + Index; + SmallVector<char, 64> AnnotationsBytes; + raw_svector_ostream Annotations(AnnotationsBytes); if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, - DebugOut, nulls())) { + DebugOut, Annotations)) { if (!NoLeadingAddr) { if (FullLeadingAddr) { if (MachOOF->is64Bit()) @@ -6809,7 +6868,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, outs() << "\t"; dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); } - IP->printInst(&Inst, outs(), "", *STI); + StringRef AnnotationsStr = Annotations.str(); + IP->printInst(&Inst, outs(), AnnotationsStr, *STI); outs() << "\n"; } else { unsigned int Arch = MachOOF->getArch(); @@ -8169,6 +8229,51 @@ static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { outs() << "\n"; } +static void PrintNoteLoadCommand(MachO::note_command Nt) { + outs() << " cmd LC_NOTE\n"; + outs() << " cmdsize " << Nt.cmdsize; + if (Nt.cmdsize != sizeof(struct MachO::note_command)) + outs() << " Incorrect size\n"; + else + outs() << "\n"; + const char *d = Nt.data_owner; + outs() << "data_owner " << format("%.16s\n", d); + outs() << " offset " << Nt.offset << "\n"; + outs() << " size " << Nt.size << "\n"; +} + +static void PrintBuildToolVersion(MachO::build_tool_version bv) { + outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; + outs() << " version " << MachOObjectFile::getVersionString(bv.version) + << "\n"; +} + +static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, + MachO::build_version_command bd) { + outs() << " cmd LC_BUILD_VERSION\n"; + outs() << " cmdsize " << bd.cmdsize; + if (bd.cmdsize != + sizeof(struct MachO::build_version_command) + + bd.ntools * sizeof(struct MachO::build_tool_version)) + outs() << " Incorrect size\n"; + else + outs() << "\n"; + outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) + << "\n"; + if (bd.sdk) + outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) + << "\n"; + else + outs() << " sdk n/a\n"; + outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) + << "\n"; + outs() << " ntools " << bd.ntools << "\n"; + for (unsigned i = 0; i < bd.ntools; ++i) { + MachO::build_tool_version bv = obj->getBuildToolVersion(i); + PrintBuildToolVersion(bv); + } +} + static void PrintSourceVersionCommand(MachO::source_version_command sd) { outs() << " cmd LC_SOURCE_VERSION\n"; outs() << " cmdsize " << sd.cmdsize; @@ -8374,6 +8479,25 @@ static void PrintRoutinesCommand64(MachO::routines_command_64 r) { outs() << " reserved6 " << r.reserved6 << "\n"; } +static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { + outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); + outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); + outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); + outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; + outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); + outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); + outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); + outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; + outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); + outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); + outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); + outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; + outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); + outs() << " es " << format("0x%08" PRIx32, cpu32.es); + outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); + outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; +} + static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); @@ -8611,7 +8735,85 @@ static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, const char *begin = Ptr + sizeof(struct MachO::thread_command); const char *end = Ptr + t.cmdsize; uint32_t flavor, count, left; - if (cputype == MachO::CPU_TYPE_X86_64) { + if (cputype == MachO::CPU_TYPE_I386) { + while (begin < end) { + if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { + memcpy((char *)&flavor, begin, sizeof(uint32_t)); + begin += sizeof(uint32_t); + } else { + flavor = 0; + begin = end; + } + if (isLittleEndian != sys::IsLittleEndianHost) + sys::swapByteOrder(flavor); + if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { + memcpy((char *)&count, begin, sizeof(uint32_t)); + begin += sizeof(uint32_t); + } else { + count = 0; + begin = end; + } + if (isLittleEndian != sys::IsLittleEndianHost) + sys::swapByteOrder(count); + if (flavor == MachO::x86_THREAD_STATE32) { + outs() << " flavor i386_THREAD_STATE\n"; + if (count == MachO::x86_THREAD_STATE32_COUNT) + outs() << " count i386_THREAD_STATE_COUNT\n"; + else + outs() << " count " << count + << " (not x86_THREAD_STATE32_COUNT)\n"; + MachO::x86_thread_state32_t cpu32; + left = end - begin; + if (left >= sizeof(MachO::x86_thread_state32_t)) { + memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); + begin += sizeof(MachO::x86_thread_state32_t); + } else { + memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); + memcpy(&cpu32, begin, left); + begin += left; + } + if (isLittleEndian != sys::IsLittleEndianHost) + swapStruct(cpu32); + Print_x86_thread_state32_t(cpu32); + } else if (flavor == MachO::x86_THREAD_STATE) { + outs() << " flavor x86_THREAD_STATE\n"; + if (count == MachO::x86_THREAD_STATE_COUNT) + outs() << " count x86_THREAD_STATE_COUNT\n"; + else + outs() << " count " << count + << " (not x86_THREAD_STATE_COUNT)\n"; + struct MachO::x86_thread_state_t ts; + left = end - begin; + if (left >= sizeof(MachO::x86_thread_state_t)) { + memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); + begin += sizeof(MachO::x86_thread_state_t); + } else { + memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); + memcpy(&ts, begin, left); + begin += left; + } + if (isLittleEndian != sys::IsLittleEndianHost) + swapStruct(ts); + if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { + outs() << "\t tsh.flavor x86_THREAD_STATE32 "; + if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) + outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; + else + outs() << "tsh.count " << ts.tsh.count + << " (not x86_THREAD_STATE32_COUNT\n"; + Print_x86_thread_state32_t(ts.uts.ts32); + } else { + outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " + << ts.tsh.count << "\n"; + } + } else { + outs() << " flavor " << flavor << " (unknown)\n"; + outs() << " count " << count << "\n"; + outs() << " state (unknown)\n"; + begin += count * sizeof(uint32_t); + } + } + } else if (cputype == MachO::CPU_TYPE_X86_64) { while (begin < end) { if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { memcpy((char *)&flavor, begin, sizeof(uint32_t)); @@ -9014,6 +9216,13 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 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_NOTE) { + MachO::note_command Nt = Obj->getNoteLoadCommand(Command); + PrintNoteLoadCommand(Nt); + } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { + MachO::build_version_command Bv = + Obj->getBuildVersionLoadCommand(Command); + PrintBuildVersionLoadCommand(Obj, Bv); } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); PrintSourceVersionCommand(Sd); @@ -9182,117 +9391,21 @@ void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { // rebase table dumping //===----------------------------------------------------------------------===// -namespace { -class SegInfo { -public: - SegInfo(const object::MachOObjectFile *Obj); - - 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 { - uint64_t Address; - uint64_t Size; - StringRef SectionName; - StringRef SegmentName; - uint64_t OffsetInSegment; - uint64_t SegmentStartAddress; - uint32_t SegmentIndex; - }; - const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset); - SmallVector<SectionInfo, 32> Sections; -}; -} - -SegInfo::SegInfo(const object::MachOObjectFile *Obj) { - // Build table of sections so segIndex/offset pairs can be translated. - uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0; - StringRef CurSegName; - uint64_t CurSegAddress; - for (const SectionRef &Section : Obj->sections()) { - SectionInfo Info; - error(Section.getName(Info.SectionName)); - Info.Address = Section.getAddress(); - Info.Size = Section.getSize(); - Info.SegmentName = - Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl()); - if (!Info.SegmentName.equals(CurSegName)) { - ++CurSegIndex; - CurSegName = Info.SegmentName; - CurSegAddress = Info.Address; - } - Info.SegmentIndex = CurSegIndex - 1; - Info.OffsetInSegment = Info.Address - CurSegAddress; - Info.SegmentStartAddress = CurSegAddress; - Sections.push_back(Info); - } -} - -StringRef SegInfo::segmentName(uint32_t SegIndex) { - for (const SectionInfo &SI : Sections) { - if (SI.SegmentIndex == SegIndex) - return SI.SegmentName; - } - 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) { - if (SI.SegmentIndex != SegIndex) - continue; - if (SI.OffsetInSegment > OffsetInSeg) - continue; - if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size)) - continue; - return SI; - } - llvm_unreachable("segIndex and offset not in any section"); -} - -StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) { - return findSection(SegIndex, OffsetInSeg).SectionName; -} - -uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) { - const SectionInfo &SI = findSection(SegIndex, OffsetInSeg); - return SI.SegmentStartAddress + OffsetInSeg; -} - -void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) { - // Build table of sections so names can used in final output. - SegInfo sectionTable(Obj); - +void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) { outs() << "segment section address type\n"; - for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) { - uint32_t SegIndex = Entry.segmentIndex(); - uint64_t OffsetInSeg = Entry.segmentOffset(); - StringRef SegmentName = sectionTable.segmentName(SegIndex); - StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); - uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); + Error Err = Error::success(); + for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { + StringRef SegmentName = Entry.segmentName(); + StringRef SectionName = Entry.sectionName(); + uint64_t Address = Entry.address(); // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", SegmentName.str().c_str(), SectionName.str().c_str(), Address, Entry.typeName().str().c_str()); } + if (Err) + report_error(Obj->getFileName(), std::move(Err)); } static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { @@ -9320,18 +9433,15 @@ static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { // bind table dumping //===----------------------------------------------------------------------===// -void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) { +void llvm::printMachOBindTable(object::MachOObjectFile *Obj) { // Build table of sections so names can used in final output. - SegInfo sectionTable(Obj); - outs() << "segment section address type " "addend dylib symbol\n"; - for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { - uint32_t SegIndex = Entry.segmentIndex(); - uint64_t OffsetInSeg = Entry.segmentOffset(); - StringRef SegmentName = sectionTable.segmentName(SegIndex); - StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); - uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) { + StringRef SegmentName = Entry.segmentName(); + StringRef SectionName = Entry.sectionName(); + uint64_t Address = Entry.address(); // Table lines look like: // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard @@ -9346,24 +9456,22 @@ void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) { << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " << Entry.symbolName() << Attr << "\n"; } + if (Err) + report_error(Obj->getFileName(), std::move(Err)); } //===----------------------------------------------------------------------===// // lazy bind table dumping //===----------------------------------------------------------------------===// -void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) { - // Build table of sections so names can used in final output. - SegInfo sectionTable(Obj); - +void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) { outs() << "segment section address " "dylib symbol\n"; - for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) { - uint32_t SegIndex = Entry.segmentIndex(); - uint64_t OffsetInSeg = Entry.segmentOffset(); - StringRef SegmentName = sectionTable.segmentName(SegIndex); - StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); - uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { + StringRef SegmentName = Entry.segmentName(); + StringRef SectionName = Entry.sectionName(); + uint64_t Address = Entry.address(); // Table lines look like: // __DATA __got 0x00012010 libSystem ___stack_chk_guard @@ -9373,30 +9481,28 @@ void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) { << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " << Entry.symbolName() << "\n"; } + if (Err) + report_error(Obj->getFileName(), std::move(Err)); } //===----------------------------------------------------------------------===// // weak bind table dumping //===----------------------------------------------------------------------===// -void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { - // Build table of sections so names can used in final output. - SegInfo sectionTable(Obj); - +void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) { outs() << "segment section address " "type addend symbol\n"; - for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) { + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { // Strong symbols don't have a location to update. if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { outs() << " strong " << Entry.symbolName() << "\n"; continue; } - uint32_t SegIndex = Entry.segmentIndex(); - uint64_t OffsetInSeg = Entry.segmentOffset(); - StringRef SegmentName = sectionTable.segmentName(SegIndex); - StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); - uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); + StringRef SegmentName = Entry.segmentName(); + StringRef SectionName = Entry.sectionName(); + uint64_t Address = Entry.address(); // Table lines look like: // __DATA __data 0x00001000 pointer 0 _foo @@ -9407,6 +9513,8 @@ void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() << "\n"; } + if (Err) + report_error(Obj->getFileName(), std::move(Err)); } // get_dyld_bind_info_symbolname() is used for disassembly and passed an @@ -9417,17 +9525,15 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, struct DisassembleInfo *info) { if (info->bindtable == nullptr) { info->bindtable = llvm::make_unique<SymbolAddressMap>(); - SegInfo sectionTable(info->O); - 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); + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) { + uint64_t Address = Entry.address(); StringRef name = Entry.symbolName(); if (!name.empty()) (*info->bindtable)[Address] = name; } + if (Err) + report_error(info->O->getFileName(), std::move(Err)); } auto name = info->bindtable->lookup(ReferenceValue); return !name.empty() ? name.data() : nullptr; |