gpt4 book ai didi

linux - 为什么链接器修改了--defsym "absolute address"

转载 作者:IT王子 更新时间:2023-10-29 00:31:16 26 4
gpt4 key购买 nike

目标:共享库以使用可执行文件(不导出符号)中的函数。

意思是: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)。

  • 为什么要修改“绝对地址”?
  • 如何避免?

更新:

我质疑以下回复的技术相关性,甚至更多的是它的“更新”:

使用 --defsym 来定义 PIC 库/可执行文件中的重定位符号是没有意义的(除了污染二进制文件而没有任何可用功能外,它没有任何用途)。

因此,在 PIC 共享库或 PIC 可执行文件中 --defsym 的唯一相关用途应该是定义(非重定位)“绝对地址”。

顺便说一句,如果您愿意阅读手册页,这就是 --defsym 的官方目的:

“在输出文件中创建一个全局符号,包含表达式给出的绝对地址。”

充其量,这是一个 Linux 链接器缺陷,修复起来很简单。对于那些等不及拒绝者意识到(并修复)他们的错误的人,解决方案是在有缺陷的链接器加载二进制镜像后修补重定位表。

然后,--defsym 在 PIC 库/可执行文件中变得有用,在我看来这是一个可喜的进步。

最佳答案

您似乎从根本上误解了 --defsym 的作用。

--defsym=symbol=expression
Create a global symbol in the *output* file, ...

也就是说,您正在构建的库中创建新符号。因此,该符号(自然地)与库一起重新定位。

我猜你想要这样的东西:

// code in library
int fn()
{
// exe_fn not exported from the executable, but we know where it is.
int (*exe_fn)(void) = (int (*)(void)) 0x432238;
return (*exe_fn)();
}

如果您不想将 0x432238 硬编码到库中,而是在构建时通过命令行传递值,只需使用 -DEXE_FN=0x432238 实现这一目标。

更新:

Goal: a shared library to use a function from an executable

您选择的方法无法实现该目标。您将不得不使用其他方式。

Why the "absolute address" is modified?

事实并非如此。当您要求链接器在绝对地址 0x432238 处定义 function 时,它会完全那样做。您可以在 objdumpnmreadelf -s 输出中看到它。

但因为该符号是在共享库中定义的,所有对该符号的引用都被重新定位,即由共享库加载地址调整(由动态加载器)。动态加载程序做其他事情毫无意义

How to avoid it?

你不能。使用其他方式实现您的目标。

关于linux - 为什么链接器修改了--defsym "absolute address",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8368423/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com