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

Inline asm: =m constraint on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rustc with SIGSEGV on Linux and 0xC0000005 on Windows #71701

Closed
kennystrawnmusic opened this issue Apr 30, 2020 · 9 comments
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@kennystrawnmusic
Copy link

kennystrawnmusic commented Apr 30, 2020

I tried this code:

//*snip*
/// Struct to store data from all registers in, in event of context switch
#[derive(Debug, Clone, Copy)]
pub struct ContextStore {
    pub rax: usize,
    pub rbx: usize,
    pub rcx: usize,
    pub rdx: usize,
    pub rdi: usize,
    pub rsi: usize,
    pub rbp: usize,
    pub rsp: usize,
    pub r8: usize,
    pub r9: usize,
    pub r10: usize,
    pub r11: usize,
    pub r12: usize,
    pub r13: usize,
    pub r14: usize,
    pub r15: usize,
    pub rip: usize,
    pub rflags: usize,
    pub cs: usize,
    pub ss: usize,
    pub fs: usize,
    pub gs: usize,
    pub fpu_buf: usize, //was giving me problems when attempting to assign as [u8; 512]
    pub avx_buf: usize, //could hold either SSE or AVX depending on what's supported
}

impl ContextStore {

    /// Copy data from all registers, including stack and instruction pointers, into Context instance
    pub fn backup() -> ContextStore {
        let reg_rax: usize;
        let reg_rbx: usize;
        let reg_rcx: usize;
        let reg_rdx: usize;
        let reg_rdi: usize;
        let reg_rsi: usize;
        let reg_rbp: usize;
        let reg_rsp: usize;
        let reg_r8: usize;
        let reg_r9: usize;
        let reg_r10: usize;
        let reg_r11: usize;
        let reg_r12: usize;
        let reg_r13: usize;
        let reg_r14: usize;
        let reg_r15: usize;
        let reg_rip: usize;
        let reg_rflags: usize;
        let reg_cs: usize;
        let reg_ss: usize;
        let reg_fs: usize;
        let reg_gs: usize;
        let fxdest: usize;
        let xdest: usize;

        unsafe {
            llvm_asm!("
                mov %rax, $1"
                :"=r"(reg_rax) ::: "volatile"
            );

            llvm_asm!("
                mov %rbx, $1"
                :"=r"(reg_rbx) ::: "volatile"
            );

            llvm_asm!("
                mov %rcx, $1"
                :"=r"(reg_rcx) ::: "volatile"
            );

            llvm_asm!("
                mov %rdx, $1"
                :"=r"(reg_rdx) ::: "volatile"
            );

            llvm_asm!("
                mov %rdi, $1"
                :"=r"(reg_rdi) ::: "volatile"
            );

            llvm_asm!("
                mov %rsi, $1"
                :"=r"(reg_rsi) ::: "volatile"
            );

            llvm_asm!("
                mov %rbp, $1"
                :"=r"(reg_rbp) ::: "volatile"
            );

            llvm_asm!("
                mov %rsp, $1"
                :"=r"(reg_rsp) ::: "volatile"
            );

            llvm_asm!("
                mov %r8, $1"
                :"=r"(reg_r8) ::: "volatile"
            );

            llvm_asm!("
                mov %r9, $1"
                :"=r"(reg_r9) ::: "volatile"
            );

            llvm_asm!("
                mov %r10, $1"
                :"=r"(reg_r10) ::: "volatile"
            );

            llvm_asm!("
                mov %r11, $1"
                :"=r"(reg_r11) ::: "volatile"
            );

            llvm_asm!("
                mov %r12, $1"
                :"=r"(reg_r12) ::: "volatile"
            );

            llvm_asm!("
                mov %r13, $1"
                :"=r"(reg_r13) ::: "volatile"
            );

            llvm_asm!("
                mov %r14, $1"
                :"=r"(reg_r14) ::: "volatile"
            );

            llvm_asm!("
                mov %r15, $1"
                :"=r"(reg_r15) ::: "volatile"
            );

            llvm_asm!("
                mov %rip, $1"
                :"=r"(reg_rip) ::: "volatile"
            );

            llvm_asm!("
                mov %rflags, $1"
                :"=r"(reg_rflags) ::: "volatile"
            );

            llvm_asm!("
                mov %cs, $1"
                :"=r"(reg_cs) ::: "volatile"
            );

            llvm_asm!("
                mov %ss, $1"
                :"=r"(reg_ss) ::: "volatile"
            );

            llvm_asm!("
                mov %fs, $1"
                :"=r"(reg_fs) ::: "volatile"
            );

            llvm_asm!("
                mov %gs, $1"
                :"=r"(reg_gs) ::: "volatile"
            );

            llvm_asm!("
                fxsave $0"
                :"=m"(fxdest)
            );

            llvm_asm!("
                xsave $0"
                :"=m"(xdest)
            );
        }

        ContextStore {
            rax: reg_rax,
            rbx: reg_rbx,
            rcx: reg_rcx,
            rdx: reg_rdx,
            rdi: reg_rdi,
            rsi: reg_rsi,
            rbp: reg_rbp,
            rsp: reg_rsp,
            r8: reg_r8,
            r9: reg_r9,
            r10: reg_r10,
            r11: reg_r11,
            r12: reg_r12,
            r13: reg_r13,
            r14: reg_r14,
            r15: reg_r15,
            rip: reg_rip,
            rflags: reg_rflags,
            cs: reg_cs,
            ss: reg_ss,
            fs: reg_fs,
            gs: reg_gs,
            fpu_buf: fxdest,
            avx_buf: xdest,
        }
    }

