是否可以覆盖动态链接可执行文件的非动态段中的符号? (例如: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
是不可能的,但也许仍在使用其他一些工具?
是否可以覆盖动态链接可执行文件的非动态段中的符号?
典型的 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 版本中构建更多标志(我很确定这在过去可以工作)。