I'm trying to load a function into a mapped memory buffer and call it later so I've made a test case to try out:
auto func() -> void{
asm(
"nop;"
"nop;"
"nop;"
"nop;"
);
}
auto main(int argc, char *argv[]) -> int{
void *exec_mem = mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// check errors here
memcpy(exec_mem, reinterpret_cast<const void*>(func), 5); // size is known
(reinterpret_cast<void(*)()>(exec_mem))(); // function call
munmap(exec_mem, getpagesize());
}
Which works fine, but as soon as I try to do something even trivial I get a segfault.
I tried to do a simple variable assignment like this:
int x;
auto func() -> void{
x = 5;
}
and now my function call segfaults. I have changed the buffer size appropriately and am certain the correct memory is being written into the buffer.
What important piece of information am I missing here? Why can't I do this?
P.S. Please don't lecture me on unsafe code, this is a simple personal learning exercise.
Ignoring the fact that this is blatant undefined behavior, if you do an assignment of a global variable, the generated code is likely to use relative addressing to reference the variable on some architectures.
That is, the function expects itself and x to be at a given address, and if you move it, things break.
This is what my GCC generates for your test function:
x:
.zero 4
.text
.globl _Z4funcv
.type _Z4funcv, @function
_Z4funcv:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $5, x(%rip)
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
Note the movl $5, x(%rip)
, which means that the code uses its own address (stored in %rip) to compute the position of x
and store 5 in it.
So in short, there's no simple way to do what you're trying to do, unless you make sure that your function only has position-independent code. And even then, it's only asking for trouble.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With