summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/frame.c25
-rw-r--r--gdb/frame.h4
-rw-r--r--gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp19
-rw-r--r--gdb/valops.c17
-rw-r--r--gdb/value.c5
-rw-r--r--gdb/value.h6
6 files changed, 37 insertions, 39 deletions
diff --git a/gdb/frame.c b/gdb/frame.c
index 3f2d2700541..2332418f347 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2121,8 +2121,13 @@ get_prev_frame_always_1 (struct frame_info *this_frame)
/* Only try to do the unwind once. */
if (this_frame->prev_p)
{
- frame_debug_printf (" -> %s // cached",
- this_frame->prev->to_string ().c_str ());
+ if (this_frame->prev != nullptr)
+ frame_debug_printf (" -> %s // cached",
+ this_frame->prev->to_string ().c_str ());
+ else
+ frame_debug_printf
+ (" -> nullptr // %s // cached",
+ frame_stop_reason_symbol_string (this_frame->stop_reason));
return this_frame->prev;
}
@@ -2515,22 +2520,6 @@ get_prev_frame (struct frame_info *this_frame)
return get_prev_frame_always (this_frame);
}
-struct frame_id
-get_prev_frame_id_by_id (struct frame_id id)
-{
- struct frame_id prev_id;
- struct frame_info *frame;
-
- frame = frame_find_by_id (id);
-
- if (frame != NULL)
- prev_id = get_frame_id (get_prev_frame (frame));
- else
- prev_id = null_frame_id;
-
- return prev_id;
-}
-
CORE_ADDR
get_frame_pc (struct frame_info *frame)
{
diff --git a/gdb/frame.h b/gdb/frame.h
index 0d2bc08a47b..2548846c1ed 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -394,10 +394,6 @@ extern struct frame_info *get_prev_frame_always (struct frame_info *);
is not found. */
extern struct frame_info *frame_find_by_id (struct frame_id id);
-/* Given a frame's ID, find the previous frame's ID. Returns null_frame_id
- if the frame is not found. */
-extern struct frame_id get_prev_frame_id_by_id (struct frame_id id);
-
/* Base attributes of a frame: */
/* The frame's `resume' address. Where the program will resume in
diff --git a/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp b/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp
index bf2a2a79756..1c0826201bb 100644
--- a/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp
+++ b/gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp
@@ -51,3 +51,22 @@ set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
gdb_test_no_output "source ${pyfile}" "load python file"
gdb_test "p some_func ()" " = 0"
+
+# When frame debugging is turned on, this test has (previously)
+# revealed some crashes due to the Python frame unwinder trying to
+# read registers.
+#
+# Enable frame debug and rerun the test. We don't bother checking the
+# output of calling 'p some_func ()' as the output will be full of
+# debug, to format of which isn't fixed. All we care about is that
+# GDB is still running afterwards.
+#
+# All of the debug output makes this really slow when testing with the
+# special read1 version of expect, hence the timeout factor.
+with_read1_timeout_factor 10 {
+ gdb_test_no_output "set debug frame on"
+ gdb_test "p some_func ()" ".*" \
+ "repeat p some_func () with frame debug on"
+ gdb_test_no_output "set debug frame off"
+}
+gdb_test "p 1 + 2 + 3" " = 6"
diff --git a/gdb/valops.c b/gdb/valops.c
index bd547923496..50874a5f55d 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1197,14 +1197,15 @@ value_assign (struct value *toval, struct value *fromval)
struct gdbarch *gdbarch;
int value_reg;
- /* Figure out which frame this is in currently.
-
- We use VALUE_FRAME_ID for obtaining the value's frame id instead of
- VALUE_NEXT_FRAME_ID due to requiring a frame which may be passed to
- put_frame_register_bytes() below. That function will (eventually)
- perform the necessary unwind operation by first obtaining the next
- frame. */
- frame = frame_find_by_id (VALUE_FRAME_ID (toval));
+ /* Figure out which frame this register value is in. The value
+ holds the frame_id for the next frame, that is the frame this
+ register value was unwound from.
+
+ Below we will call put_frame_register_bytes which requires that
+ we pass it the actual frame in which the register value is
+ valid, i.e. not the next frame. */
+ frame = frame_find_by_id (VALUE_NEXT_FRAME_ID (toval));
+ frame = get_prev_frame_always (frame);
value_reg = VALUE_REGNUM (toval);
diff --git a/gdb/value.c b/gdb/value.c
index 6a07495d32b..91db66fa3be 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3950,9 +3950,8 @@ value_fetch_lazy_register (struct value *val)
{
struct gdbarch *gdbarch;
struct frame_info *frame;
- /* VALUE_FRAME_ID is used here, instead of VALUE_NEXT_FRAME_ID,
- so that the frame level will be shown correctly. */
- frame = frame_find_by_id (VALUE_FRAME_ID (val));
+ frame = frame_find_by_id (VALUE_NEXT_FRAME_ID (val));
+ frame = get_prev_frame_always (frame);
regnum = VALUE_REGNUM (val);
gdbarch = get_frame_arch (frame);
diff --git a/gdb/value.h b/gdb/value.h
index 379cddafbe7..e1c6aabfa29 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -458,12 +458,6 @@ extern struct internalvar **deprecated_value_internalvar_hack (struct value *);
extern struct frame_id *deprecated_value_next_frame_id_hack (struct value *);
#define VALUE_NEXT_FRAME_ID(val) (*deprecated_value_next_frame_id_hack (val))
-/* Frame ID of frame to which a register value is relative. This is
- similar to VALUE_NEXT_FRAME_ID, above, but may not be assigned to.
- Note that VALUE_FRAME_ID effectively undoes the "next" operation
- that was performed during the assignment to VALUE_NEXT_FRAME_ID. */
-#define VALUE_FRAME_ID(val) (get_prev_frame_id_by_id (VALUE_NEXT_FRAME_ID (val)))
-
/* Register number if the value is from a register. */
extern int *deprecated_value_regnum_hack (struct value *);
#define VALUE_REGNUM(val) (*deprecated_value_regnum_hack (val))