Linux 可执行内存映射

Linux executable memory mapping

elf executable 包含一个部分 table。当程序加载到内存中时,这些部分将映射到段。 我认为是编译器决定内存中的段地址吗? 你认为操作系统有可能在加载程序时更改段地址吗?

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

An elf executable contains a section table.

错误:table 部分从完全 linked ET_EXECET_DYN 二进制文件中剥离是完全有效的。

This sections are mapped to segments when the program is loaded in memory.

False:部分到段映射发生在静态 link 时间,而不是 运行 时间。

I think it is the compiler which decide the segments address in memory ?

False:静态 linker 为 ET_EXEC 决定了这一点。对于ET_DYN,static linker和运行time loader配合。

Do you think it is possible for the operating system to change the segments address when the program is loaded.

对于ET_EXEC,二进制文件总是加载到静态linker linked那个二进制文件的地址。在其他地方加载它会导致程序崩溃。

对于 ET_DYN,也称为 PIE 二进制,在随机地址加载是可能的 预期。

i have a binary. I know a function address in memory and i want to hook this function from an external program. I just want to be sure that this address will never change.

如果二进制文件是 ET_EXEC 类型,所有段总是加载到 linked-at 地址,所以是的。

更新:

PIE 二进制文件中,所有东西 将一起移动(mainfoo_start 等)通过相同的重定位(重定位通常会从 运行 运行 变化;但是 GDB 禁用地址 space 随机化,所以必须做 (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.