Skip to content

Instantly share code, notes, and snippets.

@seletskiy
Created January 21, 2014 05:31
Show Gist options
  • Select an option

  • Save seletskiy/8534885 to your computer and use it in GitHub Desktop.

Select an option

Save seletskiy/8534885 to your computer and use it in GitHub Desktop.
Closures in Pure C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#define FUNC1_PLACEHOLDER 0xDEADBEEFABADF00D
int func1() {
int *ptr = (int*)FUNC1_PLACEHOLDER;
return *ptr;
}
int func1_end() {};
typedef struct closure_t {
int (*call)();
void **ctx;
int length;
} closure_t;
void closure_create(long start, long end, long placeholder, closure_t* c) {
int length = end - start;
int ptr;
if (mprotect(c->call, getpagesize(), PROT_READ|PROT_EXEC|PROT_WRITE) == -1) {
return;
}
c->length = length;
memcpy(c->call, (void*)start, length);
for (ptr = 0; ptr < length; ptr++) {
long* memptr = (long*)(c->call + ptr);
if (*memptr == placeholder) {
c->ctx = (void*)memptr;
}
printf("%2x ", *((unsigned char *)(c->call + ptr)));
}
printf("\n");
}
void closure_embed_ctx(closure_t* c, void *ctx) {
*(c->ctx) = ctx;
}
int main() {
int *test_val1 = malloc(sizeof(int));
int *test_val2 = malloc(sizeof(int));
closure_t closure;
closure.call = valloc(getpagesize());
closure_create((long)func1, (long)func1_end, FUNC1_PLACEHOLDER, &closure);
printf("closure->call = %p\n", closure.call);
printf("closure->ctx = %p\n", closure.ctx);
printf("closure->length = %p\n", closure.length);
*test_val1 = 1234;
printf("*[%p] = %d\n", test_val1, *test_val1);
closure_embed_ctx(&closure, test_val1);
printf("val1 closure call = %d\n", closure.call());
*test_val2 = 4321;
printf("*[%p] = %d\n", test_val2, *test_val2);
closure_embed_ctx(&closure, test_val2);
printf("val2 closure call = %d\n", closure.call());
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment