Description
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 the rust_eh_personality
function in library/std/src/personality/gcc.rs
itself.
STR:
- Create a
bar.cc
file with content:
#include <stdexcept>
extern "C" void qux();
void bar() { qux(); throw std::runtime_error("foo"); }
- Create a
foo.m
file with content:
void foo() { @try {} @finally {} }
- Create a
qux.rs
file with content:
#![crate_type = "staticlib"]
extern "C" {
fn foo();
}
#[no_mangle]
pub unsafe extern "C" fn qux() {
println!("foo");
foo();
}
- Create a
Makefile
file with content:
TARGET = --target=aarch64-apple-darwin
lib.dylib: bar.o foo.o libqux.a
clang++ -o $@ $^ -fuse-ld=lld -dynamiclib $(TARGET) -lobjc
bar.o: bar.cc
clang++ -o $@ -c $^ $(TARGET)
foo.o: foo.m
clang -o $@ -c $^ $(TARGET)
libqux.a: qux.rs
rustc $^ $(TARGET)
- Get clang 15 + lld and make sure it's in your
$PATH
. - Set
SDKROOT
to point to a macOS SDK - Run
make
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
Activity
nagisa commentedon Oct 9, 2022
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
ld.lld
should be fixing, regardless.As for why the
<internal>
gets constructed, I would imagine that with the move of the personality intolibstd
one of the codegen units now starts containing both the personality function and the functionality that depends on that personality (whereas before nothing in the standalone unwinding crate could unwind and thus did not reference the personality function.)A workaround on our end could probably be to make sure these personality functions end up in a CU of their own.
nagisa commentedon Oct 9, 2022
Does this happen with other linkers (e.g.
ld
that ships with Xcode, if it is something other thanlld
?)glandium commentedon Oct 10, 2022
It doesn't happen with ld64, but the resulting binary only lists 3 personalities as per
llvm-object --unwind-info
...glandium commentedon Oct 11, 2022
Should this be labeled regression-stable-to-beta or something?
apiraino commentedon Oct 11, 2022
WG-prioritization assigning priority (Zulip discussion).
@rustbot label -I-prioritize +P-critical
89 remaining items