Created
January 21, 2014 05:31
-
-
Save seletskiy/8534885 to your computer and use it in GitHub Desktop.
Closures in Pure C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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