package core:debug/trace
Overview
Captures and resolves stack traces for debugging purpose.
Debug info based support is implemented for Windows, MacOS, and Linux.
Other targets can use the instrumentation based mode, which uses Odin's instrumentation
features to trace, with some runtime overhead.
Opt in with -define:ODIN_TRACE_INSTRUMENTATION_MODE=true.
Example:
package main
import "core:debug/trace"
import "core:fmt"
main :: proc() {
track: trace.Tracking_Allocator
trace.tracking_allocator_init(&track, context.allocator)
defer trace.tracking_allocator_destroy(&track)
context.allocator = trace.tracking_allocator(&track)
defer trace.tracking_allocator_print_results(&track)
context.assertion_failure_proc = trace.assertion_failure_proc
_main()
}
_main :: proc() {
// Uncomment to try tracking allocator.
// for _ in 0..<5 {
// _ = new(int)
// free(rawptr(uintptr(100)))
// }
// Uncomment to try assertion failure handling.
// assert(false)
capture := trace.capture()
locations, err := trace.resolve(capture)
if err != nil {
fmt.eprintfln("trace error: %v", err)
return
}
defer trace.locations_destroy(locations)
trace.print(locations)
}
Index
Variables (0)
This section is empty.
Procedures (17)
- assertion_failure_proc
- capture
- capture_fill
- capture_n
- locations_destroy
- resolve_const
- resolve_n
- tracking_allocator
- tracking_allocator_bad_free_callback_add_to_array
- tracking_allocator_bad_free_callback_panic
- tracking_allocator_clear
- tracking_allocator_destroy
- tracking_allocator_init
- tracking_allocator_print_results
- tracking_allocator_proc
- tracking_allocator_reset
Procedure Groups (1)
`#config` values (4)
Types
Capture ¶
Capture :: []Capture_Entry
Related Procedures With Parameters
- capture_fill
- resolve_n
- resolve (procedure groups)
Related Procedures With Returns
Capture_Const ¶
Capture_Const :: struct { trace: [16]Capture_Entry, len: int, }
Related Procedures With Parameters
Related Procedures With Returns
Resolve_Error ¶
Resolve_Error :: enum int { None, Allocator_Error, Parse_Address_Failed, Resolve_Aborted, }
Related Procedures With Returns
- resolve_const
- resolve_n
- resolve (procedure groups)
Tracking_Allocator ¶
Tracking_Allocator :: struct { backing: runtime.Allocator, allocation_map: map[rawptr]Tracking_Allocator_Entry, bad_free_callback: Tracking_Allocator_Bad_Free_Callback, bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry, mutex: sync.Mutex, clear_on_free_all: bool, total_memory_allocated: i64, total_allocation_count: i64, total_memory_freed: i64, total_free_count: i64, peak_memory_allocated: i64, current_memory_allocated: i64, }
The backtrace tracking allocator is a similar allocator as the core:mem tracking allocator but keeps
backtraces for each allocation.
Print results at the end using tracking_allocator_print_results.
Example:
package main
import "core:debug/trace"
main :: proc() {
track: trace.Tracking_Allocator
trace.tracking_allocator_init(&track, context.allocator)
defer trace.tracking_allocator_destroy(&track)
context.allocator = trace.tracking_allocator(&track)
defer trace.tracking_allocator_print_results(&track)
_main()
}
_main :: proc() {
for _ in 0..<5 {
_ = new(int)
free(rawptr(uintptr(100)))
}
}
Tracking_Allocator_Bad_Free_Callback ¶
Tracking_Allocator_Bad_Free_Callback :: proc(t: ^Tracking_Allocator, memory: rawptr, backtrace: Capture_Const, location: runtime.Source_Code_Location)
Callback type for when tracking allocator runs into a bad free.
Tracking_Allocator_Bad_Free_Entry ¶
Tracking_Allocator_Bad_Free_Entry :: struct { memory: rawptr, location: runtime.Source_Code_Location, backtrace: Capture_Const, }
Tracking_Allocator_Entry ¶
Tracking_Allocator_Entry :: struct { memory: rawptr, size: int, alignment: int, mode: runtime.Allocator_Mode, err: runtime.Allocator_Error, location: runtime.Source_Code_Location, backtrace: Capture_Const, }
Constants
BACKTRACE_SIZE ¶
BACKTRACE_SIZE :: #config(ODIN_TRACE_SIZE, 16)
Size of a constant backtrace, as used by the tracking allocator for example.
CUSTOM_INSTRUMENTATION ¶
CUSTOM_INSTRUMENTATION :: #config(ODIN_TRACE_CUSTOM_INSTRUMENTATION, false)
When using the instrumentation mode, but you also want to use Odin's instrumentation features
for something else. You can define this, and call this package's instrumentation procedures:
instrumentation_enter, and instrumentation_exit, in your own instrumentation enter/exit procedures.
INSTRUMENTATION_MODE ¶
INSTRUMENTATION_MODE :: #config(ODIN_TRACE_INSTRUMENTATION_MODE, false)
Use the instrumentation based trace mode, instead of debug info based. This mode has a little bit of runtime performance impact, but is supported on all targets.
OOM_MARKER ¶
OOM_MARKER :: "??OOM"
The string that is used when allocation failed for a symbol/file path.
SYMBOLIZER_PROGRAM ¶
SYMBOLIZER_PROGRAM :: #config(ODIN_TRACE_SYMBOLIZER_PROGRAM, "addr2line")
The path/command to invoke for symbolization. Linux only.
Variables
This section is empty.
Procedures
assertion_failure_proc ¶
assertion_failure_proc :: proc(prefix, message: string, loc: runtime.Source_Code_Location) -> ! {…}
An assertion failure procedure that prints a back trace.
Example:
context.assertion_failure_proc = trace.assertion_failure_proc
assert(false)
capture ¶
capture :: proc(skip: int = 0) -> (bt: Capture_Const) {…}
Capture a constantly sized trace (defined by -define:ODIN_TRACE_SIZE).
The trace starts at the stack frame that called this procedure,
you can start higher up the stack using the skip argument.
capture_fill ¶
capture_fill :: proc(buf: []Capture_Entry, skip: int = 0) -> int {…}
Capture a trace into the given preallocated capture buffer (owned by the caller).
The trace starts at the stack frame that called this procedure,
you can start higher up the stack using the skip argument.
capture_n ¶
capture_n :: proc(max_len: i32, skip: int = 0, allocator := context.allocator) -> []Capture_Entry {…}
Capture a trace of the given size.
The trace starts at the stack frame that called this procedure,
you can start higher up the stack using the skip argument.
The capture must be deleted by the caller.
locations_destroy ¶
locations_destroy :: proc(locations: []runtime.Source_Code_Location, allocator := context.allocator) {…}
print ¶
print :: proc(locations: []runtime.Source_Code_Location, padding: string = "\t") {…}
Print locations to stderr.
Inputs:
locations: the result of a resolve call.
padding: padding to print before each line, defaults to a tab.
resolve_const ¶
resolve_const :: proc(bt: Capture_Const, allocator := context.allocator, temp_allocator := context.temp_allocator) -> (out: []runtime.Source_Code_Location, err: Resolve_Error) {…}
See the procedure group resolve.
Related Procedure Groups
resolve_n ¶
resolve_n :: proc(bt: []Capture_Entry, allocator := context.allocator, temp_allocator := context.temp_allocator) -> (out: []runtime.Source_Code_Location, err: Resolve_Error) {…}
See the procedure group resolve.
Related Procedure Groups
tracking_allocator ¶
tracking_allocator :: proc(data: ^Tracking_Allocator) -> runtime.Allocator {…}
tracking_allocator_bad_free_callback_add_to_array ¶
tracking_allocator_bad_free_callback_add_to_array :: proc(t: ^Tracking_Allocator, memory: rawptr, backtrace: Capture_Const, location: runtime.Source_Code_Location) {…}
tracking_allocator_bad_free_callback_panic ¶
tracking_allocator_bad_free_callback_panic :: proc(t: ^Tracking_Allocator, memory: rawptr, backtrace: Capture_Const, location: runtime.Source_Code_Location) {…}
tracking_allocator_clear ¶
tracking_allocator_clear :: proc(t: ^Tracking_Allocator) {…}
tracking_allocator_destroy ¶
tracking_allocator_destroy :: proc(t: ^Tracking_Allocator) {…}
tracking_allocator_init ¶
tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: runtime.Allocator, internals_allocator := context.allocator) {…}
tracking_allocator_print_results ¶
tracking_allocator_print_results :: proc(t: ^Tracking_Allocator, temp_allocator := context.temp_allocator) {…}
tracking_allocator_proc ¶
tracking_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> (result: []u8, err: runtime.Allocator_Error) {…}
tracking_allocator_reset ¶
tracking_allocator_reset :: proc(t: ^Tracking_Allocator) {…}
Procedure Groups
resolve ¶
resolve :: proc{ resolve_n, resolve_const, }
Resolve the back trace into source code locations, if possible.
Compile with -debug (or use -define:ODIN_TRACE_INSTRUMENTATION_MODE) for the most useful information.
The result must be destroyed using locations_destroy.
`#config` values
BACKTRACE_SIZE ¶
BACKTRACE_SIZE :: #config(ODIN_TRACE_SIZE, 16)
Size of a constant backtrace, as used by the tracking allocator for example.
CUSTOM_INSTRUMENTATION ¶
CUSTOM_INSTRUMENTATION :: #config(ODIN_TRACE_CUSTOM_INSTRUMENTATION, false)
When using the instrumentation mode, but you also want to use Odin's instrumentation features
for something else. You can define this, and call this package's instrumentation procedures:
instrumentation_enter, and instrumentation_exit, in your own instrumentation enter/exit procedures.
INSTRUMENTATION_MODE ¶
INSTRUMENTATION_MODE :: #config(ODIN_TRACE_INSTRUMENTATION_MODE, false)
Use the instrumentation based trace mode, instead of debug info based. This mode has a little bit of runtime performance impact, but is supported on all targets.
SYMBOLIZER_PROGRAM ¶
SYMBOLIZER_PROGRAM :: #config(ODIN_TRACE_SYMBOLIZER_PROGRAM, "addr2line")
The path/command to invoke for symbolization. Linux only.
Source Files
- allocator.odin
- doc.odin
- trace.odin
- trace_instrumentation.odin
- (hidden platform specific files)
Generation Information
Generated with odin version dev-2026-08 (vendor "odin") Windows_amd64 @ 2026-08-08 21:20:10.986589400 +0000 UTC