示例#1
0
void
close_dwarf_executable (void)
{
  int dwStatus = -1;
  Elf *elfHandle = NULL;

  mpiPi_msg_debug ("enter close_dwarf_executable\n");

  assert (dwHandle != NULL);
  assert (dwFd != -1);
  dwStatus = dwarf_get_elf (dwHandle, &elfHandle, &dw_err);
  if (dwStatus != DW_DLV_OK)
    {
      mpiPi_msg_debug ("dwarf_get_elf failed; ignoring : %s\n", dwarf_errmsg(dw_err));
    }

  dwStatus = dwarf_finish (dwHandle, &dw_err);
  if (dwStatus != DW_DLV_OK)
    {
      mpiPi_msg_debug ("dwarf_finish failed; ignoring : %s\n", dwarf_errmsg(dw_err));
    }
  dwHandle = NULL;

  close (dwFd);
  dwFd = -1;

  AddrToSourceMap_Destroy ();
  FunctionMap_Destroy ();
}
static void
_dwarf_die_offset(Dwarf_Die die)
{
	Dwarf_Off rel_off, die_off, cu_off, cu_len;
	Dwarf_Error de;

	if (dwarf_die_CU_offset(die, &rel_off, &de) != DW_DLV_OK) {
		tet_printf("dwarf_die_CU_offset failed: %s\n",
		    dwarf_errmsg(de));
		result = TET_FAIL;
	}
	TS_CHECK_INT(rel_off);

	if (dwarf_die_CU_offset_range(die, &cu_off, &cu_len, &de) !=
	    DW_DLV_OK) {
		tet_printf("dwarf_die_CU_offset_range failed: %s\n",
		    dwarf_errmsg(de));
		result = TET_FAIL;
	}
	TS_CHECK_INT(cu_off);
	TS_CHECK_INT(cu_len);

	if (dwarf_dieoffset(die, &die_off, &de) != DW_DLV_OK) {
		tet_printf("dwarf_dieoffset failed: %s\n", dwarf_errmsg(de));
		result = TET_FAIL;
	}
	TS_CHECK_INT(die_off);
}
示例#3
0
void CUsHolder::clean(void) throw()
{
  Dwarf_Error err = NULL;
  int ret = 0;

  for(size_t idx = 0; idx < size(); ++idx)
  {
    dwarf_dealloc(m_dbg, (*this)[idx], DW_DLA_DIE);
    (*this)[idx] = NULL;
  }

  ret = dwarf_finish(m_dbg, &err);
  if(ret != DW_DLV_OK)
  {
    MSG("libdwarf cleanup failed: %s\n", dwarf_errmsg(err));
  }

  clear();

  m_dbg = NULL;
  if(m_fd != -1)
  {
    close(m_fd), m_fd = -1;
  }
}
static void
tp_dwarf_die_offset_given_cu(void)
{
	Dwarf_Debug dbg;
	Dwarf_Error de;
	Dwarf_Off cu_offset, cu_dieoff;
	Dwarf_Unsigned cu_next_offset;
	int fd;
	
	result = TET_UNRESOLVED;

	TS_DWARF_INIT(dbg, fd, de);

	cu_offset = 0;
	TS_DWARF_CU_FOREACH(dbg, cu_next_offset, de) {
		if (dwarf_get_cu_die_offset_given_cu_header_offset(dbg,
		    cu_offset, &cu_dieoff, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_cu_die_offset_given_cu_header"
			    "_offset failed: %s", dwarf_errmsg(de));
			result = TET_FAIL;
			goto done;
		}
		TS_CHECK_INT(cu_dieoff);
		cu_offset = cu_next_offset;
	}

	if (result == TET_UNRESOLVED)
		result = TET_PASS;

done:
	TS_DWARF_FINISH(dbg, de);
	TS_RESULT(result);
}
示例#5
0
int
main (int argc, char *argv[])
{
  assert (argc >= 3);
  const char *name = argv[1];
  ptrdiff_t cuoff = strtol (argv[2], NULL, 0);
  bool new_style = argc > 3;

  int fd = open (name, O_RDONLY);
  Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);

  Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem);

  for (ptrdiff_t off = new_style ? DWARF_GETMACROS_START : 0;
       (off = dwarf_getmacros (cudie, mac, dbg, off)); )
    if (off == -1)
      {
	puts (dwarf_errmsg (dwarf_errno ()));
	break;
      }

  dwarf_end (dbg);

  return 0;
}
示例#6
0
static void
print_detail (int result, const Dwarf_Op *ops, size_t nops, Dwarf_Addr bias)
{
  if (result < 0)
    printf ("indeterminate (%s)\n", dwarf_errmsg (-1));
  else if (nops == 0)
    printf ("%s\n", result == 0 ? "same_value" : "undefined");
  else
    {
      printf ("%s expression:", result == 0 ? "location" : "value");
      for (size_t i = 0; i < nops; ++i)
	{
	  printf (" %#x", ops[i].atom);
	  if (ops[i].number2 == 0)
	    {
	      if (ops[i].atom == DW_OP_addr)
		printf ("(%#" PRIx64 ")", ops[i].number + bias);
	      else if (ops[i].number != 0)
		printf ("(%" PRId64 ")", ops[i].number);
	    }
	  else
	    printf ("(%" PRId64 ",%" PRId64 ")",
		    ops[i].number, ops[i].number2);
	}
      puts ("");
    }
}
示例#7
0
/*
 * Use the DWARF expression for the Call-frame-address and determine
 * if return address is in LR and if a new frame was allocated.
 */
