Files
u-boot/include/backtrace.h
Simon Glass 0cf38dc8c8 backtrace: Add backtrace_str() for condensed backtrace output
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>
2025-12-10 05:53:03 -07:00

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 */