builtin.c (29415B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <ctype.h> 5 #include <mach.h> 6 #include <regexp.h> 7 #define Extern extern 8 #include "acid.h" 9 #include "y.tab.h" 10 11 void cvtatof(Node*, Node*); 12 void cvtatoi(Node*, Node*); 13 void cvtitoa(Node*, Node*); 14 void bprint(Node*, Node*); 15 void funcbound(Node*, Node*); 16 void printto(Node*, Node*); 17 void getfile(Node*, Node*); 18 void fmt(Node*, Node*); 19 void pcfile(Node*, Node*); 20 void pcline(Node*, Node*); 21 void setproc(Node*, Node*); 22 void strace(Node*, Node*); 23 void follow(Node*, Node*); 24 void reason(Node*, Node*); 25 void newproc(Node*, Node*); 26 void startstop(Node*, Node*); 27 void match(Node*, Node*); 28 void status(Node*, Node*); 29 void xkill(Node*,Node*); 30 void waitstop(Node*, Node*); 31 void waitsyscall(Node*, Node*); 32 void stop(Node*, Node*); 33 void start(Node*, Node*); 34 void filepc(Node*, Node*); 35 void doerror(Node*, Node*); 36 void rc(Node*, Node*); 37 void doaccess(Node*, Node*); 38 void map(Node*, Node*); 39 void readfile(Node*, Node*); 40 void interpret(Node*, Node*); 41 void include(Node*, Node*); 42 void includepipe(Node*, Node*); 43 void regexp(Node*, Node*); 44 void textfile(Node*, Node*); 45 void deltextfile(Node*, Node*); 46 void stringn(Node*, Node*); 47 void xregister(Node*, Node*); 48 void refconst(Node*, Node*); 49 void dolook(Node*, Node*); 50 void step1(Node*, Node*); 51 52 typedef struct Btab Btab; 53 struct Btab 54 { 55 char *name; 56 void (*fn)(Node*, Node*); 57 } tab[] = 58 { 59 "access", doaccess, 60 "atof", cvtatof, 61 "atoi", cvtatoi, 62 "deltextfile", deltextfile, 63 "error", doerror, 64 "file", getfile, 65 "filepc", filepc, 66 "fnbound", funcbound, 67 "fmt", fmt, 68 "follow", follow, 69 "include", include, 70 "includepipe", includepipe, 71 "interpret", interpret, 72 "itoa", cvtitoa, 73 "kill", xkill, 74 "map", map, 75 "match", match, 76 "newproc", newproc, 77 "pcfile", pcfile, 78 "pcline", pcline, 79 "print", bprint, 80 "printto", printto, 81 "rc", rc, 82 "readfile", readfile, 83 "reason", reason, 84 "refconst", refconst, 85 "regexp", regexp, 86 "register", xregister, 87 "setproc", setproc, 88 "start", start, 89 "startstop", startstop, 90 "status", status, 91 "step1", step1, 92 "stop", stop, 93 "strace", strace, 94 "stringn", stringn, 95 "textfile", textfile, 96 "var", dolook, 97 "waitstop", waitstop, 98 "waitsyscall", waitsyscall, 99 0 100 }; 101 102 void 103 mkprint(Lsym *s) 104 { 105 prnt = malloc(sizeof(Node)); 106 memset(prnt, 0, sizeof(Node)); 107 prnt->op = OCALL; 108 prnt->left = malloc(sizeof(Node)); 109 memset(prnt->left, 0, sizeof(Node)); 110 prnt->left->sym = s; 111 } 112 113 void 114 installbuiltin(void) 115 { 116 Btab *b; 117 Lsym *s; 118 119 b = tab; 120 while(b->name) { 121 s = look(b->name); 122 if(s == 0) 123 s = enter(b->name, Tid); 124 125 s->builtin = b->fn; 126 if(b->fn == bprint) 127 mkprint(s); 128 b++; 129 } 130 } 131 132 void 133 match(Node *r, Node *args) 134 { 135 int i; 136 List *f; 137 Node *av[Maxarg]; 138 Node resi, resl; 139 140 na = 0; 141 flatten(av, args); 142 if(na != 2) 143 error("match(obj, list): arg count"); 144 145 expr(av[1], &resl); 146 if(resl.type != TLIST) 147 error("match(obj, list): need list"); 148 expr(av[0], &resi); 149 150 r->op = OCONST; 151 r->type = TINT; 152 r->store.fmt = 'D'; 153 r->store.u.ival = -1; 154 155 i = 0; 156 for(f = resl.store.u.l; f; f = f->next) { 157 if(resi.type == f->type) { 158 switch(resi.type) { 159 case TINT: 160 if(resi.store.u.ival == f->store.u.ival) { 161 r->store.u.ival = i; 162 return; 163 } 164 break; 165 case TFLOAT: 166 if(resi.store.u.fval == f->store.u.fval) { 167 r->store.u.ival = i; 168 return; 169 } 170 break; 171 case TSTRING: 172 if(scmp(resi.store.u.string, f->store.u.string)) { 173 r->store.u.ival = i; 174 return; 175 } 176 break; 177 case TLIST: 178 error("match(obj, list): not defined for list"); 179 } 180 } 181 i++; 182 } 183 } 184 185 void 186 newproc(Node *r, Node *args) 187 { 188 int i; 189 Node res; 190 char *p, *e; 191 char *argv[Maxarg], buf[Strsize]; 192 193 i = 1; 194 argv[0] = symfil; 195 196 if(args) { 197 expr(args, &res); 198 if(res.type != TSTRING) 199 error("newproc(): arg not string"); 200 if(res.store.u.string->len >= sizeof(buf)) 201 error("newproc(): too many arguments"); 202 memmove(buf, res.store.u.string->string, res.store.u.string->len); 203 buf[res.store.u.string->len] = '\0'; 204 p = buf; 205 e = buf+res.store.u.string->len; 206 for(;;) { 207 while(p < e && (*p == '\t' || *p == ' ')) 208 *p++ = '\0'; 209 if(p >= e) 210 break; 211 argv[i++] = p; 212 if(i >= Maxarg) 213 error("newproc: too many arguments"); 214 while(p < e && *p != '\t' && *p != ' ') 215 p++; 216 } 217 } 218 argv[i] = 0; 219 r->op = OCONST; 220 r->type = TINT; 221 r->store.fmt = 'D'; 222 r->store.u.ival = nproc(argv); 223 } 224 225 void 226 step1(Node *r, Node *args) 227 { 228 Node res; 229 230 USED(r); 231 if(args == 0) 232 error("step1(pid): no pid"); 233 expr(args, &res); 234 if(res.type != TINT) 235 error("step1(pid): arg type"); 236 237 msg(res.store.u.ival, "step"); 238 notes(res.store.u.ival); 239 dostop(res.store.u.ival); 240 } 241 242 void 243 startstop(Node *r, Node *args) 244 { 245 Node res; 246 247 USED(r); 248 if(args == 0) 249 error("startstop(pid): no pid"); 250 expr(args, &res); 251 if(res.type != TINT) 252 error("startstop(pid): arg type"); 253 254 msg(res.store.u.ival, "startstop"); 255 notes(res.store.u.ival); 256 dostop(res.store.u.ival); 257 } 258 259 void 260 waitstop(Node *r, Node *args) 261 { 262 Node res; 263 264 USED(r); 265 if(args == 0) 266 error("waitstop(pid): no pid"); 267 expr(args, &res); 268 if(res.type != TINT) 269 error("waitstop(pid): arg type"); 270 271 Bflush(bout); 272 msg(res.store.u.ival, "waitstop"); 273 notes(res.store.u.ival); 274 dostop(res.store.u.ival); 275 } 276 277 void 278 waitsyscall(Node *r, Node *args) 279 { 280 Node res; 281 282 USED(r); 283 if(args == 0) 284 error("waitsyscall(pid): no pid"); 285 expr(args, &res); 286 if(res.type != TINT) 287 error("waitsycall(pid): arg type"); 288 289 Bflush(bout); 290 msg(res.store.u.ival, "sysstop"); 291 notes(res.store.u.ival); 292 dostop(res.store.u.ival); 293 } 294 295 void 296 start(Node *r, Node *args) 297 { 298 Node res; 299 300 USED(r); 301 if(args == 0) 302 error("start(pid): no pid"); 303 expr(args, &res); 304 if(res.type != TINT) 305 error("start(pid): arg type"); 306 307 msg(res.store.u.ival, "start"); 308 } 309 310 void 311 stop(Node *r, Node *args) 312 { 313 Node res; 314 315 USED(r); 316 if(args == 0) 317 error("stop(pid): no pid"); 318 expr(args, &res); 319 if(res.type != TINT) 320 error("stop(pid): arg type"); 321 322 Bflush(bout); 323 msg(res.store.u.ival, "stop"); 324 notes(res.store.u.ival); 325 dostop(res.store.u.ival); 326 } 327 328 void 329 xkill(Node *r, Node *args) 330 { 331 Node res; 332 333 USED(r); 334 if(args == 0) 335 error("kill(pid): no pid"); 336 expr(args, &res); 337 if(res.type != TINT) 338 error("kill(pid): arg type"); 339 340 msg(res.store.u.ival, "kill"); 341 deinstall(res.store.u.ival); 342 } 343 344 void 345 xregister(Node *r, Node *args) 346 { 347 int tid; 348 Regdesc *rp; 349 Node res, resid; 350 Node *av[Maxarg]; 351 352 na = 0; 353 flatten(av, args); 354 if(na != 1/* && na != 2 */) 355 error("register(name): arg count"); 356 357 expr(av[0], &res); 358 if(res.type != TSTRING) 359 error("register(name): arg type: name should be string"); 360 tid = 0; 361 if(na == 2){ 362 expr(av[1], &resid); 363 if(resid.type != TINT) 364 error("register(name[, threadid]): arg type: threadid should be int"); 365 tid = resid.store.u.ival; 366 } 367 if((rp = regdesc(res.store.u.string->string)) == nil) 368 error("no such register"); 369 r->op = OCONST; 370 r->type = TREG; 371 r->store.fmt = rp->format; 372 r->store.u.reg.name = rp->name; 373 r->store.u.reg.thread = tid; 374 } 375 376 void 377 refconst(Node *r, Node *args) 378 { 379 Node *n; 380 381 if(args == 0) 382 error("refconst(expr): arg count"); 383 384 n = an(OCONST, ZN, ZN); 385 expr(args, n); 386 387 r->op = OCONST; 388 r->type = TCON; 389 r->store.u.con = n; 390 } 391 392 void 393 dolook(Node *r, Node *args) 394 { 395 Node res; 396 Lsym *l; 397 398 if(args == 0) 399 error("var(string): arg count"); 400 expr(args, &res); 401 if(res.type != TSTRING) 402 error("var(string): arg type"); 403 404 r->op = OCONST; 405 if((l = look(res.store.u.string->string)) == nil || l->v->set == 0){ 406 r->type = TLIST; 407 r->store.u.l = nil; 408 }else{ 409 r->type = l->v->type; 410 r->store = l->v->store; 411 } 412 } 413 414 void 415 status(Node *r, Node *args) 416 { 417 Node res; 418 char *p; 419 420 USED(r); 421 if(args == 0) 422 error("status(pid): no pid"); 423 expr(args, &res); 424 if(res.type != TINT) 425 error("status(pid): arg type"); 426 427 p = getstatus(res.store.u.ival); 428 r->store.u.string = strnode(p); 429 r->op = OCONST; 430 r->store.fmt = 's'; 431 r->type = TSTRING; 432 } 433 434 void 435 reason(Node *r, Node *args) 436 { 437 Node res; 438 439 if(args == 0) 440 error("reason(cause): no cause"); 441 expr(args, &res); 442 if(res.type != TINT) 443 error("reason(cause): arg type"); 444 445 r->op = OCONST; 446 r->type = TSTRING; 447 r->store.fmt = 's'; 448 r->store.u.string = strnode((*mach->exc)(cormap, acidregs)); 449 } 450 451 void 452 follow(Node *r, Node *args) 453 { 454 int n, i; 455 Node res; 456 u64int f[10]; 457 List **tail, *l; 458 459 if(args == 0) 460 error("follow(addr): no addr"); 461 expr(args, &res); 462 if(res.type != TINT) 463 error("follow(addr): arg type"); 464 465 n = (*mach->foll)(cormap, acidregs, res.store.u.ival, f); 466 if (n < 0) 467 error("follow(addr): %r"); 468 tail = &r->store.u.l; 469 for(i = 0; i < n; i++) { 470 l = al(TINT); 471 l->store.u.ival = f[i]; 472 l->store.fmt = 'X'; 473 *tail = l; 474 tail = &l->next; 475 } 476 } 477 478 void 479 funcbound(Node *r, Node *args) 480 { 481 int n; 482 Node res; 483 u64int bounds[2]; 484 List *l; 485 486 if(args == 0) 487 error("fnbound(addr): no addr"); 488 expr(args, &res); 489 if(res.type != TINT) 490 error("fnbound(addr): arg type"); 491 492 n = fnbound(res.store.u.ival, bounds); 493 if (n >= 0) { 494 r->store.u.l = al(TINT); 495 l = r->store.u.l; 496 l->store.u.ival = bounds[0]; 497 l->store.fmt = 'X'; 498 l->next = al(TINT); 499 l = l->next; 500 l->store.u.ival = bounds[1]; 501 l->store.fmt = 'X'; 502 } 503 } 504 505 void 506 setproc(Node *r, Node *args) 507 { 508 Node res; 509 510 USED(r); 511 if(args == 0) 512 error("setproc(pid): no pid"); 513 expr(args, &res); 514 if(res.type != TINT) 515 error("setproc(pid): arg type"); 516 517 sproc(res.store.u.ival); 518 } 519 520 void 521 filepc(Node *r, Node *args) 522 { 523 int i; 524 Node res; 525 char *p, c; 526 u64int v; 527 528 if(args == 0) 529 error("filepc(filename:line): arg count"); 530 expr(args, &res); 531 if(res.type != TSTRING) 532 error("filepc(filename:line): arg type"); 533 534 p = strchr(res.store.u.string->string, ':'); 535 if(p == 0) 536 error("filepc(filename:line): bad arg format"); 537 538 c = *p; 539 *p++ = '\0'; 540 i = file2pc(res.store.u.string->string, atoi(p), &v); 541 p[-1] = c; 542 if(i < 0) 543 error("filepc(filename:line): can't find address"); 544 545 r->op = OCONST; 546 r->type = TINT; 547 r->store.fmt = 'D'; 548 r->store.u.ival = v; 549 } 550 551 void 552 interpret(Node *r, Node *args) 553 { 554 Node res; 555 int isave; 556 557 if(args == 0) 558 error("interpret(string): arg count"); 559 expr(args, &res); 560 if(res.type != TSTRING) 561 error("interpret(string): arg type"); 562 563 pushstr(&res); 564 565 isave = interactive; 566 interactive = 0; 567 r->store.u.ival = yyparse(); 568 interactive = isave; 569 popio(); 570 r->op = OCONST; 571 r->type = TINT; 572 r->store.fmt = 'D'; 573 } 574 575 void 576 include(Node *r, Node *args) 577 { 578 char *file, *libfile; 579 static char buf[1024]; 580 Node res; 581 int isave; 582 583 if(args == 0) 584 error("include(string): arg count"); 585 expr(args, &res); 586 if(res.type != TSTRING) 587 error("include(string): arg type"); 588 589 Bflush(bout); 590 591 libfile = nil; 592 file = res.store.u.string->string; 593 if(access(file, AREAD) < 0 && file[0] != '/'){ 594 snprint(buf, sizeof buf, "#9/acid/%s", file); 595 libfile = unsharp(buf); 596 if(access(libfile, AREAD) >= 0){ 597 strecpy(buf, buf+sizeof buf, libfile); 598 file = buf; 599 } 600 free(libfile); 601 } 602 603 pushfile(file); 604 isave = interactive; 605 interactive = 0; 606 r->store.u.ival = yyparse(); 607 interactive = isave; 608 popio(); 609 r->op = OCONST; 610 r->type = TINT; 611 r->store.fmt = 'D'; 612 } 613 614 void 615 includepipe(Node *r, Node *args) 616 { 617 Node res; 618 int i, isave, pid, pip[2]; 619 char *argv[4]; 620 Waitmsg *w; 621 622 USED(r); 623 if(args == 0) 624 error("includepipe(string): arg count"); 625 expr(args, &res); 626 if(res.type != TSTRING) 627 error("includepipe(string): arg type"); 628 629 Bflush(bout); 630 631 argv[0] = "rc"; 632 argv[1] = "-c"; 633 argv[2] = res.store.u.string->string; 634 argv[3] = 0; 635 636 if(pipe(pip) < 0) 637 error("pipe: %r"); 638 639 pid = fork(); 640 switch(pid) { 641 case -1: 642 close(pip[0]); 643 close(pip[1]); 644 error("fork: %r"); 645 case 0: 646 close(pip[0]); 647 close(0); 648 open("/dev/null", OREAD); 649 dup(pip[1], 1); 650 if(pip[1] > 1) 651 close(pip[1]); 652 for(i=3; i<100; i++) 653 close(i); 654 exec("rc", argv); 655 sysfatal("exec rc: %r"); 656 } 657 658 close(pip[1]); 659 pushfd(pip[0]); 660 661 isave = interactive; 662 interactive = 0; 663 r->store.u.ival = yyparse(); 664 interactive = isave; 665 popio(); 666 667 r->op = OCONST; 668 r->type = TINT; 669 r->store.fmt = 'D'; 670 671 w = waitfor(pid); 672 if(w->msg && w->msg[0]) 673 error("includepipe(\"%s\"): %s", argv[2], w->msg); /* leaks w */ 674 free(w); 675 } 676 677 void 678 rc(Node *r, Node *args) 679 { 680 Node res; 681 int pid; 682 char *p, *q, *argv[4]; 683 Waitmsg *w; 684 685 USED(r); 686 if(args == 0) 687 error("rc(string): arg count"); 688 expr(args, &res); 689 if(res.type != TSTRING) 690 error("rc(string): arg type"); 691 692 argv[0] = "rc"; 693 argv[1] = "-c"; 694 argv[2] = res.store.u.string->string; 695 argv[3] = 0; 696 697 pid = fork(); 698 switch(pid) { 699 case -1: 700 error("fork %r"); 701 case 0: 702 exec("rc", argv); 703 exits(0); 704 default: 705 w = waitfor(pid); 706 break; 707 } 708 p = w->msg; 709 q = strrchr(p, ':'); 710 if (q) 711 p = q+1; 712 713 r->op = OCONST; 714 r->type = TSTRING; 715 r->store.u.string = strnode(p); 716 free(w); 717 r->store.fmt = 's'; 718 } 719 720 void 721 doerror(Node *r, Node *args) 722 { 723 Node res; 724 725 USED(r); 726 if(args == 0) 727 error("error(string): arg count"); 728 expr(args, &res); 729 if(res.type != TSTRING) 730 error("error(string): arg type"); 731 732 error(res.store.u.string->string); 733 } 734 735 void 736 doaccess(Node *r, Node *args) 737 { 738 Node res; 739 740 if(args == 0) 741 error("access(filename): arg count"); 742 expr(args, &res); 743 if(res.type != TSTRING) 744 error("access(filename): arg type"); 745 746 r->op = OCONST; 747 r->type = TINT; 748 r->store.fmt = 'D'; 749 r->store.u.ival = 0; 750 if(access(res.store.u.string->string, 4) == 0) 751 r->store.u.ival = 1; 752 } 753 754 void 755 readfile(Node *r, Node *args) 756 { 757 Node res; 758 int n, fd; 759 char *buf; 760 Dir *db; 761 762 if(args == 0) 763 error("readfile(filename): arg count"); 764 expr(args, &res); 765 if(res.type != TSTRING) 766 error("readfile(filename): arg type"); 767 768 fd = open(res.store.u.string->string, OREAD); 769 if(fd < 0) 770 return; 771 772 db = dirfstat(fd); 773 if(db == nil || db->length == 0) 774 n = 8192; 775 else 776 n = db->length; 777 free(db); 778 779 buf = malloc(n); 780 n = read(fd, buf, n); 781 782 if(n > 0) { 783 r->op = OCONST; 784 r->type = TSTRING; 785 r->store.u.string = strnodlen(buf, n); 786 r->store.fmt = 's'; 787 } 788 free(buf); 789 close(fd); 790 } 791 792 void 793 getfile(Node *r, Node *args) 794 { 795 int n; 796 char *p; 797 Node res; 798 String *s; 799 Biobuf *bp; 800 List **l, *new; 801 802 if(args == 0) 803 error("file(filename): arg count"); 804 expr(args, &res); 805 if(res.type != TSTRING) 806 error("file(filename): arg type"); 807 808 r->op = OCONST; 809 r->type = TLIST; 810 r->store.u.l = 0; 811 812 p = res.store.u.string->string; 813 bp = Bopen(p, OREAD); 814 if(bp == 0) 815 return; 816 817 l = &r->store.u.l; 818 for(;;) { 819 p = Brdline(bp, '\n'); 820 n = Blinelen(bp); 821 if(p == 0) { 822 if(n == 0) 823 break; 824 s = strnodlen(0, n); 825 Bread(bp, s->string, n); 826 } 827 else 828 s = strnodlen(p, n-1); 829 830 new = al(TSTRING); 831 new->store.u.string = s; 832 new->store.fmt = 's'; 833 *l = new; 834 l = &new->next; 835 } 836 Bterm(bp); 837 } 838 839 void 840 cvtatof(Node *r, Node *args) 841 { 842 Node res; 843 844 if(args == 0) 845 error("atof(string): arg count"); 846 expr(args, &res); 847 if(res.type != TSTRING) 848 error("atof(string): arg type"); 849 850 r->op = OCONST; 851 r->type = TFLOAT; 852 r->store.u.fval = atof(res.store.u.string->string); 853 r->store.fmt = 'f'; 854 } 855 856 void 857 cvtatoi(Node *r, Node *args) 858 { 859 Node res; 860 861 if(args == 0) 862 error("atoi(string): arg count"); 863 expr(args, &res); 864 if(res.type != TSTRING) 865 error("atoi(string): arg type"); 866 867 r->op = OCONST; 868 r->type = TINT; 869 r->store.u.ival = strtoull(res.store.u.string->string, 0, 0); 870 r->store.fmt = 'D'; 871 } 872 873 void 874 cvtitoa(Node *r, Node *args) 875 { 876 Node res; 877 Node *av[Maxarg]; 878 s64int ival; 879 char buf[128], *fmt; 880 881 if(args == 0) 882 err: 883 error("itoa(number [, printformat]): arg count"); 884 na = 0; 885 flatten(av, args); 886 if(na == 0 || na > 2) 887 goto err; 888 expr(av[0], &res); 889 if(res.type != TINT) 890 error("itoa(integer): arg type"); 891 ival = (int)res.store.u.ival; 892 fmt = "%d"; 893 if(na == 2){ 894 expr(av[1], &res); 895 if(res.type != TSTRING) 896 error("itoa(integer, string): arg type"); 897 fmt = res.store.u.string->string; 898 } 899 900 sprint(buf, fmt, ival); 901 r->op = OCONST; 902 r->type = TSTRING; 903 r->store.u.string = strnode(buf); 904 r->store.fmt = 's'; 905 } 906 907 List* 908 mapent(Map *m) 909 { 910 int i; 911 List *l, *n, **t, *h; 912 913 h = 0; 914 t = &h; 915 for(i = 0; i < m->nseg; i++) { 916 l = al(TSTRING); 917 n = al(TLIST); 918 n->store.u.l = l; 919 *t = n; 920 t = &n->next; 921 l->store.u.string = strnode(m->seg[i].name); 922 l->store.fmt = 's'; 923 l->next = al(TSTRING); 924 l = l->next; 925 l->store.u.string = strnode(m->seg[i].file ? m->seg[i].file : ""); 926 l->store.fmt = 's'; 927 l->next = al(TINT); 928 l = l->next; 929 l->store.u.ival = m->seg[i].base; 930 l->store.fmt = 'X'; 931 l->next = al(TINT); 932 l = l->next; 933 l->store.u.ival = m->seg[i].base + m->seg[i].size; 934 l->store.fmt = 'X'; 935 l->next = al(TINT); 936 l = l->next; 937 l->store.u.ival = m->seg[i].offset; 938 l->store.fmt = 'X'; 939 } 940 return h; 941 } 942 943 void 944 map(Node *r, Node *args) 945 { 946 int i; 947 Map *m; 948 List *l; 949 char *nam, *fil; 950 Node *av[Maxarg], res; 951 952 na = 0; 953 flatten(av, args); 954 955 if(na != 0) { 956 expr(av[0], &res); 957 if(res.type != TLIST) 958 error("map(list): map needs a list"); 959 if(listlen(res.store.u.l) != 5) 960 error("map(list): list must have 5 entries"); 961 962 l = res.store.u.l; 963 if(l->type != TSTRING) 964 error("map name must be a string"); 965 nam = l->store.u.string->string; 966 l = l->next; 967 if(l->type != TSTRING) 968 error("map file must be a string"); 969 fil = l->store.u.string->string; 970 m = symmap; 971 i = findseg(m, nam, fil); 972 if(i < 0) { 973 m = cormap; 974 i = findseg(m, nam, fil); 975 } 976 if(i < 0) 977 error("%s %s is not a map entry", nam, fil); 978 l = l->next; 979 if(l->type != TINT) 980 error("map entry not int"); 981 m->seg[i].base = l->store.u.ival; 982 /* 983 if (strcmp(ent, "text") == 0) 984 textseg(l->store.u.ival, &fhdr); 985 */ 986 l = l->next; 987 if(l->type != TINT) 988 error("map entry not int"); 989 m->seg[i].size = l->store.u.ival - m->seg[i].base; 990 l = l->next; 991 if(l->type != TINT) 992 error("map entry not int"); 993 m->seg[i].offset = l->store.u.ival; 994 } 995 996 r->type = TLIST; 997 r->store.u.l = 0; 998 if(symmap) 999 r->store.u.l = mapent(symmap); 1000 if(cormap) { 1001 if(r->store.u.l == 0) 1002 r->store.u.l = mapent(cormap); 1003 else { 1004 for(l = r->store.u.l; l->next; l = l->next) 1005 ; 1006 l->next = mapent(cormap); 1007 } 1008 } 1009 } 1010 1011 void 1012 flatten(Node **av, Node *n) 1013 { 1014 if(n == 0) 1015 return; 1016 1017 switch(n->op) { 1018 case OLIST: 1019 flatten(av, n->left); 1020 flatten(av, n->right); 1021 break; 1022 default: 1023 av[na++] = n; 1024 if(na >= Maxarg) 1025 error("too many function arguments"); 1026 break; 1027 } 1028 } 1029 1030 static struct 1031 { 1032 char *name; 1033 u64int val; 1034 } sregs[Maxarg/2]; 1035 static int nsregs; 1036 1037 static int 1038 straceregrw(Regs *regs, char *name, u64int *val, int isr) 1039 { 1040 int i; 1041 1042 if(!isr){ 1043 werrstr("saved registers cannot be written"); 1044 return -1; 1045 } 1046 for(i=0; i<nsregs; i++) 1047 if(strcmp(sregs[i].name, name) == 0){ 1048 *val = sregs[i].val; 1049 return 0; 1050 } 1051 return rget(acidregs, name, val); 1052 } 1053 1054 void 1055 strace(Node *r, Node *args) 1056 { 1057 Node *av[Maxarg], res; 1058 List *l; 1059 Regs regs; 1060 1061 na = 0; 1062 flatten(av, args); 1063 1064 if(na != 1) 1065 error("strace(list): want one arg"); 1066 1067 expr(av[0], &res); 1068 if(res.type != TLIST) 1069 error("strace(list): strace needs a list"); 1070 l = res.store.u.l; 1071 if(listlen(l)%2) 1072 error("strace(list): strace needs an even-length list"); 1073 for(nsregs=0; l; nsregs++){ 1074 if(l->type != TSTRING) 1075 error("strace({r,v,r,v,...}): non-string name"); 1076 sregs[nsregs].name = l->store.u.string->string; 1077 if(regdesc(sregs[nsregs].name) == nil) 1078 error("strace: bad register '%s'", sregs[nsregs].name); 1079 l = l->next; 1080 1081 if(l == nil) 1082 error("cannot happen in strace"); 1083 if(l->type != TINT) 1084 error("strace: non-int value for %s", sregs[nsregs].name); 1085 sregs[nsregs].val = l->store.u.ival; 1086 l = l->next; 1087 } 1088 regs.rw = straceregrw; 1089 1090 tracelist = 0; 1091 if(stacktrace(cormap, ®s, trlist) <= 0) 1092 error("no stack frame"); 1093 r->type = TLIST; 1094 r->store.u.l = tracelist; 1095 } 1096 1097 void 1098 regerror(char *msg) 1099 { 1100 error(msg); 1101 } 1102 1103 void 1104 regexp(Node *r, Node *args) 1105 { 1106 Node res; 1107 Reprog *rp; 1108 Node *av[Maxarg]; 1109 1110 na = 0; 1111 flatten(av, args); 1112 if(na != 2) 1113 error("regexp(pattern, string): arg count"); 1114 expr(av[0], &res); 1115 if(res.type != TSTRING) 1116 error("regexp(pattern, string): pattern must be string"); 1117 rp = regcomp(res.store.u.string->string); 1118 if(rp == 0) 1119 return; 1120 1121 expr(av[1], &res); 1122 if(res.type != TSTRING) 1123 error("regexp(pattern, string): bad string"); 1124 1125 r->store.fmt = 'D'; 1126 r->type = TINT; 1127 r->store.u.ival = regexec(rp, res.store.u.string->string, 0, 0); 1128 free(rp); 1129 } 1130 1131 char vfmt[] = "aBbcCdDfFgGiIoOqQrRsSuUVxXYZ"; 1132 1133 void 1134 fmt(Node *r, Node *args) 1135 { 1136 Node res; 1137 Node *av[Maxarg]; 1138 1139 na = 0; 1140 flatten(av, args); 1141 if(na != 2) 1142 error("fmt(obj, fmt): arg count"); 1143 expr(av[1], &res); 1144 if(res.type != TINT || strchr(vfmt, res.store.u.ival) == 0) 1145 error("fmt(obj, fmt): bad format '%c'", (char)res.store.u.ival); 1146 expr(av[0], r); 1147 r->store.fmt = res.store.u.ival; 1148 } 1149 1150 void 1151 patom(char type, Store *res) 1152 { 1153 int i; 1154 char buf[512]; 1155 extern char *typenames[]; 1156 Node *n; 1157 1158 switch(type){ 1159 case TREG: 1160 if(res->u.reg.thread) 1161 Bprint(bout, "register(\"%s\", %#ux)", res->u.reg.name, res->u.reg.thread); 1162 else 1163 Bprint(bout, "register(\"%s\")", res->u.reg.name); 1164 return; 1165 case TCON: 1166 Bprint(bout, "refconst("); 1167 n = res->u.con; 1168 patom(n->type, &n->store); 1169 Bprint(bout, ")"); 1170 return; 1171 } 1172 1173 switch(res->fmt){ 1174 case 'c': 1175 case 'C': 1176 case 'r': 1177 case 'B': 1178 case 'b': 1179 case 'X': 1180 case 'x': 1181 case 'W': 1182 case 'D': 1183 case 'd': 1184 case 'u': 1185 case 'U': 1186 case 'Z': 1187 case 'V': 1188 case 'Y': 1189 case 'o': 1190 case 'O': 1191 case 'q': 1192 case 'Q': 1193 case 'a': 1194 case 'A': 1195 case 'I': 1196 case 'i': 1197 if(type != TINT){ 1198 badtype: 1199 Bprint(bout, "*%s\\%c*", typenames[(uchar)type], res->fmt); 1200 return; 1201 } 1202 break; 1203 1204 case 'f': 1205 case 'F': 1206 if(type != TFLOAT) 1207 goto badtype; 1208 break; 1209 1210 case 's': 1211 case 'g': 1212 case 'G': 1213 case 'R': 1214 if(type != TSTRING) 1215 goto badtype; 1216 break; 1217 } 1218 1219 switch(res->fmt) { 1220 case 'c': 1221 Bprint(bout, "%c", (int)res->u.ival); 1222 break; 1223 case 'C': 1224 if(res->u.ival < ' ' || res->u.ival >= 0x7f) 1225 Bprint(bout, "%3d", (int)res->u.ival&0xff); 1226 else 1227 Bprint(bout, "%3c", (int)res->u.ival); 1228 break; 1229 case 'r': 1230 Bprint(bout, "%C", (int)res->u.ival); 1231 break; 1232 case 'B': 1233 memset(buf, '0', 34); 1234 buf[1] = 'b'; 1235 for(i = 0; i < 32; i++) { 1236 if(res->u.ival & (1<<i)) 1237 buf[33-i] = '1'; 1238 } 1239 buf[35] = '\0'; 1240 Bprint(bout, "%s", buf); 1241 break; 1242 case 'b': 1243 Bprint(bout, "%#.2x", (int)res->u.ival&0xff); 1244 break; 1245 case 'X': 1246 Bprint(bout, "%#.8lux", (ulong)res->u.ival); 1247 break; 1248 case 'x': 1249 Bprint(bout, "%#.4lux", (ulong)res->u.ival&0xffff); 1250 break; 1251 case 'W': 1252 Bprint(bout, "%#.16llux", res->u.ival); 1253 break; 1254 case 'D': 1255 Bprint(bout, "%d", (int)res->u.ival); 1256 break; 1257 case 'd': 1258 Bprint(bout, "%d", (ushort)res->u.ival); 1259 break; 1260 case 'u': 1261 Bprint(bout, "%d", (int)res->u.ival&0xffff); 1262 break; 1263 case 'U': 1264 Bprint(bout, "%lud", (ulong)res->u.ival); 1265 break; 1266 case 'Z': 1267 Bprint(bout, "%llud", res->u.ival); 1268 break; 1269 case 'V': 1270 Bprint(bout, "%lld", res->u.ival); 1271 break; 1272 case 'Y': 1273 Bprint(bout, "%#.16llux", res->u.ival); 1274 break; 1275 case 'o': 1276 Bprint(bout, "%#.11uo", (int)res->u.ival&0xffff); 1277 break; 1278 case 'O': 1279 Bprint(bout, "%#.6uo", (int)res->u.ival); 1280 break; 1281 case 'q': 1282 Bprint(bout, "%#.11o", (short)(res->u.ival&0xffff)); 1283 break; 1284 case 'Q': 1285 Bprint(bout, "%#.6o", (int)res->u.ival); 1286 break; 1287 case 'f': 1288 case 'F': 1289 Bprint(bout, "%g", res->u.fval); 1290 break; 1291 case 's': 1292 case 'g': 1293 case 'G': 1294 Bwrite(bout, res->u.string->string, res->u.string->len); 1295 break; 1296 case 'R': 1297 Bprint(bout, "%S", (Rune*)res->u.string->string); 1298 break; 1299 case 'a': 1300 case 'A': 1301 symoff(buf, sizeof(buf), res->u.ival, CANY); 1302 Bprint(bout, "%s", buf); 1303 break; 1304 case 'I': 1305 case 'i': 1306 if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0) 1307 Bprint(bout, "no instruction"); 1308 else 1309 Bprint(bout, "%s", buf); 1310 break; 1311 } 1312 } 1313 1314 void 1315 blprint(List *l) 1316 { 1317 Store *res; 1318 1319 Bprint(bout, "{"); 1320 while(l) { 1321 switch(l->type) { 1322 case TINT: 1323 res = &l->store; 1324 if(res->fmt == 'c'){ 1325 Bprint(bout, "\'%c\'", (int)res->u.ival); 1326 break; 1327 }else if(res->fmt == 'r'){ 1328 Bprint(bout, "\'%C\'", (int)res->u.ival); 1329 break; 1330 } 1331 /* fall through */ 1332 default: 1333 patom(l->type, &l->store); 1334 break; 1335 case TSTRING: 1336 Bputc(bout, '"'); 1337 patom(l->type, &l->store); 1338 Bputc(bout, '"'); 1339 break; 1340 case TLIST: 1341 blprint(l->store.u.l); 1342 break; 1343 case TCODE: 1344 pcode(l->store.u.cc, 0); 1345 break; 1346 } 1347 l = l->next; 1348 if(l) 1349 Bprint(bout, ", "); 1350 } 1351 Bprint(bout, "}"); 1352 } 1353 1354 int 1355 comx(Node res) 1356 { 1357 Lsym *sl; 1358 Node *n, xx; 1359 1360 if(res.store.fmt != 'a' && res.store.fmt != 'A') 1361 return 0; 1362 1363 if(res.store.comt == 0 || res.store.comt->base == 0) 1364 return 0; 1365 1366 sl = res.store.comt->base; 1367 if(sl->proc) { 1368 res.left = ZN; 1369 res.right = ZN; 1370 n = an(ONAME, ZN, ZN); 1371 n->sym = sl; 1372 n = an(OCALL, n, &res); 1373 n->left->sym = sl; 1374 expr(n, &xx); 1375 return 1; 1376 } 1377 print("(%s)", sl->name); 1378 return 0; 1379 } 1380 1381 void 1382 bprint(Node *r, Node *args) 1383 { 1384 int i, nas; 1385 Node res, *av[Maxarg]; 1386 1387 USED(r); 1388 na = 0; 1389 flatten(av, args); 1390 nas = na; 1391 for(i = 0; i < nas; i++) { 1392 expr(av[i], &res); 1393 switch(res.type) { 1394 default: 1395 if(comx(res)) 1396 break; 1397 patom(res.type, &res.store); 1398 break; 1399 case TCODE: 1400 pcode(res.store.u.cc, 0); 1401 break; 1402 case TLIST: 1403 blprint(res.store.u.l); 1404 break; 1405 } 1406 } 1407 if(ret == 0) 1408 Bputc(bout, '\n'); 1409 } 1410 1411 void 1412 printto(Node *r, Node *args) 1413 { 1414 int fd; 1415 Biobuf *b; 1416 int i, nas; 1417 Node res, *av[Maxarg]; 1418 1419 USED(r); 1420 na = 0; 1421 flatten(av, args); 1422 nas = na; 1423 1424 expr(av[0], &res); 1425 if(res.type != TSTRING) 1426 error("printto(string, ...): need string"); 1427 1428 fd = create(res.store.u.string->string, OWRITE, 0666); 1429 if(fd < 0) 1430 fd = open(res.store.u.string->string, OWRITE); 1431 if(fd < 0) 1432 error("printto: open %s: %r", res.store.u.string->string); 1433 1434 b = gmalloc(sizeof(Biobuf)); 1435 Binit(b, fd, OWRITE); 1436 1437 Bflush(bout); 1438 io[iop++] = bout; 1439 bout = b; 1440 1441 for(i = 1; i < nas; i++) { 1442 expr(av[i], &res); 1443 switch(res.type) { 1444 default: 1445 if(comx(res)) 1446 break; 1447 patom(res.type, &res.store); 1448 break; 1449 case TLIST: 1450 blprint(res.store.u.l); 1451 break; 1452 } 1453 } 1454 if(ret == 0) 1455 Bputc(bout, '\n'); 1456 1457 Bterm(b); 1458 close(fd); 1459 free(b); 1460 bout = io[--iop]; 1461 } 1462 1463 void 1464 pcfile(Node *r, Node *args) 1465 { 1466 Node res; 1467 char *p, buf[128]; 1468 1469 if(args == 0) 1470 error("pcfile(addr): arg count"); 1471 expr(args, &res); 1472 if(res.type != TINT) 1473 error("pcfile(addr): arg type"); 1474 1475 r->type = TSTRING; 1476 r->store.fmt = 's'; 1477 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) { 1478 r->store.u.string = strnode("?file?"); 1479 return; 1480 } 1481 p = strrchr(buf, ':'); 1482 if(p == 0) 1483 error("pcfile(addr): funny file %s", buf); 1484 *p = '\0'; 1485 r->store.u.string = strnode(buf); 1486 } 1487 1488 void 1489 pcline(Node *r, Node *args) 1490 { 1491 Node res; 1492 char *p, buf[128]; 1493 1494 if(args == 0) 1495 error("pcline(addr): arg count"); 1496 expr(args, &res); 1497 if(res.type != TINT) 1498 error("pcline(addr): arg type"); 1499 1500 r->type = TINT; 1501 r->store.fmt = 'D'; 1502 if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) { 1503 r->store.u.ival = 0; 1504 return; 1505 } 1506 1507 p = strrchr(buf, ':'); 1508 if(p == 0) 1509 error("pcline(addr): funny file %s", buf); 1510 r->store.u.ival = atoi(p+1); 1511 } 1512 1513 void 1514 textfile(Node *r, Node *args) 1515 { 1516 char *file; 1517 long base; 1518 Fhdr *fp; 1519 Node res, *av[Maxarg]; 1520 List *l, *l2, **tail, *list, *tl; 1521 1522 na = 0; 1523 flatten(av, args); 1524 1525 if(na != 0) { 1526 expr(av[0], &res); 1527 if(res.type != TLIST) 1528 error("textfile(list): textfile needs a list"); 1529 if(listlen(res.store.u.l) != 2) 1530 error("textfile(list): list must have 2 entries"); 1531 1532 l = res.store.u.l; 1533 if(l->type != TSTRING) 1534 error("textfile name must be a string"); 1535 file = l->store.u.string->string; 1536 1537 l = l->next; 1538 if(l->type != TINT) 1539 error("textfile base must be an int"); 1540 base = l->store.u.ival; 1541 1542 if((fp = crackhdr(file, OREAD)) == nil) 1543 error("crackhdr %s: %r", file); 1544 Bflush(bout); 1545 fp->base = base; 1546 fprint(2, "%s: %s %s %s\n", file, fp->aname, fp->mname, fp->fname); 1547 if(mapfile(fp, base, symmap, nil) < 0) 1548 fprint(2, "mapping %s: %r\n", file); 1549 if(corhdr){ 1550 unmapfile(corhdr, cormap); 1551 mapfile(fp, base, cormap, nil); 1552 free(correg); 1553 correg = nil; 1554 mapfile(corhdr, 0, cormap, &correg); 1555 } 1556 if(symopen(fp) < 0) 1557 fprint(2, "symopen %s: %r\n", file); 1558 else 1559 addvarsym(fp); 1560 return; 1561 } 1562 1563 l2 = nil; 1564 tail = &l2; 1565 for(fp=fhdrlist; fp; fp=fp->next){ 1566 if(fp->ftype == FCORE) 1567 continue; 1568 tl = al(TLIST); 1569 *tail = tl; 1570 tail = &tl->next; 1571 1572 list = al(TSTRING); 1573 tl->store.u.l = list; 1574 list->store.u.string = strnode(fp->filename); 1575 list->store.fmt = 's'; 1576 list->next = al(TINT); 1577 list = list->next; 1578 list->store.fmt = 'X'; 1579 list->store.u.ival = fp->base; 1580 } 1581 1582 r->type = TLIST; 1583 r->store.u.l = l2; 1584 } 1585 1586 void 1587 deltextfile(Node *r, Node *args) 1588 { 1589 int did; 1590 char *file; 1591 Fhdr *fp, *fpnext; 1592 Node res, *av[Maxarg]; 1593 1594 na = 0; 1595 flatten(av, args); 1596 1597 if(na != 1) 1598 error("deltextfile(string): arg count"); 1599 1600 expr(av[0], &res); 1601 if(res.type != TSTRING) 1602 error("deltextfile(string): arg type"); 1603 file = res.store.u.string->string; 1604 1605 did = 0; 1606 for(fp=fhdrlist; fp; fp=fpnext){ 1607 fpnext = fp->next; 1608 if(fp->ftype == FCORE) 1609 continue; 1610 if(strcmp(file, fp->filename) == 0){ 1611 did = 1; 1612 if(fp == symhdr) 1613 error("cannot remove symbols from main text file"); 1614 unmapfile(fp, symmap); 1615 uncrackhdr(fp); 1616 } 1617 } 1618 1619 delvarsym(file); 1620 if(!did) 1621 error("symbol file %s not open", file); 1622 } 1623 1624 void 1625 stringn(Node *r, Node *args) 1626 { 1627 uint addr; 1628 int i, n, ret; 1629 Node res, *av[Maxarg]; 1630 char *buf; 1631 1632 na = 0; 1633 flatten(av, args); 1634 if(na != 2) 1635 error("stringn(addr, n): arg count"); 1636 1637 expr(av[0], &res); 1638 if(res.type != TINT) 1639 error("stringn(addr, n): arg type"); 1640 addr = res.store.u.ival; 1641 1642 expr(av[1], &res); 1643 if(res.type != TINT) 1644 error("stringn(addr,n): arg type"); 1645 n = res.store.u.ival; 1646 1647 buf = malloc(n+1); 1648 if(buf == nil) 1649 error("out of memory"); 1650 1651 r->type = TSTRING; 1652 for(i=0; i<n; i++){ 1653 ret = get1(cormap, addr, (uchar*)&buf[i], 1); 1654 if(ret < 0){ 1655 free(buf); 1656 error("indir: %r"); 1657 } 1658 addr++; 1659 } 1660 buf[n] = 0; 1661 r->store.u.string = strnode(buf); 1662 free(buf); 1663 }