OSDN Git Service

PR c++/42844
[pf3gnuchains/gcc-fork.git] / gcc / unwind-dw2-fde-glibc.c
index 7dd9a72..b8a7312 100644 (file)
@@ -1,11 +1,11 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009 Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
    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 2, or (at your option)
+   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,
    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 GCC; 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 PT_GNU_EH_FRAME ELF
    segment and dl_iterate_phdr to avoid register/deregister calls at
@@ -33,7 +30,6 @@
 #define _GNU_SOURCE 1
 #endif
 
-#include "auto-host.h" /* For HAVE_LD_EH_FRAME_HDR.  */
 #include "tconfig.h"
 #include "tsystem.h"
 #ifndef inhibit_libc
 #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
     && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
        || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
+    && defined(__FreeBSD__) && __FreeBSD__ >= 7
+# define ElfW __ElfN
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if defined(USE_PT_GNU_EH_FRAME)
 
 #ifndef __RELOC_POINTER
 # define __RELOC_POINTER(ptr, base) ((ptr) + (base))
@@ -119,8 +125,9 @@ base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
       return (_Unwind_Ptr) data->tbase;
     case DW_EH_PE_datarel:
       return (_Unwind_Ptr) data->dbase;
+    default:
+      gcc_unreachable ();
     }
-  abort ();
 }
 
 static int
@@ -138,7 +145,8 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
   const struct unw_eh_frame_hdr *hdr;
   _Unwind_Ptr eh_frame;
   struct object ob;
-  
+  _Unwind_Ptr pc_low = 0, pc_high = 0;
+
   struct ext_dl_phdr_info
     {
       ElfW(Addr) dlpi_addr;
@@ -196,13 +204,13 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
                    }
                  goto found;
                }
-                 
+
              last_cache_entry = cache_entry;
              /* Exit early if we found an unused entry.  */
              if ((cache_entry->pc_low | cache_entry->pc_high) == 0)
                break;
              if (cache_entry->link != NULL)
-               prev_cache_entry = cache_entry;           
+               prev_cache_entry = cache_entry;
            }
        }
       else
@@ -228,8 +236,6 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
   if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
             + sizeof (info->dlpi_phnum))
     return -1;
-  _Unwind_Ptr pc_low = 0, pc_high = 0;
 
   /* See if PC falls into one of the loaded segments.  Find the eh_frame
      segment at the same time.  */
@@ -251,13 +257,16 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
       else if (phdr->p_type == PT_DYNAMIC)
        p_dynamic = phdr;
     }
-  
+
   if (!match)
     return 0;
 
   if (size >= sizeof (struct ext_dl_phdr_info))
     {
-      if (last_cache_entry != NULL)
+      /* Move the cache entry we're about to overwrite to the head of
+        the list.  If either last_cache_entry or prev_cache_entry are
+        NULL, that cache entry is already at the head.  */
+      if (last_cache_entry != NULL && prev_cache_entry != NULL)
        {
          prev_cache_entry->link = last_cache_entry->link;
          last_cache_entry->link = frame_hdr_cache_head;
@@ -359,8 +368,7 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
                    break;
                }
 
-             if (lo >= hi)
-               __gxx_abort ();
+             gcc_assert (lo < hi);
            }
 
          f = (fde *) (table[mid].fde + data_base);
@@ -387,11 +395,13 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
   data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc);
   if (data->ret != NULL)
     {
+      _Unwind_Ptr func;
       unsigned int encoding = get_fde_encoding (data->ret);
+
       read_encoded_value_with_base (encoding,
                                    base_from_cb_data (encoding, data),
-                                   data->ret->pc_begin,
-                                   (_Unwind_Ptr *)&data->func);
+                                   data->ret->pc_begin, &func);
+      data->func = (void *) func;
     }
   return 1;
 }