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; }
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; }
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; }
/* * 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; }
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; }