Exemplo n.º 1
0
static int __report_module(struct addr_location *al, u64 ip,
			    struct unwind_info *ui)
{
	Dwfl_Module *mod;
	struct dso *dso = NULL;

	thread__find_addr_location(ui->thread,
				   PERF_RECORD_MISC_USER,
				   MAP__FUNCTION, 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;
}
Exemplo n.º 2
0
int event__preprocess_sample(const event_t *self, struct perf_session *session,
                             struct addr_location *al, symbol_filter_t filter)
{
    u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
    struct thread *thread = perf_session__findnew(session, self->ip.pid);

    if (thread == NULL)
        return -1;

    if (symbol_conf.comm_list &&
            !strlist__has_entry(symbol_conf.comm_list, thread->comm))
        goto out_filtered;

    dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);

    thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION,
                               self->ip.ip, al, filter);
    dump_printf(" ...... dso: %s\n",
                al->map ? al->map->dso->long_name :
                al->level == 'H' ? "[hypervisor]" : "<not found>");
    /*
     * We have to do this here as we may have a dso with no symbol hit that
     * has a name longer than the ones with symbols sampled.
     */
    if (al->map && !sort_dso.elide && !al->map->dso->slen_calculated)
        dso__calc_col_width(al->map->dso);

    if (symbol_conf.dso_list &&
            (!al->map || !al->map->dso ||
             !(strlist__has_entry(symbol_conf.dso_list, al->map->dso->short_name) ||
               (al->map->dso->short_name != al->map->dso->long_name &&
                strlist__has_entry(symbol_conf.dso_list, al->map->dso->long_name)))))
        goto out_filtered;

    if (symbol_conf.sym_list && al->sym &&
            !strlist__has_entry(symbol_conf.sym_list, al->sym->name))
        goto out_filtered;

    al->filtered = false;
    return 0;

out_filtered:
    al->filtered = true;
    return 0;
}
Exemplo n.º 3
0
int event__preprocess_sample(const event_t *self, struct addr_location *al,
			     symbol_filter_t filter)
{
	u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
	struct thread *thread = threads__findnew(self->ip.pid);

	if (thread == NULL)
		return -1;

	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);

	thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
				   self->ip.ip, al, filter);
	dump_printf(" ...... dso: %s\n",
		    al->map ? al->map->dso->long_name :
			al->level == 'H' ? "[hypervisor]" : "<not found>");
	return 0;
}
Exemplo n.º 4
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->nr < 3)
		return skip_slot;

	ip = chain->ips[2];

	thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
			MAP__FUNCTION, 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;
}
Exemplo n.º 5
0
static int __report_module(struct addr_location *al, u64 ip,
			    struct unwind_info *ui)
{
	Dwfl_Module *mod;
	struct dso *dso = NULL;

	thread__find_addr_location(ui->thread, ui->machine,
				   PERF_RECORD_MISC_USER,
				   MAP__FUNCTION, ip, al);

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

	if (!dso)
		return 0;

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

	return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
}