static int check_return_reg(int ra_regno, Dwarf_Frame *frame)
{
	Dwarf_Op ops_mem[2];
	Dwarf_Op dummy;
	Dwarf_Op *ops = &dummy;
	size_t nops;
	int result;

	result = dwarf_frame_register(frame, ra_regno, ops_mem, &ops, &nops);
	if (result < 0) {
		pr_debug("dwarf_frame_register() %s\n", dwarf_errmsg(-1));
		return -1;
	}

	/*
	 * Check if return address is on the stack. If return address
	 * is in a register (typically R0), it is yet to be saved on
	 * the stack.
	 */
	if ((nops != 0 || ops != NULL) &&
		!(nops == 1 && ops[0].atom == DW_OP_regx &&
			ops[0].number2 == 0 && ops[0].offset == 0))
		return 0;

	/*
	 * Return address is in LR. Check if a frame was allocated
	 * but not-yet used.
	 */
	result = dwarf_frame_cfa(frame, &ops, &nops);
	if (result < 0) {
		pr_debug("dwarf_frame_cfa() returns %d, %s\n", result,
					dwarf_errmsg(-1));
		return -1;
	}

	/*
	 * If call frame address is in r1, no new frame was allocated.
	 */
	if (nops == 1 && ops[0].atom == DW_OP_bregx && ops[0].number == 1 &&
				ops[0].number2 == 0)
		return 1;

	/*
	 * A new frame was allocated but has not yet been used.
	 */
	return 2;
}
示例#8
0
static void
_dwarf_srcfiles(Dwarf_Die die)
{
	Dwarf_Half tag;
	Dwarf_Error de;
	Dwarf_Signed srccount;
	char **srcfiles;
	int r_srcfiles, i;

	if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
		tet_printf("dwarf_tag failed: %s\n", dwarf_errmsg(de));
		result = TET_FAIL;
		return;
	}

	r_srcfiles = dwarf_srcfiles(die, &srcfiles, &srccount, &de);
	TS_CHECK_INT(r_srcfiles);

	if (r_srcfiles == DW_DLV_ERROR) {
		tet_printf("dwarf_srcfiles should not fail but still failed:",
		    " %s", dwarf_errmsg(de));
		return;
	}

	if (r_srcfiles != DW_DLV_OK)
		return;

	if (dwarf_srcfiles(die, &srcfiles, &srccount, &de) != DW_DLV_OK) {
		tet_printf("dwarf_srcfiles failed: %s\n", dwarf_errmsg(de));
		result = TET_FAIL;
		return;
	}

	TS_CHECK_INT(srccount);
	for (i = 0; i < srccount; i++) {
		if (srcfiles[i] == NULL) {
			tet_printf("dwarf_srcfiles returned NULL pointer"
			    " srcfiles[%d]\n", i);
			result = TET_FAIL;
		} else
			TS_CHECK_STRING(srcfiles[i]);
	}
}
示例#9
0
static void
include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token)
{
  while ((token = dwarf_getmacros_off (dbg, macoff, mac, dbg, token)) != 0)
    if (token == -1)
      {
	puts (dwarf_errmsg (dwarf_errno ()));
	break;
      }
}
static int
handle_function (Dwarf_Die *func, void *arg)
{
  struct args *a = arg;

  const char *name = dwarf_diename (func);
  char **argv = a->argv;
  if (argv[0] != NULL)
    {
      bool match;
      do
	match = fnmatch (*argv, name, 0) == 0;
      while (!match && *++argv);
      if (!match)
	return 0;
    }

  if (dwarf_func_inline (func))
    return 0;

  Dwarf_Addr entrypc;
  if (dwarf_entrypc (func, &entrypc) != 0)
    error (EXIT_FAILURE, 0, "dwarf_entrypc: %s: %s",
	   dwarf_diename (func), dwarf_errmsg (-1));
  entrypc += a->dwbias;

  printf ("%-16s %#.16" PRIx64, dwarf_diename (func), entrypc);

  Dwarf_Addr *bkpts = NULL;
  int result = dwarf_entry_breakpoints (func, &bkpts);
  if (result <= 0)
    printf ("\t%s\n", dwarf_errmsg (-1));
  else
    {
      for (int i = 0; i < result; ++i)
	printf (" %#.16" PRIx64 "%s", bkpts[i] + a->dwbias,
		i == result - 1 ? "\n" : "");
      free (bkpts);
    }

  return 0;
}
示例#11
0
int type_of(Dwarf_Debug dbg, Dwarf_Die *die, Dwarf_Die *type_die,
            Dwarf_Error *err) {
  Dwarf_Attribute type;
  Dwarf_Off ref_off = 0;

  if (type_off(die, &ref_off, err) != DW_DLV_OK) {
    fprintf(stderr, "Error in getting type offset: %s\n", dwarf_errmsg(*err));
    return -1;
  }

  int status;

  if ((status = dwarf_offdie(dbg, ref_off, type_die, err)) != DW_DLV_OK) {
    fprintf(stderr, "Error %d in getting die at offset: %s\n", status,
            dwarf_errmsg(*err));
    return status;
  }

  return DW_DLV_OK;
}
示例#12
0
static void
record_line_error(const char *where, Dwarf_Error err)
{
    char tmp_buff[500];
    if (check_lines && checking_this_compiler()) {
        snprintf(tmp_buff, sizeof(tmp_buff),
            "Error getting line details calling %s dwarf error is %s",
            where,dwarf_errmsg(err));
        DWARF_CHECK_ERROR(lines_result,tmp_buff);
    }
}
示例#13
0
文件: rdwarf.c 项目: kubo/rdwarf
static int chkerr2(int ret, Dwarf_Error *err)
{
    if (ret == DW_DLV_ERROR) {
        if (err != NULL) {
            rb_raise(rd_eError, "%s", dwarf_errmsg(*err));
        } else {
            rb_raise(rd_eError, "Unknown Error");
        }
    }
    return ret == DW_DLV_OK;
}
示例#14
0
static void
tp_dwarf_ranges(void)
{
	Dwarf_Debug dbg;
	Dwarf_Ranges *ranges;
	Dwarf_Signed range_cnt;
	Dwarf_Unsigned byte_cnt;
	Dwarf_Off off;
	Dwarf_Error de;
	int fd, r_ranges, i;

	result = TET_UNRESOLVED;

	TS_DWARF_INIT(dbg, fd, de);

	off = 0;
	for (;;) {
		tet_printf("check ranges at offset(%ju):\n", (uintmax_t) off);
		r_ranges = dwarf_get_ranges_a(dbg, off, NULL, &ranges,
		    &range_cnt, &byte_cnt, &de);
		if (r_ranges != DW_DLV_OK)
			break;
		TS_CHECK_INT(range_cnt);
		TS_CHECK_UINT(byte_cnt);
		off += byte_cnt;
		for (i = 0; i < range_cnt; i++) {
			tet_printf("check range %d:\n", i);
			TS_CHECK_INT(ranges[i].dwr_type);
			TS_CHECK_UINT(ranges[i].dwr_addr1);
			TS_CHECK_UINT(ranges[i].dwr_addr2);
		}
	}

	/*
	 * SGI libdwarf return DW_DLV_ERROR when provided offset is out of
	 * range, instead of DW_DLV_NO_ENTRY as stated in the SGI libdwarf
	 * documentation. elftoolchain libdwarf follows the SGI libdwarf
	 * documentation.
	 */
#if 0
	if (r_ranges == DW_DLV_ERROR) {
		tet_printf("dwarf_get_ranges failed: %s\n", dwarf_errmsg(de));
		result = TET_FAIL;
	}
#endif

	if (result == TET_UNRESOLVED)
		result = TET_PASS;

done:
	TS_DWARF_FINISH(dbg, de);
	TS_RESULT(result);
}
示例#15
0
static Dwarf_Off
die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name)
{
	Dwarf_Off off;

	if (dwarf_attrval_unsigned(die, name, &off, &dw->dw_err) != DWARF_E_NONE) {
		terminate("die %llu: failed to get ref: %s\n",
		    die_off(dw, die), dwarf_errmsg(&dw->dw_err));
	}

	return (off);
}
示例#16
0
static Dwarf_Half
die_tag(dwarf_t *dw, Dwarf_Die die)
{
	Dwarf_Half tag;

	if (dwarf_tag(die, &tag, &dw->dw_err) == DW_DLV_OK)
		return (tag);

	terminate("die %llu: failed to get tag for type: %s\n",
	    die_off(dw, die), dwarf_errmsg(dw->dw_err));
	/*NOTREACHED*/
	return (0);
}
示例#17
0
int type_off(Dwarf_Die *die, Dwarf_Off *ref_off, Dwarf_Error *err) {
  Dwarf_Attribute type;
  int status;

  if ((status = dwarf_attr(*die, DW_AT_type, &type, err)) != DW_DLV_OK) {
    if (status == DW_DLV_NO_ENTRY) {
      fprintf(stderr, "No type information associated with die\n");
    } else {
      fprintf(stderr, "Error %d in getting type attribute: %s\n", status,
              dwarf_errmsg(*err));
    }
    return status;
  }

  if ((status = dwarf_global_formref(type, ref_off, err)) != DW_DLV_OK) {
    fprintf(stderr, "Error %d in getting type offset: %s\n", status,
            dwarf_errmsg(*err));
    return status;
  }

  return DW_DLV_OK;
}
示例#18
0
static Dwarf_Half
die_attr_form(dwarf_t *dw, Dwarf_Attribute attr)
{
	Dwarf_Half form;

	if (dwarf_whatform(attr, &form, &dw->dw_err) == DW_DLV_OK)
		return (form);

	terminate("failed to get attribute form for type: %s\n",
	    dwarf_errmsg(dw->dw_err));
	/*NOTREACHED*/
	return (0);
}
示例#19
0
static void
HandleFunctionDIE (Dwarf_Debug dwHandle, Dwarf_Die currChildDIE)
{
  char *funcName = NULL;
  Dwarf_Addr lowAddress = 0;
  Dwarf_Addr highAddress = 0;

  int dwDieNameRet, dwDieLowAddrRet, dwDieHighAddrRet;

  dwDieNameRet = dwarf_diename (currChildDIE,
				&funcName,
				&dw_err);
  if (dwDieNameRet != DW_DLV_OK)
    mpiPi_msg_debug("Failed to get DIE name : %s\n", dwarf_errmsg(dw_err));

  dwDieLowAddrRet = dwarf_lowpc (currChildDIE,
				 &lowAddress,
				 &dw_err);
  if (dwDieLowAddrRet != DW_DLV_OK)
    mpiPi_msg_debug("Failed to get low PC : %s\n", dwarf_errmsg(dw_err));

  dwDieHighAddrRet = dwarf_highpc (currChildDIE,
				   &highAddress,
				   &dw_err);

  if (dwDieHighAddrRet != DW_DLV_OK)
    mpiPi_msg_debug("Failed to get high PC : %s\n", dwarf_errmsg(dw_err));

  if ((dwDieNameRet == DW_DLV_OK) &&
      (dwDieLowAddrRet == DW_DLV_OK) && (dwDieHighAddrRet == DW_DLV_OK))
    {
      FunctionMap_Add (funcName, lowAddress, highAddress);
    }

  if ((dwDieNameRet == DW_DLV_OK) && (funcName != NULL))
    {
      dwarf_dealloc (dwHandle, funcName, DW_DLA_STRING);
    }
}
示例#20
0
static Dwarf_Off
die_off(dwarf_t *dw, Dwarf_Die die)
{
	Dwarf_Off off;

	if (dwarf_dieoffset(die, &off, &dw->dw_err) == DW_DLV_OK)
		return (off);

	terminate("failed to get offset for die: %s\n",
	    dwarf_errmsg(dw->dw_err));
	/*NOTREACHED*/
	return (0);
}
示例#21
0
/*
 * Handle DWARF 4 'offset from' DW_AT_high_pc.  Although we don't
 * fully support DWARF 4, some compilers (like FreeBSD Clang 3.5.1)
 * generate DW_AT_high_pc as an offset from DW_AT_low_pc.
 *
 * "If the value of the DW_AT_high_pc is of class address, it is the
 * relocated address of the first location past the last instruction
 * associated with the entity; if it is of class constant, the value
 * is an unsigned integer offset which when added to the low PC gives
 * the address of the first location past the last instruction
 * associated with the entity."
 *
 * DWARF4 spec, section 2.17.2.
 */
