-rdynamic
(或链接器级别的--export-dynamic
)到底做什么?它与-fvisibility*
标志或pragma
s和__attribute__
s定义的符号可见性有什么关系?
对于--export-dynamic
,ld(1)提到:
...如果你使用“dlopen”来加载一个需要引用回程序定义的符号的动态对象,而不是其他的动态对象,那么你可能需要在链接程序本身时使用这个选项。...
我不确定我是否完全理解。你能提供一个没有-rdynamic
不能工作但有-rdynamic
可以工作的例子吗?
编辑:我实际上试着编译了几个虚拟库(单文件,多文件,各种-O级别,一些函数间调用,一些隐藏符号,一些可见),有和没有-rdynamic
,到目前为止,我一直得到字节相同的输出(当然,当保持所有其他标志不变时),这很令人困惑。
5条答案
按热度按时间qmelpv7a1#
下面是一个简单的示例项目来说明
-rdynamic
的用法。“巴.c
字符串
主要.c
型
生成文件
型
这里,
bar.c
成为共享库libbar.so
,main.c
成为dlopen
的libbar
的程序,并从该库调用bar()
。bar()
调用foo()
,后者在bar.c
中是外部的,在main.c
中定义。因此,如果没有
-rdynamic
:型
而对于
-rdynamic
:型
bqf10yzr2#
-rdynamic
导出可执行文件的符号,这主要解决Mike Kinghan的回答中描述的场景,但它也有助于例如Glibc的backtrace_symbols()
符号表示回溯。下面是一个小实验(测试程序复制自here)
字符串
编译程序:
gcc main.c
并运行它,输出:型
现在,使用
-rdynamic
编译,即gcc -rdynamic main.c
,然后再次运行:型
正如你所看到的,我们现在得到了一个正确的堆栈跟踪!
现在,如果我们研究ELF的符号表条目(
readelf --dyn-syms a.out
):无
-rdynamic
型
使用
-rdynamic
,我们有更多的符号,包括可执行文件的:型
我希望这有帮助!
0x6upsns3#
我使用Glibc的
backtrace()
/backtrace_symbols()
使用rdynamic打印出回溯。如果没有
-rdynamic
,就无法获取函数名。要了解有关
backtrace()
的更多信息,请通过here阅读。jhiyze9q4#
来自 * Linux编程接口 *:
42.1.6
访问主程序中的符号
假设我们使用
dlopen()
动态加载一个共享库,使用dlsym()
从该库中获取一个函数x()
的地址,然后调用x()
。如果x()
反过来调用一个函数y()
,那么y()
通常会在程序加载的一个共享库中查找。有时候,最好让
x()
在主程序中调用y()
的实现。(这类似于回调机制。)为了做到这一点,我们必须使主程序中的(全局范围)符号对动态链接器可用,方法是使用--export-dynamic
链接器选项链接程序:$ gcc -Wl,--export-dynamic main.c
(以及其他选项和参数)同样,我们可以写如下:
$ gcc -export-dynamic main.c
个使用这两个选项中的任何一个都允许动态加载的库访问主程序中的全局符号。
gcc -rdynamic
选项和gcc -Wl,-E
选项进一步-Wl,--export-dynamic
的同义词。我猜这只适用于动态加载的共享库,用
dlopen()
打开。如果我错了请纠正我。4dbbbstv5#
为了从字面上回答OP问题,引用GCC manual:
将标志-export-dynamic传递到支持它的目标上的ELF链接器。* 这指示链接器将所有符号(而不仅仅是使用过的符号)添加到动态符号表中。* 此选项对于dlopen的某些用途或允许从程序中获取回溯是必需的。
因此,在编译使用
dlopen
的程序时,需要-rdynamic
,以使从加载的模块到程序符号的引用可解析。