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

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

Open
SSheldon opened this issue Jun 25, 2016 · 5 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug.

Comments

@SSheldon
Copy link
Contributor

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
Copy link
Contributor Author

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

@steveklabnik steveklabnik added the A-linkage Area: linking into static, shared libraries and binaries label Jun 27, 2016
@alexcrichton
Copy link
Member

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
Copy link
Member

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

  • The linker error happens on OSX because the command line option we pass -exported_symbols_list is a file that contains the symbol rust_eh_personality_catch. That is, we're indicating to the linker that this symbol should be exported.
  • That symbol does not exist, however, because it's only defined in libpanic_unwind.rlib which is not being linked. The linker on OSX decides this is a fatal error, whereas the linker on Unix for example does not decide this is a fatal error.
  • That file is generated here coming from cdylib_exports here which in turn comes from the reachable argument which is created here.
  • Creation of this list in involves iterating over all crates and pulling in their exported/reachable symbols.
  • Currently a "reachable symbol" is any #[no_mangle], reachable, extern symbol, which lo and behold our symbol is indeed.

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
Copy link
Member

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

@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 25, 2017
@bjorn3
Copy link
Member

bjorn3 commented May 15, 2022

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.

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.
Projects
None yet
Development

No branches or pull requests

5 participants