Skip to content

Instantly share code, notes, and snippets.

@karthick18
Created July 1, 2011 06:27
Show Gist options
  • Save karthick18/1057979 to your computer and use it in GitHub Desktop.
Save karthick18/1057979 to your computer and use it in GitHub Desktop.
An example closure in C that requires MAP_32BIT to work with 64 bit
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#ifndef MAP_32BIT
#error "MAP_32BIT not defined"
#endif
struct scope
{
void *args;
};
struct thunk
{
unsigned char push_op; /* push rdi */
unsigned char mov_op[2]; /* mov $env, rdi */
struct scope *scope;
unsigned char call_op; /* callq */
int call_offset; /*$offset => function - address_of_call_offset*/
unsigned char pop_op; /* popq rdi */
unsigned char ret_op; /* ret */
} __attribute__((packed));
static struct thunk initialize_thunk = { .push_op = 0x57, .mov_op = {0x48, 0xbf},
.call_op = 0xe8, .call_offset = 0,
.pop_op = 0x5f, .ret_op = 0xc3
};
typedef void (*closure_t)(void);
static void closure_block(struct scope *scope)
{
int *acc = scope->args;
++*acc;
}
/*
* Take a scope and the function block to be bound to the scope.
*/
static closure_t make_closure(void *arg, void *block)
{
struct thunk *thunk = (struct thunk *)mmap(0, sizeof(*thunk), PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT,
-1, 0);
if((char*)thunk == MAP_FAILED)
return NULL;
*thunk = initialize_thunk;
thunk->scope = calloc(1, sizeof(*thunk->scope));
if(!thunk->scope)
{
goto out_free;
}
thunk->scope->args = arg;
thunk->call_offset = (long)block - (long)&thunk->pop_op;
mprotect((void*)thunk, sizeof(*thunk), PROT_EXEC);
return (closure_t)thunk;
out_free:
munmap(thunk, sizeof(*thunk));
return (closure_t)NULL;
}
static closure_t closure;
static void update(int n)
{
int i;
for(i = 0; i < n; ++i) closure();
}
int main(int argc, char **argv)
{
int acc = 0, c = 10;
closure = make_closure((void*)&acc, (void*)&closure_block);
update(argc > 1 ? (c=atoi(argv[1])) : c);
printf("Accumulator at [%d]\n", acc);
return 0;
}
@HaskellZhangSong
Copy link

[1] 2763 segmentation fault ./a.out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment