KDAB/hotspot

Rust demangling sometimes fail with v0 style mangling

VorpalBlade opened this issue · 1 comments

Describe the bug
While hotspot does have some support for demanging rust symbol names, this only works with the default "legacy" mangling scheme. The future default of v0 doesn't seem to work. I'm not sure why, as other software using rustc-demangle works fine (such as rustfilt). It also doesn't affect all symbols.

Here is an example of an affected symbols:

_RNvXs2_NtCs2HZeD2EXGYD_10rayon_core3jobINtB5_8StackJobNtNtB7_5latch9SpinLatchNCINvNvNtB7_4join12join_context6call_bINtNtNtNtCshKHR5mXfkcF_5rayon4iter7collect8consumer13CollectResultTjjNtNtNtB1Y_5slice9mergesort15MergesortResultEENCINvNvNtB1W_8plumbing24bridge_producer_consumer6helperINtNtB1W_9enumerate17EnumerateProducerINtNtB1W_3len14MaxLenProducerINtNtB30_6chunks17ChunksMutProducerTINtNtCsbrbDdEzO4k9_4core6option6OptionNtNtNtCs6Vtru2o1b3o_14paketkoll_core5types7package10PackageRefENtNtB6T_5issue5IssueEEEEINtNtB1W_3map11MapConsumerINtB1S_15CollectConsumerB2T_ENCINvB2Y_13par_mergesortB6c_NCINvYSB6c_INtB30_16ParallelSliceMutB6c_E15par_sort_by_keyTIB6e_ReENtNtCsh8cXEf2nBEC_3std4path7PathBufENCNvCs1jZVrpv0Zbm_9paketkoll4main0E0E0EEs_0E0B1P_ENtB5_3Job7executeBbi_

This should demangle to:

<rayon_core::job::StackJob<rayon_core::latch::SpinLatch, rayon_core::join::join_context::call_b<rayon::iter::collect::consumer::CollectResult<(usize, usize, rayon::slice::mergesort::MergesortResult)>, rayon::iter::plumbing::bridge_producer_consumer::helper<rayon::iter::enumerate::EnumerateProducer<rayon::iter::len::MaxLenProducer<rayon::slice::chunks::ChunksMutProducer<(core::option::Option<paketkoll_core::types::package::PackageRef>, paketkoll_core::types::issue::Issue)>>>, rayon::iter::map::MapConsumer<rayon::iter::collect::consumer::CollectConsumer<(usize, usize, rayon::slice::mergesort::MergesortResult)>, rayon::slice::mergesort::par_mergesort<(core::option::Option<paketkoll_core::types::package::PackageRef>, paketkoll_core::types::issue::Issue), <[(core::option::Option<paketkoll_core::types::package::PackageRef>, paketkoll_core::types::issue::Issue)] as rayon::slice::ParallelSliceMut<(core::option::Option<paketkoll_core::types::package::PackageRef>, paketkoll_core::types::issue::Issue)>>::par_sort_by_key<(core::option::Option<&str>, std::path::PathBuf), paketkoll::main::{closure#0}>::{closure#0}>::{closure#0}>>::{closure#1}>::{closure#0}, rayon::iter::collect::consumer::CollectResult<(usize, usize, rayon::slice::mergesort::MergesortResult)>> as rayon_core::job::Job>::execute

It seems to only be really long symbols that cause the issue. In this case it is symbols from my project paketkoll. As this depends on Arch Linux (to run this specific code path) I have instead created a reproduction project. It took a while to figure out what causes it. It seems to be specifically par_sort_by_key from the well known rayon crate (library) which is used for parallel computation.

To Reproduce
Steps to reproduce the behavior:

  1. Download attached project and extract it: hotspot_reproducer.tar.gz
  2. RUSTFLAGS=-Csymbol-mangling-version=v0 cargo build
  3. perf record -e cycles -e sched:sched_switch --switch-events --sample-cpu -m 32M --aio -z --call-graph dwarf -- target/debug/hotspot_reproducer
  4. hotspot perf.data

Expected behavior
Names should be properly demangled.

Screenshots
image

Version Info (please complete the following information):

  • Linux Kernel version: 6.8.1-arch1-1
  • perf version: 6.7-2
  • hotspot version (appimage? selfcompiled?): Tried both the latest AppImage from Github Actions (hotspot-v1.4.1-304-g61c5ad9-x86_64.AppImage) as well as the package from AUR with the same result.
  • if self-compiled hotspot, what version of elfutils: 0.191-1

This issue have been going on for a few months, but I only now got around to reporting it, so it is not specific to kernel version or perf version I believe.

Additional context
Add any other context about the problem here.

I believe the issue is your demangling buffer length is too short (1024) and demangled symbol is longer than that (1301 in this case). Unfortunately there doesn't seem to be a great way to tell these cases apart as "not a rust symbol" and "too small buffer" have the same return code. (see https://github.com/rust-lang/rustc-demangle/blob/af38dc6b06b5665c79a4778268e4faf5decd19df/crates/capi/include/rustc_demangle.h#L8-L13)

I'm opening a rustc-demangle bug about this issue. For now I would suggest increasing the size limit from 1024, both C++ and Rust symbols can get very long in real code bases. Perhaps 8192 would be a reasonable limit?