Skip to content

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

Description

@bearmate

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)

Activity

  1. added
    A-linkageArea: linking into static, shared libraries and binaries
    O-windows-msvcToolchain: MSVC, Operating system: Windows
    on Sep 11, 2018
  2. added
    C-bugCategory: This is a bug.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jul 19, 2019
  3. Erzawenn commented on Aug 16, 2019

    @Erzawenn

    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!();
    }
  4. bearmate commented on Aug 17, 2019

    @bearmate
    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?

  5. Berrysoft commented on Mar 28, 2021

    @Berrysoft
    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.

  6. added 2 commits that reference this issue on Apr 5, 2021
    52437be
    063fe40
  7. rylev commented on May 19, 2021

    @rylev
    Contributor

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

  8. added a commit that references this issue on Mar 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binariesC-bugCategory: This is a bug.O-windows-msvcToolchain: MSVC, Operating system: WindowsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions