void thread__find_addr_location(struct thread *self, struct perf_session *session, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al, symbol_filter_t filter) { thread__find_addr_map(self, session, cpumode, type, addr, al); if (al->map != NULL) al->sym = map__find_symbol(al->map, al->addr, filter); else al->sym = NULL; }
void thread__find_addr_location(struct thread *self, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al, symbol_filter_t filter) { struct map_groups *mg = &self->mg; al->thread = self; al->addr = addr; if (cpumode & PERF_RECORD_MISC_KERNEL) { al->level = 'k'; mg = kmaps; } else if (cpumode & PERF_RECORD_MISC_USER) al->level = '.'; else { al->level = 'H'; al->map = NULL; al->sym = NULL; return; } try_again: al->map = map_groups__find(mg, type, al->addr); if (al->map == NULL) { /* * If this is outside of all known maps, and is a negative * address, try to look it up in the kernel dso, as it might be * a vsyscall or vdso (which executes in user-mode). * * XXX This is nasty, we should have a symbol list in the * "[vdso]" dso, but for now lets use the old trick of looking * in the whole kernel symbol list. */ if ((long long)al->addr < 0 && mg != kmaps) { mg = kmaps; goto try_again; } al->sym = NULL; } else { al->addr = al->map->map_ip(al->map, al->addr); al->sym = map__find_symbol(al->map, al->addr, filter); } }
static int call__parse(struct ins_operands *ops, struct map *map) { char *endptr, *tok, *name; ops->target.addr = strtoull(ops->raw, &endptr, 16); name = strchr(endptr, '<'); if (name == NULL) goto indirect_call; name++; #ifdef __arm__ if (strchr(name, '+')) return -1; #endif tok = strchr(name, '>'); if (tok == NULL) return -1; *tok = '\0'; ops->target.name = strdup(name); *tok = '>'; return ops->target.name == NULL ? -1 : 0; indirect_call: tok = strchr(endptr, '*'); if (tok == NULL) { struct symbol *sym = map__find_symbol(map, map->map_ip(map, ops->target.addr)); if (sym != NULL) ops->target.name = strdup(sym->name); else ops->target.addr = 0; return 0; } ops->target.addr = strtoull(tok + 1, NULL, 16); return 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); /* * Have we already created the kernel maps for the host machine? * * This should have happened earlier, when we processed the kernel MMAP * events, but for older perf.data files there was no such thing, so do * it now. */ if (cpumode == PERF_RECORD_MISC_KERNEL && session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) machine__create_kernel_maps(&session->host_machine); thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, self->ip.pid, self->ip.ip, al); dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : "<not found>"); al->sym = NULL; if (al->map) { 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; /* * 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 (!sort_dso.elide && !al->map->dso->slen_calculated) dso__calc_col_width(al->map->dso); al->sym = map__find_symbol(al->map, al->addr, filter); } else { const unsigned int unresolved_col_width = BITS_PER_LONG / 4; if (dsos__col_width < unresolved_col_width && !symbol_conf.col_width_list_str && !symbol_conf.field_sep && !symbol_conf.dso_list) dsos__col_width = unresolved_col_width; } if (symbol_conf.sym_list && al->sym && !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) goto out_filtered; return 0; out_filtered: al->filtered = true; return 0; }