100447ccdSAdrian Hunter /* 200447ccdSAdrian Hunter * thread-stack.c: Synthesize a thread's stack using call / return events 300447ccdSAdrian Hunter * Copyright (c) 2014, Intel Corporation. 400447ccdSAdrian Hunter * 500447ccdSAdrian Hunter * This program is free software; you can redistribute it and/or modify it 600447ccdSAdrian Hunter * under the terms and conditions of the GNU General Public License, 700447ccdSAdrian Hunter * version 2, as published by the Free Software Foundation. 800447ccdSAdrian Hunter * 900447ccdSAdrian Hunter * This program is distributed in the hope it will be useful, but WITHOUT 1000447ccdSAdrian Hunter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1100447ccdSAdrian Hunter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1200447ccdSAdrian Hunter * more details. 1300447ccdSAdrian Hunter * 1400447ccdSAdrian Hunter */ 1500447ccdSAdrian Hunter 1600447ccdSAdrian Hunter #include "thread.h" 1700447ccdSAdrian Hunter #include "event.h" 1800447ccdSAdrian Hunter #include "util.h" 1900447ccdSAdrian Hunter #include "debug.h" 2000447ccdSAdrian Hunter #include "thread-stack.h" 2100447ccdSAdrian Hunter 2200447ccdSAdrian Hunter #define STACK_GROWTH 4096 2300447ccdSAdrian Hunter 2400447ccdSAdrian Hunter struct thread_stack_entry { 2500447ccdSAdrian Hunter u64 ret_addr; 2600447ccdSAdrian Hunter }; 2700447ccdSAdrian Hunter 2800447ccdSAdrian Hunter struct thread_stack { 2900447ccdSAdrian Hunter struct thread_stack_entry *stack; 3000447ccdSAdrian Hunter size_t cnt; 3100447ccdSAdrian Hunter size_t sz; 3200447ccdSAdrian Hunter u64 trace_nr; 3300447ccdSAdrian Hunter }; 3400447ccdSAdrian Hunter 3500447ccdSAdrian Hunter static int thread_stack__grow(struct thread_stack *ts) 3600447ccdSAdrian Hunter { 3700447ccdSAdrian Hunter struct thread_stack_entry *new_stack; 3800447ccdSAdrian Hunter size_t sz, new_sz; 3900447ccdSAdrian Hunter 4000447ccdSAdrian Hunter new_sz = ts->sz + STACK_GROWTH; 4100447ccdSAdrian Hunter sz = new_sz * sizeof(struct thread_stack_entry); 4200447ccdSAdrian Hunter 4300447ccdSAdrian Hunter new_stack = realloc(ts->stack, sz); 4400447ccdSAdrian Hunter if (!new_stack) 4500447ccdSAdrian Hunter return -ENOMEM; 4600447ccdSAdrian Hunter 4700447ccdSAdrian Hunter ts->stack = new_stack; 4800447ccdSAdrian Hunter ts->sz = new_sz; 4900447ccdSAdrian Hunter 5000447ccdSAdrian Hunter return 0; 5100447ccdSAdrian Hunter } 5200447ccdSAdrian Hunter 5300447ccdSAdrian Hunter static struct thread_stack *thread_stack__new(void) 5400447ccdSAdrian Hunter { 5500447ccdSAdrian Hunter struct thread_stack *ts; 5600447ccdSAdrian Hunter 5700447ccdSAdrian Hunter ts = zalloc(sizeof(struct thread_stack)); 5800447ccdSAdrian Hunter if (!ts) 5900447ccdSAdrian Hunter return NULL; 6000447ccdSAdrian Hunter 6100447ccdSAdrian Hunter if (thread_stack__grow(ts)) { 6200447ccdSAdrian Hunter free(ts); 6300447ccdSAdrian Hunter return NULL; 6400447ccdSAdrian Hunter } 6500447ccdSAdrian Hunter 6600447ccdSAdrian Hunter return ts; 6700447ccdSAdrian Hunter } 6800447ccdSAdrian Hunter 6900447ccdSAdrian Hunter static int thread_stack__push(struct thread_stack *ts, u64 ret_addr) 7000447ccdSAdrian Hunter { 7100447ccdSAdrian Hunter int err = 0; 7200447ccdSAdrian Hunter 7300447ccdSAdrian Hunter if (ts->cnt == ts->sz) { 7400447ccdSAdrian Hunter err = thread_stack__grow(ts); 7500447ccdSAdrian Hunter if (err) { 7600447ccdSAdrian Hunter pr_warning("Out of memory: discarding thread stack\n"); 7700447ccdSAdrian Hunter ts->cnt = 0; 7800447ccdSAdrian Hunter } 7900447ccdSAdrian Hunter } 8000447ccdSAdrian Hunter 8100447ccdSAdrian Hunter ts->stack[ts->cnt++].ret_addr = ret_addr; 8200447ccdSAdrian Hunter 8300447ccdSAdrian Hunter return err; 8400447ccdSAdrian Hunter } 8500447ccdSAdrian Hunter 8600447ccdSAdrian Hunter static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr) 8700447ccdSAdrian Hunter { 8800447ccdSAdrian Hunter size_t i; 8900447ccdSAdrian Hunter 9000447ccdSAdrian Hunter /* 9100447ccdSAdrian Hunter * In some cases there may be functions which are not seen to return. 9200447ccdSAdrian Hunter * For example when setjmp / longjmp has been used. Or the perf context 9300447ccdSAdrian Hunter * switch in the kernel which doesn't stop and start tracing in exactly 9400447ccdSAdrian Hunter * the same code path. When that happens the return address will be 9500447ccdSAdrian Hunter * further down the stack. If the return address is not found at all, 9600447ccdSAdrian Hunter * we assume the opposite (i.e. this is a return for a call that wasn't 9700447ccdSAdrian Hunter * seen for some reason) and leave the stack alone. 9800447ccdSAdrian Hunter */ 9900447ccdSAdrian Hunter for (i = ts->cnt; i; ) { 10000447ccdSAdrian Hunter if (ts->stack[--i].ret_addr == ret_addr) { 10100447ccdSAdrian Hunter ts->cnt = i; 10200447ccdSAdrian Hunter return; 10300447ccdSAdrian Hunter } 10400447ccdSAdrian Hunter } 10500447ccdSAdrian Hunter } 10600447ccdSAdrian Hunter 10700447ccdSAdrian Hunter int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 10800447ccdSAdrian Hunter u64 to_ip, u16 insn_len, u64 trace_nr) 10900447ccdSAdrian Hunter { 11000447ccdSAdrian Hunter if (!thread) 11100447ccdSAdrian Hunter return -EINVAL; 11200447ccdSAdrian Hunter 11300447ccdSAdrian Hunter if (!thread->ts) { 11400447ccdSAdrian Hunter thread->ts = thread_stack__new(); 11500447ccdSAdrian Hunter if (!thread->ts) { 11600447ccdSAdrian Hunter pr_warning("Out of memory: no thread stack\n"); 11700447ccdSAdrian Hunter return -ENOMEM; 11800447ccdSAdrian Hunter } 11900447ccdSAdrian Hunter thread->ts->trace_nr = trace_nr; 12000447ccdSAdrian Hunter } 12100447ccdSAdrian Hunter 12200447ccdSAdrian Hunter /* 12300447ccdSAdrian Hunter * When the trace is discontinuous, the trace_nr changes. In that case 12400447ccdSAdrian Hunter * the stack might be completely invalid. Better to report nothing than 12500447ccdSAdrian Hunter * to report something misleading, so reset the stack count to zero. 12600447ccdSAdrian Hunter */ 12700447ccdSAdrian Hunter if (trace_nr != thread->ts->trace_nr) { 12800447ccdSAdrian Hunter thread->ts->trace_nr = trace_nr; 12900447ccdSAdrian Hunter thread->ts->cnt = 0; 13000447ccdSAdrian Hunter } 13100447ccdSAdrian Hunter 13200447ccdSAdrian Hunter if (flags & PERF_IP_FLAG_CALL) { 13300447ccdSAdrian Hunter u64 ret_addr; 13400447ccdSAdrian Hunter 13500447ccdSAdrian Hunter if (!to_ip) 13600447ccdSAdrian Hunter return 0; 13700447ccdSAdrian Hunter ret_addr = from_ip + insn_len; 13800447ccdSAdrian Hunter if (ret_addr == to_ip) 13900447ccdSAdrian Hunter return 0; /* Zero-length calls are excluded */ 14000447ccdSAdrian Hunter return thread_stack__push(thread->ts, ret_addr); 14100447ccdSAdrian Hunter } else if (flags & PERF_IP_FLAG_RETURN) { 14200447ccdSAdrian Hunter if (!from_ip) 14300447ccdSAdrian Hunter return 0; 14400447ccdSAdrian Hunter thread_stack__pop(thread->ts, to_ip); 14500447ccdSAdrian Hunter } 14600447ccdSAdrian Hunter 14700447ccdSAdrian Hunter return 0; 14800447ccdSAdrian Hunter } 14900447ccdSAdrian Hunter 15000447ccdSAdrian Hunter void thread_stack__free(struct thread *thread) 15100447ccdSAdrian Hunter { 15200447ccdSAdrian Hunter if (thread->ts) { 15300447ccdSAdrian Hunter zfree(&thread->ts->stack); 15400447ccdSAdrian Hunter zfree(&thread->ts); 15500447ccdSAdrian Hunter } 15600447ccdSAdrian Hunter } 15700447ccdSAdrian Hunter 15800447ccdSAdrian Hunter void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 15900447ccdSAdrian Hunter size_t sz, u64 ip) 16000447ccdSAdrian Hunter { 16100447ccdSAdrian Hunter size_t i; 16200447ccdSAdrian Hunter 16300447ccdSAdrian Hunter if (!thread || !thread->ts) 16400447ccdSAdrian Hunter chain->nr = 1; 16500447ccdSAdrian Hunter else 16600447ccdSAdrian Hunter chain->nr = min(sz, thread->ts->cnt + 1); 16700447ccdSAdrian Hunter 16800447ccdSAdrian Hunter chain->ips[0] = ip; 16900447ccdSAdrian Hunter 17000447ccdSAdrian Hunter for (i = 1; i < chain->nr; i++) 17100447ccdSAdrian Hunter chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr; 17200447ccdSAdrian Hunter } 173