Skip to content

Instantly share code, notes, and snippets.

@skeeto
Last active December 12, 2025 01:34
Show Gist options
  • Select an option

  • Save skeeto/443ff430fd5aa1eb0e11a701adc021de to your computer and use it in GitHub Desktop.

Select an option

Save skeeto/443ff430fd5aa1eb0e11a701adc021de to your computer and use it in GitHub Desktop.
.section .exebuf,"bwx"
.globl exebuf
exebuf: .space 1<<12
// Ref: https://old.reddit.com/r/C_Programming/comments/1pk6oql/
// Ref: https://lowkpro.com/blog/creating-c-closures-from-lua-closures.html
#include <stddef.h>
#include <stdio.h>
typedef struct {
char *beg;
char *end;
} Arena;
Arena get_exec_arena()
{
extern char exebuf[1<<12];
return (Arena){exebuf, exebuf+sizeof(exebuf)};
}
char *store(char *p, int v)
{
p[0] = v >> 0;
p[1] = v >> 8;
p[2] = v >> 16;
p[3] = v >> 24;
return p + 4;
}
char *asm_store(char *p, int *dst, int value)
{
int rel = (char *)dst - (p + 10);
*p++ = 0xc7;
*p++ = 0x05;
p = store(p, rel);
p = store(p, value);
return p;
}
char *asm_jmp(char *p, void *dst)
{
int rel = (char *)dst - p - 5;
*p++ = 0xe9;
p = store(p, rel);
return p;
}
int findex;
void callback(char *s)
{
printf("callback-%d(\"%s\")\n", findex, s);
}
void *generate_function(Arena *a, int closed_over_findex)
{
char *f = a->beg;
a->beg = asm_store(a->beg, &findex, closed_over_findex);
a->beg = asm_jmp(a->beg, callback);
return f;
}
int main()
{
Arena exe = get_exec_arena();
void (*funcs[10])(char *);
for (int i = 0; i < 10; i++) {
funcs[i] = generate_function(&exe, i);
}
funcs[4]("hello");
funcs[2]("world");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment