summaryrefslogtreecommitdiff
path: root/tools/llvm-objdump/MachODump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-objdump/MachODump.cpp')
-rw-r--r--tools/llvm-objdump/MachODump.cpp532
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;