This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Use .init_arrat/.fini_array if available


On Sat, Mar 19, 2005 at 02:25:50PM -0500, Daniel Jacobowitz wrote:
> The expected output for tst-array1 is:
> 
> preinit array 0
> preinit array 1
> preinit array 2
> init
> init array 0
> init array 1
> init array 2
> fini array 2
> fini array 1
> fini array 0
> fini
> 
> The way this normally works is that .preinit_array is run first; then
> DT_INIT, then .init_array, then .fini_array.  GCC puts a call to
> __do_global_ctors_aux in _init, which calls the __attribute__((constructor))
> functions.
> 
> I'm working on an ARM EABI port.  It's configured to not use the .ctors
> section at all; __attribute__((constructor)) entries are placed in
> .init_array.  This is mandated by the ABI.  This means that init()
> is placed into .init_array; exactly where in .init_array depends on
> optimization and -funit-at-a-time settings.  So we get this output instead:
> 
> preinit array 0
> preinit array 1
> preinit array 2
> init array 0
> init array 1
> init array 2
> init
> fini
> fini array 2
> fini array 1
> fini array 0
> 
> As far as I can tell, this is a conforming implementation of
> __attribute__((constructor)); even a desirable one.  Any suggestions on how
> to adapt the tests for this implementation?
> 

This is the patch for gcc 3.4. It is very similar to Linux/ia64 port,
which is in assembly. It works for me. Glibc calls functions in
.init_array like main ().  That is what INIT_ARRAY_LIKE_MAIN is used
for. Linux developers can take advantage of it. I haven't come up with
a better way to check it.


H.J.
------
2005-03-18  H.J. Lu  <hongjiu.lu@intel.com>

	* config/linux.h (INIT_ARRAY_LIKE_MAIN): Defined.

	* crtstuff.c: If HAVE_INITFINI_ARRAY is defined, use
	.init_array/.fini_array sections instead of .init/.fini
	sections.

--- gcc/config/linux.h.array	2003-12-03 09:43:14.000000000 -0800
+++ gcc/config/linux.h	2005-03-16 17:48:41.000000000 -0800
@@ -124,3 +124,6 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 #define TARGET_HAS_F_SETLKW
+
+/* Linux passes (argc, argv, envp) to functions in .init_array.  */
+#define INIT_ARRAY_LIKE_MAIN
--- gcc/crtstuff.c.array	2004-10-14 11:17:55.000000000 -0700
+++ gcc/crtstuff.c	2005-03-18 15:18:42.987973674 -0800
@@ -80,6 +80,21 @@ call_ ## FUNC (void)					\
 }
 #endif
 
+#ifndef HAVE_GAS_HIDDEN
+/* __do_global_ctors_aux in crtend.o. But it will be called from
+  crtbegin.o. It has to be hidden.  */
+#undef HAVE_INITFINI_ARRAY
+#endif
+
+/* Make sure that we don't use CRT_CALL_STATIC_FUNCTION by accident.  */
+#ifdef HAVE_INITFINI_ARRAY
+# undef CRT_CALL_STATIC_FUNCTION
+# undef INIT_SECTION_ASM_OP
+# define INIT_SECTION_ASM_OP
+# else
+# undef INIT_ARRAY_LIKE_MAIN
+#endif
+
 #if defined(OBJECT_FORMAT_ELF) && defined(HAVE_LD_EH_FRAME_HDR) \
     && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
     && defined(__GLIBC__) && __GLIBC__ >= 2
@@ -138,6 +153,11 @@ extern void _Jv_RegisterClasses (void *)
 
 /*  Declare a pointer to void function type.  */
 typedef void (*func_ptr) (void);
+#ifdef INIT_ARRAY_LIKE_MAIN
+typedef void (*ctors_ptr) (int, char **, char **);
+#else
+typedef void (*ctors_ptr) (void);
+#endif
 #define STATIC static
 
 #else  /* OBJECT_FORMAT_ELF */
@@ -169,15 +189,15 @@ CTOR_LIST_BEGIN;
 #elif defined(CTORS_SECTION_ASM_OP)
 /* Hack: force cc1 to switch to .data section early, so that assembling
    __CTOR_LIST__ does not undo our behind-the-back change to .ctors.  */
-static func_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
+static ctors_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
 asm (CTORS_SECTION_ASM_OP);
-STATIC func_ptr __CTOR_LIST__[1]
-  __attribute__ ((__unused__, aligned(sizeof(func_ptr))))
-  = { (func_ptr) (-1) };
+STATIC ctors_ptr __CTOR_LIST__[1]
+  __attribute__ ((__unused__, aligned(sizeof(ctors_ptr))))
+  = { (ctors_ptr) (-1) };
 #else
