1 /* 2 * Copyright (c) 2023 KNS Group LLC (YADRO) 3 * Copyright (c) 2020 Yonatan Goldschmidt <yon.goldschmidt@gmail.com> 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 #include <zephyr/kernel.h> 9 #include <zephyr/linker/linker-defs.h> 10 valid_stack(uintptr_t addr,k_tid_t current)11static bool valid_stack(uintptr_t addr, k_tid_t current) 12 { 13 return current->stack_info.start <= addr && 14 addr < current->stack_info.start + current->stack_info.size; 15 } 16 in_text_region(uintptr_t addr)17static inline bool in_text_region(uintptr_t addr) 18 { 19 return (addr >= (uintptr_t)__text_region_start) && (addr < (uintptr_t)__text_region_end); 20 } 21 22 /* 23 * This function use frame pointers to unwind stack and get trace of return addresses. 24 * Return addresses are translated in corresponding function's names using .elf file. 25 * So we get function call trace 26 */ arch_perf_current_stack_trace(uintptr_t * buf,size_t size)27size_t arch_perf_current_stack_trace(uintptr_t *buf, size_t size) 28 { 29 if (size < 1U) { 30 return 0; 31 } 32 33 size_t idx = 0; 34 35 /* 36 * In x86_64 (arch/x86/core/intel64/locore.S) %rip and %rbp 37 * are always saved in _current->callee_saved before calling 38 * handler function if interrupt is not nested 39 * 40 * %rip points the location where interrupt was occurred 41 */ 42 buf[idx++] = (uintptr_t)_current->callee_saved.rip; 43 void **fp = (void **)_current->callee_saved.rbp; 44 45 /* 46 * %rbp is frame pointer. 47 * 48 * stack frame in memory: 49 * (addresses growth up) 50 * .... 51 * ra 52 * %rbp (next) <- %rbp (curr) 53 * .... 54 */ 55 while (valid_stack((uintptr_t)fp, _current)) { 56 if (idx >= size) { 57 return 0; 58 } 59 60 if (!in_text_region((uintptr_t)fp[1])) { 61 break; 62 } 63 64 buf[idx++] = (uintptr_t)fp[1]; 65 void **new_fp = (void **)fp[0]; 66 67 /* 68 * anti-infinity-loop if 69 * new_fp can't be smaller than fp, cause the stack is growing down 70 * and trace moves deeper into the stack 71 */ 72 if (new_fp <= fp) { 73 break; 74 } 75 fp = new_fp; 76 } 77 78 return idx; 79 } 80