I am implementing a JIT (for studies) and I would like to know if it is possible to run opcodes, without using mmap, since I am 'playing' on an operating system that MMAP does not have the MAP_ANONYMOUS definition for.
The JIT code:
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int main () {
// Hexadecimal x86_64 machine code for: int mul (int a, int b) { return a * b; }
unsigned char code [] = {
0x55, // push rbp
0x48, 0x89, 0xe5, // mov rbp, rsp
0x89, 0x7d, 0xfc, // mov DWORD PTR [rbp-0x4],edi
0x89, 0x75, 0xf8, // mov DWORD PTR [rbp-0x8],esi
0x8b, 0x75, 0xfc, // mov esi,DWORD PTR [rbp-04x]
0x0f, 0xaf, 0x75, 0xf8, // imul esi,DWORD PTR [rbp-0x8]
0x89, 0xf0, // mov eax,esi
0x5d, // pop rbp
0xc3 // ret
};
// allocate executable memory via sys call
void* mem = mmap(NULL, sizeof(code), PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// copy runtime code into allocated memory
memcpy(mem, code, sizeof(code));
// typecast allocated memory to a function pointer
int (*func) () = mem;
// call function pointer
printf("%d * %d = %d\n", 5, 11, func(5, 11));
// Free up allocated memory
munmap(mem, sizeof(code));
}
If I recall correctly, before the invention of MAP_ANONYMOUS
, the standard way to map non-file-backed memory was to open /dev/zero
and map it like a file. If your system has mmap
at all, I would expect this to work.
Otherwise, you can allocate memory any way you like, and use mprotect
to make it executable. Note that you will want to ensure that your code is aligned and padded to page boundaries, so that you don't inadvertently change the protections on other parts of the program. posix_memalign
is a good way to do this, or the older valloc
.