tools/perf/util/libdw.c

Source file repositories/reference/linux-study-clean/tools/perf/util/libdw.c

File Facts

System
Linux kernel
Corpus path
tools/perf/util/libdw.c
Extension
.c
Size
4061 bytes
Lines
173
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct libdw_a2l_cb_args {
	struct dso *dso;
	struct symbol *sym;
	struct inline_node *node;
	char *leaf_srcline;
	bool leaf_srcline_used;
};

static int libdw_a2l_cb(Dwarf_Die *die, void *_args)
{
	struct libdw_a2l_cb_args *args  = _args;
	struct symbol *inline_sym = new_inline_sym(args->dso, args->sym, dwarf_diename(die));
	const char *call_fname = die_get_call_file(die);
	char *call_srcline = srcline__unknown;
	struct inline_list *ilist;

	if (!inline_sym)
		return -ENOMEM;

	/* Assign caller information to the parent. */
	if (call_fname)
		call_srcline = srcline_from_fileline(call_fname, die_get_call_lineno(die));

	list_for_each_entry(ilist, &args->node->val, list) {
		if (args->leaf_srcline == ilist->srcline)
			args->leaf_srcline_used = false;
		else if (ilist->srcline != srcline__unknown)
			free(ilist->srcline);
		ilist->srcline =  call_srcline;
		call_srcline = NULL;
		break;
	}
	if (call_srcline && call_srcline != srcline__unknown)
		free(call_srcline);

	/* Add this symbol to the chain as the leaf. */
	if (!args->leaf_srcline_used) {
		inline_list__append_tail(inline_sym, args->leaf_srcline, args->node);
		args->leaf_srcline_used = true;
	} else {
		inline_list__append_tail(inline_sym, strdup(args->leaf_srcline), args->node);
	}
	return 0;
}

int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
		     struct dso *dso, bool unwind_inlines,
		     struct inline_node *node, struct symbol *sym)
{
	Dwfl *dwfl = dso__libdw_dwfl(dso);
	Dwfl_Module *mod;
	Dwfl_Line *dwline;
	Dwarf_Addr bias;
	const char *src;
	int lineno = 0;

	if (!dwfl)
		return 0;

	mod = dwfl_addrmodule(dwfl, addr);
	if (!mod)
		return 0;

	/*
	 * Get/ignore the dwarf information. Determine the bias, difference
	 * between the regular ELF addr2line addresses and those to use with
	 * libdw.
	 */
	if (!dwfl_module_getdwarf(mod, &bias))
		return 0;

	/* Find source line information for the address. */
	dwline = dwfl_module_getsrc(mod, addr + bias);
	if (!dwline)
		return 0;

	/* Get line information. */
	src = dwfl_lineinfo(dwline, /*addr=*/NULL, &lineno, /*col=*/NULL, /*mtime=*/NULL,
			    /*length=*/NULL);

	if (file)
		*file = src ? strdup(src) : NULL;
	if (line_nr)
		*line_nr = lineno;

	/* Optionally unwind inline function call chain. */
	if (unwind_inlines && node) {
		Dwarf_Addr unused_bias;
		Dwarf_Die *cudie = dwfl_module_addrdie(mod, addr + bias, &unused_bias);
		struct libdw_a2l_cb_args args = {

Annotation

Implementation Notes