merge from gcc
[external/binutils.git] / gdb / libunwind-frame.c
index b22e6d7..481b6b2 100644 (file)
@@ -1,6 +1,7 @@
 /* Frame unwinder for frames using the libunwind library.
 
-   Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
    Written by Jeff Johnston, contributed by Red Hat Inc.
 
@@ -8,7 +9,7 @@
 
    This program 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 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +18,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 
@@ -65,11 +64,12 @@ struct libunwind_frame_cache
   CORE_ADDR base;
   CORE_ADDR func_addr;
   unw_cursor_t cursor;
+  unw_addr_space_t as;
 };
 
-/* We need to qualify the function names with a platform-specific prefix to match 
-   the names used by the libunwind library.  The UNW_OBJ macro is provided by the
-   libunwind.h header file.  */
+/* We need to qualify the function names with a platform-specific prefix
+   to match the names used by the libunwind library.  The UNW_OBJ macro is
+   provided by the libunwind.h header file.  */
 #define STRINGIFY2(name)       #name
 #define STRINGIFY(name)                STRINGIFY2(name)
 
@@ -129,7 +129,7 @@ libunwind_frame_set_descr (struct gdbarch *gdbarch, struct libunwind_descr *desc
 }
 
 static struct libunwind_frame_cache *
-libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
+libunwind_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   unw_accessors_t *acc;
   unw_addr_space_t as;
@@ -137,6 +137,7 @@ libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
   unw_regnum_t uw_sp_regnum;
   struct libunwind_frame_cache *cache;
   struct libunwind_descr *descr;
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   int i, ret;
 
   if (*this_cache)
@@ -148,29 +149,32 @@ libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
   /* We can assume we are unwinding a normal frame.  Even if this is
      for a signal trampoline, ia64 signal "trampolines" use a normal
      subroutine call to start the signal handler.  */
-  cache->func_addr = frame_func_unwind (next_frame, NORMAL_FRAME);
+  cache->func_addr = get_frame_func (this_frame);
   if (cache->func_addr == 0
-      && frame_relative_level (next_frame) > 0
-      && get_frame_type (next_frame) != SIGTRAMP_FRAME)
+      && get_next_frame (this_frame)
+      && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
     return NULL;
 
-  /* Get a libunwind cursor to the previous frame.  We do this by initializing
-     a cursor.  Libunwind treats a new cursor as the top of stack and will get
-     the current register set via the libunwind register accessor.  Now, we
-     provide the platform-specific accessors and we set up the register accessor to use
-     the frame register unwinding interfaces so that we properly get the registers for
-     the current frame rather than the top.  We then use the  unw_step function to 
-     move the libunwind cursor back one frame.  We can later use this cursor to find previous 
-     registers via the unw_get_reg interface which will invoke libunwind's special logic.  */
-  descr = libunwind_descr (get_frame_arch (next_frame));
+  /* Get a libunwind cursor to the previous frame.
+  
+     We do this by initializing a cursor.  Libunwind treats a new cursor
+     as the top of stack and will get the current register set via the
+     libunwind register accessor.  Now, we provide the platform-specific
+     accessors and we set up the register accessor to use the frame
+     register unwinding interfaces so that we properly get the registers
+     for the current frame rather than the top.  We then use the unw_step
+     function to move the libunwind cursor back one frame.  We can later
+     use this cursor to find previous registers via the unw_get_reg
+     interface which will invoke libunwind's special logic.  */
+  descr = libunwind_descr (gdbarch);
   acc = descr->accessors;
   as =  unw_create_addr_space_p (acc,
-                                gdbarch_byte_order (current_gdbarch)
+                                gdbarch_byte_order (gdbarch)
                                 == BFD_ENDIAN_BIG
                                 ? __BIG_ENDIAN
                                 : __LITTLE_ENDIAN);
 
-  unw_init_remote_p (&cache->cursor, as, next_frame);
+  unw_init_remote_p (&cache->cursor, as, this_frame);
   if (unw_step_p (&cache->cursor) < 0)
     {
       unw_destroy_addr_space_p (as);
@@ -178,7 +182,7 @@ libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
     }
 
   /* To get base address, get sp from previous frame.  */
-  uw_sp_regnum = descr->gdb2uw (SP_REGNUM);
+  uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch));
   ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp);
   if (ret < 0)
     {
@@ -187,11 +191,20 @@ libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
     }
 
   cache->base = (CORE_ADDR)fp;
+  cache->as = as;
 
   *this_cache = cache;
   return cache;
 }
 
+void
+libunwind_frame_dealloc_cache (struct frame_info *self, void *this_cache)
+{
+  struct libunwind_frame_cache *cache = this_cache;
+  if (cache->as)
+    unw_destroy_addr_space_p (cache->as);
+}
+
 unw_word_t
 libunwind_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg)
 {
@@ -202,39 +215,45 @@ static const struct frame_unwind libunwind_frame_unwind =
 {
   NORMAL_FRAME,
   libunwind_frame_this_id,
-  libunwind_frame_prev_register
+  libunwind_frame_prev_register,
+  NULL,
+  libunwind_frame_sniffer,
+  libunwind_frame_dealloc_cache,
 };
 
 /* Verify if there is sufficient libunwind information for the frame to use
    libunwind frame unwinding.  */
-const struct frame_unwind *
-libunwind_frame_sniffer (struct frame_info *next_frame)
+int
+libunwind_frame_sniffer (const struct frame_unwind *self,
+                         struct frame_info *this_frame, void **this_cache)
 {
   unw_cursor_t cursor;
   unw_accessors_t *acc;
   unw_addr_space_t as;
   struct libunwind_descr *descr;
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   int i, ret;
 
-  /* To test for libunwind unwind support, initialize a cursor to the current frame and try to back
-     up.  We use this same method when setting up the frame cache (see libunwind_frame_cache()).
-     If libunwind returns success for this operation, it means that it has found sufficient
-     libunwind unwinding information to do so.  */
+  /* To test for libunwind unwind support, initialize a cursor to
+     the current frame and try to back up.  We use this same method
+     when setting up the frame cache (see libunwind_frame_cache()).
+     If libunwind returns success for this operation, it means that
+     it has found sufficient libunwind unwinding information to do so.  */
 
-  descr = libunwind_descr (get_frame_arch (next_frame));
+  descr = libunwind_descr (gdbarch);
   acc = descr->accessors;
   as =  unw_create_addr_space_p (acc,
-                                gdbarch_byte_order (current_gdbarch)
+                                gdbarch_byte_order (gdbarch)
                                 == BFD_ENDIAN_BIG
                                 ? __BIG_ENDIAN
                                 : __LITTLE_ENDIAN);
 
-  ret = unw_init_remote_p (&cursor, as, next_frame);
+  ret = unw_init_remote_p (&cursor, as, this_frame);
 
   if (ret < 0)
     {
       unw_destroy_addr_space_p (as);
-      return NULL;
+      return 0;
     }
 
  
@@ -245,32 +264,29 @@ libunwind_frame_sniffer (struct frame_info *next_frame)
   unw_destroy_addr_space_p (as);
 
   if (ret < 0)
-    return NULL;
+    return 0;
 
-  return &libunwind_frame_unwind;
+  return 1;
 }
 
 void
-libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
-                     struct frame_id *this_id)
+libunwind_frame_this_id (struct frame_info *this_frame, void **this_cache,
+                        struct frame_id *this_id)
 {
   struct libunwind_frame_cache *cache =
-    libunwind_frame_cache (next_frame, this_cache);
+    libunwind_frame_cache (this_frame, this_cache);
 
   if (cache != NULL)
     (*this_id) = frame_id_build (cache->base, cache->func_addr);
-  else
-    (*this_id) = null_frame_id;
 }
 
-void
-libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
-                              int regnum, int *optimizedp,
-                              enum lval_type *lvalp, CORE_ADDR *addrp,
-                              int *realnump, gdb_byte *valuep)
+struct value *
+libunwind_frame_prev_register (struct frame_info *this_frame,
+                               void **this_cache, int regnum)
 {
   struct libunwind_frame_cache *cache =
-    libunwind_frame_cache (next_frame, this_cache);
+    libunwind_frame_cache (this_frame, this_cache);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
 
   void *ptr;
   unw_cursor_t *c;
@@ -280,12 +296,13 @@ libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
   unw_fpreg_t fpval;
   unw_regnum_t uw_regnum;
   struct libunwind_descr *descr;
+  struct value *val = NULL;
 
   if (cache == NULL)
-    return;
+    return frame_unwind_got_constant (this_frame, regnum, 0);
   
   /* Convert from gdb register number to libunwind register number.  */
-  descr = libunwind_descr (get_frame_arch (next_frame));
+  descr = libunwind_descr (get_frame_arch (this_frame));
   uw_regnum = descr->gdb2uw (regnum);
 
   gdb_assert (regnum >= 0);
@@ -293,63 +310,55 @@ libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
   if (!target_has_registers)
     error (_("No registers."));
 
-  *optimizedp = 0;
-  *addrp = 0;
-  *lvalp = not_lval;
-  *realnump = -1;
-
-  if (valuep)
-    memset (valuep, 0, register_size (current_gdbarch, regnum));
-
   if (uw_regnum < 0)
-    return;
-
-  /* To get the previous register, we use the libunwind register APIs with
-     the cursor we have already pushed back to the previous frame.  */
-
-  if (descr->is_fpreg (uw_regnum))
-    {
-      ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval);
-      ptr = &fpval;
-    }
-  else
-    {
-      ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval);
-      ptr = &intval;
-    }
-
-  if (ret < 0)
-    return;
-
-  if (valuep)
-    memcpy (valuep, ptr, register_size (current_gdbarch, regnum));
+    return frame_unwind_got_constant (this_frame, regnum, 0);
 
   if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0)
