|
|
2c2fa1 |
commit 6eeee81c8e59511962bdd83df5e7785bfdf871d2
|
|
|
2c2fa1 |
Author: Tom Tromey <tromey@redhat.com>
|
|
|
2c2fa1 |
Date: Fri Nov 22 17:38:44 2013 +0000
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Detect infinite loop in value_fetch_lazy's lval_register handling.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
If value_fetch_lazy loops infinitely while unwrapping lval_register
|
|
|
2c2fa1 |
values, it means we either somehow ended up with two frames with the
|
|
|
2c2fa1 |
same ID in the frame chain, or some code is trying to unwind behind
|
|
|
2c2fa1 |
get_prev_frame's back (e.g., a frame unwind sniffer trying to unwind).
|
|
|
2c2fa1 |
In any case, it should always be an internal error to end up in this
|
|
|
2c2fa1 |
situation.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
This patch adds a check and throws an internal error if the same frame
|
|
|
2c2fa1 |
is returned.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
2013-11-22 Tom Tromey <tromey@redhat.com>
|
|
|
2c2fa1 |
Pedro Alves <palves@redhat.com>
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
PR backtrace/16155
|
|
|
2c2fa1 |
* value.c (value_fetch_lazy): Internal error if
|
|
|
2c2fa1 |
get_frame_register_value returns the same register.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/valops.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/valops.c
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/valops.c
|
|
|
2c2fa1 |
@@ -1093,7 +1093,9 @@ value_fetch_lazy (struct value *val)
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
- frame = frame_find_by_id (VALUE_FRAME_ID (new_val));
|
|
|
2c2fa1 |
+ struct frame_id frame_id = VALUE_FRAME_ID (new_val);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ frame = frame_find_by_id (frame_id);
|
|
|
2c2fa1 |
regnum = VALUE_REGNUM (new_val);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
gdb_assert (frame != NULL);
|
|
|
2c2fa1 |
@@ -1107,6 +1109,22 @@ value_fetch_lazy (struct value *val)
|
|
|
2c2fa1 |
regnum, type));
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
new_val = get_frame_register_value (frame, regnum);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ /* If we get another lazy lval_register value, it means the
|
|
|
2c2fa1 |
+ register is found by reading it from the next frame.
|
|
|
2c2fa1 |
+ get_frame_register_value should never return a value with
|
|
|
2c2fa1 |
+ the frame id pointing to FRAME. If it does, it means we
|
|
|
2c2fa1 |
+ either have two consecutive frames with the same frame id
|
|
|
2c2fa1 |
+ in the frame chain, or some code is trying to unwind
|
|
|
2c2fa1 |
+ behind get_prev_frame's back (e.g., a frame unwind
|
|
|
2c2fa1 |
+ sniffer trying to unwind), bypassing its validations. In
|
|
|
2c2fa1 |
+ any case, it should always be an internal error to end up
|
|
|
2c2fa1 |
+ in this situation. */
|
|
|
2c2fa1 |
+ if (VALUE_LVAL (new_val) == lval_register
|
|
|
2c2fa1 |
+ && value_lazy (new_val)
|
|
|
2c2fa1 |
+ && frame_id_eq (VALUE_FRAME_ID (new_val), frame_id))
|
|
|
2c2fa1 |
+ internal_error (__FILE__, __LINE__,
|
|
|
2c2fa1 |
+ _("infinite loop while fetching a register"));
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* If it's still lazy (for instance, a saved register on the
|