aboutsummaryrefslogtreecommitdiff
path: root/gcc/unwind-dw2-fde-darwin.c
diff options
context:
space:
mode:
authorGeoffrey Keating <geoffk@apple.com>2002-11-07 06:00:07 +0000
committerGeoffrey Keating <geoffk@gcc.gnu.org>2002-11-07 06:00:07 +0000
commit3cfe49dab857d0d0a61597afe558a175287c27ec (patch)
tree0a818627c9d2e5109f50615e83ad08d7572b1feb /gcc/unwind-dw2-fde-darwin.c
parent12f256d42ec080c4bc69e08636ce3b40b792eae7 (diff)
downloadgcc-3cfe49dab857d0d0a61597afe558a175287c27ec.zip
gcc-3cfe49dab857d0d0a61597afe558a175287c27ec.tar.gz
gcc-3cfe49dab857d0d0a61597afe558a175287c27ec.tar.bz2
Index: ChangeLog
2002-11-05 Geoffrey Keating <geoffk@apple.com> * config.gcc: Don't create crtbegin, crtend on Darwin; do create crt2.o. Rearrange t-darwin makefiles. * crtstuff.c [OBJECT_FORMAT_MACHO]: Delete. * unwind-dw2-fde-darwin.c: New. * unwind-dw2-fde-glibc.c: Correct comment. * unwind-dw2-fde.c (__register_frame_info_bases) [DWARF2_OBJECT_END_PTR_EXTENSION]: Clear fde_end. (classify_object_over_fdes): Use last_fde. (add_fdes): Likewise. (linear_search_fdes): Likewise. * unwind-dw2-fde.h (struct object) [DWARF2_OBJECT_END_PTR_EXTENSION]: Add fde_end field. (last_fde): New. * config/darwin.h (STARTFILE_SPEC): Include crt2.o not crtbegin.o. (ENDFILE_SPEC): No crtend.o. * config/t-darwin: New. * config/i386/t-darwin: Delete. * config/darwin-crt2.c: New. * config/rs6000/t-darwin: Delete contents duplicated in t-rs6000 or config/t-darwin. Index: testsuite/ChangeLog 2002-11-05 Geoffrey Keating <geoffk@apple.com> * g++.old-deja/g++.eh/badalloc1.C: XFAIL excess errors test on Darwin. From-SVN: r58877
Diffstat (limited to 'gcc/unwind-dw2-fde-darwin.c')
-rw-r--r--gcc/unwind-dw2-fde-darwin.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/gcc/unwind-dw2-fde-darwin.c b/gcc/unwind-dw2-fde-darwin.c
new file mode 100644
index 0000000..77e44e8
--- /dev/null
+++ b/gcc/unwind-dw2-fde-darwin.c
@@ -0,0 +1,231 @@
+/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/* Locate the FDE entry for a given address, using Darwin's keymgr support. */
+
+#include "tconfig.h"
+#include <string.h>
+#include <stdlib.h>
+#include "dwarf2.h"
+#include "unwind.h"
+#define NO_BASE_OF_ENCODED_VALUE
+#define DWARF2_OBJECT_END_PTR_EXTENSION
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+/* Carefully don't include gthr.h. */
+
+typedef int __gthread_mutex_t;
+#define __gthread_mutex_lock(x) (void)(x)
+#define __gthread_mutex_unlock(x) (void)(x)
+
+static fde * _Unwind_Find_registered_FDE (void *pc,
+ struct dwarf_eh_bases *bases);
+
+#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
+#include "unwind-dw2-fde.c"
+#undef _Unwind_Find_FDE
+
+/* KeyMgr stuff. */
+#define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */
+#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */
+
+extern void *_keymgr_get_and_lock_processwide_ptr (int);
+extern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
+extern void _keymgr_unlock_processwide_ptr (int);
+
+struct mach_header;
+extern char *getsectdatafromheader (struct mach_header*, const char*,
+ const char *, unsigned long *);
+
+/* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST. */
+struct km_object_info {
+ struct object *seen_objects;
+ struct object *unseen_objects;
+ unsigned spare[2];
+};
+
+/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST. Info about each resident image. */
+struct live_images {
+ unsigned long this_size; /* sizeof (live_images) */
+ struct mach_header *mh; /* the image info */
+ unsigned long vm_slide;
+ void (*destructor)(struct live_images *); /* destructor for this */
+ struct live_images *next;
+ unsigned int examined_p;
+ void *fde;
+ void *object_info;
+ unsigned long info[2]; /* Future use. */
+};
+
+/* Bits in the examined_p field of struct live_images. */
+enum {
+ EXAMINED_IMAGE_MASK = 1, /* We've seen this one. */
+ ALLOCED_IMAGE_MASK = 2, /* The FDE entries were allocated by
+ malloc, and must be freed. This isn't
+ used by newer libgcc versions. */
+ IMAGE_IS_TEXT_MASK = 4 /* This image is in the TEXT segment. */
+};
+
+/* Delete any data we allocated on a live_images structure.
+ IMAGE has already been removed from the KEYMGR_GCC3_LIVE_IMAGE_LIST.
+ Called by KeyMgr (which will delete the struct after we return.) */
+
+static void
+live_image_destructor (struct live_images *image)
+{
+ if (image->object_info)
+ {
+ /* Free any sorted arrays. */
+ __deregister_frame_info_bases (image->fde);
+
+ free (image->object_info);
+ image->object_info = NULL;
+ if (image->examined_p & ALLOCED_IMAGE_MASK)
+ free (image->fde);
+ }
+}
+
+/* Run through the list of live images. If we can allocate memory,
+ give each unseen image a new `struct object'. Even if we can't,
+ check whether the PC is inside the FDE of each unseen image.
+ */
+
+static inline fde *
+examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
+{
+ fde *result = NULL;
+ struct live_images *image;
+
+ image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+
+ for (; image != NULL; image = image->next)
+ if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
+ {
+ char *fde;
+ unsigned long sz;
+
+ fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
+ if (fde == NULL)
+ {
+ fde = getsectdatafromheader (image->mh, "__TEXT",
+ "__eh_frame", &sz);
+ if (fde != NULL)
+ image->examined_p |= IMAGE_IS_TEXT_MASK;
+ }
+
+ /* If .eh_frame is empty, don't register at all. */
+ if (fde != NULL && sz > 0)
+ {
+ char *real_fde = (fde + image->vm_slide);
+ struct object *ob = NULL;
+ struct object panicob;
+
+ if (! dont_alloc)
+ ob = calloc (1, sizeof (struct object));
+ dont_alloc |= ob == NULL;
+ if (dont_alloc)
+ ob = &panicob;
+
+ ob->pc_begin = (void *)-1;
+ ob->tbase = 0;
+ ob->dbase = 0;
+ ob->u.single = (struct dwarf_fde *)real_fde;
+ ob->s.i = 0;
+ ob->s.b.encoding = DW_EH_PE_omit;
+ ob->fde_end = real_fde + sz;
+
+ if (! dont_alloc)
+ {
+ ob->next = unseen_objects;
+ unseen_objects = ob;
+
+ image->destructor = live_image_destructor;
+ image->object_info = ob;
+
+ image->examined_p |= EXAMINED_IMAGE_MASK;
+ }
+ image->fde = real_fde;
+
+ result = search_object (ob, pc);
+ if (result)
+ {
+ int encoding;
+
+ bases->tbase = ob->tbase;
+ bases->dbase = ob->dbase;
+
+ encoding = ob->s.b.encoding;
+ if (ob->s.b.mixed_encoding)
+ encoding = get_fde_encoding (result);
+ read_encoded_value_with_base (encoding,
+ base_from_object (encoding, ob),
+ result->pc_begin,
+ (_Unwind_Ptr *)&bases->func);
+ break;
+ }
+ }
+ else
+ image->examined_p |= EXAMINED_IMAGE_MASK;
+ }
+
+ _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+
+ return result;
+}
+
+fde *
+_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
+{
+ struct km_object_info *the_obj_info;
+ fde *ret = NULL;
+
+ the_obj_info =
+ _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
+ if (! the_obj_info)
+ the_obj_info = calloc (1, sizeof (*the_obj_info));
+
+ if (the_obj_info != NULL)
+ {
+ seen_objects = the_obj_info->seen_objects;
+ unseen_objects = the_obj_info->unseen_objects;
+
+ ret = _Unwind_Find_registered_FDE (pc, bases);
+ }
+
+ /* OK, didn't find it in the list of FDEs we've seen before,
+ so go through and look at the new ones. */
+ if (ret == NULL)
+ ret = examine_objects (pc, bases, the_obj_info == NULL);
+
+ if (the_obj_info != NULL)
+ {
+ the_obj_info->seen_objects = seen_objects;
+ the_obj_info->unseen_objects = unseen_objects;
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
+ the_obj_info);
+ }
+ return ret;
+}