共享库中的符号查找 [英] symbol lookup in shared libraries

查看:74
本文介绍了共享库中的符号查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在下面测试了这样一个简单的程序

 /*共享库*/dispatch_write_hello(无效){fprintf(stderr,"hello \ n");}外部虚空print_hello(无效){dispatch_write_hello();} 

我的主程序是这样的:

 外部无效dispatch_write_hello(无效){fprintf(stderr,"overridden \ n");}整型main(int argc,char ** argv){print_hello();返回0;} 

该程序的结果为"overriden".
为了弄清楚为什么会发生这种情况,我使用了gdb.调用链是这样的:
_dl_runtime_resolve->_dl_fixup-> _dl_lookup_symbol_x
我发现glibc中 _dl_lookup_symbol_x 的定义是

在加载的对象的符号表中搜索符号UNDEF_NAME的定义,也许带有该符号的请求版本

因此,我认为在尝试查找符号 dispatch_write_hello 时,它首先在主对象文件中查找,然后在共享库中查找.这是导致此问题的原因.我的理解正确吗?非常感谢您的宝贵时间.

解决方案

鉴于您提到 _dl_runtime_resolve ,我假设您使用的是Linux系统(感谢@Olaf对此进行了澄清).

您的问题的简短答案-是的,在插入符号期间,动态链接器将首先在可执行文件内部查找,然后才扫描共享库.因此,以 dispatch_write_hello 的定义为准.

编辑

如果您想知道为什么运行时链接程序需要将对 dispatch_write_hello 中的 dispatch_write_hello 的调用解析为同一翻译单元中除 dispatch_write_hello 之外的其他任何内容,这是由GCC中所谓的语义插入支持引起的.默认情况下,编译器将库代码内部的任何调用(即用 -fPIC 编译的代码)在运行时都视为可能插入,除非您通过 -fvisibility-hidden 明确告知不要, -Wl,-Bsymbolic -fno-semantic-interposition __ attribute __((visibility("hidden"))).这已经在网上多次讨论过,例如在臭名昭著的动态的抱歉状态Linux上的库.

请注意,与其他编译器(Clang,Visual Studio)相比,此功能会导致明显的性能损失.

I have tested such a simple program below

/* a shared library */
dispatch_write_hello(void)
{
        fprintf(stderr, "hello\n");
}

extern void
print_hello(void)
{
        dispatch_write_hello();
}

My main program is like this:

extern void
dispatch_write_hello(void)
{
        fprintf(stderr, "overridden\n");
}

int
main(int argc, char **argv)
{
        print_hello();
        return 0;
}

The result of the program is "overriden".
To figure this out why this happens, I used gdb. The call chain is like this:
_dl_runtime_resolve -> _dl_fixup ->_dl_lookup_symbol_x
I found the definition of _dl_lookup_symbol_x in glibc is

Search loaded objects' symbol tables for a definition of the symbol UNDEF_NAME, perhaps with a requested version for the symbol

So I think when trying to find the symbol dispatch_write_hello, it first of all looks up in the main object file, and then in the shared library. This is the cause of this problem. Is my understanding right? Many thanks for your time.

解决方案

Given that you mention _dl_runtime_resolve, I assume that you're on Linux system (thanks @Olaf for clarifying this).

A short answer to your question - yes, during symbols interposition dynamic linker will first look inside the executable and only then scan shared libraries. So definition of dispatch_write_hello will prevail.

EDIT

In case you wonder why runtime linker needs to resolve the call to dispatch_write_hello in print_hello to anything besides dispatch_write_hello in the same translation unit - this is caused by so called semantic interposition support in GCC. By default compiler treats any call inside library code (i.e. code compiled with -fPIC) as potentially interposable at runtime unless you specifically tell it not to, via -fvisibility-hidden, -Wl,-Bsymbolic, -fno-semantic-interposition or __attribute__((visibility("hidden"))). This has been discussed on the net many times e.g. in the infamous Sorry state of dynamic libraries on Linux.

As a side note, this feature incures significant performance penalty compared to other compilers (Clang, Visual Studio).

这篇关于共享库中的符号查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