rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.64k stars 12.63k forks source link

Linker error for cdylib with panic=abort (Undefined symbol "_rust_eh_personality_catch") #34472

Open SSheldon opened 8 years ago

SSheldon commented 8 years ago

If I attempt to compile a crate as a cdylib with panic=abort, I get the following error:

error: linking with `cc` failed: exit code: 1
note: Undefined symbols for architecture x86_64:
  "_rust_eh_personality_catch", referenced from:
     -exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I'm using rustc 1.11.0-nightly (ad7fe6521 2016-06-23) on OSX 10.11.5.

I can repro by compiling an empty lib.rs with rustc lib.rs --crate-type cdylib -C panic=abort or with a Cargo.toml like the following:

[package]
name = "foo"
version = "0.0.0"

[lib]
crate-type = ["cdylib"]

[profile.release]
panic = "abort"
SSheldon commented 8 years ago

cc @alexcrichton since you've worked on both cdylib (#33553) and panic=abort (#32900) 😊

alexcrichton commented 8 years ago

Oh dear sounds bad! Not sure how this got past the bots...

Looks like this isn't a problem on Linux (yay linker shenanigans!) but we're erroneously claiming that this symbol is exported from the cdylib when it's not even contained. I believe I see the error and I'll try to have a patch shortly.

alexcrichton commented 8 years ago

Er, maybe I won't have a chance to get around to this soon :(. As an explanation of the problem, though:

So the problem here is that the loop over crates is looping over all crates, not the crates that are linked. When dealing with panic runtimes and allocators we have crates in the crate store which aren't actually linked, because some output formats may have them linked but others may not.

The fix here will probably be just ensuring that when generating the set of reachable symbols for a particular output type we only consider those crates being linked for that output type, not all crates in the world. There's a bit of refactoring here that may need to happen because the reachable set of symbols is also used for LTO, but the principle of the solution should remain the same.

I certainly wouldn't mind helping out anyone fix this if I don't end up getting around to it.

Mark-Simulacrum commented 7 years ago

From what I can tell, on macOS today, rustc --crate-type=cdylib -Cpanic=abort test.rs completes successfully. However, the file generated is only 4 KB in size compared to the 4 MB on Linux. I suspect this is because the file is practically empty (see below for objdump). Indeed, it seems that we now are in a worse situation -- we appear to have been successful, but in fact it seems that linking and/or compilation failed.

$ objdump -s libtest.dylib
libtest.dylib:  file format Mach-O 64-bit x86-64

Contents of section __text:
 0fb0 554889e5 5dc3                        UH..].
Contents of section __unwind_info:
 0fb8 01000000 1c000000 00000000 1c000000  ................
 0fc8 00000000 1c000000 02000000 b00f0000  ................
 0fd8 34000000 34000000 b70f0000 00000000  4...4...........
 0fe8 34000000 03000000 0c000100 10000100  4...............
 0ff8 00000000 00000000                    ........
bjorn3 commented 2 years ago

I think it is expected that an empty test.rs with the cdylib crate type will result in an empty dylib. On Linux it doesn't contain any functions other than a couple of fixed libc/compiler internal ones. All of the size you are seeing on Linux is because of debuginfo. On macOS debuginfo is put in a separate .dSYM bundle and in addition I believe dsymutil which generates the .dSYM bundle is able to eliminate debuginfo for dead functions, unlike the linker on Linux.