Можно ли определить символ динамически, чтобы он мог быть найден dlsym?
Я хочу имитировать загрузку символов из общей библиотеки для целей тестирования. Есть ли способ программно определить символ во время выполнения, чтобы
dlsym
найдет?
Например:
dl_define_symbol("foobar")
....
void* f = dlsym("foobar",RTLD_NEXT);
Вопрос в том, предоставляет ли что-нибудь (dl, ld, elfutils?) функции API, которые сделали бы это возможным?
Такая функциональность, вероятно, существует внутри
ld
но это, возможно, не выставлено.
Иными словами, существует ли симметричный API для
dlsym()
и другие?
Для контекста, я пишу автоматические тесты для поведения приложения, включающего интерпозицию библиотек с использованием LD_PRELOAD и
dlsym(RTLD_NEXT)
. На самом деле это интерпозитор malloc в соответствии со связанными вопросами:
- /questions/14659044/alternativa-ustarevshej-funktsionalnosti-mallochook-v-glibc/14659054#14659054
- Как правильно вставить malloc с учетом цепочки LD_PRELOAD
Я хочу проверить случай, когда разные символы поступают из разных библиотек. Это можно обнаружить с помощью
dladdr
на символы. Псевдокод:
void* f1 = dlsym(RTLD_NEXT,"malloc");
void* f2 = dlsym(RTLD_NEXT,"malloc_usable_size");
// handle failures...
Dl_info info1;
dladdr(f1,&info1);
Dl_info info2;
dladdr(f2,&info2);
// handle failures...
if (info1.dli_fbase != info2.dli_fbase)
{
// malloc_usable_size() is provided by a different library than malloc()
// so we probably shouldn't use it
f2 = nullptr;
// set flags accordingly
}
Примером этого на практике является электрический забор. Если я цепочку:
LD_PRELOAD="mymalloc.so электрический забор.so"
Вы обнаружите, что
malloc_usable_size()
происходит от
libc
пока
malloc
происходит от
electric-fence
. Конечно, электрический забор уже не так распространен.
Это, конечно, возможно, если использовать в тестах настоящую разделяемую библиотеку. Этот вопрос спрашивает, есть ли ярлык. Другой подход заключается в том, чтобы попытаться вставить саму dlsym(). Это несколько пугает. Хотя см. - Как я могу перехватывать вызовы dlsym, используя LD_PRELOAD?