目标:使用一个来自不导出符号的可执行文件中的函数的共享库。
方法:gcc -Wl,--defsym,function=0x432238
该手册说明:
"--defsym symbol=expression" Create a global symbol in the output
file, containing the absolute address given by expression.
令我沮丧的是,dlopen()
将共享库的基地址(这是64位代码)0x7ffff676f000
添加到导出的“绝对符号地址”中:
executable shared library
---------- linker --------------
symbol: 0x432238 =====> 0x7ffff6ba1238
objdump显示库中的符号地址是正确的(0x432238
),但一旦使用dlopen()
加载后,该符号的地址就变成了0x7ffff6ba1238
。
如果加载后手动将库符号修补到正确的地址,则所有工作正常(否则,库会SEGFAULT)。
- 为什么"绝对地址"会被修改?
- 如何避免这种情况?
更新:
我质疑以下回答的技术相关性,更不用说它的'更新'了:
在PIC库/可执行文件中使用--defsym定义重新定位的符号是没有意义的(除了污染二进制文件而没有任何可用的功能之外)。
因此,在PIC共享库或PIC可执行文件中,--defsym的唯一相关用途应该是定义一个(非重新定位的)“绝对地址”。
顺便说一下,如果你费心阅读手册页面,这正是--defsym的官方目的:
"创建一个全局符号在输出文件中,包含给定表达式的绝对地址
。"
最好的情况是,这是一个Linux链接器的缺陷,这很容易修复。对于那些等不及人们意识到(并修复)他们的错误的人,解决方案是在有缺陷的链接器加载二进制镜像后修补重定位表。
然后,--defsym在PIC库/可执行文件中变得有用,这对我来说是一个受欢迎的进步。
--defsym __ImageBase=0
可以使运行在 enclave 中的代码找到 enclave 加载的地址。这允许获取堆栈跟踪、计算从__ImageBase
偏移量,并在 enclave 外部进行符号化。这只是一个例子。按照您建议的方式更改行为“在加载二进制映像后修补重定位表”将会破坏无数项目。 - Chris Beck