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

Private #[no_mangle] symbols are exported from a cdylib #98449

Open
nxtn-staged opened this issue Jun 24, 2022 · 4 comments
Open

Private #[no_mangle] symbols are exported from a cdylib #98449

nxtn-staged opened this issue Jun 24, 2022 · 4 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nxtn-staged
Copy link

In C++ (MSVC) un-mangling and exporting are controlled via extern "C" and __declspec(dllexport) respectively.

extern "C" {
    namespace to_export {
        __declspec(dllexport) int64_t foo() {
            int64_t bar();
            return bar();
        }
    }
    namespace not_to_export {
        int32_t bar() {
            return 42;
        }
    }
}
    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00001000 foo = foo

In Rust, however, all #[no_mangle] functions are exported from the final cdylib.

pub mod to_export {
    #[no_mangle]
    pub unsafe extern "system" fn foo() -> i64 {
        extern "system" {
            fn bar() -> i64;
        }
        bar()
    }
}
mod not_to_export {
    #[no_mangle]
    extern "system" fn bar() -> i32 {
        42
    }
}
    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 00001000 bar = bar
          2    1 00001010 foo = foo

It seems that it is not possible to define an un-mangled and un-exported symbol in Rust.

@SkiFire13
Copy link
Contributor

My guess is that this is related to #95604

@ehuss
Copy link
Contributor

ehuss commented Jun 24, 2022

I believe exporting the symbol is intentional as documented here. There is also some more information at #54451. Can you say more about why you would want an unmangled symbol that isn't exported?

@nxtn-staged
Copy link
Author

nxtn-staged commented Jun 24, 2022

When building #![no_std] crates or linking static libraries, I'm able to fix unresolved external symbol errors with #[no_mangle] symbols, but I do not expect them to appear in the export list.

@ChrisDenton
Copy link
Member

Yes, in general there is a difference between making a symbol for the linker to find and exporting it from the final binary. According to the no_mangle reference:

Additionally, the item will be publicly exported from the produced library or object file, similar to the used attribute.

And the used reference says (my bold):

This attribute forces the compiler to keep the variable in the output object file (.o, .rlib, etc. excluding final binaries) even if the variable is not used, or referenced, by any other item in the crate. However, the linker is still free to remove such an item.

@jyn514 jyn514 added A-linkage Area: linking into static, shared libraries and binaries T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Apr 9, 2023
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. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants