Я столкнулся с проблемой с dladdr в некоторых моих кодах, которые я кросс-компилировал для arm-linux, используя кросс-компилятор Emdebian g ++ — 4.7 для armhf. Кажется, проблема в том, что если указатель функции, который вы передаете в dladdr, является функцией, которая также вызывается в исполняемом файле, dli_fname вернет путь к исполняемому файлу вместо общей библиотеки, из которой поступил символ.
Пример скомпилирован с помощью:
/usr/bin/arm-linux-gnueabihf-g++-4.7 main.cpp -o main -ldl -fPIC
#include <dlfcn.h>
#include <iostream>
#include <stdio.h>
#include <string>
std::string findLibName(void* funcPtr) {
Dl_info info;
if (dladdr(funcPtr,&info) != 0) {
return std::string(info.dli_fname);
} else {
return "";
}
}
int main() {
printf("printf comes from %s\n",findLibName((void*)printf).c_str());
return 0;
}
Результат: printf исходит от ./main
Если я изменю тело main () на
int main() {
std::cout<<"printf comes from "<<findLibName((void*)printf)<<"\n";
return 0;
}
Результат: printf взят из /lib/arm-linux-gnueabihf/libc.so.6
Я заметил, что если функция, указатель на функцию которой вы передаете в dladdr, вызывается внутри исполняемого файла, запись будет выглядеть следующим образом:
Relocation section '.rel.plt' at offset 0x63c contains 14 entries:
Offset Info Type Sym.Value Sym. Name
00010be8 00000d16 R_ARM_JUMP_SLOT 00008730 printf
создается в разделе .rel.plt исполняемого файла, и кажется, что dladdr находит этот адрес printf из PLT, а не правильный адрес из libc.so.6, который он найдет через GOT. Dladdr справочная страница предполагает, что компиляция кода, чтобы быть независимым от позиции, должна исправить это, но это не похоже на этот компилятор. Для справки, тот же код, показанный выше, работает, как и ожидалось, в x86_64 Linux с g ++ — 4.7.
Задача ещё не решена.