3

在我使用 Emdebian 的 armhf 的 g++-4.7 交叉编译器为 arm-linux 交叉编译的一些代码中,我一直遇到 dladdr 的问题。问题似乎是,如果您传递给 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 的这个地址,而不是从 libc.so.6 中找到的正确地址,它会通过 GOT 找到。dladdr手册页建议将代码编译为位置独立应该可以解决此问题,但此编译器似乎并非如此。作为参考,上面显示的相同代码在带有 g++-4.7 的 x86_64 Linux 上按预期工作。

4

0 回答 0