#include #include #include #include "linux.h" #include "linuxsys.h" typedef struct Ureg Ureg; static void maincall(ulong, ulong, char**, ulong); static int linuxnote(void*, char*); void* mmap(char*); void* mmapfd(int); void *bss; int debug; void usage(void) { fprint(2, "usage: %s [-d] linuxprog args...\n", argv0); exits("usage"); } void main(int argc, char **argv) { long entry = 0; void *file; ARGBEGIN{ case 'd': debug = 1; break; default: usage(); }ARGEND if(argc < 1) usage(); if((file = mmap(argv[0])) == nil) { fprint(2, "mmap failed: %r\n"); exits("mmap"); } if(memcmp(file, "\x7fELF", 4) == 0) entry = elfload(file); else { fprint(2, "cannot identify binary\n"); exits("binary type"); } if(entry <= 0) { fprint(2, "error loading binary\n"); exits("binary load"); } DPRINT("entry=%lux\n", entry); maincall(entry, argc, argv, 0); abort(); // not reached } /* * set up the argument stack * for linux and do the jmp. * this should not return, since * what we're jumping to is supposed * to call exit. * * we use jumpstack, provided by stack.s * * it expects * * | envp * | * |---- * | * | argv * | * |---- * | argc * |---- ← sp * */ static void maincall(ulong entry, ulong argc, char **argv, ulong depth) { ulong buf[1024/4], *p; int i, n; /* BUG do environment */ n = 8; // padding n += (argc+1)*4; // argv n += 4; // argc /* * here's a kludge: we need some room on the * stack. rather than try to assemble "SP -= n", * since that will confuse the compiler, we just * call ourselves lots of times to bring the stack * depth down to what we want, giving us enough * room. we have no intention of returning. */ depth++; if(depth * sizeof buf < n) maincall(entry, argc, argv, depth); /* install ``syscall'' handler */ atnotify(linuxnote, 1); p = (ulong*) buf; *p++ = argc; for(i=0; ipc; if(x[0] != 0xCD || x[1] != 0x80) /* INT $0x80 */ return 0; n = ureg->ax; DPRINT("SYSCALL %d\n", n); if(n >= LMAXSYSCALL || (f=syscalltab[ureg->ax]) == 0) { print("wants unimplemented function %lux (%s) pc=%lux\n", n, n < LMAXSYSCALL ? syscallname[n] : "(?)", ureg->pc); ureg->ax = -1; } else { (*f)(ureg); DPRINT("returns %lud=0x%lux...\n", ureg->ax, ureg->ax); } ureg->pc += 2; return 1; } /* * mmap, if it were handled by the kernel * void* _mmap(char *name) { void *v; Dir *d; char *buf; vlong len; if((d = dirstat(name)) == nil || d->length == 0){ free(d); return nil; } len = d->length; free(d); buf = malloc(strlen(name)+10); if(buf == nil) return nil; sprint(buf, "file!%s", name); v = (void*)segattach(0, buf, nil, len); print("v=%lx file=%s len=%ld\n", v, name, len); free(buf); if(v == (void*)-1) return nil; return v; } void* _mmapfd(int fd) { void *v; Dir d; char buf[30]; if(dirfstat(fd, &d) < 0 || d.length == 0) return nil; snprint(buf, sizeof buf, "file!/fd/%d", fd); v = (void*)segattach(0, buf, nil, 4096); if(v == (void*)-1) return nil; return v; } */ /* * crummy mmap. should be handled by kernel. */ void* mmap(char *name) { void *v; int fd; if((fd = open(name, OREAD)) < 0) return nil; v = mmapfd(fd); close(fd); return v; } void* mmapfd(int fd) { void *v; Dir *d; vlong len; if((d = dirfstat(fd)) == nil) return nil; len = d->length; free(d); if(len == 0) return nil; v = malloc(len); if(v == nil) return nil; if(readn(fd, v, len) != len) { free(v); return nil; } return v; }