I want to run some code before main
begins, and before constructors for static variables run. I can do with with code like this (ideone)
extern "C" {
static void do_my_pre_init(void) {
// something
}
__attribute__ ((section (".preinit_array"))) void(*p_init)(void) = &do_my_pre_init;
}
Are there any language features that will not work correctly when executed in this function, due to _init
and .init_array
not yet having been executed?
Or is it only user code that should be hooking into this mechanism?
Some background on __libc_init_array
The source for a typical __libc_init_array
is something like:
static void __libc_init_array() {
size_t count, i;
count = __preinit_array_end - __preinit_array_start;
for (i = 0; i < count; i++)
__preinit_array_start[i]();
_init();
count = __init_array_end - __init_array_start;
for (i = 0; i < count; i++)
__init_array_start[i]();
}
Where the __...
symbols come from a linker script containing
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
This question is impossible to answer in general, because the language itself has no concept of
.preinit_array
, or_init
, or.init_array
. All of these concepts are implementation details for a particular system.In reality, you aren't guaranteed to have anything work at all. Things as simple as
malloc
may not work (e.g. because themalloc
subsystem itself may be using.preinit_array
to initialize itself).In practice, using dynamic linking on a GLIBC-based platform most everything will work (because
libc.so.6
initializes itself long before the first instruction of the main executable runs).For fully-static executable, all bets are off.
For non-GLIBC platform, you'll need to look into specifics of that platform (and you are very unlikely to find any guarantees).
Update:
Function calls need no setup with fully-static linking, and need dynamic loader to have initialized in dynamic linking case. No dynamic loader will start executing code in the application before it has fully initialized itself, so function calls should be safe.
In
C
, at best, this is a few instructions. At worst, this is a call tomemcpy
ormemset
. That should be safe.This is just a special case of struct assignment, so should be safe.