summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cc/libgcc/libgcc2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cc/libgcc/libgcc2.c')
-rw-r--r--gnu/usr.bin/cc/libgcc/libgcc2.c178
1 files changed, 163 insertions, 15 deletions
diff --git a/gnu/usr.bin/cc/libgcc/libgcc2.c b/gnu/usr.bin/cc/libgcc/libgcc2.c
index fc2e1ac..63a7114 100644
--- a/gnu/usr.bin/cc/libgcc/libgcc2.c
+++ b/gnu/usr.bin/cc/libgcc/libgcc2.c
@@ -1428,6 +1428,7 @@ BLOCK_PROFILER_CODE
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
+char *ctime ();
#ifdef HAVE_ATEXIT
extern void atexit (void (*) (void));
@@ -1995,21 +1996,9 @@ __do_global_dtors ()
#ifdef DO_GLOBAL_DTORS_BODY
DO_GLOBAL_DTORS_BODY;
#else
- unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
- unsigned i;
-
- /* Some systems place the number of pointers
- in the first word of the table.
- On other systems, that word is -1.
- In all cases, the table is null-terminated. */
-
- /* If the length is not recorded, count up to the null. */
- if (nptrs == -1)
- for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
-
- /* GNU LD format. */
- for (i = nptrs; i >= 1; i--)
- __DTOR_LIST__[i] ();
+ func_ptr *p;
+ for (p = __DTOR_LIST__ + 1; *p; )
+ (*p++) ();
#endif
}
@@ -2149,3 +2138,162 @@ func_ptr __CTOR_LIST__[2];
#include "gbl-ctors.h"
func_ptr __DTOR_LIST__[2];
#endif
+
+#ifdef L_eh
+typedef struct {
+ void *start;
+ void *end;
+ void *exception_handler;
+} exception_table;
+
+struct exception_table_node {
+ exception_table *table;
+ void *start;
+ void *end;
+ struct exception_table_node *next;
+};
+
+static int except_table_pos = 0;
+static void *except_pc = (void *)0;
+static struct exception_table_node *exception_table_list = 0;
+
+static exception_table *
+find_exception_table (pc)
+ void* pc;
+{
+ register struct exception_table_node *table = exception_table_list;
+ for ( ; table != 0; table = table->next)
+ {
+ if (table->start <= pc && table->end > pc)
+ return table->table;
+ }
+ return 0;
+}
+
+/* this routine takes a pc, and the address of the exception handler associated
+ with the closest exception table handler entry associated with that PC,
+ or 0 if there are no table entries the PC fits in. The algorithm works
+ something like this:
+
+ while(current_entry exists) {
+ if(current_entry.start < pc )
+ current_entry = next_entry;
+ else {
+ if(prev_entry.start <= pc && prev_entry.end > pc) {
+ save pointer to prev_entry;
+ return prev_entry.exception_handler;
+ }
+ else return 0;
+ }
+ }
+ return 0;
+
+ Assuming a correctly sorted table (ascending order) this routine should
+ return the tighest match...
+
+ In the advent of a tie, we have to give the last entry, as it represents
+ an inner block.
+ */
+
+
+void *
+__find_first_exception_table_match(pc)
+void *pc;
+{
+ exception_table *table = find_exception_table (pc);
+ int pos = 0;
+ int best = 0;
+ if (table == 0)
+ return (void*)0;
+#if 0
+ printf("find_first_exception_table_match(): pc = %x!\n",pc);
+#endif
+
+ except_pc = pc;
+
+#if 0
+ /* We can't do this yet, as we don't know that the table is sorted. */
+ do {
+ ++pos;
+ if (table[pos].start > except_pc)
+ /* found the first table[pos].start > except_pc, so the previous
+ entry better be the one we want! */
+ break;
+ } while(table[pos].exception_handler != (void*)-1);
+
+ --pos;
+ if (table[pos].start <= except_pc && table[pos].end > except_pc)
+ {
+ except_table_pos = pos;
+#if 0
+ printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
+#endif
+ return table[pos].exception_handler;
+ }
+#else
+ while (table[++pos].exception_handler != (void*)-1) {
+ if (table[pos].start <= except_pc && table[pos].end > except_pc)
+ {
+ /* This can apply. Make sure it is better or as good as the previous
+ best. */
+ /* The best one ends first. */
+ if (best == 0 || (table[pos].end <= table[best].end
+ /* The best one starts last. */
+ && table[pos].start >= table[best].start))
+ best = pos;
+ }
+ }
+ if (best != 0)
+ return table[best].exception_handler;
+#endif
+
+#if 0
+ printf("find_first_eh_table_match(): else: returning NULL!\n");
+#endif
+ return (void*)0;
+}
+
+int
+__throw_type_match (const char *catch_type, const char *throw_type)
+{
+#if 0
+ printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
+ catch_type, throw_type);
+#endif
+ return strcmp (catch_type, throw_type);
+}
+
+void
+__register_exceptions (exception_table *table)
+{
+ struct exception_table_node *node = (struct exception_table_node*)
+ malloc (sizeof (struct exception_table_node));
+ exception_table *range = table + 1;
+ node->table = table;
+
+ /* This look can be optimized away either if the table
+ is sorted, or if we pass in extra parameters. */
+ node->start = range->start;
+ node->end = range->end;
+ for (range++ ; range->start != (void*)(-1); range++)
+ {
+ if (range->start < node->start)
+ node->start = range->start;
+ if (range->end < node->end)
+ node->end = range->end;
+ }
+
+ node->next = exception_table_list;
+ exception_table_list = node;
+}
+#endif /* L_eh */
+
+#ifdef L_pure
+#define MESSAGE "pure virtual method called\n"
+void
+__pure_virtual ()
+{
+ write (2, MESSAGE, sizeof (MESSAGE) - 1);
+ _exit (-1);
+}
+#endif
OpenPOWER on IntegriCloud