diff gcc/unwind-dw2-fde-darwin.c @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children b7f97abdc517
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/unwind-dw2-fde-darwin.c	Fri Jul 17 14:47:48 2009 +0900
@@ -0,0 +1,275 @@
+/* Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Locate the FDE entry for a given address, using Darwin's keymgr support.  */
+
+#include "tconfig.h"
+#include "tsystem.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 const 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;
+struct mach_header_64;
+extern char *getsectdatafromheader (struct mach_header*, const char*,
+				    const char *, unsigned long *);
+extern char *getsectdatafromheader_64 (struct mach_header_64*, 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.  */
+  DESTRUCTOR_MAY_BE_CALLED_LIVE = 8  /* The destructor may be called on an
+					object that's part of the live
+					image list.  */
+};
+
+/* Delete any data we allocated on a live_images structure.  Either
+   IMAGE has already been removed from the
+   KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
+   after we return, or that list is locked and we're being called
+   because this object might be about to be unloaded.  Called by
+   KeyMgr.  */
+
+static void
+live_image_destructor (struct live_images *image)
+{
+  if (image->object_info)
+    {
+      struct km_object_info *the_obj_info;
+
+      the_obj_info =
+	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
+      if (the_obj_info)
+	{
+	  seen_objects = the_obj_info->seen_objects;
+	  unseen_objects = the_obj_info->unseen_objects;
+
+	  /* Free any sorted arrays.  */
+	  __deregister_frame_info_bases (image->fde);
+
+	  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);
+
+      free (image->object_info);
+      image->object_info = NULL;
+      if (image->examined_p & ALLOCED_IMAGE_MASK)
+	free (image->fde);
+      image->fde = NULL;
+    }
+  image->examined_p = 0;
+  image->destructor = NULL;
+}
+
+/* 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 const fde *
+examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
+{
+  const 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 = NULL;
+	unsigned long sz;
+
+	/* For ppc only check whether or not we have __DATA eh frames.  */
+#ifdef __ppc__
+	fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
+#endif
+
+	if (fde == NULL)
+	  {
+#if __LP64__
+	    fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh,
+					    "__TEXT", "__eh_frame", &sz);
+#else
+	    fde = getsectdatafromheader (image->mh, "__TEXT",
+					 "__eh_frame", &sz);
+#endif
+	    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;
+
+	    image->fde = real_fde;
+
+	    result = search_object (ob, pc);
+
+	    if (! dont_alloc)
+	      {
+		struct object **p;
+
+		image->destructor = live_image_destructor;
+		image->object_info = ob;
+
+		image->examined_p |= (EXAMINED_IMAGE_MASK
+				      | DESTRUCTOR_MAY_BE_CALLED_LIVE);
+
+		/* Insert the object into the classified list.  */
+		for (p = &seen_objects; *p ; p = &(*p)->next)
+		  if ((*p)->pc_begin < ob->pc_begin)
+		    break;
+		ob->next = *p;
+		*p = ob;
+	      }
+
+	    if (result)
+	      {
+		int encoding;
+		_Unwind_Ptr func;
+
+		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, &func);
+		bases->func = (void *) func;
+		break;
+	      }
+	  }
+	else
+	  image->examined_p |= EXAMINED_IMAGE_MASK;
+      }
+
+  _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+
+  return result;
+}
+
+const fde *
+_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
+{
+  struct km_object_info *the_obj_info;
+  const 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;
+}