#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. */
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;
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;
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)
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. */
#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
(*(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 */
#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
#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)
{
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; )
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
_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
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;
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 (;;)
{
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;
}
/* 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;
}
{
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
/* 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. */
/* 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. */
{
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
/* 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. */
/* 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. */