Skip to content

PartialEq impl for IpAddr causes SIGBUS on mips-unknown-linux-gnu #102722

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

Closed
djkoloski opened this issue Oct 6, 2022 · 23 comments
Closed

PartialEq impl for IpAddr causes SIGBUS on mips-unknown-linux-gnu #102722

djkoloski opened this issue Oct 6, 2022 · 23 comments
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-miscompile Issue: Correct Rust code lowers to incorrect machine code llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes O-MIPS Target: MIPS processors T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@djkoloski
Copy link
Contributor

I tried this code on mips-unknown-linux-gnu through cargo-cross:

use std::net::{IpAddr, Ipv4Addr};

fn main() {
    let value = IpAddr::V4(Ipv4Addr::new(31, 41, 59, 26));
    assert_eq!(&value, &value);
}
cross run --target mips-unknown-linux-gnu --verbose

I expected to see this happen: the program exits successfully.

Instead, this happened: qemu: uncaught target signal 10 (Bus error) - core dumped

This is truly baffling because:

  1. This is extremely plain code, just a struct in an enum.
  2. This is crashing in the implementation of PartialEq which has been generated by a derive.
  3. Removing the outer IpAddr does not cause a crash.
  4. Far more complex code runs successfully.

If this is a problem with cargo-cross instead, I would be happy to move the bug to the corresponding repo.

Meta

rustc --version --verbose:

rustc 1.64.0 (a55dd71d5 2022-09-19)
binary: rustc
commit-hash: a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52
commit-date: 2022-09-19
host: x86_64-pc-windows-msvc
release: 1.64.0
LLVM version: 14.0.6
@saethlin
Copy link
Member

saethlin commented Oct 6, 2022

Trying to repro, but I can't.

╭ ➜ ben@archlinux:/tmp/scratch
╰ ➤ cross run --target mips-unknown-linux-gnu --verbose
+ cargo metadata --format-version 1 --filter-platform mips-unknown-linux-gnu
+ rustc --print sysroot
+ rustup toolchain list
+ rustup target list --toolchain stable-x86_64-unknown-linux-gnu
+ rustup component list --toolchain stable-x86_64-unknown-linux-gnu
+ /usr/bin/docker
+ /usr/bin/docker run --userns host -e 'PKG_CONFIG_ALLOW_CROSS=1' -e 'XARGO_HOME=/xargo' -e 'CARGO_HOME=/cargo' -e 'CARGO_TARGET_DIR=/target' -e 'CROSS_RUNNER=' -e TERM -e 'USER=ben' --rm --user 1000:1000 -v /home/ben/.xargo:/xargo:Z -v /home/ben/.cargo:/cargo:Z -v /cargo/bin -v /tmp/scratch:/project:Z -v /home/ben/.rustup/toolchains/stable-x86_64-unknown-linux-gnu:/rust:Z,ro -v /tmp/scratch/target:/target:Z -w /project -i -t ghcr.io/cross-rs/mips-unknown-linux-gnu:0.2.4 sh -c 'PATH=$PATH:/rust/bin cargo run --target mips-unknown-linux-gnu --verbose'
   Compiling scratch v0.1.0 (/project)
     Running `rustc --crate-name scratch --edition=2021 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C metadata=415e3bf8bc61106d -C extra-filename=-415e3bf8bc61106d --out-dir /target/mips-unknown-linux-gnu/debug/deps --target mips-unknown-linux-gnu -C linker=mips-linux-gnu-gcc -C incremental=/target/mips-unknown-linux-gnu/debug/incremental -L dependency=/target/mips-unknown-linux-gnu/debug/deps -L dependency=/target/debug/deps`
    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
     Running `/linux-runner mips /target/mips-unknown-linux-gnu/debug/scratch`
╭ ➜ ben@archlinux:/tmp/scratch
╰ ➤ echo $?
0

Is it possible this is related to a qemu version?

@djkoloski
Copy link
Contributor Author

Maybe? I thought it might also be host platform specific but then remembered that the same issue occurred locally (on Windows) and in a GitHub action (on Ubuntu). I updated cross just in case as well and it still expressed for me.

@zachs18
Copy link
Contributor

zachs18 commented Oct 6, 2022

The github action you linked installs cross with cargo install cross --git https://github.com/cross-rs/cross.

I do see the issue when running with cross from --git, but not from crates.io, so maybe this is something that has changed between 2.4.0 on crates.io and HEAD of cross-rs. Or perhaps more likely, something that changed with the cross's dockerfile and how it calls qemu?