    /// Same as backup(), but mutable for testing purposes. Unsafe for obvious reasons.
    pub unsafe fn backup_as_mut() -> ContextStore {
        let mut reg_rax: usize;
        let mut reg_rbx: usize;
        let mut reg_rcx: usize;
        let mut reg_rdx: usize;
        let mut reg_rdi: usize;
        let mut reg_rsi: usize;
        let mut reg_rbp: usize;
        let mut reg_rsp: usize;
        let mut reg_r8: usize;
        let mut reg_r9: usize;
        let mut reg_r10: usize;
        let mut reg_r11: usize;
        let mut reg_r12: usize;
        let mut reg_r13: usize;
        let mut reg_r14: usize;
        let mut reg_r15: usize;
        let mut reg_rip: usize;
        let mut reg_rflags: usize;
        let mut reg_cs: usize;
        let mut reg_ss: usize;
        let mut reg_fs: usize;
        let mut reg_gs: usize;
        let mut fxdest: usize;
        let mut xdest: usize;

        //Don't know why the compiler is warning about this; llvm_asm! is definitely unsafe
        #[allow(unused_unsafe)]
        unsafe {
            llvm_asm!("
                mov %rax, $1"
                :"=r"(reg_rax) ::: "volatile"
            );

            llvm_asm!("
                mov %rbx, $1"
                :"=r"(reg_rbx) ::: "volatile"
            );

            llvm_asm!("
                mov %rcx, $1"
                :"=r"(reg_rcx) ::: "volatile"
            );

            llvm_asm!("
                mov %rdx, $1"
                :"=r"(reg_rdx) ::: "volatile"
            );

            llvm_asm!("
                mov %rdi, $1"
                :"=r"(reg_rdi) ::: "volatile"
            );

            llvm_asm!("
                mov %rsi, $1"
                :"=r"(reg_rsi) ::: "volatile"
            );

            llvm_asm!("
                mov %rbp, $1"
                :"=r"(reg_rbp) ::: "volatile"
            );

            llvm_asm!("
                mov %rsp, $1"
                :"=r"(reg_rsp) ::: "volatile"
            );

            llvm_asm!("
                mov %r8, $1"
                :"=r"(reg_r8) ::: "volatile"
            );

            llvm_asm!("
                mov %r9, $1"
                :"=r"(reg_r9) ::: "volatile"
            );

            llvm_asm!("
                mov %r10, $1"
                :"=r"(reg_r10) ::: "volatile"
            );

            llvm_asm!("
                mov %r11, $1"
                :"=r"(reg_r11) ::: "volatile"
            );

            llvm_asm!("
                mov %r12, $1"
                :"=r"(reg_r12) ::: "volatile"
            );

            llvm_asm!("
                mov %r13, $1"
                :"=r"(reg_r13) ::: "volatile"
            );

            llvm_asm!("
                mov %r14, $1"
                :"=r"(reg_r14) ::: "volatile"
            );

            llvm_asm!("
                mov %r15, $1"
                :"=r"(reg_r15) ::: "volatile"
            );

            llvm_asm!("
                mov %rip, $1"
                :"=r"(reg_rip) ::: "volatile"
            );

            llvm_asm!("
                mov %rflags, $1"
                :"=r"(reg_rflags) ::: "volatile"
            );

            llvm_asm!("
                mov %cs, $1"
                :"=r"(reg_cs) ::: "volatile"
            );

            llvm_asm!("
                mov %ss, $1"
                :"=r"(reg_ss) ::: "volatile"
            );

            llvm_asm!("
                mov %fs, $1"
                :"=r"(reg_fs) ::: "volatile"
            );

            llvm_asm!("
                mov %gs, $1"
                :"=r"(reg_gs) ::: "volatile"
            );

            llvm_asm!("
                fxsave $0"
                :"=m"(fxdest)
            );

            llvm_asm!("
                xsave $0"
                :"=m"(xdest)
            );
        }

        #[allow(unused_mut)]
        let mut c_stor = ContextStore {
            rax: reg_rax,
            rbx: reg_rbx,
            rcx: reg_rcx,
            rdx: reg_rdx,
            rdi: reg_rdi,
            rsi: reg_rsi,
            rbp: reg_rbp,
            rsp: reg_rsp,
            r8: reg_r8,
            r9: reg_r9,
            r10: reg_r10,
            r11: reg_r11,
            r12: reg_r12,
            r13: reg_r13,
            r14: reg_r14,
            r15: reg_r15,
            rip: reg_rip,
            rflags: reg_rflags,
            cs: reg_cs,
            ss: reg_ss,
            fs: reg_fs,
            gs: reg_gs,
            fpu_buf: fxdest,
            avx_buf: xdest,
        };
        c_stor //return this
    }

