Using ".init_array" section of ELF file

Viewed 5183

When there is a need to run a piece of code on the program startup (on Linux), how to use correctly the .init_section of an executable file (ELF32-i386)? I have the following code (GNU Assembler) which has ctor initialization function, and the address of this function is placed inside .init_array section:

.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

This code is assembled with:

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

When the resulting executable is run, only the "Main code" string is printed. How to use properly the .init_array section?

EDIT1: I want to use .init_array because there are multiple source files with their own init code. One can call all this code 'manually' on startup and modify it every time when source files are added to or removed from the project, but .init_array seems to be designed just for this case :

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.

In case when an executable is created without gcc, the linker seems to not execute the startup code. I tried to write my own standard init routine which reads function pointers in .init_array, section and calls them. It works OK for one file, where one can mark the end of the section, for example, with zero. But with multiple files this zero can be relocated in the middle of the section. How can one correctly determine the size of a section assembled from multiple source files?

2 Answers

For normal C programs the .init_array is traversed by a function that is called from _start before main gets called. A good description is on this site.

So I see two ways: You can simply link against the glibc start code. Or you have to find out another mechanism to solve this issue by yourself.

Related