Beispiel #1
0
static int __report_module(struct addr_location *al, u64 ip,
			    struct unwind_info *ui)
{
	Dwfl_Module *mod;
	struct dso *dso = NULL;
	/*
	 * Some callers will use al->sym, so we can't just use the
	 * cheaper thread__find_map() here.
	 */
	thread__find_symbol(ui->thread, PERF_RECORD_MISC_USER, ip, al);

	if (al->map)
		dso = al->map->dso;

	if (!dso)
		return 0;

	mod = dwfl_addrmodule(ui->dwfl, ip);
	if (mod) {
		Dwarf_Addr s;

		dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
		if (s != al->map->start)
			mod = 0;
	}

	if (!mod)
		mod = dwfl_report_elf(ui->dwfl, dso->short_name,
				      (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start,
				      false);

	return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
}
Beispiel #2
0
/*
 * The callchain saved by the kernel always includes the link register (LR).
 *
 *	0:	PERF_CONTEXT_USER
 *	1:	Program counter (Next instruction pointer)
 *	2:	LR value
 *	3:	Caller's caller
 *	4:	...
 *
 * The value in LR is only needed when it holds a return address. If the
 * return address is on the stack, we should ignore the LR value.
 *
 * Further, when the return address is in the LR, if a new frame was just
 * allocated but the LR was not saved into it, then the LR contains the
 * caller, slot 4: contains the caller's caller and the contents of slot 3:
 * (chain->ips[3]) is undefined and must be ignored.
 *
 * Use DWARF debug information to determine if any entries need to be skipped.
 *
 * Return:
 *	index:	of callchain entry that needs to be ignored (if any)
 *	-1	if no entry needs to be ignored or in case of errors
 */
int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
{
	struct addr_location al;
	struct dso *dso = NULL;
	int rc;
	u64 ip;
	u64 skip_slot = -1;

	if (!chain || chain->nr < 3)
		return skip_slot;

	ip = chain->ips[1];

	thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);

	if (al.map)
		dso = al.map->dso;

	if (!dso) {
		pr_debug("%" PRIx64 " dso is NULL\n", ip);
		return skip_slot;
	}

	rc = check_return_addr(dso, al.map->start, ip);

	pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n",
				dso->long_name, al.sym->name, ip, rc);

	if (rc == 0) {
		/*
		 * Return address on stack. Ignore LR value in callchain
		 */
		skip_slot = 2;
	} else if (rc == 2) {
		/*
		 * New frame allocated but return address still in LR.
		 * Ignore the caller's caller entry in callchain.
		 */
		skip_slot = 3;
	}
	return skip_slot;
}