    /// Copy data from Context instance provided as method argument into all registers, including stack and instruction pointers
    pub fn restore(ctx: ContextStore) {

        unsafe {

            llvm_asm!("
                mov $0, %rax"
                :
                : "{rax}"(ctx.rax) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rbx"
                :
                : "{rbx}"(ctx.rbx) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rcx"
                :
                : "{rcx}"(ctx.rcx) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rdx"
                :
                : "{rdx}"(ctx.rdx) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rdi"
                :
                : "{rdi}"(ctx.rdi) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rsi"
                :
                : "{rsi}"(ctx.rsi) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rbp"
                :
                : "{rbp}"(ctx.rbp) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rsp"
                :
                : "{rsp}"(ctx.rsp) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r8"
                :
                : "{r8}"(ctx.r8) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r9"
                :
                : "{r9}"(ctx.r9) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r10"
                :
                : "{r10}"(ctx.r10) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r11"
                :
                : "{r11}"(ctx.r11) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r12"
                :
                : "{r12}"(ctx.r12) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r13"
                :
                : "{r13}"(ctx.r13) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r14"
                :
                : "{r14}"(ctx.r14) :: "volatile"
            );

            llvm_asm!("
                mov $0, %r15"
                :
                : "{r15}"(ctx.r15) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rip"
                :
                : "{rip}"(ctx.rip) :: "volatile"
            );

            llvm_asm!("
                mov $0, %rflags"
                :
                : "{rflags}"(ctx.rflags) :: "volatile"
            );

            llvm_asm!("
                mov $0, %cs"
                :
                : "{cs}"(ctx.cs) :: "volatile"
            );

            llvm_asm!("
                mov $0, %ss"
                :
                : "{cs}"(ctx.ss) :: "volatile"
            );

            llvm_asm!("
                mov $0, %fs"
                :
                : "{fs}"(ctx.fs) :: "volatile"
            );

            llvm_asm!("
                mov $0, %gs"
                :
                : "{gs}"(ctx.gs) :: "volatile"
            );

            llvm_asm!("
                fxrstor $0"
                :
                : "m"(ctx.fpu_buf)
            );

            llvm_asm!("
                xrstor $0"
                :
                : "m"(ctx.avx_buf)
            );
        }
    }
}
//*snip*

I expected to see this happen:

