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;

Reply via email to