Skip to content

Instantly share code, notes, and snippets.

@jaz303
Created December 15, 2014 13:55
Show Gist options
  • Save jaz303/f2dc513f5c20353a2888 to your computer and use it in GitHub Desktop.
Save jaz303/f2dc513f5c20353a2888 to your computer and use it in GitHub Desktop.
Interruptible VM with signal handlers
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
typedef enum opcode {
OP_HALT = 0,
OP_NOP,
OP_JMP,
OP_MAX
} opcode_t;
typedef struct ins {
char i;
char o;
} ins_t;
void **jump_table_hack;
void exec(ins_t*, void***);
static void catch_signal(int signo) {
puts("abort requested!\n");
// caught a SIGINT - rewrite the opcode handlers so that
// every instruction is handled as OP_HALT - this forces
// the VM to exit with clobbering the input program
for (int i = 1; i < OP_MAX; ++i) {
jump_table_hack[i] = jump_table_hack[0];
}
}
int main(int argc, char *argv[]) {
// steal the jump table so the signal handler
// can rewrite it to force program abort
exec(NULL, &jump_table_hack);
// program that loops forever
ins_t myprog[] = {
{ OP_NOP, 0 },
{ OP_JMP, 0 }
};
// install signal handler
if (signal(SIGINT, catch_signal) == SIG_ERR) {
fputs("boom\n", stderr);
return EXIT_FAILURE;
}
// run the program
exec(myprog, NULL);
return 0;
}
void exec(ins_t *program, void ***jump_table_out) {
static void *jump_table[] = {
&&L_HALT,
&&L_NOP,
&&L_JMP
};
if (jump_table_out) {
*jump_table_out = (void**)&jump_table;
return;
}
int ip = 0;
goto *(jump_table[program[ip].i]);
L_HALT:
puts("interpreter exited gracefully!\n");
return;
L_NOP:
printf("NOP!\n");
goto *jump_table[program[++ip].i];
L_JMP:
ip = program[ip].o;
goto *jump_table[program[ip].i];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment