Closed 5-pebbles closed 2 weeks ago
By using extern "C" fn
, you tell the compiler to use the system C ABI. This will cause it to insert a prologue that makes assumptions that are upheld by the C ABI.
But _start is not called with the C ABI, it's different. You need to mark the function it as #[naked]
or use global_asm!
to define _start
to get precise control and set up something the C ABI is happy with.
For an example, see origin: https://github.com/sunfishcode/origin/blob/287fd6923ad86ea787422ffb49efcdf1df0c6093/src/arch/x86_64.rs#L29
The x86_64 Linux target (specifically the psABI: https://gitlab.com/x86-psABIs/x86-64-ABI) requires that the stack is 16-byte aligned before a call instruction is executed. Since that pushes the return address on the stack, the ABI requires rsp % 16 == 8 on function entry. So the generated code seems correct: it adjusts rsp by 0x88 so it’s 16 byte aligned afterwards. It crashes because rsp wasn’t aligned as required, shuffling code around so that it doesn’t generate movaps instructions doesn’t fix the problem.
The psABI also says that rsp is 16-byte aligned on entry to _start, so I guess you can’t define that function like any other. There may also be other oddities that you need to accommodate if you define your own _start. If you absolutely must do so, you could implement it in assembly, in a Rust file as naked function (100% assembly) or you could wait for something like https://github.com/rust-lang/rfcs/pull/3594
Alright, that makes sense. Thank you both very much!
When running the following code on Linux, I would expect it to create a
fmt::Arguments
and then exit:Instead, the process is terminated by signal SIGSEGV (Address boundary error). As far as I can tell the same thing occurs when using the standard library.
The error seems to be caused by a misaligned movaps instruction:
On this line:
1129: 0f 29 44 24 5 movaps %xmm0,0x50(%rsp)
the stack pointer is not 16 byte aligned as is required by movaps.This example does not produce the error at optimization levels other than 0, however I expect the issue is still present. The
fmt::Arguments
is just constructed at compile time.The issue can be negated by adding an arbitrary arithmetic operation after the format. This causes the compiler to replace the movaps with mov:
Is this is expected behavior, if so how can I prevent it?
Command
rustc --version --verbose