Skip to content

Compiling std for UEFI with panic=abort fails #98133

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
Ayush1325 opened this issue Jun 15, 2022 · 4 comments
Closed

Compiling std for UEFI with panic=abort fails #98133

Ayush1325 opened this issue Jun 15, 2022 · 4 comments
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@Ayush1325
Copy link
Contributor

Ayush1325 commented Jun 15, 2022

I am trying to implement std for the UEFI targets as a part of my GSoC project. I am currently trying to build std using the #![feature(restricted_std)]. When I try to compile std along with panic_abort, I get the following error:

error: linking with `rust-lld` failed: exit status: 1
  |
  = note: "rust-lld" "-flavor" "link" "/NOLOGO" "/entry:efi_main" "/subsystem:efi_application" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.1wmkhau9wf5mggc4.rcgu.o" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.2dbrudlb642mvcxh.rcgu.o" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.390rrbcz9df7m17.rcgu.o" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.3yl41t6ohz1j19lz.rcgu.o" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.4ndg5iuai60vb1e.rcgu.o" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.4z4woxftcrn577kv.rcgu.o" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.29upyblqtj4qjy9c.rcgu.o" "/LIBPATH:/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps" "/LIBPATH:/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/debug/deps" "/LIBPATH:/var/home/ayush/Documents/Programming/Rust/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-uefi/lib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libr_efi-9860c65d670ddb26.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libstd-818bb3edb226311d.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libpanic_abort-b537655868a6eb10.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/librustc_demangle-fbd85641d8aabb11.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libstd_detect-fab2f0e1b867d822.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libhashbrown-25dd1101220abe44.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/librustc_std_workspace_alloc-e0f3f68f61f3a7ec.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libunwind-67271849d17a208b.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libcfg_if-6c94eec96134b1f2.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/liblibc-04c66ae9b882fddc.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/liballoc-31f22b8597517001.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/librustc_std_workspace_core-28288f540a1df2c0.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libcore-a891fd5a4b0f6ffd.rlib" "/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/libcompiler_builtins-e1dc617638fd0a75.rlib" "/NXCOMPAT" "/LIBPATH:/var/home/ayush/Documents/Programming/Rust/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-uefi/lib" "/OUT:/var/home/ayush/Documents/Programming/Rust/uefi/hello_world/target/x86_64-unknown-uefi/debug/deps/hello_world-86b7bdb62ca4e356.efi" "/OPT:REF,NOICF" "/DEBUG" "/NODEFAULTLIB"
  = note: rust-lld: error: undefined symbol: __CxxFrameHandler3
          >>> referenced by libstd-818bb3edb226311d.rlib(std-818bb3edb226311d.std.d4a9d80c-cgu.2.rcgu.o):(.xdata)
          >>> referenced by libstd-818bb3edb226311d.rlib(std-818bb3edb226311d.std.d4a9d80c-cgu.2.rcgu.o):(.xdata)

This error of course is caused due to the UEFI target having "is-like-msvc": true in the target.json.

I know it can be fixed by adding a blank implementation for __CxxFrameHandler3:

#[no_mangle]
pub extern "C" fn __CxxFrameHandler3() {}

I wanted to ask if this is expected behavior or a bug? I thought setting panic=abort should mean that I don't need unwinding.

Here is my .cargo/config.toml:

[unstable]
build-std = ["compiler_builtins", "panic_abort", "std"]
build-std-features = ["compiler-builtins-mem"]

[build]
target = "x86_64-unknown-uefi"

Cargo.toml

[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
r-efi = "4.0"

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"
@Ayush1325 Ayush1325 added the C-bug Category: This is a bug. label Jun 15, 2022
@eggyal
Copy link
Contributor

eggyal commented Jun 15, 2022

Unless a crate defines the eh_personality lang item (stdlib does not: it's typically defined in the panic_unwind library, which is only linked with -Cpanic=unwind), the complier expects the personality function to be provided upstream. For targets that use Dwarf unwinding, the symbol is named rust_eh_personality; for MSVC-like targets (such as UEFI) that use SEH unwinding, it's named __CxxFrameHandler3 (see rustc_codegen_llvm::MiscMethods::eh_personality).

When using -Cpanic=abort, the compiler links in the panic_abort library which provides a dummy rust_eh_personality function; I think it should probably be modified, for MSVC-like targets, to provide a dummy __CxxFrameHandler3 function instead:

// This... is a bit of an oddity. The tl;dr; is that this is required to link
// correctly, the longer explanation is below.
//
// Right now the binaries of libcore/libstd that we ship are all compiled with
// `-C panic=unwind`. This is done to ensure that the binaries are maximally
// compatible with as many situations as possible. The compiler, however,
// requires a "personality function" for all functions compiled with `-C
// panic=unwind`. This personality function is hardcoded to the symbol
// `rust_eh_personality` and is defined by the `eh_personality` lang item.
//
// So... why not just define that lang item here? Good question! The way that
// panic runtimes are linked in is actually a little subtle in that they're
// "sort of" in the compiler's crate store, but only actually linked if another
// isn't actually linked. This ends up meaning that both this crate and the
// panic_unwind crate can appear in the compiler's crate store, and if both
// define the `eh_personality` lang item then that'll hit an error.
//
// To handle this the compiler only requires the `eh_personality` is defined if
// the panic runtime being linked in is the unwinding runtime, and otherwise
// it's not required to be defined (rightfully so). In this case, however, this
// library just defines this symbol so there's at least some personality
// somewhere.
//
// Essentially this symbol is just defined to get wired up to libcore/libstd
// binaries, but it should never be called as we don't link in an unwinding
// runtime at all.
pub mod personalities {
#[rustc_std_internal_symbol]
#[cfg(not(any(
all(target_family = "wasm", not(target_os = "emscripten")),
all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
)))]
pub extern "C" fn rust_eh_personality() {}
// On x86_64-pc-windows-gnu we use our own personality function that needs
// to return `ExceptionContinueSearch` as we're passing on all our frames.
#[rustc_std_internal_symbol]
#[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86_64"))]
pub extern "C" fn rust_eh_personality(
_record: usize,
_frame: usize,
_context: usize,
_dispatcher: usize,
) -> u32 {
1 // `ExceptionContinueSearch`
}
// Similar to above, this corresponds to the `eh_catch_typeinfo` lang item
// that's only used on Emscripten currently.
//
// Since panics don't generate exceptions and foreign exceptions are
// currently UB with -C panic=abort (although this may be subject to
// change), any catch_unwind calls will never use this typeinfo.
#[rustc_std_internal_symbol]
#[allow(non_upper_case_globals)]
#[cfg(target_os = "emscripten")]
static rust_eh_catch_typeinfo: [usize; 2] = [0; 2];
// These two are called by our startup objects on i686-pc-windows-gnu, but
// they don't need to do anything so the bodies are nops.
#[rustc_std_internal_symbol]
#[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
pub extern "C" fn rust_eh_register_frames() {}
#[rustc_std_internal_symbol]
#[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
pub extern "C" fn rust_eh_unregister_frames() {}
}

@rustbot label +A-runtime +T-libs

@rustbot rustbot added A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 15, 2022
@Ayush1325
Copy link
Contributor Author

Hi @eggyal , I no longer seem to be getting the error from the latest master.

Previously I was using a v1.61.0 commit. So maybe it was fixed after that?

@eggyal
Copy link
Contributor

eggyal commented Jun 15, 2022

Possibly fixed by #96959 ?

@Ayush1325
Copy link
Contributor Author

@eggyal. Maybe, and it seems to be a much better approach than what I was doing. I am closing this issue for now.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants