Add a new function backtrace_str() that returns a condensed backtrace string containing function names and line numbers separated by " <-". For example: "func_a:123 <-func_b:456 <-func_c:789" This is useful for logging and debugging where a compact representation of the call stack is needed. The depth is controlled by the new CONFIG_BACKTRACE_DEPTH option (default 3). Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
134 lines
4.0 KiB
C
134 lines
4.0 KiB
C
/* 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 */
|