#include #include #include #include #include #include #include #include #include "scheme.h" #define mask(x,m) (((int)(x)) & (int)(m)) #define unshift(n) (((int)(n)) >> fx_shift) #define shift(n) ((ptr)((n) << fx_shift)) #define ref(x,i) (*((ptr*)((x)+(i)))) #define pagesize 4096 static void install_handlers(); static char* char_string[128] = { "#\\nul","#\\soh","#\\stx","#\\etx","#\\eot","#\\enq","#\\ack","#\\bel", "#\\bs", "#\\tab","#\\lf", "#\\vt", "#\\ff", "#\\cr", "#\\so", "#\\si", "#\\dle","#\\dc1","#\\dc2","#\\dc3","#\\dc4","#\\nak","#\\syn","#\\etb", "#\\can","#\\em", "#\\sub","#\\esc","#\\fs", "#\\gs", "#\\rs", "#\\us", "#\\space","#\\!","#\\\"","#\\#","#\\$","#\\%","#\\&","#\\'", "#\\(","#\\)","#\\*","#\\+","#\\,","#\\-","#\\.","#\\/", "#\\0","#\\1","#\\2","#\\3","#\\4","#\\5","#\\6","#\\7", "#\\8","#\\9","#\\:","#\\;","#\\<","#\\=","#\\>","#\\?", "#\\@","#\\A","#\\B","#\\C","#\\D","#\\E","#\\F","#\\G", "#\\H","#\\I","#\\J","#\\K","#\\L","#\\M","#\\N","#\\O", "#\\P","#\\Q","#\\R","#\\S","#\\T","#\\U","#\\V","#\\W", "#\\X","#\\Y","#\\Z","#\\[","#\\\\","#\\]","#\\^","#\\_", "#\\`","#\\a","#\\b","#\\c","#\\d","#\\e","#\\f","#\\g", "#\\h","#\\i","#\\j","#\\k","#\\l","#\\m","#\\n","#\\o", "#\\p","#\\q","#\\r","#\\s","#\\t","#\\u","#\\v","#\\w", "#\\x","#\\y","#\\z","#\\{","#\\|","#\\}","#\\~","#\\del"}; static ptr s_car(ptr x){ ptr* p = (ptr*)(x - pair_tag); return p[0]; } static ptr s_cdr(ptr x){ ptr* p = (ptr*)(x - pair_tag); return p[1]; } static void print_object(ptr x); static void print_rest(ptr x){ while(1){ if (x == empty_list) { return; } else if(mask(x,pair_mask) == pair_tag){ printf(" "); print_object(s_car(x)); x = s_cdr(x); } else { printf(" . "); print_object(x); return; } } } static void print_vector(ptr p){ int len = (int) ref(p, disp_vector_length - vector_tag); int i; printf("#("); if(len > 0){ print_object(ref(p, disp_vector_data - vector_tag)); for(i=disp_vector_data; i> char_shift) & 127]); } else if(((int)x & pair_mask) == pair_tag){ printf("("); print_object(s_car(x)); print_rest(s_cdr(x)); printf(")"); } else if(mask(x, vector_mask) == vector_tag){ print_vector(x); } else if(mask(x, string_mask) == string_tag){ print_string(x); } else if(mask(x, symbol_mask) == symbol_tag){ print_symbol(x); } else { printf("#", (int)x); } } static void print_ptr(ptr x){ print_object(x); printf("\n"); return; print_ptr(x); } static char* allocate_unprotected_space(int size){ int aligned_size = ((size + pagesize - 1) / pagesize) * pagesize; char* p = mmap(0, aligned_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); if(p == MAP_FAILED){ perror("allocate_unprotected_space failed to mmap"); exit(-10); } return p; } static char* allocate_protected_space(int size){ int status; int aligned_size = ((size + pagesize - 1) / pagesize) * pagesize; char* p = mmap(0, aligned_size + 2*pagesize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); if(p == MAP_FAILED){ perror("allocate_protected_space failed to mmap"); exit(-10); } status = mprotect(p, pagesize, PROT_NONE); if(status != 0){ perror("allocate_protected_space failed to protect"); exit(-10); } status = mprotect(p+pagesize+aligned_size, pagesize, PROT_NONE); if(status != 0){ perror("allocate_protected_space failed to protect"); exit(-10); } return (p + pagesize); } static void deallocate_unprotected_space(char* p, int size){ int status; int aligned_size = ((size + pagesize - 1) / pagesize) * pagesize; status = munmap(p, aligned_size); if(status != 0){ perror("deallocate_unprotected_space failed to unmap"); exit(-10); } } static void deallocate_protected_space(char* p, int size){ int status; int aligned_size = ((size + pagesize - 1) / pagesize) * pagesize; status = munmap(p-pagesize, aligned_size + 2*pagesize); if(status != 0){ perror("deallocate_protected_space failed to unmap"); exit(-10); } } char* global_heap_start; char* global_heap_end; char* global_stak_start; char* global_stak_end; int main(int argc, char** argv){ install_handlers(); if (pagesize != getpagesize()){ fprintf(stderr, "Pagesize Mismatch\n"); exit(-1); } int stak_size = (1024 * pagesize); /* holds 1M cells */ int heap_size = (640 * pagesize); /* holds 1M cells */ char* heap = allocate_unprotected_space(heap_size); char* stak = allocate_protected_space(stak_size); global_heap_start = heap; global_stak_start = stak; global_heap_end = heap+heap_size; global_stak_end = stak+stak_size; pcb_t* pcb = (pcb_t*) allocate_protected_space(sizeof(pcb_t)); fprintf(stderr, "pcb=0x%08x\n", (int)pcb); pcb->heap_base = heap; pcb->heap_size = (char*) heap_size; pcb->allocation_pointer = heap; pcb->allocation_redline = heap + heap_size - 2 * pagesize; pcb->scheme_stack = stak + stak_size; #if 0 fprintf(stderr, "scheme_stack=0x%08x\n", (int)pcb->scheme_stack); #endif scheme_main(pcb); #if 0 fprintf(stderr, "%d bytes used\n", pcb->allocation_pointer - heap); #endif deallocate_protected_space(stak, stak_size); deallocate_unprotected_space(pcb->heap_base, (int) pcb->heap_size); deallocate_protected_space((char*)pcb, sizeof(pcb_t)); return 0; } ptr S_error(ptr args){ if(mask(args,pair_mask) != pair_tag){ fprintf(stderr, "Error in Error: no arguments\n"); exit(-1); } ptr fst = ref(args, disp_car - pair_tag); if(fst == bool_f){ fprintf(stderr, "Error\n"); exit(0); } if(mask(fst, symbol_mask) == symbol_tag){ ptr str = ref(fst, disp_symbol_string - symbol_tag); fprintf(stderr, "Error in %s\n", str+disp_string_data-string_tag); exit(0); } fprintf(stderr, "Invalid argument 0x%08x to S_error\n", (int)fst); exit(-1); } /* * From the manpages: * * int open(const char *pathname, int flags); * int open(const char *pathname, int flags, mode_t mode); * flags = (O_RDONLY | O_WRONLY | O_RDWR) ? O_CREAT ? O_TRUNC ? O_APPEND * return -1 on failure * * int unlink(const char *pathname); */ ptr S_open_file(ptr str, ptr flagptr){ int flags; int f = unshift(flagptr); char* path = str + disp_string_data - string_tag; if(f == 0){ flags = O_WRONLY; } else if(f == 1){ flags = O_WRONLY | O_APPEND; } else if(f == 2){ unlink(path); flags = O_WRONLY | O_CREAT; } else if(f == 3){ flags = O_WRONLY | O_TRUNC; } else if(f == 4){ flags = O_RDONLY; } else { fprintf(stderr, "Error in S_open_file: invalid mode 0x%08x\n", (int)flagptr); exit(-10); } int fd = open(path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(fd == -1){ fprintf(stderr, "Cannot open %s\n", path); perror("S_open_file"); exit(-10); } if(fd != unshift(shift(fd))){ fprintf(stderr, "fd %d too big\n", fd); exit(-10); } return shift(fd); } ptr S_write(ptr fdptr, ptr idx, ptr str){ int fd = unshift(fdptr); int len = unshift(idx); char* buf = str+disp_string_data-string_tag; int bytes = write(fd, buf, len); if(bytes != len){ perror("S_write"); exit(-10); } return bool_t; } ptr S_read(ptr fdptr, ptr bufptr, ptr lenptr){ int fd = unshift(fdptr); int len = unshift(lenptr); char* buf = bufptr+disp_string_data-string_tag; int bytes = read(fd, buf, len); if(bytes == -1){ perror("S_read"); exit(-10); } return shift(bytes); } ptr S_close(ptr fd){ int err = close(unshift(fd)); if(err != 0){ perror("S_close"); exit(-10); } return bool_t; } /* * From the manpage: * * int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); * int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); * int sigpending(sigset_t *set); * int sigsuspend(const sigset_t *mask); struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); } siginfo_t { int si_signo; int si_errno; int si_code; pid_t si_pid; uid_t si_uid; int si_status; clock_t si_utime; clock_t si_stime; sigval_t si_value; int si_int; void * si_ptr; void * si_addr; int si_band; int si_fd; } si_code: SEGV_MAPERR | address not mapped to object SEGV_ACCERR | invalid permissions for mapped object */ void segv_handler(int signum, siginfo_t * info, void* ctxt){ fprintf(stderr, "segv cought\n"); fprintf(stderr, "address of fault = 0x%08x\n", (int) info->si_addr); fprintf(stderr, "heap is 0x%08x .. 0x%08x\n", (int) global_heap_start, (int) global_heap_end - 1); fprintf(stderr, "stak is 0x%08x .. 0x%08x\n", (int) global_stak_start, (int) global_stak_end - 1); fprintf(stderr, "caused by: %s\n", (info->si_code == SEGV_MAPERR) ? "unmapped object" : "invalid permission"); exit(-10); } static void install_handlers(){ return; stack_t ss; ss.ss_sp = malloc(SIGSTKSZ); if (ss.ss_sp == NULL){ fprintf(stderr, "Error allocating altstack\n"); exit(-10); } ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) == -1) { fprintf(stderr, "Error installing altstack\n"); exit(-10); } struct sigaction act; sigset_t set; sigemptyset(&set); act.sa_sigaction = segv_handler; act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; act.sa_mask = set; int err = sigaction(SIGSEGV, &act, NULL); if(err){ perror("installing handlers failed"); exit(-10); } }