Here's another example program (intentionally performing an unaligned read of a u32)

unsafe fn read_u32_unaligned(ptr: *const [u8]) -> u32 {
    *ptr.cast()
}

fn main() {
    let x: Box<[u8; 8]> = Box::new([1,2,3,4,5,6,7,8]);

    unsafe {
        println!("{:08X}", read_u32_unaligned(&*x));
        println!("{:08X}", read_u32_unaligned(&x[1..])); // at least one of these accesses is definitely unaligned
    }
}

Gives these results:

Does not give SIGBUS on latest crates.io release of cross:

$ cargo install cross
...
$ cross run --target mips-unknown-linux-gnu
...
01020304
02030405

Gives SIGBUS on HEAD of cross:

$ cargo install cross --git https://github.com/cross-rs/cross
...
$ cross run --target mips-unknown-linux-gnu
...
01020304
qemu: uncaught target signal 10 (Bus error) - core dumped
Bus error (core dumped)

Maybe we should look into if the original example program is miscompiled down to something with an unaligned memory access? I looked at it a bit, but I do not know MIPS assembly enough to make sense of it.

@Noratrieb
Copy link
Member

Between 2.4.0 and main of cross, QEMU has been bumped from 5.1.0 to 6.1.0.

@djkoloski
Copy link
Contributor Author

Thanks for the help everyone, I think this is pretty conclusively a cross issue. I've moved the issue to the cross repo here: cross-rs/cross#1060

@zachs18
Copy link
Contributor

zachs18 commented Oct 7, 2022

I think this may be a QEMU issue or a miscompilation, and not a cross issue, since I can observe it without cross at all on qemu-mips version 7.0.0 (Debian 1:7.0+dfsg-7ubuntu2) on Ubuntu Kinetic (22.10 pre-release) using rust 1.64.0 stable.

# .cargo/config.coml
[target.mips-unknown-linux-gnu]
linker = "mips-linux-gnu-gcc"
runner = ["qemu-mips", "-L", "/usr/mips-linux-gnu", "-g", "23456"]

(same main.rs as OP, default Cargo.toml, run sudo apt install gcc-mips-linux-gnu qemu-user gdb-multiarch)

# Note: this will wait for GDB to connect
$ cargo run --target mips-unknown-linux-gnu
   Compiling rust-102722 v0.1.0 (/root/rust-102722-mwe)
    Finished dev [unoptimized + debuginfo] target(s) in 0.16s
     Running `qemu-mips -L /usr/mips-linux-gnu -g 23456 target/mips-unknown-linux-gnu/debug/rust-102722`
qemu: uncaught target signal 10 (Bus error) - core dumped
Bus error (core dumped)
# In another terminal
$ gdb-multiarch target/mips-unknown-linux-gnu/debug/rust-102722
gdb> sysroot /usr/mips-linux-gnu
gdb> target remote localhost:23456
gdb> c
Program received signal SIGBUS, Bus error.
...

