【发布时间】:2016-06-20 00:41:21
【问题描述】:
当程序启动时(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
运行生成的可执行文件时,仅打印“主代码”字符串。如何正确使用 .init_array 部分?
EDIT1:我想使用 .init_array 因为有多个源文件有自己的初始化代码。可以在启动时“手动”调用所有这些代码,并在每次将源文件添加到项目中或从项目中删除时对其进行修改,但 .init_array 似乎就是为这种情况而设计的:
在将控制权转移到应用程序之前,运行时链接器 处理在应用程序中找到的任何初始化部分和任何 加载的依赖项。初始化部分 .preinit_array, .init_array 和 .init 由链接编辑器在动态时创建 对象已构建。
运行时链接器执行地址包含在 .preinit_array 和 .init_array 部分。这些功能是 执行的顺序与它们的地址出现在 数组。
如果在没有 gcc 的情况下创建可执行文件,链接器似乎不会执行启动代码。我尝试编写自己的标准初始化例程,该例程读取 .init_array 部分中的函数指针并调用它们。它适用于一个文件,其中一个可以标记部分的结尾,例如,用零。但是对于多个文件,这个零可以重新定位在该部分的中间。如何正确确定由多个源文件组合而成的节的大小?
【问题讨论】:
-
gnu ld 默认链接器脚本确实在某些系统上自动提供符号
__init_array_start和__init_array_end,因此您也许可以使用它们。 YMMV。 -
@Jester,谢谢,这可能是公认的答案。
标签: linux assembly elf gnu-assembler