#if _WIN32
# define WIN32_LEAN_AND_MEAN 1
# include <windows.h>
#else
# include <sys/mman.h>
#endif
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef struct execMem_s {
union { void *p; int(*fn)(int x); } ptr;
size_t n;
struct execMem_s *prev, *next;
} execMem_t;
execMem_t *g_execMem_head = (execMem_t *)0;
execMem_t *g_execMem_tail = (execMem_t *)0;
execMem_t *NewExecMem(size_t n) {
execMem_t *execMem;
execMem = (execMem_t *)malloc(sizeof(*execMem));
if (!execMem)
exit(EXIT_FAILURE);
#if _WIN32
execMem->ptr.p = VirtualAlloc(0, n, MEM_COMMIT|MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
#else
execMem->ptr.p = mmap(0, n, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_ANON|MAP_PRIVATE, 0, 0);
#endif
if (!execMem->ptr.p) {
free((void *)execMem);
exit(EXIT_FAILURE);
}
execMem->n = n;
execMem->next = (execMem_t *)0;
if ((execMem->prev = g_execMem_tail) != (execMem_t *)0)
g_execMem_tail->next = execMem;
else
g_execMem_head = execMem;
g_execMem_tail = execMem;
return execMem;
}
execMem_t *DeleteExecMem(execMem_t *execMem) {
if (!execMem)
return (execMem_t *)0;
#if _WIN32
VirtualFree(execMem->ptr.p, 0, MEM_RELEASE);
#else
munmap(execMem->ptr.p, execMem->n);
#endif
if (execMem->prev)
execMem->prev->next = execMem->next;
if (execMem->next)
execMem->next->prev = execMem->prev;
if (g_execMem_head==execMem)
g_execMem_head = execMem->next;
if (g_execMem_tail==execMem)
g_execMem_tail = execMem->prev;
free((void *)execMem);
return (execMem_t *)0;
}
void *ExecMemPtr(execMem_t *execMem) {
return execMem->ptr.p;
}
int main() {
static const int x = 5;
unsigned char prog[] = {
#if 0
0xB8, 0x2A, 0x00, 0x00, 0x00, /*mov eax, 0x2A*/
0xC3 /*retn*/
#else
0x8B, 0x44, 0x24, 0x04, /*mov eax, [esp+4]*/
0x83, 0xC0, 0x0E, /*add eax, byte 0x0E*/
0xC3 /*retn*/
#endif
};
execMem_t *execMem;
execMem = NewExecMem(sizeof(prog));
printf("Hello, world!\n");
fflush(stdout);
memcpy(execMem->ptr.p, &prog[0], sizeof(prog));
printf("execMem->ptr.fn(%i) -> %i\n", x, execMem->ptr.fn(x));
fflush(stdout);
DeleteExecMem(execMem);
return 0;
}