OSDN Git Service

* libgcc2.c (__do_global_ctors): Call atexit with one arg.
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
index 53dfdbf..a27caa3 100644 (file)
@@ -53,10 +53,6 @@ Boston, MA 02111-1307, USA.  */
 #undef abort
 #endif
 
-#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
-#define WEAK_ALIAS
-#endif
-
 /* In a cross-compilation situation, default to inhibiting compilation
    of routines that use libc.  */
 
@@ -1709,11 +1705,9 @@ __bb_init_func (struct bb *blocks)
   if (blocks->zero_word)
     return;
 
-#ifdef ON_EXIT
   /* Initialize destructor.  */
   if (!bb_head)
-    ON_EXIT (__bb_exit_func, 0);
-#endif
+    atexit (__bb_exit_func);
 
   /* Set up linked list.  */
   blocks->zero_word = 1;
@@ -2077,17 +2071,15 @@ found:        ;
 static void
 __bb_init_prg ()
 {
-
   FILE *file;
   char buf[BBINBUFSIZE];
   const char *p;
   const char *pos;
   enum bb_func_mode m;
+  int i;
 
-#ifdef ON_EXIT
   /* Initialize destructor.  */
-  ON_EXIT (__bb_exit_func, 0);
-#endif
+  atexit (__bb_exit_func);
 
   if (!(file = fopen ("bb.in", "r")))
     return;
@@ -2164,7 +2156,10 @@ __bb_init_prg ()
       bb_hashbuckets = (struct bb_edge **) 
                    malloc (BB_BUCKETS * sizeof (struct bb_edge *));
       if (bb_hashbuckets)
-        memset (bb_hashbuckets, 0, BB_BUCKETS * sizeof (struct bb_edge *));
+       /* Use a loop here rather than calling bzero to avoid having to
+          conditionalize its existance.  */
+       for (i = 0; i < BB_BUCKETS; i++)
+         bb_hashbuckets[i] = 0;
     }
 
   if (bb_mode & 12)
@@ -2173,11 +2168,8 @@ __bb_init_prg ()
       bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
     }
 
-#ifdef ON_EXIT
-      /* Initialize destructor.  */
-      ON_EXIT (__bb_exit_trace_func, 0);
-#endif
-
+  /* Initialize destructor.  */
+  atexit (__bb_exit_trace_func);
 }
 
 /* Called upon entering a basic block.  */
@@ -2833,6 +2825,15 @@ cacheflush (char *beg, int size, int flag)
 #endif
 
 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
+
+/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
+   code to run constructors.  In that case, we need to handle EH here, too.  */
+
+#ifdef EH_FRAME_SECTION
+#include "frame.h"
+extern unsigned char __EH_FRAME_BEGIN__[];
+#endif
+
 /* Run all the global destructors on exit from the program.  */
 
 void
@@ -2848,28 +2849,26 @@ __do_global_dtors ()
       (*(p-1)) ();
     }
 #endif
+#ifdef EH_FRAME_SECTION
+  __deregister_frame_info (__EH_FRAME_BEGIN__);
+#endif
 }
 #endif
 
 #ifndef HAS_INIT_SECTION
 /* Run all the global constructors on entry to the program.  */
 
-#ifndef ON_EXIT
-#define ON_EXIT(a, b)
-#else
-/* Make sure the exit routine is pulled in to define the globals as
-   bss symbols, just in case the linker does not automatically pull
-   bss definitions from the library.  */
-
-extern int _exit_dummy_decl;
-int *_exit_dummy_ref = &_exit_dummy_decl;
-#endif /* ON_EXIT */
-
 void
 __do_global_ctors ()
 {
+#ifdef EH_FRAME_SECTION
+  {
+    static struct object object;
+    __register_frame_info (__EH_FRAME_BEGIN__, &object);
+  }
+#endif
   DO_GLOBAL_CTORS_BODY;
-  ON_EXIT (__do_global_dtors, 0);
+  atexit (__do_global_dtors);
 }
 #endif /* no HAS_INIT_SECTION */
 
@@ -2903,17 +2902,26 @@ SYMBOL__MAIN ()
 #include "gbl-ctors.h"
 
 /* Provide default definitions for the lists of constructors and
-   destructors, so that we don't get linker errors.  
-
-   The old code sometimes put these into the data segment and sometimes
-   into the bss segment.  Putting these into the data segment should always
-   work and avoids a little bit of complexity.  */
+   destructors, so that we don't get linker errors.  These symbols are
+   intentionally bss symbols, so that gld and/or collect will provide
+   the right values.  */
 
 /* We declare the lists here with two elements each,
-   so that they are valid empty lists if no other definition is loaded.  */
+   so that they are valid empty lists if no other definition is loaded.
+
+   If we are using the old "set" extensions to have the gnu linker
+   collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
+   must be in the bss/common section.
+
+   Long term no port should use those extensions.  But many still do.  */
 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
