PROTECTED int unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) { struct cursor *c = (struct cursor *) cursor; dwarf_loc_t loc; loc = DWARF_NULL_LOC; /* default to "not saved" */ #warning FIX ME! memset (sloc, 0, sizeof (sloc)); if (DWARF_IS_NULL_LOC (loc)) { sloc->type = UNW_SLT_NONE; return 0; } #if !defined(UNW_LOCAL_ONLY) if (DWARF_IS_REG_LOC (loc)) { sloc->type = UNW_SLT_REG; sloc->u.regnum = DWARF_GET_LOC (loc); } else #endif { sloc->type = UNW_SLT_MEMORY; sloc->u.addr = DWARF_GET_LOC (loc); } return 0; }
PROTECTED int unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) { struct cursor *c = (struct cursor *) cursor; dwarf_loc_t loc; switch (reg) { case UNW_SH_R0: case UNW_SH_R1: case UNW_SH_R2: case UNW_SH_R3: case UNW_SH_R4: case UNW_SH_R5: case UNW_SH_R6: case UNW_SH_R7: case UNW_SH_R8: case UNW_SH_R9: case UNW_SH_R10: case UNW_SH_R11: case UNW_SH_R12: case UNW_SH_R13: case UNW_SH_R14: case UNW_SH_R15: case UNW_SH_PC: case UNW_SH_PR: loc = c->dwarf.loc[reg]; break; default: loc = DWARF_NULL_LOC; /* default to "not saved" */ break; } memset (sloc, 0, sizeof (*sloc)); if (DWARF_IS_NULL_LOC (loc)) { sloc->type = UNW_SLT_NONE; return 0; } #if !defined(UNW_LOCAL_ONLY) if (DWARF_IS_REG_LOC (loc)) { sloc->type = UNW_SLT_REG; sloc->u.regnum = DWARF_GET_LOC (loc); } else #endif { sloc->type = UNW_SLT_MEMORY; sloc->u.addr = DWARF_GET_LOC (loc); } return 0; }
PROTECTED int unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) { struct cursor *c = (struct cursor *) cursor; dwarf_loc_t loc; loc = DWARF_NULL_LOC; /* default to "not saved" */ switch (reg) { case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break; case UNW_X86_64_RSP: loc = c->dwarf.loc[RSP]; break; case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break; case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break; case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break; case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break; case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break; default: break; } memset (sloc, 0, sizeof (unw_save_loc_t)); if (DWARF_IS_NULL_LOC (loc)) { sloc->type = UNW_SLT_NONE; return 0; } #if !defined(UNW_LOCAL_ONLY) if (DWARF_IS_REG_LOC (loc)) { sloc->type = UNW_SLT_REG; sloc->u.regnum = DWARF_GET_LOC (loc); } else #endif { sloc->type = UNW_SLT_MEMORY; sloc->u.addr = DWARF_GET_LOC (loc); } return 0; }
static int apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) { unw_word_t regnum, addr, cfa, ip; unw_word_t prev_ip, prev_cfa; unw_addr_space_t as; dwarf_loc_t cfa_loc; unw_accessors_t *a; int i, ret; void *arg; prev_ip = c->ip; prev_cfa = c->cfa; as = c->as; arg = c->as_arg; a = unw_get_accessors (as); /* Evaluate the CFA first, because it may be referred to by other expressions. */ if (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG) { /* CFA is equal to [reg] + offset: */ /* As a special-case, if the stack-pointer is the CFA and the stack-pointer wasn't saved, popping the CFA implicitly pops the stack-pointer as well. */ if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP) && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg)) && (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME)) cfa = c->cfa; else { regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val); if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0) return ret; } cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val; } else { /* CFA is equal to EXPR: */ assert (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_EXPR); addr = rs->reg[DWARF_CFA_REG_COLUMN].val; if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0) return ret; /* the returned location better be a memory location... */ if (DWARF_IS_REG_LOC (cfa_loc)) return -UNW_EBADFRAME; cfa = DWARF_GET_LOC (cfa_loc); } for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) { switch ((dwarf_where_t) rs->reg[i].where) { case DWARF_WHERE_UNDEF: c->loc[i] = DWARF_NULL_LOC; break; case DWARF_WHERE_SAME: break; case DWARF_WHERE_CFAREL: c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val); break; case DWARF_WHERE_REG: c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val)); break; case DWARF_WHERE_EXPR: addr = rs->reg[i].val; if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0) return ret; break; case DWARF_WHERE_VAL_EXPR: addr = rs->reg[i].val; if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0) return ret; c->loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (c->loc[i])); break; } } c->cfa = cfa; /* DWARF spec says undefined return address location means end of stack. */ if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column])) c->ip = 0; else { ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip); if (ret < 0) return ret; c->ip = ip; } /* XXX: check for ip to be code_aligned */ if (c->ip == prev_ip && c->cfa == prev_cfa) { Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", __FUNCTION__, (long) c->ip); return -UNW_EBADFRAME; } if (c->stash_frames) tdep_stash_frame (c, rs); return 0; }