diff options
-rw-r--r-- | gdb/frame.c | 25 | ||||
-rw-r--r-- | gdb/frame.h | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp | 19 | ||||
-rw-r--r-- | gdb/valops.c | 17 | ||||
-rw-r--r-- | gdb/value.c | 5 | ||||
-rw-r--r-- | gdb/value.h | 6 |
6 files changed, 37 insertions, 39 deletions
diff --git a/gdb/frame.c b/gdb/frame.c index 3f2d270..2332418 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 0d2bc08..2548846 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 bf2a2a7..1c08262 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 bd54792..50874a5 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 6a07495..91db66f 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 379cdda..e1c6aab 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)) |