benfred / py-spy

Sampling profiler for Python programs
MIT License
12.14k stars 400 forks source link

Support native extensions on RISC-V #594

Open ndemashov opened 1 year ago

ndemashov commented 1 year ago

I'm running py-spy on RISC-V Mango Pi and it works. Thanks for making such a great tool. It'd be even better if profiling on RISC-V supported native extensions. I tried to follow the steps from the issue with the same theme for ARM architecture.

  1. Add riscv64 support to remoteprocess build.rs.

    let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    match target_arch.as_str() {
        "x86_64" | "arm" | "riscv64" => {}
        _ => return,
    };
  2. Support risc-v in mod.rs Add path to riscv binds.

    #[cfg_attr(target_arch="riscv64", path="[bindings_riscv.rs](http://bindings_riscv.rs/)")]

Add register for risc-v.

    #[cfg(target_arch="riscv64")]
    pub fn bx(&self) -> Result<u64> {
        unsafe { self.register(5) }
    }

Add functions for risc-v on the example of other architectures.

#[cfg(target_arch="riscv64")]
extern {
    #[link_name="_Uriscv_create_addr_space"]
    #[allow(improper_ctypes)]
    fn create_addr_space(acc: *mut unw_accessors_t, byteorder: c_int) -> unw_addr_space_t;
    #[link_name="_Uriscv_destroy_addr_space"]
    fn destroy_addr_space(addr: unw_addr_space_t) -> c_void;
    #[link_name="_Uriscv_init_remote"]
    fn init_remote(cursor: *mut unw_cursor_t, addr: unw_addr_space_t, ptr: *mut c_void) -> c_int;
    #[link_name="_Uriscv_get_reg"]
    fn get_reg(cursor: *mut unw_cursor_t, reg: unw_regnum_t, val: *mut unw_word_t) -> c_int;
    #[link_name="_Uriscv_step"]
    fn step(cursor: *mut unw_cursor_t) -> c_int;
    #[link_name="_Uriscv_get_proc_name"]
    fn get_proc_name(cursor: *mut unw_cursor, buffer: * mut c_char, len: size_t, offset: *mut unw_word_t) -> c_int;
    #[link_name="_Uriscv_set_caching_policy"]
    fn set_caching_policy(spc: unw_addr_space_t, policy: unw_caching_policy_t) -> c_int;
  1. Build libunwind for risc-v from source and generate risc-v bindings with rust-bindgen 0.65.1.

    bindgen /usr/local/include/libunwind.h --allowlist-type unw_.*
  2. Run remoteprocess tests. cargo test --release --features unwind All tests passed.

  3. In py-spy Cargo.toml set path to remoteprocess remoteprocess = { path = "/home/user/source/remoteprocess", features=["unwind"]}

  4. In python_bindings add functions:

    #[cfg(target_arch = "riscv64")]
    pub fn get_interp_head_offset(version: &Version) -> usize {
        match version {
            Version{major: 3, minor: 9, patch: 5, ..} => 32,
            _ => 32
        }
    }
     #[cfg(all(target_os="linux", target_arch="riscv64"))]
    pub fn get_tstate_current_offset(version: &Version) -> Option<usize> {
        match version {
            Version{major: 3, minor: 9, patch: 5, ..} => Some(568),
            _ => None
        }
    }

    Got the values by running generate_bindings.py.

  5. Generate bindings for python v3_9_5 by running generate_bindings.py.

  6. Disabled architecture check in build.rs

Run py-spy testing. py-spy cargo test --release

Failed: Test_subprocess Test_thread_names Test_thread_reuse

Failed to get traces failed to get os threadid

I tried to read the full backtrace, but that didn't help me understand the cause of the problem. Could you please tell me how to overcome these errors?

benfred commented 11 months ago

It seems like you got pretty far here!

Failed to get traces failed to get os threadid

The issue here seems to be matching the OS thread id to the Python pthread id . On x86_64 we do this be examining the RBX register on the top level of the native stack https://github.com/benfred/py-spy/blob/fea1c42a45701968f76a8babbd903d92a1092117/src/python_spy.rs#L480-L483 to get the pthread id.

However, from python 3.11 on we can get OS thread id directly from the PyThreadState object https://github.com/benfred/py-spy/blob/fea1c42a45701968f76a8babbd903d92a1092117/src/python_interpreters.rs#L334-L336 - and don't need hacks like this to get the native thread id . Does everything work for you using python 3.11?

ndemashov commented 10 months ago

Thank you for response! I tried to use python3.11 and still get one error while run cargo test --release: test_subprocesses ... FAILED

failures: ---- test_subprocesses stdout ---- thread 'test_subprocesses' panicked at 'assertion failed: (left == right) left: 1, right: 3', tests/integration_test.rs:343:9

cargo test --verbose output

running 13 tests
test config::tests::test_parse_args ... ok
test config::tests::test_parse_dump_args ... ok
test config::tests::test_parse_record_args ... ok
test config::tests::test_parse_top_args ... ok
test coredump::test::test_coredump ... thread 'coredump::test::test_coredump' panicked at 'misaligned pointer dereference: address must be a multiple of 0x8 but is 0x3f9329a334', src/coredump.rs:94:30
stack backtrace:
   0: rust_begin_unwind
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5
   1: core::panicking::panic_fmt
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:14
   2: core::panicking::panic_misaligned_pointer_dereference
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:174:5
   3: py_spy::coredump::CoreDump::new
             at ./src/coredump.rs:94:30
   4: py_spy::coredump::test::test_coredump
             at ./src/coredump.rs:438:20
   5: py_spy::coredump::test::test_coredump::{{closure}}
             at ./src/coredump.rs:434:24
   6: core::ops::function::FnOnce::call_once
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
   7: core::ops::function::FnOnce::call_once
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
thread 'coredump::test::test_coredump' panicked at 'panic in a function that cannot unwind', library/core/src/panicking.rs:126:5
stack backtrace:
   0:       0x2ad4ade93c - std::backtrace_rs::backtrace::libunwind::trace::h2cdfd0b384999b1a
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:       0x2ad4ade93c - std::backtrace_rs::backtrace::trace_unsynchronized::had05dddedfca6819
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:       0x2ad4ade93c - std::sys_common::backtrace::_print_fmt::hd3c3961298077cf6
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:65:5
   3:       0x2ad4ade93c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hf994e4d85f36bd65
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:44:22
   4:       0x2ad4afbddc - core::fmt::write::hd25d4d0403c7a6ad
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/fmt/mod.rs:1254:17
   5:       0x2ad4adaea6 - std::io::Write::write_fmt::h81ae5a647e1597f4
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/io/mod.rs:1698:15
   6:       0x2ad4ade7a2 - std::sys_common::backtrace::_print::he9bfd442805fab7c
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:47:5
   7:       0x2ad4ade7a2 - std::sys_common::backtrace::print::h384e61d38491532e
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:34:9
   8:       0x2ad4adff48 - std::panicking::default_hook::{{closure}}::h7a771e9becb29ed1
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:269:22
   9:       0x2ad4adfd16 - std::panicking::default_hook::h166f783bb38d877c
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:288:9
  10:       0x2ad48d3e4e - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h142c939f22cf21be
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/boxed.rs:1987:9
  11:       0x2ad48d3e4e - test::test_main::{{closure}}::h534699d1a22e2c0d
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/test/src/lib.rs:134:21
  12:       0x2ad4ae0aea - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h0707b6bc4500857e
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/boxed.rs:1987:9
  13:       0x2ad4ae0aea - std::panicking::rust_panic_with_hook::h38a8c211dcdf7695
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:695:13
  14:       0x2ad4ae08a8 - std::panicking::begin_panic_handler::{{closure}}::hd74e13214bccd1a1
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:580:13
  15:       0x2ad4adec84 - std::sys_common::backtrace::__rust_end_short_backtrace::h26c5545f867f7fe9
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:150:18
  16:       0x2ad4ae06ec - rust_begin_unwind
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5
  17:       0x2ad4825b9e - core::panicking::panic_nounwind_fmt::h9a5c823be68e84f6
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:96:14
  18:       0x2ad4825c06 - core::panicking::panic_nounwind::h37b151ce8964c935
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:126:5
  19:       0x2ad4825cc6 - core::panicking::panic_cannot_unwind::ha8d8f96017115a93
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:188:5
  20:       0x2ad4838190 - py_spy::coredump::CoreDump::new::hea8ea75c27315234
                               at /home/n.demashov/my_rep/py-spy/src/coredump.rs:75:5
  21:       0x2ad4850abe - py_spy::coredump::test::test_coredump::h0bbdaf7ac4ef6d17
                               at /home/n.demashov/my_rep/py-spy/src/coredump.rs:438:20
  22:       0x2ad4845500 - py_spy::coredump::test::test_coredump::{{closure}}::hdbcd092f71d03f9a
                               at /home/n.demashov/my_rep/py-spy/src/coredump.rs:434:24
  23:       0x2ad482d79a - core::ops::function::FnOnce::call_once::h4d8e73149fd49a40
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
  24:       0x2ad48d705a - core::ops::function::FnOnce::call_once::he3d9cfffdbb90d3f
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
  25:       0x2ad48d705a - test::__rust_begin_short_backtrace::h482d75e4f168d6cf
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/test/src/lib.rs:655:18
  26:       0x2ad48b40ee - test::run_test::{{closure}}::hca314de3e02080fc
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/test/src/lib.rs:646:30
  27:       0x2ad48b40ee - core::ops::function::FnOnce::call_once{{vtable.shim}}::hb1adc11552bef124
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
  28:       0x2ad48b3698 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hb396e472257b5b94
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/boxed.rs:1973:9
  29:       0x2ad48b3698 - <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::hec5f7fa0a7a7fbde
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panic/unwind_safe.rs:271:9
  30:       0x2ad48b3698 - std::panicking::try::do_call::h2a7c67e013d8222b
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:485:40
  31:       0x2ad48d7208 - __rust_try
  32:       0x2ad48d63a6 - std::panicking::try::h7eedc1484179d0af
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:449:19
  33:       0x2ad48d63a6 - std::panic::catch_unwind::hb1f8464c8268f3da
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panic.rs:140:14
  34:       0x2ad48d63a6 - test::run_test_in_process::h2feadc1b1129eacf
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/test/src/lib.rs:678:27
  35:       0x2ad48d63a6 - test::run_test::run_test_inner::{{closure}}::h6875c7506960d07f
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/test/src/lib.rs:572:39
  36:       0x2ad48af986 - test::run_test::run_test_inner::{{closure}}::h622942bd12ae91dc
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/test/src/lib.rs:599:37
  37:       0x2ad48af986 - std::sys_common::backtrace::__rust_begin_short_backtrace::hf80b002df9ed0160
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:134:18
  38:       0x2ad48d7208 - __rust_try
  39:       0x2ad48b3f4c - std::panicking::try::h1cd45d7e2d196540
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:449:19
  40:       0x2ad48b3f4c - std::panic::catch_unwind::h49380926c4783f5a
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panic.rs:140:14
  41:       0x2ad48b3f4c - std::thread::Builder::spawn_unchecked_::{{closure}}::hdf032fd740feae6a
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/thread/mod.rs:525:30
  42:       0x2ad48b3f4c - core::ops::function::FnOnce::call_once{{vtable.shim}}::h3e1a656a613e2eeb
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
  43:       0x2ad4ae3d02 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h0b03618cb7377f0c
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/boxed.rs:1973:9
  44:       0x2ad4ae3d02 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hd9aa49240836ce86
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/boxed.rs:1973:9
  45:       0x2ad4ae3d02 - std::sys::unix::thread::Thread::new::thread_start::he04e98a78d04050f
                               at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys/unix/thread.rs:108:17
  46:       0x3f988944c2 - <unknown>
  47:       0x3f988944c2 - <unknown>
thread caused non-unwinding panic. aborting.
error: test failed, to rerun pass `--lib`

Caused by:
  process didn't exit successfully: `/home/n.demashov/my_rep/py-spy/target/debug/deps/py_spy-a0444821ef2e4047` (signal: 6, SIGABRT: process abort signal)