sysproc.ed (10059B)
1 1i 2 #define WANT_M 3 . 4 g/"edf.h"/d 5 ,s/->ref =/->ref.ref =/g 6 ,s/ref(p->dot)/ref(\&p->dot->ref)/g 7 ,s/ref(p->fgrp)/ref(\&p->fgrp->ref)/g 8 ,s/ref(p->pgrp)/ref(\&p->pgrp->ref)/g 9 ,s/ref(p->egrp)/ref(\&p->egrp->ref)/g 10 ,s/lock(img)/lock(\&img->ref.lk)/g 11 ,s/ref(img)/ref(\&img->ref)/g 12 ,s/return0(void\*)/return0(void *v)/g 13 ,s/(s = up->seg\[i\])/(&)/g 14 ,s;MACHP(0)->ticks;msec();g 15 /ESEG.*= newseg/a 16 flushmmu(); // Needed for Plan 9 VX 17 . 18 ,s;sleep(\&phore;sleep(\&phore.rendez;g 19 ,s;lock(\&s->sema);lock(\&s->sema.rendez.lk);g 20 ,s;wakeup(p);wakeup(\&p->rendez);g 21 ,s;lock(up->rgrp);lock(\&up->rgrp->ref.lk);g 22 ,s;ref(up->rgrp);ref(\&up->rgrp->ref);g 23 /sysr1/ s/(ulong\*)/(uint32 *x)/ 24 /Admitted/,/ yield/c 25 yield(); 26 . 27 /^ checkpagerefs/ c 28 vx32sysr1(); 29 . 30 /^sysrfork/ s/ulong/uint32/ 31 /^l2be/ s/long/uint32/ 32 -1 s/ulong/uint32/ 33 /^sysexec/ s/ulong/uint32/ 34 -1i 35 static char Echanged[] = "exec arguments changed underfoot"; 36 37 . 38 /^{/+1;/^}/-1 c 39 char *volatile elem, *volatile file, *ufile; 40 Chan *volatile tc; 41 42 /* 43 * Open the file, remembering the final element and the full name. 44 */ 45 file = nil; 46 elem = nil; 47 tc = nil; 48 if(waserror()){ 49 if(file) 50 free(file); 51 if(elem) 52 free(elem); 53 if(tc) 54 cclose(tc); 55 nexterror(); 56 } 57 58 ufile = uvalidaddr(arg[0], 1, 0); 59 file = validnamedup(ufile, 1); 60 tc = namec(file, Aopen, OEXEC, 0); 61 kstrdup((char**)&elem, up->genbuf); 62 63 /* 64 * Read the header. If it's a #!, fill in progarg[] with info and repeat. 65 */ 66 int i, n, nprogarg; 67 char *progarg[sizeof(Exec)/2+1]; 68 char *prog, *p; 69 char line[sizeof(Exec)+1]; 70 Exec exec; 71 72 nprogarg = 0; 73 n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0); 74 if(n < 2) 75 error(Ebadexec); 76 p = (char*)&exec; 77 if(p[0] == '#' && p[1] == '!'){ 78 memmove(line, p, n); 79 nprogarg = shargs(line, n, progarg); 80 if(nprogarg == 0) 81 error(Ebadexec); 82 83 /* The original file becomes an extra arg after #! line */ 84 progarg[nprogarg++] = file; 85 86 /* 87 * Take the #! $0 as a file to open, and replace 88 * $0 with the original path's name. 89 */ 90 prog = progarg[0]; 91 progarg[0] = elem; 92 cclose(tc); 93 tc = nil; /* in case namec errors out */ 94 tc = namec(prog, Aopen, OEXEC, 0); 95 n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0); 96 if(n < 2) 97 error(Ebadexec); 98 } 99 100 /* 101 * #! has had its chance, now we need a real binary 102 */ 103 uint32 magic, entry, text, etext, data, edata, bss, ebss; 104 105 magic = l2be(exec.magic); 106 if(n != sizeof(Exec) || l2be(exec.magic) != AOUT_MAGIC) 107 error(Ebadexec); 108 109 entry = l2be(exec.entry); 110 text = l2be(exec.text); 111 data = l2be(exec.data); 112 bss = l2be(exec.bss); 113 etext = ROUND(UTZERO+sizeof(Exec)+text, BY2PG); 114 edata = ROUND(etext + data, BY2PG); 115 ebss = ROUND(etext + data + bss, BY2PG); 116 117 //iprint("entry %#lux text %#lux data %#lux bss %#lux\n", entry, text, data, bss); 118 //iprint("etext %#lux edata %#lux ebss %#lux\n", etext, edata, ebss); 119 120 if(entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text) 121 error(Ebadexec); 122 123 /* many overflow possibilities */ 124 if(text >= USTKTOP || data >= USTKTOP || bss >= USTKTOP 125 || etext >= USTKTOP || edata >= USTKTOP || ebss >= USTKTOP 126 || etext >= USTKTOP || edata < etext || ebss < edata) 127 error(Ebadexec); 128 129 /* 130 * Copy argv into new stack segment temporarily mapped elsewhere. 131 * Be careful: multithreaded program could be changing argv during this. 132 * Pass 1: count number of arguments, string bytes. 133 */ 134 int nargv, strbytes; 135 uint32 argp, ssize, spage; 136 137 strbytes = 0; 138 for(i=0; i<nprogarg; i++) 139 strbytes += strlen(progarg[i]) + 1; 140 141 argp = arg[1]; 142 for(nargv=0;; nargv++, argp += BY2WD){ 143 uint32 a; 144 char *str; 145 146 a = *(uint32*)uvalidaddr(argp, BY2WD, 0); 147 if(a == 0) 148 break; 149 str = uvalidaddr(a, 1, 0); 150 n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1; 151 if(nprogarg > 0 && nargv == 0) 152 continue; /* going to skip argv[0] on #! */ 153 strbytes += n; 154 } 155 if(nargv == 0) 156 error("exec missing argv"); 157 158 /* 159 * Skip over argv[0] if using #!. Waited until now so that 160 * string would still be checked for validity during loop. 161 */ 162 if(nprogarg > 0){ 163 nargv--; 164 arg[1] += BY2WD; 165 } 166 167 ssize = BY2WD*((nprogarg+nargv)+1) + ROUND(strbytes, BY2WD) + sizeof(Tos); 168 169 /* 170 * 8-byte align SP for those (e.g. sparc) that need it. 171 * execregs() will subtract another 4 bytes for argc. 172 */ 173 if((ssize+4) & 7) 174 ssize += 4; 175 spage = (ssize+(BY2PG-1)) >> PGSHIFT; 176 177 /* 178 * Pass 2: build the stack segment, being careful not to assume 179 * that the counts from pass 1 are still valid. 180 */ 181 if(spage > TSTKSIZ) 182 error(Enovmem); 183 184 qlock(&up->seglock); 185 if(waserror()){ 186 if(up->seg[ESEG]){ 187 putseg(up->seg[ESEG]); 188 up->seg[ESEG] = nil; 189 } 190 qunlock(&up->seglock); 191 nexterror(); 192 } 193 up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG); 194 flushmmu(); // Needed for Plan 9 VX XXX really? 195 196 /* 197 * Top-of-stack structure. 198 */ 199 uchar *uzero; 200 uzero = up->pmmu.uzero; 201 Tos *tos; 202 uint32 utos; 203 utos = USTKTOP - sizeof(Tos); 204 tos = (Tos*)(uzero + utos + TSTKTOP - USTKTOP); 205 tos->cyclefreq = m->cyclefreq; 206 cycles((uvlong*)&tos->pcycles); 207 tos->pcycles = -tos->pcycles; 208 tos->kcycles = tos->pcycles; 209 tos->clock = 0; 210 211 /* 212 * Argument pointers and strings, together. 213 */ 214 char *bp, *ep; 215 uint32 *targp; 216 uint32 ustrp, uargp; 217 218 ustrp = utos - ROUND(strbytes, BY2WD); 219 uargp = ustrp - BY2WD*((nprogarg+nargv)+1); 220 bp = (char*)(uzero + ustrp + TSTKTOP - USTKTOP); 221 ep = bp + strbytes; 222 p = bp; 223 targp = (uint32*)(uzero + uargp + TSTKTOP - USTKTOP); 224 225 /* #! args are trusted */ 226 for(i=0; i<nprogarg; i++){ 227 n = strlen(progarg[i]) + 1; 228 if(n > ep - p) 229 error(Echanged); 230 memmove(p, progarg[i], n); 231 p += n; 232 *targp++ = ustrp; 233 ustrp += n; 234 } 235 236 /* the rest are not */ 237 argp = arg[1]; 238 for(i=0; i<nargv; i++){ 239 uint32 a; 240 char *str; 241 242 a = *(uint32*)uvalidaddr(argp, BY2WD, 0); 243 argp += BY2WD; 244 245 str = uvalidaddr(a, 1, 0); 246 n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1; 247 if(n > ep - p) 248 error(Echanged); 249 memmove(p, str, n); 250 p += n; 251 *targp++ = ustrp; 252 ustrp += n; 253 } 254 255 if(*(uint32*)uvalidaddr(argp, BY2WD, 0) != 0) 256 error(Echanged); 257 *targp = 0; 258 259 /* 260 * But wait, there's more: prepare an arg copy for up->args 261 * using the copy we just made in the temporary segment. 262 */ 263 char *args; 264 int nargs; 265 266 n = p - bp; /* includes NUL on last arg, so must be > 0 */ 267 if(n <= 0) /* nprogarg+nargv > 0; checked above */ 268 error(Egreg); 269 if(n > 128) 270 n = 128; 271 args = smalloc(n); 272 if(waserror()){ 273 free(args); 274 nexterror(); 275 } 276 memmove(args, bp, n); 277 /* find beginning of UTF character boundary to place final NUL */ 278 while(n > 0 && (args[n-1]&0xC0) == 0x80) 279 n--; 280 args[n-1] = '\0'; 281 nargs = n; 282 283 /* 284 * Now we're ready to commit. 285 */ 286 free(up->text); 287 up->text = elem; 288 free(up->args); 289 up->args = args; 290 up->nargs = n; 291 elem = nil; 292 poperror(); /* args */ 293 294 /* 295 * Free old memory. Special segments maintained across exec. 296 */ 297 Segment *s; 298 for(i = SSEG; i <= BSEG; i++) { 299 putseg(up->seg[i]); 300 up->seg[i] = nil; /* in case of error */ 301 } 302 for(i = BSEG+1; i< NSEG; i++) { 303 s = up->seg[i]; 304 if(s && (s->type&SG_CEXEC)) { 305 putseg(s); 306 up->seg[i] = nil; 307 } 308 } 309 310 /* 311 * Close on exec 312 */ 313 Fgrp *f; 314 f = up->fgrp; 315 for(i=0; i<=f->maxfd; i++) 316 fdclose(i, CCEXEC); 317 318 /* Text. Shared. Attaches to cache image if possible */ 319 /* attachimage returns a locked cache image */ 320 Image *img; 321 Segment *ts; 322 img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (etext-UTZERO)>>PGSHIFT); 323 ts = img->s; 324 up->seg[TSEG] = ts; 325 ts->flushme = 1; 326 ts->fstart = 0; 327 ts->flen = sizeof(Exec)+text; 328 unlock(&img->ref.lk); 329 330 /* Data. Shared. */ 331 s = newseg(SG_DATA, etext, (edata-etext)>>PGSHIFT); 332 up->seg[DSEG] = s; 333 334 /* Attached by hand */ 335 incref(&img->ref); 336 s->image = img; 337 s->fstart = ts->fstart+ts->flen; 338 s->flen = data; 339 340 /* BSS. Zero fill on demand */ 341 up->seg[BSEG] = newseg(SG_BSS, edata, (ebss-edata)>>PGSHIFT); 342 343 /* 344 * Move the stack 345 */ 346 s = up->seg[ESEG]; 347 up->seg[ESEG] = 0; 348 up->seg[SSEG] = s; 349 qunlock(&up->seglock); 350 poperror(); /* seglock */ 351 352 s->base = USTKTOP-USTKSIZE; 353 s->top = USTKTOP; 354 relocateseg(s, USTKTOP-TSTKTOP); 355 356 /* 357 * '/' processes are higher priority (hack to make /ip more responsive). 358 */ 359 if(devtab[tc->type]->dc == L'/') 360 up->basepri = PriRoot; 361 up->priority = up->basepri; 362 poperror(); /* tc, elem, file */ 363 cclose(tc); 364 free(file); 365 // elem is now up->text 366 367 /* 368 * At this point, the mmu contains info about the old address 369 * space and needs to be flushed 370 */ 371 flushmmu(); 372 qlock(&up->debug); 373 up->nnote = 0; 374 up->notify = 0; 375 up->notified = 0; 376 up->privatemem = 0; 377 procsetup(up); 378 qunlock(&up->debug); 379 if(up->hang) 380 up->procctl = Proc_stopme; 381 382 return execregs(entry, USTKTOP - uargp, nprogarg+nargv); 383 . 384 /^syssleep/s/ulong/uint32/ 385 /^sysalarm/s/ulong/uint32/ 386 /^sysexits/s/ulong/uint32/ 387 /status/;/if(status)/ c 388 char *status; 389 char *inval = "invalid exit string"; 390 char buf[ERRMAX]; 391 392 if(arg[0]){ 393 . 394 /validaddr/c 395 status = uvalidaddr(arg[0], 1, 0); 396 . 397 /^ }/ c 398 }else 399 status = nil; 400 . 401 /^sys_wait/s/ulong/uint32/ 402 /validaddr(arg\[0\], sizeof(OWaitmsg), 1)/ c 403 ow = uvalidaddr(arg[0], sizeof(OWaitmsg), 1); 404 . 405 /ow =/d 406 /^sysawait/s/ulong/uint32/ 407 /ulong n/ s/ulong/uint32/ 408 a 409 char *buf; 410 . 411 /validaddr/ s/v/buf = uv/ 412 /i = / s/(char\*)arg\[0\]/buf/ 413 /^generrstr/ s/char \*buf/uint32 addr/ 414 /^$/i 415 char *buf; 416 . 417 /validaddr/ s/v/buf = uv/ 418 s/(ulong)buf/addr/ 419 /^syserrstr/s/ulong/uint32/ 420 /return/s/(char\*)// 421 /^sys_errstr/s/ulong/uint32/ 422 /return/s/(char\*)// 423 /^sysnotify/s/ulong/uint32/ 424 /validaddr/;/up->notify/c 425 uvalidaddr(arg[0], 1, 0); 426 up->notify = arg[0]; /* checked again when used */ 427 . 428 /^sysnoted/s/ulong/uint32/ 429 /^syssegbrk/s/ulong/uint32/ 430 /addr/s/ulong/uint32/ 431 /^syssegattach/s/ulong/uint32/ 432 /return/s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/ 433 /^syssegdetach/s/ulong/uint32/ 434 /addr/s/ulong/uint32/ 435 /^syssegfree/s/ulong/uint32/ 436 /from/s/ulong/uint32/ 437 /^sysbrk_/s/ulong/uint32/ 438 /^sysrendezvous/s/ulong/uint32/ 439 /^syssemacquire/s/ulong/uint32/ 440 /validaddr/ s/v/addr = uv/ 441 /addr =/d 442 /(ulong)addr/s/(ulong)addr/arg[0]/ 443 /^syssemrelease/s/ulong/uint32/ 444 /validaddr/ s/v/addr = uv/ 445 /addr =/d 446 /(ulong)addr/s/(ulong)addr/arg[0]/