Я пытался динамически вызвать функцию в самом исполняемом файле.
Целевая функция test_func
была закодирована вместе с функцией main
в том же исходном файле. Вот пример кода:
#include <stdio.h>
#include <dlfcn.h>
// or with some tricks
// void __attribute__((visibility("default")))
void test_func(void)
{
printf("test_func in %s \n",__FILE__);
}
int main()
{
void *handle = dlopen(0, RTLD_LAZY); // or RTLD_GLOBAL
printf("dlopen return %p\n", handle);
void (*func)() = dlsym(handle, "test_func");
printf("dlsym return %p\n", func);
if (func) (*func)();
return 0;
}
Затем я скомпилировал его с помощью gcc
, и результат получился таким:
$ ./a.out
dlopen return 0xe29dfbec1c7bc0d
dlsym return 0x0
Я могу прочитать символ в ELF. Мне пришло в голову, что должен быть какой-то способ получить функцию test_func
и вызвать ее.
$ readelf -s a.out | grep test_func
40: 00000000000017c8 36 FUNC GLOBAL DEFAULT 13 test_func
Есть ли что-то, что мне не хватает?
dlopen
и dlsym
также работают в Windows, но имена файлов библиотеки явно отличаются. stackoverflow.com/questions/11741580/… кажется актуальным
Извини, моя ошибка. Орфографию исправил, спасибо.
Еще раз спасибо, но в моем исходном вопросе я действительно хочу спросить: могу ли я динамически вызывать функцию в самом исполняемом файле с помощью GetModuleHandle()/GetProcAddress()?
Вы используете окна? Тогда вам следует рассмотреть возможность использования DLL для динамической загрузки функций.
Обычно, когда вы вызываете dlopen(0, RTLD_LAZY)
, он пытается открыть собственную таблицу символов исполняемого файла; при извлечении символов он может работать не так, как ожидалось. Это связано с тем, что динамический компоновщик может не предоставлять все символы исполняемого файла так же, как для общих библиотек.
Несмотря на то, что вы можете увидеть test_func
в выводе readelf
, он все равно может быть недоступен через dlsym
, если он не отображается должным образом или если таблица динамических символов не заполнена должным образом.
Итак, поскольку цель dlopen
в основном касается общих библиотек. Распространенным решением было бы переключение на общую библиотеку, но если вам действительно нужно использовать исполняемый файл:
Вы должны обязательно выполнить компиляцию с флагом -rdynamic
, чтобы символы были включены в таблицу динамических символов.
gcc -rdynamic -o a.out <filename.c>
Это важно, чтобы символы были видны через dlsym
.
Итак, если позиция -rdynamic
должна быть принята, то dlopen(NULL, RTLD_LAZY)
действительно должно сработать. Если предположить, что это не так, то, вероятно, это ошибка или ошибка в вашем компоновщике или динамическом загрузчике и в том, как он обрабатывает символы.
Итак, в сортировке мы можем сказать:
-rdynamic
при компиляции, чтобы отображать символы.dlopen
и dlsym
по назначению.Вот полный код, в котором я использовал -rdynamic
, а также проверил, виден ли символ или нет:
#include <stdio.h>
#include <dlfcn.h>
// Define the function to be called
void __attribute__((visibility("default"))) test_func(void)
{
printf("test_func in %s \n", __FILE__);
}
int main()
{
// Open the executable's symbol table
void *handle = dlopen(NULL, RTLD_LAZY);
if (!handle) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
return 1;
}
printf("dlopen return %p\n", handle);
// Retrieve the address of test_func
void (*func)() = dlsym(handle, "test_func");
if (!func) {
fprintf(stderr, "dlsym failed: %s\n", dlerror());
dlclose(handle);
return 1;
}
printf("dlsym return %p\n", func);
// Call the function if found
(*func)();
// Close the handle
dlclose(handle);
return 0;
}
Сообщите мне, если вы все еще сталкиваетесь с какими-либо ошибками
Я пытался исправить орфографию, но есть несколько неясных фраз. Я думаю, вы имеете в виду «скомпилировано», а не «соблюдено»; но что означает это предложение? Как именно вы это скомпилировали?