Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | /* SPDX-License-Identifier: GPL-2.0+ */ /* * Backtrace support * * Copyright 2025 Canonical Ltd * Written by Simon Glass <simon.glass@canonical.com> */ #ifndef __BACKTRACE_H #define __BACKTRACE_H /* Maximum number of stack frames that can be collected */ #define BACKTRACE_MAX_FRAMES 100 /* Size of buffer for all symbol strings combined */ #define BACKTRACE_SYM_BUFSZ (4 * 1024) /** * struct backtrace_frame - a single stack frame in a backtrace * * @addr: return address for this frame * @sym: pointer to symbol string in backtrace_ctx->sym_buf, or NULL if not * yet resolved or if sym_buf ran out of space */ struct backtrace_frame { void *addr; char *sym; }; /** * struct backtrace_ctx - context for backtrace operations * * This structure holds all state for collecting and symbolising a backtrace. * It should be declared static to avoid consuming stack space (~5KB). * * Lifecycle: * 1. Call backtrace_init() - fills @frame[].addr with return addresses and * sets @count. The @frame[].sym pointers are initialised to NULL. * 2. Call backtrace_get_syms() - resolves addresses to symbol strings, * writing them into @sym_buf and setting @frame[].sym pointers. * 3. Access @frame[0..count-1] to read addresses and symbol strings. * 4. Call backtrace_uninit() to release resources (currently a no-op). * * @frame: array of stack frames * @count: number of valid entries in @frame * @sym_buf: buffer holding NUL-terminated symbol strings packed consecutively */ struct backtrace_ctx { struct backtrace_frame frame[BACKTRACE_MAX_FRAMES]; unsigned int count; char sym_buf[BACKTRACE_SYM_BUFSZ]; }; /** * backtrace_init() - collect a backtrace * * Collect backtrace addresses into the context. Call backtrace_uninit() when * done with the context. * * @ctx: context to fill * @skip: number of stack frames to skip (0 to include backtrace_init itself) * Return: number of addresses collected, or -ve on error (e.g. -ENOSYS) */ int backtrace_init(struct backtrace_ctx *ctx, unsigned int skip); /** * backtrace_get_syms() - get symbol strings for a backtrace * * Convert the addresses in the context to symbol strings. The strings are * stored in ctx->syms[]. The caller must provide a buffer of sufficient size. * * @ctx: context with addresses from backtrace_init() * @buf: buffer to use for string storage * @size: size of buffer in bytes * Return: 0 if OK, -ENOSPC if buffer too small */ int backtrace_get_syms(struct backtrace_ctx *ctx, char *buf, int size); /** * backtrace_uninit() - free backtrace resources * * Free any memory allocated in the context. * * @ctx: context to free */ void backtrace_uninit(struct backtrace_ctx *ctx); /** * backtrace_show() - print a backtrace * * Print a backtrace of the current call stack. * * Return: 0 if OK, -ve on error */ int backtrace_show(void); /** * backtrace_strf() - get a condensed backtrace string into a buffer * * Return a string containing the last CONFIG_BACKTRACE_SUMMARY_FRAMES function names * and line number, separated by ``<-``. * * For example: ``func_a:12 <-func_b:34 <-func_c:56`` * * @skip: number of stack frames to skip (0 to include backtrace_strf itself) * @buf: buffer to write the string to * @size: size of buffer * Return: pointer to buf, or NULL on error */ char *backtrace_strf(unsigned int skip, char *buf, int size); /** * backtrace_str() - get a condensed backtrace string * * Return a string containing the last CONFIG_BACKTRACE_SUMMARY_FRAMES function names * and line number, separated by ``<-``. The string is statically allocated and * will be overwritten on the next call. * * For example: ``func_a:12 <-func_b:34 <-func_c:56`` * * @skip: number of stack frames to skip (0 to include backtrace_str itself) * Return: pointer to static string, or NULL on error */ #if CONFIG_IS_ENABLED(BACKTRACE) const char *backtrace_str(unsigned int skip); #else static inline const char *backtrace_str(unsigned int skip) { return NULL; } #endif #endif /* __BACKTRACE_H */ |