-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
ld64.lld: error: too many personalities (4) for compact unwind to encode #102754
Comments
So, uh, wouldn’t this code basically mean that you cannot link a binary that consists of more than 3 languages with their own unwinding personalities? That seems like an unfortunate limitation, and I would argue that this is something As for why the A workaround on our end could probably be to make sure these personality functions end up in a CU of their own. |
Does this happen with other linkers (e.g. |
It doesn't happen with ld64, but the resulting binary only lists 3 personalities as per |
Should this be labeled regression-stable-to-beta or something? |
WG-prioritization assigning priority (Zulip discussion). @rustbot label -I-prioritize +P-critical |
The LLVM bug has a fix for lld. |
@glandium do you have a link for the bug fix? |
btw - why is |
This comment says it's because the distributed core/std libraries are compiled with panic=unwind and need an Now, maybe it shouldn't be exported from a staticlib with that resolution having already happened? |
It seems like this is actually having the reverse of the intended effect. The real problem is the lld bug, but adding this in when it isn't actually required doesn't seem great to me. |
Does the lld fix need a backport to our LLVM fork? |
I don't believe that would fix our issue because the error occurs during the final link of the rust static lib to chromium (which uses llvm 16). For us, we either need a fix in rust (don't export the unused and unnecessary symbol) or wait for the lld fix to land in chromium |
|
@estebank suggested that we should make a note of this known |
@glandium did you test the llvm fix? It doesn't seem to be working for me for some reason. I just built using https://chromium.googlesource.com/a/external/github.com/llvm/llvm-project/+/refs/heads/llvmorg-16-init-8697-g60809cd2 which contains the fix https://chromium.googlesource.com/a/external/github.com/llvm/llvm-project/+/refs/heads/llvmorg-16-init-8697-g60809cd2/lld/test/MachO/eh-frame-personality-dedup.s |
this only handles the case of synthetic symbols |
also we still have the issue where rust stack traces are sometimes garbled (which seems likely to be related) and I'm not sure how to address that with no way to change the rust personality routine. We can test it (for now) by building std with abort, but even that option will apparently go away soon and we would have to patch rust if we wanted to change it |
I think you should open a separate issue for that. |
I agree it's a separate issue, but I strongly suspect it's related. |
With enough people using rust, uncommon situations will happen with increasing frequency. I'm really struggling to understanding why you'd want to keep this known limitation that some people will encounter. There are a lot of things I've never personally seen and yet I know they exist, sometimes in large numbers. |
I don't think that any cross platform app trivializes the set of applications that could be affected by this |
Can you explain a bit more here? I'm not seeing how modifying the assembly can produce the same effect without the custom personality function. There will be an exception handler which is the problem that the custom function addresses. From the issue:
|
As I understand if __gxx_personality_v0 is used with the call site table empty, the personality function will call |
but as it says in the issue there is an exception handler in CFRunLoopRunSpecific which causes the exception to be re-thrown and that's what causes the problem with the stack trace. My understanding is that the chromium personality function short circuits the exception handler search and then the default personality function works as you describe because it functions as if the call site table is empty when it's not. |
I think I found a hacky workaround by renaming |
@bridiver Have you tried my suggested solution?
This should result in exactly the same behavior as the custom personality function while using one less total personality function in the program. (Once this is confirmed to work, the assembly code can be further simplified, such as by removing the unnecessary catch clauses.) |
That doesn't work, but I should have followed up because my description of the correct behavior was actually incorrect. I created a small test exe that contains only libbase.a (which contains the chromium personality function) and libbrave_rust.a and this is the output of triggering an objc exception inside
With your proposed change what I get in Brave is
which is the same thing I am currently getting in Brave with the change I described because there is still some dependency issue that is causing it to search libbrave_rust.a before libbase.a and is also similar to what I get in my test exe if I list libbrave_rust.a before libbase.a. Things get very complicated when building all of chromium + Brave so I'm starting from something simple and slowly adding dependencies to try to figure out what is causing the difference between my small test app and Brave. |
I am not having any luck getting this to work. None of the above suggestions work and in general the inability to build a rust static library without rust_eh_personality is becoming really problematic for us. |
Cc'ing @pcwalton for help -- we use Rust in Brave's Chromium fork. IIUC, using C, Objective-C, and Rust in the same exe uses up all three personalities for compact unwind, and naively we need a fourth. Thanks. |
@bjorn3 I tried build-std with panic=abort, but the "in the future" change is not in the future, that is exactly the change that broke things for us and rust_eh_personality is still exported 5ff0876 Instead of the original stub implementation, could this be implemented as a weak_import and some option not to include the symbol in the output? Maybe something like |
I found a workaround for now which is to use |
That sounds like the right solution for now. I don't think that Rust aborts would have UB—they would kill the process safely. (I don't have much to add to this issue beyond what's already been discussed, fwiw) |
@pcwalton are you sure about that? It sounds like the entire reason for making this change to move it into std and always include it is because it did have UB at least in some cases? In any case I got it working by leaving |
So based on what I have working, I think this could be very easily implemented by moving the implementation of |
I have a guess for a solution. There is I don't see an option to tell LLVM to not emit compact unwind in the first place. If it exists, though, the post-processing with The unwinder should be able to deal with DWARF unwind, because even when compact unwind is enabled, it can't encode all situations and needs DWARF as a fallback anyways. |
Ultimately, this is an Apple ABI issue, but I don't know whether that'll ever be fixed. They only allow 3 personalities to be used in compact-unwind in a single shared-object. And the system already has 3 canonical personalities already ( Because of this, I'd like to propose a change to LLVM to only emit compact unwind when using one of those 3 canonical Apple-shipped personality functions. That should fix this issue "once and for all" (for non-rust uses as well), but does mean Rust code would use DWARF unwind for all functions -- even if the program being linked doesn't happen to require all 3 of the "official" personalities. Which is a bit unfortunate, but presumably not terrible. |
This issue is now a blocker for Rust integration into Chromium mainline. We can try some of the workarounds here, and I am just starting to explore the space. Thanks for all the information here so far. |
…onality symbols. For the rest, use DWARFs. Details: rust-lang/rust#102754 The MachO format uses 2 bits to encode these personality funtions, with 0 reserved for "no-personality". This means we can only have up to 3 personality. There are already three popular personalities: __gxx_personality_v0, __gcc_personality_v0, and __objc_personality_v0. As a result, any system that needs custom-personality will run into a problem. This patch implemented jyknight's proposal to simply force DWARFs for all non-canonical personality functions. Differential Revision: https://reviews.llvm.org/D144999
The patch implementing jyknight's proposal (with slight modification*) has landed. We should be able to have more than 3 personalities symbols now. (*) In stead of making From a user's perspective, this feature requires no tweaking of any new flag - should "just work". |
@oontvoo Hello, when we introduce the rust library into the iOS project, there will be a compilation error. I see that the above problem may be the same, but I tried it and it didn't work. |
For anyone else coming to this issue when trying to build a project in Xcode, I believe it's fixed/mitigated in Xcode 15. Not sure if it's properly fixed in Xcode 15, but my project now builds when targeting |
When mixing ObjC, C++ and Rust in the same binary on aarch64-apple-darwin targets (e.g. like in Firefox), lld from LLVM 15 complains about "too many personalities". This is a regression from #92845 and affects beta.
For some reason, since #92845, this code in lld is hit: https://github.com/llvm/llvm-project/blob/d30dccd21f2c3bc1ed6cd054c131436a1af548e1/lld/MachO/UnwindInfoSection.cpp#L300
Ultimately, this leads to https://github.com/llvm/llvm-project/blob/d30dccd21f2c3bc1ed6cd054c131436a1af548e1/lld/MachO/UnwindInfoSection.cpp#L378
where there are 4 personalities instead of 3:
___objc_personality_v0
,___gxx_personality_v0
,_rust_eh_personality
<internal>
With previous rust versions, only the first three ones would be there. It looks like the relocation that triggers the
<internal>
is related to therust_eh_personality
function inlibrary/std/src/personality/gcc.rs
itself.STR:
bar.cc
file with content:foo.m
file with content:qux.rs
file with content:Makefile
file with content:$PATH
.SDKROOT
to point to a macOS SDKmake
This does not happen on x86_64-apple-darwin, but interestingly the list of personalities there is:
___objc_personality_v0
,___gxx_personality_v0
,<internal>
(no
_rust_eh_personality
).With rust 1.64, the list of personalities was:
___objc_personality_v0
,___gxx_personality_v0
,_rust_eh_personality
The text was updated successfully, but these errors were encountered: