Reputation: 97631
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?
__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 = .;
Upvotes: 1
Views: 622
Reputation: 213754
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?
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 the malloc
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:
Can I make function calls,
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.
assign structs
In C
, at best, this is a few instructions. At worst, this is a call to memcpy
or memset
. That should be safe.
use array initializers.
This is just a special case of struct assignment, so should be safe.
Upvotes: 1