diff options
author | Stephan Rohr <stephan.rohr@intel.com> | 2025-08-20 06:06:23 -0700 |
---|---|---|
committer | Stephan Rohr <stephan.rohr@intel.com> | 2025-09-24 01:31:52 -0700 |
commit | 3a3c3a0e7280ef8907d62ea83706a2ef3081831b (patch) | |
tree | 70c20a5448526e6d61dbd4c30a4349a0782b2c41 /gdb/python/python.c | |
parent | 4c47471ba4cfd59206ce1cb33ae2f19ced2f29cd (diff) | |
download | binutils-3a3c3a0e7280ef8907d62ea83706a2ef3081831b.zip binutils-3a3c3a0e7280ef8907d62ea83706a2ef3081831b.tar.gz binutils-3a3c3a0e7280ef8907d62ea83706a2ef3081831b.tar.bz2 |
gdb: resolve type to target_type in expression evaluation
If an expression is evaluated with 'EVAL_AVOID_SIDE_EFFECTS', we're
essentially interested in compatibility of the operands. If there is an
operand of reference type, this would give us a memory value that would
cause a failure if GDB attempts to access the contents.
GDB fails to evaluate binary expressions for the following example:
struct
{
int &get () { return x; };
int x = 1;
} v_struct;
The GDB output is:
(gdb) print v_struct3.get () == 1 && v_struct3.get () == 2
Cannot access memory at address 0x0
(gdb) print v_struct3.get () == 1 || v_struct3.get () == 2
Cannot access memory at address 0x0
Likewise, GDB fails to resolve the type for some expressions:
(gdb) ptype v_struct.get ()
type = int &
(gdb) ptype v_struct.get () == 1
Cannot access memory at address 0x0
(gdb) ptype v_struct.get () + 1
Cannot access memory at address 0x0
(gdb) ptype v_struct.get () && 1
Cannot access memory at address 0x0
(gdb) ptype v_struct.get () || 1
Cannot access memory at address 0x0
(gdb) ptype !v_struct.get ()
Cannot access memory at address 0x0
(gdb) ptype v_struct.get () ? 2 : 3
Cannot access memory at address 0x0
(gdb) ptype v_struct.get () | 1
Cannot access memory at address 0x0
Expression evaluation uses helper functions such as 'value_equal',
'value_logical_not', etc. These helper functions do not take a 'noside'
argument and if one of their value arguments was created from a function
call that returns a reference type when noside == EVAL_AVOID_SIDE_EFFECTS,
GDB attempts to read from an invalid memory location. Consider the
following call stack of the 'ptype v_struct.get () + 1' command at the time
of assertion when the memory error is raised:
#0 memory_error (err=TARGET_XFER_E_IO, memaddr=0) at gdb/corefile.c:114
#1 read_value_memory (val=.., bit_offset=0, stack=false, memaddr=0,
buffer=.. "", length=4) at gdb/valops.c:1075
#2 value::fetch_lazy_memory (this=..) at gdb/value.c:3996
#3 value::fetch_lazy (this=..) at gdb/value.c:4135
#4 value::contents_writeable (this=..) at gdb/value.c:1329
#5 value::contents (this=..) at gdb/value.c:1319
#6 value_as_mpz (val=..) at gdb/value.c:2685
#7 scalar_binop (arg1=.., arg2=.., op=BINOP_ADD) at gdb/valarith.c:1240
#8 value_binop (arg1=.., arg2=.., op=BINOP_ADD) at gdb/valarith.c:1489
#9 eval_op_add (expect_type=0x0, exp=.., noside=EVAL_AVOID_SIDE_EFFECTS,
arg1=.., arg2=..) at gdb/eval.c:1333
#10 expr::add_operation::evaluate (this=.., expect_type=0x0, exp=..,
noside=EVAL_AVOID_SIDE_EFFECTS) at gdb/expop.h:1209
#11 expression::evaluate (this=.., expect_type=0x0,
noside=EVAL_AVOID_SIDE_EFFECTS) at gdb/eval.c:110
#12 expression::evaluate_type (this=..) at gdb/expression.h:242
'add_operation::evaluate' calls the helper 'eval_op_add' which attempts
to read from the unresolved memory location. Convert to the target type
to avoid such problems. The patch is implemented in 'expop.h' for the
following reasons:
* Support templated classes without explicit helpers, e.g.,
'binop_operation' and 'comparison_operation'.
* Stripping references in 'binop_promote' requires additional
refactoring beyond this patch as we would need to carry on the
'noside' parameter.
The above failures are resolved with the patch:
(gdb) print v_struct.get () == 1 && v_struct3.get () == 2
$1 = false
(gdb) print v_struct.get () == 1 || v_struct3.get () == 2
$2 = true
(gdb) ptype v_struct.get ()
type = int &
(gdb) ptype v_struct.get () == 1
type = bool
(gdb) ptype v_struct.get () + 1
type = int
(gdb) ptype v_struct.get () && 1
type = bool
(gdb) ptype v_struct.get () || 1
type = bool
(gdb) ptype !v_struct.get ()
type = bool
(gdb) ptype v_struct.get () ? 2 : 3
type = int
(gdb) ptype v_struct.get () | 1
type = int
Co-Authored-By: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb/python/python.c')
0 files changed, 0 insertions, 0 deletions