/* Cache and manage frames for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001,
- 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1986-1987, 1989, 1991, 1994-1996, 1998, 2000-2004,
+ 2007-2012 Free Software Foundation, Inc.
This file is part of GDB.
return frame_unwind_pc (skip_inlined_frames (this_frame));
}
+int
+frame_unwind_caller_pc_if_available (struct frame_info *this_frame,
+ CORE_ADDR *pc)
+{
+ return frame_unwind_pc_if_available (skip_inlined_frames (this_frame), pc);
+}
+
int
get_frame_func_if_available (struct frame_info *this_frame, CORE_ADDR *pc)
{
frame_register_unwind (frame, regnum, &optimized, &unavailable,
&lval, &addr, &realnum, buf);
+
+ if (optimized)
+ error (_("Register %d was optimized out"), regnum);
+ if (unavailable)
+ throw_error (NOT_AVAILABLE_ERROR,
+ _("Register %d is not available"), regnum);
}
void
return frame_unwind_register_unsigned (frame->next, regnum);
}
+int
+read_frame_register_unsigned (struct frame_info *frame, int regnum,
+ ULONGEST *val)
+{
+ struct value *regval = get_frame_register_value (frame, regnum);
+
+ if (!value_optimized_out (regval)
+ && value_entirely_available (regval))
+ {
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int size = register_size (gdbarch, VALUE_REGNUM (regval));
+
+ *val = extract_unsigned_integer (value_contents (regval), size, byte_order);
+ return 1;
+ }
+
+ return 0;
+}
+
void
put_frame_register (struct frame_info *frame, int regnum,
const gdb_byte *buf)
{
struct frame_info *sentinel_frame =
create_sentinel_frame (current_program_space, get_current_regcache ());
- if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
- RETURN_MASK_ERROR) != 0)
+ if (catch_exceptions (current_uiout, unwind_to_current_frame,
+ sentinel_frame, RETURN_MASK_ERROR) != 0)
{
/* Oops! Fake a current frame? Is this useful? It has a PC
of zero, for instance. */
if (!target_has_registers || !target_has_stack || !target_has_memory)
return 0;
- /* No current inferior, no frame. */
- if (ptid_equal (inferior_ptid, null_ptid))
- return 0;
+ /* Traceframes are effectively a substitute for the live inferior. */
+ if (get_traceframe_number () < 0)
+ {
+ /* No current inferior, no frame. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return 0;
- /* Don't try to read from a dead thread. */
- if (is_exited (inferior_ptid))
- return 0;
+ /* Don't try to read from a dead thread. */
+ if (is_exited (inferior_ptid))
+ return 0;
- /* ... or from a spinning thread. */
- if (is_executing (inferior_ptid))
- return 0;
+ /* ... or from a spinning thread. */
+ if (is_executing (inferior_ptid))
+ return 0;
+ }
return 1;
}
if (get_frame_type (this_frame) == INLINE_FRAME)
return get_prev_frame_raw (this_frame);
+ /* Check that this frame is unwindable. If it isn't, don't try to
+ unwind to the prev frame. */
+ this_frame->stop_reason
+ = this_frame->unwind->stop_reason (this_frame,
+ &this_frame->prologue_cache);
+
+ if (this_frame->stop_reason != UNWIND_NO_REASON)
+ return NULL;
+
/* Check that this frame's ID was valid. If it wasn't, don't try to
unwind to the prev frame. Be careful to not apply this test to
the sentinel frame. */
while (get_frame_type (next_frame) == INLINE_FRAME)
next_frame = next_frame->next;
- if (get_frame_type (next_frame) == NORMAL_FRAME
+ if ((get_frame_type (next_frame) == NORMAL_FRAME
+ || get_frame_type (next_frame) == TAILCALL_FRAME)
&& (get_frame_type (this_frame) == NORMAL_FRAME
+ || get_frame_type (this_frame) == TAILCALL_FRAME
|| get_frame_type (this_frame) == INLINE_FRAME))
return pc - 1;
we can't do much better. */
sal->pc = get_frame_pc (frame);
+ sal->pspace = get_frame_program_space (frame);
+
return;
}
{
switch (reason)
{
- case UNWIND_NULL_ID:
- return _("unwinder did not report frame ID");
-
- case UNWIND_INNER_ID:
- return _("previous frame inner to this frame (corrupt stack?)");
-
- case UNWIND_SAME_ID:
- return _("previous frame identical to this frame (corrupt stack?)");
-
- case UNWIND_NO_SAVED_PC:
- return _("frame did not save the PC");
+#define SET(name, description) \
+ case name: return _(description);
+#include "unwind_stop_reasons.def"
+#undef SET
- case UNWIND_NO_REASON:
- case UNWIND_FIRST_ERROR:
default:
internal_error (__FILE__, __LINE__,
"Invalid frame stop reason");