如何手动提供core::panicking::panic*给lld?
How to manually provide core::panicking::panic* to lld?
我正在将 rlib 的 Rust 代码编译为 LLVM IR,然后使用 Clang 编译 & link 它与 C 程序。这一直有效,直到我的代码包含恐慌,此时我得到 linker 错误:
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)
我尝试了两种方法来缓解这种情况:
我已将 panic_handler
添加到我的图书馆:
use core::panic::PanicInfo;
#[panic_handler]
pub extern fn panic(_: &PanicInfo<'_>) -> ! {
loop{}
}
我在 Cargo.toml
:
中将 panic
模式设置为 abort
[profile.release]
panic = "abort"
单独或组合都不能解决问题。
更多详情
在评论中,@Solomon Ucko 要求提供有关整个编译管道的更多详细信息。正如我在标签中所写,这是 no_std
;另外,编译目标是MOS 6502。这是要编译和(尝试)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
基于 ,我通过将 -Z build-std
传递给 Cargo 来解决这个问题,从而从 Rust 的 core
库中获取 LLVM IR,并将其链接进去。
但后来我意识到我可以做得更好,并避免 -Z std
强加的长时间编译,只需采用以下定义
core::panicking::panic_bounds_check
和 core::panicking::panic
来自这些 IR 文件,简化了它们的主体,并将它们添加到手写的 panic.ll
文件中:
%"panic::location::Location" = type { { [0 x i8]*, i64 }, i32, i32 }
; core::panicking::panic
; Function Attrs: cold noinline noreturn nounwind nonlazybind
define void @_ZN4core9panicking5panic17hd695e3b1d0dd4ef4E([0 x i8]* noalias nonnull readonly align 1 %expr.0, i64 %expr.1, %"panic::location::Location"* noalias readonly align 8 dereferenceable(24) %0) unnamed_addr #22 {
start:
unreachable
}
; core::panicking::panic_bounds_check
; Function Attrs: cold noinline noreturn nounwind nonlazybind
define void @_ZN4core9panicking18panic_bounds_check17hc3a71010bf41c72dE(i64 %0, i64 %1, %"panic::location::Location"* noalias readonly align 8 dereferenceable(24) %2) unnamed_addr #22 {
start:
unreachable
}
TBH 我不确定它有多健壮(也许他们应该在“无法访问”之前通过分支循环到 start
?),但至少它让我得到了一个完全链接和可运行的程序。
我正在将 rlib 的 Rust 代码编译为 LLVM IR,然后使用 Clang 编译 & link 它与 C 程序。这一直有效,直到我的代码包含恐慌,此时我得到 linker 错误:
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)
我尝试了两种方法来缓解这种情况:
我已将
panic_handler
添加到我的图书馆:use core::panic::PanicInfo; #[panic_handler] pub extern fn panic(_: &PanicInfo<'_>) -> ! { loop{} }
我在
中将Cargo.toml
:panic
模式设置为abort
[profile.release] panic = "abort"
单独或组合都不能解决问题。
更多详情
在评论中,@Solomon Ucko 要求提供有关整个编译管道的更多详细信息。正如我在标签中所写,这是 no_std
;另外,编译目标是MOS 6502。这是要编译和(尝试)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
基于 -Z build-std
传递给 Cargo 来解决这个问题,从而从 Rust 的 core
库中获取 LLVM IR,并将其链接进去。
但后来我意识到我可以做得更好,并避免 -Z std
强加的长时间编译,只需采用以下定义
core::panicking::panic_bounds_check
和 core::panicking::panic
来自这些 IR 文件,简化了它们的主体,并将它们添加到手写的 panic.ll
文件中:
%"panic::location::Location" = type { { [0 x i8]*, i64 }, i32, i32 }
; core::panicking::panic
; Function Attrs: cold noinline noreturn nounwind nonlazybind
define void @_ZN4core9panicking5panic17hd695e3b1d0dd4ef4E([0 x i8]* noalias nonnull readonly align 1 %expr.0, i64 %expr.1, %"panic::location::Location"* noalias readonly align 8 dereferenceable(24) %0) unnamed_addr #22 {
start:
unreachable
}
; core::panicking::panic_bounds_check
; Function Attrs: cold noinline noreturn nounwind nonlazybind
define void @_ZN4core9panicking18panic_bounds_check17hc3a71010bf41c72dE(i64 %0, i64 %1, %"panic::location::Location"* noalias readonly align 8 dereferenceable(24) %2) unnamed_addr #22 {
start:
unreachable
}
TBH 我不确定它有多健壮(也许他们应该在“无法访问”之前通过分支循环到 start
?),但至少它让我得到了一个完全链接和可运行的程序。