static int
handle_high_pc(Dwarf_Die die, Dwarf_Unsigned lopc, Dwarf_Unsigned *hipc)
{
	Dwarf_Error de;
	Dwarf_Half form;
	Dwarf_Attribute at;
	int ret;

	ret = dwarf_attr(die, DW_AT_high_pc, &at, &de);
	if (ret == DW_DLV_ERROR) {
		warnx("dwarf_attr failed: %s", dwarf_errmsg(de));
		return (ret);
	}
	ret = dwarf_whatform(at, &form, &de);
	if (ret == DW_DLV_ERROR) {
		warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
		return (ret);
	}
	if (dwarf_get_form_class(2, 0, 0, form) == DW_FORM_CLASS_CONSTANT)
		*hipc += lopc;

	return (DW_DLV_OK);
}
示例#22
0
static int
die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req)
{
	*valp = 0;

	if (dwarf_attrval_flag(die, name, valp, &dw->dw_err) != DWARF_E_NONE) {
		if (req) 
			terminate("die %llu: failed to get flag: %s\n",
			    die_off(dw, die), dwarf_errmsg(&dw->dw_err));
		return (0);
	}

	return (1);
}
示例#23
0
static void
tp_dwarf_die_offset_sanity(void)
{
	Dwarf_Debug dbg;
	Dwarf_Die die;
	Dwarf_Error de;
	Dwarf_Off rel_off, die_off, cu_off, cu_len;
	Dwarf_Unsigned cu_next_offset;
	int fd;

	result = TET_UNRESOLVED;

	TS_DWARF_INIT(dbg, fd, de);

	TS_DWARF_CU_FOREACH(dbg, cu_next_offset, de) {
		if (dwarf_siblingof(dbg, NULL, &die, &de) == DW_DLV_ERROR) {
			tet_printf("dwarf_siblingof failed: %s\n",
			    dwarf_errmsg(de));
			result = TET_FAIL;
			goto done;
		}
		if (dwarf_die_CU_offset(NULL, &rel_off, &de) != DW_DLV_ERROR) {
			tet_infoline("dwarf_die_CU_offset didn't return"
			    " DW_DLV_ERROR when called with NULL arguments");
			result = TET_FAIL;
			goto done;
		}
		if (dwarf_die_CU_offset_range(NULL, &cu_off, &cu_len, &de) !=
		    DW_DLV_ERROR) {
			tet_infoline("dwarf_die_CU_offset_range didn't return"
			    " DW_DLV_ERROR when called with NULL arguments");
			result = TET_FAIL;
			goto done;
		}
		if (dwarf_dieoffset(NULL, &die_off, &de) != DW_DLV_ERROR) {
			tet_infoline("dwarf_dieoffset didn't return DW_DLV_ERROR"
			    " when called with NULL arguments");
			result = TET_FAIL;
			goto done;
		}
	}

	if (result == TET_UNRESOLVED)
		result = TET_PASS;

done:
	TS_DWARF_FINISH(dbg, de);
	TS_RESULT(result);
}
示例#24
0
int
main (int argc, char *argv[])
{
  int cnt;

  for (cnt = 1; cnt < argc; ++cnt)
    {
      Dwarf_Off offset = 0;
      size_t len;

      int fd = open (argv[cnt], O_RDONLY);
      if (fd == -1)
	{
	  printf ("cannot open '%s': %m\n", argv[cnt]);
	  return 1;
	}

      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
      if (dbg == NULL)
	{
	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
	  close (fd);
	  return 1;
	}

      /* Try to use NULL Dwarf object.  */
      const char *str = dwarf_getstring (NULL, offset, &len);
      assert (str == NULL);

      /* Use insane offset.  */
      str = dwarf_getstring (dbg, ~0UL, &len);
      assert (str == NULL);

      /* Now do some real work.  */
      for (int i = 0; i < 100; ++i)
	{
	  str = dwarf_getstring (dbg, offset, &len);
	  puts (str);

	  /* Advance.  */
	  offset += len + 1;
	}

      close (fd);
    }

  return 0;
}
示例#25
0
static Dwarf_Die
die_child(dwarf_t *dw, Dwarf_Die die)
{
	Dwarf_Die child;
	int rc;

	if ((rc = dwarf_child(die, &child, &dw->dw_err)) == DW_DLV_OK)
		return (child);
	else if (rc == DW_DLV_NO_ENTRY)
		return (NULL);

	terminate("die %llu: failed to find type child: %s\n",
	    die_off(dw, die), dwarf_errmsg(dw->dw_err));
	/*NOTREACHED*/
	return (NULL);
}
示例#26
0
static Dwarf_Die
die_sibling(dwarf_t *dw, Dwarf_Die die)
{
	Dwarf_Die sib;
	int rc;

	if ((rc = dwarf_siblingof(dw->dw_dw, die, &sib, &dw->dw_err)) ==
	    DW_DLV_OK)
		return (sib);
	else if (rc == DW_DLV_NO_ENTRY)
		return (NULL);

	terminate("die %llu: failed to find type sibling: %s\n",
	    die_off(dw, die), dwarf_errmsg(dw->dw_err));
	/*NOTREACHED*/
	return (NULL);
}
示例#27
0
文件: rdwarf.c 项目: kubo/rdwarf
static void chkerr1(int ret, Dwarf_Error *err, VALUE obj)
{
    VALUE exc = Qnil;
    switch (ret) {
    case DW_DLV_NO_ENTRY:
        exc = rb_exc_new_cstr(rd_eError, "No Entry");
    case DW_DLV_ERROR:
        if (err != NULL) {
            exc = rb_exc_new_cstr(rd_eError, dwarf_errmsg(*err));
        } else {
            exc = rb_exc_new_cstr(rd_eError, "Unknown Error");
        }
    }
    if (!NIL_P(exc)) {
        rb_iv_set(exc, "@obj", obj);
        rb_exc_raise(exc);
    }
}
示例#28
0
static int
die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req)
{
	const char *str = NULL;

	if (dwarf_attrval_string(die, name, &str, &dw->dw_err) != DWARF_E_NONE ||
	    str == NULL) {
		if (req) 
			terminate("die %llu: failed to get string: %s\n",
			    die_off(dw, die), dwarf_errmsg(&dw->dw_err));
		else
			*strp = NULL;
		return (0);
	} else
		*strp = xstrdup(str);

	return (1);
}
示例#29
0
static int
handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi,
	    GElf_Addr pc, struct stuff *stuff)
{
  int result = dwarf_cfi_addrframe (cfi, pc - stuff->bias, &stuff->frame);
  if (result != 0)
    {
      error (0, 0, "dwarf_addrframe (%s): %s", which, dwfl_errmsg (-1));
      return 1;
    }

  Dwarf_Addr start = pc;
  Dwarf_Addr end = pc;
  bool signalp;
  int ra_regno = dwarf_frame_info (stuff->frame, &start, &end, &signalp);
  if (ra_regno >= 0)
    {
      start += stuff->bias;
      end += stuff->bias;
    }

  printf ("%s has %#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n",
	  which, pc, start, end);

  if (ra_regno < 0)
    printf ("\treturn address register unavailable (%s)\n",
	    dwarf_errmsg (0));
  else
    printf ("\treturn address in reg%u%s\n",
	    ra_regno, signalp ? " (signal frame)" : "");

  Dwarf_Op *cfa_ops;
  size_t cfa_nops;
  result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops);

  printf ("\tCFA ");
  print_detail (result, cfa_ops, cfa_nops, stuff->bias);

  (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc),
				     &print_register, stuff);

  return 0;
}
static void
tp_dwarf_get_address_size(void)
{
	Dwarf_Debug dbg;
	Dwarf_Error de;
	Dwarf_Half addr_size;
	int fd, result;

	dbg = NULL;
	result = TET_UNRESOLVED;

	if (dwarf_get_address_size(NULL, &addr_size, &de) != DW_DLV_ERROR) {
		tet_infoline("dwarf_get_adderss_size NULL 'dbg' test failed");
		result = TET_FAIL;
		goto done;
	}

	TS_DWARF_INIT(dbg, fd, de);

	if (dwarf_get_address_size(dbg, NULL, &de) != DW_DLV_ERROR) {
		tet_infoline("dwarf_get_adderss_size NULL 'addr_size' test "
		    "failed");
		result = TET_FAIL;
		goto done;
	}

	if (dwarf_get_address_size(dbg, &addr_size, &de) != DW_DLV_OK) {
		tet_printf("dwarf_get_address_size failed: %s",
		    dwarf_errmsg(de));
		result = TET_FAIL;
		goto done;
	}

	TS_CHECK_UINT(addr_size);

	if (result == TET_UNRESOLVED)
		result = TET_PASS;

done:
	TS_DWARF_FINISH(dbg, de);
	TS_RESULT(result);
}