package debug_trace import "base:intrinsics" import "base:runtime" Frame :: distinct uintptr Frame_Location :: struct { using loc: runtime.Source_Code_Location, allocator: runtime.Allocator, } delete_frame_location :: proc(fl: Frame_Location) -> runtime.Allocator_Error { allocator := fl.allocator delete(fl.loc.procedure, allocator) or_return delete(fl.loc.file_path, allocator) or_return return nil } Context :: struct { in_resolve: bool, // atomic impl: _Context, } init :: proc(ctx: ^Context) -> bool { return _init(ctx) } destroy :: proc(ctx: ^Context) -> bool { return _destroy(ctx) } @(require_results) frames :: proc(ctx: ^Context, skip: uint, frames_buffer: []Frame) -> []Frame { return _frames(ctx, skip, frames_buffer) } @(require_results) resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> (result: Frame_Location) { return _resolve(ctx, frame, allocator) } @(require_results) in_resolve :: proc "contextless" (ctx: ^Context) -> bool { return intrinsics.atomic_load(&ctx.in_resolve) } _format_hex :: proc(buf: []byte, val: uintptr, allocator: runtime.Allocator) -> int { _digits := "0123456789abcdef" shift := (size_of(uintptr) * 8) - 4 offs := 0 for shift >= 0 { d := (val >> uint(shift)) & 0xf buf[offs] = _digits[d] shift -= 4 offs += 1 } return offs } _format_missing_proc :: proc(addr: uintptr, allocator: runtime.Allocator) -> string { PREFIX :: "proc:0x" buf, buf_err := make([]byte, len(PREFIX) + 16, allocator) copy(buf, PREFIX) if buf_err != nil { return "OUT_OF_MEMORY" } offs := len(PREFIX) offs += _format_hex(buf[offs:], uintptr(addr), allocator) return string(buf[:offs]) }