I am wrapping a low level ABI in Rust, taking advantage of the naked
function feature. Here is my code and relevant disassembly
#![feature(asm)]
#![feature(naked_functions)]
struct MyStruct {
someVar: i64, // not important
// ...
}
impl MyStruct {
#[naked]
extern "C" fn wrap(&self) {
unsafe {
asm!("NOP" :::: "volatile");
// not sure if the volatile option is needed, but I
// figured it wouldn't hurt
}
}
}
Disassembled with LLDB:
ABIWrap`ABIWrap::{{impl}}::wrap:
* 0x100001310 <+0>: movq %rdi, -0x10(%rbp)
* 0x100001314 <+4>: movq %rsi, -0x8(%rbp)
* 0x100001318 <+8>: movq -0x10(%rbp), %rax
* 0x10000131c <+12>: movq -0x8(%rbp), %rcx
* 0x100001320 <+16>: movq %rax, -0x20(%rbp)
* 0x100001324 <+20>: movq %rcx, -0x18(%rbp)
0x100001328 <+24>: nop
0x100001329 <+25>: retq
0x10000132a <+26>: nopw (%rax,%rax)
The 6 lines preceding the NOP (I've marked with *
) are what I am confused by. Shouldn't the naked
directive leave, for lack of a better term, a naked function?
I am attempting to allow the arguments to just pass through this function to the ABI as it follows roughly the same calling convention as Rust, I just need to swap one or two of the registers, hence the inline assembly.
Is there a way to get rid of these 6 preceding instructions? I am calling against the ABI a lot and the previous way I was calling against it was causing a decent amount of overhead. I want to make sure that the registers containing any important values aren't overwritten.
Side note: is the "volatile" option needed? I wasn't sure but added it anyways.
After tinkering with this more, (and figuring how to effectively disassemble my release build), I found that the extra instructions are only added during the debug build (or at least when -O0).
When compiling the code with -O2, I found that all of the assembly was inlined, but that is easily fixed with an #[inline(never)]
directive. Now the arguments are being passed correctly without the extra instructions ruining my registers :)
Now I just need to have the code only run -O2 on just these functions and not the rest of the debug build...