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

Missing symbol in no_std application on panic (windows-msvc) #54137

Closed
bearmate opened this issue Sep 11, 2018 · 4 comments
Closed

Missing symbol in no_std application on panic (windows-msvc) #54137

bearmate opened this issue Sep 11, 2018 · 4 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-windows-msvc Toolchain: MSVC, Operating system: Windows T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@bearmate
Copy link

bearmate commented Sep 11, 2018

A no_std application with the panic strategy set to abort and a panic_handler defined still needs the symbol "__CxxFrameHandler3" if a panic is invoked. The toolchain is nightly-x86_64-pc-windows-msvc.

A sample failing to compile due to this can be found at this repository. It contains a minimal implementation of a no_std binary for windows with stubs for the needed memory functions and the panic_handler.

#![no_std]
#![no_main]
#![feature(panic_handler)]

use core::panic::PanicInfo;

#[panic_handler]
fn handle_panic(_: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8, _src: *const u8, _n: usize) -> *mut u8 {
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8, _src: *const u8, _n: usize) -> *mut u8 {
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memset(mem: *mut u8, _val: i32, _n: usize) -> *mut u8 {
    mem
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(_mem1: *const u8, _mem2: *const u8, _n: usize) -> i32 {
    0
}

#[no_mangle]
pub extern "C" fn mainCRTStartup() -> ! {
    main()
}

#[no_mangle]
pub extern "C" fn main() -> ! {
    panic!()
}

I expected the application to compile just fine, because a panic_handler is defined and the panic strategy is set to "abort".

Instead I get a linker error complaining about the missing symbol "__CxxFrameHandler3". This only occurs if panic! is called. If I instead just loop forever in the main function, the compiler will return no error and work just fine.

Meta

PS D:\prj\test\no-std-minimal> cargo build --verbose
   Compiling no-std-minimal v0.1.0 (file:///D:/prj/test/no-std-minimal)
     Running `rustc --crate-name no_std_minimal src\main.rs --crate-type bin --emit=dep-info,link -C panic=abort -C debuginfo=2 -C metadata=f00f98cc62ddcb51 -C extra-filename=-f00f98cc62ddcb51 --out-dir D:\prj\test\no-std-minimal\target\debug\deps -C incremental=D:\prj\test\no-std-minimal\target\debug\incremental -L dependency=D:\prj\test\no-std-minimal\target\debug\deps`
error: linking with `link.exe` failed: exit code: 1120
  |
  = note: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.13.26128\\bin\\HostX64\\x64\\link.exe" "/NOLOGO" "/NXCOMPAT" "/LIBPATH:C:\\Users\\bruno\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib" "D:\\prj\\test\\no-std-minimal\\target\\debug\\deps\\no_std_minimal-f00f98cc62ddcb51.4kfg7hloiv5kxloy.rcgu.o" "/OUT:D:\\prj\\test\\no-std-minimal\\target\\debug\\deps\\no_std_minimal-f00f98cc62ddcb51.exe" "/OPT:REF,NOICF" "/DEBUG" "/NATVIS:C:\\Users\\bruno\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\intrinsic.natvis" "/NATVIS:C:\\Users\\bruno\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\liballoc.natvis" "/NATVIS:C:\\Users\\bruno\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\libcore.natvis" "/LIBPATH:D:\\prj\\test\\no-std-minimal\\target\\debug\\deps" "/LIBPATH:C:\\Users\\bruno\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib" "C:\\Users\\bruno\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libcore-68a97103729b5fa4.rlib" "C:\\Users\\bruno\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libcompiler_builtins-8c450e159daacabd.rlib"
  = note: Non-UTF-8 output: libcore-68a97103729b5fa4.rlib(core-68a97103729b5fa4.core.d33te014-cgu.15.rcgu.o) : error LNK2001: Nicht aufgel\xf6stes externes Symbol \"__CxxFrameHandler3\".\r\nD:\\prj\\test\\no-std-minimal\\target\\debug\\deps\\no_std_minimal-f00f98cc62ddcb51.exe : fatal error LNK1120: 1 nicht aufgel\xf6ste Externe\r\n

error: aborting due to previous error

error: Could not compile `no-std-minimal`.

Caused by:
  process didn't exit successfully: `rustc --crate-name no_std_minimal src\main.rs --crate-type bin --emit=dep-info,link -C panic=abort -C debuginfo=2 -C metadata=f00f98cc62ddcb51 -C extra-filename=-f00f98cc62ddcb51 --out-dir D:\prj\test\no-std-minimal\target\debug\deps -C incremental=D:\prj\test\no-std-minimal\target\debug\incremental -L dependency=D:\prj\test\no-std-minimal\target\debug\deps` (exit code: 1)
@estebank estebank added A-linkage Area: linking into static, shared libraries and binaries O-windows-msvc Toolchain: MSVC, Operating system: Windows labels Sep 11, 2018
@jonas-schievink jonas-schievink added C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 19, 2019
@Erzawenn
Copy link

I'm facing the same issue with stable version 1.36. I don't know if it is an issue in the documentation which doesn't state that on Windows, you have to link with CRT or in the crate panic_abort that doesn't define this symbole on msvc starget.

In src\librustc_codegen_llvm\context.rs, a different name is defined for rust_eh_personality:

       let llfn = match tcx.lang_items().eh_personality() {
            Some(def_id) if !wants_msvc_seh(self.sess()) => {
                resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
            }
            _ => {
                let name = if wants_msvc_seh(self.sess()) {
                    "__CxxFrameHandler3"
                } else {
                    "rust_eh_personality"
                };
                let fty = self.type_variadic_func(&[], self.type_i32());
                self.declare_cfn(name, fty)
            }
        };

But, unfortunatly, in crate libpanic_abort, rust_eh_personality is inconditionnaly defined.

Two examples of code that compiles:

  • with CRT linkage
#![cfg(target_os = "windows")]
#![no_std]
#![no_main]
#![windows_subsystem = "console"]

use core::panic::PanicInfo;

// required by no_std
#[panic_handler]
fn handle_panic(_info: &PanicInfo) -> ! {
    loop {}
}

// linkage to CRT library according to crt-static flag set in .cargo/config:
// [target.x86_64-pc-windows-msvc]
// rustflags = ["-C", "target-feature=+crt-static"]
#[cfg(target_feature = "crt-static")]
#[link(name = "libcmt")]
extern {}
#[cfg(not(target_feature = "crt-static"))]
#[link(name = "msvcrt")]
extern {}

// CRT is used, the entry point is main
#[no_mangle]
pub extern "C" fn main() -> i32 {
    panic!();
}
  • with symbole __CxxFrameHandler3
#![cfg(target_os = "windows")]
#![no_std]
#![no_main]
#![windows_subsystem = "console"]

use core::panic::PanicInfo;

// required by no_std
#[panic_handler]
fn handle_panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub unsafe extern "C" fn memset(mem: *mut u8, _val: i32, _n: usize) -> *mut u8 {
    mem
}

#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8, _src: *const u8, _n: usize) -> *mut u8 {
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(_mem1: *const u8, _mem2: *const u8, _n: usize) -> i32 {
    0
}

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

// no CRT and console subsystem => the entry point is mainCRTStartup
#[no_mangle]
pub extern "C" fn mainCRTStartup() -> ! {
    panic!();
}

@bearmate
Copy link
Author

From the comments it looks like __CxxFrameHandler3 is used as the personality function on msvc to convince LLVM to use SEH instead of Dwarf exception handling, so it does not inject a dependency to _Unwind_Resume. Is this even necessary for panic=abort? Couldn't we keep rust_eh_personality on msvc if panic=abort and everything would work fine?

@Berrysoft
Copy link
Contributor

Could we just forward to __CxxFrameHandler3 in rust_eh_personality, and remove the requirement of __CxxFrameHandler3 in context.rs? I'll try to do that later.

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Apr 5, 2021
Add `__CxxFrameHandler3` in `panic_abort`

Fix rust-lang#54137

<del>I initially tried to forward to `__CxxFrameHandler3` from `rust_eh_personality`, but later I found that LLVM uses handler names to distinguish exception type. Therefore I choose to add `__CxxFrameHandler3` in `panic_abort`. Anyway it solves the link problem, and this function will never be called.</del>

It seems that the original issue was solved, but still adding these tests.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Apr 5, 2021
Add `__CxxFrameHandler3` in `panic_abort`

Fix rust-lang#54137

<del>I initially tried to forward to `__CxxFrameHandler3` from `rust_eh_personality`, but later I found that LLVM uses handler names to distinguish exception type. Therefore I choose to add `__CxxFrameHandler3` in `panic_abort`. Anyway it solves the link problem, and this function will never be called.</del>

It seems that the original issue was solved, but still adding these tests.
@rylev
Copy link
Member

rylev commented May 19, 2021

Going to close this as this no longer seems to be an issue. See here for more information.

@rylev rylev closed this as completed May 19, 2021
BatmanAoD added a commit to BatmanAoD/panic-abort that referenced this issue Mar 25, 2023
'main.rs' code copied from:
rust-lang/rust#54137
@Enselic Enselic marked this as a duplicate of #62795 Dec 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-windows-msvc Toolchain: MSVC, Operating system: Windows T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants