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

Limit symbols exported from proc macros #99944

Merged
merged 3 commits into from
Aug 1, 2022

Conversation

bjorn3
Copy link
Member

@bjorn3 bjorn3 commented Jul 30, 2022

Only __rustc_proc_macro_decls_*__ and rust_metadata_* need to be
exported for proc macros to work. All other symbols only increase binary
size and have the potential to conflict with symbols from the host
compiler.

Fixes #99909
Fixes #59998

cc @eddyb

Only __rustc_proc_macro_decls_*__ and rust_metadata_* need to be
exported for proc macros to work. All other symbols only increase binary
size and have the potential to conflict with symbols from the host
compiler.
@bjorn3 bjorn3 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. I-heavy Issue: Problems and improvements with respect to binary size of generated code. A-proc-macros Area: Procedural macros labels Jul 30, 2022
@rust-highfive
Copy link
Collaborator

r? @jackh726

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 30, 2022
Copy link
Member

@eddyb eddyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this! (and sorry I didn't mention the section stuff, was expecting that would get a bit in the way)

r=me with an issue for the #[no_mangle] stuff

compiler/rustc_codegen_ssa/src/back/linker.rs Outdated Show resolved Hide resolved
Comment on lines -260 to +271
if tcx.sess.crate_types().contains(&CrateType::Dylib) {
if tcx.sess.crate_types().contains(&CrateType::Dylib)
|| tcx.sess.crate_types().contains(&CrateType::ProcMacro)
{
let symbol_name = metadata_symbol_name(tcx);
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));

symbols.push((
exported_symbol,
SymbolExportInfo {
level: SymbolExportLevel::Rust,
level: SymbolExportLevel::C,
kind: SymbolExportKind::Data,
used: false,
used: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @michaelwoerister @wesleywiser @rust-lang/wg-llvm
Is anyone aware of any potential negative consequences of this?

I'm a bit surprised we even need a symbol (and don't find it by section instead).

If the symbol only exists to keep the section from being GC'd, shouldn't it be some form of unexported #[used]? (e.g. keep Rust export level, or go even lower? but always set used: true)

Copy link
Member Author

@bjorn3 bjorn3 Jul 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The symbol is needed on at least macOS to prevent the section from being discarded. The exact name is unique. I think it would make sense in the future to ensure that the symbol exists when using a dylib as dependency to ensure versions don't get mixed without recompilation.

Copy link
Member

@eddyb eddyb Jul 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, right, the SVH enforcement ideas, but is this symbol accessible to the dynamic loader at all?
Also it might be good to have dedicated symbols in case the metadata ones get stripped.

EDIT: moved the rest of the comment below to #73917 (comment)

(click to open old version)

We could even have something like this:

struct LinkGuard {
    deps: &'static [&'static LinkGuard],
}

extern "Rust" {
    // foo[b7924b40b7ed5e7f]::{shim:LINK_GUARD#0}::<0x461e83de35f0b704f7e69b4cc741ad8eu128>
    #[link_name = "_RINSCsfL95rG4I7iB_3foo10LINK_GUARDKo461e83de35f0b704f7e69b4cc741ad8e_E"] 
    static LINK_GUARD_DEP_FOO: LinkGuard;

    // bar[acb4b2d152c0bd2e]::{shim:LINK_GUARD#0}::<0xf8fc0fadc6a6e727eef4b916531abfe9u128>
    #[link_name = "_RINSCsePjaApBJGQA_3bar10LINK_GUARDKof8fc0fadc6a6e727eef4b916531abfe9_E"] 
    static LINK_GUARD_DEP_BAR: LinkGuard;
}

// my_crate[78009e3fbfa2f6af]::{shim:LINK_GUARD#0}::<0xe538955c5950b59a598304a1e701c9fbu128>
#[export_name = "_RINSCsaiLK1vfX74x_8my_crate10LINK_GUARDKoe538955c5950b59a598304a1e701c9fb_E"]
pub static LINK_GUARD: LinkGuard {
    deps: unsafe { &[
        &LINK_GUARD_DEP_FOO,
        &LINK_GUARD_DEP_BAR,
    ] }
};

(and then use global constructors to ensure it gets kept in - potentially even doing some redundant SVH checking at runtime too...? or something more cursed where it's "activating" something that would be broken otherwise. but that's too much)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. cc #73917

src/test/run-make-fulldeps/symbol-visibility/Makefile Outdated Show resolved Hide resolved
src/test/run-make-fulldeps/symbol-visibility/Makefile Outdated Show resolved Hide resolved
@eddyb
Copy link
Member

eddyb commented Jul 30, 2022

@bjorn3 Oh, almost forgot, can you look for // ignore-stage1 proc macro tests, and/or those that mention #59998, and try making them always run? I'm curious if export limiting can fix #59998.

@bjorn3
Copy link
Member Author

bjorn3 commented Jul 31, 2022

#59998 is indeed fixed by this it seems.

@rust-log-analyzer

This comment has been minimized.

@eddyb
Copy link
Member

eddyb commented Jul 31, 2022

@bors r+ rollup=never Thanks!

(#99944 (comment) might still worry me, but it's just the section for a holding the .rmeta, and dylib usage should be pretty limited, and it's easy to fix it it's just the C/Rust level difference)

@bors
Copy link
Contributor

bors commented Jul 31, 2022

📌 Commit b87f8a4 has been approved by eddyb

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 31, 2022
@bors
Copy link
Contributor

bors commented Aug 1, 2022

⌛ Testing commit b87f8a4 with merge 25bb1c1...

@bors
Copy link
Contributor

bors commented Aug 1, 2022

☀️ Test successful - checks-actions
Approved by: eddyb
Pushing 25bb1c1 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Aug 1, 2022
@bors bors merged commit 25bb1c1 into rust-lang:master Aug 1, 2022
@rustbot rustbot added this to the 1.64.0 milestone Aug 1, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (25bb1c1): comparison url.

Instruction count

  • Primary benchmarks: 🎉 relevant improvements found
  • Secondary benchmarks: 🎉 relevant improvements found
mean1 max count2
Regressions 😿
(primary)
N/A N/A 0
Regressions 😿
(secondary)
N/A N/A 0
Improvements 🎉
(primary)
-0.6% -2.9% 41
Improvements 🎉
(secondary)
-2.4% -10.7% 11
All 😿🎉 (primary) -0.6% -2.9% 41

Max RSS (memory usage)

Results
  • Primary benchmarks: 🎉 relevant improvements found
  • Secondary benchmarks: no relevant changes found
mean1 max count2
Regressions 😿
(primary)
N/A N/A 0
Regressions 😿
(secondary)
N/A N/A 0
Improvements 🎉
(primary)
-1.7% -2.2% 8
Improvements 🎉
(secondary)
N/A N/A 0
All 😿🎉 (primary) -1.7% -2.2% 8

Cycles

Results
  • Primary benchmarks: 🎉 relevant improvements found
  • Secondary benchmarks: mixed results
mean1 max count2
Regressions 😿
(primary)
N/A N/A 0
Regressions 😿
(secondary)
3.7% 3.7% 1
Improvements 🎉
(primary)
-3.0% -6.6% 6
Improvements 🎉
(secondary)
-5.3% -9.8% 4
All 😿🎉 (primary) -3.0% -6.6% 6

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

@rustbot label: -perf-regression

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

@bjorn3 bjorn3 deleted the hide_proc_macro_symbols branch August 1, 2022 16:53
@Alexendoo
Copy link
Member

Following this PR rustc_private crates from rustup no longer work on aarch64-unknown-linux-gnu

#![feature(rustc_private)]

extern crate rustc_attr;

Gives the error:

error: /home/alex/.rustup/toolchains/nightly-2022-08-14-aarch64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libserde_derive-6dc9fea9ed4dba80.so: cannot allocate memory in static TLS block
 --> src/lib.rs:3:1
  |
3 | extern crate rustc_attr;
  | ^^^^^^^^^^^^^^^^^^^^^^^^

@bjorn3
Copy link
Member Author

bjorn3 commented Aug 14, 2022

I think this is because proc macros of rustc are incorrectly compiled with -Ztls-model=initial-exec. This tls model is not allowed for dlopen'ed dylibs. It just so happens to work by accident in certain cases. For example before this PR some tls variables would be incorrectly resolved in the host rustc instance instead of the proc macro itself (causing #59998) and thus not run into trouble. The fix would be to limit -Ztls-model=initial-exec to crates not compiled for the host. That is replacing

rustflags.arg("-Ztls-model=initial-exec");
with an env var that causes the argument to be passed in this if block:
if target.is_some() {

@eddyb
Copy link
Member

eddyb commented Aug 14, 2022

@Alexendoo Can you file a separate issue for that? Also, ignoring rustc_private, can you use serde_derive in general on that platform? I would assume so, which means this is a very strange interaction.

At most maybe this is misbehaving on some platforms (note the powerpc- exclusion):

rust/src/bootstrap/builder.rs

Lines 1848 to 1854 in f03ce30

// Compile everything except libraries and proc macros with the more
// efficient initial-exec TLS model. This doesn't work with `dlopen`,
// so we can't use it by default in general, but we can use it for tools
// and our own internal libraries.
if !mode.must_support_dlopen() && !target.triple.starts_with("powerpc-") {
rustflags.arg("-Ztls-model=initial-exec");
}

EDIT: ahh @bjorn3 replied while I was typing this, "only worked by accident" explains a lot, heh.

@Alexendoo
Copy link
Member

Thanks! Opened #100530

Yeah serde_derive works fine as a regular dependency. I'll try to reproduce the issue without rustup + test the fix

badboy added a commit to mozilla/uniffi-rs that referenced this pull request Jul 25, 2023
In m-c we're running into linking issues in `uniffi_macros`,
where it's missing symbols coming from `uniffi_core`:

    /bin/ld: uniffi_foreign_executor_callback_set: undefined version:
    /bin/ld: failed to set dynamic section sizes: bad value

That's most likely this issue on Rust:
rust-lang/rust#111888
It's called out that this likely actually broke because of another PR:
rust-lang/rust#99944

Despite this bug there's a bit of an issue in UniFFI to begin with:
We're exporting `extern "C"` functions from a crate that is a dependency
of some other crates, including `uniffi_macros`, and thus the symbols
land in a part where they are not needed.

However for `uniffi_meta` in particular we don't need much from
`uniffi_core`, so for now we just copy the necessary bits to get it all
working.
badboy added a commit to badboy/uniffi-rs that referenced this pull request Jul 25, 2023
In m-c we're running into linking issues in `uniffi_macros`,
where it's missing symbols coming from `uniffi_core`:

    /bin/ld: uniffi_foreign_executor_callback_set: undefined version:
    /bin/ld: failed to set dynamic section sizes: bad value

That's most likely this issue on Rust:
rust-lang/rust#111888
It's called out that this likely actually broke because of another PR:
rust-lang/rust#99944

Despite this bug there's a bit of an issue in UniFFI to begin with:
We're exporting `extern "C"` functions from a crate that is a dependency
of some other crates, including `uniffi_macros`, and thus the symbols
land in a part where they are not needed.

However for `uniffi_meta` in particular we don't need much from
`uniffi_core`, so for now we just copy the necessary bits to get it all
working.
badboy added a commit to mozilla/uniffi-rs that referenced this pull request Jul 25, 2023
In m-c we're running into linking issues in `uniffi_macros`,
where it's missing symbols coming from `uniffi_core`:

    /bin/ld: uniffi_foreign_executor_callback_set: undefined version:
    /bin/ld: failed to set dynamic section sizes: bad value

That's most likely this issue on Rust:
rust-lang/rust#111888
It's called out that this likely actually broke because of another PR:
rust-lang/rust#99944

Despite this bug there's a bit of an issue in UniFFI to begin with:
We're exporting `extern "C"` functions from a crate that is a dependency
of some other crates, including `uniffi_macros`, and thus the symbols
land in a part where they are not needed.

However for `uniffi_meta` in particular we don't need much from
`uniffi_core`, so for now we just copy the necessary bits to get it all
working.
badboy added a commit to mozilla/uniffi-rs that referenced this pull request Jul 25, 2023
In m-c we're running into linking issues in `uniffi_macros`,
where it's missing symbols coming from `uniffi_core`:

    /bin/ld: uniffi_foreign_executor_callback_set: undefined version:
    /bin/ld: failed to set dynamic section sizes: bad value

That's most likely this issue on Rust:
rust-lang/rust#111888
It's called out that this likely actually broke because of another PR:
rust-lang/rust#99944

Despite this bug there's a bit of an issue in UniFFI to begin with:
We're exporting `extern "C"` functions from a crate that is a dependency
of some other crates, including `uniffi_macros`, and thus the symbols
land in a part where they are not needed.

However for `uniffi_meta` in particular we don't need much from
`uniffi_core`, so for now we just copy the necessary bits to get it all
working.
badboy added a commit to mozilla/uniffi-rs that referenced this pull request Jul 25, 2023
In m-c we're running into linking issues in `uniffi_macros`,
where it's missing symbols coming from `uniffi_core`:

    /bin/ld: uniffi_foreign_executor_callback_set: undefined version:
    /bin/ld: failed to set dynamic section sizes: bad value

That's most likely this issue on Rust:
rust-lang/rust#111888
It's called out that this likely actually broke because of another PR:
rust-lang/rust#99944

Despite this bug there's a bit of an issue in UniFFI to begin with:
We're exporting `extern "C"` functions from a crate that is a dependency
of some other crates, including `uniffi_macros`, and thus the symbols
land in a part where they are not needed.

However for `uniffi_meta` in particular we don't need much from
`uniffi_core`, so for now we just copy the necessary bits to get it all
working.
badboy added a commit to mozilla/uniffi-rs that referenced this pull request Jul 25, 2023
In m-c we're running into linking issues in `uniffi_macros`,
where it's missing symbols coming from `uniffi_core`:

    /bin/ld: uniffi_foreign_executor_callback_set: undefined version:
    /bin/ld: failed to set dynamic section sizes: bad value

That's most likely this issue on Rust:
rust-lang/rust#111888
It's called out that this likely actually broke because of another PR:
rust-lang/rust#99944

Despite this bug there's a bit of an issue in UniFFI to begin with:
We're exporting `extern "C"` functions from a crate that is a dependency
of some other crates, including `uniffi_macros`, and thus the symbols
land in a part where they are not needed.

However for `uniffi_meta` in particular we don't need much from
`uniffi_core`, so for now we just copy the necessary bits to get it all
working.
badboy added a commit to mozilla/uniffi-rs that referenced this pull request Jul 26, 2023
In m-c we're running into linking issues in `uniffi_macros`,
where it's missing symbols coming from `uniffi_core`:

    /bin/ld: uniffi_foreign_executor_callback_set: undefined version:
    /bin/ld: failed to set dynamic section sizes: bad value

That's most likely this issue on Rust:
rust-lang/rust#111888
It's called out that this likely actually broke because of another PR:
rust-lang/rust#99944

Despite this bug there's a bit of an issue in UniFFI to begin with:
We're exporting `extern "C"` functions from a crate that is a dependency
of some other crates, including `uniffi_macros`, and thus the symbols
land in a part where they are not needed.

However for `uniffi_meta` in particular we don't need much from
`uniffi_core`, so for now we just copy the necessary bits to get it all
working.
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 9, 2023
…proc-macros-issue-99978, r=bjorn3

Restrict linker version script of proc-macro crates to just its two symbols

Restrict linker version script of proc-macro crates to just the two symbols of each proc-macro crate.

The main known effect of doing this is to stop including `#[no_mangle]` symbols in the linker version script.

Background:

The combination of a proc-macro crate with an import of another crate that itself exports a no_mangle function was broken for a period of time, because:

* In PR rust-lang#99944 we stopped exporting no_mangle symbols from proc-macro crates; proc-macro crates have a very limited interface and are meant to be treated as a blackbox to everything except rustc itself. However: he constructed linker version script still referred to them, but resolving that discrepancy was left as a FIXME in the code, tagged with issue rust-lang#99978.
* In PR rust-lang#108017 we started telling the linker to check (via the`--no-undefined-version` linker invocation flag) that every symbol referenced in the "linker version script" is provided as linker input. So the unresolved discrepancy from rust-lang#99978 started surfacing as a compile-time error (e.g. rust-lang#111888).

Fix rust-lang#111888
Fix rust-lang#99978.
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 A-proc-macros Area: Procedural macros I-heavy Issue: Problems and improvements with respect to binary size of generated code. merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Proc macros should limit symbol exports Proc macro errors can lead to rustc panics at stage1 or on non-Linux
9 participants