I get it, that's a lot of inline assembly, but also highly necessary if you're developing an OS ― and backing up registers to initiate a context switch is one of those areas in which developers have no choice but to get down and dirty.

So, using cargo bootimage ― which definitely worked before I wrote this code ― shouldn't be a problem here, especially given that there are plenty of crates out there that serve, to a degree, as safe abstractions. If the inline assembly has any syntax problems in it (reversed $1 and $0 for example which might be the case here) then the compiler should throw an error, not crash.

Instead, this happened:

No compiler errors are output, but the compiler crashes ― with, exactly as the title says, a segmentation fault, using an Arch Linux host.

Here's the GDB output ― and this is using the copied-and-pasted arguments that cargo bootimage is passing down to rustc whenever I try to build this project:

 sudo gdb /opt/rust/bin/rustc
GNU gdb (GDB) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /opt/rust/bin/rustc...
(gdb) set args --crate-name foundation --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -Cbitcode-in-rlib=no -C debuginfo=2 -C metadata=43bb5f9c010d384a -C extra-filename=-43bb5f9c010d384a --out-dir /home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps --target /home/realkstrawn93/Desktop/foundation/foundation.json -C incremental=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/incremental -L dependency=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps -L dependency=/home/realkstrawn93/Desktop/foundation/target/debug/deps --extern acpi=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libacpi-2468ed628f48cc96.rlib --extern bootloader=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libbootloader-9cc0e1fe6e171121.rlib --extern conquer_once=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libconquer_once-c97aa096525a92d5.rlib --extern crossbeam_queue=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libcrossbeam_queue-b1977b968e889611.rlib --extern embedded_graphics=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libembedded_graphics-1a0e2418ea24d543.rlib --extern embedded_hal=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libembedded_hal-2a0341aff3027e3a.rlib --extern futures=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libfutures-5a4e74d4cf36b338.rlib --extern lazy_static=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/liblazy_static-75eb22ceac96cc86.rlib --extern linked_list_allocator=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/liblinked_list_allocator-f207ac3a6355d05d.rlib --extern pc_keyboard=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libpc_keyboard-fdb3a18b96a076fd.rlib --extern pic8259_simple=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libpic8259_simple-c3975024e57f481b.rlib --extern raw_cpuid=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libraw_cpuid-c7af727af4bd4ba0.rlib --extern spin=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libspin-49552fecbc548142.rlib --extern tinypci=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libtinypci-2049d2f725a17edf.rlib --extern uart_16550=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libuart_16550-2592cdbc4cace607.rlib --extern volatile=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libvolatile-b5909b2d587908c7.rlib --extern x86_64=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libx86_64-3e58c4978b5c685f.rlib --sysroot /home/realkstrawn93/Desktop/foundation/target/sysroot
(gdb) run
Starting program: /opt/rust/bin/rustc --crate-name foundation --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -Cbitcode-in-rlib=no -C debuginfo=2 -C metadata=43bb5f9c010d384a -C extra-filename=-43bb5f9c010d384a --out-dir /home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps --target /home/realkstrawn93/Desktop/foundation/foundation.json -C incremental=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/incremental -L dependency=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps -L dependency=/home/realkstrawn93/Desktop/foundation/target/debug/deps --extern acpi=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libacpi-2468ed628f48cc96.rlib --extern bootloader=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libbootloader-9cc0e1fe6e171121.rlib --extern conquer_once=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libconquer_once-c97aa096525a92d5.rlib --extern crossbeam_queue=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libcrossbeam_queue-b1977b968e889611.rlib --extern embedded_graphics=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libembedded_graphics-1a0e2418ea24d543.rlib --extern embedded_hal=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libembedded_hal-2a0341aff3027e3a.rlib --extern futures=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libfutures-5a4e74d4cf36b338.rlib --extern lazy_static=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/liblazy_static-75eb22ceac96cc86.rlib --extern linked_list_allocator=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/liblinked_list_allocator-f207ac3a6355d05d.rlib --extern pc_keyboard=--Type <RET> for more, q to quit, c to continue without paging--
/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libpc_keyboard-fdb3a18b96a076fd.rlib --extern pic8259_simple=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libpic8259_simple-c3975024e57f481b.rlib --extern raw_cpuid=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libraw_cpuid-c7af727af4bd4ba0.rlib --extern spin=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libspin-49552fecbc548142.rlib --extern tinypci=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libtinypci-2049d2f725a17edf.rlib --extern uart_16550=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libuart_16550-2592cdbc4cace607.rlib --extern volatile=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libvolatile-b5909b2d587908c7.rlib --extern x86_64=/home/realkstrawn93/Desktop/foundation/target/foundation/debug/deps/libx86_64-3e58c4978b5c685f.rlib --sysroot /home/realkstrawn93/Desktop/foundation/target/sysroot
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
process 291019 is executing new program: /opt/rust/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0x7fffef3ff700 (LWP 291023)]
[New Thread 0x7fffecdff700 (LWP 291024)]
[Thread 0x7fffecdff700 (LWP 291024) exited]
[New Thread 0x7fffecdff700 (LWP 291026)]
[New Thread 0x7fffe743b700 (LWP 291027)]
[New Thread 0x7fffe6dff700 (LWP 291028)]
[Thread 0x7fffe6dff700 (LWP 291028) exited]
[New Thread 0x7fffe6dff700 (LWP 291029)]
[New Thread 0x7fffe65ff700 (LWP 291030)]
[Thread 0x7fffe6dff700 (LWP 291029) exited]
[New Thread 0x7fffe6dff700 (LWP 291031)]
[New Thread 0x7fffe5b7f700 (LWP 291032)]
[Thread 0x7fffe65ff700 (LWP 291030) exited]
[New Thread 0x7fffe65ff700 (LWP 291033)]
[Thread 0x7fffe6dff700 (LWP 291031) exited]
[New Thread 0x7fffe6dff700 (LWP 291034)]
[Thread 0x7fffe5b7f700 (LWP 291032) exited]
[Thread 0x7fffe65ff700 (LWP 291033) exited]
[New Thread 0x7fffe65ff700 (LWP 291035)]
[Thread 0x7fffe6dff700 (LWP 291034) exited]
[New Thread 0x7fffe6dff700 (LWP 291036)]
[New Thread 0x7fffe5b7f700 (LWP 291037)]
[New Thread 0x7fffe53ff700 (LWP 291038)]
[Thread 0x7fffe5b7f700 (LWP 291037) exited]
[Thread 0x7fffe6dff700 (LWP 291036) exited]
[Thread 0x7fffe65ff700 (LWP 291035) exited]
[New Thread 0x7fffe5b7f700 (LWP 291039)]
[Thread 0x7fffe53ff700 (LWP 291038) exited]
[New Thread 0x7fffe53ff700 (LWP 291040)]
[Thread 0x7fffe5b7f700 (LWP 291039) exited]
[New Thread 0x7fffe5b7f700 (LWP 291041)]
--Type <RET> for more, q to quit, c to continue without paging--

