I noticed that lld handles __init_array{start, end} incorrectly.
GNU ld
% objdump -t ./ld | grep init_array
00000000010cc000 l .ctors 0000000000000000 .hidden
init_array_end
00000000010cc000 l .ctors 0000000000000000 .hidden
__init_array_start
lld
% objdump -t ./bin/lld |grep init_array
0000000000000000 g O *ABS* 0000000000000000 init_array_start
0000000000000000 g O *ABS* 0000000000000000 __init_array_end
This patch is an attempt to fix.
If you agree with the approach, I'll change fini_array and preinit_array as well, and add tests.
It would be nice to add a class LinkerDefinedAtoms, that you can use for the purpose. It would simplify / remove extraneous code.
Another thing apart from visibility that lld doesnot currently do is the symbols get added for executables all the time, even there is no init_array section.