The constructor and destructor tables are declared as arrays with one non-NULL element. Walking those until a NULL element is reached looks like out-of-bound accesses to newer compilers, and they turn the code into infinite loops (e.g. clang 3.8), because it is undefined behavior.
Use constructor/destructor calling code that should be legal in both the gcc and clang C dialect, to hopefully be immune from undefined behavior optimizations in the future. While there, clean up crtbegin.c and crtbegin.S a little and make them more similar. 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 1 Aug 2016 16:56:31 -0000 @@ -85,36 +85,37 @@ long __guard_local __dso_hidden __attrib static const init_f __CTOR_LIST__[1] - __attribute__((section(".ctors"))) = { (void *)-1 }; /* XXX */ + __used __attribute__((section(".ctors"))) = { (void *)-1 }; /* XXX */ static const init_f __DTOR_LIST__[1] - __attribute__((section(".dtors"))) = { (void *)-1 }; /* XXX */ + __used __attribute__((section(".dtors"))) = { (void *)-1 }; /* XXX */ + +extern const init_f ctor_list[] asm(".ctors"); +extern const init_f dtor_list[] asm(".dtors"); static void __dtors(void) __used; static void __ctors(void) __used; static void -__ctors() +__ctors(void) { - unsigned long i = (unsigned long) __CTOR_LIST__[0]; - const init_f *p; + int i; + + for (i = 0; ctor_list[i + 1] != NULL; i++) + continue; - if (i == -1) { - for (i = 1; __CTOR_LIST__[i] != NULL; i++) - ; + while (i > 0) { + ctor_list[i](); i--; } - p = __CTOR_LIST__ + i; - while (i--) - (**p--)(); } static void -__dtors() +__dtors(void) { - const init_f *p = __DTOR_LIST__ + 1; + int i; - while (*p) - (**p++)(); + for (i = 1; dtor_list[i] != NULL; i++) + dtor_list[i](); } void __init(void); @@ -130,8 +131,8 @@ MD_SECT_CALL_FUNC(".init", __do_init); MD_SECT_CALL_FUNC(".fini", __do_fini); -void -__do_init() +static void +__do_init(void) { static int initialized = 0; static struct dwarf2_eh_object object; @@ -146,14 +147,14 @@ __do_init() __register_frame_info(__EH_FRAME_BEGIN__, &object); if (__JCR_LIST__[0] && _Jv_RegisterClasses) _Jv_RegisterClasses(__JCR_LIST__); - (__ctors)(); + __ctors(); atexit(__fini); } } -void -__do_fini() +static void +__do_fini(void) { static int finalized = 0; @@ -162,7 +163,7 @@ __do_fini() /* * Call global destructors. */ - (__dtors)(); + __dtors(); } } Index: lib/csu/crtbeginS.c =================================================================== RCS file: /cvs/src/lib/csu/crtbeginS.c,v retrieving revision 1.16 diff -u -p -r1.16 crtbeginS.c --- lib/csu/crtbeginS.c 7 Apr 2015 01:27:06 -0000 1.16 +++ lib/csu/crtbeginS.c 1 Aug 2016 16:56:31 -0000 @@ -38,7 +38,6 @@ * constructors and destructors. The first element contains the * number of pointers in each. * The tables are also null-terminated. - */ #include <stdlib.h> @@ -96,39 +95,39 @@ asm(".hidden pthread_atfork\n .weak pthr static init_f __CTOR_LIST__[1] - __attribute__((section(".ctors"))) = { (void *)-1 }; /* XXX */ + __used __attribute__((section(".ctors"))) = { (void *)-1 }; /* XXX */ static init_f __DTOR_LIST__[1] - __attribute__((section(".dtors"))) = { (void *)-1 }; /* XXX */ + __used __attribute__((section(".dtors"))) = { (void *)-1 }; /* XXX */ + +extern const init_f ctor_list[] asm(".ctors"); +extern const init_f dtor_list[] asm(".dtors"); static void __dtors(void) __used; static void __ctors(void) __used; -void +static void __ctors(void) { - unsigned long i = (unsigned long) __CTOR_LIST__[0]; - init_f *p; + int i; - if (i == -1) { - for (i = 1; __CTOR_LIST__[i] != NULL; i++) - ; + for (i = 0; ctor_list[i + 1] != NULL; i++) + continue; + + while (i > 0) { + ctor_list[i](); i--; } - p = __CTOR_LIST__ + i; - while (i--) { - (**p--)(); - } } static void __dtors(void) { - init_f *p = __DTOR_LIST__ + 1; + int i; - while (*p) { - (**p++)(); - } + for (i = 1; dtor_list[i] != NULL; i++) + dtor_list[i](); } + void _init(void); void _fini(void); static void _do_init(void) __used; @@ -141,7 +140,7 @@ MD_SECTION_PROLOGUE(".fini", _fini); MD_SECT_CALL_FUNC(".init", _do_init); MD_SECT_CALL_FUNC(".fini", _do_fini); -void +static void _do_init(void) { static int initialized = 0; @@ -159,7 +158,7 @@ _do_init(void) } } -void +static void _do_fini(void) { static int finalized = 0;