我一直在重新编码一些我在共享对象库中包含的libC函数。其中一些功能在内部调用自己。
现在问题是当我从另一个程序使用dlsym
时,dlsym
提供的函数(内部使用需要内部函数)将调用libC的函数而不是我已经重新编码的函数我的图书馆。
这是一个简单的例子:
lib.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *memset(void *s, int c, size_t n)
{
printf("Calling LIB's Memset\n");
for (size_t i = 0; i < n; ++i)
((char *) s)[i] = c;
return s;
}
void *calloc(size_t mnemb, size_t size)
{
size_t sz = mnemb * size;
void *addr = malloc(sz);
printf("Calling LIB's Calloc\n");
memset(addr, 0, sz);
return addr;
}
gcc lib.c -fPIC -shared -o lib.so
的main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(void)
{
void *handler = dlopen("./lib.so", RTLD_NOW);
void (*_calloc)(size_t, size_t);
if (!handler)
{
printf("Could not open lib\n");
return 1;
}
_calloc = dlsym(handler, "calloc");
if (!_calloc)
{
printf("Could not extract symbol\n");
return 1;
}
_calloc(10, 10);
return 0;
}
gcc main.c -ldl
$ ./a.out
Calling LIB's Calloc
如您所见,只调用来自lib的calloc
函数,不调用内部memset
。
如何在我的库中告知显式调用自己的函数?
注意:我的函数必须以与libC相同的方式调用,因为它也可以与LD_PRELOAD
一起使用。
答案 0 :(得分:2)
如何在我的库中告知显式调用自己的函数?
最好的方法可能是为自己的函数提供不同的名称。例如,在名称前加上一致的前缀:my_strlen
,my_printf
等。然后在库打算调用其他函数时,只使用这些名称。愚蠢的例子:
size_t my_strlen(const char *s) {
return *s ? (1 + my_strlen(s + 1)) : 0;
}
要使外部调用者调用它们来代替它们的名字,插入包装函数。例如:
size_t strlen(const char *s) {
return my_strlen(s);
}
但是,再次,不要依赖于库中的包装器。如果愿意,你甚至可以将包装器拆分成一个单独的库。
这里的想法是尽量减少您对链接器游戏和动态链接效果的影响。当你想要替换自己的标准库函数实现时,你无法完全避免这些,但是这样你可以减少它们的范围,从而给你带来麻烦。