int
_UPT_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
		     int need_unwind_info, void *arg)
{
  struct UPT_info *ui = arg;
  int ret = -UNW_ENOINFO;

  if (get_unwind_info (&ui->edi, ui->pid, as, ip, arg) < 0)
    return -UNW_ENOINFO;

#if UNW_TARGET_IA64
  if (ui->edi.ktab.format != -1)
    {
      /* The kernel unwind table resides in local memory, so we have
	 to use the local address space to search it.  Since
	 _UPT_put_unwind_info() has no easy way of detecting this
	 case, we simply make a copy of the unwind-info, so
	 _UPT_put_unwind_info() can always free() the unwind-info
	 without ill effects.  */
      ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi,
				      need_unwind_info, arg);
      if (ret >= 0)
	{
	  if (!need_unwind_info)
	    pi->unwind_info = NULL;
	  else
	    {
	      void *mem = malloc (pi->unwind_info_size);

	      if (!mem)
		return -UNW_ENOMEM;
	      memcpy (mem, pi->unwind_info, pi->unwind_info_size);
	      pi->unwind_info = mem;
	    }
	}
    }
#endif

  if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1)
    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache,
				    pi, need_unwind_info, arg);

#if UNW_TARGET_ARM
  if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1)
    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi,
                                    need_unwind_info, arg);
#endif

  if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
				    need_unwind_info, arg);

  return ret;
}
Beispiel #2
0
HIDDEN int
unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip,
                                unw_proc_info_t *pi, unw_dyn_info_t *di,
                                int need_unwind_info, void *arg)
{
  pi->start_ip = di->start_ip;
  pi->end_ip = di->end_ip;
  pi->gp = di->gp;
  pi->format = di->format;
  switch (di->format)
    {
    case UNW_INFO_FORMAT_DYNAMIC:
      pi->handler = di->u.pi.handler;
      pi->lsda = 0;
      pi->flags = di->u.pi.flags;
      pi->unwind_info_size = 0;
      if (need_unwind_info)
        pi->unwind_info = di;
      else
        pi->unwind_info = NULL;
      return 0;

    case UNW_INFO_FORMAT_TABLE:
    case UNW_INFO_FORMAT_REMOTE_TABLE:
#ifdef tdep_search_unwind_table
      /* call platform-specific search routine: */
      return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
#else
      /* fall through */
#endif
    default:
      break;
    }
  return -UNW_EINVAL;
}
Beispiel #3
0
HIDDEN int
tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
		     unw_proc_info_t *pi, int need_unwind_info, void *arg)
{
# if defined(HAVE_DL_ITERATE_PHDR)
  unw_dyn_info_t di, *dip = &di;
  intrmask_t saved_mask;
  int ret;

  di.u.ti.segbase = ip;	/* this is cheap... */

  SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
  ret = dl_iterate_phdr (callback, &di);
  SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);

  if (ret <= 0)
    {
      if (!kernel_table.u.ti.table_data)
	{
	  if ((ret = get_kernel_table (&kernel_table)) < 0)
	    return ret;
	}
      if (ip < kernel_table.start_ip || ip >= kernel_table.end_ip)
	return -UNW_ENOINFO;
      dip = &kernel_table;
    }
# elif defined(HAVE_DLMODINFO)
# define UNWIND_TBL_32BIT	0x8000000000000000
  struct load_module_desc lmd;
  unw_dyn_info_t di, *dip = &di;
  struct unwind_header
    {
      uint64_t header_version;
      uint64_t start_offset;
      uint64_t end_offset;
    }
  *uhdr;

  if (!dlmodinfo (ip, &lmd, sizeof (lmd), NULL, 0, 0))
    return -UNW_ENOINFO;

  di.format = UNW_INFO_FORMAT_TABLE;
  di.start_ip = lmd.text_base;
  di.end_ip = lmd.text_base + lmd.text_size;
  di.gp = lmd.linkage_ptr;
  di.u.ti.name_ptr = 0;	/* no obvious table-name available */
  di.u.ti.segbase = lmd.text_base;

  uhdr = (struct unwind_header *) lmd.unwind_base;

  if ((uhdr->header_version & ~UNWIND_TBL_32BIT) != 1
      && (uhdr->header_version & ~UNWIND_TBL_32BIT) != 2)
    {
      Debug (1, "encountered unknown unwind header version %ld\n",
 	     (long) (uhdr->header_version & ~UNWIND_TBL_32BIT));
      return -UNW_EBADVERSION;
    }
  if (uhdr->header_version & UNWIND_TBL_32BIT)
    {
      Debug (1, "32-bit unwind tables are not supported yet\n");
      return -UNW_EINVAL;
    }

  di.u.ti.table_data = (unw_word_t *) (di.u.ti.segbase + uhdr->start_offset);
  di.u.ti.table_len = ((uhdr->end_offset - uhdr->start_offset)
		       / sizeof (unw_word_t));

  Debug (16, "found table `%s': segbase=%lx, len=%lu, gp=%lx, "
 	 "table_data=%p\n", (char *) di.u.ti.name_ptr, di.u.ti.segbase,
 	 di.u.ti.table_len, di.gp, di.u.ti.table_data);
# endif

  /* now search the table: */
  return tdep_search_unwind_table (as, ip, dip, pi, need_unwind_info, arg);
}