static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame);
static const char *frame_stop_reason_symbol_string (enum unwind_stop_reason reason);
+/* Status of some values cached in the frame_info object. */
+
+enum cached_copy_status
+{
+ /* Value is unknown. */
+ CC_UNKNOWN,
+
+ /* We have a value. */
+ CC_VALUE,
+
+ /* Value was not saved. */
+ CC_NOT_SAVED,
+
+ /* Value is unavailable. */
+ CC_UNAVAILABLE
+};
+
/* We keep a cache of stack frames, each of which is a "struct
frame_info". The innermost one gets allocated (in
wait_for_inferior) each time the inferior stops; current_frame
/* Cached copy of the previous frame's resume address. */
struct {
- int p;
+ enum cached_copy_status status;
CORE_ADDR value;
} prev_pc;
fprintf_unfiltered (file, "<unknown>");
fprintf_unfiltered (file, ",");
fprintf_unfiltered (file, "pc=");
- if (fi->next != NULL && fi->next->prev_pc.p)
- fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_pc.value));
- else
+ if (fi->next == NULL || fi->next->prev_pc.status == CC_UNKNOWN)
fprintf_unfiltered (file, "<unknown>");
+ else if (fi->next->prev_pc.status == CC_VALUE)
+ fprintf_unfiltered (file, "%s",
+ hex_string (fi->next->prev_pc.value));
+ else if (fi->next->prev_pc.status == CC_NOT_SAVED)
+ val_print_not_saved (file);
+ else if (fi->next->prev_pc.status == CC_UNAVAILABLE)
+ val_print_unavailable (file);
fprintf_unfiltered (file, ",");
fprintf_unfiltered (file, "id=");
if (fi->this_id.p)
return NULL;
}
-static int
-frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc)
+static CORE_ADDR
+frame_unwind_pc (struct frame_info *this_frame)
{
- if (!this_frame->prev_pc.p)
+ if (this_frame->prev_pc.status == CC_UNKNOWN)
{
if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame)))
{
{
pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
}
- if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+ if (ex.reason < 0)
{
- this_frame->prev_pc.p = -1;
-
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog,
- "{ frame_unwind_pc (this_frame=%d)"
- " -> <unavailable> }\n",
- this_frame->level);
- }
- else if (ex.reason < 0)
- {
- throw_exception (ex);
+ if (ex.error == NOT_AVAILABLE_ERROR)
+ {
+ this_frame->prev_pc.status = CC_UNAVAILABLE;
+
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "{ frame_unwind_pc (this_frame=%d)"
+ " -> <unavailable> }\n",
+ this_frame->level);
+ }
+ else if (ex.error == OPTIMIZED_OUT_ERROR)
+ {
+ this_frame->prev_pc.status = CC_NOT_SAVED;
+
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "{ frame_unwind_pc (this_frame=%d)"
+ " -> <not saved> }\n",
+ this_frame->level);
+ }
+ else
+ throw_exception (ex);
}
else
{
this_frame->prev_pc.value = pc;
- this_frame->prev_pc.p = 1;
+ this_frame->prev_pc.status = CC_VALUE;
if (frame_debug)
fprintf_unfiltered (gdb_stdlog,
"{ frame_unwind_pc (this_frame=%d) "
else
internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
}
- if (this_frame->prev_pc.p < 0)
- {
- *pc = -1;
- return 0;
- }
- else
- {
- *pc = this_frame->prev_pc.value;
- return 1;
- }
-}
-static CORE_ADDR
-frame_unwind_pc (struct frame_info *this_frame)
-{
- CORE_ADDR pc;
-
- if (!frame_unwind_pc_if_available (this_frame, &pc))
+ if (this_frame->prev_pc.status == CC_VALUE)
+ return this_frame->prev_pc.value;
+ else if (this_frame->prev_pc.status == CC_UNAVAILABLE)
throw_error (NOT_AVAILABLE_ERROR, _("PC not available"));
+ else if (this_frame->prev_pc.status == CC_NOT_SAVED)
+ throw_error (OPTIMIZED_OUT_ERROR, _("PC not saved"));
else
- return pc;
+ internal_error (__FILE__, __LINE__,
+ "unexpected prev_pc status: %d",
+ (int) this_frame->prev_pc.status);
}
CORE_ADDR
return frame_unwind_pc (skip_artificial_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_artificial_frames (this_frame), pc);
-}
-
int
get_frame_func_if_available (struct frame_info *this_frame, CORE_ADDR *pc)
{
very likely to read this, and the corresponding unwinder is
entitled to rely that the PC doesn't magically change. */
fi->next->prev_pc.value = pc;
- fi->next->prev_pc.p = 1;
+ fi->next->prev_pc.status = CC_VALUE;
/* We currently assume that frame chain's can't cross spaces. */
fi->pspace = fi->next->pspace;