2

因此,在 Linux 上,当使用 gcc 编译/链接的 C++ 程序加载其可执行文件时,会发生以下情况:

  1. 执行*系统调用
  2. 加载了 LD 动态库
  3. C++ 静态初始化
  4. 主入口点

假设我有一些原型功能void f()

是否有某种方式(通过源修改、属性、编译器/链接器选项等)将可执行文件与 f 链接,以便在第 1 步和第 2 步之间执行?

第 2 步和第 3 步之间呢?

(显然没有标准的方法可以做到这一点,我要求为最新版本的 gcc/linux/x86_64/glibc/binutils 提供平台特定、编译器特定的方式)

4

2 回答 2

2

是的,您可以在 (1) 和 (2) 之间或 (2) 和 (3) 之间执行此操作。第 2 步“加载了 ld 动态库”实际上是通过调用动态链接器来完成的,ld.so. 通常,这将是/lib64/ld-linux-x86-64.so.2或类似的;它是 glibc 的一部分。但是,路径实际上是在可执行文件中指定的,因此您可以使用任何您想要的路径。

$ readelf -l `which bash`
⋮
Program Headers:
⋮
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

⋮

这是除了做LD_PRELOAD/之类的事情之外LD_AUDIT

对于 (2) 和 (3) 之间,听起来您只想更改入口点地址。

于 2012-05-24T16:56:37.217 回答
-1

基本上没有。系统调用将execve()擦除环境。您在地址空间中所做的任何事情都无法在新地址空间中继续存在。您可以将文件描述符(当然,标记为 CLOEXEC 的除外)发送到新进程中,并且您可以通过环境将参数传递给它。

...这给了你一些可能做你想做的事。您可以将 LD_PRELOAD 设置为“首先”加载共享库,然后从目标可执行文件运行任何代码,并且在共享链接器解析任何符号之前。从您的问题中不清楚这是否符合您的要求。

于 2012-05-24T16:51:37.657 回答