覆盖动态链接可执行文件的非动态部分中的符号

问题描述 投票:0回答:1

是否可以覆盖动态链接可执行文件的非动态段中的符号? (例如:Linux 上 ELF 可执行文件的 .text 和 .(ro)data 段。)

我知道可以使用

LD_PRELOAD
覆盖动态部分中的引用。

What is the Difference between LD_PRELOAD_PATH and LD_LIBRARY_PATH?的答案声称

LD_PRELOAD
还允许覆盖静态链接函数,但我不确定如何实现。手册页说

LD_PRELOAD 在所有其他对象之前加载的附加的、用户指定的 ELF 共享对象的列表。此功能可用于选择性地覆盖其他共享对象中的功能。

因此,除非动态链接的可执行文件中的所有内容都是共享对象(仅包含一些对象,并且引用了一些对象?)这听起来像我想要的使用

LD_PRELOAD
是不可能的,但也许仍在使用其他一些工具?

linux gcc linker ld elf
1个回答
0
投票

是否可以覆盖动态链接可执行文件的非动态段中的符号?

典型的 ELF 二进制文件有两个独立的符号表:动态符号表(

.dynsym
.dynstr
)和静态符号表(
.symtab
.strtab
)。您可以使用
nm a.out
nm -D a.out
分别检查每个表。

静态符号表通常只保留用于调试; 什么都在运行时查看它(尽管“自我意识”二进制文件可能会检查那里的符号,例如打印崩溃堆栈跟踪)。

可以完全删除该表(使用

strip
),并且二进制文件仍然可以正常运行。

由于

LD_PRELOAD
的处理和动态符号解析是由动态链接器执行的,并且由于动态链接器从不查看静态符号表,因此遵循,唯一可以插入的符号是动态符号。

... 的答案声称

LD_PRELOAD
还允许覆盖静态链接函数。

您可能在这里将“静态”的两种不同用法混合在一起。

当函数来自

a.out
foo.o
时,它会静态链接到
libfoo.a
—— 即函数的代码出现在
.text
a.out
部分。

这与“静态链接

(as in
static int foo() { ... }`”无关。

同时具有静态和全局链接的函数都可以静态链接到

a.out
,但只有具有全局链接的函数才会出现在动态符号表中,并且只有出现在动态符号表中的函数才能使用
LD_PRELOAD
进行插入。

即使对于出现在

a.out
的动态符号表中的函数,插入也可能不起作用(我无法让它在 Fedora 40 上运行)。您可能需要使用
-fPIC
构建主要可执行文件,并且可能需要在最近的 GCC 版本中构建更多标志(我很确定这在过去可以工作)。

© www.soinside.com 2019 - 2024. All rights reserved.