我需要编写一个小库,通过设置LD_PRELOAD来加载,它将覆盖标准C库中的某些函数,但也会在标准库中调用这些函数。具体来说,我希望我的闪亮的新库让用户提供他们自己的resolv.conf,以便他们可以,例如,指定他们的默认域,或在其中为长主机名设置别名。如果我要这样做,我将需要很好地理解链接器的工作原理,所以任何人都可以指出我的一些良好的文档,并不认为我已经知道了这一切并且只需要一个参考,但也不假设我是一个完全白痴?
答案 0 :(得分:3)
如果您使用的是GNU链接器,那么您需要了解的一件事是RTLD_NEXT。这允许您“在当前库之后”在搜索顺序中查找下一个函数。“
这样,您可以覆盖标准功能,但仍然可以调用原始版本。
我在跟踪分配统计信息的malloc版本中使用了此功能。我需要覆盖malloc以收集统计数据,但我仍然希望malloc的原始版本进行分配:
static void *(*next_malloc)(size_t) = NULL;
__attribute__ ((constructor))
static void
bootstrap()
{
next_malloc = dlsym(RTLD_NEXT, "malloc");
}
void *
malloc(size_t size)
{
void *ptr = next_malloc(size);
// collect some stats
return ptr;
}
答案 1 :(得分:1)
听起来你对动态加载感兴趣而不是一般的链接。这就是ODBC在运行时查找和使用特定驱动程序的方式,就像你想对你的解析器一样。
我会给你一些关于动态链接的关键字,而不是谷歌你随机链接:
概念: “动态加载”“位置独立代码”soname
工具: LD_DEBUG ldconfig ldd nm objdump
用于动态加载的C API: dlfcn.h dlopen dlsym dlerror dlclose
我找到了一个很好的教程,我记得在使用ODBC时很有帮助: http://www.ibm.com/developerworks/library/l-shobj/
但是,它建议直接调用ld,这与gcc是禁止的。而是使用-shared选项:
g++ -shared -fPIC foo.c -o libfoo.so.1.0 -Wl,soname,libfoo.so.1
另外:您应该寻找不涉及LD_PRELOAD或LD_LIBRARY_PATH的解决方案,它们基本上是调试工具,并且在生产中需要它们的库存在缺陷: Why LD_LIBRARY_PATH is bad LD_LIBRARY_PATH Is Not The Answer LD_LIBRARY_PATH - just say no
ODBC使用odbc.ini配置文件来避免它,您可以在其中指定要使用的.so的完整路径。
答案 2 :(得分:1)
有几个很好的答案,但没有人提到引导我完成这项工作的资源:Building library interposers for fun and profit。