Как получить адрес функции из текущего исполняемого файла?

Мне нужно узнать адрес функции из текущего исполняемого файла на Solaris 10 с использованием C++ (я использую GNU g++ 4.9.2). Например, у меня есть функция, например: void doSomething(const char *p), которая может быть определена или не определена в текущем исполняемом файле. Итак, я хотел бы найти функцию в текущем исполняемом файле, если она существует, а затем вызвать ее, чтобы выполнить некоторую операцию по умолчанию. Как я могу это сделать? Длсим поможет? Пожалуйста, помогите мне с синтаксисом и искаженным именем.


person Dr. Debasish Jana    schedule 22.11.2016    source источник
comment
Да, именно в этом и заключается цель dlsym. Он вернет указатель функции (т.е. адрес) для функции по (искаженному) имени.   -  person Cameron    schedule 22.11.2016
comment
@Cameron Пожалуйста, помогите мне использовать аргументы (для поиска в текущем исполняемом файле) и искаженное имя   -  person Dr. Debasish Jana    schedule 22.11.2016


Ответы (2)


Вы можете получить список символов в вашем исполняемом файле, запустив nm exec. Или, если вы пытаетесь получить символ из общей библиотеки, вы также можете nm использовать библиотеку для символов. Выберите тот, который вы хотите, и загрузите его чем-то вроде...

void* handle = dlopen(NULL, RTLD_LAZY);
void* ptr = dlsym(handle, "mangled_name_you_got_from_nm");

Хотя вы, вероятно, захотите привести его к типу указателя функции функции, которую вы загружаете, с помощью чего-то вроде (очевидно, измените на соответствующий тип указателя функции)...

void* handle = dlopen(NULL, RTLD_LAZY);
auto ptr = reinterpret_cast<int(*)(int)>(dlsym(handle, "mangled_name_you_got_from_nm"));
person pat    schedule 22.11.2016
comment
Есть ли аналог nm на Solaris 10? Это помогло бы мне получить искаженное имя - person Dr. Debasish Jana; 22.11.2016
comment
Вы можете использовать elfdump -S - person yugr; 22.11.2016
comment
Этот ответ имеет два недостатка: (1) изменение имени может меняться между компиляторами или даже между разными версиями одного и того же компилятора. (2) Если основной исполняемый файл не связан с -rdynamic (или эквивалентным), функция не будет экспортирована в динамическую таблицу символов, и dlsym вернет для нее NULL. - person Employed Russian; 21.12.2016
comment
@EmployedRussian Solaris 10 не поддерживает статически связанные исполняемые файлы. См. Статическое связывание — куда оно делось?: С Solaris 10 вы можете больше не создавать статический исполняемый файл. ... - person Andrew Henle; 05.01.2017
comment
@AndrewHenle Статическая ссылка не имеет абсолютно ничего общего с ответом или моим комментарием. - person Employed Russian; 05.01.2017
comment
@EmployedRussian Статическое связывание не имеет абсолютно никакого отношения к ответу или моему комментарию. Неправильно. В своем комментарии вы прямо указываете, что исполняемый файл должен быть динамически связан: Если основной исполняемый файл не связан с -rdynamic (или эквивалентным) Еще раз: Solaris 10 не поддерживает ничего кроме динамического связывания, поэтому ваш комментарий излишен. - person Andrew Henle; 05.01.2017
comment
@AndrewHenle Вы ошибаетесь. Флаг -rdynamic указывает, какие символы экспортируются из динамически связанного исполняемого файла (по умолчанию, без -rdynamic, только символы, на которые ссылается экспортируются другие общие библиотеки). - person Employed Russian; 05.01.2017

Необходимость «вызывать foo(), если он определен, и ничего не делать, если нет» довольно распространена в библиотеках.

Одним из распространенных примеров является вызов pthread_mutex_lock и pthread_mutex_unlock, если программа связана с потоками, но без блокировки в противном случае.

Слабые неразрешенные символы — идеальное решение.

extern void foo() __attribute__((weak));

void MaybeCallFoo()
{
   if (&foo == NULL) { printf("foo is not defined\n"); return; }
   foo();  // It is defined, call it.
}
person Employed Russian    schedule 21.12.2016