From cc27559a20f4238a0f3fb31c02dbd2c9fecaed65 Mon Sep 17 00:00:00 2001 From: Jaro Fietz Date: Fri, 14 Nov 2025 21:55:08 +0100 Subject: [PATCH] Fix dwarf2 "assertion failed" on bra without skip dwarf expression op 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 --- gdb/dwarf2/loc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index 86e8a2f4638..3afb6b0abf7 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -1902,7 +1902,8 @@ dwarf2_get_symbol_read_needs (gdb::array_view 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; -- 2.47.3