StackFrame
Description
A single captured stack frame. Just the IP – symbol resolution happens later in FormatStackTrace.
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Debug.h:82:
size padded_size;
u32 alloc_trace_n;
StackFrame alloc_trace[DEBUG_ALLOCATOR_MAX_TRACE];
} DebugRecord;- In
Debug.h:98:
u32 alloc_trace_n;
u32 free_trace_n;
StackFrame alloc_trace[DEBUG_ALLOCATOR_MAX_TRACE];
StackFrame free_trace[DEBUG_ALLOCATOR_MAX_TRACE];
} DebugFreedEntry;- In
Debug.h:99:
u32 free_trace_n;
StackFrame alloc_trace[DEBUG_ALLOCATOR_MAX_TRACE];
StackFrame free_trace[DEBUG_ALLOCATOR_MAX_TRACE];
} DebugFreedEntry;- In
Backtrace.h:68:
typedef struct StackFrame {
void *ip;
} StackFrame;
///
- In
Backtrace.h:76:
/// TAGS: Backtrace, Type, Frame
///
typedef Vec(StackFrame) StackFrames;
// ---------------------------------------------------------------------------
- In
Backtrace.h:98:
/// TAGS: Backtrace, Capture, Trace, Stack
///
size capture_stack_trace_raw(StackFrame *out, size max_frames, size skip_frames);
///
- In
Backtrace.h:125:
/// TAGS: Backtrace, Capture, Trace, CFI, Stack
///
size capture_stack_trace_cfi_raw(StackFrame *out, size max_frames, size skip_frames, SymbolResolver *resolver);
bool capture_stack_trace_cfi_vec(StackFrames *out, size skip_frames, SymbolResolver *resolver);
#endif- In
Backtrace.h:141:
/// TAGS: Backtrace, Format, Trace, Stack
///
void format_stack_trace_raw(Str *out, const StackFrame *frames, size count, Allocator *alloc);
///
- In
Backtrace.h:168:
/// TAGS: Backtrace, Format, Trace, Symbol, Stack
///
void format_stack_trace_with_raw(Str *out, const StackFrame *frames, size count, SymbolResolver *resolver);
void format_stack_trace_with_vec(Str *out, const StackFrames *frames, SymbolResolver *resolver);
#endif- In
Log.c:65:
// call site context up to Abort(). Skip our own + LogWrite's
// frame (1 frame).
StackFrame frames[32];
size n = CaptureStackTrace(frames, 32, 1);
Str trace = StrInit(&h);- In
Debug.c:278:
}
static void debug_emit_trace(const StackFrame *frames, size count, Zstr label, Allocator *meta) {
if (!count) {
LOG_ERROR(" {} trace: (none captured)", label);- In
Debug.c:365:
entry.requested_size = live_rec->requested_size;
entry.alloc_trace_n = live_rec->alloc_trace_n;
MemCopy(entry.alloc_trace, live_rec->alloc_trace, (size)live_rec->alloc_trace_n * sizeof(StackFrame));
entry.free_trace_n = 0;
if (self->config.capture_traces && self->config.trace_depth > 0) {- In
Backtrace.c:41:
typedef struct RawSinkCtx {
StackFrame *out;
size max;
size n;- In
Backtrace.c:61:
static bool vec_sink(void *user, void *ip) {
VecSinkCtx *s = (VecSinkCtx *)user;
StackFrame f = {.ip = ip};
if (!VecPushBackR(s->vec, f)) {
s->oom = true;- In
Backtrace.c:175:
}
size capture_stack_trace_raw(StackFrame *out, size max_frames, size skip_frames) {
if (!out || max_frames == 0)
return 0;- In
Backtrace.c:192:
// Shared formatter body (raw view: pointer + length).
static void format_walk_win(Str *out, const StackFrame *frames, size count, Allocator *alloc) {
ensure_dbghelp();
HANDLE proc = GetCurrentProcess();- In
Backtrace.c:265:
}
void format_stack_trace_raw(Str *out, const StackFrame *frames, size count, Allocator *alloc) {
if (!out || !frames)
return;- In
Backtrace.c:341:
# endif
size capture_stack_trace_raw(StackFrame *out, size max_frames, size skip_frames) {
if (!out || max_frames == 0)
return 0;- In
Backtrace.c:386:
# endif
static void format_walk_mac(Str *out, const StackFrame *frames, size count, Allocator *alloc) {
# if FEATURE_PARSER_MACHO
bool cache_ok = (alloc != NULL);- In
Backtrace.c:427:
}
void format_stack_trace_raw(Str *out, const StackFrame *frames, size count, Allocator *alloc) {
if (!out || !frames || !alloc)
return;- In
Backtrace.c:445:
#elif defined(__GNUC__) || defined(__clang__)
size capture_stack_trace_raw(StackFrame *out, size max_frames, size skip_frames) {
if (!out || max_frames == 0)
return 0;- In
Backtrace.c:482:
}
static void format_walk_with(Str *out, const StackFrame *frames, size count, SymbolResolver *resolver) {
for (size i = 0; i < count; ++i) {
ResolvedSymbol r;- In
Backtrace.c:493:
}
static void format_walk_alloc(Str *out, const StackFrame *frames, size count, Allocator *alloc) {
SymbolResolver res;
if (!SymbolResolverInit(&res, alloc)) {- In
Backtrace.c:505:
}
void format_stack_trace_with_raw(Str *out, const StackFrame *frames, size count, SymbolResolver *resolver) {
if (!out || !frames || !resolver)
return;- In
Backtrace.c:517:
}
void format_stack_trace_raw(Str *out, const StackFrame *frames, size count, Allocator *alloc) {
if (!out || !frames || !alloc)
return;- In
Backtrace.c:653:
}
size capture_stack_trace_cfi_raw(StackFrame *out, size max_frames, size skip_frames, SymbolResolver *resolver) {
if (!out || max_frames == 0 || !resolver)
return 0;- In
Backtrace.c:673:
// in v1). aarch64 follows a very similar pattern and is in
// FUTURE-PLANS.
size capture_stack_trace_cfi_raw(StackFrame *out, size max_frames, size skip_frames, SymbolResolver *resolver) {
(void)out;
(void)max_frames;- In
AllocDebug.c:401:
DebugRecord *rec = MapGetFirstPtr(&dbg.live, p);
u32 n = ok ? rec->alloc_trace_n : 0;
StackFrame snapshot[DEBUG_ALLOCATOR_MAX_TRACE];
ok = ok && (n > 0);
if (ok)- In
AllocDebug.c:404:
ok = ok && (n > 0);
if (ok)
MemCopy(snapshot, rec->alloc_trace, (size)n * sizeof(StackFrame));
AllocatorFree(adbg, p);- In
Backtrace.c:14:
// Named helpers so we can verify a specific symbol shows up in the
// captured trace.
static __attribute__((noinline)) size bt_capture_with_helper(StackFrame *frames, size max) {
return CaptureStackTrace(frames, max, 0);
}- In
Backtrace.c:18:
}
static __attribute__((noinline)) size bt_capture_outer(StackFrame *frames, size max) {
return bt_capture_with_helper(frames, max);
}- In
Backtrace.c:23:
bool test_backtrace_capture_non_empty(void) {
StackFrame frames[32];
size n = bt_capture_outer(frames, 32);
return n >= 2 && n <= 32; // at least helper + outer
- In
Backtrace.c:32:
Allocator *alloc_base = ALLOCATOR_OF(&alloc);
StackFrame frames[32];
size n = bt_capture_outer(frames, 32);- In
Backtrace.c:104:
}
StackFrame frames[16];
size n = bt_capture_outer(frames, 16);- In
Backtrace.c:126:
// here we still get FP frames (test build flag), but the unwinder is
// driven by .eh_frame rules in either case.
static __attribute__((noinline)) size cfi_capture_inner(SymbolResolver *r, StackFrame *frames, size max) {
return CaptureStackTraceCfi(frames, max, 0, r);
}- In
Backtrace.c:130:
}
static __attribute__((noinline)) size cfi_capture_outer(SymbolResolver *r, StackFrame *frames, size max) {
return cfi_capture_inner(r, frames, max);
}- In
Backtrace.c:144:
}
StackFrame frames[32];
size n = cfi_capture_outer(&res, frames, 32);- In
Backtrace.c:169:
// snapshots at a slightly different PC inside its respective capture
// function.
static __attribute__((noinline)) size fp_capture_inner(StackFrame *frames, size max) {
return CaptureStackTrace(frames, max, 0);
}- In
Backtrace.c:175:
static __attribute__((noinline)) void cfi_vs_fp_inner(
SymbolResolver *r,
StackFrame *fp_frames,
size *fp_n,
StackFrame *cfi_frames,- In
Backtrace.c:177:
StackFrame *fp_frames,
size *fp_n,
StackFrame *cfi_frames,
size *cfi_n,
size max- In
Backtrace.c:195:
}
StackFrame fp[32], cfi[32];
size fp_n = 0, cfi_n = 0;
cfi_vs_fp_inner(&res, fp, &fp_n, cfi, &cfi_n, 32);
Last updated on