Specifically, I observed that core::array::equality::{impl#9}::spec_eq<u8, u8, 4> (<T as core::array::equality::SpecArrayEq<U,_>>::spec_eq::hd4c38287a2b6c14f) was using lw (load word) with an unaligned address, which caused a SIGBUS.

The program is about to perform lw at,0(at) (basically at = *(at + 0);), but at is not word-aligned (0x3ffff049), so this causes a SIGBUS.

GDB Screenshots under QEMU 7.0.0

QEMU 7.0.0: GDB before lw at,0(at):
screenshot of gdb before lw at,0(at)

QEMU 7.0.0: GDB after lw at,0(at):
screenshot of gdb after lw at,0(at)

Note that this same instruction executes without SIGBUS on QEMU 6.2.0 for some reason.

GDB Screenshots under QEMU 6.2.0

QEMU 6.2.0: GDB before lw at,0(at):
screenshot of gdb before lw at,0(at)

QEMU 6.2.0: GDB after lw at,0(at):
screenshot of gdb after lw at,0(at)


Does anyone know for sure if MIPS allows unaligned accesses or not? If it does, then this may be a QEMU issue. If not, then this may be a miscompilation.

@djkoloski
Copy link
Contributor Author

Reopening this since it seems worth investigating as a potential miscompilation. Thanks @zachs18 for putting in a ton of legwork to gather some more information!

@djkoloski djkoloski reopened this Oct 7, 2022
@workingjubilee workingjubilee added the O-MIPS Target: MIPS processors label Mar 3, 2023
@urosbericsyrmia
Copy link

I have run the code with both cargo and cross and it works fine. Are you sure the issue is still occurring?
Same main.rs as OP's, default Cargo.toml, config.toml is as follows:

[target.mips-unknown-linux-gnu]
linker = "mips-linux-gnu-gcc"
runner = ["qemu-mips", "-L", "/usr/mips-linux-gnu"]

After running cargo run -Z build-std --target mips-unknown-linux-gnu it finished successfully. Same thing with cross run -Z build-std --target mips-unknown-linux-gnu.
Can someone please confirm that this is also working for you?

@zachs18
Copy link
Contributor

zachs18 commented Mar 13, 2024

@urosbericsyrmia What version of QEMU are you using?

I can still reproduce this on QEMU 8.0.4 (in an Ubuntu 23.10 docker container) with a slightly modified fn main

use std::net::{IpAddr, Ipv4Addr};

fn main() {
    println!("A");
    let value = IpAddr::V4(Ipv4Addr::new(31, 41, 59, 26));
    assert_eq!(&value, &value);
    println!("B");
}

gives

cargo run -Z build-std --target mips-unknown-linux-gnu
   Compiling rust-102722 v0.1.0 (/rust-102722-mwe)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.49s
     Running `qemu-mips -L /usr/mips-linux-gnu target/mips-unknown-linux-gnu/debug/rust-102722`
A
Bus error (core dumped)
# rustc --version -v
rustc 1.78.0-nightly (a165f1f65 2024-03-12)
binary: rustc
commit-hash: a165f1f65015b1bd4afd2ec50700aaacf2e0c485
commit-date: 2024-03-12
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 18.1.0
# qemu-mips --version
qemu-mips version 8.0.4 (Debian 1:8.0.4+dfsg-1ubuntu3.23.10.3)
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers

Now the first bus error happens is in _ZN4core3num23_$LT$impl$u20$usize$GT$9repeat_u817hde665bc3cd149eabE, a.k.a core::num::<impl usize>::repeat_u8::hde665bc3cd149eab, which calls usize::from_ne_bytes, which uses a transmute, which should not have alignment issues, so maybe this is a miscompilation? Or as said before, if MIPS-linux-gnu is supposed to allow unaligned reads, then this could be a QEMU issue.

@urosbericsyrmia
Copy link

Originally, I was running the code with QEMU 4.2.1.

# qemu-mips --version
qemu-mips version 4.2.1 (Debian 1:4.2-3ubuntu6.28)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
# rustc --version -v
rustc 1.78.0-nightly (3b1717c05 2024-03-10)
binary: rustc
commit-hash: 3b1717c052de4a2dbdd3badb0e7a885f40a8ad9e
commit-date: 2024-03-10
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 18.1.0
cargo run -Z build-std --target mips-unknown-linux-gnu
   Compiling ip_addr v0.1.0 (/[...]/issue_102722/ip_addr)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.78s
     Running `qemu-mips -L /usr/mips-linux-gnu target/mips-unknown-linux-gnu/debug/ip_addr`
A
B

But after installing and building QEMU 8.0.4 I get the same error as you.

cargo run -Z build-std --target mips-unknown-linux-gnu
   Compiling ip_addr v0.1.0 (/[...]/issue_102722/ip_addr)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 9.23s
     Running `/[...]/qemu-8.0.4/build/qemu-mips -L /usr/mips-linux-gnu target/mips-unknown-linux-gnu/debug/ip_addr`
A
qemu: uncaught target signal 10 (Bus error) - core dumped
Bus error (core dumped)

Thus, is this a QEMU issue? I'm going to take a closer look, thanks for your effort.

@urosbericsyrmia
Copy link

As far as I can tell this issue is unrelated to rust. Should we close it here and move it somewhere else?

@zachs18
Copy link
Contributor

zachs18 commented Mar 20, 2024

@urosbericsyrmia So far, AFAICT no one in this thread has definitively figured out if mips-unknown-linux-gnu allows unaligned lw (either in hardware or by software fallback), e.g. by testing the affected code on real mips hardware. If it does, this is a QEMU issue (and this issue should be closed and the bug reported to QEMU). If it does not, this is a miscompilation (or otherwise a bug in rust) and is a rustc and/or LLVM issue (even if it is a LLVM issue, this issue should remain open until the relevant LLVM bug has been fixed, or rustc is patched to work around it).

@urosbericsyrmia
Copy link

Just wanted to point out that I was able to reproduce the issue with the following main.rs:

fn main() {
    println!("A");
    println!("B");
}

I get:

A
qemu: uncaught target signal 10 (Bus error) - core dumped
Bus error (core dumped)

By debugging the code I came to a conclusion that there is no issue with PartialEq impl for IpAddr, but rather the issue appears when there are multiple println!. The second println! invokes usize::from_ne_bytes([x; mem::size_of::<usize>()]) which causes an error.
Can somebody confirm this?
Of course, I am still uncertain if the cause of the issue is alignment or is it a QEMU issue.

@jdmitrovic-syrmia
Copy link

This seems to be fixed in the latest nightly build (updated to rustc 1.79.0-nightly (a07f3eb 2024-04-11) from rustc 1.79.0-nightly (47ecded 2024-03-26)).

@jdmitrovic-syrmia
Copy link

Could we close this issue if it doesn't occur anymore?

@purplesyringa
Copy link
Contributor

Another reproducer of what is probably the same issue:

use core::mem::ManuallyDrop;

fn noop() {}

fn meow_new<E>(cause: E) -> ManuallyDrop<E> {
    noop();
    ManuallyDrop::new(cause)
}

#[repr(packed)]
struct Unaligned(i32);

fn main() {
    meow_new(Unaligned(123i32));
}
$ rustc -Vv
rustc 1.84.0-nightly (439284741 2024-10-21)
binary: rustc
commit-hash: 4392847410ddd67f6734dd9845f9742ff9e85c83
commit-date: 2024-10-21
host: x86_64-unknown-linux-gnu
release: 1.84.0-nightly
LLVM version: 19.1.1


$ cross run --target mips-unknown-linux-gnu -Zbuild-std
Bus error (core dumped)

As far as I can see from the core dump, the problem is an unaligned lw like in other instances.

@saethlin
Copy link
Member

I can't reproduce that crash. I'm on

Digest: sha256:f7868daaad4efcf7863807eb0e448817b496eaf34f1c95f57bc998cc7353fb3d
Status: Downloaded newer image for ghcr.io/cross-rs/mips-unknown-linux-gnu:0.2.5
rustc 1.84.0-nightly (1e4f10ba6 2024-10-29)
binary: rustc
commit-hash: 1e4f10ba6476e48a42a79b9f846a2d9366525b9e
commit-date: 2024-10-29
host: x86_64-unknown-linux-gnu
release: 1.84.0-nightly
LLVM version: 19.1.1

@purplesyringa
Copy link
Contributor

Hmm. I can reproduce this using the git version of cross (4090beca), and I can't reproduce this on your version (v0.2.5). As expected, the code contains an unaligned lw instruction when compiled with both versions, so it's never been fixed by rustc. But I'm not sure why this didn't trigger SIGBUS under v0.2.5, investigating.

@purplesyringa
Copy link
Contributor

I think I've partially figured it out. cross packs its own version of QEMU in the Docker images. The executable passes on QEMU 5.1.0, packed with cross 0.2.5, and SIGBUSes on QEMU 8.2.2, packed with the latest cross version. There's a three year difference between these versions, so it's quite likely that QEMU only learned to notice unaligned accesses somewhere in that interval.

@saethlin saethlin added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-miscompile Issue: Correct Rust code lowers to incorrect machine code labels Oct 30, 2024
@saethlin
Copy link
Member

I've installed cross from git, so now I'm on

Digest: sha256:367c43176e52bfadd99d6fdeba9ddb63862d264266f588448824f8bf94ae8f3a
Status: Downloaded newer image for ghcr.io/cross-rs/mips-unknown-linux-gnu:main

And I can reproduce the SIGBUS.

@purplesyringa
Copy link
Contributor

I've filed an upstream issue: llvm/llvm-project#114283

@purplesyringa
Copy link
Contributor

LLVM 20 ships with a fix.

@rustbot label +llvm-fixed-upstream

@rustbot rustbot added the llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes label Feb 11, 2025
@purplesyringa
Copy link
Contributor

Rust now ships LLVM 20, and I've verified that my code now works correctly. I think this can be closed.

@saethlin saethlin closed this as completed Jun 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-miscompile Issue: Correct Rust code lowers to incorrect machine code llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes O-MIPS Target: MIPS processors 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

9 participants