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 16*92a9e4f7SAdrian Hunter #include <linux/rbtree.h> 17*92a9e4f7SAdrian Hunter #include <linux/list.h> 1800447ccdSAdrian Hunter #include "thread.h" 1900447ccdSAdrian Hunter #include "event.h" 20*92a9e4f7SAdrian Hunter #include "machine.h" 2100447ccdSAdrian Hunter #include "util.h" 2200447ccdSAdrian Hunter #include "debug.h" 23*92a9e4f7SAdrian Hunter #include "symbol.h" 24*92a9e4f7SAdrian Hunter #include "comm.h" 2500447ccdSAdrian Hunter #include "thread-stack.h" 2600447ccdSAdrian Hunter 27*92a9e4f7SAdrian Hunter #define CALL_PATH_BLOCK_SHIFT 8 28*92a9e4f7SAdrian Hunter #define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT) 29*92a9e4f7SAdrian Hunter #define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1) 3000447ccdSAdrian Hunter 31*92a9e4f7SAdrian Hunter struct call_path_block { 32*92a9e4f7SAdrian Hunter struct call_path cp[CALL_PATH_BLOCK_SIZE]; 33*92a9e4f7SAdrian Hunter struct list_head node; 3400447ccdSAdrian Hunter }; 3500447ccdSAdrian Hunter 36*92a9e4f7SAdrian Hunter /** 37*92a9e4f7SAdrian Hunter * struct call_path_root - root of all call paths. 38*92a9e4f7SAdrian Hunter * @call_path: root call path 39*92a9e4f7SAdrian Hunter * @blocks: list of blocks to store call paths 40*92a9e4f7SAdrian Hunter * @next: next free space 41*92a9e4f7SAdrian Hunter * @sz: number of spaces 42*92a9e4f7SAdrian Hunter */ 43*92a9e4f7SAdrian Hunter struct call_path_root { 44*92a9e4f7SAdrian Hunter struct call_path call_path; 45*92a9e4f7SAdrian Hunter struct list_head blocks; 46*92a9e4f7SAdrian Hunter size_t next; 47*92a9e4f7SAdrian Hunter size_t sz; 48*92a9e4f7SAdrian Hunter }; 49*92a9e4f7SAdrian Hunter 50*92a9e4f7SAdrian Hunter /** 51*92a9e4f7SAdrian Hunter * struct call_return_processor - provides a call-back to consume call-return 52*92a9e4f7SAdrian Hunter * information. 53*92a9e4f7SAdrian Hunter * @cpr: call path root 54*92a9e4f7SAdrian Hunter * @process: call-back that accepts call/return information 55*92a9e4f7SAdrian Hunter * @data: anonymous data for call-back 56*92a9e4f7SAdrian Hunter */ 57*92a9e4f7SAdrian Hunter struct call_return_processor { 58*92a9e4f7SAdrian Hunter struct call_path_root *cpr; 59*92a9e4f7SAdrian Hunter int (*process)(struct call_return *cr, void *data); 60*92a9e4f7SAdrian Hunter void *data; 61*92a9e4f7SAdrian Hunter }; 62*92a9e4f7SAdrian Hunter 63*92a9e4f7SAdrian Hunter #define STACK_GROWTH 2048 64*92a9e4f7SAdrian Hunter 65*92a9e4f7SAdrian Hunter /** 66*92a9e4f7SAdrian Hunter * struct thread_stack_entry - thread stack entry. 67*92a9e4f7SAdrian Hunter * @ret_addr: return address 68*92a9e4f7SAdrian Hunter * @timestamp: timestamp (if known) 69*92a9e4f7SAdrian Hunter * @ref: external reference (e.g. db_id of sample) 70*92a9e4f7SAdrian Hunter * @branch_count: the branch count when the entry was created 71*92a9e4f7SAdrian Hunter * @cp: call path 72*92a9e4f7SAdrian Hunter * @no_call: a 'call' was not seen 73*92a9e4f7SAdrian Hunter */ 74*92a9e4f7SAdrian Hunter struct thread_stack_entry { 75*92a9e4f7SAdrian Hunter u64 ret_addr; 76*92a9e4f7SAdrian Hunter u64 timestamp; 77*92a9e4f7SAdrian Hunter u64 ref; 78*92a9e4f7SAdrian Hunter u64 branch_count; 79*92a9e4f7SAdrian Hunter struct call_path *cp; 80*92a9e4f7SAdrian Hunter bool no_call; 81*92a9e4f7SAdrian Hunter }; 82*92a9e4f7SAdrian Hunter 83*92a9e4f7SAdrian Hunter /** 84*92a9e4f7SAdrian Hunter * struct thread_stack - thread stack constructed from 'call' and 'return' 85*92a9e4f7SAdrian Hunter * branch samples. 86*92a9e4f7SAdrian Hunter * @stack: array that holds the stack 87*92a9e4f7SAdrian Hunter * @cnt: number of entries in the stack 88*92a9e4f7SAdrian Hunter * @sz: current maximum stack size 89*92a9e4f7SAdrian Hunter * @trace_nr: current trace number 90*92a9e4f7SAdrian Hunter * @branch_count: running branch count 91*92a9e4f7SAdrian Hunter * @kernel_start: kernel start address 92*92a9e4f7SAdrian Hunter * @last_time: last timestamp 93*92a9e4f7SAdrian Hunter * @crp: call/return processor 94*92a9e4f7SAdrian Hunter * @comm: current comm 95*92a9e4f7SAdrian Hunter */ 9600447ccdSAdrian Hunter struct thread_stack { 9700447ccdSAdrian Hunter struct thread_stack_entry *stack; 9800447ccdSAdrian Hunter size_t cnt; 9900447ccdSAdrian Hunter size_t sz; 10000447ccdSAdrian Hunter u64 trace_nr; 101*92a9e4f7SAdrian Hunter u64 branch_count; 102*92a9e4f7SAdrian Hunter u64 kernel_start; 103*92a9e4f7SAdrian Hunter u64 last_time; 104*92a9e4f7SAdrian Hunter struct call_return_processor *crp; 105*92a9e4f7SAdrian Hunter struct comm *comm; 10600447ccdSAdrian Hunter }; 10700447ccdSAdrian Hunter 10800447ccdSAdrian Hunter static int thread_stack__grow(struct thread_stack *ts) 10900447ccdSAdrian Hunter { 11000447ccdSAdrian Hunter struct thread_stack_entry *new_stack; 11100447ccdSAdrian Hunter size_t sz, new_sz; 11200447ccdSAdrian Hunter 11300447ccdSAdrian Hunter new_sz = ts->sz + STACK_GROWTH; 11400447ccdSAdrian Hunter sz = new_sz * sizeof(struct thread_stack_entry); 11500447ccdSAdrian Hunter 11600447ccdSAdrian Hunter new_stack = realloc(ts->stack, sz); 11700447ccdSAdrian Hunter if (!new_stack) 11800447ccdSAdrian Hunter return -ENOMEM; 11900447ccdSAdrian Hunter 12000447ccdSAdrian Hunter ts->stack = new_stack; 12100447ccdSAdrian Hunter ts->sz = new_sz; 12200447ccdSAdrian Hunter 12300447ccdSAdrian Hunter return 0; 12400447ccdSAdrian Hunter } 12500447ccdSAdrian Hunter 126*92a9e4f7SAdrian Hunter static struct thread_stack *thread_stack__new(struct thread *thread, 127*92a9e4f7SAdrian Hunter struct call_return_processor *crp) 12800447ccdSAdrian Hunter { 12900447ccdSAdrian Hunter struct thread_stack *ts; 13000447ccdSAdrian Hunter 13100447ccdSAdrian Hunter ts = zalloc(sizeof(struct thread_stack)); 13200447ccdSAdrian Hunter if (!ts) 13300447ccdSAdrian Hunter return NULL; 13400447ccdSAdrian Hunter 13500447ccdSAdrian Hunter if (thread_stack__grow(ts)) { 13600447ccdSAdrian Hunter free(ts); 13700447ccdSAdrian Hunter return NULL; 13800447ccdSAdrian Hunter } 13900447ccdSAdrian Hunter 140*92a9e4f7SAdrian Hunter if (thread->mg && thread->mg->machine) 141*92a9e4f7SAdrian Hunter ts->kernel_start = machine__kernel_start(thread->mg->machine); 142*92a9e4f7SAdrian Hunter else 143*92a9e4f7SAdrian Hunter ts->kernel_start = 1ULL << 63; 144*92a9e4f7SAdrian Hunter ts->crp = crp; 145*92a9e4f7SAdrian Hunter 14600447ccdSAdrian Hunter return ts; 14700447ccdSAdrian Hunter } 14800447ccdSAdrian Hunter 14900447ccdSAdrian Hunter static int thread_stack__push(struct thread_stack *ts, u64 ret_addr) 15000447ccdSAdrian Hunter { 15100447ccdSAdrian Hunter int err = 0; 15200447ccdSAdrian Hunter 15300447ccdSAdrian Hunter if (ts->cnt == ts->sz) { 15400447ccdSAdrian Hunter err = thread_stack__grow(ts); 15500447ccdSAdrian Hunter if (err) { 15600447ccdSAdrian Hunter pr_warning("Out of memory: discarding thread stack\n"); 15700447ccdSAdrian Hunter ts->cnt = 0; 15800447ccdSAdrian Hunter } 15900447ccdSAdrian Hunter } 16000447ccdSAdrian Hunter 16100447ccdSAdrian Hunter ts->stack[ts->cnt++].ret_addr = ret_addr; 16200447ccdSAdrian Hunter 16300447ccdSAdrian Hunter return err; 16400447ccdSAdrian Hunter } 16500447ccdSAdrian Hunter 16600447ccdSAdrian Hunter static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr) 16700447ccdSAdrian Hunter { 16800447ccdSAdrian Hunter size_t i; 16900447ccdSAdrian Hunter 17000447ccdSAdrian Hunter /* 17100447ccdSAdrian Hunter * In some cases there may be functions which are not seen to return. 17200447ccdSAdrian Hunter * For example when setjmp / longjmp has been used. Or the perf context 17300447ccdSAdrian Hunter * switch in the kernel which doesn't stop and start tracing in exactly 17400447ccdSAdrian Hunter * the same code path. When that happens the return address will be 17500447ccdSAdrian Hunter * further down the stack. If the return address is not found at all, 17600447ccdSAdrian Hunter * we assume the opposite (i.e. this is a return for a call that wasn't 17700447ccdSAdrian Hunter * seen for some reason) and leave the stack alone. 17800447ccdSAdrian Hunter */ 17900447ccdSAdrian Hunter for (i = ts->cnt; i; ) { 18000447ccdSAdrian Hunter if (ts->stack[--i].ret_addr == ret_addr) { 18100447ccdSAdrian Hunter ts->cnt = i; 18200447ccdSAdrian Hunter return; 18300447ccdSAdrian Hunter } 18400447ccdSAdrian Hunter } 18500447ccdSAdrian Hunter } 18600447ccdSAdrian Hunter 187*92a9e4f7SAdrian Hunter static bool thread_stack__in_kernel(struct thread_stack *ts) 188*92a9e4f7SAdrian Hunter { 189*92a9e4f7SAdrian Hunter if (!ts->cnt) 190*92a9e4f7SAdrian Hunter return false; 191*92a9e4f7SAdrian Hunter 192*92a9e4f7SAdrian Hunter return ts->stack[ts->cnt - 1].cp->in_kernel; 193*92a9e4f7SAdrian Hunter } 194*92a9e4f7SAdrian Hunter 195*92a9e4f7SAdrian Hunter static int thread_stack__call_return(struct thread *thread, 196*92a9e4f7SAdrian Hunter struct thread_stack *ts, size_t idx, 197*92a9e4f7SAdrian Hunter u64 timestamp, u64 ref, bool no_return) 198*92a9e4f7SAdrian Hunter { 199*92a9e4f7SAdrian Hunter struct call_return_processor *crp = ts->crp; 200*92a9e4f7SAdrian Hunter struct thread_stack_entry *tse; 201*92a9e4f7SAdrian Hunter struct call_return cr = { 202*92a9e4f7SAdrian Hunter .thread = thread, 203*92a9e4f7SAdrian Hunter .comm = ts->comm, 204*92a9e4f7SAdrian Hunter .db_id = 0, 205*92a9e4f7SAdrian Hunter }; 206*92a9e4f7SAdrian Hunter 207*92a9e4f7SAdrian Hunter tse = &ts->stack[idx]; 208*92a9e4f7SAdrian Hunter cr.cp = tse->cp; 209*92a9e4f7SAdrian Hunter cr.call_time = tse->timestamp; 210*92a9e4f7SAdrian Hunter cr.return_time = timestamp; 211*92a9e4f7SAdrian Hunter cr.branch_count = ts->branch_count - tse->branch_count; 212*92a9e4f7SAdrian Hunter cr.call_ref = tse->ref; 213*92a9e4f7SAdrian Hunter cr.return_ref = ref; 214*92a9e4f7SAdrian Hunter if (tse->no_call) 215*92a9e4f7SAdrian Hunter cr.flags |= CALL_RETURN_NO_CALL; 216*92a9e4f7SAdrian Hunter if (no_return) 217*92a9e4f7SAdrian Hunter cr.flags |= CALL_RETURN_NO_RETURN; 218*92a9e4f7SAdrian Hunter 219*92a9e4f7SAdrian Hunter return crp->process(&cr, crp->data); 220*92a9e4f7SAdrian Hunter } 221*92a9e4f7SAdrian Hunter 222*92a9e4f7SAdrian Hunter static int thread_stack__flush(struct thread *thread, struct thread_stack *ts) 223*92a9e4f7SAdrian Hunter { 224*92a9e4f7SAdrian Hunter struct call_return_processor *crp = ts->crp; 225*92a9e4f7SAdrian Hunter int err; 226*92a9e4f7SAdrian Hunter 227*92a9e4f7SAdrian Hunter if (!crp) { 228*92a9e4f7SAdrian Hunter ts->cnt = 0; 229*92a9e4f7SAdrian Hunter return 0; 230*92a9e4f7SAdrian Hunter } 231*92a9e4f7SAdrian Hunter 232*92a9e4f7SAdrian Hunter while (ts->cnt) { 233*92a9e4f7SAdrian Hunter err = thread_stack__call_return(thread, ts, --ts->cnt, 234*92a9e4f7SAdrian Hunter ts->last_time, 0, true); 235*92a9e4f7SAdrian Hunter if (err) { 236*92a9e4f7SAdrian Hunter pr_err("Error flushing thread stack!\n"); 237*92a9e4f7SAdrian Hunter ts->cnt = 0; 238*92a9e4f7SAdrian Hunter return err; 239*92a9e4f7SAdrian Hunter } 240*92a9e4f7SAdrian Hunter } 241*92a9e4f7SAdrian Hunter 242*92a9e4f7SAdrian Hunter return 0; 243*92a9e4f7SAdrian Hunter } 244*92a9e4f7SAdrian Hunter 24500447ccdSAdrian Hunter int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 24600447ccdSAdrian Hunter u64 to_ip, u16 insn_len, u64 trace_nr) 24700447ccdSAdrian Hunter { 24800447ccdSAdrian Hunter if (!thread) 24900447ccdSAdrian Hunter return -EINVAL; 25000447ccdSAdrian Hunter 25100447ccdSAdrian Hunter if (!thread->ts) { 252*92a9e4f7SAdrian Hunter thread->ts = thread_stack__new(thread, NULL); 25300447ccdSAdrian Hunter if (!thread->ts) { 25400447ccdSAdrian Hunter pr_warning("Out of memory: no thread stack\n"); 25500447ccdSAdrian Hunter return -ENOMEM; 25600447ccdSAdrian Hunter } 25700447ccdSAdrian Hunter thread->ts->trace_nr = trace_nr; 25800447ccdSAdrian Hunter } 25900447ccdSAdrian Hunter 26000447ccdSAdrian Hunter /* 26100447ccdSAdrian Hunter * When the trace is discontinuous, the trace_nr changes. In that case 26200447ccdSAdrian Hunter * the stack might be completely invalid. Better to report nothing than 263*92a9e4f7SAdrian Hunter * to report something misleading, so flush the stack. 26400447ccdSAdrian Hunter */ 26500447ccdSAdrian Hunter if (trace_nr != thread->ts->trace_nr) { 266*92a9e4f7SAdrian Hunter if (thread->ts->trace_nr) 267*92a9e4f7SAdrian Hunter thread_stack__flush(thread, thread->ts); 26800447ccdSAdrian Hunter thread->ts->trace_nr = trace_nr; 26900447ccdSAdrian Hunter } 27000447ccdSAdrian Hunter 271*92a9e4f7SAdrian Hunter /* Stop here if thread_stack__process() is in use */ 272*92a9e4f7SAdrian Hunter if (thread->ts->crp) 273*92a9e4f7SAdrian Hunter return 0; 274*92a9e4f7SAdrian Hunter 27500447ccdSAdrian Hunter if (flags & PERF_IP_FLAG_CALL) { 27600447ccdSAdrian Hunter u64 ret_addr; 27700447ccdSAdrian Hunter 27800447ccdSAdrian Hunter if (!to_ip) 27900447ccdSAdrian Hunter return 0; 28000447ccdSAdrian Hunter ret_addr = from_ip + insn_len; 28100447ccdSAdrian Hunter if (ret_addr == to_ip) 28200447ccdSAdrian Hunter return 0; /* Zero-length calls are excluded */ 28300447ccdSAdrian Hunter return thread_stack__push(thread->ts, ret_addr); 28400447ccdSAdrian Hunter } else if (flags & PERF_IP_FLAG_RETURN) { 28500447ccdSAdrian Hunter if (!from_ip) 28600447ccdSAdrian Hunter return 0; 28700447ccdSAdrian Hunter thread_stack__pop(thread->ts, to_ip); 28800447ccdSAdrian Hunter } 28900447ccdSAdrian Hunter 29000447ccdSAdrian Hunter return 0; 29100447ccdSAdrian Hunter } 29200447ccdSAdrian Hunter 293*92a9e4f7SAdrian Hunter void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr) 294*92a9e4f7SAdrian Hunter { 295*92a9e4f7SAdrian Hunter if (!thread || !thread->ts) 296*92a9e4f7SAdrian Hunter return; 297*92a9e4f7SAdrian Hunter 298*92a9e4f7SAdrian Hunter if (trace_nr != thread->ts->trace_nr) { 299*92a9e4f7SAdrian Hunter if (thread->ts->trace_nr) 300*92a9e4f7SAdrian Hunter thread_stack__flush(thread, thread->ts); 301*92a9e4f7SAdrian Hunter thread->ts->trace_nr = trace_nr; 302*92a9e4f7SAdrian Hunter } 303*92a9e4f7SAdrian Hunter } 304*92a9e4f7SAdrian Hunter 30500447ccdSAdrian Hunter void thread_stack__free(struct thread *thread) 30600447ccdSAdrian Hunter { 30700447ccdSAdrian Hunter if (thread->ts) { 308*92a9e4f7SAdrian Hunter thread_stack__flush(thread, thread->ts); 30900447ccdSAdrian Hunter zfree(&thread->ts->stack); 31000447ccdSAdrian Hunter zfree(&thread->ts); 31100447ccdSAdrian Hunter } 31200447ccdSAdrian Hunter } 31300447ccdSAdrian Hunter 31400447ccdSAdrian Hunter void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 31500447ccdSAdrian Hunter size_t sz, u64 ip) 31600447ccdSAdrian Hunter { 31700447ccdSAdrian Hunter size_t i; 31800447ccdSAdrian Hunter 31900447ccdSAdrian Hunter if (!thread || !thread->ts) 32000447ccdSAdrian Hunter chain->nr = 1; 32100447ccdSAdrian Hunter else 32200447ccdSAdrian Hunter chain->nr = min(sz, thread->ts->cnt + 1); 32300447ccdSAdrian Hunter 32400447ccdSAdrian Hunter chain->ips[0] = ip; 32500447ccdSAdrian Hunter 32600447ccdSAdrian Hunter for (i = 1; i < chain->nr; i++) 32700447ccdSAdrian Hunter chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr; 32800447ccdSAdrian Hunter } 329*92a9e4f7SAdrian Hunter 330*92a9e4f7SAdrian Hunter static void call_path__init(struct call_path *cp, struct call_path *parent, 331*92a9e4f7SAdrian Hunter struct symbol *sym, u64 ip, bool in_kernel) 332*92a9e4f7SAdrian Hunter { 333*92a9e4f7SAdrian Hunter cp->parent = parent; 334*92a9e4f7SAdrian Hunter cp->sym = sym; 335*92a9e4f7SAdrian Hunter cp->ip = sym ? 0 : ip; 336*92a9e4f7SAdrian Hunter cp->db_id = 0; 337*92a9e4f7SAdrian Hunter cp->in_kernel = in_kernel; 338*92a9e4f7SAdrian Hunter RB_CLEAR_NODE(&cp->rb_node); 339*92a9e4f7SAdrian Hunter cp->children = RB_ROOT; 340*92a9e4f7SAdrian Hunter } 341*92a9e4f7SAdrian Hunter 342*92a9e4f7SAdrian Hunter static struct call_path_root *call_path_root__new(void) 343*92a9e4f7SAdrian Hunter { 344*92a9e4f7SAdrian Hunter struct call_path_root *cpr; 345*92a9e4f7SAdrian Hunter 346*92a9e4f7SAdrian Hunter cpr = zalloc(sizeof(struct call_path_root)); 347*92a9e4f7SAdrian Hunter if (!cpr) 348*92a9e4f7SAdrian Hunter return NULL; 349*92a9e4f7SAdrian Hunter call_path__init(&cpr->call_path, NULL, NULL, 0, false); 350*92a9e4f7SAdrian Hunter INIT_LIST_HEAD(&cpr->blocks); 351*92a9e4f7SAdrian Hunter return cpr; 352*92a9e4f7SAdrian Hunter } 353*92a9e4f7SAdrian Hunter 354*92a9e4f7SAdrian Hunter static void call_path_root__free(struct call_path_root *cpr) 355*92a9e4f7SAdrian Hunter { 356*92a9e4f7SAdrian Hunter struct call_path_block *pos, *n; 357*92a9e4f7SAdrian Hunter 358*92a9e4f7SAdrian Hunter list_for_each_entry_safe(pos, n, &cpr->blocks, node) { 359*92a9e4f7SAdrian Hunter list_del(&pos->node); 360*92a9e4f7SAdrian Hunter free(pos); 361*92a9e4f7SAdrian Hunter } 362*92a9e4f7SAdrian Hunter free(cpr); 363*92a9e4f7SAdrian Hunter } 364*92a9e4f7SAdrian Hunter 365*92a9e4f7SAdrian Hunter static struct call_path *call_path__new(struct call_path_root *cpr, 366*92a9e4f7SAdrian Hunter struct call_path *parent, 367*92a9e4f7SAdrian Hunter struct symbol *sym, u64 ip, 368*92a9e4f7SAdrian Hunter bool in_kernel) 369*92a9e4f7SAdrian Hunter { 370*92a9e4f7SAdrian Hunter struct call_path_block *cpb; 371*92a9e4f7SAdrian Hunter struct call_path *cp; 372*92a9e4f7SAdrian Hunter size_t n; 373*92a9e4f7SAdrian Hunter 374*92a9e4f7SAdrian Hunter if (cpr->next < cpr->sz) { 375*92a9e4f7SAdrian Hunter cpb = list_last_entry(&cpr->blocks, struct call_path_block, 376*92a9e4f7SAdrian Hunter node); 377*92a9e4f7SAdrian Hunter } else { 378*92a9e4f7SAdrian Hunter cpb = zalloc(sizeof(struct call_path_block)); 379*92a9e4f7SAdrian Hunter if (!cpb) 380*92a9e4f7SAdrian Hunter return NULL; 381*92a9e4f7SAdrian Hunter list_add_tail(&cpb->node, &cpr->blocks); 382*92a9e4f7SAdrian Hunter cpr->sz += CALL_PATH_BLOCK_SIZE; 383*92a9e4f7SAdrian Hunter } 384*92a9e4f7SAdrian Hunter 385*92a9e4f7SAdrian Hunter n = cpr->next++ & CALL_PATH_BLOCK_MASK; 386*92a9e4f7SAdrian Hunter cp = &cpb->cp[n]; 387*92a9e4f7SAdrian Hunter 388*92a9e4f7SAdrian Hunter call_path__init(cp, parent, sym, ip, in_kernel); 389*92a9e4f7SAdrian Hunter 390*92a9e4f7SAdrian Hunter return cp; 391*92a9e4f7SAdrian Hunter } 392*92a9e4f7SAdrian Hunter 393*92a9e4f7SAdrian Hunter static struct call_path *call_path__findnew(struct call_path_root *cpr, 394*92a9e4f7SAdrian Hunter struct call_path *parent, 395*92a9e4f7SAdrian Hunter struct symbol *sym, u64 ip, u64 ks) 396*92a9e4f7SAdrian Hunter { 397*92a9e4f7SAdrian Hunter struct rb_node **p; 398*92a9e4f7SAdrian Hunter struct rb_node *node_parent = NULL; 399*92a9e4f7SAdrian Hunter struct call_path *cp; 400*92a9e4f7SAdrian Hunter bool in_kernel = ip >= ks; 401*92a9e4f7SAdrian Hunter 402*92a9e4f7SAdrian Hunter if (sym) 403*92a9e4f7SAdrian Hunter ip = 0; 404*92a9e4f7SAdrian Hunter 405*92a9e4f7SAdrian Hunter if (!parent) 406*92a9e4f7SAdrian Hunter return call_path__new(cpr, parent, sym, ip, in_kernel); 407*92a9e4f7SAdrian Hunter 408*92a9e4f7SAdrian Hunter p = &parent->children.rb_node; 409*92a9e4f7SAdrian Hunter while (*p != NULL) { 410*92a9e4f7SAdrian Hunter node_parent = *p; 411*92a9e4f7SAdrian Hunter cp = rb_entry(node_parent, struct call_path, rb_node); 412*92a9e4f7SAdrian Hunter 413*92a9e4f7SAdrian Hunter if (cp->sym == sym && cp->ip == ip) 414*92a9e4f7SAdrian Hunter return cp; 415*92a9e4f7SAdrian Hunter 416*92a9e4f7SAdrian Hunter if (sym < cp->sym || (sym == cp->sym && ip < cp->ip)) 417*92a9e4f7SAdrian Hunter p = &(*p)->rb_left; 418*92a9e4f7SAdrian Hunter else 419*92a9e4f7SAdrian Hunter p = &(*p)->rb_right; 420*92a9e4f7SAdrian Hunter } 421*92a9e4f7SAdrian Hunter 422*92a9e4f7SAdrian Hunter cp = call_path__new(cpr, parent, sym, ip, in_kernel); 423*92a9e4f7SAdrian Hunter if (!cp) 424*92a9e4f7SAdrian Hunter return NULL; 425*92a9e4f7SAdrian Hunter 426*92a9e4f7SAdrian Hunter rb_link_node(&cp->rb_node, node_parent, p); 427*92a9e4f7SAdrian Hunter rb_insert_color(&cp->rb_node, &parent->children); 428*92a9e4f7SAdrian Hunter 429*92a9e4f7SAdrian Hunter return cp; 430*92a9e4f7SAdrian Hunter } 431*92a9e4f7SAdrian Hunter 432*92a9e4f7SAdrian Hunter struct call_return_processor * 433*92a9e4f7SAdrian Hunter call_return_processor__new(int (*process)(struct call_return *cr, void *data), 434*92a9e4f7SAdrian Hunter void *data) 435*92a9e4f7SAdrian Hunter { 436*92a9e4f7SAdrian Hunter struct call_return_processor *crp; 437*92a9e4f7SAdrian Hunter 438*92a9e4f7SAdrian Hunter crp = zalloc(sizeof(struct call_return_processor)); 439*92a9e4f7SAdrian Hunter if (!crp) 440*92a9e4f7SAdrian Hunter return NULL; 441*92a9e4f7SAdrian Hunter crp->cpr = call_path_root__new(); 442*92a9e4f7SAdrian Hunter if (!crp->cpr) 443*92a9e4f7SAdrian Hunter goto out_free; 444*92a9e4f7SAdrian Hunter crp->process = process; 445*92a9e4f7SAdrian Hunter crp->data = data; 446*92a9e4f7SAdrian Hunter return crp; 447*92a9e4f7SAdrian Hunter 448*92a9e4f7SAdrian Hunter out_free: 449*92a9e4f7SAdrian Hunter free(crp); 450*92a9e4f7SAdrian Hunter return NULL; 451*92a9e4f7SAdrian Hunter } 452*92a9e4f7SAdrian Hunter 453*92a9e4f7SAdrian Hunter void call_return_processor__free(struct call_return_processor *crp) 454*92a9e4f7SAdrian Hunter { 455*92a9e4f7SAdrian Hunter if (crp) { 456*92a9e4f7SAdrian Hunter call_path_root__free(crp->cpr); 457*92a9e4f7SAdrian Hunter free(crp); 458*92a9e4f7SAdrian Hunter } 459*92a9e4f7SAdrian Hunter } 460*92a9e4f7SAdrian Hunter 461*92a9e4f7SAdrian Hunter static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr, 462*92a9e4f7SAdrian Hunter u64 timestamp, u64 ref, struct call_path *cp, 463*92a9e4f7SAdrian Hunter bool no_call) 464*92a9e4f7SAdrian Hunter { 465*92a9e4f7SAdrian Hunter struct thread_stack_entry *tse; 466*92a9e4f7SAdrian Hunter int err; 467*92a9e4f7SAdrian Hunter 468*92a9e4f7SAdrian Hunter if (ts->cnt == ts->sz) { 469*92a9e4f7SAdrian Hunter err = thread_stack__grow(ts); 470*92a9e4f7SAdrian Hunter if (err) 471*92a9e4f7SAdrian Hunter return err; 472*92a9e4f7SAdrian Hunter } 473*92a9e4f7SAdrian Hunter 474*92a9e4f7SAdrian Hunter tse = &ts->stack[ts->cnt++]; 475*92a9e4f7SAdrian Hunter tse->ret_addr = ret_addr; 476*92a9e4f7SAdrian Hunter tse->timestamp = timestamp; 477*92a9e4f7SAdrian Hunter tse->ref = ref; 478*92a9e4f7SAdrian Hunter tse->branch_count = ts->branch_count; 479*92a9e4f7SAdrian Hunter tse->cp = cp; 480*92a9e4f7SAdrian Hunter tse->no_call = no_call; 481*92a9e4f7SAdrian Hunter 482*92a9e4f7SAdrian Hunter return 0; 483*92a9e4f7SAdrian Hunter } 484*92a9e4f7SAdrian Hunter 485*92a9e4f7SAdrian Hunter static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts, 486*92a9e4f7SAdrian Hunter u64 ret_addr, u64 timestamp, u64 ref, 487*92a9e4f7SAdrian Hunter struct symbol *sym) 488*92a9e4f7SAdrian Hunter { 489*92a9e4f7SAdrian Hunter int err; 490*92a9e4f7SAdrian Hunter 491*92a9e4f7SAdrian Hunter if (!ts->cnt) 492*92a9e4f7SAdrian Hunter return 1; 493*92a9e4f7SAdrian Hunter 494*92a9e4f7SAdrian Hunter if (ts->cnt == 1) { 495*92a9e4f7SAdrian Hunter struct thread_stack_entry *tse = &ts->stack[0]; 496*92a9e4f7SAdrian Hunter 497*92a9e4f7SAdrian Hunter if (tse->cp->sym == sym) 498*92a9e4f7SAdrian Hunter return thread_stack__call_return(thread, ts, --ts->cnt, 499*92a9e4f7SAdrian Hunter timestamp, ref, false); 500*92a9e4f7SAdrian Hunter } 501*92a9e4f7SAdrian Hunter 502*92a9e4f7SAdrian Hunter if (ts->stack[ts->cnt - 1].ret_addr == ret_addr) { 503*92a9e4f7SAdrian Hunter return thread_stack__call_return(thread, ts, --ts->cnt, 504*92a9e4f7SAdrian Hunter timestamp, ref, false); 505*92a9e4f7SAdrian Hunter } else { 506*92a9e4f7SAdrian Hunter size_t i = ts->cnt - 1; 507*92a9e4f7SAdrian Hunter 508*92a9e4f7SAdrian Hunter while (i--) { 509*92a9e4f7SAdrian Hunter if (ts->stack[i].ret_addr != ret_addr) 510*92a9e4f7SAdrian Hunter continue; 511*92a9e4f7SAdrian Hunter i += 1; 512*92a9e4f7SAdrian Hunter while (ts->cnt > i) { 513*92a9e4f7SAdrian Hunter err = thread_stack__call_return(thread, ts, 514*92a9e4f7SAdrian Hunter --ts->cnt, 515*92a9e4f7SAdrian Hunter timestamp, ref, 516*92a9e4f7SAdrian Hunter true); 517*92a9e4f7SAdrian Hunter if (err) 518*92a9e4f7SAdrian Hunter return err; 519*92a9e4f7SAdrian Hunter } 520*92a9e4f7SAdrian Hunter return thread_stack__call_return(thread, ts, --ts->cnt, 521*92a9e4f7SAdrian Hunter timestamp, ref, false); 522*92a9e4f7SAdrian Hunter } 523*92a9e4f7SAdrian Hunter } 524*92a9e4f7SAdrian Hunter 525*92a9e4f7SAdrian Hunter return 1; 526*92a9e4f7SAdrian Hunter } 527*92a9e4f7SAdrian Hunter 528*92a9e4f7SAdrian Hunter static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts, 529*92a9e4f7SAdrian Hunter struct perf_sample *sample, 530*92a9e4f7SAdrian Hunter struct addr_location *from_al, 531*92a9e4f7SAdrian Hunter struct addr_location *to_al, u64 ref) 532*92a9e4f7SAdrian Hunter { 533*92a9e4f7SAdrian Hunter struct call_path_root *cpr = ts->crp->cpr; 534*92a9e4f7SAdrian Hunter struct call_path *cp; 535*92a9e4f7SAdrian Hunter struct symbol *sym; 536*92a9e4f7SAdrian Hunter u64 ip; 537*92a9e4f7SAdrian Hunter 538*92a9e4f7SAdrian Hunter if (sample->ip) { 539*92a9e4f7SAdrian Hunter ip = sample->ip; 540*92a9e4f7SAdrian Hunter sym = from_al->sym; 541*92a9e4f7SAdrian Hunter } else if (sample->addr) { 542*92a9e4f7SAdrian Hunter ip = sample->addr; 543*92a9e4f7SAdrian Hunter sym = to_al->sym; 544*92a9e4f7SAdrian Hunter } else { 545*92a9e4f7SAdrian Hunter return 0; 546*92a9e4f7SAdrian Hunter } 547*92a9e4f7SAdrian Hunter 548*92a9e4f7SAdrian Hunter cp = call_path__findnew(cpr, &cpr->call_path, sym, ip, 549*92a9e4f7SAdrian Hunter ts->kernel_start); 550*92a9e4f7SAdrian Hunter if (!cp) 551*92a9e4f7SAdrian Hunter return -ENOMEM; 552*92a9e4f7SAdrian Hunter 553*92a9e4f7SAdrian Hunter return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp, 554*92a9e4f7SAdrian Hunter true); 555*92a9e4f7SAdrian Hunter } 556*92a9e4f7SAdrian Hunter 557*92a9e4f7SAdrian Hunter static int thread_stack__no_call_return(struct thread *thread, 558*92a9e4f7SAdrian Hunter struct thread_stack *ts, 559*92a9e4f7SAdrian Hunter struct perf_sample *sample, 560*92a9e4f7SAdrian Hunter struct addr_location *from_al, 561*92a9e4f7SAdrian Hunter struct addr_location *to_al, u64 ref) 562*92a9e4f7SAdrian Hunter { 563*92a9e4f7SAdrian Hunter struct call_path_root *cpr = ts->crp->cpr; 564*92a9e4f7SAdrian Hunter struct call_path *cp, *parent; 565*92a9e4f7SAdrian Hunter u64 ks = ts->kernel_start; 566*92a9e4f7SAdrian Hunter int err; 567*92a9e4f7SAdrian Hunter 568*92a9e4f7SAdrian Hunter if (sample->ip >= ks && sample->addr < ks) { 569*92a9e4f7SAdrian Hunter /* Return to userspace, so pop all kernel addresses */ 570*92a9e4f7SAdrian Hunter while (thread_stack__in_kernel(ts)) { 571*92a9e4f7SAdrian Hunter err = thread_stack__call_return(thread, ts, --ts->cnt, 572*92a9e4f7SAdrian Hunter sample->time, ref, 573*92a9e4f7SAdrian Hunter true); 574*92a9e4f7SAdrian Hunter if (err) 575*92a9e4f7SAdrian Hunter return err; 576*92a9e4f7SAdrian Hunter } 577*92a9e4f7SAdrian Hunter 578*92a9e4f7SAdrian Hunter /* If the stack is empty, push the userspace address */ 579*92a9e4f7SAdrian Hunter if (!ts->cnt) { 580*92a9e4f7SAdrian Hunter cp = call_path__findnew(cpr, &cpr->call_path, 581*92a9e4f7SAdrian Hunter to_al->sym, sample->addr, 582*92a9e4f7SAdrian Hunter ts->kernel_start); 583*92a9e4f7SAdrian Hunter if (!cp) 584*92a9e4f7SAdrian Hunter return -ENOMEM; 585*92a9e4f7SAdrian Hunter return thread_stack__push_cp(ts, 0, sample->time, ref, 586*92a9e4f7SAdrian Hunter cp, true); 587*92a9e4f7SAdrian Hunter } 588*92a9e4f7SAdrian Hunter } else if (thread_stack__in_kernel(ts) && sample->ip < ks) { 589*92a9e4f7SAdrian Hunter /* Return to userspace, so pop all kernel addresses */ 590*92a9e4f7SAdrian Hunter while (thread_stack__in_kernel(ts)) { 591*92a9e4f7SAdrian Hunter err = thread_stack__call_return(thread, ts, --ts->cnt, 592*92a9e4f7SAdrian Hunter sample->time, ref, 593*92a9e4f7SAdrian Hunter true); 594*92a9e4f7SAdrian Hunter if (err) 595*92a9e4f7SAdrian Hunter return err; 596*92a9e4f7SAdrian Hunter } 597*92a9e4f7SAdrian Hunter } 598*92a9e4f7SAdrian Hunter 599*92a9e4f7SAdrian Hunter if (ts->cnt) 600*92a9e4f7SAdrian Hunter parent = ts->stack[ts->cnt - 1].cp; 601*92a9e4f7SAdrian Hunter else 602*92a9e4f7SAdrian Hunter parent = &cpr->call_path; 603*92a9e4f7SAdrian Hunter 604*92a9e4f7SAdrian Hunter /* This 'return' had no 'call', so push and pop top of stack */ 605*92a9e4f7SAdrian Hunter cp = call_path__findnew(cpr, parent, from_al->sym, sample->ip, 606*92a9e4f7SAdrian Hunter ts->kernel_start); 607*92a9e4f7SAdrian Hunter if (!cp) 608*92a9e4f7SAdrian Hunter return -ENOMEM; 609*92a9e4f7SAdrian Hunter 610*92a9e4f7SAdrian Hunter err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp, 611*92a9e4f7SAdrian Hunter true); 612*92a9e4f7SAdrian Hunter if (err) 613*92a9e4f7SAdrian Hunter return err; 614*92a9e4f7SAdrian Hunter 615*92a9e4f7SAdrian Hunter return thread_stack__pop_cp(thread, ts, sample->addr, sample->time, ref, 616*92a9e4f7SAdrian Hunter to_al->sym); 617*92a9e4f7SAdrian Hunter } 618*92a9e4f7SAdrian Hunter 619*92a9e4f7SAdrian Hunter static int thread_stack__trace_begin(struct thread *thread, 620*92a9e4f7SAdrian Hunter struct thread_stack *ts, u64 timestamp, 621*92a9e4f7SAdrian Hunter u64 ref) 622*92a9e4f7SAdrian Hunter { 623*92a9e4f7SAdrian Hunter struct thread_stack_entry *tse; 624*92a9e4f7SAdrian Hunter int err; 625*92a9e4f7SAdrian Hunter 626*92a9e4f7SAdrian Hunter if (!ts->cnt) 627*92a9e4f7SAdrian Hunter return 0; 628*92a9e4f7SAdrian Hunter 629*92a9e4f7SAdrian Hunter /* Pop trace end */ 630*92a9e4f7SAdrian Hunter tse = &ts->stack[ts->cnt - 1]; 631*92a9e4f7SAdrian Hunter if (tse->cp->sym == NULL && tse->cp->ip == 0) { 632*92a9e4f7SAdrian Hunter err = thread_stack__call_return(thread, ts, --ts->cnt, 633*92a9e4f7SAdrian Hunter timestamp, ref, false); 634*92a9e4f7SAdrian Hunter if (err) 635*92a9e4f7SAdrian Hunter return err; 636*92a9e4f7SAdrian Hunter } 637*92a9e4f7SAdrian Hunter 638*92a9e4f7SAdrian Hunter return 0; 639*92a9e4f7SAdrian Hunter } 640*92a9e4f7SAdrian Hunter 641*92a9e4f7SAdrian Hunter static int thread_stack__trace_end(struct thread_stack *ts, 642*92a9e4f7SAdrian Hunter struct perf_sample *sample, u64 ref) 643*92a9e4f7SAdrian Hunter { 644*92a9e4f7SAdrian Hunter struct call_path_root *cpr = ts->crp->cpr; 645*92a9e4f7SAdrian Hunter struct call_path *cp; 646*92a9e4f7SAdrian Hunter u64 ret_addr; 647*92a9e4f7SAdrian Hunter 648*92a9e4f7SAdrian Hunter /* No point having 'trace end' on the bottom of the stack */ 649*92a9e4f7SAdrian Hunter if (!ts->cnt || (ts->cnt == 1 && ts->stack[0].ref == ref)) 650*92a9e4f7SAdrian Hunter return 0; 651*92a9e4f7SAdrian Hunter 652*92a9e4f7SAdrian Hunter cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, NULL, 0, 653*92a9e4f7SAdrian Hunter ts->kernel_start); 654*92a9e4f7SAdrian Hunter if (!cp) 655*92a9e4f7SAdrian Hunter return -ENOMEM; 656*92a9e4f7SAdrian Hunter 657*92a9e4f7SAdrian Hunter ret_addr = sample->ip + sample->insn_len; 658*92a9e4f7SAdrian Hunter 659*92a9e4f7SAdrian Hunter return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp, 660*92a9e4f7SAdrian Hunter false); 661*92a9e4f7SAdrian Hunter } 662*92a9e4f7SAdrian Hunter 663*92a9e4f7SAdrian Hunter int thread_stack__process(struct thread *thread, struct comm *comm, 664*92a9e4f7SAdrian Hunter struct perf_sample *sample, 665*92a9e4f7SAdrian Hunter struct addr_location *from_al, 666*92a9e4f7SAdrian Hunter struct addr_location *to_al, u64 ref, 667*92a9e4f7SAdrian Hunter struct call_return_processor *crp) 668*92a9e4f7SAdrian Hunter { 669*92a9e4f7SAdrian Hunter struct thread_stack *ts = thread->ts; 670*92a9e4f7SAdrian Hunter int err = 0; 671*92a9e4f7SAdrian Hunter 672*92a9e4f7SAdrian Hunter if (ts) { 673*92a9e4f7SAdrian Hunter if (!ts->crp) { 674*92a9e4f7SAdrian Hunter /* Supersede thread_stack__event() */ 675*92a9e4f7SAdrian Hunter thread_stack__free(thread); 676*92a9e4f7SAdrian Hunter thread->ts = thread_stack__new(thread, crp); 677*92a9e4f7SAdrian Hunter if (!thread->ts) 678*92a9e4f7SAdrian Hunter return -ENOMEM; 679*92a9e4f7SAdrian Hunter ts = thread->ts; 680*92a9e4f7SAdrian Hunter ts->comm = comm; 681*92a9e4f7SAdrian Hunter } 682*92a9e4f7SAdrian Hunter } else { 683*92a9e4f7SAdrian Hunter thread->ts = thread_stack__new(thread, crp); 684*92a9e4f7SAdrian Hunter if (!thread->ts) 685*92a9e4f7SAdrian Hunter return -ENOMEM; 686*92a9e4f7SAdrian Hunter ts = thread->ts; 687*92a9e4f7SAdrian Hunter ts->comm = comm; 688*92a9e4f7SAdrian Hunter } 689*92a9e4f7SAdrian Hunter 690*92a9e4f7SAdrian Hunter /* Flush stack on exec */ 691*92a9e4f7SAdrian Hunter if (ts->comm != comm && thread->pid_ == thread->tid) { 692*92a9e4f7SAdrian Hunter err = thread_stack__flush(thread, ts); 693*92a9e4f7SAdrian Hunter if (err) 694*92a9e4f7SAdrian Hunter return err; 695*92a9e4f7SAdrian Hunter ts->comm = comm; 696*92a9e4f7SAdrian Hunter } 697*92a9e4f7SAdrian Hunter 698*92a9e4f7SAdrian Hunter /* If the stack is empty, put the current symbol on the stack */ 699*92a9e4f7SAdrian Hunter if (!ts->cnt) { 700*92a9e4f7SAdrian Hunter err = thread_stack__bottom(thread, ts, sample, from_al, to_al, 701*92a9e4f7SAdrian Hunter ref); 702*92a9e4f7SAdrian Hunter if (err) 703*92a9e4f7SAdrian Hunter return err; 704*92a9e4f7SAdrian Hunter } 705*92a9e4f7SAdrian Hunter 706*92a9e4f7SAdrian Hunter ts->branch_count += 1; 707*92a9e4f7SAdrian Hunter ts->last_time = sample->time; 708*92a9e4f7SAdrian Hunter 709*92a9e4f7SAdrian Hunter if (sample->flags & PERF_IP_FLAG_CALL) { 710*92a9e4f7SAdrian Hunter struct call_path_root *cpr = ts->crp->cpr; 711*92a9e4f7SAdrian Hunter struct call_path *cp; 712*92a9e4f7SAdrian Hunter u64 ret_addr; 713*92a9e4f7SAdrian Hunter 714*92a9e4f7SAdrian Hunter if (!sample->ip || !sample->addr) 715*92a9e4f7SAdrian Hunter return 0; 716*92a9e4f7SAdrian Hunter 717*92a9e4f7SAdrian Hunter ret_addr = sample->ip + sample->insn_len; 718*92a9e4f7SAdrian Hunter if (ret_addr == sample->addr) 719*92a9e4f7SAdrian Hunter return 0; /* Zero-length calls are excluded */ 720*92a9e4f7SAdrian Hunter 721*92a9e4f7SAdrian Hunter cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, 722*92a9e4f7SAdrian Hunter to_al->sym, sample->addr, 723*92a9e4f7SAdrian Hunter ts->kernel_start); 724*92a9e4f7SAdrian Hunter if (!cp) 725*92a9e4f7SAdrian Hunter return -ENOMEM; 726*92a9e4f7SAdrian Hunter err = thread_stack__push_cp(ts, ret_addr, sample->time, ref, 727*92a9e4f7SAdrian Hunter cp, false); 728*92a9e4f7SAdrian Hunter } else if (sample->flags & PERF_IP_FLAG_RETURN) { 729*92a9e4f7SAdrian Hunter if (!sample->ip || !sample->addr) 730*92a9e4f7SAdrian Hunter return 0; 731*92a9e4f7SAdrian Hunter 732*92a9e4f7SAdrian Hunter err = thread_stack__pop_cp(thread, ts, sample->addr, 733*92a9e4f7SAdrian Hunter sample->time, ref, from_al->sym); 734*92a9e4f7SAdrian Hunter if (err) { 735*92a9e4f7SAdrian Hunter if (err < 0) 736*92a9e4f7SAdrian Hunter return err; 737*92a9e4f7SAdrian Hunter err = thread_stack__no_call_return(thread, ts, sample, 738*92a9e4f7SAdrian Hunter from_al, to_al, ref); 739*92a9e4f7SAdrian Hunter } 740*92a9e4f7SAdrian Hunter } else if (sample->flags & PERF_IP_FLAG_TRACE_BEGIN) { 741*92a9e4f7SAdrian Hunter err = thread_stack__trace_begin(thread, ts, sample->time, ref); 742*92a9e4f7SAdrian Hunter } else if (sample->flags & PERF_IP_FLAG_TRACE_END) { 743*92a9e4f7SAdrian Hunter err = thread_stack__trace_end(ts, sample, ref); 744*92a9e4f7SAdrian Hunter } 745*92a9e4f7SAdrian Hunter 746*92a9e4f7SAdrian Hunter return err; 747*92a9e4f7SAdrian Hunter } 748