Skip to content
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

Compiling std for UEFI with panic=abort fails #98133

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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