static inline int
local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
                      int need_unwind_info, void *arg)
{
  unw_dyn_info_list_t *list;
  unw_dyn_info_t *di;

# pragma weak _U_dyn_info_list_addr
  if (!_U_dyn_info_list_addr)
    return -UNW_ENOINFO;

  list = (unw_dyn_info_list_t *) (uintptr_t) _U_dyn_info_list_addr ();
  for (di = list->first; di; di = di->next)
    if (ip >= di->start_ip && ip < di->end_ip)
      return unwi_extract_dynamic_proc_info (as, ip, pi, di, need_unwind_info,
                                             arg);
  return -UNW_ENOINFO;
}
Example #2
0
HIDDEN int
unwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip,
                                unw_proc_info_t *pi,
                                int need_unwind_info, void *arg)
{
  unw_accessors_t *a = unw_get_accessors (as);
  unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2, start_ip, end_ip;
  unw_dyn_info_t *di = NULL;
  int ret;

  if (as->dyn_info_list_addr)
    dyn_list_addr = as->dyn_info_list_addr;
  else
    {
      if ((*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg) < 0)
        return -UNW_ENOINFO;
      if (as->caching_policy != UNW_CACHE_NONE)
        as->dyn_info_list_addr = dyn_list_addr;
    }

  do
    {
      addr = dyn_list_addr;

      ret = -UNW_ENOINFO;

      if (fetchw (as, a, &addr, &gen1, arg) < 0
          || fetchw (as, a, &addr, &next_addr, arg) < 0)
        return ret;

      for (addr = next_addr; addr != 0; addr = next_addr)
        {
          if (fetchw (as, a, &addr, &next_addr, arg) < 0)
            goto recheck;       /* only fail if generation # didn't change */

          addr += WSIZE;        /* skip over prev_addr */

          if (fetchw (as, a, &addr, &start_ip, arg) < 0
              || fetchw (as, a, &addr, &end_ip, arg) < 0)
            goto recheck;       /* only fail if generation # didn't change */

          if (ip >= start_ip && ip < end_ip)
            {
              if (!di)
                di = calloc (1, sizeof (*di));

              di->start_ip = start_ip;
              di->end_ip = end_ip;

              if (fetchw (as, a, &addr, &di->gp, arg) < 0
                  || fetch32 (as, a, &addr, &di->format, arg) < 0)
                goto recheck;   /* only fail if generation # didn't change */

              addr += 4;        /* skip over padding */

              if (need_unwind_info
                  && intern_dyn_info (as, a, &addr, di, arg) < 0)
                goto recheck;   /* only fail if generation # didn't change */

              if (unwi_extract_dynamic_proc_info (as, ip, pi, di,
                                                  need_unwind_info, arg) < 0)
                {
                  free_dyn_info (di);
                  goto recheck; /* only fail if generation # didn't change */
                }
              ret = 0;  /* OK, found it */
              break;
            }
        }

      /* Re-check generation number to ensure the data we have is
         consistent.  */
    recheck:
      addr = dyn_list_addr;
      if (fetchw (as, a, &addr, &gen2, arg) < 0)
        return ret;
    }
  while (gen1 != gen2);

  if (ret < 0 && di)
    free (di);

  return ret;
}