Linux可执行内存映射

时间:2016-06-16 16:17:15

标签: elf

elf可执行文件包含一个section表。当程序加载到内存中时,此部分将映射到段。 我认为是编译器决定内存中的段地址? 您是否认为在加载程序时操作系统可以更改段地址。

我说的是单个精灵可执行文件。这不是一个图书馆。 事实上,我有一个二进制文件。我知道内存中的函数地址,我想从外部程序挂钩这个函数。我只是想确保这个地址永远不会改变。我不会在目标程序中重新编译或更改任何内容。

1 个答案:

答案 0 :(得分:3)

  

elf可执行文件包含节表。

错误:从完全链接的ET_EXECET_DYN二进制文件中删除部分表格完全有效。

  

当程序加载到内存中时,此部分将映射到段。

错误:段到段的映射发生在静态链接时,而不是在运行时。

  

我认为是编译器决定内存中的段地址吗?

错误:它是为ET_EXEC决定这个的静态链接器。对于ET_DYN,静态链接器和运行时加载器协作。

  

您是否认为操作系统可以在加载程序时更改段地址。

对于ET_EXEC,二进制文件始终加载在静态链接器链接该二进制文件的地址处。在其他地方加载它会使程序崩溃。

对于ET_DYN,也称为PIE二进制文件,在随机地址加载可能是

  我有一个二进制文件。我知道内存中的函数地址,我想从外部程序挂钩这个函数。我只是想确保这个地址永远不会改变。

如果二进制文件的类型为ET_EXEC,则所有段始终都会在链接地址处加载,所以是的。

<强>更新

PIE二进制文件中,所有内容将通过相同的重定位(mainfoo_start等一起移动(重定位通常会因运行而异;但GDB会禁用地址空间随机化,因此必须执行(gdb) set disable-randomization off)。

要在GDB中查找重定位,您可以执行以下操作:

(gdb) p &main
(gdb) start
(gdb) p &main

流程开始前&main的第一个值应与nm test | grep main的输出相同。第二个值(进程开始后)应该是重定位值(其中main落在内存中)。两者之间的差异是(页面对齐)重定位。

要在运行时(从程序本身内)找到此重定位,需要使用dl_iterate_phdr()并使用dlpi_addrDocumentation