-STATIC func_ptr __CTOR_LIST__[1]
-  __attribute__ ((__unused__, section(".ctors"), aligned(sizeof(func_ptr))))
-  = { (func_ptr) (-1) };
+STATIC ctors_ptr __CTOR_LIST__[1]
+  __attribute__ ((__unused__, section(".ctors"), aligned(sizeof(ctors_ptr))))
+  = { (ctors_ptr) (-1) };
 #endif /* __CTOR_LIST__ alternatives */
 
 #ifdef DTOR_LIST_BEGIN
@@ -287,8 +307,23 @@ __do_global_dtors_aux (void)
   completed = 1;
 }
 
+#ifdef HAVE_INITFINI_ARRAY
+extern ctors_ptr __do_global_ctors_aux
+  __attribute__ ((__visibility__ ("hidden")));
+static const ctors_ptr __do_global_ctors_aux_array []
+  __attribute__ ((used, section (".init_array"), aligned (sizeof (ctors_ptr)))) =
+{
+  &__do_global_ctors_aux
+};
+static const func_ptr __do_global_dtors_aux_array []
+  __attribute__ ((used, section (".fini_array"), aligned (sizeof (func_ptr)))) =
+{
+  &__do_global_dtors_aux
+};
+#else
 /* Stick a call to __do_global_dtors_aux into the .fini section.  */
 CRT_CALL_STATIC_FUNCTION (FINI_SECTION_ASM_OP, __do_global_dtors_aux)
+#endif
 
 #if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
 /* Stick a call to __register_frame_info into the .init section.  For some
@@ -317,7 +352,15 @@ frame_dummy (void)
 #endif /* JCR_SECTION_NAME */
 }
 
+#ifdef HAVE_INITFINI_ARRAY
+static const func_ptr frame_dummy_array []
+  __attribute__ ((used, section (".init_array"), aligned (sizeof (func_ptr)))) =
+{
+  &frame_dummy
+};
+#else
 CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, frame_dummy)
+#endif
 #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
 
 #else  /* OBJECT_FORMAT_ELF */
@@ -418,15 +461,15 @@ CTOR_LIST_END;
 #elif defined(CTORS_SECTION_ASM_OP)
 /* Hack: force cc1 to switch to .data section early, so that assembling
    __CTOR_LIST__ does not undo our behind-the-back change to .ctors.  */
-static func_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
+static ctors_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
 asm (CTORS_SECTION_ASM_OP);
-STATIC func_ptr __CTOR_END__[1]
-  __attribute__((aligned(sizeof(func_ptr))))
-  = { (func_ptr) 0 };
+STATIC ctors_ptr __CTOR_END__[1]
+  __attribute__((aligned(sizeof(ctors_ptr))))
+  = { (ctors_ptr) 0 };
 #else
-STATIC func_ptr __CTOR_END__[1]
-  __attribute__((section(".ctors"), aligned(sizeof(func_ptr))))
-  = { (func_ptr) 0 };
+STATIC ctors_ptr __CTOR_END__[1]
+  __attribute__((section(".ctors"), aligned(sizeof(ctors_ptr))))
+  = { (ctors_ptr) 0 };
 #endif
 
 #ifdef DTOR_LIST_END
@@ -471,16 +514,30 @@ STATIC void *__JCR_END__[1] 
 #ifdef INIT_SECTION_ASM_OP
 
 #ifdef OBJECT_FORMAT_ELF
+#ifdef HAVE_INITFINI_ARRAY
+void __attribute__ ((__visibility__ ("hidden")))
+#else
 static void __attribute__((used))
+#endif
+#ifdef INIT_ARRAY_LIKE_MAIN
+__do_global_ctors_aux (int argc, char *argv[], char *envp[])
+#else
 __do_global_ctors_aux (void)
+#endif
 {
-  func_ptr *p;
-  for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+  ctors_ptr *p;
+  for (p = __CTOR_END__ - 1; *p != (ctors_ptr) -1; p--)
+#ifdef INIT_ARRAY_LIKE_MAIN
+    (*p) (argc, argv, envp);
+#else
     (*p) ();
+#endif
 }
 
+#ifndef HAVE_INITFINI_ARRAY
 /* Stick a call to __do_global_ctors_aux into the .init section.  */
 CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_ctors_aux)
+#endif
 #else  /* OBJECT_FORMAT_ELF */
 
 /* Stick the real initialization code, followed by a normal sort of
@@ -527,11 +584,11 @@ extern void __do_global_ctors (void);
 void
 __do_global_ctors (void)
 {
-  func_ptr *p;
+  ctors_ptr *p;
 #if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
   __do_global_ctors_1();
 #endif
-  for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+  for (p = __CTOR_END__ - 1; *p != (ctors_ptr) -1; p--)
     (*p) ();
 }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]