共享对象本身显式调用内部函数

时间:2018-02-09 16:51:31

标签: c shared-libraries

我一直在重新编码一些我在共享对象库中包含的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一起使用。

1 个答案:

答案 0 :(得分:2)

  

如何在我的库中告知显式调用自己的函数?

最好的方法可能是为自己的函数提供不同的名称。例如,在名称前加上一致的前缀:my_strlenmy_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);
}

但是,再次,不要依赖于库中的包装器。如果愿意,你甚至可以将包装器拆分成一个单独的库。

这里的想法是尽量减少您对链接器游戏和动态链接效果的影响。当你想要替换自己的标准库函数实现时,你无法完全避免这些,但是这样你可以减少它们的范围,从而给你带来麻烦。