+#if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
 func_ptr __CTOR_LIST__[2] = {0, 0};
 func_ptr __DTOR_LIST__[2] = {0, 0};
+#else
+func_ptr __CTOR_LIST__[2];
+func_ptr __DTOR_LIST__[2];
+#endif
 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
 #endif /* L_ctors */
 \f
@@ -2922,22 +2930,17 @@ func_ptr __DTOR_LIST__[2] = {0, 0};
 #include "gbl-ctors.h"
 
 #ifdef NEED_ATEXIT
-# ifdef ON_EXIT
-#  undef ON_EXIT
-# endif
-int _exit_dummy_decl = 0;      /* prevent compiler & linker warnings */
-#endif
 
-#ifndef ON_EXIT
+#ifndef HAVE_ON_EXIT
 
-#ifdef NEED_ATEXIT
 # include <errno.h>
 
 static func_ptr *atexit_chain = 0;
 static long atexit_chain_length = 0;
 static volatile long last_atexit_chain_slot = -1;
 
-int atexit (func_ptr func)
+int
+atexit (func_ptr func)
 {
   if (++last_atexit_chain_slot == atexit_chain_length)
     {
@@ -2959,22 +2962,13 @@ int atexit (func_ptr func)
   atexit_chain[last_atexit_chain_slot] = func;
   return (0);
 }
-#endif /* NEED_ATEXIT */
-
-/* If we have no known way of registering our own __do_global_dtors
-   routine so that it will be invoked at program exit time, then we
-   have to define our own exit routine which will get this to happen.  */
 
-extern void __do_global_dtors ();
-extern void __bb_exit_func ();
 extern void _cleanup ();
 extern void _exit () __attribute__ ((noreturn));
 
 void 
 exit (int status)
 {
-#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
-#ifdef NEED_ATEXIT
   if (atexit_chain)
     {
       for ( ; last_atexit_chain_slot-- >= 0; )
@@ -2985,19 +2979,6 @@ exit (int status)
       free (atexit_chain);
       atexit_chain = 0;
     }
-#else /* No NEED_ATEXIT */
-  __do_global_dtors ();
-#endif /* No NEED_ATEXIT */
-#endif /* !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF) */
-/* In gbl-ctors.h, ON_EXIT is defined if HAVE_ATEXIT is defined.  In
-   __bb_init_func and _bb_init_prg, __bb_exit_func is registered with
-   ON_EXIT if ON_EXIT is defined.  Thus we must not call __bb_exit_func here
-   if HAVE_ATEXIT is defined. */
-#ifndef HAVE_ATEXIT
-#ifndef inhibit_libc
-  __bb_exit_func ();
-#endif
-#endif /* !HAVE_ATEXIT */
 #ifdef EXIT_BODY
   EXIT_BODY;
 #else
@@ -3006,17 +2987,17 @@ exit (int status)
   _exit (status);
 }
 
-#else /* ON_EXIT defined */
-int _exit_dummy_decl = 0;      /* prevent compiler & linker warnings */
+#else /* HAVE_ON_EXIT */
 
-# ifndef HAVE_ATEXIT
-/* Provide a fake for atexit() using ON_EXIT.  */
-int atexit (func_ptr func)
+/* Simple; we just need a wrapper for ON_EXIT.  */
+int
+atexit (func_ptr func)
 {
-  return ON_EXIT (func, NULL);
+  return ON_EXIT (func);
 }
-# endif /* HAVE_ATEXIT */
-#endif /* ON_EXIT defined */
+
+#endif /* HAVE_ON_EXIT */
+#endif /* NEED_ATEXIT */
 
 #endif /* L_exit */
 \f
@@ -3692,16 +3673,21 @@ __unwinding_cleanup ()
    for a dummy call to a routine __unwinding_cleanup() when there are nothing
    but cleanups remaining. This allows a debugger to examine the state
    at which the throw was executed, before any cleanups, rather than
-   at the terminate point after the stack has been unwound. */
+   at the terminate point after the stack has been unwound.
+
+   EH is the current eh_context structure.
+   PC is the address of the call to __throw.
+   MY_UDATA is the unwind information for __throw.
+   OFFSET_P is where we return the SP adjustment offset.  */
 
 static void *
-throw_helper (eh, pc, my_udata, udata_p)
+throw_helper (eh, pc, my_udata, offset_p)
      struct eh_context *eh;
      void *pc;
      frame_state *my_udata;
-     frame_state **udata_p;
+     long *offset_p;
 {
-  frame_state *udata = *udata_p;
+  frame_state ustruct2, *udata = &ustruct2;
   frame_state ustruct;
   frame_state *sub_udata = &ustruct;
   void *saved_pc = pc;
@@ -3714,12 +3700,15 @@ throw_helper (eh, pc, my_udata, udata_p)
   int only_cleanup = 0;
   int rethrow = 0;
   int saved_state = 0;
+  long args_size;
   __eh_info *eh_info = (__eh_info *)eh->info;
 
   /* Do we find a handler based on a re-throw PC? */
   if (eh->table_index != (void *) 0)
     rethrow = 1;
 
+  memcpy (udata, my_udata, sizeof (*udata));
+
   handler = (void *) 0;
   for (;;)
     { 
@@ -3795,6 +3784,8 @@ throw_helper (eh, pc, my_udata, udata_p)
 
   eh->handler_label = handler;
 
+  args_size = udata->args_size;
+
   if (pc == saved_pc)
     /* We found a handler in the throw context, no need to unwind.  */
     udata = my_udata;
@@ -3847,7 +3838,17 @@ throw_helper (eh, pc, my_udata, udata_p)
     }
   /* udata now refers to the frame called by the handler frame.  */
 
-  *udata_p = udata;
+  /* We adjust SP by the difference between __throw's CFA and the CFA for
+     the frame called by the handler frame, because those CFAs correspond
+     to the SP values at the two call sites.  We need to further adjust by
+     the args_size of the handler frame itself to get the handler frame's
+     SP from before the args were pushed for that call.  */
+#ifdef STACK_GROWS_DOWNWARD
+  *offset_p = udata->cfa - my_udata->cfa + args_size;
+#else
+  *offset_p = my_udata->cfa - udata->cfa - args_size;
+#endif
+                      
   return handler;
 }
 
@@ -3867,8 +3868,10 @@ __throw ()
 {
   struct eh_context *eh = (*get_eh_context) ();
   void *pc, *handler;
-  frame_state ustruct;
-  frame_state *udata = &ustruct;
+  long offset;
+
+  /* XXX maybe make my_ustruct static so we don't have to look it up for
+     each throw.  */
   frame_state my_ustruct, *my_udata = &my_ustruct;
 
   /* This is required for C++ semantics.  We must call terminate if we
@@ -3879,14 +3882,12 @@ __throw ()
     
   /* Start at our stack frame.  */
 label:
-  udata = __frame_state_for (&&label, udata);
-  if (! udata)
+  my_udata = __frame_state_for (&&label, my_udata);
+  if (! my_udata)
     __terminate ();
 
   /* We need to get the value from the CFA register. */
-  udata->cfa = __builtin_dwarf_cfa ();
-
-  memcpy (my_udata, udata, sizeof (*udata));
+  my_udata->cfa = __builtin_dwarf_cfa ();
 
   /* Do any necessary initialization to access arbitrary stack frames.
      On the SPARC, this means flushing the register windows.  */
@@ -3895,17 +3896,11 @@ label:
   /* Now reset pc to the right throw point.  */
   pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
 
-  handler = throw_helper (eh, pc, my_udata, &udata);
+  handler = throw_helper (eh, pc, my_udata, &offset);
 
   /* Now go!  */
 
-  __builtin_eh_return ((void *)eh,
-#ifdef STACK_GROWS_DOWNWARD
-                      udata->cfa - my_udata->cfa,
-#else
-                      my_udata->cfa - udata->cfa,
-#endif
-                      handler);
+  __builtin_eh_return ((void *)eh, offset, handler);
 
   /* Epilogue:  restore the handler frame's register values and return
      to the stub.  */
@@ -3919,8 +3914,10 @@ __rethrow (index)
 {
   struct eh_context *eh = (*get_eh_context) ();
   void *pc, *handler;
-  frame_state ustruct;
-  frame_state *udata = &ustruct;
+  long offset;
+
+  /* XXX maybe make my_ustruct static so we don't have to look it up for
+     each throw.  */
   frame_state my_ustruct, *my_udata = &my_ustruct;
 
   /* This is required for C++ semantics.  We must call terminate if we
@@ -3936,14 +3933,12 @@ __rethrow (index)
     
   /* Start at our stack frame.  */
 label:
-  udata = __frame_state_for (&&label, udata);
-  if (! udata)
+  my_udata = __frame_state_for (&&label, my_udata);
+  if (! my_udata)
     __terminate ();
 
   /* We need to get the value from the CFA register. */
-  udata->cfa = __builtin_dwarf_cfa ();
-
-  memcpy (my_udata, udata, sizeof (*udata));
+  my_udata->cfa = __builtin_dwarf_cfa ();
 
   /* Do any necessary initialization to access arbitrary stack frames.
      On the SPARC, this means flushing the register windows.  */
@@ -3952,17 +3947,11 @@ label:
   /* Now reset pc to the right throw point.  */
   pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
 
-  handler = throw_helper (eh, pc, my_udata, &udata);
+  handler = throw_helper (eh, pc, my_udata, &offset);
 
   /* Now go!  */
 
-  __builtin_eh_return ((void *)eh,
-#ifdef STACK_GROWS_DOWNWARD
-                      udata->cfa - my_udata->cfa,
-#else
-                      my_udata->cfa - udata->cfa,
-#endif
-                      handler);
+  __builtin_eh_return ((void *)eh, offset, handler);
 
   /* Epilogue:  restore the handler frame's register values and return
      to the stub.  */