2012-03-01 Pedro Alves <palves@redhat.com>
[deliverable/binutils-gdb.git] / gdb / inline-frame.c
index 731d3adcaaf1c16e879c2f887fb48fe3eae3158e..3e2da736f6352cb065bf27f48862990efc27dafd 100644 (file)
@@ -1,6 +1,6 @@
 /* Inline frame unwinder for GDB.
 
-   Copyright (C) 2008 Free Software Foundation, Inc.
+   Copyright (C) 2008-2012 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,6 +22,7 @@
 #include "block.h"
 #include "frame-unwind.h"
 #include "inferior.h"
+#include "regcache.h"
 #include "symtab.h"
 #include "vec.h"
 
@@ -59,7 +60,8 @@ DEF_VEC_O(inline_state_s);
 
 static VEC(inline_state_s) *inline_states;
 
-/* Locate saved inlined frame state for PTID, if it exists.  */
+/* Locate saved inlined frame state for PTID, if it exists
+   and is valid.  */
 
 static struct inline_state *
 find_inline_frame_state (ptid_t ptid)
@@ -70,7 +72,20 @@ find_inline_frame_state (ptid_t ptid)
   for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++)
     {
       if (ptid_equal (state->ptid, ptid))
-       return state;
+       {
+         struct regcache *regcache = get_thread_regcache (ptid);
+         CORE_ADDR current_pc = regcache_read_pc (regcache);
+
+         if (current_pc != state->saved_pc)
+           {
+             /* PC has changed - this context is invalid.  Use the
+                default behavior.  */
+             VEC_unordered_remove (inline_state_s, inline_states, ix);
+             return NULL;
+           }
+         else
+           return state;
+       }
     }
 
   return NULL;
@@ -110,7 +125,10 @@ clear_inline_frame_state (ptid_t ptid)
     {
       VEC (inline_state_s) *new_states = NULL;
       int pid = ptid_get_pid (ptid);
-      for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++)
+
+      for (ix = 0;
+          VEC_iterate (inline_state_s, inline_states, ix, state);
+          ix++)
        if (pid != ptid_get_pid (state->ptid))
          VEC_safe_push (inline_state_s, new_states, state);
       VEC_free (inline_state_s, inline_states);
@@ -148,6 +166,10 @@ inline_frame_this_id (struct frame_info *this_frame,
      frame").  This will take work.  */
   gdb_assert (frame_id_p (*this_id));
 
+  /* For now, require we don't match outer_frame_id either (see
+     comment above).  */
+  gdb_assert (!frame_id_eq (*this_id, outer_frame_id));
+
   /* Future work NOTE: Alexandre Oliva applied a patch to GCC 4.3
      which generates DW_AT_entry_pc for inlined functions when
      possible.  If this attribute is available, we should use it
@@ -221,13 +243,8 @@ inline_frame_sniffer (const struct frame_unwind *self,
      can be stepped into later).  */
   if (state != NULL && state->skipped_frames > 0 && next_frame == NULL)
     {
-      if (this_pc != state->saved_pc)
-       state->skipped_frames = 0;
-      else
-       {
-         gdb_assert (depth >= state->skipped_frames);
-         depth -= state->skipped_frames;
-       }
+      gdb_assert (depth >= state->skipped_frames);
+      depth -= state->skipped_frames;
     }
 
   /* If all the inlined functions here already have frames, then pass
@@ -241,16 +258,15 @@ inline_frame_sniffer (const struct frame_unwind *self,
   return 1;
 }
 
-const struct frame_unwind inline_frame_unwinder = {
+const struct frame_unwind inline_frame_unwind = {
   INLINE_FRAME,
+  default_frame_unwind_stop_reason,
   inline_frame_this_id,
   inline_frame_prev_register,
   NULL,
   inline_frame_sniffer
 };
 
-const struct frame_unwind *const inline_frame_unwind = &inline_frame_unwinder;
-
 /* Return non-zero if BLOCK, an inlined function block containing PC,
    has a group of contiguous instructions starting at PC (but not
    before it).  */
@@ -272,7 +288,7 @@ block_starting_point_at (CORE_ADDR pc, struct block *block)
   if (new_block == block || contained_in (new_block, block))
     return 0;
 
-  /* The immediately preceeding address belongs to a different block,
+  /* The immediately preceding address belongs to a different block,
      which is not a child of this one.  Treat this as an entrance into
      BLOCK.  */
   return 1;
This page took 0.026491 seconds and 4 git commands to generate.