我无法使用间接函数将精灵的gnu扩展名用于dladdr
。
在下面的示例中,fabs
和sin
是libm
中的两个动态函数,其中sin
也是间接函数。从指针查找fabs
效果很好,但找不到sin
。我已尝试向dlopen
和-rdynamic
添加各种标记但未成功。
调试程序显示sin
从gnu-indirect-function variable
到__sin_avx
的评估方式。
我在这里遗漏了什么或是dladdr
不支持的间接功能吗?
/*
compiled with g++-5 -fPIC -ldl
*/
#include <cmath>
#include <dlfcn.h>
#include <iostream>
char const * name (void * arg)
{
void * h = dlopen (NULL, RTLD_LAZY);
if (h)
{
Dl_info res;
int status = dladdr (arg, & res);
dlclose (h);
if (status && res.dli_sname && arg == res.dli_saddr)
return res.dli_sname;
}
return "";
}
int main ()
{
std::cout << fabs (0.0) << " " << name ((void *) fabs) << std::endl; // found
std::cout << sin (0.0) << " " << name ((void *) sin ) << std::endl; // not found
}
答案 0 :(得分:3)
我在这里遗漏了什么,还是dladdr不支持的间接功能?
好的,这个很有趣。
因此ifuncs通过将原始函数地址(在本例中为sin
)替换为当前平台上动态链接器解析的函数地址来工作。根据CPU功能,sin
可以解析为4种实现之一:
libm_ifunc (__sin, (HAS_ARCH_FEATURE (FMA4_Usable) ? __sin_fma4 :
HAS_ARCH_FEATURE (AVX_Usable)
? __sin_avx : __sin_sse2));
weak_alias (__sin, sin)
现在每个__sin_XXX
都是一个内部Glibc函数,不 导出来自libm.so
,这就是dladdr
无效的原因找到它。
所以答案基本上没有,dladdr
对ifuncs不起作用......
如果删除-fPIC ,可以正常工作
这是因为无论何时编译w / o -fPIC
编译器都知道当前源文件将转到主可执行文件,因此运行时函数地址可以保证解析为可执行文件的PLT条目。因此,它不是从GOT加载它,而是简单地将PLT地址传递给name
和dladdr
,然后愉快地在可执行文件的symtab中找到sin
。
编辑:
由Glibc人员here确认。