共享库中的符号查找 [英] symbol lookup in shared libraries
问题描述
我已经在下面测试了这样一个简单的程序
/*共享库*/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屋!