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

fix regression in panic_misaligned_pointer_dereference #118683

Conversation

thomasdangl
Copy link

#118362 introduced a regression that breaks pointer dereferencing in core.

use std::ptr;

pub fn main() {
    let a: *const u8 = ptr::null();
    dbg!(unsafe { *a });
}
[profile.dev]
panic = "abort"
[build]
target = "x86_64-pc-windows-msvc"

[unstable]
build-std = ["std", "panic_abort"]
build-std-features = ["panic_immediate_abort"]

[target.x86_64-pc-windows-msvc]
linker = "rust-lld.exe"

Until 8de5bd0 this worked totally fine.
However, since the commit ended up in master, the linker is quite unhappy about the symbol:

  = note: rust-lld: error: undefined symbol: core::panicking::panic_misaligned_pointer_dereference::h89d210946737113d
          >>> referenced by C:\Users\User\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\fs.rs:517
          >>>               libstd-93222e7335411a9e.rlib(std-93222e7335411a9e.std.f1f999d9f794207e-cgu.06.rcgu.o):(std::sys::windows::fs::File::readlink::ha67e29df7ba249d0)
          >>> referenced by C:\Users\User\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\fs.rs:518
          >>>               libstd-93222e7335411a9e.rlib(std-93222e7335411a9e.std.f1f999d9f794207e-cgu.06.rcgu.o):(std::sys::windows::fs::File::readlink::ha67e29df7ba249d0)
          >>> referenced by C:\Users\User\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\fs.rs:519
          >>>               libstd-93222e7335411a9e.rlib(std-93222e7335411a9e.std.f1f999d9f794207e-cgu.06.rcgu.o):(std::sys::windows::fs::File::readlink::ha67e29df7ba249d0)
          >>> referenced 33 more times

Is there a specific reason panic_misaligned_pointer_dereference is supposed to be inlined?
Otherwise I suggest we just avoid inlining it for panic_immediate_abort.

Perhaps this is also something to be added as an example for #118393.

Best,
Thomas

@rustbot
Copy link
Collaborator

rustbot commented Dec 6, 2023

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @m-ou-se (or someone else) soon.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 6, 2023
@saethlin
Copy link
Member

saethlin commented Dec 6, 2023

Is there a specific reason panic_misaligned_pointer_dereference is supposed to be inlined?

Yes, the entire point of that feature is to permit these symbols to be fully optimized out, along with all the formatting code that they drag in.

Can you explain your use-case more? I don't understand how the feature used to work for you before; you're building an unoptimized standard library so it should be full of panic formatting code.

@thomasdangl
Copy link
Author

Yes, the entire point of that feature is to permit these symbols to be fully optimized out, along with all the formatting code that they drag in.

I see. In that case it might make sense to investigate further within the compiler.
Something is generating references to non-existing symbols.

Can you explain your use-case more? I don't understand how the feature used to work for you before; you're building an unoptimized standard library so it should be full of panic formatting code.

I'm building a no_std application with panic=abort for Windows. My goal is to reduce the overall code size of my program using panic_immediate_abort among other options.
I'm not worried about having the formatting code in the debug build (although optimizing this away would be desirable as you have mentioned).

Rather, my problem is that neither my program nor std is building anymore because the offending line causes an linker error whenever a pointer is dereferenced (with panic_immediate_abort). So in that sense, the problem is independent from any specific use case.

@saethlin
Copy link
Member

saethlin commented Dec 7, 2023

I can trivially reproduce all the behavior you're experiencing on Linux with the default linker. That's good, I suppose.

Since I wrote the alignment checks and I've fiddled a lot with panic_immediate_abort, I'll assign myself to this.

r? saethlin

@rustbot rustbot assigned saethlin and unassigned m-ou-se Dec 7, 2023
compiler-errors added a commit to compiler-errors/rust that referenced this pull request Dec 7, 2023
…achable, r=bjorn3

Tell MirUsedCollector that the pointer alignment checks calls its panic symbol

Fixes rust-lang#118683 (not an issue, but that PR is a basically a bug report)

When we had `panic_immediate_abort` start adding `#[inline]` to this panic function, builds started breaking because we failed to write up the MIR assert terminator to the correct panic shim. Things happened to work before by pure luck because without this feature enabled, the function we're inserting calls to is `#[inline(never)]` so we always generated code for it.

r? bjorn3
@bors bors closed this in #118693 Dec 8, 2023
@bors bors closed this in 646d627 Dec 8, 2023
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Dec 8, 2023
Rollup merge of rust-lang#118693 - saethlin:alignment-check-symbol-reachable, r=bjorn3

Tell MirUsedCollector that the pointer alignment checks calls its panic symbol

Fixes rust-lang#118683 (not an issue, but that PR is a basically a bug report)

When we had `panic_immediate_abort` start adding `#[inline]` to this panic function, builds started breaking because we failed to write up the MIR assert terminator to the correct panic shim. Things happened to work before by pure luck because without this feature enabled, the function we're inserting calls to is `#[inline(never)]` so we always generated code for it.

r? bjorn3
@saethlin
Copy link
Member

saethlin commented Dec 9, 2023

@thomasdangl The PR that I linked this to is now part of the latest nightly. Can you confirm that the latest nightly works for you?

@Vollbrecht
Copy link

Vollbrecht commented Dec 10, 2023

we were also effected by this in https://github.com/esp-rs/esp-idf-hal but our CI is working again with latest nightly.

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Dec 14, 2023
…nnethercote

Fix cases where std accidentally relied on inline(never)

This PR increases the power of `-Zcross-crate-inline-threshold=always` so that it applies through `#[inline(never)]`. Note that though this is called "cross-crate-inlining" in this case especially it is _just_ lazy per-CGU codegen. The MIR inliner and LLVM still respect the attribute as much as they ever have.

Trying to bootstrap with the new `-Zcross-crate-inline-threshold=always` change revealed two bugs:

We have special intrinsics `assert_inhabited`, `assert_zero_valid`, and `assert_mem_uniniitalized_valid` which codegen backends will lower to nothing or a call to `panic_nounwind`.  Since we may not have any call to `panic_nounwind` in MIR but emit one anyway, we need to specially tell `MirUsedCollector` about this situation.

`#[lang = "start"]` is special-cased already so that `MirUsedCollector` will collect it, but then when we make it cross-crate-inlinable it is only assigned to a CGU based on whether `MirUsedCollector` saw a call to it, which of course we didn't.

---

I started looking into this because rust-lang#118683 revealed a case where we were accidentally relying on a function being `#[inline(never)]`, and cranking up cross-crate-inlinability seems like a way to find other situations like that.

r? `@nnethercote` because I don't like what I'm doing to the CGU partitioning code here but I can't come up with something much better
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 14, 2023
…ethercote

Fix cases where std accidentally relied on inline(never)

This PR increases the power of `-Zcross-crate-inline-threshold=always` so that it applies through `#[inline(never)]`. Note that though this is called "cross-crate-inlining" in this case especially it is _just_ lazy per-CGU codegen. The MIR inliner and LLVM still respect the attribute as much as they ever have.

Trying to bootstrap with the new `-Zcross-crate-inline-threshold=always` change revealed two bugs:

We have special intrinsics `assert_inhabited`, `assert_zero_valid`, and `assert_mem_uniniitalized_valid` which codegen backends will lower to nothing or a call to `panic_nounwind`.  Since we may not have any call to `panic_nounwind` in MIR but emit one anyway, we need to specially tell `MirUsedCollector` about this situation.

`#[lang = "start"]` is special-cased already so that `MirUsedCollector` will collect it, but then when we make it cross-crate-inlinable it is only assigned to a CGU based on whether `MirUsedCollector` saw a call to it, which of course we didn't.

---

I started looking into this because rust-lang#118683 revealed a case where we were accidentally relying on a function being `#[inline(never)]`, and cranking up cross-crate-inlinability seems like a way to find other situations like that.

r? `@nnethercote` because I don't like what I'm doing to the CGU partitioning code here but I can't come up with something much better
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 14, 2023
…ethercote

Fix cases where std accidentally relied on inline(never)

This PR increases the power of `-Zcross-crate-inline-threshold=always` so that it applies through `#[inline(never)]`. Note that though this is called "cross-crate-inlining" in this case especially it is _just_ lazy per-CGU codegen. The MIR inliner and LLVM still respect the attribute as much as they ever have.

Trying to bootstrap with the new `-Zcross-crate-inline-threshold=always` change revealed two bugs:

We have special intrinsics `assert_inhabited`, `assert_zero_valid`, and `assert_mem_uniniitalized_valid` which codegen backends will lower to nothing or a call to `panic_nounwind`.  Since we may not have any call to `panic_nounwind` in MIR but emit one anyway, we need to specially tell `MirUsedCollector` about this situation.

`#[lang = "start"]` is special-cased already so that `MirUsedCollector` will collect it, but then when we make it cross-crate-inlinable it is only assigned to a CGU based on whether `MirUsedCollector` saw a call to it, which of course we didn't.

---

I started looking into this because rust-lang#118683 revealed a case where we were accidentally relying on a function being `#[inline(never)]`, and cranking up cross-crate-inlinability seems like a way to find other situations like that.

r? `@nnethercote` because I don't like what I'm doing to the CGU partitioning code here but I can't come up with something much better
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 15, 2023
…ethercote

Fix cases where std accidentally relied on inline(never)

This PR increases the power of `-Zcross-crate-inline-threshold=always` so that it applies through `#[inline(never)]`. Note that though this is called "cross-crate-inlining" in this case especially it is _just_ lazy per-CGU codegen. The MIR inliner and LLVM still respect the attribute as much as they ever have.

Trying to bootstrap with the new `-Zcross-crate-inline-threshold=always` change revealed two bugs:

