Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Demangle failure with dragonbox symbol #269

Open
scoopr opened this issue Jun 10, 2022 · 4 comments
Open

Demangle failure with dragonbox symbol #269

scoopr opened this issue Jun 10, 2022 · 4 comments

Comments

@scoopr
Copy link

scoopr commented Jun 10, 2022

Hello!

I noticed a case where the demangling fails, but where (llvm/apple) c++filt seems to work, with this beauty:
__ZZZN3jkj9dragonbox10to_decimalIfNS0_20default_float_traitsIfEEJNS0_6detail11policy_impl4sign6ignoreENS5_13trailing_zero6removeEEEEDaNS0_23signed_significand_bitsIT_T0_EEjDpT1_ENKUlSC_E_clINS5_26decimal_to_binary_rounding15nearest_to_evenEEESA_SC_ENKUlDpT_E_clIJEEESA_SM_

A self contained test could be

fn main() -> Result<(),std::fmt::Error>{
    let mangled = "__ZZZN3jkj9dragonbox10to_decimalIfNS0_20default_float_traitsIfEEJNS0_6detail11policy_impl4sign6ignoreENS5_13trailing_zero6removeEEEEDaNS0_23signed_significand_bitsIT_T0_EEjDpT1_ENKUlSC_E_clINS5_26decimal_to_binary_rounding15nearest_to_evenEEESA_SC_ENKUlDpT_E_clIJEEESA_SM_";
    let sym = cpp_demangle::Symbol::new(mangled).unwrap();
    let demangled = sym.demangle(&Default::default())?;
    println!("Demangled: {}", demangled);
    Ok(())
}

And that just fails with Error: Error.

c++filt output for me is:

jkj::dragonbox::signed_significand_bits jkj::dragonbox::signed_significand_bits auto jkj::dragonbox::to_decimal<float, jkj::dragonbox::default_float_traits<float>, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove>(jkj::dragonbox::signed_significand_bits<float, jkj::dragonbox::default_float_traits<float> >, unsigned int, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove)::'lambda'(jkj::dragonbox::default_float_traits<float>)::operator()<jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even>(jkj::dragonbox::default_float_traits<float>) const::'lambda'(auto...)::operator()<>('lambda'(auto...)) const

And finally attempt to minimise the source of the symbol for proof that I didn't just conjure it up myself. Steps:

git clone https://github.com/jk-jeon/dragonbox.git
vim dragonbox.cpp
clang -std=c++17  -c dragonbox.cpp
nm dragonbox.o | grep __ZZZ

where the dragonbox.cpp contents being:

#include "dragonbox/include/dragonbox/dragonbox.h"

void dragon_test() {
  jkj::dragonbox::float_bits<float> br(0.0f);
  auto const exponent_bits = br.extract_exponent_bits();
  auto const s = br.remove_exponent_bits(exponent_bits);

  auto result = jkj::dragonbox::to_decimal(
      s, exponent_bits, jkj::dragonbox::policy::sign::ignore,
      jkj::dragonbox::policy::trailing_zero::remove);
}

Fiddling with the DemangleOptions didn't seem to affect the outcome.

I wonder if it is possible to make the demangler "fool proof" on valid input, or should there perhaps be some "lossy mode", where it demangles as much as it can, but bails out gracefully giving partial result, for when I don't have too strict needs.

khuey added a commit to khuey/cpp_demangle that referenced this issue Jun 11, 2022
@khuey
Copy link
Collaborator

khuey commented Jun 11, 2022

llvm-cxxfilt (built from rev 82fcd7397a5939a9f0148513cc7b6883a00a16b0) doesn't demangle this for me.

@scoopr
Copy link
Author

scoopr commented Jun 13, 2022

Hm, both the tools that come from xcode (xcode 13.4.1, c++filt claims to be 13.1.6), and homebrew installed (llvm/clang 13.0.1) seem to demangle it just fine. And these are the latest "stable" versions that I can easily install right now. I wonder if the mangling has then changed in later versions

@khuey
Copy link
Collaborator

khuey commented Jun 13, 2022

I followed the instructions you provided using clang's tip and the symbol produced now appears to be

_ZZZN3jkj9dragonbox10to_decimalIfNS0_20default_float_traitsIfEEJNS0_6detail11policy_impl4sign6ignoreENS5_13trailing_zero6removeEEEEDaNS0_23signed_significand_bitsIT_T0_EEjDpT1_ENKUlSB_E_clINS5_26decimal_to_binary_rounding15nearest_to_evenEEEDaSB_ENKUlDpT_E_clIJEEEDaSL_

llvm-cxxfilt produces

auto auto auto jkj::dragonbox::to_decimal<float, jkj::dragonbox::default_float_traits<float>, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove>(jkj::dragonbox::signed_significand_bits<float, jkj::dragonbox::default_float_traits<float>>, unsigned int, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove)::'lambda'(float)::operator()<jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even>(float) const::'lambda'(auto...)::operator()<>(auto...) const

cpp_demangle produces

auto auto auto jkj::dragonbox::to_decimal<float, jkj::dragonbox::default_float_traits<float>, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove>(jkj::dragonbox::signed_significand_bits<float, jkj::dragonbox::default_float_traits<float> >, unsigned int, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove)::{lambda(auto:1)#1}::operator()<jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even>(jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even) const::{lambda(auto:1)#1}::operator()<>() const

(libiberty does not parse this succesfully)

@khuey
Copy link
Collaborator

khuey commented Jun 14, 2022

Fixing the incorrect lambda parameters here is pretty tricky, I think it's going to require some serious refactoring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants