uintptr sys_wait(va_list list) { ulong pid; Waitmsg w; OWaitmsg *ow; ow = va_arg(list, OWaitmsg*); if(ow == nil) pid = pwait(nil); else { validaddr((uintptr)ow, sizeof(OWaitmsg), 1); evenaddr((uintptr)ow); pid = pwait(&w); } if(ow != nil){ readnum(0, ow->pid, NUMSIZE, w.pid, NUMSIZE); readnum(0, ow->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE); readnum(0, ow->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE); readnum(0, ow->time+TReal*NUMSIZE, NUMSIZE, w.time[TReal], NUMSIZE); strncpy(ow->msg, w.msg, sizeof(ow->msg)-1); ow->msg[sizeof(ow->msg)-1] = '\0'; } return pid; }
void syssemalt(Ar0 *ar0, ...) { Proc *up = externup(); int **sl; int i, *np, ns; Segment *sg; Sem *ksl[16]; va_list list; va_start(list, ar0); /* * void semalt(int*[], int); */ ar0->i = -1; sl = va_arg(list, int**); ns = va_arg(list, int); sl = validaddr(sl, ns * sizeof(int*), 1); if(ns > nelem(ksl)) panic("syssemalt: bug: too many semaphores in alt"); for(i = 0; i < ns; i++){ np = sl[i]; np = validaddr(np, sizeof(int), 1); evenaddr(PTR2UINT(np)); if((sg = seg(up, PTR2UINT(np), 0)) == nil) error(Ebadarg); ksl[i] = segmksem(sg, np); } ar0->i = semalt(ksl, ns); va_end(list); }
long syssemrelease(ulong *arg) { long *addr, delta; Segment *s; validaddr(arg[0], sizeof(long), 1); evenaddr(arg[0]); addr = (long*)arg[0]; delta = arg[1]; if((s = seg(up, (ulong)addr, 0)) == nil) error(Ebadarg); if(delta < 0 || *addr < 0) error(Ebadarg); return semrelease(s, addr, arg[1]); }
void syspipe(Ar0* ar0, ...) { Proc *up = externup(); int *a, fd[2]; Chan *c[2]; static char *datastr[] = {"data", "data1"}; va_list list; va_start(list, ar0); /* * int pipe(int fd[2]); */ a = va_arg(list, int*); va_end(list); a = validaddr(a, sizeof(fd), 1); evenaddr(PTR2UINT(a)); c[0] = namec("#|", Atodir, 0, 0); c[1] = nil; fd[0] = -1; fd[1] = -1; if(waserror()){ cclose(c[0]); if(c[1]) cclose(c[1]); nexterror(); } c[1] = cclone(c[0]); if(walk(&c[0], datastr+0, 1, 1, nil) < 0) error(Egreg); if(walk(&c[1], datastr+1, 1, 1, nil) < 0) error(Egreg); c[0] = c[0]->dev->open(c[0], ORDWR); c[1] = c[1]->dev->open(c[1], ORDWR); if(newfd2(fd, c) < 0) error(Enofd); poperror(); a[0] = fd[0]; a[1] = fd[1]; ar0->i = 0; }
long syssemacquire(ulong *arg) { int block; long *addr; Segment *s; validaddr(arg[0], sizeof(long), 1); evenaddr(arg[0]); addr = (long*)arg[0]; block = arg[1]; if((s = seg(up, (ulong)addr, 0)) == nil) error(Ebadarg); if(*addr < 0) error(Ebadarg); return semacquire(s, addr, block); }
long systsemacquire(ulong *arg) { long *addr; ulong ms; Segment *s; validaddr(arg[0], sizeof(long), 1); evenaddr(arg[0]); addr = (long*)arg[0]; ms = arg[1]; if((s = seg(up, (ulong)addr, 0)) == nil) error(Ebadarg); if(*addr < 0) error(Ebadarg); return tsemacquire(s, addr, ms); }
void syssemwakeup(Ar0* ar0, ...) { Proc *up = externup(); int *np; Sem *s; Segment *sg; va_list list; va_start(list, ar0); /* * void semwakeup(int*); */ np = va_arg(list, int*); np = validaddr(np, sizeof *np, 1); evenaddr(PTR2UINT(np)); if((sg = seg(up, PTR2UINT(np), 0)) == nil) error(Ebadarg); s = segmksem(sg, np); semwakeup(s, 1, 1); va_end(list); }
long syspipe(uint32 *arg) { int fd[2]; Chan *c[2]; Dev *d; static char *datastr[] = {"data", "data1"}; int *ufd; ufd = uvalidaddr(arg[0], 2*BY2WD, 1); evenaddr(arg[0]); d = devtab[devno('|', 0)]; c[0] = namec("#|", Atodir, 0, 0); c[1] = 0; fd[0] = -1; fd[1] = -1; if(waserror()){ cclose(c[0]); if(c[1]) cclose(c[1]); nexterror(); } c[1] = cclone(c[0]); if(walk(&c[0], datastr+0, 1, 1, nil) < 0) error(Egreg); if(walk(&c[1], datastr+1, 1, 1, nil) < 0) error(Egreg); c[0] = d->open(c[0], ORDWR); c[1] = d->open(c[1], ORDWR); if(newfd2(fd, c) < 0) error(Enofd); poperror(); ufd[0] = fd[0]; ufd[1] = fd[1]; return 0; }
long sys_wait(ulong *arg) { int pid; Waitmsg w; OWaitmsg *ow; if(arg[0] == 0) return pwait(nil); validaddr(arg[0], sizeof(OWaitmsg), 1); evenaddr(arg[0]); pid = pwait(&w); if(pid >= 0){ ow = (OWaitmsg*)arg[0]; readnum(0, ow->pid, NUMSIZE, w.pid, NUMSIZE); readnum(0, ow->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE); readnum(0, ow->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE); readnum(0, ow->time+TReal*NUMSIZE, NUMSIZE, w.time[TReal], NUMSIZE); strncpy(ow->msg, w.msg, sizeof(ow->msg)); ow->msg[sizeof(ow->msg)-1] = '\0'; } return pid; }
void syscallfmt(int syscallno, ulong pc, va_list list) { long l; Fmt fmt; void *v; vlong vl; uintptr p; int i[2], len; char *a, **argv; fmtstrinit(&fmt); fmtprint(&fmt, "%uld %s ", up->pid, up->text); if(syscallno > nsyscall) fmtprint(&fmt, " %d ", syscallno); else fmtprint(&fmt, "%s ", sysctab[syscallno]? sysctab[syscallno]: "huh?"); fmtprint(&fmt, "%ulx ", pc); if(up->syscalltrace != nil) free(up->syscalltrace); switch(syscallno){ case SYSR1: p = va_arg(list, uintptr); fmtprint(&fmt, "%#p", p); break; case _ERRSTR: /* deprecated */ case CHDIR: case EXITS: case REMOVE: a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); break; case BIND: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux", i[0]); break; case CLOSE: case NOTED: i[0] = va_arg(list, int); fmtprint(&fmt, "%d", i[0]); break; case DUP: i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %d", i[0], i[1]); break; case ALARM: l = va_arg(list, unsigned long); fmtprint(&fmt, "%#lud ", l); break; case EXEC: a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); argv = va_arg(list, char**); evenaddr(PTR2UINT(argv)); for(;;){ validaddr((ulong)argv, sizeof(char**), 0); a = *(char **)argv; if(a == nil) break; fmtprint(&fmt, " "); fmtuserstring(&fmt, a, ""); argv++; } break; case _FSESSION: /* deprecated */ case _FSTAT: /* deprecated */ case _FWSTAT: /* obsolete */ i[0] = va_arg(list, int); a = va_arg(list, char*); fmtprint(&fmt, "%d %#p", i[0], a); break; case FAUTH: i[0] = va_arg(list, int); a = va_arg(list, char*); fmtprint(&fmt, "%d", i[0]); fmtuserstring(&fmt, a, ""); break; case SEGBRK: case RENDEZVOUS: v = va_arg(list, void*); fmtprint(&fmt, "%#p ", v); v = va_arg(list, void*); fmtprint(&fmt, "%#p", v); break; case _MOUNT: /* deprecated */ i[0] = va_arg(list, int); fmtprint(&fmt, "%d ", i[0]); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux ", i[0]); a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); break; case OPEN: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux", i[0]); break; case OSEEK: /* deprecated */ i[0] = va_arg(list, int); l = va_arg(list, long); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %ld %d", i[0], l, i[1]); break; case SLEEP: l = va_arg(list, long); fmtprint(&fmt, "%ld", l); break; case _STAT: /* obsolete */ case _WSTAT: /* obsolete */ a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); a = va_arg(list, char*); fmtprint(&fmt, "%#p", a); break; case RFORK: i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux", i[0]); break; case PIPE: case BRK_: v = va_arg(list, int*); fmtprint(&fmt, "%#p", v); break; case CREATE: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%#ux %#ux", i[0], i[1]); break; case FD2PATH: case FSTAT: case FWSTAT: i[0] = va_arg(list, int); a = va_arg(list, char*); l = va_arg(list, unsigned long); fmtprint(&fmt, "%d %#p %lud", i[0], a, l); break; case NOTIFY: case SEGDETACH: case _WAIT: /* deprecated */ v = va_arg(list, void*); fmtprint(&fmt, "%#p", v); break; case SEGATTACH: i[0] = va_arg(list, int); fmtprint(&fmt, "%d ", i[0]); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); /*FALLTHROUGH*/ case SEGFREE: case SEGFLUSH: v = va_arg(list, void*); l = va_arg(list, unsigned long); fmtprint(&fmt, "%#p %lud", v, l); break; case UNMOUNT: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); break; case SEMACQUIRE: case SEMRELEASE: v = va_arg(list, int*); i[0] = va_arg(list, int); fmtprint(&fmt, "%#p %d", v, i[0]); break; // case TSEMACQUIRE: // v = va_arg(list, long*); // l = va_arg(list, ulong); // fmtprint(&fmt, "%#p %ld", v, l); // break; case SEEK: v = va_arg(list, vlong*); i[0] = va_arg(list, int); vl = va_arg(list, vlong); i[1] = va_arg(list, int); fmtprint(&fmt, "%#p %d %#llux %d", v, i[0], vl, i[1]); break; case FVERSION: i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %d ", i[0], i[1]); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); l = va_arg(list, unsigned long); fmtprint(&fmt, "%lud", l); break; case WSTAT: case STAT: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); /*FALLTHROUGH*/ case ERRSTR: case AWAIT: a = va_arg(list, char*); l = va_arg(list, unsigned long); fmtprint(&fmt, "%#p %lud", a, l); break; case MOUNT: i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %d ", i[0], i[1]); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux ", i[0]); a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); break; case _READ: /* deprecated */ case PREAD: i[0] = va_arg(list, int); v = va_arg(list, void*); l = va_arg(list, long); fmtprint(&fmt, "%d %#p %ld", i[0], v, l); if(syscallno == PREAD){ vl = va_arg(list, vlong); fmtprint(&fmt, " %lld", vl); } break; case _WRITE: /* deprecated */ case PWRITE: i[0] = va_arg(list, int); v = va_arg(list, void*); l = va_arg(list, long); fmtprint(&fmt, "%d ", i[0]); len = MIN(l, 64); fmtrwdata(&fmt, v, len, " "); fmtprint(&fmt, "%ld", l); if(syscallno == PWRITE){ vl = va_arg(list, vlong); fmtprint(&fmt, " %lld", vl); } break; } up->syscalltrace = fmtstrflush(&fmt); }
uintptr sysexec(va_list list) { Segment *s, *ts; int i; Chan *tc; char **argv, **argp, **argp0; char *a, *e, *charp, *args, *file, *file0; char *progarg[sizeof(Exec)/2+1], *elem, progelem[64]; ulong magic, ssize, nargs, nbytes, n; uintptr t, d, b, entry, bssend, text, data, bss, tstk, align; int indir; Exec exec; char line[sizeof(Exec)]; Fgrp *f; Image *img; Tos *tos; args = elem = nil; file0 = va_arg(list, char*); validaddr((uintptr)file0, 1, 0); argp0 = va_arg(list, char**); evenaddr((uintptr)argp0); validaddr((uintptr)argp0, 2*BY2WD, 0); if(*argp0 == nil) error(Ebadarg); file0 = validnamedup(file0, 1); if(waserror()){ free(file0); free(elem); free(args); /* Disaster after commit */ if(up->seg[SSEG] == nil) pexit(up->errstr, 1); s = up->seg[ESEG]; if(s != nil){ putseg(s); up->seg[ESEG] = nil; } nexterror(); } align = BY2PG; indir = 0; file = file0; for(;;){ tc = namec(file, Aopen, OEXEC, 0); if(waserror()){ cclose(tc); nexterror(); } if(!indir) kstrdup(&elem, up->genbuf); n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0); if(n <= 2) error(Ebadexec); magic = l2be(exec.magic); if(n == sizeof(Exec) && (magic == AOUT_MAGIC)){ entry = l2be(exec.entry); text = l2be(exec.text); if(magic & HDR_MAGIC) text += 8; switch(magic){ case S_MAGIC: /* 2MB segment alignment for amd64 */ align = 0x200000; break; case V_MAGIC: /* 16K segment alignment for mips */ align = 0x4000; break; } if(text >= (USTKTOP-USTKSIZE)-(UTZERO+sizeof(Exec)) || entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text) error(Ebadexec); break; /* for binary */ } /* * Process #! /bin/sh args ... */ memmove(line, &exec, n); if(indir || line[0]!='#' || line[1]!='!') error(Ebadexec); n = shargs(line, n, progarg); if(n < 1) error(Ebadexec); indir = 1; /* * First arg becomes complete file name */ progarg[n++] = file; progarg[n] = nil; argp0++; file = progarg[0]; if(strlen(elem) >= sizeof progelem) error(Ebadexec); strcpy(progelem, elem); progarg[0] = progelem; poperror(); cclose(tc); } data = l2be(exec.data); bss = l2be(exec.bss); align--; t = (UTZERO+sizeof(Exec)+text+align) & ~align; align = BY2PG-1; d = (t + data + align) & ~align; bssend = t + data + bss; b = (bssend + align) & ~align; if(t >= (USTKTOP-USTKSIZE) || d >= (USTKTOP-USTKSIZE) || b >= (USTKTOP-USTKSIZE)) error(Ebadexec); /* * Args: pass 1: count */ nbytes = sizeof(Tos); /* hole for profiling clock at top of stack (and more) */ nargs = 0; if(indir){ argp = progarg; while(*argp != nil){ a = *argp++; nbytes += strlen(a) + 1; nargs++; } } argp = argp0; while(*argp != nil){ a = *argp++; if(((uintptr)argp&(BY2PG-1)) < BY2WD) validaddr((uintptr)argp, BY2WD, 0); validaddr((uintptr)a, 1, 0); e = vmemchr(a, 0, USTKSIZE); if(e == nil) error(Ebadarg); nbytes += (e - a) + 1; if(nbytes >= USTKSIZE) error(Enovmem); nargs++; } ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1)); /* * 8-byte align SP for those (e.g. sparc) that need it. * execregs() will subtract another 4 bytes for argc. */ if(BY2WD == 4 && (ssize+4) & 7) ssize += 4; if(PGROUND(ssize) >= USTKSIZE) error(Enovmem); /* * Build the stack segment, putting it in kernel virtual for the moment */ qlock(&up->seglock); if(waserror()){ qunlock(&up->seglock); nexterror(); } s = up->seg[SSEG]; do { tstk = s->base; if(tstk <= USTKSIZE) error(Enovmem); } while((s = isoverlap(up, tstk-USTKSIZE, USTKSIZE)) != nil); up->seg[ESEG] = newseg(SG_STACK, tstk-USTKSIZE, USTKSIZE/BY2PG); /* * Args: pass 2: assemble; the pages will be faulted in */ tos = (Tos*)(tstk - sizeof(Tos)); tos->cyclefreq = m->cyclefreq; tos->kcycles = 0; tos->pcycles = 0; tos->clock = 0; argv = (char**)(tstk - ssize); charp = (char*)(tstk - nbytes); if(indir) argp = progarg; else argp = argp0; for(i=0; i<nargs; i++){ if(indir && *argp==nil) { indir = 0; argp = argp0; } *argv++ = charp + (USTKTOP-tstk); a = *argp++; if(indir) e = strchr(a, 0); else { validaddr((uintptr)a, 1, 0); e = vmemchr(a, 0, (char*)tstk - charp); if(e == nil) error(Ebadarg); } n = (e - a) + 1; memmove(charp, a, n); charp += n; } /* copy args; easiest from new process's stack */ a = (char*)(tstk - nbytes); n = charp - a; if(n > 128) /* don't waste too much space on huge arg lists */ n = 128; args = smalloc(n); memmove(args, a, n); if(n>0 && args[n-1]!='\0'){ /* make sure last arg is NUL-terminated */ /* put NUL at UTF-8 character boundary */ for(i=n-1; i>0; --i) if(fullrune(args+i, n-i)) break; args[i] = 0; n = i+1; } /* * Committed. * Free old memory. * Special segments are maintained across exec */ for(i = SSEG; i <= BSEG; i++) { putseg(up->seg[i]); /* prevent a second free if we have an error */ up->seg[i] = nil; } for(i = ESEG+1; i < NSEG; i++) { s = up->seg[i]; if(s != nil && (s->type&SG_CEXEC) != 0) { putseg(s); up->seg[i] = nil; } } /* * Close on exec */ if((f = up->fgrp) != nil) { for(i=0; i<=f->maxfd; i++) fdclose(i, CCEXEC); } /* Text. Shared. Attaches to cache image if possible */ /* attachimage returns a locked cache image */ img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT); ts = img->s; up->seg[TSEG] = ts; ts->flushme = 1; ts->fstart = 0; ts->flen = sizeof(Exec)+text; unlock(img); /* Data. Shared. */ s = newseg(SG_DATA, t, (d-t)>>PGSHIFT); up->seg[DSEG] = s; /* Attached by hand */ incref(img); s->image = img; s->fstart = ts->fstart+ts->flen; s->flen = data; /* BSS. Zero fill on demand */ up->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT); /* * Move the stack */ s = up->seg[ESEG]; up->seg[ESEG] = nil; s->base = USTKTOP-USTKSIZE; s->top = USTKTOP; relocateseg(s, USTKTOP-tstk); up->seg[SSEG] = s; qunlock(&up->seglock); poperror(); /* seglock */ /* * '/' processes are higher priority (hack to make /ip more responsive). */ if(devtab[tc->type]->dc == L'/') up->basepri = PriRoot; up->priority = up->basepri; poperror(); /* tc */ cclose(tc); poperror(); /* file0 */ free(file0); qlock(&up->debug); free(up->text); up->text = elem; free(up->args); up->args = args; up->nargs = n; up->setargs = 0; up->nnote = 0; up->notify = 0; up->notified = 0; up->privatemem = 0; up->noswap = 0; procsetup(up); qunlock(&up->debug); /* * At this point, the mmu contains info about the old address * space and needs to be flushed */ flushmmu(); if(up->hang) up->procctl = Proc_stopme; return execregs(entry, ssize, nargs); }
long sysexec(ulong *arg) { Segment *s, *ts; ulong t, d, b; int i; Chan *tc; char **argv, **argp; char *a, *charp, *args, *file, *file0; char *progarg[sizeof(Exec)/2+1], *elem, progelem[64]; ulong ssize, spage, nargs, nbytes, n, bssend; int indir; Exec exec; char line[sizeof(Exec)]; Fgrp *f; Image *img; ulong magic, text, entry, data, bss; Tos *tos; indir = 0; elem = nil; validaddr(arg[0], 1, 0); file0 = validnamedup((char*)arg[0], 1); if(waserror()){ free(file0); free(elem); nexterror(); } file = file0; for(;;){ tc = namec(file, Aopen, OEXEC, 0); if(waserror()){ cclose(tc); nexterror(); } if(!indir) kstrdup(&elem, up->genbuf); n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0); if(n < 2) error(Ebadexec); magic = l2be(exec.magic); text = l2be(exec.text); entry = l2be(exec.entry); if(n==sizeof(Exec) && (magic == AOUT_MAGIC)){ if(text >= USTKTOP-UTZERO || entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text) error(Ebadexec); break; /* for binary */ } /* * Process #! /bin/sh args ... */ memmove(line, &exec, sizeof(Exec)); if(indir || line[0]!='#' || line[1]!='!') error(Ebadexec); n = shargs(line, n, progarg); if(n == 0) error(Ebadexec); indir = 1; /* * First arg becomes complete file name */ progarg[n++] = file; progarg[n] = 0; validaddr(arg[1], BY2WD, 1); arg[1] += BY2WD; file = progarg[0]; if(strlen(elem) >= sizeof progelem) error(Ebadexec); strcpy(progelem, elem); progarg[0] = progelem; poperror(); cclose(tc); } data = l2be(exec.data); bss = l2be(exec.bss); t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1); d = (t + data + (BY2PG-1)) & ~(BY2PG-1); bssend = t + data + bss; b = (bssend + (BY2PG-1)) & ~(BY2PG-1); if(t >= KZERO || d >= KZERO || b >= KZERO) error(Ebadexec); /* * Args: pass 1: count */ nbytes = sizeof(Tos); /* hole for profiling clock at top of stack (and more) */ nargs = 0; if(indir){ argp = progarg; while(*argp){ a = *argp++; nbytes += strlen(a) + 1; nargs++; } } evenaddr(arg[1]); argp = (char**)arg[1]; validaddr((ulong)argp, BY2WD, 0); while(*argp){ a = *argp++; if(((ulong)argp&(BY2PG-1)) < BY2WD) validaddr((ulong)argp, BY2WD, 0); validaddr((ulong)a, 1, 0); nbytes += ((char*)vmemchr(a, 0, 0x7FFFFFFF) - a) + 1; nargs++; } ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1)); /* * 8-byte align SP for those (e.g. sparc) that need it. * execregs() will subtract another 4 bytes for argc. */ if((ssize+4) & 7) ssize += 4; spage = (ssize+(BY2PG-1)) >> PGSHIFT; /* * Build the stack segment, putting it in kernel virtual for the moment */ if(spage > TSTKSIZ) error(Enovmem); qlock(&up->seglock); if(waserror()){ qunlock(&up->seglock); nexterror(); } up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG); /* * Args: pass 2: assemble; the pages will be faulted in */ tos = (Tos*)(TSTKTOP - sizeof(Tos)); tos->cyclefreq = m->cyclefreq; cycles((uvlong*)&tos->pcycles); tos->pcycles = -tos->pcycles; tos->kcycles = tos->pcycles; tos->clock = 0; argv = (char**)(TSTKTOP - ssize); charp = (char*)(TSTKTOP - nbytes); args = charp; if(indir) argp = progarg; else argp = (char**)arg[1]; for(i=0; i<nargs; i++){ if(indir && *argp==0) { indir = 0; argp = (char**)arg[1]; } *argv++ = charp + (USTKTOP-TSTKTOP); n = strlen(*argp) + 1; memmove(charp, *argp++, n); charp += n; } free(file0); free(up->text); up->text = elem; elem = nil; /* so waserror() won't free elem */ USED(elem); /* copy args; easiest from new process's stack */ n = charp - args; if(n > 128) /* don't waste too much space on huge arg lists */ n = 128; a = up->args; up->args = nil; free(a); up->args = smalloc(n); memmove(up->args, args, n); if(n>0 && up->args[n-1]!='\0'){ /* make sure last arg is NUL-terminated */ /* put NUL at UTF-8 character boundary */ for(i=n-1; i>0; --i) if(fullrune(up->args+i, n-i)) break; up->args[i] = 0; n = i+1; } up->nargs = n; /* * Committed. * Free old memory. * Special segments are maintained across exec */ for(i = SSEG; i <= BSEG; i++) { putseg(up->seg[i]); /* prevent a second free if we have an error */ up->seg[i] = 0; } for(i = BSEG+1; i < NSEG; i++) { s = up->seg[i]; if(s != 0 && (s->type&SG_CEXEC)) { putseg(s); up->seg[i] = 0; } } /* * Close on exec */ f = up->fgrp; for(i=0; i<=f->maxfd; i++) fdclose(i, CCEXEC); /* Text. Shared. Attaches to cache image if possible */ /* attachimage returns a locked cache image */ img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT); ts = img->s; up->seg[TSEG] = ts; ts->flushme = 1; ts->fstart = 0; ts->flen = sizeof(Exec)+text; unlock(img); /* Data. Shared. */ s = newseg(SG_DATA, t, (d-t)>>PGSHIFT); up->seg[DSEG] = s; /* Attached by hand */ incref(img); s->image = img; s->fstart = ts->fstart+ts->flen; s->flen = data; /* BSS. Zero fill on demand */ up->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT); /* * Move the stack */ s = up->seg[ESEG]; up->seg[ESEG] = 0; up->seg[SSEG] = s; qunlock(&up->seglock); poperror(); /* seglock */ poperror(); /* elem */ s->base = USTKTOP-USTKSIZE; s->top = USTKTOP; relocateseg(s, USTKTOP-TSTKTOP); /* * '/' processes are higher priority (hack to make /ip more responsive). */ if(devtab[tc->type]->dc == L'/') up->basepri = PriRoot; up->priority = up->basepri; poperror(); cclose(tc); /* * At this point, the mmu contains info about the old address * space and needs to be flushed */ flushmmu(); qlock(&up->debug); up->nnote = 0; up->notify = 0; up->notified = 0; up->privatemem = 0; procsetup(up); qunlock(&up->debug); if(up->hang) up->procctl = Proc_stopme; return execregs(entry, ssize, nargs); }
void syscallfmt(int syscallno, ...) { Proc *up = externup(); va_list list; int32_t l; Fmt fmt; void *v; int64_t vl; uintptr_t p; int i[2], len; char *a, **argv; va_start(list, syscallno); iprint("%d: %d nsyscall %d\n", up->pid, syscallno, nsyscall); fmtstrinit(&fmt); fmtprint(&fmt, "%d %s ", up->pid, up->text); if(syscallno > nsyscall) fmtprint(&fmt, " %d ", syscallno); else fmtprint(&fmt, "%s ", systab[syscallno].n); if(up->syscalltrace != nil) free(up->syscalltrace); up->syscalltrace = nil; switch(syscallno){ case CHDIR: case EXITS: case REMOVE: a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); break; case BIND: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux", i[0]); break; case CLOSE: case NOTED: i[0] = va_arg(list, int); fmtprint(&fmt, "%d", i[0]); break; case DUP: i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %d", i[0], i[1]); break; case ALARM: l = va_arg(list, unsigned long); fmtprint(&fmt, "%#lud ", l); break; case EXEC: a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); argv = va_arg(list, char**); evenaddr(PTR2UINT(argv)); for(;;){ a = *(char**)validaddr(argv, sizeof(char**), 0); if(a == nil) break; fmtprint(&fmt, " "); fmtuserstring(&fmt, a, ""); argv++; } break; case FAUTH: i[0] = va_arg(list, int); a = va_arg(list, char*); fmtprint(&fmt, "%d", i[0]); fmtuserstring(&fmt, a, ""); break; case SEGBRK: case RENDEZVOUS: v = va_arg(list, void*); fmtprint(&fmt, "%#p ", v); v = va_arg(list, void*); fmtprint(&fmt, "%#p", v); break; case OPEN: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux", i[0]); break; case RFORK: i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux", i[0]); break; case PIPE: case BRK_: v = va_arg(list, int*); fmtprint(&fmt, "%#p", v); break; case CREATE: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%#ux %#ux", i[0], i[1]); break; case FD2PATH: case FSTAT: case FWSTAT: i[0] = va_arg(list, int); a = va_arg(list, char*); l = va_arg(list, unsigned long); fmtprint(&fmt, "%d %#p %lud", i[0], a, l); break; case NOTIFY: case SEGDETACH: v = va_arg(list, void*); fmtprint(&fmt, "%#p", v); break; case SEGATTACH: i[0] = va_arg(list, int); fmtprint(&fmt, "%d ", i[0]); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); /*FALLTHROUGH*/ case SEGFREE: case SEGFLUSH: v = va_arg(list, void*); l = va_arg(list, unsigned long); fmtprint(&fmt, "%#p %lud", v, l); break; case UNMOUNT: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); break; case SEMACQUIRE: case SEMRELEASE: v = va_arg(list, int*); i[0] = va_arg(list, int); fmtprint(&fmt, "%#p %d", v, i[0]); break; case TSEMACQUIRE: v = va_arg(list, int*); l = va_arg(list, uint32_t); fmtprint(&fmt, "%#p %ld", v, l); break; case AWAKE: vl = va_arg(list, int64_t); fmtprint(&fmt, "%lld", vl); break; case SEEK: i[0] = va_arg(list, int); vl = va_arg(list, int64_t); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %#llux %d", i[0], vl, i[1]); break; case FVERSION: i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %d ", i[0], i[1]); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); l = va_arg(list, unsigned long); fmtprint(&fmt, "%lud", l); break; case WSTAT: case STAT: a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); /*FALLTHROUGH*/ case ERRSTR: case AWAIT: a = va_arg(list, char*); l = va_arg(list, unsigned long); fmtprint(&fmt, "%#p %lud", a, l); break; case MOUNT: i[0] = va_arg(list, int); i[1] = va_arg(list, int); fmtprint(&fmt, "%d %d ", i[0], i[1]); a = va_arg(list, char*); fmtuserstring(&fmt, a, " "); i[0] = va_arg(list, int); fmtprint(&fmt, "%#ux ", i[0]); a = va_arg(list, char*); fmtuserstring(&fmt, a, ""); break; case READ: /* deprecated */ case PREAD: i[0] = va_arg(list, int); v = va_arg(list, void*); l = va_arg(list, int32_t); fmtprint(&fmt, "%d %#p %ld", i[0], v, l); if(syscallno == PREAD){ vl = va_arg(list, int64_t); fmtprint(&fmt, " %lld", vl); } break; case WRITE: /* deprecated */ case PWRITE: i[0] = va_arg(list, int); v = va_arg(list, void*); l = va_arg(list, int32_t); fmtprint(&fmt, "%d ", i[0]); len = MIN(l, 64); fmtrwdata(&fmt, v, len, " "); fmtprint(&fmt, "%ld", l); if(syscallno == PWRITE){ vl = va_arg(list, int64_t); fmtprint(&fmt, " %lld", vl); } break; } up->syscalltrace = fmtstrflush(&fmt); }