Beispiel #1
0
HIDDEN void
tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
{
  struct cursor *c = (struct cursor *) dwarf_to_cursor (d);
  unw_tdep_frame_t *f = &c->frame_info;

  Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
         " ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] "
         "sp [where=%d val=%ld @0x%lx]\n",
         d->ip, d->cfa, f->frame_type,
         rs->reg.where[DWARF_CFA_REG_COLUMN],
         rs->reg.val[DWARF_CFA_REG_COLUMN],
         rs->reg.val[DWARF_CFA_OFF_COLUMN],
         DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
         rs->reg.where[FP], rs->reg.val[FP], DWARF_GET_LOC(d->loc[FP]),
         rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]),
         rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP]));

  /* A standard frame is defined as:
      - CFA is register-relative offset off FP or SP;
      - Return address is saved in LR;
      - FP is unsaved or saved at CFA+offset, offset != -1;
      - LR is unsaved or saved at CFA+offset, offset != -1;
      - SP is unsaved or saved at CFA+offset, offset != -1.  */
  if (f->frame_type == UNW_AARCH64_FRAME_OTHER
      && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
      && (rs->reg.val[DWARF_CFA_REG_COLUMN] == FP
          || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP)
      && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29)
      && rs->ret_addr_column == LR
      && (rs->reg.where[FP] == DWARF_WHERE_UNDEF
          || rs->reg.where[FP] == DWARF_WHERE_SAME
          || (rs->reg.where[FP] == DWARF_WHERE_CFAREL
              && labs(rs->reg.val[FP]) < (1 << 29)
              && rs->reg.val[FP]+1 != 0))
      && (rs->reg.where[LR] == DWARF_WHERE_UNDEF
          || rs->reg.where[LR] == DWARF_WHERE_SAME
          || (rs->reg.where[LR] == DWARF_WHERE_CFAREL
              && labs(rs->reg.val[LR]) < (1 << 29)
              && rs->reg.val[LR]+1 != 0))
      && (rs->reg.where[SP] == DWARF_WHERE_UNDEF
          || rs->reg.where[SP] == DWARF_WHERE_SAME
          || (rs->reg.where[SP] == DWARF_WHERE_CFAREL
              && labs(rs->reg.val[SP]) < (1 << 29)
              && rs->reg.val[SP]+1 != 0)))
  {
    /* Save information for a standard frame. */
    f->frame_type = UNW_AARCH64_FRAME_STANDARD;
    f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP);
    f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
    if (rs->reg.where[FP] == DWARF_WHERE_CFAREL)
      f->fp_cfa_offset = rs->reg.val[FP];
    if (rs->reg.where[LR] == DWARF_WHERE_CFAREL)
      f->lr_cfa_offset = rs->reg.val[LR];
    if (rs->reg.where[SP] == DWARF_WHERE_CFAREL)
      f->sp_cfa_offset = rs->reg.val[SP];
    Debug (4, " standard frame\n");
  }
  else
    Debug (4, " unusual frame\n");
}
Beispiel #2
0
HIDDEN void
tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
{
  struct cursor *c = (struct cursor *) dwarf_to_cursor (d);
  unw_tdep_frame_t *f = &c->frame_info;

  Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
         " ra=0x%lx rbp [where=%d val=%ld @0x%lx] rsp [where=%d val=%ld @0x%lx]\n",
         d->ip, d->cfa, f->frame_type,
         rs->reg[DWARF_CFA_REG_COLUMN].where,
         rs->reg[DWARF_CFA_REG_COLUMN].val,
         rs->reg[DWARF_CFA_OFF_COLUMN].val,
         DWARF_GET_LOC(d->loc[d->ret_addr_column]),
         rs->reg[RBP].where, rs->reg[RBP].val, DWARF_GET_LOC(d->loc[RBP]),
         rs->reg[RSP].where, rs->reg[RSP].val, DWARF_GET_LOC(d->loc[RSP]));

  /* A standard frame is defined as:
      - CFA is register-relative offset off RBP or RSP;
      - Return address is saved at CFA-8;
      - RBP is unsaved or saved at CFA+offset, offset != -1;
      - RSP is unsaved or saved at CFA+offset, offset != -1.  */
  if (f->frame_type == UNW_X86_64_FRAME_OTHER
      && (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
      && (rs->reg[DWARF_CFA_REG_COLUMN].val == RBP
          || rs->reg[DWARF_CFA_REG_COLUMN].val == RSP)
      && labs((long) rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
      && DWARF_GET_LOC(d->loc[d->ret_addr_column]) == d->cfa-8
      && (rs->reg[RBP].where == DWARF_WHERE_UNDEF
          || rs->reg[RBP].where == DWARF_WHERE_SAME
          || (rs->reg[RBP].where == DWARF_WHERE_CFAREL
              && labs((long) rs->reg[RBP].val) < (1 << 14)
              && rs->reg[RBP].val+1 != 0))
      && (rs->reg[RSP].where == DWARF_WHERE_UNDEF
          || rs->reg[RSP].where == DWARF_WHERE_SAME
          || (rs->reg[RSP].where == DWARF_WHERE_CFAREL
              && labs((long) rs->reg[RSP].val) < (1 << 14)
              && rs->reg[RSP].val+1 != 0)))
  {
    /* Save information for a standard frame. */
    f->frame_type = UNW_X86_64_FRAME_STANDARD;
    f->cfa_reg_rsp = (rs->reg[DWARF_CFA_REG_COLUMN].val == RSP);
    f->cfa_reg_offset = rs->reg[DWARF_CFA_OFF_COLUMN].val;
    if (rs->reg[RBP].where == DWARF_WHERE_CFAREL)
      f->rbp_cfa_offset = rs->reg[RBP].val;
    if (rs->reg[RSP].where == DWARF_WHERE_CFAREL)
      f->rsp_cfa_offset = rs->reg[RSP].val;
    Debug (4, " standard frame\n");
  }

  /* Signal frame was detected via augmentation in tdep_fetch_frame()  */
  else if (f->frame_type == UNW_X86_64_FRAME_SIGRETURN)
  {
    /* Later we are going to fish out {RBP,RSP,RIP} from sigcontext via
       their ucontext_t offsets.  Confirm DWARF info agrees with the
       offsets we expect.  */

#ifndef NDEBUG
    const unw_word_t uc = c->sigcontext_addr;

    assert (DWARF_GET_LOC(d->loc[RIP]) - uc == UC_MCONTEXT_GREGS_RIP);
    assert (DWARF_GET_LOC(d->loc[RBP]) - uc == UC_MCONTEXT_GREGS_RBP);
    assert (DWARF_GET_LOC(d->loc[RSP]) - uc == UC_MCONTEXT_GREGS_RSP);
#endif

    Debug (4, " sigreturn frame\n");
  }

  /* PLT and guessed RBP-walked frames are handled in unw_step(). */
  else
    Debug (4, " unusual frame\n");
}