Fix dwarf2 "assertion failed" on bra without skip dwarf expression op
authorJaro Fietz <jaro.fietz@gmx.de>
Fri, 14 Nov 2025 20:55:08 +0000 (21:55 +0100)
committerTom Tromey <tromey@adacore.com>
Thu, 20 Nov 2025 16:06:09 +0000 (09:06 -0700)
When interpreting dwarf expressions, the function
dwarf2_get_symbol_read_needs walks over all instructions via
the call graph by using a to-visit and a visited list.
Upon reaching a bra operation, it pushes both the next op and the
branch target into the to-visit list.
If the branch-target can be reached linearly from the next op,
the branch-target will be visited twice.

At the top of the visit-loop, there is an assertion that a visited
instruction must never be visited again.
This assertion fails in the above case.

For example a DIE with DW_AT_location: 30 31 28 0 0 9f
(DW_OP_lit0; DW_OP_lit1; DW_OP_bra: 0; DW_OP_stack_value)
will result in
.././binutils-gdb/gdb/dwarf2/loc.c:1905: internal-error: dwarf2_get_symbol_read_needs: Assertion `visited_ops.find (op_ptr) == visited_ops.end ()' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.

Adding a skip operation which makes the branch-target not linearly
accessible from the next op, makes the example work. For example a
DIE with DW_AT_location: 32 31 28 3 0 2f 1 0 96 9f (DW_OP_lit2;
DW_OP_lit1; DW_OP_bra: 3; DW_OP_skip: 1; DW_OP_nop; DW_OP_stack_value)
produces the correct result $1 = 2.

This patch replaces the failing assertion with a continue to properly
skip an already visited dwarf expression op.
This makes the first example work correctly and result in $1 = 0.

Running the testsuite resulted in different results upon every run
(arch-linux 6.17.7-arch1-1 x86_64).
Comparing the results of 3 runs of the unmodified code with three
runs containing the fix does not yield a significant difference:

unmodified version: # of expected passes 126821, 126813, 126838
fix version: # of expected passes 126866, 126801, 126817

Approved-By: Tom Tromey <tom@tromey.com>
gdb/dwarf2/loc.c

index 86e8a2f46385ae2a2a4292582654ead02cc709a1..3afb6b0abf7ad0c6404cfae0a798eb7b376059b2 100644 (file)
@@ -1902,7 +1902,8 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
       /* Pop one op to visit, mark it as visited.  */
       const gdb_byte *op_ptr = ops_to_visit.back ();
       ops_to_visit.pop_back ();
-      gdb_assert (visited_ops.find (op_ptr) == visited_ops.end ());
+      if (visited_ops.find (op_ptr) != visited_ops.end ())
+       continue;
       visited_ops.insert (op_ptr);
 
       dwarf_location_atom op = (dwarf_location_atom) *op_ptr;
This page took 0.092285 seconds and 5 git commands to generate.