updated 5e

This commit is contained in:
aiju 2011-06-24 15:10:22 +02:00
parent a3e9415aa8
commit 81d393942d
9 changed files with 645 additions and 94 deletions

View file

@ -4,9 +4,8 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
Process **PP; int nflag, pflag, bflag;
Ref nproc;
static int nflag;
void void
dump(void) dump(void)
@ -37,23 +36,44 @@ cleanup(void)
if(P == nil) if(P == nil)
return; return;
remproc(P);
decref(&nproc);
freesegs(); freesegs();
fddecref(P->fd); fddecref(P->fd);
if(P->path != nil && decref(P->path) == 0)
free(P->path);
free(P); free(P);
} }
static void static void
usage(void) usage(void)
{ {
fprint(2, "usage: 5e [ -n ] text [ args ]\n"); fprint(2, "usage: 5e [-npb] text [...]\n");
exits(nil); 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 void
main(int argc, char **argv) main(int argc, char **argv)
{ {
ARGBEGIN { ARGBEGIN {
case 'n': nflag++; break; case 'n': nflag++; break;
case 'p': pflag++; break;
case 'b': bflag++; break;
default: usage(); default: usage();
} ARGEND; } ARGEND;
if(argc < 1) if(argc < 1)
@ -65,6 +85,8 @@ main(int argc, char **argv)
atexit(cleanup); atexit(cleanup);
if(nflag) if(nflag)
adjustns(); adjustns();
if(pflag)
initfs("armproc", "/proc");
initproc(); initproc();
if(loadtext(argv[0], argc, argv) < 0) if(loadtext(argv[0], argc, argv) < 0)
sysfatal("%r"); sysfatal("%r");

View file

@ -22,7 +22,7 @@ enum {
static void static void
invalid(u32int instr) 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 static u32int
@ -81,7 +81,7 @@ single(u32int instr)
addr = *Rn; addr = *Rn;
if(instr & fP) if(instr & fP)
addr += offset; addr += offset;
targ = vaddr(addr, &seg); targ = vaddr(addr, 4, &seg);
switch(instr & (fB | fL)) { switch(instr & (fB | fL)) {
case 0: case 0:
*(u32int*) targ = *Rd; *(u32int*) targ = *Rd;
@ -120,7 +120,7 @@ swap(u32int instr)
Rn = P->R + ((instr >> 16) & 15); Rn = P->R + ((instr >> 16) & 15);
if(Rm == P->R + 15 || Rd == P->R + 15 || Rn == P->R + 15) if(Rm == P->R + 15 || Rd == P->R + 15 || Rn == P->R + 15)
invalid(instr); invalid(instr);
targ = (u32int *) vaddr(*Rn, &seg); targ = (u32int *) vaddr(*Rn, 4, &seg);
lock(&seg->lock); lock(&seg->lock);
if(instr & fB) { if(instr & fB) {
tmp = *(u8int*) targ; tmp = *(u8int*) targ;
@ -256,11 +256,11 @@ halfword(u32int instr)
if(instr & fP) if(instr & fP)
target += offset; target += offset;
switch(instr & (fSg | fH | fL)) { switch(instr & (fSg | fH | fL)) {
case fSg: *(u8int*) vaddr(target, &seg) = *Rd; break; case fSg: *(u8int*) vaddr(target, 1, &seg) = *Rd; break;
case fSg | fL: *Rd = (long) *(char*) vaddr(target, &seg); break; case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
case fH: case fSg | fH: *(u16int*) vaddr(target, &seg) = *Rd; break; case fH: case fSg | fH: *(u16int*) vaddr(target, 2, &seg) = *Rd; break;
case fH | fL: *Rd = *(u16int*) vaddr(target, &seg); break; case fH | fL: *Rd = *(u16int*) vaddr(target, 2, &seg); break;
case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, &seg); break; case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break;
} }
segunlock(seg); segunlock(seg);
if(!(instr & fP)) if(!(instr & fP))
@ -289,9 +289,9 @@ block(u32int instr)
if(instr & fP) if(instr & fP)
targ += 4; targ += 4;
if(instr & fL) if(instr & fL)
P->R[i] = *(u32int*) vaddr(targ, &seg); P->R[i] = *(u32int*) vaddr(targ, 4, &seg);
else else
*(u32int*) vaddr(targ, &seg) = P->R[i]; *(u32int*) vaddr(targ, 4, &seg) = P->R[i];
segunlock(seg); segunlock(seg);
if(!(instr & fP)) if(!(instr & fP))
targ += 4; targ += 4;
@ -303,9 +303,9 @@ block(u32int instr)
if(instr & fP) if(instr & fP)
targ -= 4; targ -= 4;
if(instr & fL) if(instr & fL)
P->R[i] = *(u32int*) vaddr(targ, &seg); P->R[i] = *(u32int*) vaddr(targ, 4, &seg);
else else
*(u32int*) vaddr(targ, &seg) = P->R[i]; *(u32int*) vaddr(targ, 4, &seg) = P->R[i];
segunlock(seg); segunlock(seg);
if(!(instr & fP)) if(!(instr & fP))
targ -= 4; targ -= 4;
@ -382,7 +382,7 @@ singleex(u32int instr)
if(Rd == P->R + 15 || Rn == P->R + 15) if(Rd == P->R + 15 || Rn == P->R + 15)
invalid(instr); invalid(instr);
if(instr & fS) { if(instr & fS) {
targ = vaddr(*Rn, &seg); targ = vaddr(*Rn, 4, &seg);
lock(&seg->lock); lock(&seg->lock);
*Rd = *targ; *Rd = *targ;
segunlock(seg); segunlock(seg);
@ -390,11 +390,11 @@ singleex(u32int instr)
Rm = P->R + (instr & 15); Rm = P->R + (instr & 15);
if(Rm == P->R + 15) if(Rm == P->R + 15)
invalid(instr); invalid(instr);
targ = vaddr(*Rn, &seg); targ = vaddr(*Rn, 4, &seg);
if(canlock(&seg->lock)) { if(canlock(&seg->lock)) {
*Rd = 1; *Rd = 1;
} else { } else {
*targ = *Rd; *targ = *Rm;
unlock(&seg->lock); unlock(&seg->lock);
*Rd = 0; *Rd = 0;
} }
@ -408,7 +408,7 @@ step(void)
u32int instr; u32int instr;
Segment *seg; Segment *seg;
instr = *(u32int*) vaddr(P->R[15], &seg); instr = *(u32int*) vaddr(P->R[15], 4, &seg);
segunlock(seg); segunlock(seg);
if(fulltrace) { if(fulltrace) {
print("%d ", P->pid); print("%d ", P->pid);

View file

@ -4,8 +4,9 @@ typedef struct Fdtable Fdtable;
typedef struct Fd Fd; typedef struct Fd Fd;
enum { enum {
STACKTOP = 0x80000000UL, STACKSIZE = 0x100000,
STACKSIZE = 0x10000,
NAMEMAX = 27,
FDBLOCK = 16, FDBLOCK = 16,
SEGNUM = 8, SEGNUM = 8,
@ -25,17 +26,23 @@ enum {
}; };
struct Process { struct Process {
Segment* S[SEGNUM]; Segment *S[SEGNUM];
u32int R[16]; /* general purpose registers / PC (R15) */ u32int R[16]; /* general purpose registers / PC (R15) */
u32int CPSR; /* status register */ u32int CPSR; /* status register */
char errbuf[ERRMAX]; char errbuf[ERRMAX];
char name[NAMEMAX+1];
Ref *path; /* Ref + string data */
Fd *fd; Fd *fd;
int pid; int pid;
Process *prev, *next;
}; };
extern void **_privates; extern void **_privates;
extern int _nprivates; extern int _nprivates;
#define P (*(Process**)_privates) #define P (*(Process**)_privates)
extern Ref nproc;
extern Process plist;
extern Lock plistlock;
enum { enum {
SEGFLLOCK = 1, SEGFLLOCK = 1,
@ -44,16 +51,16 @@ enum {
struct Segment { struct Segment {
Ref; Ref;
int flags; int flags;
RWLock rw; /* lock for SEGLOCK segments */ RWLock rw; /* lock for SEGFLLOCK segments */
Lock lock; /* atomic accesses */ Lock lock; /* atomic accesses */
u32int start, size; u32int start, size;
void *data; void *data;
Ref *ref; Ref *dref;
}; };
struct Fd { struct Fd {
RWLock; RWLock;
Ref ref; Ref;
u8int *fds; u8int *fds;
int nfds; int nfds;
}; };

View file

@ -4,8 +4,8 @@ void *erealloc(void *, u32int);
void initproc(void); void initproc(void);
int loadtext(char *, int, char **); int loadtext(char *, int, char **);
Segment *newseg(u32int, u32int, int); Segment *newseg(u32int, u32int, int);
void *vaddr(u32int, Segment **); void *vaddr(u32int, u32int, Segment **);
void *vaddrnol(u32int); void *vaddrnol(u32int, u32int);
void step(void); void step(void);
void syscall(void); void syscall(void);
void cherrstr(char *, ...); void cherrstr(char *, ...);
@ -20,4 +20,10 @@ void cleanup(void);
void segunlock(Segment *); void segunlock(Segment *);
void *copyifnec(u32int, int, int *); void *copyifnec(u32int, int, int *);
void *bufifnec(u32int, int, int *); void *bufifnec(u32int, int, int *);
void copyback(u32int, int, void *); void copyback(u32int, int, void *);
void initfs(char *, char *);
void suicide(char *, ...);
void fdclear(Fd *);
void addproc(Process *);
void remproc(Process *);
Process *findproc(int);

437
sys/src/cmd/5e/fs.c Normal file
View file

@ -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);
}

View file

@ -1,7 +1,7 @@
</$objtype/mkfile </$objtype/mkfile
TARG=5e 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 HFILES=dat.h fns.h
BIN=/$objtype/bin BIN=/$objtype/bin

View file

@ -8,12 +8,74 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
Process plist;
Lock plistlock;
void void
initproc(void) initproc(void)
{ {
P = emallocz(sizeof(Process)); P = emallocz(sizeof(Process));
P->pid = getpid(); P->pid = getpid();
P->fd = newfd(); 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 static void
@ -21,7 +83,7 @@ initstack(int argc, char **argv)
{ {
ulong tos, sp, ap, size, i, len; ulong tos, sp, ap, size, i, len;
tos = STACKTOP - sizeof(Tos) * 2; tos = mach->utop - sizeof(Tos) * 2;
sp = tos; sp = tos;
size = 8; size = 8;
@ -31,22 +93,22 @@ initstack(int argc, char **argv)
sp -= size; sp -= size;
sp &= ~7; sp &= ~7;
P->R[0] = tos; P->R[0] = tos;
P->R[1] = STACKTOP - 4; P->R[1] = mach->utop - 4;
P->R[13] = sp; P->R[13] = sp;
*(ulong *) vaddrnol(sp) = argc; *(ulong *) vaddrnol(sp, 4) = argc;
sp += 4; sp += 4;
ap = sp + (argc + 1) * 4; ap = sp + (argc + 1) * 4;
for(i = 0; i < argc; i++) { for(i = 0; i < argc; i++) {
*(ulong *) vaddrnol(sp) = ap; *(ulong *) vaddrnol(sp, 4) = ap;
sp += 4; sp += 4;
len = strlen(argv[i]) + 1; len = strlen(argv[i]) + 1;
memcpy(vaddrnol(ap), argv[i], len); memcpy(vaddrnol(ap, len), argv[i], len);
ap += 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 static int
@ -104,9 +166,9 @@ invalid:
int int
loadtext(char *file, int argc, char **argv) loadtext(char *file, int argc, char **argv)
{ {
int fd, i; int fd;
Fhdr fp; Fhdr fp;
Segment *text, *data, *bss, *stack; Segment *text, *data, *bss;
char buf[2]; char buf[2];
fd = open(file, OREAD); 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] == '!') if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')
return loadscript(fd, file, argc, argv); return loadscript(fd, file, argc, argv);
seek(fd, 0, 0); seek(fd, 0, 0);
if(crackhdr(fd, &fp) == 0) { if(crackhdr(fd, &fp) == 0 || fp.magic != E_MAGIC) {
werrstr("exec header invalid");
return -1;
}
if(fp.magic != E_MAGIC) {
werrstr("exec header invalid"); werrstr("exec header invalid");
return -1; return -1;
} }
copyname(file);
freesegs(); freesegs();
memset(P->R, 0, sizeof(P->R)); memset(P->R, 0, sizeof(P->R));
P->CPSR = 0; P->CPSR = 0;
text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT); text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
data = newseg(fp.dataddr, fp.datsz, SEGDATA); data = newseg(fp.dataddr, fp.datsz, SEGDATA);
bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS); 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); seek(fd, fp.txtoff - fp.hdrsz, 0);
if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz) if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
sysfatal("%r"); sysfatal("%r");
@ -136,19 +195,11 @@ loadtext(char *file, int argc, char **argv)
if(readn(fd, data->data, fp.datsz) < fp.datsz) if(readn(fd, data->data, fp.datsz) < fp.datsz)
sysfatal("%r"); sysfatal("%r");
memset(bss->data, 0, bss->size); memset(bss->data, 0, bss->size);
memset(stack->data, 0, stack->size);
P->R[15] = fp.entry; P->R[15] = fp.entry;
if(havesymbols && syminit(fd, &fp) < 0) if(havesymbols && syminit(fd, &fp) < 0)
fprint(2, "initializing symbol table: %r\n"); fprint(2, "initializing symbol table: %r\n");
close(fd); close(fd);
for(i = 0; i < P->fd->nfds * 8; i++) fdclear(P->fd);
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);
initstack(argc, argv); initstack(argc, argv);
return 0; return 0;
} }
@ -178,7 +229,7 @@ newfd(void)
Fd *fd; Fd *fd;
fd = emallocz(sizeof(*fd)); fd = emallocz(sizeof(*fd));
incref(&fd->ref); incref(fd);
return fd; return fd;
} }
@ -201,7 +252,7 @@ copyfd(Fd *old)
void void
fddecref(Fd *fd) fddecref(Fd *fd)
{ {
if(decref(&fd->ref) == 0) { if(decref(fd) == 0) {
free(fd->fds); free(fd->fds);
free(fd); free(fd);
} }
@ -242,3 +293,25 @@ setcexec(Fd *fd, int n, int status)
fd->fds[n / 8] |= (1 << (n % 8)); fd->fds[n / 8] |= (1 << (n % 8));
wunlock(fd); 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);
}

View file

@ -13,10 +13,10 @@ newseg(u32int start, u32int size, int idx)
incref(s); incref(s);
s->start = start; s->start = start;
s->size = size; s->size = size;
s->ref = emalloc(size + sizeof(Ref)); s->dref = emalloc(size + sizeof(Ref));
memset(s->ref, 0, sizeof(Ref)); memset(s->dref, 0, sizeof(Ref));
incref(s->ref); incref(s->dref);
s->data = s->ref + 1; s->data = s->dref + 1;
if(idx == SEGBSS) if(idx == SEGBSS)
s->flags = SEGFLLOCK; s->flags = SEGFLLOCK;
P->S[idx] = s; P->S[idx] = s;
@ -31,8 +31,8 @@ freesegs(void)
for(s = P->S; s < P->S + SEGNUM; s++) { for(s = P->S; s < P->S + SEGNUM; s++) {
if(*s == nil) if(*s == nil)
continue; continue;
if(decref((*s)->ref) == 0) if(decref((*s)->dref) == 0)
free((*s)->ref); free((*s)->dref);
if(decref(*s) == 0) if(decref(*s) == 0)
free(*s); free(*s);
*s = nil; *s = nil;
@ -40,7 +40,7 @@ freesegs(void)
} }
void * void *
vaddr(u32int addr, Segment **seg) vaddr(u32int addr, u32int len, Segment **seg)
{ {
Segment **ss, *s; Segment **ss, *s;
@ -49,23 +49,25 @@ vaddr(u32int addr, Segment **seg)
continue; continue;
s = *ss; s = *ss;
if(addr >= s->start && addr < s->start + s->size) { if(addr >= s->start && addr < s->start + s->size) {
if(addr + len > s->start + s->size)
break;
if(s->flags & SEGFLLOCK) if(s->flags & SEGFLLOCK)
rlock(&s->rw); rlock(&s->rw);
*seg = s; *seg = s;
return (char *)s->data + (addr - s->start); 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; return nil;
} }
void * void *
vaddrnol(u32int addr) vaddrnol(u32int addr, u32int len)
{ {
Segment *seg; Segment *seg;
void *ret; void *ret;
ret = vaddr(addr, &seg); ret = vaddr(addr, len, &seg);
segunlock(seg); segunlock(seg);
return ret; return ret;
} }
@ -84,7 +86,7 @@ copyifnec(u32int addr, int len, int *copied)
void *targ, *ret; void *targ, *ret;
Segment *seg; Segment *seg;
targ = vaddr(addr, &seg); targ = vaddr(addr, len > 0 ? len : 0, &seg);
if((seg->flags & SEGFLLOCK) == 0) { if((seg->flags & SEGFLLOCK) == 0) {
*copied = 0; *copied = 0;
return targ; return targ;
@ -104,7 +106,7 @@ bufifnec(u32int addr, int len, int *buffered)
void *targ; void *targ;
Segment *seg; Segment *seg;
targ = vaddr(addr, &seg); targ = vaddr(addr, len, &seg);
if((seg->flags & SEGFLLOCK) == 0) { if((seg->flags & SEGFLLOCK) == 0) {
*buffered = 0; *buffered = 0;
return targ; return targ;
@ -122,7 +124,7 @@ copyback(u32int addr, int len, void *data)
if(len <= 0) if(len <= 0)
return; return;
targ = vaddr(addr, &seg); targ = vaddr(addr, len, &seg);
memmove(targ, data, len); memmove(targ, data, len);
segunlock(seg); segunlock(seg);
free(data); free(data);

View file

@ -9,7 +9,7 @@ static u32int
arg(int n) arg(int n)
{ {
/* no locking necessary, since we're on the stack */ /* 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 static u64int
@ -127,7 +127,7 @@ sysseek(void)
vlong n, *ret; vlong n, *ret;
Segment *seg; Segment *seg;
ret = vaddr(arg(0), &seg); ret = vaddr(arg(0), 8, &seg);
fd = arg(1); fd = arg(1);
n = argv(2); n = argv(2);
type = arg(4); type = arg(4);
@ -202,7 +202,7 @@ sysexits(void)
if(arg(0) == 0) if(arg(0) == 0)
exits(nil); exits(nil);
else else
exits(vaddrnol(arg(0))); exits(vaddrnol(arg(0), 0));
} }
static void static void
@ -218,10 +218,10 @@ sysbrk(void)
sysfatal("bss length < 0, wtf?"); sysfatal("bss length < 0, wtf?");
s = P->S[SEGBSS]; s = P->S[SEGBSS];
wlock(&s->rw); wlock(&s->rw);
s->ref = realloc(s->ref, v - s->start + 4); s->dref = realloc(s->dref, v - s->start + 4);
if(s->ref == nil) if(s->dref == nil)
sysfatal("error reallocating"); sysfatal("error reallocating");
s->data = s->ref + 1; s->data = s->dref + 1;
if(s->size < v - s->start) if(s->size < v - s->start)
memset((char*)s->data + s->size, 0, v - s->start - s->size); memset((char*)s->data + s->size, 0, v - s->start - s->size);
s->size = v - s->start; s->size = v - s->start;
@ -276,16 +276,17 @@ sysrfork(void)
Process *p; Process *p;
Segment *s, *t; Segment *s, *t;
Fd *old; Fd *old;
enum {
RFORKPASS = RFENVG | RFCENVG | RFNOTEG | RFNOMNT | RFNAMEG | RFCNAMEG | RFNOWAIT | RFREND | RFFDG | RFCFDG,
RFORKHANDLED = RFPROC | RFMEM,
};
flags = arg(0); flags = arg(0);
if(systrace) if(systrace)
fprint(2, "rfork(%#o)\n", flags); fprint(2, "rfork(%#o)\n", flags);
if(flags & ~(RFORKPASS | RFORKHANDLED)) if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) ||
sysfatal("rfork with unhandled flags %#o", flags & ~(RFORKPASS | RFORKHANDLED)); (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 & RFPROC) == 0) {
if(flags & RFFDG) { if(flags & RFFDG) {
old = P->fd; old = P->fd;
@ -297,9 +298,10 @@ sysrfork(void)
P->fd = newfd(); P->fd = newfd();
fddecref(old); fddecref(old);
} }
P->R[0] = noteerr(rfork(flags & RFORKPASS), 0); P->R[0] = noteerr(rfork(flags), 0);
return; return;
} }
incref(&nproc);
p = emallocz(sizeof(Process)); p = emallocz(sizeof(Process));
memcpy(p, P, sizeof(Process)); memcpy(p, P, sizeof(Process));
for(i = 0; i < SEGNUM; i++) { for(i = 0; i < SEGNUM; i++) {
@ -311,15 +313,15 @@ sysrfork(void)
incref(t); incref(t);
t->size = s->size; t->size = s->size;
t->start = s->start; t->start = s->start;
t->ref = emalloc(sizeof(Ref) + s->size); t->dref = emalloc(sizeof(Ref) + s->size);
memset(t->ref, 0, sizeof(Ref)); memset(t->dref, 0, sizeof(Ref));
incref(t->ref); incref(t->dref);
t->data = t->ref + 1; t->data = t->dref + 1;
memcpy(t->data, s->data, s->size); memcpy(t->data, s->data, s->size);
p->S[i] = t; p->S[i] = t;
} else { } else {
incref(s->dref);
incref(s); incref(s);
incref(s->ref);
} }
} }
@ -328,15 +330,17 @@ sysrfork(void)
else if(flags & RFCFDG) else if(flags & RFCFDG)
p->fd = newfd(); p->fd = newfd();
else else
incref(&P->fd->ref); incref(P->fd);
rc = rfork(RFPROC | RFMEM | (flags & RFORKPASS)); incref(P->path);
if(rc < 0) rc = rfork(RFMEM | flags);
sysfatal("rfork: %r"); if(rc < 0) /* this should NEVER happen */
sysfatal("rfork failed wtf: %r");
if(rc == 0) { if(rc == 0) {
P = p; P = p;
atexit(cleanup); atexit(cleanup);
P->pid = getpid(); P->pid = getpid();
addproc(P);
} }
P->R[0] = rc; P->R[0] = rc;
} }
@ -351,16 +355,16 @@ sysexec(void)
name = arg(0); name = arg(0);
argv = arg(1); argv = arg(1);
namet = strdup(vaddr(name, &seg1)); namet = strdup(vaddr(name, 0, &seg1));
segunlock(seg1); segunlock(seg1);
argvt = vaddr(argv, &seg1); argvt = vaddr(argv, 0, &seg1);
if(systrace) if(systrace)
fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv); fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
for(argc = 0; argvt[argc]; argc++) for(argc = 0; argvt[argc]; argc++)
; ;
argvv = emalloc(sizeof(char *) * argc); argvv = emalloc(sizeof(char *) * argc);
for(i = 0; i < argc; i++) { for(i = 0; i < argc; i++) {
argvv[i] = strdup(vaddr(argvt[i], &seg2)); argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
segunlock(seg2); segunlock(seg2);
} }
segunlock(seg1); segunlock(seg1);