Esempio n. 1
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);
}
/**
 * Finds a function name in DWARF DIE (Debug Information Entry).
 * For more info on DWARF format, see http://www.dwarfstd.org/Download.php , http://www.ibm.com/developerworks/library/os-debugging/
 *
 * @return true if we need to stop search (i.e. either found it or some error happened)
 */
bool FindFunctionNameInDIE(Dwarf_Debug DebugInfo, Dwarf_Die Die, Dwarf_Addr Addr, const char **OutFuncName)
{
	Dwarf_Error ErrorInfo;
	Dwarf_Half Tag;
	Dwarf_Unsigned LowerPC, HigherPC;
	char *TempFuncName;
	int ReturnCode;

	if (dwarf_tag(Die, &Tag, &ErrorInfo) != DW_DLV_OK || Tag != DW_TAG_subprogram ||
		dwarf_attrval_unsigned(Die, DW_AT_low_pc, &LowerPC, &ErrorInfo) != DW_DLV_OK ||
		dwarf_attrval_unsigned(Die, DW_AT_high_pc, &HigherPC, &ErrorInfo) != DW_DLV_OK ||
		Addr < LowerPC || HigherPC <= Addr
		) 
	{
		return false;
	}
	
	// found it
	*OutFuncName = NULL;
	Dwarf_Attribute SubAt;
	ReturnCode = dwarf_attr(Die, DW_AT_name, &SubAt, &ErrorInfo);
	if (ReturnCode == DW_DLV_ERROR)
	{
		return true;	// error, but stop the search
	}
	else if (ReturnCode == DW_DLV_OK) 
	{
		if (dwarf_formstring(SubAt, &TempFuncName, &ErrorInfo))
		{
			*OutFuncName = NULL;
		}
		else
		{
			*OutFuncName = TempFuncName;
		}
		return true;
	}

	// DW_AT_Name is not present, look in DW_AT_specification
	Dwarf_Attribute SpecAt;
	if (dwarf_attr(Die, DW_AT_specification, &SpecAt, &ErrorInfo))
	{
		// not found, tough luck
		return false;
	}

	Dwarf_Off Offset;
	if (dwarf_global_formref(SpecAt, &Offset, &ErrorInfo))
	{
		return false;
	}

	Dwarf_Die SpecDie;
	if (dwarf_offdie(DebugInfo, Offset, &SpecDie, &ErrorInfo))
	{
		return false;
	}

	if (dwarf_attrval_string(SpecDie, DW_AT_name, OutFuncName, &ErrorInfo))
	{
		*OutFuncName = NULL;
	}

	return true;
}
Esempio n. 3
0
static void
search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, char **rlt_func)
{
	Dwarf_Die ret_die, spec_die;
	Dwarf_Error de;
	Dwarf_Half tag;
	Dwarf_Unsigned lopc, hipc;
	Dwarf_Off ref;
	Dwarf_Attribute sub_at, spec_at;
	char *func0;
	const char *func1;
	int ret;

	if (*rlt_func != NULL)
		goto done;

	if (dwarf_tag(die, &tag, &de)) {
		warnx("dwarf_tag: %s", dwarf_errmsg(de));
		goto cont_search;
	}
	if (tag == DW_TAG_subprogram) {
		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ||
		    dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de))
			goto cont_search;
		if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK)
			goto cont_search;
		if (addr < lopc || addr >= hipc)
			goto cont_search;

		/* Found it! */

		if ((*rlt_func = strdup(unknown)) == NULL)
			err(EXIT_FAILURE, "strdup");
		ret = dwarf_attr(die, DW_AT_name, &sub_at, &de);
		if (ret == DW_DLV_ERROR)
			goto done;
		if (ret == DW_DLV_OK) {
			if (dwarf_formstring(sub_at, &func0, &de) ==
			    DW_DLV_OK) {
				free(*rlt_func);
				if ((*rlt_func = strdup(func0)) == NULL)
					err(EXIT_FAILURE, "strdup");
			}
			goto done;
		}

		/*
		 * If DW_AT_name is not present, but DW_AT_specification is
		 * present, then probably the actual name is in the DIE
		 * referenced by DW_AT_specification.
		 */
		if (dwarf_attr(die, DW_AT_specification, &spec_at, &de))
			goto done;
		if (dwarf_global_formref(spec_at, &ref, &de))
			goto done;
		if (dwarf_offdie(dbg, ref, &spec_die, &de))
			goto done;
		if (dwarf_attrval_string(spec_die, DW_AT_name, &func1, &de) ==
		    DW_DLV_OK) {
			free(*rlt_func);
			if ((*rlt_func = strdup(func1)) == NULL)
			    err(EXIT_FAILURE, "strdup");
		}

		goto done;
	}

cont_search:

	/* Search children. */
	ret = dwarf_child(die, &ret_die, &de);
	if (ret == DW_DLV_ERROR)
		errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de));
	else if (ret == DW_DLV_OK)
		search_func(dbg, ret_die, addr, rlt_func);

	/* Search sibling. */
	ret = dwarf_siblingof(dbg, die, &ret_die, &de);
	if (ret == DW_DLV_ERROR)
		errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de));
	else if (ret == DW_DLV_OK)
		search_func(dbg, ret_die, addr, rlt_func);

done:
	dwarf_dealloc(dbg, die, DW_DLA_DIE);
}