示例#1
0
static int
fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
{
    int ret, dynamic = 1;

    /* The 'ip' can point either to the previous or next instruction
       depending on what type of frame we have: normal call or a place
       to resume execution (e.g. after signal frame).

       For a normal call frame we need to back up so we point within the
       call itself; this is important because a) the call might be the
       very last instruction of the function and the edge of the FDE,
       and b) so that run_cfi_program() runs locations up to the call
       but not more.

       For execution resume, we need to do the exact opposite and look
       up using the current 'ip' value.  That is where execution will
       continue, and it's important we get this right, as 'ip' could be
       right at the function entry and hence FDE edge, or at instruction
       that manipulates CFA (push/pop). */
    if (c->use_prev_instr)
        --ip;

    if (c->pi_valid && !need_unwind_info)
        return 0;

    memset (&c->pi, 0, sizeof (c->pi));

    /* check dynamic info first --- it overrides everything else */
    ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
                                       c->as_arg);
    if (ret == -UNW_ENOINFO)
    {
        dynamic = 0;
        if ((ret = tdep_find_proc_info (c, ip, need_unwind_info)) < 0)
            return ret;
    }

    if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC
            && c->pi.format != UNW_INFO_FORMAT_TABLE
            && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE)
        return -UNW_ENOINFO;

    c->pi_valid = 1;
    c->pi_is_dynamic = dynamic;

    /* Let system/machine-dependent code determine frame-specific attributes. */
    if (ret >= 0)
        tdep_fetch_frame (c, ip, need_unwind_info);

    /* Update use_prev_instr for the next frame. */
    if (need_unwind_info)
    {
        assert(c->pi.unwind_info);
        struct dwarf_cie_info *dci = c->pi.unwind_info;
        c->use_prev_instr = ! dci->signal_frame;
    }

    return ret;
}
示例#2
0
文件: Gstep.c 项目: bminor/libunwind
static inline int
arm_exidx_step (struct cursor *c)
{
  unw_word_t old_ip, old_cfa;
  uint8_t buf[32];
  int ret;

  old_ip = c->dwarf.ip;
  old_cfa = c->dwarf.cfa;

  /* mark PC unsaved */
  c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC;
  unw_word_t ip = c->dwarf.ip;
  if (c->dwarf.use_prev_instr)
    --ip;

  /* check dynamic info first --- it overrides everything else */
  ret = unwi_find_dynamic_proc_info (c->dwarf.as, ip, &c->dwarf.pi, 1,
                                     c->dwarf.as_arg);
  if (ret == -UNW_ENOINFO)
    {
      if ((ret = tdep_find_proc_info (&c->dwarf, ip, 1)) < 0)
        return ret;
    }

  if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX)
    return -UNW_ENOINFO;

  ret = arm_exidx_extract (&c->dwarf, buf);
  if (ret == -UNW_ESTOPUNWIND)
    return 0;
  else if (ret < 0)
    return ret;

  ret = arm_exidx_decode (buf, ret, &c->dwarf);
  if (ret < 0)
    return ret;

  if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
    {
      Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
               __FUNCTION__, (long) c->dwarf.ip);
      return -UNW_EBADFRAME;
    }

  c->dwarf.pi_valid = 0;

  return (c->dwarf.ip == 0) ? 0 : 1;
}
示例#3
0
文件: Gstep.c 项目: 0-T-0/linux-sgx
static inline int
arm_exidx_step (struct cursor *c)
{
  unw_word_t old_ip, old_cfa;
  uint8_t buf[32];
  int ret;

  old_ip = c->dwarf.ip;
  old_cfa = c->dwarf.cfa;

  /* mark PC unsaved */
  c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC;

  if ((ret = tdep_find_proc_info (&c->dwarf, c->dwarf.ip, 1)) < 0)
     return ret;

  if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX)
    return -UNW_ENOINFO;

  ret = arm_exidx_extract (&c->dwarf, buf);
  if (ret == -UNW_ESTOPUNWIND)
    return 0;
  else if (ret < 0)
    return ret;

  ret = arm_exidx_decode (buf, ret, &c->dwarf);
  if (ret < 0)
    return ret;

  if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
    {
      Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
	       __FUNCTION__, (long) c->dwarf.ip);
      return -UNW_EBADFRAME;
    }

  return (c->dwarf.ip == 0) ? 0 : 1;
}