Разделяемый объект явно вызывает внутреннюю функцию внутри себя
Я переписывал некоторые функции 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
Как видите, только calloc
вызывается функция из библиотеки, внутренняя memset
не называется.
Как я могу сказать в своей библиотеке явно вызывать свои собственные функции?
Примечание. Моя функция должна вызываться так же, как и библиотека libC, так как она должна работать с LD_PRELOAD
тоже.
1 ответ
Как я могу сказать в своей библиотеке явно вызывать свои собственные функции?
Возможно, лучшим способом было бы дать вашим собственным функциям разные имена. Например, префикс их имен с постоянным префиксом: 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);
}
Но, опять же, не полагайтесь на оболочки внутри библиотеки. Вы можете даже разделить обертки на отдельную библиотеку, если хотите.
Идея здесь состоит в том, чтобы свести к минимуму воздействие линкерных игр и динамических эффектов линковки. Вы не можете полностью избежать их, когда нужно заменить свои собственные реализации стандартных библиотечных функций, но таким образом вы можете уменьшить область их применения, чтобы они доставляли вам неприятности.