我正在尝试检查调用dlopen
和dlsym
的程序的行为:最终目标是插入一个小函数,将函数记录到通过dlsym
获得的函数。
通常情况下,对于要用foo
包装的某些函数DYLD_INSERT_LIBRARIES
,可以这样写:
void (*real_foo)(void);
void init() __attribute__((constructor)) {
real_foo = dlsym(RTLD_NEXT, "foo");
}
void foo(void) {
puts("foo was called");
real_foo();
}
问题在于,当你试图包裹dlsym
时,你最终得到了这个:
void* (*real_dlsym)(void* handle, const char* symbol);
void init() __attribute__((constructor)) {
real_dlsym = dlsym(RTLD_NEXT, "dlsym");
}
void* dlsym(void* handle, const char* symbol) {
return real_dlsym(handle, symbol);
}
init
最终会调用您自己的dlsym
实现,这无济于事。
当我导出另一个时,如何获得“真正的”dlsym?或者有更好的方法来拦截对dlsym的调用吗?
答案 0 :(得分:0)
至少在10.12系统上,dlsym
实际上是在/usr/lib/system/libdyld.dylib
中实现的。它应该适用于dlopen()
该文件,然后使用返回的句柄调用dlsym()
以获得真正的dlsym()
实现。您可能需要额外mode
个dlopen()
标记,例如RTLD_FIRST
和/或RTLD_LOCAL
。排序如下:
void *libdyld_handle = dlopen("/usr/lib/system/libdyld.dylib", RTLD_LAZY);
void *dlsym_funcptr = dlsym(libdyld_handle, "dlsym");