我在我的一些代码中遇到了dladdr的问题,我使用Emdebian的g ++ - 4.7交叉编译器为armhf交叉编译arm-linux。问题似乎是,如果传递给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正在从PLT中找到printf的这个地址,而不是通过GOT找到的libc.so.6中的正确地址。 dladdr man page建议将代码编译为位置无关应该解决这个问题,但这似乎不是这个编译器的情况。作为参考,上面显示的相同代码在使用g ++ - 4.7的x86_64 Linux上按预期工作。