package core:debug/trace

⌘K
Ctrl+K
or
/

    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)
    }
    

    Types

    Capture ¶

    Capture :: []Capture_Entry
    Related Procedures With Parameters
    Related Procedures With Returns

    Capture_Const ¶

    Capture_Const :: struct {
    	trace: [16]Capture_Entry,
    	len:   int,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Capture_Entry ¶

    Capture_Entry :: distinct uintptr
     

    Platform specific.

    Resolve_Error ¶

    Resolve_Error :: enum int {
    	None, 
    	Allocator_Error, 
    	Parse_Address_Failed, 
    	Resolve_Aborted, 
    }
    Related Procedures With Returns

    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)))
    	}
    }
    
    Related Procedures With Parameters

    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

    Generation Information

    Generated with odin version dev-2026-08 (vendor "odin") Windows_amd64 @ 2026-08-08 21:20:10.986589400 +0000 UTC