static int sample_ustack(struct perf_sample *sample, struct thread *thread, u64 *regs) { struct stack_dump *stack = &sample->user_stack; struct map *map; unsigned long sp; u64 stack_size, *buf; buf = malloc(STACK_SIZE); if (!buf) { pr_debug("failed to allocate sample uregs data\n"); return -1; } sp = (unsigned long) regs[PERF_REG_POWERPC_R1]; map = map_groups__find(thread->mg, (u64)sp); if (!map) { pr_debug("failed to get stack map\n"); free(buf); return -1; } stack_size = map->end - sp; stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size; memcpy(buf, (void *) sp, stack_size); stack->data = (char *) buf; stack->size = stack_size; return 0; }
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); } }
void thread__find_addr_map(struct thread *self, struct perf_session *session, u8 cpumode, enum map_type type, pid_t pid, u64 addr, struct addr_location *al) { struct map_groups *mg = &self->mg; struct machine *machine = NULL; al->thread = self; al->addr = addr; al->cpumode = cpumode; al->filtered = false; if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { al->level = 'k'; machine = perf_session__find_host_machine(session); if (machine == NULL) { al->map = NULL; return; } mg = &machine->kmaps; } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { al->level = '.'; machine = perf_session__find_host_machine(session); } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { al->level = 'g'; machine = perf_session__find_machine(session, pid); if (machine == NULL) { al->map = NULL; return; } mg = &machine->kmaps; } else { /* * 'u' means guest os user space. * TODO: We don't support guest user space. Might support late. */ if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) al->level = 'u'; else al->level = 'H'; al->map = NULL; if ((cpumode == PERF_RECORD_MISC_GUEST_USER || cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && !perf_guest) al->filtered = true; if ((cpumode == PERF_RECORD_MISC_USER || cpumode == PERF_RECORD_MISC_KERNEL) && !perf_host) al->filtered = true; 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 && cpumode == PERF_RECORD_MISC_KERNEL && machine && mg != &machine->kmaps) { mg = &machine->kmaps; goto try_again; } } else al->addr = al->map->map_ip(al->map, al->addr); }