我想迭代所有加载的共享库并获取它们的基地址和文件名。这基本上是Linux上的dl_iterate_phdr
。
但我想为Mac做同样的事情。
答案 0 :(得分:3)
刚刚完成:
输入是指向某些静态内容(例如函数)的任何指针,目标是查找库及其部分。
我在ptr_is_in_exe
函数中实现了此here:
static bool
ptr_is_in_exe(const void *ptr, const struct mach_header *& header, intptr_t& offset, uintptr_t& vmaddr, std::string& image_name)
{
uint32_t i, count = _dyld_image_count();
for (i = 0; i < count; i++) {
header = _dyld_get_image_header(i);
offset = _dyld_get_image_vmaddr_slide(i);
uint32_t j = 0;
struct load_command* cmd = (struct load_command*)((char *)header + sizeof(struct mach_header));
if(header->magic == MH_MAGIC_64)
cmd = (struct load_command*)((char *)header + sizeof(struct mach_header_64));
while (j < header->ncmds) {
if (cmd->cmd == LC_SEGMENT) {
struct segment_command* seg = (struct segment_command*)cmd;
if (((intptr_t)ptr >= (seg->vmaddr + offset)) && ((intptr_t)ptr < (seg->vmaddr + offset + seg->vmsize))) {
vmaddr = seg->vmaddr;
image_name = _dyld_get_image_name(i);
return true;
}
}
if (cmd->cmd == LC_SEGMENT_64) {
struct segment_command_64* seg = (struct segment_command_64*)cmd;
if (((uintptr_t)ptr >= (seg->vmaddr + offset)) && ((uintptr_t)ptr < (seg->vmaddr + offset + seg->vmsize))) {
vmaddr = seg->vmaddr;
image_name = _dyld_get_image_name(i);
return true;
}
}
j++;
cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
}
}
return false;
}
答案 1 :(得分:2)
dyld(3)手册页(似乎不再在线)中记录的功能似乎提供了类似的功能。
以下是该内容:
NAME
_dyld_image_count, _dyld_get_image_header, _dyld_get_image_vmaddr_slide, _dyld_get_image_name, _dyld_register_func_for_add_image, _dyld_register_func_for_remove_image, NSVersionOfRunTimeLibrary, NSVersionOfLinkTimeLibrary _NSGetExecutablePath
概要
#include <mach-o/dyld.h> uint32_t _dyld_image_count(void); const struct mach_header* _dyld_get_image_header(uint32_t image_index); intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index); const char* _dyld_get_image_name(uint32_t image_index); void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)); void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)); int32_t NSVersionOfRunTimeLibrary(const char* libraryName); int32_t NSVersionOfLinkTimeLibrary(const char* libraryName); int _NSGetExecutablePath(char* buf, uint32_t* bufsize);
说明
这些例程提供了对dyld的额外反省 由
提供dlopen()
和dladdr()
_dyld_image_count()
返回映射的当前图像数 通过dyld。请注意,使用此计数来迭代所有图像不是 线程安全,因为另一个线程可能是添加或删除图像 在迭代期间。
_dyld_get_image_header()
返回一个指向the mach标题的指针 由image_index索引的图像。如果image_index
超出范围,则为NULL 归还。
_dyld_get_image_vmaddr_slide()
返回虚拟内存地址 由image_index
索引的图像的幻灯片数量。如果image_index
超出范围归零。
_dyld_get_image_name()
返回索引的图像的名称image_index
。 C-string继续由dyld拥有并且应该 没有删除。如果image_index
超出范围,则返回NULL。
_dyld_register_func_for_add_image()
注册指定的函数 添加新图像时要调用(捆绑或动态共享) 图书馆)到该计划。首次注册此功能时,它是 为当前属于该过程的每个图像调用一次。
_dyld_register_func_for_remove_image()
注册指定的 删除图像时要调用的函数(包或动态) 来自流程的共享库。
NSVersionOfRunTimeLibrary()
返回current_version数 由libraryName指定的当前加载的dylib。该 对于/path/libbar.3.dylib和,libraryName参数为“bar” 对于/path/Foo.framework/Versions/A/Foo,“Foo”。此函数返回 如果没有加载这样的库,则为-1。
NSVersionOfLinkTimeLibrary()
返回当前的版本号 主要可执行文件在构建时链接。 libraryName 对于/path/libbar.3.dylib和“Foo”,参数将是“bar” /path/Foo.framework/Versions/A/Foo。如果是,此函数返回-1 主可执行文件没有链接到指定的库。
_NSGetExecutablePath()
将主要可执行文件的路径复制到 缓冲区buf
。bufsize
参数最初应该是。{ 缓冲区的大小。如果路径是,则此函数返回0 成功复制,和 *bufsize
保持不变。如果缓冲区不够大,则返回-1,并将*bufsize
设置为所需的大小。注意_NSGetExecutablePath()
将返回可执行文件的“路径”而不是a 可执行文件的“真实路径”。也就是说,路径可以是符号的 链接而不是真实的文件。使用深层目录总bufsize 需要的可能超过MAXPATHLEN
。