We have special intrinsics `assert_inhabited`, `assert_zero_valid`, and `assert_mem_uniniitalized_valid` which codegen backends will lower to nothing or a call to `panic_nounwind`.  Since we may not have any call to `panic_nounwind` in MIR but emit one anyway, we need to specially tell `MirUsedCollector` about this situation.

`#[lang = "start"]` is special-cased already so that `MirUsedCollector` will collect it, but then when we make it cross-crate-inlinable it is only assigned to a CGU based on whether `MirUsedCollector` saw a call to it, which of course we didn't.

---

I started looking into this because rust-lang#118683 revealed a case where we were accidentally relying on a function being `#[inline(never)]`, and cranking up cross-crate-inlinability seems like a way to find other situations like that.

r? `@nnethercote` because I don't like what I'm doing to the CGU partitioning code here but I can't come up with something much better
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Dec 19, 2023
Fix cases where std accidentally relied on inline(never)

This PR increases the power of `-Zcross-crate-inline-threshold=always` so that it applies through `#[inline(never)]`. Note that though this is called "cross-crate-inlining" in this case especially it is _just_ lazy per-CGU codegen. The MIR inliner and LLVM still respect the attribute as much as they ever have.

Trying to bootstrap with the new `-Zcross-crate-inline-threshold=always` change revealed two bugs:

We have special intrinsics `assert_inhabited`, `assert_zero_valid`, and `assert_mem_uniniitalized_valid` which codegen backends will lower to nothing or a call to `panic_nounwind`.  Since we may not have any call to `panic_nounwind` in MIR but emit one anyway, we need to specially tell `MirUsedCollector` about this situation.

`#[lang = "start"]` is special-cased already so that `MirUsedCollector` will collect it, but then when we make it cross-crate-inlinable it is only assigned to a CGU based on whether `MirUsedCollector` saw a call to it, which of course we didn't.

---

I started looking into this because rust-lang/rust#118683 revealed a case where we were accidentally relying on a function being `#[inline(never)]`, and cranking up cross-crate-inlinability seems like a way to find other situations like that.

r? `@nnethercote` because I don't like what I'm doing to the CGU partitioning code here but I can't come up with something much better
lnicola pushed a commit to lnicola/rust-analyzer that referenced this pull request Apr 7, 2024
Fix cases where std accidentally relied on inline(never)

This PR increases the power of `-Zcross-crate-inline-threshold=always` so that it applies through `#[inline(never)]`. Note that though this is called "cross-crate-inlining" in this case especially it is _just_ lazy per-CGU codegen. The MIR inliner and LLVM still respect the attribute as much as they ever have.

Trying to bootstrap with the new `-Zcross-crate-inline-threshold=always` change revealed two bugs:

We have special intrinsics `assert_inhabited`, `assert_zero_valid`, and `assert_mem_uniniitalized_valid` which codegen backends will lower to nothing or a call to `panic_nounwind`.  Since we may not have any call to `panic_nounwind` in MIR but emit one anyway, we need to specially tell `MirUsedCollector` about this situation.

`#[lang = "start"]` is special-cased already so that `MirUsedCollector` will collect it, but then when we make it cross-crate-inlinable it is only assigned to a CGU based on whether `MirUsedCollector` saw a call to it, which of course we didn't.

---

I started looking into this because rust-lang/rust#118683 revealed a case where we were accidentally relying on a function being `#[inline(never)]`, and cranking up cross-crate-inlinability seems like a way to find other situations like that.

r? `@nnethercote` because I don't like what I'm doing to the CGU partitioning code here but I can't come up with something much better
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this pull request Apr 27, 2024
Fix cases where std accidentally relied on inline(never)

This PR increases the power of `-Zcross-crate-inline-threshold=always` so that it applies through `#[inline(never)]`. Note that though this is called "cross-crate-inlining" in this case especially it is _just_ lazy per-CGU codegen. The MIR inliner and LLVM still respect the attribute as much as they ever have.

Trying to bootstrap with the new `-Zcross-crate-inline-threshold=always` change revealed two bugs:

We have special intrinsics `assert_inhabited`, `assert_zero_valid`, and `assert_mem_uniniitalized_valid` which codegen backends will lower to nothing or a call to `panic_nounwind`.  Since we may not have any call to `panic_nounwind` in MIR but emit one anyway, we need to specially tell `MirUsedCollector` about this situation.

`#[lang = "start"]` is special-cased already so that `MirUsedCollector` will collect it, but then when we make it cross-crate-inlinable it is only assigned to a CGU based on whether `MirUsedCollector` saw a call to it, which of course we didn't.

---

I started looking into this because rust-lang/rust#118683 revealed a case where we were accidentally relying on a function being `#[inline(never)]`, and cranking up cross-crate-inlinability seems like a way to find other situations like that.

r? `@nnethercote` because I don't like what I'm doing to the CGU partitioning code here but I can't come up with something much better
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants