static cl::opt<bool> NoLeadingAddr("no-leading-addr",
cl::desc("Print no leading address"));
-static cl::opt<bool>
- PrintImmHex("print-imm-hex",
- cl::desc("Use hex format for immediate values"));
-
cl::opt<bool> llvm::UniversalHeaders("universal-headers",
cl::desc("Print Mach-O universal headers "
"(requires -macho)"));
cl::desc("Print archive headers for Mach-O archives "
"(requires -macho)"));
+cl::opt<bool>
+ ArchiveMemberOffsets("archive-member-offsets",
+ cl::desc("Print the offset to each archive member for "
+ "Mach-O archives (requires -macho and "
+ "-archive-headers)"));
+
cl::opt<bool>
llvm::IndirectSymbols("indirect-symbols",
cl::desc("Print indirect symbol table for Mach-O "
cl::desc("Print the linker optimization hints for "
"Mach-O objects (requires -macho)"));
-cl::list<std::string>
- llvm::DumpSections("section",
- cl::desc("Prints the specified segment,section for "
- "Mach-O objects (requires -macho)"));
-
-cl::opt<bool> llvm::Raw("raw",
- cl::desc("Have -section dump the raw binary contents"));
-
cl::opt<bool>
llvm::InfoPlist("info-plist",
cl::desc("Print the info plist section as strings for "
static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
cl::ZeroOrMore);
+
bool ArchAll = false;
static std::string ThumbTripleName;
struct SymbolSorter {
bool operator()(const SymbolRef &A, const SymbolRef &B) {
- SymbolRef::Type AType, BType;
- A.getType(AType);
- B.getType(BType);
-
- uint64_t AAddr, BAddr;
- if (AType != SymbolRef::ST_Function)
- AAddr = 0;
- else
- A.getAddress(AAddr);
- if (BType != SymbolRef::ST_Function)
- BAddr = 0;
- else
- B.getAddress(BAddr);
+ uint64_t AAddr = (A.getType() != SymbolRef::ST_Function) ? 0 : A.getValue();
+ uint64_t BAddr = (B.getType() != SymbolRef::ST_Function) ? 0 : B.getValue();
return AAddr < BAddr;
}
};
case MachO::DICE_KIND_DATA:
if (Length >= 4) {
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 4));
+ 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<uint8_t>(bytes, 2));
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << Value;
Size = 2;
} else {
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 2));
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[0];
outs() << "\t.byte " << Value;
Size = 1;
break;
case MachO::DICE_KIND_JUMP_TABLE8:
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 1));
+ 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<uint8_t>(bytes, 2));
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << format("%5u", Value & 0xffff)
<< "\t@ KIND_JUMP_TABLE16\n";
case MachO::DICE_KIND_JUMP_TABLE32:
case MachO::DICE_KIND_ABS_JUMP_TABLE32:
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 4));
+ 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)
return Size;
}
-static void getSectionsAndSymbols(const MachO::mach_header Header,
- MachOObjectFile *MachOObj,
+static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
std::vector<SectionRef> &Sections,
std::vector<SymbolRef> &Symbols,
SmallVectorImpl<uint64_t> &FoundFns,
uint64_t &BaseSegmentAddress) {
for (const SymbolRef &Symbol : MachOObj->symbols()) {
- StringRef SymName;
- Symbol.getName(SymName);
- if (!SymName.startswith("ltmp"))
+ ErrorOr<StringRef> SymName = Symbol.getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ if (!SymName->startswith("ltmp"))
Symbols.push_back(Symbol);
}
Sections.push_back(Section);
}
- MachOObjectFile::LoadCommandInfo Command =
- MachOObj->getFirstLoadCommandInfo();
bool BaseSegmentAddressSet = false;
- for (unsigned i = 0;; ++i) {
+ for (const auto &Command : MachOObj->load_commands()) {
if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
// We found a function starts segment, parse the addresses for later
// consumption.
BaseSegmentAddress = SLC.vmaddr;
}
}
-
- if (i == Header.ncmds - 1)
- break;
- else
- Command = MachOObj->getNextLoadCommandInfo(Command);
}
}
if (indirect_symbol < Symtab.nsyms) {
symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
- StringRef SymName;
- Symbol.getName(SymName);
- outs() << SymName;
+ ErrorOr<StringRef> SymName = Symbol.getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ outs() << *SymName;
} else {
outs() << "?";
}
}
static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
- uint32_t LoadCommandCount = O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
}
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = O->getNextLoadCommandInfo(Load);
}
}
}
static void PrintDylibs(MachOObjectFile *O, bool JustId) {
- uint32_t LoadCommandCount = O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ unsigned Index = 0;
+ for (const auto &Load : O->load_commands()) {
if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
(!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
Load.C.cmd == MachO::LC_LOAD_DYLIB ||
outs() << "LC_LOAD_UPWARD_DYLIB ";
else
outs() << "LC_??? ";
- outs() << "command " << I << "\n";
+ outs() << "command " << Index++ << "\n";
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = O->getNextLoadCommandInfo(Load);
}
}
SymbolAddressMap *AddrMap) {
// Create a map of symbol addresses to symbol names.
for (const SymbolRef &Symbol : O->symbols()) {
- SymbolRef::Type ST;
- Symbol.getType(ST);
+ SymbolRef::Type ST = Symbol.getType();
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
- uint64_t Address;
- Symbol.getAddress(Address);
- StringRef SymName;
- Symbol.getName(SymName);
+ uint64_t Address = Symbol.getValue();
+ ErrorOr<StringRef> SymNameOrErr = Symbol.getName();
+ if (std::error_code EC = SymNameOrErr.getError())
+ report_fatal_error(EC.message());
+ StringRef SymName = *SymNameOrErr;
if (!SymName.startswith(".objc"))
(*AddrMap)[Address] = SymName;
}
// Set the size of the literal pointer.
uint32_t lp_size = O->is64Bit() ? 8 : 4;
- // Collect the external relocation symbols for the the literal pointers.
+ // Collect the external relocation symbols for the literal pointers.
std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
for (const RelocationRef &Reloc : Section.relocations()) {
DataRefImpl Rel;
RE = O->getRelocation(Rel);
isExtern = O->getPlainRelocationExternal(RE);
if (isExtern) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
+ uint64_t RelocOffset = Reloc.getOffset();
symbol_iterator RelocSym = Reloc.getSymbol();
Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
}
[&](const std::pair<uint64_t, SymbolRef> &P) { return P.first == i; });
if (Reloc != Relocs.end()) {
symbol_iterator RelocSym = Reloc->second;
- StringRef SymName;
- RelocSym->getName(SymName);
- outs() << "external relocation entry for symbol:" << SymName << "\n";
+ ErrorOr<StringRef> SymName = RelocSym->getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ outs() << "external relocation entry for symbol:" << *SymName << "\n";
continue;
}
if (verbose)
CreateSymbolAddressMap(O, &AddrMap);
- for (unsigned i = 0; i < DumpSections.size(); ++i) {
- StringRef DumpSection = DumpSections[i];
+ for (unsigned i = 0; i < FilterSections.size(); ++i) {
+ StringRef DumpSection = FilterSections[i];
std::pair<StringRef, StringRef> DumpSegSectName;
DumpSegSectName = DumpSection.split(',');
StringRef DumpSegName, DumpSectName;
uint32_t sect_size = BytesStr.size();
uint64_t sect_addr = Section.getAddress();
- if (Raw) {
- outs().write(BytesStr.data(), BytesStr.size());
- continue;
- }
-
outs() << "Contents of (" << SegName << "," << SectName
<< ") section\n";
// UniversalHeaders or ArchiveHeaders.
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
- DylibsUsed || DylibId || ObjcMetaData ||
- (DumpSections.size() != 0 && !Raw)) {
+ DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
outs() << Filename;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
PrintSectionHeaders(MachOOF);
if (SectionContents)
PrintSectionContents(MachOOF);
- if (DumpSections.size() != 0)
+ if (FilterSections.size() != 0)
DumpSectionContents(Filename, MachOOF, !NonVerbose);
if (InfoPlist)
DumpInfoPlistSectionContents(Filename, MachOOF);
}
}
-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";
// 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);
}
outs() << format("%3d/", UID);
unsigned GID = C.getGID();
outs() << format("%-3d ", GID);
- uint64_t Size = C.getRawSize();
- outs() << format("%5" PRId64, Size) << " ";
+ ErrorOr<uint64_t> 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) {
}
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);
}
}
if (Archive *A = dyn_cast<Archive>(&Bin)) {
outs() << "Archive : " << Filename << "\n";
if (ArchiveHeaders)
- printArchiveHeaders(A, true, false);
+ printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
I != E; ++I) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary();
+ if (std::error_code EC = I->getError()) {
+ errs() << "llvm-objdump: '" << Filename << "': " << EC.message()
+ << ".\n";
+ exit(1);
+ }
+ auto &C = I->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
outs() << " (architecture " << ArchitectureName << ")";
outs() << "\n";
if (ArchiveHeaders)
- printArchiveHeaders(A.get(), true, false);
+ printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError()) {
+ errs() << "llvm-objdump: '" << Filename
+ << "': " << EC.message() << ".\n";
+ exit(1);
+ }
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
std::unique_ptr<Archive> &A = *AOrErr;
outs() << "Archive : " << Filename << "\n";
if (ArchiveHeaders)
- printArchiveHeaders(A.get(), true, false);
+ printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError()) {
+ errs() << "llvm-objdump: '" << Filename << "': " << EC.message()
+ << ".\n";
+ exit(1);
+ }
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
outs() << " (architecture " << ArchitectureName << ")";
outs() << "\n";
if (ArchiveHeaders)
- printArchiveHeaders(A.get(), true, false);
+ printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError()) {
+ errs() << "llvm-objdump: '" << Filename << "': " << EC.message()
+ << ".\n";
+ exit(1);
+ }
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
uint64_t adrp_addr;
uint32_t adrp_inst;
BindTable *bindtable;
+ uint32_t depth;
};
// SymbolizerGetOpInfo() is the operand information call back function.
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;
bool r_scattered = false;
uint32_t r_value, pair_r_value, r_type;
for (const RelocationRef &Reloc : info->S.relocations()) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
+ uint64_t RelocOffset = Reloc.getOffset();
if (RelocOffset == sect_offset) {
Rel = Reloc.getRawDataRefImpl();
RE = info->O->getRelocation(Rel);
}
}
if (reloc_found && isExtern) {
- StringRef SymName;
- Symbol.getName(SymName);
- const char *name = SymName.data();
+ ErrorOr<StringRef> SymName = Symbol.getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
// For i386 extern relocation entries the value in the instruction is
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;
bool isExtern = false;
SymbolRef Symbol;
for (const RelocationRef &Reloc : info->S.relocations()) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
+ uint64_t RelocOffset = Reloc.getOffset();
if (RelocOffset == sect_offset) {
Rel = Reloc.getRawDataRefImpl();
RE = info->O->getRelocation(Rel);
// is the offset from the external symbol.
if (info->O->getAnyRelocationPCRel(RE))
op_info->Value -= Pc + Offset + Size;
- StringRef SymName;
- Symbol.getName(SymName);
- const char *name = SymName.data();
+ ErrorOr<StringRef> SymName = Symbol.getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ const char *name = SymName->data();
unsigned Type = info->O->getAnyRelocationType(RE);
if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
DataRefImpl RelNext = Rel;
op_info->SubtractSymbol.Name = name;
symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
Symbol = *RelocSymNext;
- StringRef SymNameNext;
- Symbol.getName(SymNameNext);
- name = SymNameNext.data();
+ ErrorOr<StringRef> SymNameNext = Symbol.getName();
+ if (std::error_code EC = SymNameNext.getError())
+ report_fatal_error(EC.message());
+ name = SymNameNext->data();
}
}
// TODO: add the VariantKinds to op_info->VariantKind for relocation types
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;
auto Reloc =
std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
[&](const RelocationRef &Reloc) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
+ uint64_t RelocOffset = Reloc.getOffset();
return RelocOffset == sect_offset;
});
}
if (isExtern) {
- StringRef SymName;
- Symbol.getName(SymName);
- const char *name = SymName.data();
+ ErrorOr<StringRef> SymName = Symbol.getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
switch (r_type) {
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 =
std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
[&](const RelocationRef &Reloc) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
+ uint64_t RelocOffset = Reloc.getOffset();
return RelocOffset == sect_offset;
});
// NOTE: Scattered relocations don't exist on arm64.
if (!info->O->getPlainRelocationExternal(RE))
return 0;
- StringRef SymName;
- Reloc->getSymbol()->getName(SymName);
- const char *name = SymName.data();
+ ErrorOr<StringRef> SymName = Reloc->getSymbol()->getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
// it returns a pointer to that string. Else it returns nullptr.
static const char *GuessCstringPointer(uint64_t ReferenceValue,
struct DisassembleInfo *info) {
- uint32_t LoadCommandCount = info->O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : info->O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
}
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = info->O->getNextLoadCommandInfo(Load);
}
return nullptr;
}
// symbol name being referenced by the stub or pointer.
static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
struct DisassembleInfo *info) {
- uint32_t LoadCommandCount = info->O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : info->O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
if (indirect_symbol < Symtab.nsyms) {
symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
- StringRef SymName;
- Symbol.getName(SymName);
- const char *name = SymName.data();
+ ErrorOr<StringRef> SymName = Symbol.getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ const char *name = SymName->data();
return name;
}
}
if (indirect_symbol < Symtab.nsyms) {
symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
- StringRef SymName;
- Symbol.getName(SymName);
- const char *name = SymName.data();
+ ErrorOr<StringRef> SymName = Symbol.getName();
+ if (std::error_code EC = SymName.getError())
+ report_fatal_error(EC.message());
+ const char *name = SymName->data();
return name;
}
}
}
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = info->O->getNextLoadCommandInfo(Load);
}
return nullptr;
}
selref = false;
msgref = false;
cfstring = false;
- uint32_t LoadCommandCount = info->O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : info->O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
}
}
// TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = info->O->getNextLoadCommandInfo(Load);
}
return 0;
}
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);
// for the specified section offset in the specified section reference.
// If no relocation information is found and a non-zero ReferenceValue for the
// symbol is passed, look up that address in the info's AddrMap.
-static const char *
-get_symbol_64(uint32_t sect_offset, SectionRef S, DisassembleInfo *info,
- uint64_t &n_value,
- uint64_t ReferenceValue = UnknownAddressOrSize) {
+static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
+ DisassembleInfo *info, uint64_t &n_value,
+ uint64_t ReferenceValue = 0) {
n_value = 0;
if (!info->verbose)
return nullptr;
bool isExtern = false;
SymbolRef Symbol;
for (const RelocationRef &Reloc : S.relocations()) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
+ uint64_t RelocOffset = Reloc.getOffset();
if (RelocOffset == sect_offset) {
Rel = Reloc.getRawDataRefImpl();
RE = info->O->getRelocation(Rel);
// and return its name.
const char *SymbolName = nullptr;
if (reloc_found && isExtern) {
- Symbol.getAddress(n_value);
- if (n_value == UnknownAddressOrSize)
- n_value = 0;
- StringRef name;
- Symbol.getName(name);
- if (!name.empty()) {
- SymbolName = name.data();
+ n_value = Symbol.getValue();
+ ErrorOr<StringRef> NameOrError = Symbol.getName();
+ if (std::error_code EC = NameOrError.getError())
+ report_fatal_error(EC.message());
+ StringRef Name = *NameOrError;
+ if (!Name.empty()) {
+ SymbolName = Name.data();
return SymbolName;
}
}
// We did not find an external relocation entry so look up the ReferenceValue
// as an address of a symbol and if found return that symbol's name.
- if (ReferenceValue != UnknownAddressOrSize)
- SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
+ SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
return SymbolName;
}
}
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) << " ";
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)
}
}
-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;
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);
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;
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);
<< 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) {
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);
}
}
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);
}
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";
struct objc_image_info64 o;
const char *r;
+ if (S == SectionRef())
+ return;
+
StringRef SectName;
S.getName(SectName);
DataRefImpl Ref = S.getRawDataRefImpl();
info.adrp_addr = 0;
info.adrp_inst = 0;
+ info.depth = 0;
const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
if (CL != SectionRef()) {
info.S = CL;
// 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);
}
}
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(RelocOffset);
- 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) {
- Symbol.getAddress(ReferenceValue);
+ // 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();
+ }
}
}
}
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();
// Tell the comment stream that the vector changed underneath it.
CommentsToEmit.clear();
- CommentStream.resync();
}
static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
SmallVector<uint64_t, 8> FoundFns;
uint64_t BaseSegmentAddress;
- getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns,
+ getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
BaseSegmentAddress);
// Sort the symbols by address, just in case they didn't come in that way.
diContext.reset(new DWARFContextInMemory(*DbgObj));
}
- if (DumpSections.size() == 0)
+ if (FilterSections.size() == 0)
outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
bool symbolTableWorked = false;
- // Parse relocations.
- std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
- for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
- 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;
bool DisSymNameFound = false;
for (const SymbolRef &Symbol : MachOOF->symbols()) {
- SymbolRef::Type ST;
- Symbol.getType(ST);
+ SymbolRef::Type ST = Symbol.getType();
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
- uint64_t Address;
- Symbol.getAddress(Address);
- StringRef SymName;
- Symbol.getName(SymName);
+ uint64_t Address = Symbol.getValue();
+ ErrorOr<StringRef> SymNameOrErr = Symbol.getName();
+ if (std::error_code EC = SymNameOrErr.getError())
+ report_fatal_error(EC.message());
+ StringRef SymName = *SymNameOrErr;
AddrMap[Address] = SymName;
if (!DisSymName.empty() && DisSymName == SymName)
DisSymNameFound = true;
// Disassemble symbol by symbol.
for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
- StringRef SymName;
- Symbols[SymIdx].getName(SymName);
+ ErrorOr<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
+ if (std::error_code EC = SymNameOrErr.getError())
+ report_fatal_error(EC.message());
+ StringRef SymName = *SymNameOrErr;
- SymbolRef::Type ST;
- Symbols[SymIdx].getType(ST);
- if (ST != SymbolRef::ST_Function)
+ SymbolRef::Type ST = Symbols[SymIdx].getType();
+ if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
continue;
// Make sure the symbol is defined in this section.
continue;
// Start at the address of the symbol relative to the section's address.
- uint64_t Start = 0;
+ uint64_t Start = Symbols[SymIdx].getValue();
uint64_t SectionAddress = Sections[SectIdx].getAddress();
- Symbols[SymIdx].getAddress(Start);
Start -= SectionAddress;
// Stop disassembling either at the beginning of the next symbol or at
uint64_t NextSym = 0;
uint64_t NextSymIdx = SymIdx + 1;
while (Symbols.size() > NextSymIdx) {
- SymbolRef::Type NextSymType;
- Symbols[NextSymIdx].getType(NextSymType);
+ SymbolRef::Type NextSymType = Symbols[NextSymIdx].getType();
if (NextSymType == SymbolRef::ST_Function) {
containsNextSym =
Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
- Symbols[NextSymIdx].getAddress(NextSym);
+ NextSym = Symbols[NextSymIdx].getValue();
NextSym -= SectionAddress;
break;
}
DebugOut, Annotations);
if (gotInst) {
if (!NoShowRawInsn) {
- DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size));
+ 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);
}
if (!NoShowRawInsn) {
outs() << "\t";
- DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize));
+ dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
}
IP->printInst(&Inst, outs(), "", *STI);
outs() << "\n";
const RelocationRef &Reloc, uint64_t Addr,
StringRef &Name, uint64_t &Addend) {
if (Reloc.getSymbol() != Obj->symbol_end()) {
- Reloc.getSymbol()->getName(Name);
+ ErrorOr<StringRef> NameOrErr = Reloc.getSymbol()->getName();
+ if (std::error_code EC = NameOrErr.getError())
+ report_fatal_error(EC.message());
+ Name = *NameOrErr;
Addend = Addr;
return;
}
auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
- SectionRef RelocSection = Obj->getRelocationSection(RE);
+ SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
uint64_t SectionAddr = RelocSection.getAddress();
// Go back one so that SymbolAddress <= Addr.
--Sym;
- section_iterator SymSection = Obj->section_end();
- Sym->second.getSection(SymSection);
+ section_iterator SymSection = *Sym->second.getSection();
if (RelocSection == *SymSection) {
// There's a valid symbol in the same section before this reference.
- Sym->second.getName(Name);
+ ErrorOr<StringRef> NameOrErr = Sym->second.getName();
+ if (std::error_code EC = NameOrErr.getError())
+ report_fatal_error(EC.message());
+ Name = *NameOrErr;
Addend = Addr - Sym->first;
return;
}
StringRef Name;
uint64_t Addend;
- if (!Reloc.getObjectFile())
+ if (!Reloc.getObject())
return;
findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
// Next we need to look at the relocations to find out what objects are
// actually being referred to.
for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
- uint64_t RelocAddress;
- Reloc.getOffset(RelocAddress);
+ uint64_t RelocAddress = Reloc.getOffset();
uint32_t EntryIdx = RelocAddress / EntrySize;
uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
<< format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
// 4. The personality function, if present.
- if (Entry.PersonalityReloc.getObjectFile()) {
+ if (Entry.PersonalityReloc.getObject()) {
outs() << " personality function: "
<< format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
}
// 5. This entry's language-specific data area.
- if (Entry.LSDAReloc.getObjectFile()) {
+ if (Entry.LSDAReloc.getObject()) {
outs() << " LSDA: " << format("0x%" PRIx64,
Entry.LSDAAddr) << ' ';
printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
for (const SymbolRef &SymRef : Obj->symbols()) {
// Discard any undefined or absolute symbols. They're not going to take part
// in the convenience lookup for unwind info and just take up resources.
- section_iterator Section = Obj->section_end();
- SymRef.getSection(Section);
+ section_iterator Section = *SymRef.getSection();
if (Section == Obj->section_end())
continue;
- uint64_t Addr;
- SymRef.getAddress(Addr);
+ uint64_t Addr = SymRef.getValue();
Symbols.insert(std::make_pair(Addr, SymRef));
}
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";
}
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";
}
outs() << "\n";
}
-static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds,
- uint32_t filetype, uint32_t cputype,
- bool verbose) {
- if (ncmds == 0)
- return;
+static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
+ uint32_t cputype, bool verbose) {
StringRef Buf = Obj->getData();
- MachOObjectFile::LoadCommandInfo Command = Obj->getFirstLoadCommandInfo();
- for (unsigned i = 0;; ++i) {
- outs() << "Load command " << i << "\n";
+ unsigned Index = 0;
+ for (const auto &Command : Obj->load_commands()) {
+ outs() << "Load command " << Index++ << "\n";
if (Command.C.cmd == MachO::LC_SEGMENT) {
MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
const char *sg_segname = SLC.segname;
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) {
// TODO: get and print the raw bytes of the load command.
}
// TODO: print all the other kinds of load commands.
- if (i == ncmds - 1)
- break;
- else
- Command = Obj->getNextLoadCommandInfo(Command);
}
}
-static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds,
+static void getAndPrintMachHeader(const MachOObjectFile *Obj,
uint32_t &filetype, uint32_t &cputype,
bool verbose) {
if (Obj->is64Bit()) {
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);
- ncmds = H_64.ncmds;
filetype = H_64.filetype;
cputype = H_64.cputype;
} else {
H = Obj->getHeader();
PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
H.sizeofcmds, H.flags, verbose);
- ncmds = H.ncmds;
filetype = H.filetype;
cputype = H.cputype;
}
void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
- uint32_t ncmds = 0;
uint32_t filetype = 0;
uint32_t cputype = 0;
- getAndPrintMachHeader(file, ncmds, filetype, cputype, !NonVerbose);
- PrintLoadCommands(file, ncmds, filetype, cputype, !NonVerbose);
+ getAndPrintMachHeader(file, filetype, cputype, !NonVerbose);
+ PrintLoadCommands(file, filetype, cputype, !NonVerbose);
}
//===----------------------------------------------------------------------===//
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 CurSegAddress;
for (const SectionRef &Section : Obj->sections()) {
SectionInfo Info;
- if (error(Section.getName(Info.SectionName)))
- return;
+ error(Section.getName(Info.SectionName));
Info.Address = Section.getAddress();
Info.Size = Section.getSize();
Info.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) {
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();