I'm using the Gnu Arm Embedded Toolchain and I'm writing a custom linker file for a project. I'm writing custom startup/initialization code too. The project uses lots of C++ code, in addition to C and some assembler.
I'm looking for documentation related to the linker sections that handles initialization:
- .preinit_array
- .init
- .init_array
- .ctors
- ...
Mostly, I've found blogs and various posts on the web. But it still leaves me with lots of open questions.
I have made global initialization work (at least the cases I can come up with) by using only the .init_array section but there are many details I'd like to get on top of in order to know that I've covered everything.
For example (see the snippet below):
- What exactly is each section used for? When are they output by the compiler?
- I've read the source code for
__libc_init_array(for inspiration) and that one calls a function called_init()in between handling the.preinit_arrayand the.init_arraysections. Where does this_init()function come from? - What's the purpose of the
.ctorssection? I must admit I don't understand the comment. - What's the purpose of the crtbegin.o and similar files?
- What's does
CONSTRUCTORSmean in the .data section? - ...
Everything related to tear-down can be skipped for now. It's not relevant for this project.
Here are the relevant sections from the default linker script of my GCC installation, if that helps the discussion:
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.data :
{
__data_start = .;
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
Any input is welcome! Thanks in advance.