Thread 19 "rustc" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe5b7f700 (LWP 291041)]
0x00007ffff1cb7b1e in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) ()
   from /opt/rust/toolchains/nightly-x86_64-unknown-linux-gnu/bin/../lib/../lib/libLLVM-9-rust-1.45.0-nightly.so

Note that it's actually rustc itself that's segfaulting here ― this here is why I didn't file any bug reports with the cargo-bootimage crate maintainers: cargo bootimage invokes rustc to actually do the compiling, using a custom set of parameters that the above gdb output is preserving for posterity.

Also, the instruction that rustc is segfaulting in ― again, according to GDB ― is very clearly a line of LLVM inline assembly parsing code: llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) ()

Since this is really the only part of my project in which I use any inline assembly at all (the x86_64 crate is of great help elsewhere), I am fairly confident that the problem here is that something in Rust's LLVM implementation just can't handle this much inline assembly at one time. Hopefully there's a way to improve this upstream.

@kennystrawnmusic kennystrawnmusic added the C-bug Category: This is a bug. label Apr 30, 2020
@kennystrawnmusic kennystrawnmusic changed the title SIGSEGV on cargo bootimage attempt when llvm_asm! is being used SIGSEGV on cargo bootimage attempt when large quantities of llvm_asm! is used Apr 30, 2020
@kennystrawnmusic kennystrawnmusic changed the title SIGSEGV on cargo bootimage attempt when large quantities of llvm_asm! is used Compiler segfaults on cargo bootimage attempt when large quantities of llvm_asm! is used Apr 30, 2020
@kennystrawnmusic kennystrawnmusic changed the title Compiler segfaults on cargo bootimage attempt when large quantities of llvm_asm! is used rustc crashes with SIGSEGV on cargo bootimage attempt when large quantities of llvm_asm! is used Apr 30, 2020
@kennystrawnmusic kennystrawnmusic changed the title rustc crashes with SIGSEGV on cargo bootimage attempt when large quantities of llvm_asm! is used rustc crashes with SIGSEGV in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) () Apr 30, 2020
@kennystrawnmusic kennystrawnmusic changed the title rustc crashes with SIGSEGV in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) () rustc crashes with SIGSEGV in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) () on cargo bootloader attempt Apr 30, 2020
@jonas-schievink jonas-schievink added A-inline-assembly Area: Inline assembly (`asm!(…)`) 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. requires-nightly This issue requires a nightly compiler in some way. labels Apr 30, 2020
@mati865
Copy link
Contributor

mati865 commented Apr 30, 2020

Could you post rustc -vV and nightly version which has worked before?

@kennystrawnmusic
Copy link
Author

kennystrawnmusic commented Apr 30, 2020

$ rustc -vV
rustc 1.45.0-nightly (fa51f810e 2020-04-29)
binary: rustc
commit-hash: fa51f810e5b9254904b92660e7280b7d6a46f112
commit-date: 2020-04-29
host: x86_64-unknown-linux-gnu
release: 1.45.0-nightly
LLVM version: 9.0

And the last nightly to work was one from March ― but that was also from before I wrote the code that triggers the crash.

@kennystrawnmusic
Copy link
Author

kennystrawnmusic commented Apr 30, 2020

Tried switching the argument identifiers around (i.e. $0 in the backup method and $1 in the restore method, as opposed to the other way around). Still crashes despite this change, so definitely not a programming error on my part.

@kennystrawnmusic kennystrawnmusic changed the title rustc crashes with SIGSEGV in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) () on cargo bootloader attempt rustc crashes with SIGSEGV in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) () on cargo bootimage attempt May 1, 2020
@kennystrawnmusic
Copy link
Author

Updated title to fix command-line typo

@kennystrawnmusic
Copy link
Author

kennystrawnmusic commented May 4, 2020

Tested on Windows 10 too using VSCode — same problem:

Caused by:
  process didn't exit successfully: `rustc --crate-name foundation --edition=2018 src\main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -Cbitcode-in-rlib=no -C debuginfo=2 -C metadata=60de9187690c6bae -C extra-filename=-60de9187690c6bae --out-dir C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps --target \\?\C:\Users\straw\OneDrive\Desktop\foundation\foundation.json -C incremental=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\incremental -L dependency=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps -L dependency=C:\Users\straw\OneDrive\Desktop\foundation\target\debug\deps --extern acpi=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libacpi-911e99990d1370c4.rlib --extern bootloader=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libbootloader-feade19b8e251328.rlib --extern conquer_once=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libconquer_once-a2aba22aab6db5b6.rlib --extern crossbeam_queue=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libcrossbeam_queue-b20f8af9651d403f.rlib --extern embedded_graphics=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libembedded_graphics-66ba73ef75c38921.rlib --extern embedded_hal=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libembedded_hal-1e397f2a27a0447d.rlib --extern futures=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libfutures-a87e7ff1798fecb7.rlib --extern lazy_static=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\liblazy_static-dbc34cf01993b890.rlib --extern linked_list_allocator=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\liblinked_list_allocator-9fee535727fb8f51.rlib --extern pc_keyboard=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libpc_keyboard-3ae60d4904d8c86c.rlib --extern pic8259_simple=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libpic8259_simple-9c0dc24a4430f246.rlib --extern raw_cpuid=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libraw_cpuid-489f44f947e82819.rlib --extern spin=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libspin-3e5a86b1502513a4.rlib --extern tinypci=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libtinypci-aa4d12055b01e3b8.rlib --extern uart_16550=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libuart_16550-2d93cf0f842439c9.rlib --extern volatile=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libvolatile-16e5c1084e3ba27b.rlib --extern x86_64=C:\Users\straw\OneDrive\Desktop\foundation\target\foundation\debug\deps\libx86_64-63e41976cc62d233.rlib --sysroot C:\Users\straw\OneDrive\Desktop\foundation\target/sysroot` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
