aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2/loc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dwarf2/loc.c')
-rw-r--r--gdb/dwarf2/loc.c52
1 files changed, 29 insertions, 23 deletions
diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
index ecda7a6..5fe1884 100644
--- a/gdb/dwarf2/loc.c
+++ b/gdb/dwarf2/loc.c
@@ -1867,21 +1867,19 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
std::vector<const gdb_byte *> ops_to_visit;
/* Operations already visited. */
- gdb::unordered_set<const gdb_byte *> visited_ops;
+ std::vector<bool> visited_ops (expr.size (), false);
/* Insert OP in OPS_TO_VISIT if it is within the expression's range and
hasn't been visited yet. */
- auto insert_in_ops_to_visit
- = [expr_end, &visited_ops, &ops_to_visit] (const gdb_byte *op_ptr)
- {
- if (op_ptr >= expr_end)
- return;
+ auto insert_in_ops_to_visit = [&] (const gdb_byte *op_ptr)
+ {
+ size_t off = op_ptr - expr.data ();
- if (visited_ops.find (op_ptr) != visited_ops.end ())
- return;
+ if (off >= expr.size () || visited_ops[off])
+ return;
- ops_to_visit.push_back (op_ptr);
- };
+ ops_to_visit.push_back (op_ptr);
+ };
/* Expressions can invoke other expressions with DW_OP_call*. Protect against
a loop of calls. */
@@ -1892,17 +1890,24 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
depth++;
- /* Initialize the to-visit list with the first operation. */
- insert_in_ops_to_visit (&expr[0]);
-
- while (!ops_to_visit.empty ())
+ const gdb_byte *op_ptr = &expr[0];
+ while (op_ptr != nullptr || !ops_to_visit.empty ())
{
- /* Pop one op to visit, mark it as visited. */
- const gdb_byte *op_ptr = ops_to_visit.back ();
- ops_to_visit.pop_back ();
- if (visited_ops.find (op_ptr) != visited_ops.end ())
- continue;
- visited_ops.insert (op_ptr);
+ /* If the previous operation fell through, just keep going.
+ Otherwise pop the next op to visit. */
+ if (op_ptr == nullptr)
+ {
+ op_ptr = ops_to_visit.back ();
+ ops_to_visit.pop_back ();
+ }
+
+ size_t pc = op_ptr - expr.data ();
+ if (visited_ops[pc])
+ {
+ op_ptr = nullptr;
+ continue;
+ }
+ visited_ops[pc] = true;
dwarf_location_atom op = (dwarf_location_atom) *op_ptr;
@@ -2153,8 +2158,7 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
op_ptr += 2;
insert_in_ops_to_visit (op_ptr + offset);
- insert_in_ops_to_visit (op_ptr);
- continue;
+ break;
}
case DW_OP_call2:
@@ -2267,7 +2271,9 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
if (symbol_needs == SYMBOL_NEEDS_FRAME)
break;
- insert_in_ops_to_visit (op_ptr);
+ /* Don't run off the end. */
+ if (op_ptr >= expr_end)
+ op_ptr = nullptr;
}
return symbol_needs;