Is there any pure-Rust solution for libgcc_s.so in libunwind?

Rust binary/libraries still depend on libgcc for unwinding. Is there any pure-Rust solution for replacing libgcc_s.so? I saw there are pure-Rust libc replacement. How about libunwind? Or someone has been working on the dependency already. I don’t know if this issue has been discussed. If yes, please give me some pointers. Thanks.

No pure-Rust libunwind, however, it’s possible to statically link your binary if you are building for a -musl target.

It may also be possible to statically link libgcc, like we do on Windows, but AFAIK nobody has taken the time to figure out how to do this yet.

Thanks. I want to reduce C dependencies actually. I just realized that libgcc is another dependency regardless of libc.

For what purpose, if I may ask?

People had attempted this in the past (perhaps still working on it), but aside from writing #[no-std] code, there are currently no C-less solutions.

Thanks for the reply. Similar purpose as steed - to reduce the C dependency for security. Actually, I don’t have specific purpose for me. This is just for discussion.

I have looked steed. It seems that it aims to replace libstd. However, libgcc_s is the dependency of libunwind. That’s why I post this seeking solution for libgcc_s.

The stack unwinder is a big ball of hair, and perhaps that means it should be more of a priority for replacement with Rust than, like, the arithmetic helper routines, but whoever takes on the task should be aware of what they’re getting into – poorly documented, dependent on all kinds of low-level details about the architecture and the way the architecture is reflected into DWARF, and you gotta be bug-for-bug compatible with the existing implementation, because the only spec is “what existing compilers produce and the existing library accepts”.

Thanks for the explanation, @zackw. I didn’t expect the stack unwinder was such a complicated component.

Does LLVM provide a similar library?

I didn’t propose to rewrite the whole library for general purpose. What if the unwinder is specific for Rust programs? We don’t have to support many architectures.

I don't know, but if it does, it's going to be just as nasty as the one from GCC.

FFI means that doesn't help any.

LLVM has its own libunwind. It’s written (mostly) in C++, and some assembly.

https://github.com/main-- (perhaps this is @main?) and I have been talking about collaborating on a pure-Rust stack walker and unwinder (discussion here: https://github.com/gimli-rs/gimli/issues/248)

We have a bunch of infrastructural pieces in place already:

  • gimli can already parse .eh_frame sections and evaluate the unwinding info.

  • findshlibs is a wrapper over dl_iterate_phdr on Linux and dyld APIs on macos. It let’s you find the already-mapped-in-memory .eh_frame section for each shared library and executable, so it doesn’t need to be re-mapped.

We’re still not very far with the actual stack walking and unwinding built on top of that infrastructure. Part of what we need to do is create a canonical repo and merge our two separate efforts we each previously started.

If anyone else would like to help out, let me know! :slight_smile: This is currently moving fairly slowly, at a rare-block-of-free-time pace. Another contributor or two could help speed it up :wink:

2 Likes

I came up this question when looking at dependencies of a Rust binary.

@fitzgen Glad to hear that someone starts working on that. Thank you! Hopefully, we can get rid of libunwind in the future. I’m pretty new to Rust and unwind mechanism, and I’m not sure if I can help.

naïve noob, sorry, so:

  • is it sensible to unwind over FFI boundary?
  • wouldn't that other library leave our RAM in an unpredictable state?
  • isn't unwinding supposed to only work reliably and be useful in pure-Rust world?

It’s undefined behavior to panic over FFI boundaries, but you can still get a backtrace.

1 Like

Yes! There is no obvious reason why it shouldn't be possible to unwind across languages in a multi-language application.

Of course any valid implementation would always have to make sure that destructors are run properly and frames are unwound correctly. This is a problem, but not a very hard one - as Rust uses the C++ unwinder right now, it already has some basic compatibility - it's just not guaranteed and if you try to catch a C++ exception in Rust, the runtime gets very confused (it expects a Rust panic but there is none).

Yes, unwinding from Rust through FFI boundaries (or vice versa) is undefined behavior right now. But an RFC can of course change that!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.