linux - 使用 ELF 文件的 ".init_array"部分

标签 linux assembly elf gnu-assembler

当需要在程序启动时运行一段代码(Linux),如何正确使用可执行文件(ELF32-i386)的.init_section?我有以下代码(GNU Assembler),它有 ctor 初始化函数,这个函数的地址放在 .init_array 部分:

.intel_syntax noprefix
.data
s1: .asciz "Init code\n"
s2: .asciz "Main code\n"
.global _start
.global ctor
.text
ctor:
    mov     eax, 4           # sys_write()
    mov     ebx, 1           # stdout
    mov     ecx, offset s1 
    mov     edx, 10
    int     0x80
    ret

.section .init_array
    .long ctor

.text
_start:
    mov     eax, 4
    mov     ebx, 1
    mov     ecx, offset s2
    mov     edx, 10
    int     0x80

    mov     eax, 1
    mov     ebx, 0
    int     0x80

此代码与:

as -o init.o init.asm
ld -o init init.o

运行生成的可执行文件时,只会打印“Main code”字符串。如何正确使用 .init_array 部分?

编辑 1:我想使用 .init_array,因为有多个源文件都有自己的初始化代码。可以在启动时“手动”调用所有这些代码,并在每次将源文件添加到项目或从项目中删除时修改它,但是 .init_array 似乎是专门为这种情况设计的:

Before transferring control to an application, the runtime linker processes any initialization sections found in the application and any loaded dependencies. The initialization sections .preinit_array, .init_array, and .init are created by the link-editor when a dynamic object is built.

The runtime linker executes functions whose addresses are contained in the .preinit_array and .init_array sections. These functions are executed in the same order in which their addresses appear in the array.

如果在没有 gcc 的情况下创建可执行文件,链接器似乎不会执行启动代码。我尝试编写自己的标准 init 例程,它读取 .init_array 部分中的函数指针并调用它们。它适用于一个文件,其中可以标记该部分的结尾,例如,用零标记。但是对于多个文件,这个零可以重新定位在部分的中间。如何正确确定由多个源文件组装而成的节的大小?

最佳答案

如果您按照自己的方式创建一个静态链接 裸可执行文件,在_start 入口点使用您自己的代码,您的代码就从该点开始运行。如果你想让某事发生,你的代码必须让它发生。没有魔法。

使用节对于将来自多个源文件的启动代码组合在一起很有用,因此所有启动代码都是冷的并且可能被调出页面,或者至少不需要 TLB 条目。

因此,您通过将函数放在那里并从 _start 之后某个时间运行的代码调用它们来“正确使用”部分。

在您的代码示例中,.init_array 看起来像是一个函数指针列表。我假设标准 CRT 启动文件读取 ELF 文件并找到该部分的长度,然后通过它间接调用这些函数。由于您正在编写自定义代码,因此调用一个执行所有操作的 init 函数会更快。


动态链接:

“运行时链接器”是动态二进制文件的 ELF 解释器。它在 _start 之前在您的进程中运行代码,所以是的,显然它确实处理了 ELF 部分并让奇迹发生了。


因此,为了响应您的编辑,您的选择是:自己实现 .init_array 的处理,或者创建动态可执行文件。我很确定其他问题已经涵盖了这个过程,而且我没有时间为仍然没有链接 libc 的动态可执行文件研究正确的命令行。 (尽管您可能只想使用 gcc -nostartfiles 或其他东西。)

如果您遇到困难,请发表评论。当我有更多时间时,我可能会稍后更新它,或者随时在工作命令中进行编辑。

关于linux - 使用 ELF 文件的 ".init_array"部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35827230/

相关文章:

Xilinx SDK 中 zynq7000 的 Linux 应用程序项目

linux - 如何从 ELF 文件中禁用地址随机化 (ASLR)?

linux - 尽管设置了rpath,但未找到共享库

linux - 为什么 MPI 不能优雅地完成?

php - 在 Alpine Linux 中安装特定版本的 PHP

assembly - 从COM抓取流量

linux - 在 Linux 中编写快捷的临时 GUI 应用程序的最简单方法(语言、工具等)是什么?

c - 在 Assembly x86 中遍历二维数组

c++ - 程序集文件 (.s) 抛出错误 : unknown use of instruction mnemonic without a size suffix

c - 如何读取二进制文件并将数据存储在C中的指针处