Estoy tratando de cargar una función en un búfer de memoria mapeado y llamarla más tarde, así que hice un caso de prueba para probar:
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()); }Lo cual funciona bien, pero tan pronto como trato de hacer algo incluso trivial, obtengo un error de segmento.
Traté de hacer una asignación de variable simple como esta:
int x; auto func() -> void{ x = 5; }y ahora mi función llama a segfaults. Cambié el tamaño del búfer correctamente y estoy seguro de que se está escribiendo la memoria correcta en el búfer.
¿Qué información importante me estoy perdiendo aquí? ¿Por qué no puedo hacer esto?
PD Por favor, no me den lecciones sobre códigos inseguros, este es un simple ejercicio de aprendizaje personal.
Ignorando el hecho de que este es un comportamiento evidentemente indefinido, si realiza una asignación de una variable global, es probable que el código generado use direccionamiento relativo para hacer referencia a la variable en algunas arquitecturas.
Es decir, la función espera que ella misma y x estén en una dirección dada, y si la mueves, las cosas se rompen.
Esto es lo que genera mi GCC para su función de prueba:
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 Tenga en cuenta el movl $5, x(%rip) , lo que significa que el código usa su propia dirección (almacenada en %rip) para calcular la posición de x y almacenar 5 en ella.
En resumen, no hay una manera simple de hacer lo que está tratando de hacer, a menos que se asegure de que su función solo tenga código independiente de la posición . E incluso entonces, solo está buscando problemas.