From da76f5588e022410b2c6e32749b54b9ce3a4ae91 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 23 Apr 2026 21:48:12 +0300 Subject: [PATCH] builtin: fix libbacktrace not supported on OpenBSD (fixes #22261) --- vlib/builtin/backtraces.c.v | 8 +- vlib/builtin/builtin.c.v | 6 +- vlib/builtin/builtin_d_use_libbacktrace.c.v | 176 +++++++++++--------- vlib/builtin/panicing.c.v | 12 +- 4 files changed, 115 insertions(+), 87 deletions(-) diff --git a/vlib/builtin/backtraces.c.v b/vlib/builtin/backtraces.c.v index 53daaed30..90ed5d6f6 100644 --- a/vlib/builtin/backtraces.c.v +++ b/vlib/builtin/backtraces.c.v @@ -13,8 +13,12 @@ pub fn print_backtrace() { } $else $if tinyc { C.tcc_backtrace(c'Backtrace') } $else $if use_libbacktrace ? { - // NOTE: TCC doesn't have the unwind library - print_libbacktrace(1) + $if openbsd { + print_backtrace_skipping_top_frames(2) + } $else { + // NOTE: TCC doesn't have the unwind library + print_libbacktrace(1) + } } $else { print_backtrace_skipping_top_frames(2) } diff --git a/vlib/builtin/builtin.c.v b/vlib/builtin/builtin.c.v index 3b97a0edf..34030f051 100644 --- a/vlib/builtin/builtin.c.v +++ b/vlib/builtin/builtin.c.v @@ -57,7 +57,11 @@ fn v_segmentation_fault_handler(signal_number i32) { C.fprintf(C.stderr, c'signal %d: segmentation fault\n', signal_number) } $if use_libbacktrace ? { - eprint_libbacktrace(1) + $if openbsd { + print_backtrace() + } $else { + eprint_libbacktrace(1) + } } $else { print_backtrace() } diff --git a/vlib/builtin/builtin_d_use_libbacktrace.c.v b/vlib/builtin/builtin_d_use_libbacktrace.c.v index 133233ae8..7c9df4575 100644 --- a/vlib/builtin/builtin_d_use_libbacktrace.c.v +++ b/vlib/builtin/builtin_d_use_libbacktrace.c.v @@ -1,107 +1,119 @@ @[has_globals] module builtin -#flag -I@VEXEROOT/thirdparty/libbacktrace -#flag @VEXEROOT/thirdparty/libbacktrace/backtrace.o -#include +$if openbsd { + // OpenBSD lacks the sysctl path lookup that bundled libbacktrace needs, + // so `-d use_libbacktrace` falls back to the native BSD backtrace path. + fn print_libbacktrace(frames_to_skip int) { + } -// NOTE: Don't mark this as a @[typedef] or it may cause compiler errors! -pub struct C.backtrace_state { - // filename &char -} + @[noinline] + fn eprint_libbacktrace(frames_to_skip int) { + } +} $else { + #flag -I@VEXEROOT/thirdparty/libbacktrace + #flag @VEXEROOT/thirdparty/libbacktrace/backtrace.o + #include -type BacktraceErrorCallback = fn (data voidptr, msg &char, errnum int) voidptr + // NOTE: Don't mark this as a @[typedef] or it may cause compiler errors! + pub struct C.backtrace_state { + // filename &char + } -type BacktraceFullCallback = fn (data voidptr, pc voidptr, filename &char, lineno int, func &char) &int + type BacktraceErrorCallback = fn (data voidptr, msg &char, errnum int) -fn C.backtrace_create_state(filename &char, threaded i32, error_callback BacktraceErrorCallback, data voidptr) &C.backtrace_state -fn C.backtrace_full(state &C.backtrace_state, skip i32, cb BacktraceFullCallback, err_cb BacktraceErrorCallback, + type BacktraceFullCallback = fn (data voidptr, pc voidptr, filename &char, lineno int, func &char) int + + fn C.backtrace_create_state(filename &char, threaded i32, error_callback BacktraceErrorCallback, data voidptr) &C.backtrace_state + fn C.backtrace_full(state &C.backtrace_state, skip i32, cb BacktraceFullCallback, err_cb BacktraceErrorCallback, data voidptr) i32 -__global bt_state = init_bt_state() + __global bt_state = init_bt_state() -fn init_bt_state() &C.backtrace_state { - $if !tinyc { - mut filename := &char(unsafe { nil }) - $if windows { - filename = unsafe { string_from_wide(&&u16(g_main_argv)[0]).str } - } $else { - filename = unsafe { &&char(g_main_argv)[0] } + fn init_bt_state() &C.backtrace_state { + $if !tinyc { + mut filename := &char(unsafe { nil }) + $if windows { + filename = unsafe { string_from_wide(&&u16(g_main_argv)[0]).str } + } $else { + filename = unsafe { &&char(g_main_argv)[0] } + } + return C.backtrace_create_state(filename, 1, bt_error_handler, 0) } - return C.backtrace_create_state(filename, 1, bt_error_handler, 0) + return &C.backtrace_state(unsafe { nil }) } - return &C.backtrace_state(unsafe { nil }) -} -// for bt_error_callback -struct BacktraceOptions { - stdin bool = true -} - -fn bt_print_callback(data &BacktraceOptions, pc voidptr, filename_ptr &char, line int, fn_name_ptr &char) int { - filename := if filename_ptr == unsafe { nil } { - '???' - } else { - unsafe { filename_ptr.vstring() } - } - fn_name := if fn_name_ptr == unsafe { nil } { - '???' - } else { - demangle_v_symbol(unsafe { fn_name_ptr.vstring() }) - } - // keep it for later - // pc_64 := u64(pc) - bt_str := '${filename}:${line}: by ${fn_name}' - if data.stdin { - println(bt_str) - } else { - eprintln(bt_str) + // for bt_error_callback + struct BacktraceOptions { + stdin bool = true } - return 0 -} - -fn bt_error_callback(data voidptr, msg_ptr &char, errnum int) { - // if data != unsafe { nil } && data.state != unsafe { nil } && data.state.filename != unsafe { nil } { - // filename := unsafe{ data.state.filename.vstring() } - // eprint('${filename}: ') - // } - msg := unsafe { msg_ptr.vstring() } - eprint('libbacktrace: ${msg}') - if errnum > 0 { - eprint(': ${C.strerror(errnum)}') + fn bt_print_callback(data_ptr voidptr, pc voidptr, filename_ptr &char, line int, fn_name_ptr &char) int { + data := unsafe { &BacktraceOptions(data_ptr) } + filename := if filename_ptr == unsafe { nil } { + '???' + } else { + unsafe { filename_ptr.vstring() } + } + fn_name := if fn_name_ptr == unsafe { nil } { + '???' + } else { + demangle_v_symbol(unsafe { fn_name_ptr.vstring() }) + } + // keep it for later + // pc_64 := u64(pc) + bt_str := '${filename}:${line}: by ${fn_name}' + if data.stdin { + println(bt_str) + } else { + eprintln(bt_str) + } + return 0 } - eprintln('') -} + fn bt_error_callback(data voidptr, msg_ptr &char, errnum int) { + // if data != unsafe { nil } && data.state != unsafe { nil } && data.state.filename != unsafe { nil } { + // filename := unsafe{ data.state.filename.vstring() } + // eprint('${filename}: ') + // } -// for backtrace_create_state only -fn bt_error_handler(data voidptr, msg &char, errnum int) { - eprint('libbacktrace: ') - eprint(unsafe { msg.vstring() }) - if errnum > 0 { - eprint(': ${C.strerror(errnum)}') + msg := unsafe { msg_ptr.vstring() } + eprint('libbacktrace: ${msg}') + if errnum > 0 { + eprint(': ${C.strerror(errnum)}') + } + + eprintln('') } - eprintln('') - exit(1) -} -@[noinline] -fn print_libbacktrace(frames_to_skip int) { - $if no_backtrace ? { - return + // for backtrace_create_state only + fn bt_error_handler(data voidptr, msg &char, errnum int) { + eprint('libbacktrace: ') + eprint(unsafe { msg.vstring() }) + if errnum > 0 { + eprint(': ${C.strerror(errnum)}') + } + eprintln('') + exit(1) } - data := &BacktraceOptions{} - C.backtrace_full(bt_state, frames_to_skip, bt_print_callback, bt_error_callback, data) -} -@[noinline] -fn eprint_libbacktrace(frames_to_skip int) { - $if no_backtrace ? { - return + @[noinline] + fn print_libbacktrace(frames_to_skip int) { + $if no_backtrace ? { + return + } + data := &BacktraceOptions{} + C.backtrace_full(bt_state, frames_to_skip, bt_print_callback, bt_error_callback, data) } - data := &BacktraceOptions{ - stdin: false + + @[noinline] + fn eprint_libbacktrace(frames_to_skip int) { + $if no_backtrace ? { + return + } + data := &BacktraceOptions{ + stdin: false + } + C.backtrace_full(bt_state, frames_to_skip, bt_print_callback, bt_error_callback, data) } - C.backtrace_full(bt_state, frames_to_skip, bt_print_callback, bt_error_callback, data) } diff --git a/vlib/builtin/panicing.c.v b/vlib/builtin/panicing.c.v index 71860b76d..006b444f2 100644 --- a/vlib/builtin/panicing.c.v +++ b/vlib/builtin/panicing.c.v @@ -44,7 +44,11 @@ fn panic_debug(line_no int, file string, mod string, fn_name string, s string) { C.exit(1) } $if use_libbacktrace ? { - eprint_libbacktrace(1) + $if openbsd { + print_backtrace_skipping_top_frames(1) + } $else { + eprint_libbacktrace(1) + } } $else { print_backtrace_skipping_top_frames(1) } @@ -106,7 +110,11 @@ pub fn panic(s string) { C.exit(1) } $if use_libbacktrace ? { - eprint_libbacktrace(1) + $if openbsd { + print_backtrace_skipping_top_frames(1) + } $else { + eprint_libbacktrace(1) + } } $else { print_backtrace_skipping_top_frames(1) } -- 2.39.5