1 个不稳定版本

0.0.1 2022年4月29日

#10 in #backtracking

MIT 许可证

20KB
242

tracefp

基于帧指针的堆栈回溯库。

要求

在编译项目时,设置以下环境变量

  • CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
  • CXXFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
  • RUSTFLAGS += -Cforce-frame-pointers=yes

并将以下参数添加到 cargo build

rustup component add rust-src
cargo build -Z build-std --target x86_64-unknown-linux-gnu

其中 x86_64-unknown-linux-gnu 可以替换为其他值,并且 build-std 目前仅支持夜间Rust。

注意:当您在 macOS + aarch64 上使用此库时,您不需要做任何事情,因为该平台上的所有库默认都启用了帧指针。

示例

堆栈回溯

fn main() {
    func1_inlined();
}

#[inline(always)]
fn func1_inlined() {
    func2()
}

fn func2() {
    tracefp::trace(|pc| {
        println!("{:#x}", pc);
        backtrace::resolve(pc as _, |s| {
            println!("    {:?}", s.name());
        });
        true
    });
}

示例输出

0x0
0x100d7348b
    Some(hello::func2::h53002ef4ebe4d7d7)
0x100d73337
    Some(hello::func1_inlined::h30751d2ee2774466)
    Some(hello::main::h994e0b3179971102)
0x100d72ddf
    Some(core::ops::function::FnOnce::call_once::h3dec9d79421d8d27)
0x100d71723
    Some(std::sys_common::backtrace::__rust_begin_short_backtrace::h9755a7454510e50f)
0x100d716db
    Some(std::rt::lang_start::{{closure}}::ha86392d061932837)
0x100e4065f
    Some(core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h8eb3ac20f80eabfa)
    Some(std::panicking::try::do_call::ha6ddf2c638427188)
    Some(std::panicking::try::hda8741de507c1ad0)
    Some(std::panic::catch_unwind::h82424a01f258bd39)
    Some(std::rt::lang_start_internal::{{closure}}::h67e296ed5b030b7b)
    Some(std::panicking::try::do_call::hd3dd7e7e10f6424e)
    Some(std::panicking::try::ha0a7bd8122e3fb7c)
    Some(std::panic::catch_unwind::h809b0e1092e9475d)
    Some(std::rt::lang_start_internal::h358b6d58e23c88c7)
0x100d716a3
    Some(std::rt::lang_start::h1342399ebba7a37d)
0x100d734df
    Some("_main")
0x101059087
0xd82e7fffffffffff

在信号处理程序中的堆栈回溯

use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGPROF};

fn main() {
    // Register perf signal handler.
    let h = SigHandler::SigAction(perf_signal_handler);
    let a = SigAction::new(h, SaFlags::SA_SIGINFO, SigSet::empty());
    unsafe {
        sigaction(SIGPROF, &a).unwrap();
    }

    // Send a SIGPROF signal to the current process.
    unsafe {
        libc::kill(libc::getpid(), libc::SIGPROF);
    }

    // Block until the signal handler finishes executing.
    loop {}
}

#[no_mangle]
pub extern "C" fn perf_signal_handler(_: libc::c_int, _: *mut libc::siginfo_t, ucontext: *mut libc::c_void) {
    tracefp::trace_from_ucontext(ucontext, |pc| {
        println!("{:#x}", pc);
        backtrace::resolve(pc as _, |s| {
            println!("    {:?}", s.name());
        });
        true
    });
    std::process::exit(0);
}

示例输出

0x1c32e4824
    Some("_thread_get_state")
0x100409093
    Some(core::ops::function::FnOnce::call_once::h775fb44fbbe53d95)
0x1004090eb
    Some(std::sys_common::backtrace::__rust_begin_short_backtrace::h3acd0b11747c5033)
0x100408a2b
    Some(std::rt::lang_start::{{closure}}::hf7b77a4d60d2f840)
0x1004d7faf
    Some(core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h8eb3ac20f80eabfa)
    Some(std::panicking::try::do_call::ha6ddf2c638427188)
    Some(std::panicking::try::hda8741de507c1ad0)
    Some(std::panic::catch_unwind::h82424a01f258bd39)
    Some(std::rt::lang_start_internal::{{closure}}::h67e296ed5b030b7b)
    Some(std::panicking::try::do_call::hd3dd7e7e10f6424e)
    Some(std::panicking::try::ha0a7bd8122e3fb7c)
    Some(std::panic::catch_unwind::h809b0e1092e9475d)
    Some(std::rt::lang_start_internal::h358b6d58e23c88c7)
0x1004089f3
    Some(std::rt::lang_start::hd321e36029dcfdd2)
0x1004093d7
    Some("_main")
0x1007bd087
0x921a7fffffffffff

依赖项

~43KB