crt: Unify and simplify handling of constructor/destructor lists
GNU binutils ld traditionally provides __CTOR_LIST__ and __DTOR_LIST__
symbols via a linker script, while lld doesn't.
Due to this, we previously provided our own copy of these symbols while
building with clang (assuming that means we'd be linking with lld), see
1e81200e88f.
In an attempt to unify things, binutils 2.30 changed the linker script
to conditionally provide these symbols, in case they were undefined,
but otherwise prefer the ones provided by object files linked in.
This attempt failed though (and was reverted for binutils 2.31), since
libgcc turned out to contain dummy fallback symbols named __CTOR_LIST__
and __DTOR_LIST__, without any section assignments, meaning they weren't
actually sorted by the linker along with any of the constructors to be
called.
In order to unify and simplify things, always provide our own version
of these symbols. When using a binutils version other than 2.30, that
always unconditionally provides its own __CTOR_LIST__/__DTOR_LIST__
symbols, this doesn't result in a conflict with multiply defined symbols,
but ld just silently uses the symbol it provided via the linker script,
but retains the data provided from the object files. (Tested with
binutils 2.22, 2.26 and 2.30.)
In such a case, the list between __CTOR_LIST__ and __CTOR_END__ will
contain one extra (func_ptr)-1 entry at the start, the one provided by
code (and one extra, for our purposes harmless, null terminator at the
end).
By always providing our own, and adapting the code for iterating the
lists to cope with a stray extra sentinel in the list, we can use the
same logic for all cases of both binutils ld and lld, including the
previously broken binutils 2.30.
Signed-off-by: Martin Storsjö <martin@martin.st>
3 files changed