summaryrefslogtreecommitdiff
path: root/src/dwarf/Gparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dwarf/Gparser.c')
-rw-r--r--src/dwarf/Gparser.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c
index 1ce862c2..fe7c5817 100644
--- a/src/dwarf/Gparser.c
+++ b/src/dwarf/Gparser.c
@@ -734,7 +734,7 @@ create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
}
static inline int
-eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as,
+eval_location_expr (struct dwarf_cursor *c, unw_word_t stack_val, unw_addr_space_t as,
unw_accessors_t *a, unw_word_t addr,
dwarf_loc_t *locp, void *arg)
{
@@ -746,7 +746,7 @@ eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as,
return ret;
/* evaluate the expression: */
- if ((ret = dwarf_eval_expr (c, &addr, len, &val, &is_register)) < 0)
+ if ((ret = dwarf_eval_expr (c, stack_val, &addr, len, &val, &is_register)) < 0)
return ret;
if (is_register)
@@ -804,7 +804,10 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
assert (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR);
addr = rs->reg.val[DWARF_CFA_REG_COLUMN];
- if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0)
+ /* The dwarf standard doesn't specify an initial value to be pushed on */
+ /* the stack before DW_CFA_def_cfa_expression evaluation. We push on a */
+ /* dummy value (0) to keep the eval_location_expr function consistent. */
+ if ((ret = eval_location_expr (c, 0, as, a, addr, &cfa_loc, arg)) < 0)
return ret;
/* the returned location better be a memory location... */
if (DWARF_IS_REG_LOC (cfa_loc))
@@ -844,13 +847,17 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
case DWARF_WHERE_EXPR:
addr = rs->reg.val[i];
- if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
+ /* The dwarf standard requires the current CFA to be pushed on the */
+ /* stack before DW_CFA_expression evaluation. */
+ if ((ret = eval_location_expr (c, cfa, as, a, addr, new_loc + i, arg)) < 0)
return ret;
break;
case DWARF_WHERE_VAL_EXPR:
addr = rs->reg.val[i];
- if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
+ /* The dwarf standard requires the current CFA to be pushed on the */
+ /* stack before DW_CFA_val_expression evaluation. */
+ if ((ret = eval_location_expr (c, cfa, as, a, addr, new_loc + i, arg)) < 0)
return ret;
new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i]));
break;