-    return;
+    return frame_unwind_got_constant (this_frame, regnum, 0);
 
   switch (sl.type)
     {
-    case UNW_SLT_NONE:
-      *optimizedp = 1;
-      break;
-
     case UNW_SLT_MEMORY:
-      *lvalp = lval_memory;
-      *addrp = sl.u.addr;
+      val = frame_unwind_got_memory (this_frame, regnum, sl.u.addr);
       break;
 
     case UNW_SLT_REG:
-      *lvalp = lval_register;
-      *realnump = regnum;
+      val = frame_unwind_got_register (this_frame, regnum,
+                                       descr->uw2gdb (sl.u.regnum));
       break;
+    case UNW_SLT_NONE:
+      {
+        /* The register is not stored at a specific memory address nor
+           inside another register.  So use libunwind to fetch the register
+           value for us, and create a constant value with the result.  */
+        if (descr->is_fpreg (uw_regnum))
+          {
+            ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval);
+            if (ret < 0)
+              return frame_unwind_got_constant (this_frame, regnum, 0);
+            val = frame_unwind_got_bytes (this_frame, regnum,
+                                          (gdb_byte *) &fpval);
+          }
+        else
+          {
+            ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval);
+            if (ret < 0)
+              return frame_unwind_got_constant (this_frame, regnum, 0);
+            val = frame_unwind_got_constant (this_frame, regnum, intval);
+          }
+        set_value_optimized_out (val, 1);
+        break;
+      }
     }
+
+  return val;
 } 
 
 CORE_ADDR
-libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache)
+libunwind_frame_base_address (struct frame_info *this_frame, void **this_cache)
 {
   struct libunwind_frame_cache *cache =
-    libunwind_frame_cache (next_frame, this_cache);
+    libunwind_frame_cache (this_frame, this_cache);
 
   if (cache == NULL)
     return (CORE_ADDR)NULL;
@@ -367,13 +376,16 @@ libunwind_search_unwind_table (void *as, long ip, void *di,
 }
 
 /* Verify if we are in a sigtramp frame and we can use libunwind to unwind.  */
-const struct frame_unwind *
-libunwind_sigtramp_frame_sniffer (struct frame_info *next_frame)
+int
+libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self,
+                                  struct frame_info *this_frame,
+                                  void **this_cache)
 {
   unw_cursor_t cursor;
   unw_accessors_t *acc;
   unw_addr_space_t as;
   struct libunwind_descr *descr;
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   int i, ret;
 
   /* To test for libunwind unwind support, initialize a cursor to the
@@ -383,29 +395,29 @@ libunwind_sigtramp_frame_sniffer (struct frame_info *next_frame)
      has found sufficient libunwind unwinding information to do
      so.  */
 
-  descr = libunwind_descr (get_frame_arch (next_frame));
+  descr = libunwind_descr (gdbarch);
   acc = descr->accessors;
   as =  unw_create_addr_space_p (acc,
-                                gdbarch_byte_order (current_gdbarch)
+                                gdbarch_byte_order (gdbarch)
                                 == BFD_ENDIAN_BIG
                                 ? __BIG_ENDIAN
                                 : __LITTLE_ENDIAN);
 
-  ret = unw_init_remote_p (&cursor, as, next_frame);
+  ret = unw_init_remote_p (&cursor, as, this_frame);
 
   if (ret < 0)
     {
       unw_destroy_addr_space_p (as);
-      return NULL;
+      return 0;
     }
 
   /* Check to see if we are in a signal frame.  */
   ret = unw_is_signal_frame_p (&cursor);
   unw_destroy_addr_space_p (as);
   if (ret > 0)
-    return &libunwind_frame_unwind;
+    return 1;
 
-  return NULL;
+  return 0;
 }
 
 /* The following routine is for accessing special registers of the top frame.
@@ -431,7 +443,7 @@ libunwind_get_reg_special (struct gdbarch *gdbarch, struct regcache *regcache,
   descr = libunwind_descr (gdbarch);
   acc = descr->special_accessors;
   as =  unw_create_addr_space_p (acc,
-                                gdbarch_byte_order (current_gdbarch)
+                                gdbarch_byte_order (gdbarch)
                                 == BFD_ENDIAN_BIG
                                 ? __BIG_ENDIAN
                                 : __LITTLE_ENDIAN);
@@ -462,7 +474,7 @@ libunwind_get_reg_special (struct gdbarch *gdbarch, struct regcache *regcache,
     return -1;
 
   if (buf)
-    memcpy (buf, ptr, register_size (current_gdbarch, regnum));
+    memcpy (buf, ptr, register_size (gdbarch, regnum));
 
   return 0;
 }