diff options
author | Kevin Buettner <kevinb@redhat.com> | 2016-09-27 21:18:44 -0700 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2016-11-16 11:38:19 -0700 |
commit | 41b56feb5063aee4fefb4a991eb796d1e8a7475e (patch) | |
tree | ca88891a5d6ab514db31652af8d3093386b25f58 /gdb/value.c | |
parent | df433d316277ff5293832d3cd6cbc30b5c38dec0 (diff) | |
download | gdb-41b56feb5063aee4fefb4a991eb796d1e8a7475e.zip gdb-41b56feb5063aee4fefb4a991eb796d1e8a7475e.tar.gz gdb-41b56feb5063aee4fefb4a991eb796d1e8a7475e.tar.bz2 |
Change meaning of VALUE_FRAME_ID; rename to VALUE_NEXT_FRAME_ID
The VALUE_FRAME_ID macro provides access to a member in struct value
that's used to hold the frame id that's used when determining a
register's value or when assigning to a register. The underlying
member has a long and obscure name. I won't refer to it here, but
will simply refer to VALUE_FRAME_ID as if it's the struct value member
instead of being a convenient macro.
At the moment, without this patch in place, VALUE_FRAME_ID is set in
value_of_register_lazy() and several other locations to hold the frame
id of the frame passed to those functions.
VALUE_FRAME_ID is used in the lval_register case of
value_fetch_lazy(). To fetch the register's value, it calls
get_frame_register_value() which, in turn, calls
frame_unwind_register_value() with frame->next.
A python based unwinder may wish to determine the value of a register
or evaluate an expression containing a register. When it does this,
value_fetch_lazy() will be called under some circumstances. It will
attempt to determine the frame id associated with the frame passed to
it. In so doing, it will end up back in the frame sniffer of the very
same python unwinder that's attempting to learn the value of a
register as part of the sniffing operation. This recursion is not
desirable.
As noted above, when value_fetch_lazy() wants to fetch a register's
value, it does so (indirectly) by unwinding from frame->next.
With this in mind, a solution suggests itself: Change VALUE_FRAME_ID
to hold the frame id associated with the next frame. Then, when it
comes time to obtain the value associated with the register, we can
simply unwind from the frame corresponding to the frame id stored in
VALUE_FRAME_ID. This neatly avoids the python unwinder recursion
problem by changing when the "next" operation occurs. Instead of the
"next" operation occuring when the register value is fetched, it
occurs earlier on when assigning a frame id to VALUE_FRAME_ID.
(Thanks to Pedro for this suggestion.)
This patch implements this idea.
It builds on the patch "Distinguish sentinel frame from null frame".
Without that work in place, it's necessary to check for null_id at
several places and then obtain the sentinel frame.
It also renames most occurences of VALUE_FRAME_ID to
VALUE_NEXT_FRAME_ID to reflect the new meaning of this field.
There are several uses of VALUE_FRAME_ID which were not changed. In
each case, the original meaning of VALUE_FRAME_ID is required to get
correct results. In all but one of these uses, either
put_frame_register_bytes() or get_frame_register_bytes() is being
called with the frame value obtained from VALUE_FRAME_ID. Both of
these functions perform some unwinding by performing a "->next"
operation on the frame passed to it. If we were to use the new
VALUE_NEXT_FRAME_ID macro, this would effectively do two "->next"
operations, which is not what we want.
The VALUE_FRAME_ID macro has been redefined in terms of
VALUE_NEXT_FRAME_ID. It simply fetches the previous frame's id,
providing this id as the value of the macro.
gdb/ChangeLog:
* value.h (VALUE_FRAME_ID): Rename to VALUE_NEXT_FRAME_ID. Update
comment. Create new VALUE_FRAME_ID which is defined in terms of
VALUE_NEXT_FRAME_ID.
(deprecated_value_frame_id_hack): Rename to
deprecated_value_next_frame_id_hack.
* dwarf2loc.c, findvar.c, frame-unwind.c, sentinel-frame.c,
valarith.c, valops.c, value.c: Adjust nearly all occurences of
VALUE_FRAME_ID to VALUE_NEXT_FRAME_ID. Add comments for those
which did not change.
* value.c (struct value): Rename frame_id field to next_frame_id.
Update comment.
(deprecated_value_frame_id_hack): Rename to
deprecated_value_next_frame_id_hack.
(value_fetch_lazy): Call frame_unwind_register_value()
instead of get_frame_register_value().
* frame.c (get_prev_frame_id_by_id): New function.
* frame.h (get_prev_frame_id_by_id): Declare.
* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Make
VALUE_NEXT_FRAME_ID refer to the next frame.
* findvar.c (value_of_register_lazy): Likewise.
(default_value_from_register): Likewise.
(value_from_register): Likewise.
* frame_unwind.c (frame_unwind_got_optimized): Likewise.
* sentinel-frame.c (sentinel_frame_prev_register): Likewise.
* value.h (VALUE_FRAME_ID): Update comment describing this macro.
Diffstat (limited to 'gdb/value.c')
-rw-r--r-- | gdb/value.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/gdb/value.c b/gdb/value.c index 62c5e37..0575a55 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -262,9 +262,11 @@ struct value bitfields. */ struct value *parent; - /* Frame register value is relative to. This will be described in - the lval enum above as "lval_register". */ - struct frame_id frame_id; + /* Frame ID of "next" frame to which a register value is relative. A + register value is indicated when the lval enum (above) is set to + lval_register. So, if the register value is found relative to frame F, + then the frame id of F->next will be stored in next_frame_id. */ + struct frame_id next_frame_id; /* Type of the value. */ struct type *type; @@ -943,7 +945,7 @@ allocate_value_lazy (struct type *type) val->enclosing_type = type; VALUE_LVAL (val) = not_lval; val->location.address = 0; - VALUE_FRAME_ID (val) = null_frame_id; + VALUE_NEXT_FRAME_ID (val) = null_frame_id; val->offset = 0; val->bitpos = 0; val->bitsize = 0; @@ -1582,9 +1584,9 @@ deprecated_value_internalvar_hack (struct value *value) } struct frame_id * -deprecated_value_frame_id_hack (struct value *value) +deprecated_value_next_frame_id_hack (struct value *value) { - return &value->frame_id; + return &value->next_frame_id; } short * @@ -1786,7 +1788,7 @@ value_copy (struct value *arg) val->offset = arg->offset; val->bitpos = arg->bitpos; val->bitsize = arg->bitsize; - VALUE_FRAME_ID (val) = VALUE_FRAME_ID (arg); + VALUE_NEXT_FRAME_ID (val) = VALUE_NEXT_FRAME_ID (arg); VALUE_REGNUM (val) = VALUE_REGNUM (arg); val->lazy = arg->lazy; val->embedded_offset = value_embedded_offset (arg); @@ -3228,7 +3230,7 @@ value_primitive_field (struct value *arg1, LONGEST offset, } set_value_component_location (v, arg1); VALUE_REGNUM (v) = VALUE_REGNUM (arg1); - VALUE_FRAME_ID (v) = VALUE_FRAME_ID (arg1); + VALUE_NEXT_FRAME_ID (v) = VALUE_NEXT_FRAME_ID (arg1); return v; } @@ -3974,7 +3976,7 @@ value_fetch_lazy (struct value *val) } else if (VALUE_LVAL (val) == lval_register) { - struct frame_info *frame; + struct frame_info *next_frame; int regnum; struct type *type = check_typedef (value_type (val)); struct value *new_val = val, *mark = value_mark (); @@ -3985,27 +3987,33 @@ value_fetch_lazy (struct value *val) while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val)) { - struct frame_id frame_id = VALUE_FRAME_ID (new_val); + struct frame_id next_frame_id = VALUE_NEXT_FRAME_ID (new_val); - frame = frame_find_by_id (frame_id); + next_frame = frame_find_by_id (next_frame_id); regnum = VALUE_REGNUM (new_val); - gdb_assert (frame != NULL); + gdb_assert (next_frame != NULL); /* Convertible register routines are used for multi-register values and for interpretation in different types (e.g. float or int from a double register). Lazy register values should have the register's natural type, so they do not apply. */ - gdb_assert (!gdbarch_convert_register_p (get_frame_arch (frame), + gdb_assert (!gdbarch_convert_register_p (get_frame_arch (next_frame), regnum, type)); - new_val = get_frame_register_value (frame, regnum); + /* FRAME was obtained, above, via VALUE_NEXT_FRAME_ID. + Since a "->next" operation was performed when setting + this field, we do not need to perform a "next" operation + again when unwinding the register. That's why + frame_unwind_register_value() is called here instead of + get_frame_register_value(). */ + new_val = frame_unwind_register_value (next_frame, regnum); /* If we get another lazy lval_register value, it means the - register is found by reading it from the next frame. - get_frame_register_value should never return a value with - the frame id pointing to FRAME. If it does, it means we + register is found by reading it from NEXT_FRAME's next frame. + frame_unwind_register_value should never return a value with + the frame id pointing to NEXT_FRAME. If it does, it means we either have two consecutive frames with the same frame id in the frame chain, or some code is trying to unwind behind get_prev_frame's back (e.g., a frame unwind @@ -4014,7 +4022,7 @@ value_fetch_lazy (struct value *val) in this situation. */ if (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val) - && frame_id_eq (VALUE_FRAME_ID (new_val), frame_id)) + && frame_id_eq (VALUE_NEXT_FRAME_ID (new_val), next_frame_id)) internal_error (__FILE__, __LINE__, _("infinite loop while fetching a register")); } @@ -4034,6 +4042,9 @@ value_fetch_lazy (struct value *val) if (frame_debug) { 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)); regnum = VALUE_REGNUM (val); gdbarch = get_frame_arch (frame); |