I'm expermenting with function pointers on Linux and trying to execute this C program:
#include <stdio.h>
#include <string.h>
int myfun()
{
return 42;
}
int main()
{
char data[500];
memcpy(data, myfun, sizeof(data));
int (*fun_pointer)() = (void*)data;
printf("%d\n", fun_pointer());
return 0;
}
Unfortunately it segfaults on fun_pointer()
call. I suspect that it is connected with some memory flags, but I don't found information about it.
Could you explain why this code segfaults? Don't see to the fixed data
array size, it is ok and copying without calling the function is successfull.
UPD: Finally I've found that the memory segment should be marked as executable using mprotect system call called with PROT_EXEC
flag. Moreover the memory segment should be returned by mmap function as stated in the POSIX specification.
There is the same code that uses allocated by mmap
memory with PROT_EXEC
flag (and works):
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int myfun()
{
return 42;
}
int main()
{
size_t size = (char*)main - (char*)myfun;
char *data = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
memcpy(data, myfun, size);
int (*fun_pointer)() = (void*)data;
printf("%d\n", fun_pointer());
munmap(data, size);
return 0;
}
This example should be complied with -fPIC
gcc option to ensure that the code in functions is position-independent.
For a program to execute as a process, it has to be loaded into memory via a program loader. The executable file that contains the program consists of several sections that identify different regions of the program and where they should be loaded into memory.
Program is a passive entity as it resides in the secondary memory. Process is a active entity as it is created during execution and loaded into the main memory. 3.
Load an executable file into memory. This is done through the exec (now execve ) system call. During this call, 3 main memory areas, called regions are filled: The text region, which consists of a set of instructions your process is to follow : basically, your program.
Several problems there:
data
array stays in data segment, not in code segment.In addition to Diask's answer you probably want to use some JIT compilation techniques (to generate executable code in memory), and you should be sure that the memory zone containing the code is executable (see mprotect(2) and the NX bit; often the call stack is not executable for security reasons). You could use GNU lightning (quickly emitting slow machine code), asmjit, libjit, LLVM, GCCJIT (able to slowly emit fast optimized machine code). You could also emit some C code in some temporary file /tmp/emittedcode.c
, fork a compilation command gcc -Wall -O -fPIC -shared /tmp/emittedcode.c -o /tmp/emittedcode.so
then dlopen(3) that shared object /tmp/emittedcode.so
and use dlsym(3) to find function pointers by their name there.
See also this, this, this, this and that answers. Read about trampoline code, closures, and continuations & CPS.
Of course, copying code from one zone to another usually don't work (it has to be position independent code to make that work, or you need your own relocation machinery, a bit like a linker does).
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