Error: Kernel build failed

Again: no idea why the LLVM is having trouble building the selection DAG. Only thing I can think of is that perhaps something in the prelude is interfacing with my inline asm in a way that is causing an endless selection DAG building loop that overruns the buffer; trying something else.

@kennystrawnmusic
Copy link
Author

kennystrawnmusic commented May 4, 2020

After further testing and further code modification I now know what’s triggering this bug: it’s the =m operand, and it makes sense now that I think about it — if you send something to a memory address of an uninitialized variable, that constitutes dereferencing a null pointer.

That’s still no excuse for the compiler crash though; Rust needs to throw an error instead.

@kennystrawnmusic kennystrawnmusic changed the title rustc crashes with SIGSEGV in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) () on cargo bootimage attempt Inline asm: =m operand causes the SelectionDAGBuilder to crash with SIGSEGV on Linux and 0xC0000005 on Windows May 5, 2020
@kennystrawnmusic kennystrawnmusic changed the title Inline asm: =m operand causes the SelectionDAGBuilder to crash with SIGSEGV on Linux and 0xC0000005 on Windows Inline asm: =m operand on uninitialized object variable in “impl” block causes the SelectionDAGBuilder to crash with SIGSEGV on Linux and 0xC0000005 on Windows May 5, 2020
@kennystrawnmusic kennystrawnmusic changed the title Inline asm: =m operand on uninitialized object variable in “impl” block causes the SelectionDAGBuilder to crash with SIGSEGV on Linux and 0xC0000005 on Windows Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash with SIGSEGV on Linux and 0xC0000005 on Windows May 5, 2020
@kennystrawnmusic kennystrawnmusic changed the title Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash with SIGSEGV on Linux and 0xC0000005 on Windows Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rusty with SIGSEGV on Linux and 0xC0000005 on Windows May 5, 2020
@kennystrawnmusic kennystrawnmusic changed the title Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rusty with SIGSEGV on Linux and 0xC0000005 on Windows Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rustC with SIGSEGV on Linux and 0xC0000005 on Windows May 5, 2020
@kennystrawnmusic kennystrawnmusic changed the title Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rustC with SIGSEGV on Linux and 0xC0000005 on Windows Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rustc with SIGSEGV on Linux and 0xC0000005 on Windows May 5, 2020
@kennystrawnmusic kennystrawnmusic changed the title Inline asm: =m operand on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rustc with SIGSEGV on Linux and 0xC0000005 on Windows Inline asm: =m constraint on uninitialized object variable in impl block causes the SelectionDAGBuilder to crash rustc with SIGSEGV on Linux and 0xC0000005 on Windows May 5, 2020
@kennystrawnmusic
Copy link
Author

kennystrawnmusic commented May 5, 2020

Updated the title to better reflect the additional information gathered from further testing and further editing.

What needs to happen: Rust needs to throw error: cannot use =m on address that does not exist instead of passing this to LLVM and crashing in the process.

@Amanieu
Copy link
Member

Amanieu commented May 8, 2020

=m constraints are broken and have always been. Use =*m and pass the address of the memory instead of the memory itself.

I would also like to point out that your code is also broken in multiple ways:

  • The compiler is free to insert arbitrary code between llvm_asm! blocks. This means that there is no guarantee that the registers will keep the value you set them to.
  • Your instruction operands are the wrong way around for AT&T syntax.
  • Operands are index from $0, not $1.
  • You can't write to the rip or cs registers. You need to use a jump instruction.
  • You can't use segment registers (ds) as operands to inline assembly.

Basically, the whole function should be implemented as a single inline assembly block.

@Amanieu
Copy link
Member

Amanieu commented May 22, 2020

This issue does not apply to the new asm! (RFC 2850) which doesn't support memory constraints.

The legacy llvm_asm! is deprecated and is no longer maintained.

@Amanieu Amanieu closed this as completed May 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. requires-nightly This issue requires a nightly compiler in some way. 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

4 participants