【问题标题】:How to get name of gnu indirect function using dladdr?如何使用 dladdr 获取 gnu 间接函数的名称?
【发布时间】:2017-01-10 23:42:10
【问题描述】:

我无法通过使用dladdr 的间接函数获得对elf 的gnu 扩展。

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

调试器显示如何从gnu-indirect-function variable 评估sin__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
}

【问题讨论】:

  • 有趣,如果你删除 -fPIC 就可以工作。

标签: c++ gnu elf


【解决方案1】:

我在这里遗漏了什么还是 dladdr 不支持间接函数?

好的,这个很有趣。

因此 ifuncs 通过将原始函数地址(在本例中为 sin)替换为当前平台上的动态链接器解析的地址来工作。 sin 可以根据 CPU 能力解析为 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 确认。

【讨论】:

  • 非常感谢。我确实找到了一些关于 ifunc 和可见性的posts,但这个主题对我来说很新。作为一种变通方法,有没有办法引用原始间接函数,即__attribute__ ifunc
  • 我个人不知道比手动解析 GOT 表更简单的方法(例如,描述为 here),但这是一项艰巨的任务。您可以尝试在libc-help提问。
  • here 是我在 libc-help 上的问题的答案。简而言之,当解析到其实现时,有关原始 ifunc 符号名称的信息会丢失。关于解析 GOT - 请原谅我的程序集 - 但从我可以从生成的代码中读取的内容,我不确定 ifuncs 在程序启动时是否已经解决,而不是在第一次调用时解决。如果是这样,就没有机会解析 GOT 的原始 ifunc 地址,对吧?
  • 我做了一个小实验,似乎 ifuncs 被懒惰地解析了。所以理论上你可以在程序启动时通过分析 GOT 来解决它们,直到它们被运行时链接器丢弃。这当然不适用于构造函数中使用的 ifunc。
  • 我在上面使用常量参数的错误,sin@PLT 访问在生成的代码中被忽略了,这让我感到困惑。感谢您的努力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 2012-10-18
  • 1970-01-01
相关资源
最近更新 更多