Our crtbegin.o has: [ 8] .ctors PROGBITS 00000000 000248 000004 00 A 0 0 4
whereas crtend.o has: [ 8] .ctors PROGBITS 00000000 000048 000004 00 WA 0 0 4 So in crtbegin.o the .ctors section is read-only while in crtend.o it is writable. Our current linker concatenates those sections as intended into a writable section in the output binary. But lld, the llvm linker, creates two separate sections, which causes the output binary to crash as the code that runs constructors doesn't encounter the sentinel from crtend.o. The Solaris linker exhibits the same behaviour. Turns out that the ELF spec actually suggests that lld is right here as the section flags are different. Therefore I think we should apply the following diff. ok? Index: lib/csu/crtbegin.c =================================================================== RCS file: /cvs/src/lib/csu/crtbegin.c,v retrieving revision 1.20 diff -u -p -r1.20 crtbegin.c --- lib/csu/crtbegin.c 10 Nov 2015 04:14:03 -0000 1.20 +++ lib/csu/crtbegin.c 21 Dec 2016 23:36:09 -0000 @@ -84,9 +84,9 @@ __asm(".hidden __dso_handle"); long __guard_local __dso_hidden __attribute__((section(".openbsd.randomdata"))); -static const init_f __CTOR_LIST__[1] +static init_f __CTOR_LIST__[1] __attribute__((section(".ctors"))) = { (void *)-1 }; /* XXX */ -static const init_f __DTOR_LIST__[1] +static init_f __DTOR_LIST__[1] __attribute__((section(".dtors"))) = { (void *)-1 }; /* XXX */ static void __dtors(void) __used;