我在一个用dlopen加载的共享对象(代码)里面。我想知道加载调用的标志。我无权访问加载程序(代码) - 例如它可能是一个脚本解释器 - 但我必须使用相同的标志创建后续的dlopen调用。
我该怎么做?
答案 0 :(得分:3)
您可以使用以下库代替调试器:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
typedef void *(*orig_dlopen_type)(const char *file, int mode);
void *dlopen(const char *file, int mode)
{
fprintf(stderr, "dlopen called (mode: %d) on %s\n", mode, file);
orig_dlopen_type orig_dlopen;
orig_dlopen = (orig_dlopen_type)dlsym(RTLD_NEXT, "dlopen");
return orig_dlopen(file, mode);
}
使用gcc -shared -fPIC dlopen_trace.c -o dlopen_trace.so -ldl
然后使用LD_PRELOAD=dlopen_trace.so
正常执行您的程序。每次调用dlopen
时都应该打印一个调试行。
如果您愿意,也可以修改途中的标志......
答案 1 :(得分:0)
我认为如果没有调试器的帮助,这是不可能的。
从latest glibc code开始,以下是dlopen
void *
dlopen (const char *file, int mode)
{
return __dlopen (file, mode, RETURN_ADDRESS (0));
}
而__dlopen
又被定义为
void *
__dlopen (const char *file, int mode DL_CALLER_DECL)
{
# ifdef SHARED
if (__builtin_expect (_dlfcn_hook != NULL, 0))
return _dlfcn_hook->dlopen (file, mode, DL_CALLER);
# endif
struct dlopen_args args;
args.file = file;
args.mode = mode;
args.caller = DL_CALLER;
# ifdef SHARED
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
# else
if (_dlerror_run (dlopen_doit, &args))
return NULL;
__libc_register_dl_open_hook ((struct link_map *) args.new);
__libc_register_dlfcn_hook ((struct link_map *) args.new);
return args.new;
# endif
}
您要查找的标记RTLD_LAZY
,RTLD_NOW
,RTLD_GLOBAL
和RTLD_LOCAL
已进行OR运算并存储在mode
变量中。正如你所看到的那样,它没有传递回来的路线或类似的东西。
编辑:似乎确实有一种方法可以达到你想要的效果,如另一个答案所示。如果您可以取消接受我的回答,我可以删除它以便帮助将来的访问者