Я собираюсь ответить на
вызов этой функции из моего кода c, который я пишу
часть.
Нижеследующее работает при определенных допущениях, таких как динамическое связывание и независимый от позиции код. Я не слишком долго думал о том, что произойдет, если они сломаются (давайте поэкспериментируем / обсудим, если есть интерес).
$ cat lib.c
int data = 42;
static int foo () { return data; }
gcc -fpic -shared lib.c -o lib.so
$ nm lib.so | grep foo
00000000000010e9 t foo
Выше приведено воспроизведение с адресом, который вы знаете. Адрес, который мы знаем сейчас, 0x10e9
. Это виртуальный адрес foo
до переезда. Мы смоделируем перемещение, которое динамический загрузчик делает вручную, просто добавив базовый адрес, по которому загружается lib.so
.
$ cat 1.c
#define _GNU_SOURCE
#include <stdio.h>
#include <link.h>
#include <string.h>
#include <elf.h>
#define FOO_VADDR 0x10e9
typedef int(*func_t)();
int callback(struct dl_phdr_info *info, size_t size, void *data)
{
if (!(strstr(info->dlpi_name, "lib.so")))
return 0;
Elf64_Addr addr = info->dlpi_addr + FOO_VADDR;
func_t f = (func_t)addr;
int res = f();
printf("res = %d\n", res);
return 0;
}
int main()
{
void *handle = dlopen("./lib.so", RTLD_LAZY);
if (!handle) {
puts("failed to load");
return 1;
}
dl_iterate_phdr(&callback, NULL);
dlclose(handle);
return 0;
}
А теперь ...
$ gcc 1.c -ldl && ./a.out
res = 42
Вуаля - это сработало! Это было весело.
Кредит: Это было полезно.
Если у вас есть вопросы, не стесняйтесь читать человека и спрашивать в комментариях.
Что касается
статически скомпилировать эту функцию в моем двоичном файле
Я не знаю, с ума. Это было бы сложнее. Почему ты этого хочешь? Кроме того, знаете ли вы, зависит ли функция от некоторых данных (или, возможно, она вызывает другие функции) в исходном файле ELF, как в примере выше?