如何使用dladdr获取gnu间接函数的名称?

时间:2017-01-08 14:03:02

标签: c++ gnu elf

我无法使用间接函数将精灵的gnu扩展名用于dladdr

在下面的示例中,fabssinlibm中的两个动态函数,其中sin也是间接函数。从指针查找fabs效果很好,但找不到sin。我已尝试向dlopen-rdynamic添加各种标记但未成功。

调试程序显示singnu-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
}

1 个答案:

答案 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地址传递给namedladdr,然后愉快地在可执行文件的symtab中找到sin

编辑:

由Glibc人员here确认。