Я пытаюсь вручную установить RSP и начать выполнение с пользовательского адреса в Rust с помощью встроенной сборки x86_64.
У меня есть C код, который работает:
#include <stddef.h>
void __attribute ((noreturn)) jump_with_stack(size_t jump_addr, size_t *jump_stack) {
__asm__ volatile ( \
"movq %[stack], %%rsp\n" \
"xor %%rdx, %%rdx\n" \
"jmp *%[entry]" \
: /* None */ \
: [stack] "r" (jump_stack), [entry] "r" (jump_addr) \
: "rdx", "memory" \
);
}
Это это разборка:
jump_with_stack:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi
mov rax, QWORD PTR [rbp-16]
mov rcx, QWORD PTR [rbp-8]
movq rax, %rsp
xor %rdx, %rdx
jmp *rcx
nop
pop rbp
ret
И этот код Rust, который не делает:
#![feature(asm)]
pub unsafe extern fn rust_jump_with_stack(target: usize, targ_stack: *mut usize) -> ! {
asm!("mov rsp, $0
xor rdx, rdx
jmp [$1]"
:
:"r"(targ_stack), "r"(target)
: "rdx", "memory"
: "intel");
unreachable!();
}
Вот ржавчина разборки:
example::rust_jump_with_stack:
push rax
mov rsp, rsi
xor rdx, rdx
jmp qword ptr [rdi]
lea rdi, [rip + .L__unnamed_3]
lea rdx, [rip + .L__unnamed_4]
mov rax, qword ptr [rip + std::panicking::begin_panic@GOTPCREL]
mov esi, 40
call rax
ud2
(Оба выхода разборки от Godbolt Explorer)
Я не понимаю разницы между ними или того, что означает разница в сгенерированном коде.