void MachOLoader::loadDylibs(const MachO& mach, bool nobind, bool bindLazy) { for (std::string dylib : mach.dylibs()) { // __darwin_dlopen checks if already loaded // automatically adds a reference if so int flags = DARWIN_RTLD_GLOBAL; if (nobind) flags |= __DARLING_RTLD_NOBIND; if (bindLazy) flags |= DARWIN_RTLD_LAZY; else flags |= DARWIN_RTLD_NOW; if (!Darling::DlopenWithContext(dylib.c_str(), flags, m_rpathContext)) { LOG << "Failed to dlopen " << dylib << ", throwing an exception\n"; std::stringstream ss; ss << "Cannot load " << dylib << ": " << __darwin_dlerror(); throw std::runtime_error(ss.str()); } } }
void printBinInfo(const char* path, const char* arch, const char* opt) { MachO* macho = MachO::readFile(path, arch, true); if (!macho) throw std::runtime_error("Load failed"); OpMode opmode = getOpMode(opt); std::cout << "Platform: " << macho->platform() << std::endl; switch (opmode) { case ModeDylibs: { std::cout << "Dylibs:\n"; for (const char* name : macho->dylibs()) { std::cout << "\t" << name << std::endl; } break; } case ModeSymbols: { std::cout << "Symbols:\n"; for (const MachO::Symbol& s : macho->symbols()) { if (!s.addr) continue; std::cout << '\t' << s.name << " at " << "[0x" << std::hex << std::setfill('0'); if (macho->is64()) std::cout << std::setw(16); else std::cout << std::setw(8); std::cout << s.addr << std::setw(0) << std::dec << ']' << std::endl; } break; } case ModeExports: { std::cout << "Exports:\n"; for (const MachO::Export* e : macho->exports()) { std::cout << '\t' << e->name << " at " << "[0x" << std::hex << std::setfill('0'); if (macho->is64()) std::cout << std::setw(16); else std::cout << std::setw(8); std::cout << e->addr << std::setw(0) << "] (flag: " << e->flag << ")" << std::dec << std::endl; } break; } case ModeBinds: { std::cout << "Binds:\n"; for (const MachO::Bind* b : macho->binds()) { std::cout << '\t' << b->name << " at " << "[0x" << std::hex << std::setfill('0'); if (macho->is64()) std::cout << std::setw(16); else std::cout << std::setw(8); std::cout << b->vmaddr << std::setw(0) << "] "; if (!b->is_classic) std::cout << "(addend: " << b->addend; else std::cout << "(value: " << b->value; std::cout << ", type: " << int(b->type) << ", ordinal: " << int(b->ordinal) << ")"; if (b->is_weak) std::cout << 'W'; if (b->is_classic) std::cout << 'C'; if (b->is_lazy) std::cout << 'L'; std::cout << std::dec << std::endl; } break; } case ModeSegments: { std::cout << "Segments:\n" << std::hex; printSegments(macho->segments64()); printSegments(macho->segments()); break; } case ModeRebases: { std::cout << "Rebases:\n"; for (MachO::Rebase* r : macho->rebases()) { std::cout << "\t at [0x" << std::hex << std::setfill('0'); if (macho->is64()) std::cout << std::setw(16); else std::cout << std::setw(8); std::cout << r->vmaddr << std::dec << std::setw(0) << "]\n"; } break; } case ModeRelocations: { std::cout << "External relocations:\n"; for (MachO::Relocation* r : macho->relocations()) { std::cout << '\t' << r->name << " at " << "[0x" << std::hex << std::setfill('0'); if (macho->is64()) std::cout << std::setw(16); else std::cout << std::setw(8); std::cout << r->addr << std::setw(0) << "] "; if (r->pcrel) std::cout << "PC-REL"; std::cout << std::endl; } break; } } delete macho; }