[llvm-objdump] for mach-o add -bind, -lazy-bind, and -weak-bind options

This finishes the ability of llvm-objdump to print out all information from
the LC_DYLD_INFO load command.

The -bind option prints out symbolic references that dyld must resolve 
immediately.

The -lazy-bind option prints out symbolc reference that are lazily resolved on 
first use.

The -weak-bind option prints out information about symbols which dyld must
try to coalesce across images.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217853 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nick Kledzik
2014-09-16 01:41:51 +00:00
parent 2e363ece75
commit 367cf70f27
11 changed files with 544 additions and 3 deletions

View File

@@ -2178,7 +2178,7 @@ private:
SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
// Build table of sections so segIndex/offset pairs can be translated.
uint32_t CurSegIndex = 0;
uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
StringRef CurSegName;
uint64_t CurSegAddress;
for (const SectionRef &Section : Obj->sections()) {
@@ -2253,3 +2253,118 @@ void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) {
Entry.typeName().str().c_str());
}
}
static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
StringRef DylibName;
switch (Ordinal) {
case MachO::BIND_SPECIAL_DYLIB_SELF:
return "this-image";
case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
return "main-executable";
case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
return "flat-namespace";
default:
Obj->getLibraryShortNameByIndex(Ordinal-1, DylibName);
return DylibName;
}
}
//===----------------------------------------------------------------------===//
// bind table dumping
//===----------------------------------------------------------------------===//
void llvm::printMachOBindTable(const 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);
// Table lines look like:
// __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard
outs() << format("%-8s %-18s 0x%08" PRIX64 " %-8s %-8" PRId64 " %-20s",
SegmentName.str().c_str(),
SectionName.str().c_str(),
Address,
Entry.typeName().str().c_str(),
Entry.addend(),
ordinalName(Obj, Entry.ordinal()))
<< Entry.symbolName();
if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
outs() << " (weak_import)\n";
else
outs() << "\n";
}
}
//===----------------------------------------------------------------------===//
// 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);
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);
// Table lines look like:
// __DATA __got 0x00012010 libSystem ___stack_chk_guard
outs() << format("%-8s %-18s 0x%08" PRIX64 " %-20s",
SegmentName.str().c_str(),
SectionName.str().c_str(),
Address,
ordinalName(Obj, Entry.ordinal()))
<< Entry.symbolName() << "\n";
}
}
//===----------------------------------------------------------------------===//
// 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);
outs() << "segment section address "
"type addend symbol\n";
for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) {
// 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);
// Table lines look like:
// __DATA __data 0x00001000 pointer 0 _foo
outs() << format("%-8s %-18s 0x%08" PRIX64 " %-8s %-8" PRId64 " ",
SegmentName.str().c_str(),
SectionName.str().c_str(),
Address,
Entry.typeName().str().c_str(),
Entry.addend())
<< Entry.symbolName() << "\n";
}
}

View File

@@ -84,6 +84,15 @@ ExportsTrie("exports-trie", cl::desc("Display mach-o exported symbols"));
static cl::opt<bool>
Rebase("rebase", cl::desc("Display mach-o rebasing info"));
static cl::opt<bool>
Bind("bind", cl::desc("Display mach-o binding info"));
static cl::opt<bool>
LazyBind("lazy-bind", cl::desc("Display mach-o lazy binding info"));
static cl::opt<bool>
WeakBind("weak-bind", cl::desc("Display mach-o weak binding info"));
static cl::opt<bool>
MachOOpt("macho", cl::desc("Use MachO specific object file parser"));
static cl::alias
@@ -736,6 +745,38 @@ static void printRebaseTable(const ObjectFile *o) {
}
}
static void printBindTable(const ObjectFile *o) {
outs() << "Bind table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachOBindTable(MachO);
else {
errs() << "This operation is only currently supported "
"for Mach-O executable files.\n";
return;
}
}
static void printLazyBindTable(const ObjectFile *o) {
outs() << "Lazy bind table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachOLazyBindTable(MachO);
else {
errs() << "This operation is only currently supported "
"for Mach-O executable files.\n";
return;
}
}
static void printWeakBindTable(const ObjectFile *o) {
outs() << "Weak bind table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachOWeakBindTable(MachO);
else {
errs() << "This operation is only currently supported "
"for Mach-O executable files.\n";
return;
}
}
static void printPrivateFileHeader(const ObjectFile *o) {
if (o->isELF()) {
@@ -770,6 +811,12 @@ static void DumpObject(const ObjectFile *o) {
printExportsTrie(o);
if (Rebase)
printRebaseTable(o);
if (Bind)
printBindTable(o);
if (LazyBind)
printLazyBindTable(o);
if (WeakBind)
printWeakBindTable(o);
}
/// @brief Dump each object file in \a a;
@@ -853,7 +900,10 @@ int main(int argc, char **argv) {
&& !UnwindInfo
&& !PrivateHeaders
&& !ExportsTrie
&& !Rebase) {
&& !Rebase
&& !Bind
&& !LazyBind
&& !WeakBind) {
cl::PrintHelpMessage();
return 2;
}

View File

@@ -37,6 +37,9 @@ void printCOFFUnwindInfo(const object::COFFObjectFile* o);
void printMachOUnwindInfo(const object::MachOObjectFile* o);
void printMachOExportsTrie(const object::MachOObjectFile* o);
void printMachORebaseTable(const object::MachOObjectFile* o);
void printMachOBindTable(const object::MachOObjectFile* o);
void printMachOLazyBindTable(const object::MachOObjectFile* o);
void printMachOWeakBindTable(const object::MachOObjectFile* o);
void printELFFileHeader(const object::ObjectFile *o);
void printCOFFFileHeader(const object::ObjectFile *o);
void printMachOFileHeader(const object::ObjectFile *o);