From 950fd2d5ce8d4019c1884eb98fd9dbbb16049efc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 28 Apr 2024 13:52:52 +0100 Subject: Rename `trace_linux.odin` to `trace_cpp.odin` --- core/debug/trace/trace_cpp.odin | 195 ++++++++++++++++++++++++++++++++++++++ core/debug/trace/trace_linux.odin | 195 -------------------------------------- core/debug/trace/trace_nil.odin | 2 +- 3 files changed, 196 insertions(+), 196 deletions(-) create mode 100644 core/debug/trace/trace_cpp.odin delete mode 100644 core/debug/trace/trace_linux.odin (limited to 'core/debug/trace') diff --git a/core/debug/trace/trace_cpp.odin b/core/debug/trace/trace_cpp.odin new file mode 100644 index 000000000..894046c45 --- /dev/null +++ b/core/debug/trace/trace_cpp.odin @@ -0,0 +1,195 @@ +//+private file +//+build linux, darwin +package debug_trace + +import "base:intrinsics" +import "base:runtime" +import "core:strings" +import "core:fmt" +import "core:c" + +// NOTE: Relies on C++23 which adds and becomes ABI and that can be used +foreign import stdcpplibbacktrace "system:stdc++_libbacktrace" + +foreign import libdl "system:dl" + +backtrace_state :: struct {} +backtrace_error_callback :: proc "c" (data: rawptr, msg: cstring, errnum: c.int) +backtrace_simple_callback :: proc "c" (data: rawptr, pc: uintptr) -> c.int +backtrace_full_callback :: proc "c" (data: rawptr, pc: uintptr, filename: cstring, lineno: c.int, function: cstring) -> c.int +backtrace_syminfo_callback :: proc "c" (data: rawptr, pc: uintptr, symname: cstring, symval: uintptr, symsize: uintptr) + +@(default_calling_convention="c", link_prefix="__glibcxx_") +foreign stdcpplibbacktrace { + backtrace_create_state :: proc( + filename: cstring, + threaded: c.int, + error_callback: backtrace_error_callback, + data: rawptr, + ) -> ^backtrace_state --- + backtrace_simple :: proc( + state: ^backtrace_state, + skip: c.int, + callback: backtrace_simple_callback, + error_callback: backtrace_error_callback, + data: rawptr, + ) -> c.int --- + backtrace_pcinfo :: proc( + state: ^backtrace_state, + pc: uintptr, + callback: backtrace_full_callback, + error_callback: backtrace_error_callback, + data: rawptr, + ) -> c.int --- + backtrace_syminfo :: proc( + state: ^backtrace_state, + addr: uintptr, + callback: backtrace_syminfo_callback, + error_callback: backtrace_error_callback, + data: rawptr, + ) -> c.int --- + + // NOTE(bill): this is technically an internal procedure, but it is exposed + backtrace_free :: proc( + state: ^backtrace_state, + p: rawptr, + size: c.size_t, // unused + error_callback: backtrace_error_callback, // unused + data: rawptr, // unused + ) --- +} + +Dl_info :: struct { + dli_fname: cstring, + dli_fbase: rawptr, + dli_sname: cstring, + dli_saddr: rawptr, +} + +@(default_calling_convention="c") +foreign libdl { + dladdr :: proc(addr: rawptr, info: ^Dl_info) -> c.int --- +} + +@(private="package") +_Context :: struct { + state: ^backtrace_state, +} + +@(private="package") +_init :: proc(ctx: ^Context) -> (ok: bool) { + defer if !ok do destroy(ctx) + + ctx.impl.state = backtrace_create_state("odin-debug-trace", 1, nil, ctx) + return ctx.impl.state != nil +} + +@(private="package") +_destroy :: proc(ctx: ^Context) -> bool { + if ctx != nil { + backtrace_free(ctx.impl.state, nil, 0, nil, nil) + } + return true +} + +@(private="package") +_frames :: proc "contextless" (ctx: ^Context, skip: uint, frames_buffer: []Frame) -> (frames: []Frame) { + Backtrace_Context :: struct { + ctx: ^Context, + frames: []Frame, + frame_count: int, + } + + btc := &Backtrace_Context{ + ctx = ctx, + frames = frames_buffer, + } + backtrace_simple( + ctx.impl.state, + c.int(skip + 2), + proc "c" (user: rawptr, address: uintptr) -> c.int { + btc := (^Backtrace_Context)(user) + address := Frame(address) + if address == 0 { + return 1 + } + if btc.frame_count == len(btc.frames) { + return 1 + } + btc.frames[btc.frame_count] = address + btc.frame_count += 1 + return 0 + }, + nil, + btc, + ) + + if btc.frame_count > 0 { + frames = btc.frames[:btc.frame_count] + } + return +} + +@(private="package") +_resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> Frame_Location { + intrinsics.atomic_store(&ctx.in_resolve, true) + defer intrinsics.atomic_store(&ctx.in_resolve, false) + + Backtrace_Context :: struct { + rt_ctx: runtime.Context, + allocator: runtime.Allocator, + frame: Frame_Location, + } + + btc := &Backtrace_Context{ + rt_ctx = context, + allocator = allocator, + } + done := backtrace_pcinfo( + ctx.impl.state, + uintptr(frame), + proc "c" (data: rawptr, address: uintptr, file: cstring, line: c.int, symbol: cstring) -> c.int { + btc := (^Backtrace_Context)(data) + context = btc.rt_ctx + + frame := &btc.frame + + if file != nil { + frame.file_path = strings.clone_from_cstring(file, btc.allocator) + } else if info: Dl_info; dladdr(rawptr(address), &info) != 0 && info.dli_fname != "" { + frame.file_path = strings.clone_from_cstring(info.dli_fname, btc.allocator) + } + if symbol != nil { + frame.procedure = strings.clone_from_cstring(symbol, btc.allocator) + } else if info: Dl_info; dladdr(rawptr(address), &info) != 0 && info.dli_sname != "" { + frame.procedure = strings.clone_from_cstring(info.dli_sname, btc.allocator) + } else { + frame.procedure = fmt.aprintf("(procedure: 0x%x)", allocator=btc.allocator) + } + frame.line = i32(line) + return 0 + }, + nil, + btc, + ) + if done != 0 { + return btc.frame + } + + // NOTE(bill): pcinfo cannot resolve, but it might be possible to get the procedure name at least + backtrace_syminfo( + ctx.impl.state, + uintptr(frame), + proc "c" (data: rawptr, address: uintptr, symbol: cstring, _ignore0, _ignore1: uintptr) { + if symbol != nil { + btc := (^Backtrace_Context)(data) + context = btc.rt_ctx + btc.frame.procedure = strings.clone_from_cstring(symbol, btc.allocator) + } + }, + nil, + btc, + ) + + return btc.frame +} \ No newline at end of file diff --git a/core/debug/trace/trace_linux.odin b/core/debug/trace/trace_linux.odin deleted file mode 100644 index 211c379ca..000000000 --- a/core/debug/trace/trace_linux.odin +++ /dev/null @@ -1,195 +0,0 @@ -//+private file -//+build linux -package debug_trace - -import "base:intrinsics" -import "base:runtime" -import "core:strings" -import "core:fmt" -import "core:c" - -// NOTE: Relies on C++23 which adds and becomes ABI and that can be used -foreign import stdcpplibbacktrace "system:stdc++_libbacktrace" - -foreign import libdl "system:dl" - -backtrace_state :: struct {} -backtrace_error_callback :: proc "c" (data: rawptr, msg: cstring, errnum: c.int) -backtrace_simple_callback :: proc "c" (data: rawptr, pc: uintptr) -> c.int -backtrace_full_callback :: proc "c" (data: rawptr, pc: uintptr, filename: cstring, lineno: c.int, function: cstring) -> c.int -backtrace_syminfo_callback :: proc "c" (data: rawptr, pc: uintptr, symname: cstring, symval: uintptr, symsize: uintptr) - -@(default_calling_convention="c", link_prefix="__glibcxx_") -foreign stdcpplibbacktrace { - backtrace_create_state :: proc( - filename: cstring, - threaded: c.int, - error_callback: backtrace_error_callback, - data: rawptr, - ) -> ^backtrace_state --- - backtrace_simple :: proc( - state: ^backtrace_state, - skip: c.int, - callback: backtrace_simple_callback, - error_callback: backtrace_error_callback, - data: rawptr, - ) -> c.int --- - backtrace_pcinfo :: proc( - state: ^backtrace_state, - pc: uintptr, - callback: backtrace_full_callback, - error_callback: backtrace_error_callback, - data: rawptr, - ) -> c.int --- - backtrace_syminfo :: proc( - state: ^backtrace_state, - addr: uintptr, - callback: backtrace_syminfo_callback, - error_callback: backtrace_error_callback, - data: rawptr, - ) -> c.int --- - - // NOTE(bill): this is technically an internal procedure, but it is exposed - backtrace_free :: proc( - state: ^backtrace_state, - p: rawptr, - size: c.size_t, // unused - error_callback: backtrace_error_callback, // unused - data: rawptr, // unused - ) --- -} - -Dl_info :: struct { - dli_fname: cstring, - dli_fbase: rawptr, - dli_sname: cstring, - dli_saddr: rawptr, -} - -@(default_calling_convention="c") -foreign libdl { - dladdr :: proc(addr: rawptr, info: ^Dl_info) -> c.int --- -} - -@(private="package") -_Context :: struct { - state: ^backtrace_state, -} - -@(private="package") -_init :: proc(ctx: ^Context) -> (ok: bool) { - defer if !ok do destroy(ctx) - - ctx.impl.state = backtrace_create_state("odin-debug-trace", 1, nil, ctx) - return ctx.impl.state != nil -} - -@(private="package") -_destroy :: proc(ctx: ^Context) -> bool { - if ctx != nil { - backtrace_free(ctx.impl.state, nil, 0, nil, nil) - } - return true -} - -@(private="package") -_frames :: proc "contextless" (ctx: ^Context, skip: uint, frames_buffer: []Frame) -> (frames: []Frame) { - Backtrace_Context :: struct { - ctx: ^Context, - frames: []Frame, - frame_count: int, - } - - btc := &Backtrace_Context{ - ctx = ctx, - frames = frames_buffer, - } - backtrace_simple( - ctx.impl.state, - c.int(skip + 2), - proc "c" (user: rawptr, address: uintptr) -> c.int { - btc := (^Backtrace_Context)(user) - address := Frame(address) - if address == 0 { - return 1 - } - if btc.frame_count == len(btc.frames) { - return 1 - } - btc.frames[btc.frame_count] = address - btc.frame_count += 1 - return 0 - }, - nil, - btc, - ) - - if btc.frame_count > 0 { - frames = btc.frames[:btc.frame_count] - } - return -} - -@(private="package") -_resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> Frame_Location { - intrinsics.atomic_store(&ctx.in_resolve, true) - defer intrinsics.atomic_store(&ctx.in_resolve, false) - - Backtrace_Context :: struct { - rt_ctx: runtime.Context, - allocator: runtime.Allocator, - frame: Frame_Location, - } - - btc := &Backtrace_Context{ - rt_ctx = context, - allocator = allocator, - } - done := backtrace_pcinfo( - ctx.impl.state, - uintptr(frame), - proc "c" (data: rawptr, address: uintptr, file: cstring, line: c.int, symbol: cstring) -> c.int { - btc := (^Backtrace_Context)(data) - context = btc.rt_ctx - - frame := &btc.frame - - if file != nil { - frame.file_path = strings.clone_from_cstring(file, btc.allocator) - } else if info: Dl_info; dladdr(rawptr(address), &info) != 0 && info.dli_fname != "" { - frame.file_path = strings.clone_from_cstring(info.dli_fname, btc.allocator) - } - if symbol != nil { - frame.procedure = strings.clone_from_cstring(symbol, btc.allocator) - } else if info: Dl_info; dladdr(rawptr(address), &info) != 0 && info.dli_sname != "" { - frame.procedure = strings.clone_from_cstring(info.dli_sname, btc.allocator) - } else { - frame.procedure = fmt.aprintf("(procedure: 0x%x)", allocator=btc.allocator) - } - frame.line = i32(line) - return 0 - }, - nil, - btc, - ) - if done != 0 { - return btc.frame - } - - // NOTE(bill): pcinfo cannot resolve, but it might be possible to get the procedure name at least - backtrace_syminfo( - ctx.impl.state, - uintptr(frame), - proc "c" (data: rawptr, address: uintptr, symbol: cstring, _ignore0, _ignore1: uintptr) { - if symbol != nil { - btc := (^Backtrace_Context)(data) - context = btc.rt_ctx - btc.frame.procedure = strings.clone_from_cstring(symbol, btc.allocator) - } - }, - nil, - btc, - ) - - return btc.frame -} \ No newline at end of file diff --git a/core/debug/trace/trace_nil.odin b/core/debug/trace/trace_nil.odin index 926bd18cc..40478898b 100644 --- a/core/debug/trace/trace_nil.odin +++ b/core/debug/trace/trace_nil.odin @@ -1,4 +1,4 @@ -//+build !windows !linux +//+build !windows !linux !darwin package debug_trace _Context :: struct { -- cgit v1.2.3