Beispiel #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;
}
PROTECTED int
unw_get_proc_info_by_ip (unw_addr_space_t as, unw_word_t ip,
			 unw_proc_info_t *pi, void *as_arg)
{
  unw_accessors_t *a = unw_get_accessors (as);
  int ret;

  ret = unwi_find_dynamic_proc_info (as, ip, pi, 0, as_arg);
  if (ret == -UNW_ENOINFO)
    ret = (*a->find_proc_info) (as, ip, pi, 0, as_arg);
  return ret;
}
Beispiel #3
0
static inline int
get_proc_name (unw_addr_space_t as, unw_word_t ip,
	       char *buf, size_t buf_len, unw_word_t *offp, void *arg)
{
  unw_accessors_t *a = unw_get_accessors (as);
  unw_proc_info_t pi;
  int ret;

  buf[0] = '\0';	/* always return a valid string, even if it's empty */

  ret = unwi_find_dynamic_proc_info (as, ip, &pi, 1, arg);
  if (ret == 0)
    {
      unw_dyn_info_t *di = pi.unwind_info;

      if (offp)
	*offp = ip - pi.start_ip;

      switch (di->format)
	{
	case UNW_INFO_FORMAT_DYNAMIC:
	  ret = intern_string (as, a, di->u.pi.name_ptr, buf, buf_len, arg);
	  break;

	case UNW_INFO_FORMAT_TABLE:
	case UNW_INFO_FORMAT_REMOTE_TABLE:
	  /* XXX should we create a fake name, e.g.: "tablenameN",
	     where N is the index of the function in the table??? */
	  ret = -UNW_ENOINFO;
	  break;

	default:
	  ret = -UNW_EINVAL;
	  break;
	}
      unwi_put_dynamic_unwind_info (as, &pi, arg);
      return ret;
    }

  if (ret != -UNW_ENOINFO)
    return ret;

  /* not a dynamic procedure, try to lookup static procedure name: */

  if (a->get_proc_name)
    return (*a->get_proc_name) (as, ip, buf, buf_len, offp, arg);

  return -UNW_ENOINFO;
}
Beispiel #4
0
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;
}