changeset 3291:68c8985fd5f0

* src/synth.ld src/synth_entry.c: Look for static constructors in the .init_array section as well as .ctors (needed for gcc 4.7 and later)
author jlarmour
date Fri, 03 Oct 2014 15:13:21 +0000
parents a1df75458e13
children 7f8e529b4d82
files packages/hal/synth/arch/current/ChangeLog packages/hal/synth/arch/current/src/synth.ld packages/hal/synth/arch/current/src/synth_entry.c
diffstat 3 files changed, 35 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/packages/hal/synth/arch/current/ChangeLog
+++ b/packages/hal/synth/arch/current/ChangeLog
@@ -1,3 +1,9 @@
+2014-10-01  Ross Younger  <wry@ecoscentric.com>
+
+	* src/synth.ld src/synth_entry.c: Look for static constructors in
+	the .init_array section as well as .ctors (needed for gcc 4.7 and
+	later)
+
 2011-08-13  Sergei Gavrikov  <sergei.gavrikov@gmail.com>
 
 	* cdl/hal_synth.cdl (CYGPKG_HAL_SYNTH_TESTS): Fix a typo in make rule.
--- a/packages/hal/synth/arch/current/src/synth.ld
+++ b/packages/hal/synth/arch/current/src/synth.ld
@@ -197,6 +197,9 @@ GROUP(libtarget.a libgcc.a)
       KEEP(*(SORT(.ctors*))) __CTOR_END__ = ABSOLUTE(.);                        \
      __DTOR_LIST__ = ABSOLUTE(.);                                            	\
        KEEP(*(SORT(.dtors*))) __DTOR_END__ = ABSOLUTE(.);                    	\
+      /* In gcc 4.7, constructors moved from .ctors to .init_array . */         \
+     . = ALIGN(8); __init_array_start__ = ABSOLUTE(.);                          \
+      KEEP(*(SORT(.init_array*))) __init_array_end__ = ABSOLUTE(.);             \
     . = ALIGN(32);                                                              \
     KEEP(*( SORT (.ecos.table.*)));                                             \
     _GOT2_START_ = ABSOLUTE(.); *(.got2) _GOT2_END_ = ABSOLUTE(.);              \
--- a/packages/hal/synth/arch/current/src/synth_entry.c
+++ b/packages/hal/synth/arch/current/src/synth_entry.c
@@ -68,10 +68,27 @@ cyg_bool cyg_hal_stop_constructors;
 typedef void (*pfunc) (void);
 extern pfunc __CTOR_LIST__[];
 extern pfunc __CTOR_END__[];
+extern pfunc __init_array_start__[];
+extern pfunc __init_array_end__[];
 
 void
 cyg_hal_invoke_constructors (void)
 {
+    /* Note: We appear to be running the constructors twice here, but
+     * this is not actually the case.
+     * gcc 4.7 changed the way static constructors are linked:
+     * - Prior to gcc 4.7, they appeared in the .ctors section of the
+     *   ELF * image.
+     * - Since gcc 4.7, they moved to .init_array and in the reverse
+     *   order.
+     *
+     * For us to look for both (both here and in synth.ld) is harmless,
+     * because the constructors are only linked once, and we are not
+     * too worried about squeezing every last byte of code size out of
+     * the synth target.
+     *
+     * - wry, 2014-10-01
+     */
 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
     static pfunc *p = &__CTOR_END__[-1];
     
@@ -83,11 +100,20 @@ cyg_hal_invoke_constructors (void)
             break;
         }
     }
+    for (p = &__init_array_start__[0]; p != (__init_array_end__); p++) {
+        (*p) ();
+        if (cyg_hal_stop_constructors) {
+            p++;
+            break;
+        }
+    }
 #else
     pfunc *p;
 
     for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--)
         (*p) ();
+    for (p = &__init_array_start__[0]; p != (__init_array_end__); p++)
+        (*p) ();
 #endif
 }