Blob
- Date:
- Message:
- Working on better handling of multithreading in general and core dumps in particular. See notes: new types: register is something that when dereferenced gives you the registers. the Ureg is no longer mapped at 0. refconst is something that gives a constant when dereferenced. new builtin register("AX") creates register values new builtin refconst(0x123) creates refconst values new builtin var("foo") is equivalent to the variable foo (it returns foo but can also be used as the lhs of an assignment). new acid function getregs() returns a list of the current values of registers. new acid function setregs() sets the current registers to those values. note that getregs and setregs operate on register locations, not the register values themselves. new acid function resetregs() sets registers to register("AX"), etc. new acid function clearregs() sets all registers to constant -1. the default register settings are as in resetregs(), not small numbers. new acid variables coretext, pids, systype, corefile, cmdline. new behavior: local variable lookup, stk, etc., use the acid values of registers (*PC, *SP, and so on), so the thread support code can change the context completely. unary + is applicable to more data types and prints more often.
- Actions:
- History | Blame | Raw File
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>4 #include <ctype.h>5 #include <mach.h>6 #define Extern extern7 #include "acid.h"9 void10 error(char *fmt, ...)11 {12 int i;13 char buf[2048];14 va_list arg;16 /* Unstack io channels */17 if(iop != 0) {18 for(i = 1; i < iop; i++)19 Bterm(io[i]);20 bout = io[0];21 iop = 0;22 }24 ret = 0;25 gotint = 0;26 Bflush(bout);27 if(silent)28 silent = 0;29 else {30 va_start(arg, fmt);31 vseprint(buf, buf+sizeof(buf), fmt, arg);32 va_end(arg);33 fprint(2, "%Z: (error) %s\n", buf);34 }35 while(popio())36 ;37 interactive = 1;38 longjmp(err, 1);39 }41 void42 unwind(void)43 {44 int i;45 Lsym *s;46 Value *v;48 for(i = 0; i < Hashsize; i++) {49 for(s = hash[i]; s; s = s->hash) {50 while(s->v->pop) {51 v = s->v->pop;52 free(s->v);53 s->v = v;54 }55 }56 }57 }59 void60 execute(Node *n)61 {62 Value *v;63 Lsym *sl;64 Node *l, *r;65 int i, s, e;66 Node res, xx;67 static int stmnt;69 gc();70 if(gotint)71 error("interrupted");73 if(n == 0)74 return;76 if(stmnt++ > 5000) {77 Bflush(bout);78 stmnt = 0;79 }81 l = n->left;82 r = n->right;84 switch(n->op) {85 default:86 expr(n, &res);87 if(ret || (res.type == TLIST && res.store.u.l == 0))88 break;89 prnt->right = &res;90 expr(prnt, &xx);91 break;92 case OASGN:93 case OCALL:94 expr(n, &res);95 break;96 case OCOMPLEX:97 decl(n);98 break;99 case OLOCAL:100 for(n = n->left; n; n = n->left) {101 if(ret == 0)102 error("local not in function");103 sl = n->sym;104 if(sl->v->ret == ret)105 error("%s declared twice", sl->name);106 v = gmalloc(sizeof(Value));107 v->ret = ret;108 v->pop = sl->v;109 sl->v = v;110 v->scope = 0;111 *(ret->tail) = sl;112 ret->tail = &v->scope;113 v->set = 0;114 }115 break;116 case ORET:117 if(ret == 0)118 error("return not in function");119 expr(n->left, ret->val);120 longjmp(ret->rlab, 1);121 case OLIST:122 execute(n->left);123 execute(n->right);124 break;125 case OIF:126 expr(l, &res);127 if(r && r->op == OELSE) {128 if(bool(&res))129 execute(r->left);130 else131 execute(r->right);132 }133 else if(bool(&res))134 execute(r);135 break;136 case OWHILE:137 for(;;) {138 expr(l, &res);139 if(!bool(&res))140 break;141 execute(r);142 }143 break;144 case ODO:145 expr(l->left, &res);146 if(res.type != TINT)147 error("loop must have integer start");148 s = res.store.u.ival;149 expr(l->right, &res);150 if(res.type != TINT)151 error("loop must have integer end");152 e = res.store.u.ival;153 for(i = s; i <= e; i++)154 execute(r);155 break;156 }157 }159 int160 bool(Node *n)161 {162 int true = 0;164 if(n->op != OCONST)165 fatal("bool: not const");167 switch(n->type) {168 case TINT:169 if(n->store.u.ival != 0)170 true = 1;171 break;172 case TFLOAT:173 if(n->store.u.fval != 0.0)174 true = 1;175 break;176 case TSTRING:177 if(n->store.u.string->len)178 true = 1;179 break;180 case TLIST:181 if(n->store.u.l)182 true = 1;183 break;184 }185 return true;186 }188 void189 convflt(Node *r, char *flt)190 {191 char c;193 c = flt[0];194 if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {195 r->type = TSTRING;196 r->store.fmt = 's';197 r->store.u.string = strnode(flt);198 }199 else {200 r->type = TFLOAT;201 r->store.u.fval = atof(flt);202 }203 }205 void206 indir(Map *m, ulong addr, char fmt, Node *r)207 {208 int i;209 u32int ival;210 u64int vval;211 int ret;212 u8int cval;213 u16int sval;214 char buf[512], reg[12];216 r->op = OCONST;217 r->store.fmt = fmt;218 switch(fmt) {219 default:220 error("bad pointer format '%c' for *", fmt);221 case 'c':222 case 'C':223 case 'b':224 r->type = TINT;225 ret = get1(m, addr, &cval, 1);226 if (ret < 0)227 error("indir: %r");228 r->store.u.ival = cval;229 break;230 case 'x':231 case 'd':232 case 'u':233 case 'o':234 case 'q':235 case 'r':236 r->type = TINT;237 ret = get2(m, addr, &sval);238 if (ret < 0)239 error("indir: %r");240 r->store.u.ival = sval;241 break;242 case 'a':243 case 'A':244 case 'B':245 case 'X':246 case 'D':247 case 'U':248 case 'O':249 case 'Q':250 r->type = TINT;251 ret = get4(m, addr, &ival);252 if (ret < 0)253 error("indir: %r");254 r->store.u.ival = ival;255 break;256 case 'V':257 case 'W':258 case 'Y':259 case 'Z':260 r->type = TINT;261 ret = get8(m, addr, &vval);262 if (ret < 0)263 error("indir: %r");264 r->store.u.ival = vval;265 break;266 case 's':267 r->type = TSTRING;268 for(i = 0; i < sizeof(buf)-1; i++) {269 ret = get1(m, addr, (uchar*)&buf[i], 1);270 if (ret < 0)271 error("indir: %r");272 addr++;273 if(buf[i] == '\0')274 break;275 }276 buf[i] = 0;277 if(i == 0)278 strcpy(buf, "(null)");279 r->store.u.string = strnode(buf);280 break;281 case 'R':282 r->type = TSTRING;283 for(i = 0; i < sizeof(buf)-2; i += 2) {284 ret = get1(m, addr, (uchar*)&buf[i], 2);285 if (ret < 0)286 error("indir: %r");287 addr += 2;288 if(buf[i] == 0 && buf[i+1] == 0)289 break;290 }291 buf[i++] = 0;292 buf[i] = 0;293 r->store.u.string = runenode((Rune*)buf);294 break;295 case 'i':296 case 'I':297 if ((*mach->das)(m, addr, fmt, buf, sizeof(buf)) < 0)298 error("indir: %r");299 r->type = TSTRING;300 r->store.fmt = 's';301 r->store.u.string = strnode(buf);302 break;303 case 'f':304 ret = get1(m, addr, (uchar*)buf, mach->szfloat);305 if (ret < 0)306 error("indir: %r");307 mach->ftoa32(buf, sizeof(buf), (void*) buf);308 convflt(r, buf);309 break;310 case 'g':311 ret = get1(m, addr, (uchar*)buf, mach->szfloat);312 if (ret < 0)313 error("indir: %r");314 mach->ftoa32(buf, sizeof(buf), (void*) buf);315 r->type = TSTRING;316 r->store.u.string = strnode(buf);317 break;318 case 'F':319 ret = get1(m, addr, (uchar*)buf, mach->szdouble);320 if (ret < 0)321 error("indir: %r");322 mach->ftoa64(buf, sizeof(buf), (void*) buf);323 convflt(r, buf);324 break;325 case '3': /* little endian ieee 80 with hole in bytes 8&9 */326 ret = get1(m, addr, (uchar*)reg, 10);327 if (ret < 0)328 error("indir: %r");329 memmove(reg+10, reg+8, 2); /* open hole */330 memset(reg+8, 0, 2); /* fill it */331 leieeeftoa80(buf, sizeof(buf), reg);332 convflt(r, buf);333 break;334 case '8': /* big-endian ieee 80 */335 ret = get1(m, addr, (uchar*)reg, 10);336 if (ret < 0)337 error("indir: %r");338 beieeeftoa80(buf, sizeof(buf), reg);339 convflt(r, buf);340 break;341 case 'G':342 ret = get1(m, addr, (uchar*)buf, mach->szdouble);343 if (ret < 0)344 error("indir: %r");345 mach->ftoa64(buf, sizeof(buf), (void*) buf);346 r->type = TSTRING;347 r->store.u.string = strnode(buf);348 break;349 }350 }352 void353 indirreg(Regs *regs, char *name, char fmt, Node *r)354 {355 ulong val;357 if(regs == 0)358 error("no register set for *%s=", name);360 r->op = OCONST;361 r->store.fmt = fmt;362 switch(fmt){363 default:364 error("bad pointer format '%c' for *%s", fmt, name);365 case 'c':366 case 'C':367 case 'b':368 case 'x':369 case 'd':370 case 'u':371 case 'o':372 case 'q':373 case 'r':374 case 'a':375 case 'A':376 case 'B':377 case 'X':378 case 'D':379 case 'U':380 case 'O':381 case 'Q':382 case 'V':383 case 'W':384 case 'Y':385 case 'Z':386 if(rget(regs, name, &val) < 0)387 error("reading %s: %r", name);388 r->type = TINT;389 r->store.u.ival = val;390 break;391 case 'f':392 case 'g':393 case 'F':394 case '3':395 case '8':396 case 'G':397 error("floating point registers not supported");398 break;399 }400 }402 void403 windir(Map *m, Node aes, Node *rval, Node *r)404 {405 uchar cval;406 ushort sval;407 Node res;408 int ret;410 if(m == 0)411 error("no map for */@=");413 if(aes.type != TINT)414 error("bad type lhs of */@=");416 expr(rval, &res);418 if(m != cormap && wtflag == 0)419 error("not in write mode");421 r->type = res.type;422 r->store.fmt = res.store.fmt;423 r->store = res.store;425 switch(res.store.fmt) {426 default:427 error("bad pointer format '%c' for */@=", res.store.fmt);428 case 'c':429 case 'C':430 case 'b':431 cval = res.store.u.ival;432 ret = put1(m, aes.store.u.ival, &cval, 1);433 break;434 case 'r':435 case 'x':436 case 'd':437 case 'u':438 case 'o':439 sval = res.store.u.ival;440 ret = put2(m, aes.store.u.ival, sval);441 r->store.u.ival = sval;442 break;443 case 'a':444 case 'A':445 case 'B':446 case 'X':447 case 'D':448 case 'U':449 case 'O':450 ret = put4(m, aes.store.u.ival, res.store.u.ival);451 break;452 case 'V':453 case 'W':454 case 'Y':455 case 'Z':456 ret = put8(m, aes.store.u.ival, res.store.u.ival);457 break;458 case 's':459 case 'R':460 ret = put1(m, aes.store.u.ival, (uchar*)res.store.u.string->string, res.store.u.string->len);461 break;462 }463 if (ret < 0)464 error("windir: %r");465 }467 void468 windirreg(Regs *regs, char *name, Node *rval, Node *r)469 {470 Node res;472 if(regs == 0)473 error("no register set for *%s=", name);475 expr(rval, &res);477 r->type = res.type;478 r->store.fmt = res.store.fmt;479 r->store = res.store;481 switch(res.store.fmt){482 default:483 error("bad format '%c' for *%s=", res.store.fmt, name);484 case 'c':485 case 'C':486 case 'b':487 case 'x':488 case 'd':489 case 'u':490 case 'o':491 case 'q':492 case 'r':493 case 'a':494 case 'A':495 case 'B':496 case 'X':497 case 'D':498 case 'U':499 case 'O':500 case 'Q':501 case 'V':502 case 'W':503 case 'Y':504 case 'Z':505 if(rput(regs, name, res.store.u.ival) < 0)506 error("writing %s: %r", name);507 break;508 case 'f':509 case 'g':510 case 'F':511 case '3':512 case '8':513 case 'G':514 error("floating point registers not supported");515 break;516 }517 }519 void520 call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)521 {522 int np, i;523 Rplace rlab;524 Node *n, res;525 Value *v, *f;526 Lsym *s, *next;527 Node *avp[Maxarg], *ava[Maxarg];529 rlab.local = 0;531 na = 0;532 flatten(avp, parameters);533 np = na;534 na = 0;535 flatten(ava, local);536 if(np != na) {537 if(np < na)538 error("%s: too few arguments", fn);539 error("%s: too many arguments", fn);540 }542 rlab.tail = &rlab.local;544 ret = &rlab;545 for(i = 0; i < np; i++) {546 n = ava[i];547 switch(n->op) {548 default:549 error("%s: %d formal not a name", fn, i);550 case ONAME:551 expr(avp[i], &res);552 s = n->sym;553 break;554 case OINDM:555 res.store.u.cc = avp[i];556 res.type = TCODE;557 res.store.comt = 0;558 if(n->left->op != ONAME)559 error("%s: %d formal not a name", fn, i);560 s = n->left->sym;561 break;562 }563 if(s->v->ret == ret)564 error("%s already declared at this scope", s->name);566 v = gmalloc(sizeof(Value));567 v->ret = ret;568 v->pop = s->v;569 s->v = v;570 v->scope = 0;571 *(rlab.tail) = s;572 rlab.tail = &v->scope;574 v->store = res.store;575 v->type = res.type;576 v->set = 1;577 }579 ret->val = retexp;580 if(setjmp(rlab.rlab) == 0)581 execute(body);583 for(s = rlab.local; s; s = next) {584 f = s->v;585 next = f->scope;586 s->v = f->pop;587 free(f);588 }589 }