BACKTRACE(9) | Kernel Developer's Manual | BACKTRACE(9) |
backtrace
,
backtrace_packed
,
backtrace_user
, — gather the
PC and return addresses of a thread's kernel or user call stack
#include
<kern/backtrace.h>
unsigned int
backtrace
(uintptr_t *bt,
unsigned int btlen, struct
backtrace_control *ctl, backtrace_info_t
*info_out);
size_t
backtrace_packed
(backtrace_pack_t
packing, uintptr_t *bt, size_t
btlen, struct backtrace_control *ctl,
backtrace_info_t *info_out);
unsigned int
backtrace_user
(uintptr_t *bt,
unsigned int btlen, struct
backtrace_control *ctl, struct backtrace_user_info
*info_out);
The backtrace
,
backtrace_packed
, and
backtrace_user
functions fill a buffer with the
current PC and return addresses of a thread's kernel and user call stack,
respectively. This is only possible when frame pointers are pushed to the
stack, alongside the return addresses.
clang(1), disables this behavior with
the -fomit-frame-pointer
flag, so it will prevent
these functions from working. Furthermore, leaf functions and inlined
function calls can also prevent backtracing from reporting the source-level
function control flow.
backtrace_user
()
operates on user call stacks, while backtrace
()
captures the current kernel call stack.
backtrace_packed
() writes a more compact
representation of the return addresses to a buffer, which can be unpacked
with backtrace_unpack(9).
Calling backtrace_user
() on a kernel thread (which
lacks a user context) is undefined.
Up to btlen
instruction addresses (or btsize bytes for
backtrace_packed
())
are written to the buffer at bt. These functions also
accept ctl and info_out
arguments, described in
BACKTRACE_CONTROL and
BACKTRACE_INFO, respectively.
backtrace_packed
() takes a
backtrace_pack_t to control which packing scheme to
use.
backtrace
()
records the kernel PC and call stack of the current thread.
backtrace_packed
()
records the kernel PC and call stack of the current thread in a buffer in a
compact representation. See
backtrace_pack(9) for a
description of the supported formats.
backtrace_user
()
records the user PC and call stack of the current thread, which must be
associated with a user space task.
The backtrace
functions return the number
of PC and return address elements (or bytes for
backtrace_packed
()) written to the provided buffer.
If there is space, the buffer is terminated with a NULL entry (except for
backtrace_packed
()). The
info_out argument will be set with information about
the provided call stack. backtrace_user
() will set
btui_error to an error of the
copyin(9) routine if an error occurred
during call stack traversal.
The backtrace
functions accept a
struct backtrace_control control argument to alter
their behavior, with the following fields:
BTF_KERN_INTERRUPTED
backtrace
() only, record the PC and return
addresses of the interrupted call stack.backtrace_user
() only, the function to use
instead of copyin(9) to copy data
from the thread's user space virtual address space into the kernel.The backtrace
functions report additional
information through a backtrace_info_t flags
out-parameter, with the following options:
BTI_64_BIT
BTI_TRUNCATED
The
backtrace_user
()
variant uses an out-parameter structure struct
backtrace_user_info to return additional context:
backtrace_user
() (as the control
structure's frame address field) to follow the corresponding async
stack.uintptr_t bt[8] = {}; enum backtrace_info bti = BTI_NONE; unsigned int len = backtrace(bt, sizeof(bt) / sizeof(bt[0]), NULL, &bti); for (unsigned int i = 0; i < len; i++) { printf("%d: 0x%lx\n", i, bt[i]); } if (bti & BTI_TRUNCATED) { printf("[... TRUNCATED ...]\n"); }
June 30, 2021 | Darwin |