diff options
author | aiju <aiju@phicode.de> | 2011-06-24 15:10:22 +0200 |
---|---|---|
committer | aiju <aiju@phicode.de> | 2011-06-24 15:10:22 +0200 |
commit | 81d393942d8834b6e071ab0957b655a99e737486 (patch) | |
tree | a4b6c1cc206c87d46f390139502e03dafddd9c2a /sys/src/cmd/5e | |
parent | a3e9415aa8cdba6059c972c582e3645c4c112139 (diff) |
updated 5e
Diffstat (limited to 'sys/src/cmd/5e')
-rw-r--r-- | sys/src/cmd/5e/5e.c | 30 | ||||
-rw-r--r-- | sys/src/cmd/5e/arm.c | 32 | ||||
-rw-r--r-- | sys/src/cmd/5e/dat.h | 19 | ||||
-rw-r--r-- | sys/src/cmd/5e/fns.h | 12 | ||||
-rw-r--r-- | sys/src/cmd/5e/fs.c | 437 | ||||
-rw-r--r-- | sys/src/cmd/5e/mkfile | 2 | ||||
-rw-r--r-- | sys/src/cmd/5e/proc.c | 125 | ||||
-rw-r--r-- | sys/src/cmd/5e/seg.c | 28 | ||||
-rw-r--r-- | sys/src/cmd/5e/sys.c | 54 |
9 files changed, 645 insertions, 94 deletions
diff --git a/sys/src/cmd/5e/5e.c b/sys/src/cmd/5e/5e.c index 3aac578d1..b2f23674c 100644 --- a/sys/src/cmd/5e/5e.c +++ b/sys/src/cmd/5e/5e.c @@ -4,9 +4,8 @@ #include "dat.h" #include "fns.h" -Process **PP; - -static int nflag; +int nflag, pflag, bflag; +Ref nproc; void dump(void) @@ -37,23 +36,44 @@ cleanup(void) if(P == nil) return; + remproc(P); + decref(&nproc); freesegs(); fddecref(P->fd); + if(P->path != nil && decref(P->path) == 0) + free(P->path); free(P); } static void usage(void) { - fprint(2, "usage: 5e [ -n ] text [ args ]\n"); + fprint(2, "usage: 5e [-npb] text [...]\n"); exits(nil); } void +suicide(char *fmt, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, fmt); + vsnprint(buf, sizeof(buf), fmt, va); + va_end(va); + fprint(2, "%s\n", buf); + if(!bflag) + exits(buf); + abort(); +} + +void main(int argc, char **argv) { ARGBEGIN { case 'n': nflag++; break; + case 'p': pflag++; break; + case 'b': bflag++; break; default: usage(); } ARGEND; if(argc < 1) @@ -65,6 +85,8 @@ main(int argc, char **argv) atexit(cleanup); if(nflag) adjustns(); + if(pflag) + initfs("armproc", "/proc"); initproc(); if(loadtext(argv[0], argc, argv) < 0) sysfatal("%r"); diff --git a/sys/src/cmd/5e/arm.c b/sys/src/cmd/5e/arm.c index fcaab3fb4..507c46361 100644 --- a/sys/src/cmd/5e/arm.c +++ b/sys/src/cmd/5e/arm.c @@ -22,7 +22,7 @@ enum { static void invalid(u32int instr) { - sysfatal("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4); + suicide("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4); } static u32int @@ -81,7 +81,7 @@ single(u32int instr) addr = *Rn; if(instr & fP) addr += offset; - targ = vaddr(addr, &seg); + targ = vaddr(addr, 4, &seg); switch(instr & (fB | fL)) { case 0: *(u32int*) targ = *Rd; @@ -120,7 +120,7 @@ swap(u32int instr) Rn = P->R + ((instr >> 16) & 15); if(Rm == P->R + 15 || Rd == P->R + 15 || Rn == P->R + 15) invalid(instr); - targ = (u32int *) vaddr(*Rn, &seg); + targ = (u32int *) vaddr(*Rn, 4, &seg); lock(&seg->lock); if(instr & fB) { tmp = *(u8int*) targ; @@ -256,11 +256,11 @@ halfword(u32int instr) if(instr & fP) target += offset; switch(instr & (fSg | fH | fL)) { - case fSg: *(u8int*) vaddr(target, &seg) = *Rd; break; - case fSg | fL: *Rd = (long) *(char*) vaddr(target, &seg); break; - case fH: case fSg | fH: *(u16int*) vaddr(target, &seg) = *Rd; break; - case fH | fL: *Rd = *(u16int*) vaddr(target, &seg); break; - case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, &seg); break; + case fSg: *(u8int*) vaddr(target, 1, &seg) = *Rd; break; + case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break; + case fH: case fSg | fH: *(u16int*) vaddr(target, 2, &seg) = *Rd; break; + case fH | fL: *Rd = *(u16int*) vaddr(target, 2, &seg); break; + case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break; } segunlock(seg); if(!(instr & fP)) @@ -289,9 +289,9 @@ block(u32int instr) if(instr & fP) targ += 4; if(instr & fL) - P->R[i] = *(u32int*) vaddr(targ, &seg); + P->R[i] = *(u32int*) vaddr(targ, 4, &seg); else - *(u32int*) vaddr(targ, &seg) = P->R[i]; + *(u32int*) vaddr(targ, 4, &seg) = P->R[i]; segunlock(seg); if(!(instr & fP)) targ += 4; @@ -303,9 +303,9 @@ block(u32int instr) if(instr & fP) targ -= 4; if(instr & fL) - P->R[i] = *(u32int*) vaddr(targ, &seg); + P->R[i] = *(u32int*) vaddr(targ, 4, &seg); else - *(u32int*) vaddr(targ, &seg) = P->R[i]; + *(u32int*) vaddr(targ, 4, &seg) = P->R[i]; segunlock(seg); if(!(instr & fP)) targ -= 4; @@ -382,7 +382,7 @@ singleex(u32int instr) if(Rd == P->R + 15 || Rn == P->R + 15) invalid(instr); if(instr & fS) { - targ = vaddr(*Rn, &seg); + targ = vaddr(*Rn, 4, &seg); lock(&seg->lock); *Rd = *targ; segunlock(seg); @@ -390,11 +390,11 @@ singleex(u32int instr) Rm = P->R + (instr & 15); if(Rm == P->R + 15) invalid(instr); - targ = vaddr(*Rn, &seg); + targ = vaddr(*Rn, 4, &seg); if(canlock(&seg->lock)) { *Rd = 1; } else { - *targ = *Rd; + *targ = *Rm; unlock(&seg->lock); *Rd = 0; } @@ -408,7 +408,7 @@ step(void) u32int instr; Segment *seg; - instr = *(u32int*) vaddr(P->R[15], &seg); + instr = *(u32int*) vaddr(P->R[15], 4, &seg); segunlock(seg); if(fulltrace) { print("%d ", P->pid); diff --git a/sys/src/cmd/5e/dat.h b/sys/src/cmd/5e/dat.h index d8356f07d..63499bc97 100644 --- a/sys/src/cmd/5e/dat.h +++ b/sys/src/cmd/5e/dat.h @@ -4,8 +4,9 @@ typedef struct Fdtable Fdtable; typedef struct Fd Fd; enum { - STACKTOP = 0x80000000UL, - STACKSIZE = 0x10000, + STACKSIZE = 0x100000, + + NAMEMAX = 27, FDBLOCK = 16, SEGNUM = 8, @@ -25,17 +26,23 @@ enum { }; struct Process { - Segment* S[SEGNUM]; + Segment *S[SEGNUM]; u32int R[16]; /* general purpose registers / PC (R15) */ u32int CPSR; /* status register */ char errbuf[ERRMAX]; + char name[NAMEMAX+1]; + Ref *path; /* Ref + string data */ Fd *fd; int pid; + Process *prev, *next; }; extern void **_privates; extern int _nprivates; #define P (*(Process**)_privates) +extern Ref nproc; +extern Process plist; +extern Lock plistlock; enum { SEGFLLOCK = 1, @@ -44,16 +51,16 @@ enum { struct Segment { Ref; int flags; - RWLock rw; /* lock for SEGLOCK segments */ + RWLock rw; /* lock for SEGFLLOCK segments */ Lock lock; /* atomic accesses */ u32int start, size; void *data; - Ref *ref; + Ref *dref; }; struct Fd { RWLock; - Ref ref; + Ref; u8int *fds; int nfds; }; diff --git a/sys/src/cmd/5e/fns.h b/sys/src/cmd/5e/fns.h index 7ae97eae8..a28f5f433 100644 --- a/sys/src/cmd/5e/fns.h +++ b/sys/src/cmd/5e/fns.h @@ -4,8 +4,8 @@ void *erealloc(void *, u32int); void initproc(void); int loadtext(char *, int, char **); Segment *newseg(u32int, u32int, int); -void *vaddr(u32int, Segment **); -void *vaddrnol(u32int); +void *vaddr(u32int, u32int, Segment **); +void *vaddrnol(u32int, u32int); void step(void); void syscall(void); void cherrstr(char *, ...); @@ -20,4 +20,10 @@ void cleanup(void); void segunlock(Segment *); void *copyifnec(u32int, int, int *); void *bufifnec(u32int, int, int *); -void copyback(u32int, int, void *);
\ No newline at end of file +void copyback(u32int, int, void *); +void initfs(char *, char *); +void suicide(char *, ...); +void fdclear(Fd *); +void addproc(Process *); +void remproc(Process *); +Process *findproc(int); diff --git a/sys/src/cmd/5e/fs.c b/sys/src/cmd/5e/fs.c new file mode 100644 index 000000000..c14e6231d --- /dev/null +++ b/sys/src/cmd/5e/fs.c @@ -0,0 +1,437 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> +#include "dat.h" +#include "fns.h" + +static char *luser; +extern int pflag; + +enum +{ + Qdir, + Qtrace, + Qargs, + Qctl, + Qfd, + Qfpregs, + Qkregs, + Qmem, + Qnote, + Qnoteid, + Qnotepg, + Qns, + Qproc, + Qregs, + Qsegment, + Qstatus, + Qtext, + Qwait, + Qprofile, + Qsyscall, + NQid, +}; + +typedef struct Aux Aux; +typedef struct Dirtab Dirtab; +struct Dirtab { + char name[28]; + Qid qid; + vlong length; + long perm; +}; +struct Aux { + Process *p; + int fd; + Dirtab *d; +}; + +Dirtab procdir[] = +{ + "args", {Qargs}, 0, 0660, + "ctl", {Qctl}, 0, 0600, + "fd", {Qfd}, 0, 0444, + "fpregs", {Qfpregs}, 0, 0400, + "kregs", {Qkregs}, 18 * 4, 0400, + "mem", {Qmem}, 0, 0400, + "note", {Qnote}, 0, 0000, + "noteid", {Qnoteid}, 0, 0664, + "notepg", {Qnotepg}, 0, 0000, + "ns", {Qns}, 0, 0444, + "proc", {Qproc}, 0, 0400, + "regs", {Qregs}, 18 * 4, 0400, + "segment", {Qsegment}, 0, 0444, + "status", {Qstatus}, 176, 0444, + "text", {Qtext}, 0, 0400, + "wait", {Qwait}, 0, 0400, + "profile", {Qprofile}, 0, 0400, + "syscall", {Qsyscall}, 0, 0400, + "", {0}, 0, 0, +}; + +static char * +readin(int pid, char *file) +{ + char *name, *buf; + int fd, rc; + + name = smprint("#p/%d/%s", pid, file); + fd = open(name, OREAD); + if(fd < 0) + return nil; + buf = malloc(1024); + rc = read(fd, buf, 1023); + if(rc < 0) + return nil; + buf[rc] = 0; + free(name); + close(fd); + return buf; +} + +static int +calcmem(Process *p) +{ + int i, r; + + r = 0; + for(i = 0; i < SEGNUM; i++) { + if(i == SEGSTACK) + continue; + if(p->S[i] == nil) + continue; + r += p->S[i]->size; + } + r = (r + 1023) / 1024; + return r; +} + +static int +copymem(Process *p, char *buf, u32int addr, int len) +{ + int i, n, r; + + r = len; + while(len > 0) { + for(i = 0; i < SEGNUM; i++) { + if(p->S[i] == nil) + continue; + if(p->S[i]->start <= addr && p->S[i]->start + p->S[i]->size > addr) + break; + } + if(i == SEGNUM) { + werrstr("bad arg in syscall"); + return -1; + } + n = p->S[i]->start + p->S[i]->size - addr; + if(n > len) + n = len; + memcpy(buf, (char*)p->S[i]->data + addr - p->S[i]->start, n); + len -= n; + buf += n; + } + return r; +} + +static char * +segments(Process *p) +{ + char *r, *s; + static char *names[] = { + [SEGTEXT] "Text", + [SEGSTACK] "Stack", + [SEGDATA] "Data", + [SEGBSS] "Bss", + }; + int i; + + r = emalloc(1024); + s = r; + for(i = 0; i < SEGNUM; i++) { + if(p->S[i] == nil) + continue; + s += sprint(s, "%-7s%c %.8ux %.8ux %4ld\n", names[i], i == SEGTEXT ? 'R' : ' ', p->S[i]->start, p->S[i]->start + p->S[i]->size, p->S[i]->dref->ref); + } + return r; +} + +static void +procattach(Req *req) +{ + req->fid->qid = (Qid) {0, 0, 0x80}; + req->fid->aux = emallocz(sizeof(Aux)); + ((Aux *) req->fid->aux)->fd = -1; + req->ofcall.qid = req->fid->qid; + respond(req, nil); +} + +static char * +procwalk(Fid *fid, char *name, Qid *qid) +{ + int pid; + char buf[20]; + Dirtab *d; + Aux *a; + + a = fid->aux; + if(fid->qid.path == 0) { + pid = atoi(name); + sprint(buf, "%d", pid); + if(strcmp(buf, name) != 0 || (a->p = findproc(pid)) == nil) + return "file does not exist"; + *qid = (Qid) {pid * NQid, 0, 0x80}; + fid->qid = *qid; + return nil; + } + if((fid->qid.path % NQid) == 0) { + for(d = procdir; d->name[0] != 0; d++) + if(strcmp(d->name, name) == 0) + break; + if(d->name[0] == 0) + return "file does not exist"; + *qid = d->qid; + qid->path += fid->qid.path; + fid->qid = *qid; + a->d = d; + return nil; + } + return "the front fell off"; +} + +static char * +procclone(Fid *old, Fid *new) +{ + new->aux = emallocz(sizeof(Aux)); + memcpy(new->aux, old->aux, sizeof(Aux)); + return nil; +} + +static void +procopen(Req *req) +{ + Aux *a; + + a = req->fid->aux; + switch((int)(req->fid->qid.path % NQid)) { + case Qtext: + a->fd = open((char*)(a->p->path + 1), OREAD); + break; + default: + respond(req, nil); + return; + } + if(a->fd < 0) + responderror(req); + else + respond(req, nil); +} + +static void +procdestroyfid(Fid *fid) +{ + Aux *a; + + a = fid->aux; + free(a); +} + +static int +procgen(int n, Dir *d, void *) +{ + int i; + Process *p; + + p = &plist; + for(i = 0;; i++) { + p = p->next; + if(p == &plist) + return -1; + if(i == n) + break; + } + d->uid = estrdup9p(luser); + d->gid = estrdup9p(luser); + d->muid = estrdup9p(luser); + d->name = smprint("%d", p->pid); + d->mode = DMDIR | 0555; + d->qid = (Qid) {p->pid * NQid, 0, 0x80}; + return 0; +} + +static int +procsubgen(int n, Dir *d, void *) +{ + Dirtab *di; + + if(n >= nelem(procdir) - 1) + return -1; + + di = procdir + n; + d->uid = estrdup9p(luser); + d->gid = estrdup9p(luser); + d->muid = estrdup9p(luser); + d->name = estrdup9p(di->name); + d->mode = di->perm; + d->length = di->length; + d->qid = di->qid; + return 0; +} + +static void +procread(Req *req) +{ + Aux *a; + Process *p; + char *buf; + int rc; + + a = req->fid->aux; + if(a == nil) { + respond(req, "the front fell off"); + return; + } + if(req->fid->qid.path == 0) { + dirread9p(req, procgen, nil); + respond(req, nil); + return; + } + p = a->p; + switch((int)(req->fid->qid.path % NQid)) { + case Qdir: + dirread9p(req, procsubgen, nil); + respond(req, nil); + break; + case Qstatus: + buf = readin(p->pid, "status"); + if(buf == nil) + responderror(req); + else { + memset(buf, ' ', 27); + memcpy(buf, p->name, strlen(p->name)); + sprint(buf + 149, "%d", calcmem(p)); + buf[strlen(buf)] = ' '; + readstr(req, buf); + free(buf); + respond(req, nil); + } + break; + case Qsegment: + buf = segments(p); + readstr(req, buf); + free(buf); + respond(req, nil); + break; + case Qtext: + rc = pread(a->fd, req->ofcall.data, req->ifcall.count, req->ifcall.offset); + if(rc >= 0) { + req->ofcall.count = rc; + respond(req, nil); + } else + responderror(req); + break; + case Qmem: + rc = copymem(p, req->ofcall.data, req->ifcall.offset, req->ifcall.count); + if(rc >= 0) { + req->ofcall.count = rc; + respond(req, nil); + } else + responderror(req); + break; + case Qregs: + buf = emallocz(18 * 4); + memcpy(buf, p->R, 15 * 4); + memcpy(buf + 16 * 4, &p->CPSR, 4); + memcpy(buf + 17 * 4, p->R + 15, 4); + readbuf(req, buf, 18 * 4); + free(buf); + respond(req, nil); + break; + default: + respond(req, "the front fell off"); + } +} + +static void +writeto(Req *req, char *fmt, ...) +{ + int fd, rc; + va_list va; + char *file; + + va_start(va, fmt); + file = vsmprint(fmt, va); + va_end(va); + fd = open(file, OWRITE); + free(file); + if(fd < 0) { + responderror(req); + return; + } + rc = write(fd, req->ifcall.data, req->ifcall.count); + req->ofcall.count = rc; + if(rc < req->ifcall.count) + responderror(req); + else + respond(req, nil); + close(fd); +} + +static void +procwrite(Req *req) +{ + switch((int)(req->fid->qid.path % NQid)) { + case Qnote: + writeto(req, "#p/%lld/note", req->fid->qid.path / NQid); + break; + default: + respond(req, "the front fell off"); + } +} + +static void +procstat(Req *req) +{ + Aux *a; + Dir *d; + + d = &req->d; + a = req->fid->aux; + if(a == nil) { + respond(req, "the front fell off"); + return; + } + d->qid = req->fid->qid; + if(a->d != nil) { + d->mode = a->d->perm; + d->length = a->d->length; + d->name = strdup(a->d->name); + } else { + d->mode = 0555 | DMDIR; + if(d->qid.path != 0) + d->name = smprint("%lld", d->qid.path / NQid); + } + d->uid = strdup(luser); + d->gid = strdup(luser); + d->muid = strdup(luser); + respond(req, nil); +} + +static Srv procsrv = { + .attach = procattach, + .walk1 = procwalk, + .clone = procclone, + .destroyfid = procdestroyfid, + .open = procopen, + .read = procread, + .stat = procstat, +}; + +void +initfs(char *name, char *mtpt) +{ + luser = getuser(); + remove("/srv/armproc"); + postmountsrv(&procsrv, name, mtpt, MREPL); +} diff --git a/sys/src/cmd/5e/mkfile b/sys/src/cmd/5e/mkfile index 5fcb58784..496fa8346 100644 --- a/sys/src/cmd/5e/mkfile +++ b/sys/src/cmd/5e/mkfile @@ -1,7 +1,7 @@ </$objtype/mkfile TARG=5e -OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O +OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O HFILES=dat.h fns.h BIN=/$objtype/bin diff --git a/sys/src/cmd/5e/proc.c b/sys/src/cmd/5e/proc.c index 411420282..fa1dc9aad 100644 --- a/sys/src/cmd/5e/proc.c +++ b/sys/src/cmd/5e/proc.c @@ -8,12 +8,74 @@ #include "dat.h" #include "fns.h" +Process plist; +Lock plistlock; + void initproc(void) { P = emallocz(sizeof(Process)); P->pid = getpid(); P->fd = newfd(); + incref(&nproc); + plist.prev = P; + plist.next = P; + P->prev = &plist; + P->next = &plist; +} + +void +addproc(Process *p) +{ + lock(&plistlock); + p->prev = plist.prev; + p->next = &plist; + plist.prev->next = p; + plist.prev = p; + unlock(&plistlock); +} + +void +remproc(Process *p) +{ + lock(&plistlock); + p->prev->next = p->next; + p->next->prev = p->prev; + unlock(&plistlock); +} + +Process * +findproc(int pid) +{ + Process *p; + + lock(&plistlock); + for(p = plist.next; p != &plist; p = p->next) + if(p->pid == pid) + break; + unlock(&plistlock); + if(p != &plist) + return p; + return nil; +} + +static void +copyname(char *file) +{ + char *p; + + p = strrchr(file, '/'); + if(p == nil) + p = file; + else + p++; + strncpy(P->name, p, NAMEMAX); + + if(P->path != nil && decref(P->path) == 0) + free(P->path); + P->path = emallocz(5 + strlen(file)); + incref(P->path); + strcpy((char*)(P->path + 1), file); } static void @@ -21,7 +83,7 @@ initstack(int argc, char **argv) { ulong tos, sp, ap, size, i, len; - tos = STACKTOP - sizeof(Tos) * 2; + tos = mach->utop - sizeof(Tos) * 2; sp = tos; size = 8; @@ -31,22 +93,22 @@ initstack(int argc, char **argv) sp -= size; sp &= ~7; P->R[0] = tos; - P->R[1] = STACKTOP - 4; + P->R[1] = mach->utop - 4; P->R[13] = sp; - *(ulong *) vaddrnol(sp) = argc; + *(ulong *) vaddrnol(sp, 4) = argc; sp += 4; ap = sp + (argc + 1) * 4; for(i = 0; i < argc; i++) { - *(ulong *) vaddrnol(sp) = ap; + *(ulong *) vaddrnol(sp, 4) = ap; sp += 4; len = strlen(argv[i]) + 1; - memcpy(vaddrnol(ap), argv[i], len); + memcpy(vaddrnol(ap, len), argv[i], len); ap += len; } - *(ulong *) vaddrnol(sp) = 0; + *(ulong *) vaddrnol(sp, 4) = 0; - ((Tos *) vaddrnol(tos))->pid = getpid(); + ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = getpid(); } static int @@ -104,9 +166,9 @@ invalid: int loadtext(char *file, int argc, char **argv) { - int fd, i; + int fd; Fhdr fp; - Segment *text, *data, *bss, *stack; + Segment *text, *data, *bss; char buf[2]; fd = open(file, OREAD); @@ -114,21 +176,18 @@ loadtext(char *file, int argc, char **argv) if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!') return loadscript(fd, file, argc, argv); seek(fd, 0, 0); - if(crackhdr(fd, &fp) == 0) { - werrstr("exec header invalid"); - return -1; - } - if(fp.magic != E_MAGIC) { + if(crackhdr(fd, &fp) == 0 || fp.magic != E_MAGIC) { werrstr("exec header invalid"); return -1; } + copyname(file); freesegs(); memset(P->R, 0, sizeof(P->R)); P->CPSR = 0; text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT); data = newseg(fp.dataddr, fp.datsz, SEGDATA); bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS); - stack = newseg(STACKTOP - STACKSIZE, STACKSIZE, SEGSTACK); + newseg(mach->utop - STACKSIZE, STACKSIZE, SEGSTACK); seek(fd, fp.txtoff - fp.hdrsz, 0); if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz) sysfatal("%r"); @@ -136,19 +195,11 @@ loadtext(char *file, int argc, char **argv) if(readn(fd, data->data, fp.datsz) < fp.datsz) sysfatal("%r"); memset(bss->data, 0, bss->size); - memset(stack->data, 0, stack->size); P->R[15] = fp.entry; if(havesymbols && syminit(fd, &fp) < 0) fprint(2, "initializing symbol table: %r\n"); close(fd); - for(i = 0; i < P->fd->nfds * 8; i++) - if(iscexec(P->fd, i)) - close(i); - wlock(P->fd); - free(P->fd->fds); - P->fd->fds = nil; - P->fd->nfds = 0; - wunlock(P->fd); + fdclear(P->fd); initstack(argc, argv); return 0; } @@ -178,7 +229,7 @@ newfd(void) Fd *fd; fd = emallocz(sizeof(*fd)); - incref(&fd->ref); + incref(fd); return fd; } @@ -201,7 +252,7 @@ copyfd(Fd *old) void fddecref(Fd *fd) { - if(decref(&fd->ref) == 0) { + if(decref(fd) == 0) { free(fd->fds); free(fd); } @@ -242,3 +293,25 @@ setcexec(Fd *fd, int n, int status) fd->fds[n / 8] |= (1 << (n % 8)); wunlock(fd); } + +void +fdclear(Fd *fd) +{ + int i, j, k; + + wlock(fd); + if(fd->nfds == 0) { + wunlock(fd); + return; + } + for(i = 0; i < fd->nfds; i++) { + j = fd->fds[i]; + for(k = 0; k < 8; k++) + if(j & (1<<k)) + close(8 * i + k); + } + free(fd->fds); + fd->nfds = 0; + fd->fds = nil; + wunlock(fd); +} diff --git a/sys/src/cmd/5e/seg.c b/sys/src/cmd/5e/seg.c index caa4002ac..1cde88241 100644 --- a/sys/src/cmd/5e/seg.c +++ b/sys/src/cmd/5e/seg.c @@ -13,10 +13,10 @@ newseg(u32int start, u32int size, int idx) incref(s); s->start = start; s->size = size; - s->ref = emalloc(size + sizeof(Ref)); - memset(s->ref, 0, sizeof(Ref)); - incref(s->ref); - s->data = s->ref + 1; + s->dref = emalloc(size + sizeof(Ref)); + memset(s->dref, 0, sizeof(Ref)); + incref(s->dref); + s->data = s->dref + 1; if(idx == SEGBSS) s->flags = SEGFLLOCK; P->S[idx] = s; @@ -31,8 +31,8 @@ freesegs(void) for(s = P->S; s < P->S + SEGNUM; s++) { if(*s == nil) continue; - if(decref((*s)->ref) == 0) - free((*s)->ref); + if(decref((*s)->dref) == 0) + free((*s)->dref); if(decref(*s) == 0) free(*s); *s = nil; @@ -40,7 +40,7 @@ freesegs(void) } void * -vaddr(u32int addr, Segment **seg) +vaddr(u32int addr, u32int len, Segment **seg) { Segment **ss, *s; @@ -49,23 +49,25 @@ vaddr(u32int addr, Segment **seg) continue; s = *ss; if(addr >= s->start && addr < s->start + s->size) { + if(addr + len > s->start + s->size) + break; if(s->flags & SEGFLLOCK) rlock(&s->rw); *seg = s; return (char *)s->data + (addr - s->start); } } - sysfatal("fault %.8ux @ %.8ux", addr, P->R[15]); + suicide("fault %.8ux (%d) @ %.8ux", addr, len, P->R[15]); return nil; } void * -vaddrnol(u32int addr) +vaddrnol(u32int addr, u32int len) { Segment *seg; void *ret; - ret = vaddr(addr, &seg); + ret = vaddr(addr, len, &seg); segunlock(seg); return ret; } @@ -84,7 +86,7 @@ copyifnec(u32int addr, int len, int *copied) void *targ, *ret; Segment *seg; - targ = vaddr(addr, &seg); + targ = vaddr(addr, len > 0 ? len : 0, &seg); if((seg->flags & SEGFLLOCK) == 0) { *copied = 0; return targ; @@ -104,7 +106,7 @@ bufifnec(u32int addr, int len, int *buffered) void *targ; Segment *seg; - targ = vaddr(addr, &seg); + targ = vaddr(addr, len, &seg); if((seg->flags & SEGFLLOCK) == 0) { *buffered = 0; return targ; @@ -122,7 +124,7 @@ copyback(u32int addr, int len, void *data) if(len <= 0) return; - targ = vaddr(addr, &seg); + targ = vaddr(addr, len, &seg); memmove(targ, data, len); segunlock(seg); free(data); diff --git a/sys/src/cmd/5e/sys.c b/sys/src/cmd/5e/sys.c index e88f8f1e0..daa02e0c7 100644 --- a/sys/src/cmd/5e/sys.c +++ b/sys/src/cmd/5e/sys.c @@ -9,7 +9,7 @@ static u32int arg(int n) { /* no locking necessary, since we're on the stack */ - return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n); + return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4); } static u64int @@ -127,7 +127,7 @@ sysseek(void) vlong n, *ret; Segment *seg; - ret = vaddr(arg(0), &seg); + ret = vaddr(arg(0), 8, &seg); fd = arg(1); n = argv(2); type = arg(4); @@ -202,7 +202,7 @@ sysexits(void) if(arg(0) == 0) exits(nil); else - exits(vaddrnol(arg(0))); + exits(vaddrnol(arg(0), 0)); } static void @@ -218,10 +218,10 @@ sysbrk(void) sysfatal("bss length < 0, wtf?"); s = P->S[SEGBSS]; wlock(&s->rw); - s->ref = realloc(s->ref, v - s->start + 4); - if(s->ref == nil) + s->dref = realloc(s->dref, v - s->start + 4); + if(s->dref == nil) sysfatal("error reallocating"); - s->data = s->ref + 1; + s->data = s->dref + 1; if(s->size < v - s->start) memset((char*)s->data + s->size, 0, v - s->start - s->size); s->size = v - s->start; @@ -276,16 +276,17 @@ sysrfork(void) Process *p; Segment *s, *t; Fd *old; - enum { - RFORKPASS = RFENVG | RFCENVG | RFNOTEG | RFNOMNT | RFNAMEG | RFCNAMEG | RFNOWAIT | RFREND | RFFDG | RFCFDG, - RFORKHANDLED = RFPROC | RFMEM, - }; flags = arg(0); if(systrace) fprint(2, "rfork(%#o)\n", flags); - if(flags & ~(RFORKPASS | RFORKHANDLED)) - sysfatal("rfork with unhandled flags %#o", flags & ~(RFORKPASS | RFORKHANDLED)); + if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) || + (flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) || + (flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) { + P->R[0] = -1; + cherrstr("bad arg in syscall"); + return; + } if((flags & RFPROC) == 0) { if(flags & RFFDG) { old = P->fd; @@ -297,9 +298,10 @@ sysrfork(void) P->fd = newfd(); fddecref(old); } - P->R[0] = noteerr(rfork(flags & RFORKPASS), 0); + P->R[0] = noteerr(rfork(flags), 0); return; } + incref(&nproc); p = emallocz(sizeof(Process)); memcpy(p, P, sizeof(Process)); for(i = 0; i < SEGNUM; i++) { @@ -311,15 +313,15 @@ sysrfork(void) incref(t); t->size = s->size; t->start = s->start; - t->ref = emalloc(sizeof(Ref) + s->size); - memset(t->ref, 0, sizeof(Ref)); - incref(t->ref); - t->data = t->ref + 1; + t->dref = emalloc(sizeof(Ref) + s->size); + memset(t->dref, 0, sizeof(Ref)); + incref(t->dref); + t->data = t->dref + 1; memcpy(t->data, s->data, s->size); p->S[i] = t; } else { + incref(s->dref); incref(s); - incref(s->ref); } } @@ -328,15 +330,17 @@ sysrfork(void) else if(flags & RFCFDG) p->fd = newfd(); else - incref(&P->fd->ref); + incref(P->fd); - rc = rfork(RFPROC | RFMEM | (flags & RFORKPASS)); - if(rc < 0) - sysfatal("rfork: %r"); + incref(P->path); + rc = rfork(RFMEM | flags); + if(rc < 0) /* this should NEVER happen */ + sysfatal("rfork failed wtf: %r"); if(rc == 0) { P = p; atexit(cleanup); P->pid = getpid(); + addproc(P); } P->R[0] = rc; } @@ -351,16 +355,16 @@ sysexec(void) name = arg(0); argv = arg(1); - namet = strdup(vaddr(name, &seg1)); + namet = strdup(vaddr(name, 0, &seg1)); segunlock(seg1); - argvt = vaddr(argv, &seg1); + argvt = vaddr(argv, 0, &seg1); if(systrace) fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv); for(argc = 0; argvt[argc]; argc++) ; argvv = emalloc(sizeof(char *) * argc); for(i = 0; i < argc; i++) { - argvv[i] = strdup(vaddr(argvt[i], &seg2)); + argvv[i] = strdup(vaddr(argvt[i], 0, &seg2)); segunlock(seg2); } segunlock(seg1); |