将现有函数复制到内存缓冲区中

我试图加载一个函数到映射的内存缓冲区,稍后调用它,所以我做了一个testing用例来试验:

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()); } 

哪些工作正常,但只要我尝试做甚至微不足道的事情,我会得到一个段错误。

我试图做一个简单的variables赋值,像这样:

 int x; auto func() -> void{ x = 5; } 

现在我的函数调用segfaults。 我已经适当地改变了缓冲区的大小,并确保正确的内存正在写入缓冲区。

我在这里错过了多less重要的信息? 为什么我不能这样做?

PS请不要给我讲解不安全的代码,这是一个简单的个人学习练习。

忽略这样一个事实,即这是明显的未定义的行为,如果你做一个全局变量的分配,生成的代码可能会使用相对寻址来引用某些体系结构上的变量。

也就是说,函数期望自己和x在一个给定的地址,如果你移动它,事情就会中断。

这是我的GCC为您的测试功能生成的:

 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 

请注意movl $5, x(%rip) ,这意味着代码使用自己的地址(存储在%rip中)来计算x的位置并在其中存储5。

所以总之,没有简单的方法来做你想做的事情,除非你确定你的函数只有位置无关的代码 。 即使如此,这只是要求麻烦。