I am compiling the Rust code of an rlib to LLVM IR, and then using Clang to compile & link it with a C program. This works until my code contains panics, at which point I get linker errors:
ld.lld: error: undefined symbol: core::panicking::panic_bounds_check::hc3a71010bf41c72d
>>> referenced by ld-temp.o
>>> lto.tmp:(run)
>>> referenced by ld-temp.o
>>> lto.tmp:(run)
>>> referenced by ld-temp.o
>>> lto.tmp:(run)
>>> referenced 11 more times
ld.lld: error: undefined symbol: core::panicking::panic::hd695e3b1d0dd4ef4
>>> referenced by ld-temp.o
>>> lto.tmp:(run)
clang: error: ld.lld command failed with exit code 1 (use -v to see invocation)
I have tried two things to mitigate this:
I have added a
panic_handler
to my library:use core::panic::PanicInfo; #[panic_handler] pub extern fn panic(_: &PanicInfo<'_>) -> ! { loop{} }
I have set the
panic
mode toabort
in myCargo.toml
:[profile.release] panic = "abort"
Neither on its own, nor combined, solves the issue.
Further details
In the comments, @Solomon Ucko requested more details on the whole compilation pipeline. As I wrote in the tags, this is with no_std
; also, the compilation target is MOS 6502. This is the full list of commands to compile and (try to) link:
llvm-mos/bin/clang --config llvm-mos-sdk/build/commodore/64.cfg \
-O2 -c \
-o _build/main.c.o \
src/main.c
cargo rustc --release -- \
-C debuginfo=0 -C opt-level=1 --emit=llvm-ir
llvm-mos/bin/clang --config llvm-mos-sdk/build/commodore/64.cfg \
-O2 \
-o _build/charset.prg \
_build/main.c.o \
target/release/deps/chip8_c64-e21ff59526dd729a.ll
Based on this answer, I worked around this by passing
-Z build-std
to Cargo, thereby getting the LLVM IR from Rust'score
library, and linking it in.But then I realized I can do one better, and avoid the long compilation time imposed by
-Z std
, by just taking the definitions ofcore::panicking::panic_bounds_check
andcore::panicking::panic
from these IR files, simplifying their body, and adding them to a hand-writtenpanic.ll
file:TBH I'm not sure how robust that is (maybe they should loop by branchin to
start
before `unreachable?), but at least it got me to a fully linked and runnable program.