OSDN Git Service

* tree.h: Declare make_decl_rtl_for_debug.
[pf3gnuchains/gcc-fork.git] / gcc / unwind-dw2-fde-darwin.c
index 77e44e8..6245ed3 100644 (file)
@@ -1,32 +1,30 @@
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
 
-   This file is part of GNU CC.
+   This file is part of GCC.
 
-   GNU CC is free software; you can redistribute it and/or modify
+   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 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
-   GNU CC is distributed in the hope that it will be useful,
+   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.
 
-   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.  */
+   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.
 
-/* 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.  */
+   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"
@@ -41,8 +39,8 @@ 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);
+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"
@@ -57,8 +55,11 @@ 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 *);
+                                   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 {
@@ -86,37 +87,61 @@ enum {
   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.  */
+  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.  */
 };
 \f
-/* 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.)  */
+/* 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 
+static void
 live_image_destructor (struct live_images *image)
 {
   if (image->object_info)
     {
-      /* Free any sorted arrays.  */
-      __deregister_frame_info_bases (image->fde);
+      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 fde *
+
+static inline const fde *
 examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
 {
-  fde *result = NULL;
+  const fde *result = NULL;
   struct live_images *image;
 
   image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
@@ -124,31 +149,40 @@ examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
   for (; image != NULL; image = image->next)
     if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
       {
-       char *fde;
+       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;
@@ -156,34 +190,44 @@ examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
            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)
              {
-               ob->next = unseen_objects;
-               unseen_objects = ob;
-               
+               struct object **p;
+
                image->destructor = live_image_destructor;
                image->object_info = ob;
-               
-               image->examined_p |= EXAMINED_IMAGE_MASK;
+
+               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;
              }
-           image->fde = real_fde;
-           
-           result = search_object (ob, pc);
+
            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, 
+               read_encoded_value_with_base (encoding,
                                              base_from_object (encoding, ob),
-                                             result->pc_begin, 
-                                             (_Unwind_Ptr *)&bases->func);
+                                             result->pc_begin, &func);
+               bases->func = (void *) func;
                break;
              }
          }
@@ -196,25 +240,25 @@ examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
   return result;
 }
 
-fde *
+const fde *
 _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
 {
   struct km_object_info *the_obj_info;
-  fde *ret = NULL;
+  const fde *ret = NULL;
 
-  the_obj_info = 
+  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)
@@ -224,8 +268,20 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
     {
       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);
     }
+  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
+                                         the_obj_info);
   return ret;
 }
+
+void *
+_darwin10_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+