1 #define EXTERN 2 #include "l.h" 3 #include <ar.h> 4 5 #ifndef DEFAULT 6 #define DEFAULT '9' 7 #endif 8 9 char *noname = "<none>"; 10 char symname[] = SYMDEF; 11 char thechar = '6'; 12 char *thestring = "amd64"; 13 char *paramspace = "FP"; 14 15 char** libdir; 16 int nlibdir = 0; 17 static int maxlibdir = 0; 18 19 /* 20 * -H2 -T0x200028 -R0x200000 is plan9 format (was -T4136 -R4096) 21 * -H5 -T0x80110000 -R4096 is ELF32 22 * -H6 -T0x2000e8 -R0x200000 is ELF64 23 * 24 * options used: 189BLPQSVWabcjlnpsvz 25 */ 26 27 void 28 usage(void) 29 { 30 diag("usage: %s [-options] objects", argv0); 31 errorexit(); 32 } 33 34 static int 35 isobjfile(char *f) 36 { 37 int n, v; 38 Biobuf *b; 39 char buf1[5], buf2[SARMAG]; 40 41 b = Bopen(f, OREAD); 42 if(b == nil) 43 return 0; 44 n = Bread(b, buf1, 5); 45 if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<')) 46 v = 1; /* good enough for our purposes */ 47 else{ 48 Bseek(b, 0, 0); 49 n = Bread(b, buf2, SARMAG); 50 v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0; 51 } 52 Bterm(b); 53 return v; 54 } 55 56 void 57 main(int argc, char *argv[]) 58 { 59 int i, c; 60 char *a; 61 char name[LIBNAMELEN]; 62 63 Binit(&bso, 1, OWRITE); 64 cout = -1; 65 listinit(); 66 memset(debug, 0, sizeof(debug)); 67 nerrors = 0; 68 outfile = "6.out"; 69 HEADTYPE = -1; 70 INITTEXT = -1; 71 INITTEXTP = -1; 72 INITDAT = -1; 73 INITRND = -1; 74 INITENTRY = 0; 75 ARGBEGIN { 76 default: 77 c = ARGC(); 78 if(c >= 0 && c < sizeof(debug)) 79 debug[c]++; 80 break; 81 case 'o': /* output to (next arg) */ 82 outfile = ARGF(); 83 break; 84 case 'E': 85 a = ARGF(); 86 if(a) 87 INITENTRY = a; 88 break; 89 case 'H': 90 a = ARGF(); 91 if(a) 92 HEADTYPE = atolwhex(a); 93 break; 94 case 'L': 95 addlibpath(EARGF(usage())); 96 break; 97 case 'T': 98 a = ARGF(); 99 if(a) 100 INITTEXT = atolwhex(a); 101 break; 102 case 'P': 103 a = ARGF(); 104 if(a) 105 INITTEXTP = atolwhex(a); 106 break; 107 case 'D': 108 a = ARGF(); 109 if(a) 110 INITDAT = atolwhex(a); 111 break; 112 case 'R': 113 a = ARGF(); 114 if(a) 115 INITRND = atolwhex(a); 116 break; 117 case 'x': /* produce export table */ 118 doexp = 1; 119 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1])) 120 readundefs(ARGF(), SEXPORT); 121 break; 122 case 'u': /* produce dynamically loadable module */ 123 dlm = 1; 124 debug['l']++; 125 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1])) 126 readundefs(ARGF(), SIMPORT); 127 break; 128 } ARGEND 129 USED(argc); 130 if(*argv == 0) 131 usage(); 132 if(!debug['9'] && !debug['U'] && !debug['B']) 133 debug[DEFAULT] = 1; 134 a = getenv("ccroot"); 135 if(a != nil && *a != '\0') { 136 if(!fileexists(a)) { 137 diag("nonexistent $ccroot: %s", a); 138 errorexit(); 139 } 140 }else 141 a = ""; 142 snprint(name, sizeof(name), "%s/%s/lib", a, thestring); 143 addlibpath(name); 144 if(HEADTYPE == -1) { 145 if(debug['B']) 146 HEADTYPE = 2; 147 if(debug['9']) 148 HEADTYPE = 2; 149 } 150 switch(HEADTYPE) { 151 default: 152 diag("unknown -H option"); 153 errorexit(); 154 case 2: /* plan 9 */ 155 HEADR = 32L+8L; 156 if(INITTEXT == -1) 157 INITTEXT = 0x200000+HEADR; 158 if(INITDAT == -1) 159 INITDAT = 0; 160 if(INITRND == -1) 161 INITRND = 0x200000; 162 break; 163 case 5: /* elf32 executable */ 164 HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16); 165 if(INITTEXT == -1) 166 INITTEXT = 0xf0110000L; 167 if(INITDAT == -1) 168 INITDAT = 0; 169 if(INITRND == -1) 170 INITRND = 4096; 171 break; 172 case 6: /* ELF64 executable */ 173 HEADR = rnd(Ehdr64sz+3*Phdr64sz, 16); 174 if(INITTEXT == -1) 175 INITTEXT = 0x200000+HEADR; 176 if(INITDAT == -1) 177 INITDAT = 0; 178 if(INITRND == -1) 179 INITRND = 0x200000; 180 break; 181 } 182 if (INITTEXTP == -1) 183 INITTEXTP = INITTEXT; 184 if(INITDAT != 0 && INITRND != 0) 185 print("warning: -D0x%llux is ignored because of -R0x%lux\n", 186 INITDAT, INITRND); 187 if(debug['v']) 188 Bprint(&bso, "HEADER = -H%ld -T0x%llux -D0x%llux -R0x%lux\n", 189 HEADTYPE, INITTEXT, INITDAT, INITRND); 190 Bflush(&bso); 191 for(i=1; optab[i].as; i++) { 192 c = optab[i].as; 193 if(opindex[c] != nil) { 194 diag("phase error in optab: %d (%A)", i, c); 195 errorexit(); 196 } 197 opindex[c] = &optab[i]; 198 } 199 200 for(i=0; i<Ymax; i++) 201 ycover[i*Ymax + i] = 1; 202 203 ycover[Yi0*Ymax + Yi8] = 1; 204 ycover[Yi1*Ymax + Yi8] = 1; 205 206 ycover[Yi0*Ymax + Ys32] = 1; 207 ycover[Yi1*Ymax + Ys32] = 1; 208 ycover[Yi8*Ymax + Ys32] = 1; 209 210 ycover[Yi0*Ymax + Yi32] = 1; 211 ycover[Yi1*Ymax + Yi32] = 1; 212 ycover[Yi8*Ymax + Yi32] = 1; 213 ycover[Ys32*Ymax + Yi32] = 1; 214 215 ycover[Yi0*Ymax + Yi64] = 1; 216 ycover[Yi1*Ymax + Yi64] = 1; 217 ycover[Yi8*Ymax + Yi64] = 1; 218 ycover[Ys32*Ymax + Yi64] = 1; 219 ycover[Yi32*Ymax + Yi64] = 1; 220 221 ycover[Yal*Ymax + Yrb] = 1; 222 ycover[Ycl*Ymax + Yrb] = 1; 223 ycover[Yax*Ymax + Yrb] = 1; 224 ycover[Ycx*Ymax + Yrb] = 1; 225 ycover[Yrx*Ymax + Yrb] = 1; 226 ycover[Yrl*Ymax + Yrb] = 1; 227 228 ycover[Ycl*Ymax + Ycx] = 1; 229 230 ycover[Yax*Ymax + Yrx] = 1; 231 ycover[Ycx*Ymax + Yrx] = 1; 232 233 ycover[Yax*Ymax + Yrl] = 1; 234 ycover[Ycx*Ymax + Yrl] = 1; 235 ycover[Yrx*Ymax + Yrl] = 1; 236 237 ycover[Yf0*Ymax + Yrf] = 1; 238 239 ycover[Yal*Ymax + Ymb] = 1; 240 ycover[Ycl*Ymax + Ymb] = 1; 241 ycover[Yax*Ymax + Ymb] = 1; 242 ycover[Ycx*Ymax + Ymb] = 1; 243 ycover[Yrx*Ymax + Ymb] = 1; 244 ycover[Yrb*Ymax + Ymb] = 1; 245 ycover[Yrl*Ymax + Ymb] = 1; 246 ycover[Ym*Ymax + Ymb] = 1; 247 248 ycover[Yax*Ymax + Yml] = 1; 249 ycover[Ycx*Ymax + Yml] = 1; 250 ycover[Yrx*Ymax + Yml] = 1; 251 ycover[Yrl*Ymax + Yml] = 1; 252 ycover[Ym*Ymax + Yml] = 1; 253 254 ycover[Yax*Ymax + Ymm] = 1; 255 ycover[Ycx*Ymax + Ymm] = 1; 256 ycover[Yrx*Ymax + Ymm] = 1; 257 ycover[Yrl*Ymax + Ymm] = 1; 258 ycover[Ym*Ymax + Ymm] = 1; 259 ycover[Ymr*Ymax + Ymm] = 1; 260 261 ycover[Yax*Ymax + Yxm] = 1; 262 ycover[Ycx*Ymax + Yxm] = 1; 263 ycover[Yrx*Ymax + Yxm] = 1; 264 ycover[Yrl*Ymax + Yxm] = 1; 265 ycover[Ym*Ymax + Yxm] = 1; 266 ycover[Yxr*Ymax + Yxm] = 1; 267 268 for(i=0; i<D_NONE; i++) { 269 reg[i] = -1; 270 if(i >= D_AL && i <= D_R15B) { 271 reg[i] = (i-D_AL) & 7; 272 if(i >= D_SPB && i <= D_DIB) 273 regrex[i] = 0x40; 274 if(i >= D_R8B && i <= D_R15B) 275 regrex[i] = Rxr | Rxx | Rxb; 276 } 277 if(i >= D_AH && i<= D_BH) 278 reg[i] = 4 + ((i-D_AH) & 7); 279 if(i >= D_AX && i <= D_R15) { 280 reg[i] = (i-D_AX) & 7; 281 if(i >= D_R8) 282 regrex[i] = Rxr | Rxx | Rxb; 283 } 284 if(i >= D_F0 && i <= D_F0+7) 285 reg[i] = (i-D_F0) & 7; 286 if(i >= D_M0 && i <= D_M0+7) 287 reg[i] = (i-D_M0) & 7; 288 if(i >= D_X0 && i <= D_X0+15) { 289 reg[i] = (i-D_X0) & 7; 290 if(i >= D_X0+8) 291 regrex[i] = Rxr | Rxx | Rxb; 292 } 293 if(i >= D_CR+8 && i <= D_CR+15) 294 regrex[i] = Rxr; 295 } 296 297 zprg.link = P; 298 zprg.pcond = P; 299 zprg.back = 2; 300 zprg.as = AGOK; 301 zprg.from.type = D_NONE; 302 zprg.from.index = D_NONE; 303 zprg.from.scale = 1; 304 zprg.to = zprg.from; 305 zprg.mode = 64; 306 307 pcstr = "%.6llux "; 308 nuxiinit(); 309 histgen = 0; 310 textp = P; 311 datap = P; 312 edatap = P; 313 pc = 0; 314 dtype = 4; 315 cout = create(outfile, 1, 0775); 316 if(cout < 0) { 317 diag("cannot create %s: %r", outfile); 318 errorexit(); 319 } 320 version = 0; 321 cbp = buf.cbuf; 322 cbc = sizeof(buf.cbuf); 323 firstp = prg(); 324 lastp = firstp; 325 326 if(INITENTRY == 0) { 327 INITENTRY = "_main"; 328 if(debug['p']) 329 INITENTRY = "_mainp"; 330 if(!debug['l']) 331 lookup(INITENTRY, 0)->type = SXREF; 332 } else if(!(*INITENTRY >= '0' && *INITENTRY <= '9')) 333 lookup(INITENTRY, 0)->type = SXREF; 334 335 while(*argv) 336 objfile(*argv++); 337 if(!debug['l']) 338 loadlib(); 339 firstp = firstp->link; 340 if(firstp == P) 341 errorexit(); 342 if(doexp || dlm){ 343 EXPTAB = "_exporttab"; 344 zerosig(EXPTAB); 345 zerosig("etext"); 346 zerosig("edata"); 347 zerosig("end"); 348 if(dlm){ 349 import(); 350 HEADTYPE = 2; 351 INITTEXT = 0; 352 INITDAT = 0; 353 INITRND = 8; 354 INITENTRY = EXPTAB; 355 } 356 export(); 357 } 358 patch(); 359 follow(); 360 dodata(); 361 dostkoff(); 362 paramspace = "SP"; /* (FP) now (SP) on output */ 363 if(debug['p']) 364 if(debug['1']) 365 doprof1(); 366 else 367 doprof2(); 368 span(); 369 doinit(); 370 asmb(); 371 undef(); 372 if(debug['v']) { 373 Bprint(&bso, "%5.2f cpu time\n", cputime()); 374 Bprint(&bso, "%ld symbols\n", nsymbol); 375 Bprint(&bso, "%ld memory used\n", thunk); 376 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 377 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 378 } 379 Bflush(&bso); 380 381 errorexit(); 382 } 383 384 void 385 addlibpath(char *arg) 386 { 387 char **p; 388 389 if(nlibdir >= maxlibdir) { 390 if(maxlibdir == 0) 391 maxlibdir = 8; 392 else 393 maxlibdir *= 2; 394 p = malloc(maxlibdir*sizeof(*p)); 395 if(p == nil) { 396 diag("out of memory"); 397 errorexit(); 398 } 399 memmove(p, libdir, nlibdir*sizeof(*p)); 400 free(libdir); 401 libdir = p; 402 } 403 libdir[nlibdir++] = strdup(arg); 404 } 405 406 char* 407 findlib(char *file) 408 { 409 int i; 410 char name[LIBNAMELEN]; 411 412 for(i = 0; i < nlibdir; i++) { 413 snprint(name, sizeof(name), "%s/%s", libdir[i], file); 414 if(fileexists(name)) 415 return libdir[i]; 416 } 417 return nil; 418 } 419 420 void 421 loadlib(void) 422 { 423 int i; 424 long h; 425 Sym *s; 426 427 loop: 428 xrefresolv = 0; 429 for(i=0; i<libraryp; i++) { 430 if(debug['v']) 431 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]); 432 objfile(library[i]); 433 } 434 if(xrefresolv) 435 for(h=0; h<nelem(hash); h++) 436 for(s = hash[h]; s != S; s = s->link) 437 if(s->type == SXREF) 438 goto loop; 439 } 440 441 void 442 errorexit(void) 443 { 444 445 if(nerrors) { 446 if(cout >= 0) 447 remove(outfile); 448 exits("error"); 449 } 450 exits(0); 451 } 452 453 void 454 objfile(char *file) 455 { 456 long off, esym, cnt, l; 457 int f, work; 458 Sym *s; 459 char magbuf[SARMAG]; 460 char name[LIBNAMELEN], pname[LIBNAMELEN]; 461 struct ar_hdr arhdr; 462 char *e, *start, *stop; 463 464 if(debug['v']) 465 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); 466 Bflush(&bso); 467 if(file[0] == '-' && file[1] == 'l') { 468 snprint(pname, sizeof(pname), "lib%s.a", file+2); 469 e = findlib(pname); 470 if(e == nil) { 471 diag("cannot find library: %s", file); 472 errorexit(); 473 } 474 snprint(name, sizeof(name), "%s/%s", e, pname); 475 file = name; 476 } 477 f = open(file, 0); 478 if(f < 0) { 479 diag("cannot open %s: %r", file); 480 errorexit(); 481 } 482 l = read(f, magbuf, SARMAG); 483 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ 484 /* load it as a regular file */ 485 l = seek(f, 0L, 2); 486 seek(f, 0L, 0); 487 ldobj(f, l, file); 488 close(f); 489 return; 490 } 491 492 l = read(f, &arhdr, SAR_HDR); 493 if(l != SAR_HDR) { 494 diag("%s: short read on archive file symbol header", file); 495 goto out; 496 } 497 if(strncmp(arhdr.name, symname, strlen(symname))) { 498 diag("%s: first entry not symbol header", file); 499 goto out; 500 } 501 502 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size); 503 off = SARMAG + SAR_HDR; 504 505 /* 506 * just bang the whole symbol file into memory 507 */ 508 seek(f, off, 0); 509 cnt = esym - off; 510 start = malloc(cnt + 10); 511 cnt = read(f, start, cnt); 512 if(cnt <= 0){ 513 close(f); 514 return; 515 } 516 stop = &start[cnt]; 517 memset(stop, 0, 10); 518 519 work = 1; 520 while(work) { 521 if(debug['v']) 522 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file); 523 Bflush(&bso); 524 work = 0; 525 for(e = start; e < stop; e = strchr(e+5, 0) + 1) { 526 s = lookup(e+5, 0); 527 if(s->type != SXREF) 528 continue; 529 sprint(pname, "%s(%s)", file, s->name); 530 if(debug['v']) 531 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname); 532 Bflush(&bso); 533 l = e[1] & 0xff; 534 l |= (e[2] & 0xff) << 8; 535 l |= (e[3] & 0xff) << 16; 536 l |= (e[4] & 0xff) << 24; 537 seek(f, l, 0); 538 /* need readn to read the dumps (at least) */ 539 l = readn(f, &arhdr, SAR_HDR); 540 if(l != SAR_HDR) 541 goto bad; 542 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) 543 goto bad; 544 l = atolwhex(arhdr.size); 545 ldobj(f, l, pname); 546 if(s->type == SXREF) { 547 diag("%s: failed to load: %s", file, s->name); 548 errorexit(); 549 } 550 work = 1; 551 xrefresolv = 1; 552 } 553 } 554 return; 555 556 bad: 557 diag("%s: bad or out of date archive", file); 558 out: 559 close(f); 560 } 561 562 int 563 zaddr(uchar *p, Adr *a, Sym *h[]) 564 { 565 int c, t, i; 566 int l; 567 Sym *s; 568 Auto *u; 569 570 t = p[0]; 571 c = 1; 572 if(t & T_INDEX) { 573 a->index = p[c]; 574 a->scale = p[c+1]; 575 c += 2; 576 } else { 577 a->index = D_NONE; 578 a->scale = 0; 579 } 580 a->offset = 0; 581 if(t & T_OFFSET) { 582 /* 583 * Hack until Charles fixes the compiler. 584 a->offset = (long)(p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24)); 585 */ 586 l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); 587 a->offset = l; 588 c += 4; 589 if(t & T_64) { 590 l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); 591 a->offset = ((vlong)l<<32) | (a->offset & 0xFFFFFFFFUL); 592 c += 4; 593 } 594 } 595 a->sym = S; 596 if(t & T_SYM) { 597 a->sym = h[p[c]]; 598 c++; 599 } 600 a->type = D_NONE; 601 if(t & T_FCONST) { 602 a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); 603 a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24); 604 c += 8; 605 a->type = D_FCONST; 606 } else 607 if(t & T_SCONST) { 608 for(i=0; i<NSNAME; i++) 609 a->scon[i] = p[c+i]; 610 c += NSNAME; 611 a->type = D_SCONST; 612 } 613 if(t & T_TYPE) { 614 a->type = p[c]; 615 c++; 616 } 617 s = a->sym; 618 if(s == S) 619 return c; 620 621 t = a->type; 622 if(t != D_AUTO && t != D_PARAM) 623 return c; 624 l = a->offset; 625 for(u=curauto; u; u=u->link) { 626 if(u->asym == s) 627 if(u->type == t) { 628 if(u->aoffset > l) 629 u->aoffset = l; 630 return c; 631 } 632 } 633 634 while(nhunk < sizeof(Auto)) 635 gethunk(); 636 u = (Auto*)hunk; 637 nhunk -= sizeof(Auto); 638 hunk += sizeof(Auto); 639 640 u->link = curauto; 641 curauto = u; 642 u->asym = s; 643 u->aoffset = l; 644 u->type = t; 645 return c; 646 } 647 648 void 649 addlib(char *obj) 650 { 651 char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name; 652 int i, search; 653 654 if(histfrogp <= 0) 655 return; 656 657 name = fn1; 658 search = 0; 659 if(histfrog[0]->name[1] == '/') { 660 sprint(name, ""); 661 i = 1; 662 } else if(histfrog[0]->name[1] == '.') { 663 sprint(name, "."); 664 i = 0; 665 } else { 666 sprint(name, ""); 667 i = 0; 668 search = 1; 669 } 670 671 for(; i<histfrogp; i++) { 672 snprint(comp, sizeof comp, histfrog[i]->name+1); 673 for(;;) { 674 p = strstr(comp, "$O"); 675 if(p == 0) 676 break; 677 memmove(p+1, p+2, strlen(p+2)+1); 678 p[0] = thechar; 679 } 680 for(;;) { 681 p = strstr(comp, "$M"); 682 if(p == 0) 683 break; 684 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) { 685 diag("library component too long"); 686 return; 687 } 688 memmove(p+strlen(thestring), p+2, strlen(p+2)+1); 689 memmove(p, thestring, strlen(thestring)); 690 } 691 if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) { 692 diag("library component too long"); 693 return; 694 } 695 if(i > 0 || !search) 696 strcat(fn1, "/"); 697 strcat(fn1, comp); 698 } 699 700 cleanname(name); 701 702 if(search){ 703 p = findlib(name); 704 if(p != nil){ 705 snprint(fn2, sizeof(fn2), "%s/%s", p, name); 706 name = fn2; 707 } 708 } 709 710 for(i=0; i<libraryp; i++) 711 if(strcmp(name, library[i]) == 0) 712 return; 713 if(libraryp == nelem(library)){ 714 diag("too many autolibs; skipping %s", name); 715 return; 716 } 717 718 p = malloc(strlen(name) + 1); 719 strcpy(p, name); 720 library[libraryp] = p; 721 p = malloc(strlen(obj) + 1); 722 strcpy(p, obj); 723 libraryobj[libraryp] = p; 724 libraryp++; 725 } 726 727 void 728 addhist(long line, int type) 729 { 730 Auto *u; 731 Sym *s; 732 int i, j, k; 733 734 u = malloc(sizeof(Auto)); 735 s = malloc(sizeof(Sym)); 736 s->name = malloc(2*(histfrogp+1) + 1); 737 738 u->asym = s; 739 u->type = type; 740 u->aoffset = line; 741 u->link = curhist; 742 curhist = u; 743 744 j = 1; 745 for(i=0; i<histfrogp; i++) { 746 k = histfrog[i]->value; 747 s->name[j+0] = k>>8; 748 s->name[j+1] = k; 749 j += 2; 750 } 751 } 752 753 void 754 histtoauto(void) 755 { 756 Auto *l; 757 758 while(l = curhist) { 759 curhist = l->link; 760 l->link = curauto; 761 curauto = l; 762 } 763 } 764 765 void 766 collapsefrog(Sym *s) 767 { 768 int i; 769 770 /* 771 * bad encoding of path components only allows 772 * MAXHIST components. if there is an overflow, 773 * first try to collapse xxx/.. 774 */ 775 for(i=1; i<histfrogp; i++) 776 if(strcmp(histfrog[i]->name+1, "..") == 0) { 777 memmove(histfrog+i-1, histfrog+i+1, 778 (histfrogp-i-1)*sizeof(histfrog[0])); 779 histfrogp--; 780 goto out; 781 } 782 783 /* 784 * next try to collapse . 785 */ 786 for(i=0; i<histfrogp; i++) 787 if(strcmp(histfrog[i]->name+1, ".") == 0) { 788 memmove(histfrog+i, histfrog+i+1, 789 (histfrogp-i-1)*sizeof(histfrog[0])); 790 goto out; 791 } 792 793 /* 794 * last chance, just truncate from front 795 */ 796 memmove(histfrog+0, histfrog+1, 797 (histfrogp-1)*sizeof(histfrog[0])); 798 799 out: 800 histfrog[histfrogp-1] = s; 801 } 802 803 void 804 nopout(Prog *p) 805 { 806 p->as = ANOP; 807 p->from.type = D_NONE; 808 p->to.type = D_NONE; 809 } 810 811 uchar* 812 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) 813 { 814 int n; 815 816 n = stop - good; 817 memmove(buf, good, stop - good); 818 stop = buf + n; 819 n = MAXIO - n; 820 if(n > max) 821 n = max; 822 n = read(f, stop, n); 823 if(n <= 0) 824 return 0; 825 return stop + n; 826 } 827 828 void 829 ldobj(int f, long c, char *pn) 830 { 831 vlong ipc; 832 Prog *p, *t; 833 uchar *bloc, *bsize, *stop; 834 int v, o, r, skip, mode; 835 Sym *h[NSYM], *s, *di; 836 ulong sig; 837 static int files; 838 static char **filen; 839 char **nfilen; 840 841 if((files&15) == 0){ 842 nfilen = malloc((files+16)*sizeof(char*)); 843 memmove(nfilen, filen, files*sizeof(char*)); 844 free(filen); 845 filen = nfilen; 846 } 847 filen[files++] = strdup(pn); 848 849 bsize = buf.xbuf; 850 bloc = buf.xbuf; 851 di = S; 852 853 newloop: 854 memset(h, 0, sizeof(h)); 855 version++; 856 histfrogp = 0; 857 ipc = pc; 858 skip = 0; 859 mode = 64; 860 861 loop: 862 if(c <= 0) 863 goto eof; 864 r = bsize - bloc; 865 if(r < 100 && r < c) { /* enough for largest prog */ 866 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 867 if(bsize == 0) 868 goto eof; 869 bloc = buf.xbuf; 870 goto loop; 871 } 872 o = bloc[0] | (bloc[1] << 8); 873 if(o <= AXXX || o >= ALAST) { 874 if(o < 0) 875 goto eof; 876 diag("%s: opcode out of range %d", pn, o); 877 print(" probably not a .6 file\n"); 878 errorexit(); 879 } 880 881 if(o == ANAME || o == ASIGNAME) { 882 sig = 0; 883 if(o == ASIGNAME) { 884 sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); 885 bloc += 4; 886 c -= 4; 887 } 888 stop = memchr(&bloc[4], 0, bsize-&bloc[4]); 889 if(stop == 0){ 890 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 891 if(bsize == 0) 892 goto eof; 893 bloc = buf.xbuf; 894 stop = memchr(&bloc[4], 0, bsize-&bloc[4]); 895 if(stop == 0){ 896 fprint(2, "%s: name too long\n", pn); 897 errorexit(); 898 } 899 } 900 v = bloc[2]; /* type */ 901 o = bloc[3]; /* sym */ 902 bloc += 4; 903 c -= 4; 904 905 r = 0; 906 if(v == D_STATIC) 907 r = version; 908 s = lookup((char*)bloc, r); 909 c -= &stop[1] - bloc; 910 bloc = stop + 1; 911 912 if(debug['S'] && r == 0) 913 sig = 1729; 914 if(sig != 0){ 915 if(s->sig != 0 && s->sig != sig) 916 diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name); 917 s->sig = sig; 918 s->file = files-1; 919 } 920 921 if(debug['W']) 922 print(" ANAME %s\n", s->name); 923 h[o] = s; 924 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 925 s->type = SXREF; 926 if(v == D_FILE) { 927 if(s->type != SFILE) { 928 histgen++; 929 s->type = SFILE; 930 s->value = histgen; 931 } 932 if(histfrogp < MAXHIST) { 933 histfrog[histfrogp] = s; 934 histfrogp++; 935 } else 936 collapsefrog(s); 937 } 938 goto loop; 939 } 940 941 while(nhunk < sizeof(Prog)) 942 gethunk(); 943 p = (Prog*)hunk; 944 nhunk -= sizeof(Prog); 945 hunk += sizeof(Prog); 946 947 p->as = o; 948 p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24); 949 p->back = 2; 950 p->mode = mode; 951 r = zaddr(bloc+6, &p->from, h) + 6; 952 r += zaddr(bloc+r, &p->to, h); 953 bloc += r; 954 c -= r; 955 956 if(debug['W']) 957 print("%P\n", p); 958 959 switch(p->as) { 960 case AHISTORY: 961 if(p->to.offset == -1) { 962 addlib(pn); 963 histfrogp = 0; 964 goto loop; 965 } 966 addhist(p->line, D_FILE); /* 'z' */ 967 if(p->to.offset) 968 addhist(p->to.offset, D_FILE1); /* 'Z' */ 969 histfrogp = 0; 970 goto loop; 971 972 case AEND: 973 histtoauto(); 974 if(curtext != P) 975 curtext->to.autom = curauto; 976 curauto = 0; 977 curtext = P; 978 if(c) 979 goto newloop; 980 return; 981 982 case AGLOBL: 983 s = p->from.sym; 984 if(s->type == 0 || s->type == SXREF) { 985 s->type = SBSS; 986 s->value = 0; 987 } 988 if(s->type != SBSS) { 989 diag("%s: redefinition: %s in %s", 990 pn, s->name, TNAME); 991 s->type = SBSS; 992 s->value = 0; 993 } 994 if(p->to.offset > s->value) 995 s->value = p->to.offset; 996 goto loop; 997 998 case ADYNT: 999 if(p->to.sym == S) { 1000 diag("DYNT without a sym\n%P", p); 1001 break; 1002 } 1003 di = p->to.sym; 1004 p->from.scale = 4; 1005 if(di->type == SXREF) { 1006 if(debug['z']) 1007 Bprint(&bso, "%P set to %d\n", p, dtype); 1008 di->type = SCONST; 1009 di->value = dtype; 1010 dtype += 4; 1011 } 1012 if(p->from.sym == S) 1013 break; 1014 1015 p->from.offset = di->value; 1016 p->from.sym->type = SDATA; 1017 if(curtext == P) { 1018 diag("DYNT not in text: %P", p); 1019 break; 1020 } 1021 p->to.sym = curtext->from.sym; 1022 p->to.type = D_ADDR; 1023 p->to.index = D_EXTERN; 1024 goto data; 1025 1026 case AINIT: 1027 if(p->from.sym == S) { 1028 diag("INIT without a sym\n%P", p); 1029 break; 1030 } 1031 if(di == S) { 1032 diag("INIT without previous DYNT\n%P", p); 1033 break; 1034 } 1035 p->from.offset = di->value; 1036 p->from.sym->type = SDATA; 1037 goto data; 1038 1039 case ADATA: 1040 data: 1041 if(edatap == P) 1042 datap = p; 1043 else 1044 edatap->link = p; 1045 edatap = p; 1046 p->link = P; 1047 goto loop; 1048 1049 case AGOK: 1050 diag("%s: GOK opcode in %s", pn, TNAME); 1051 pc++; 1052 goto loop; 1053 1054 case ATEXT: 1055 if(curtext != P) { 1056 histtoauto(); 1057 curtext->to.autom = curauto; 1058 curauto = 0; 1059 } 1060 skip = 0; 1061 curtext = p; 1062 s = p->from.sym; 1063 if(s == S) { 1064 diag("%s: no TEXT symbol: %P", pn, p); 1065 errorexit(); 1066 } 1067 if(s->type != 0 && s->type != SXREF) { 1068 if(p->from.scale & DUPOK) { 1069 skip = 1; 1070 goto casdef; 1071 } 1072 diag("%s: redefinition: %s\n%P", pn, s->name, p); 1073 } 1074 s->type = STEXT; 1075 s->value = pc; 1076 lastp->link = p; 1077 lastp = p; 1078 p->pc = pc; 1079 pc++; 1080 if(textp == P) { 1081 textp = p; 1082 etextp = p; 1083 goto loop; 1084 } 1085 etextp->pcond = p; 1086 etextp = p; 1087 goto loop; 1088 1089 case AMODE: 1090 if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){ 1091 switch((int)p->from.offset){ 1092 case 16: case 32: case 64: 1093 mode = p->from.offset; 1094 break; 1095 } 1096 } 1097 goto loop; 1098 1099 case AFMOVF: 1100 case AFADDF: 1101 case AFSUBF: 1102 case AFSUBRF: 1103 case AFMULF: 1104 case AFDIVF: 1105 case AFDIVRF: 1106 case AFCOMF: 1107 case AFCOMFP: 1108 case AMOVSS: 1109 case AADDSS: 1110 case ASUBSS: 1111 case AMULSS: 1112 case ADIVSS: 1113 case ACOMISS: 1114 case AUCOMISS: 1115 if(skip) 1116 goto casdef; 1117 if(p->from.type == D_FCONST) { 1118 /* size sb 9 max */ 1119 sprint(literal, "$%lux", ieeedtof(&p->from.ieee)); 1120 s = lookup(literal, 0); 1121 if(s->type == 0) { 1122 s->type = SBSS; 1123 s->value = 4; 1124 t = prg(); 1125 t->as = ADATA; 1126 t->line = p->line; 1127 t->from.type = D_EXTERN; 1128 t->from.sym = s; 1129 t->from.scale = 4; 1130 t->to = p->from; 1131 if(edatap == P) 1132 datap = t; 1133 else 1134 edatap->link = t; 1135 edatap = t; 1136 t->link = P; 1137 } 1138 p->from.type = D_EXTERN; 1139 p->from.sym = s; 1140 p->from.offset = 0; 1141 } 1142 goto casdef; 1143 1144 case AFMOVD: 1145 case AFADDD: 1146 case AFSUBD: 1147 case AFSUBRD: 1148 case AFMULD: 1149 case AFDIVD: 1150 case AFDIVRD: 1151 case AFCOMD: 1152 case AFCOMDP: 1153 case AMOVSD: 1154 case AADDSD: 1155 case ASUBSD: 1156 case AMULSD: 1157 case ADIVSD: 1158 case ACOMISD: 1159 case AUCOMISD: 1160 if(skip) 1161 goto casdef; 1162 if(p->from.type == D_FCONST) { 1163 /* size sb 18 max */ 1164 sprint(literal, "$%lux.%lux", 1165 p->from.ieee.l, p->from.ieee.h); 1166 s = lookup(literal, 0); 1167 if(s->type == 0) { 1168 s->type = SBSS; 1169 s->value = 8; 1170 t = prg(); 1171 t->as = ADATA; 1172 t->line = p->line; 1173 t->from.type = D_EXTERN; 1174 t->from.sym = s; 1175 t->from.scale = 8; 1176 t->to = p->from; 1177 if(edatap == P) 1178 datap = t; 1179 else 1180 edatap->link = t; 1181 edatap = t; 1182 t->link = P; 1183 } 1184 p->from.type = D_EXTERN; 1185 p->from.sym = s; 1186 p->from.offset = 0; 1187 } 1188 goto casdef; 1189 1190 casdef: 1191 default: 1192 if(skip) 1193 nopout(p); 1194 1195 if(p->to.type == D_BRANCH) 1196 p->to.offset += ipc; 1197 lastp->link = p; 1198 lastp = p; 1199 p->pc = pc; 1200 pc++; 1201 goto loop; 1202 } 1203 goto loop; 1204 1205 eof: 1206 diag("truncated object file: %s", pn); 1207 } 1208 1209 Sym* 1210 lookup(char *symb, int v) 1211 { 1212 Sym *s; 1213 char *p; 1214 long h; 1215 int l, c; 1216 1217 h = v; 1218 for(p=symb; c = *p; p++) 1219 h = h+h+h + c; 1220 l = (p - symb) + 1; 1221 h &= 0xffffff; 1222 h %= NHASH; 1223 for(s = hash[h]; s != S; s = s->link) 1224 if(s->version == v) 1225 if(memcmp(s->name, symb, l) == 0) 1226 return s; 1227 1228 while(nhunk < sizeof(Sym)) 1229 gethunk(); 1230 s = (Sym*)hunk; 1231 nhunk -= sizeof(Sym); 1232 hunk += sizeof(Sym); 1233 1234 s->name = malloc(l + 1); 1235 memmove(s->name, symb, l); 1236 1237 s->link = hash[h]; 1238 s->type = 0; 1239 s->version = v; 1240 s->value = 0; 1241 s->sig = 0; 1242 hash[h] = s; 1243 nsymbol++; 1244 return s; 1245 } 1246 1247 Prog* 1248 prg(void) 1249 { 1250 Prog *p; 1251 1252 while(nhunk < sizeof(Prog)) 1253 gethunk(); 1254 p = (Prog*)hunk; 1255 nhunk -= sizeof(Prog); 1256 hunk += sizeof(Prog); 1257 1258 *p = zprg; 1259 return p; 1260 } 1261 1262 Prog* 1263 copyp(Prog *q) 1264 { 1265 Prog *p; 1266 1267 p = prg(); 1268 *p = *q; 1269 return p; 1270 } 1271 1272 Prog* 1273 appendp(Prog *q) 1274 { 1275 Prog *p; 1276 1277 p = prg(); 1278 p->link = q->link; 1279 q->link = p; 1280 p->line = q->line; 1281 p->mode = q->mode; 1282 return p; 1283 } 1284 1285 void 1286 gethunk(void) 1287 { 1288 char *h; 1289 long nh; 1290 1291 nh = NHUNK; 1292 if(thunk >= 5L*NHUNK) { 1293 nh = 5L*NHUNK; 1294 if(thunk >= 25L*NHUNK) 1295 nh = 25L*NHUNK; 1296 } 1297 h = mysbrk(nh); 1298 if(h == (char*)-1) { 1299 diag("out of memory"); 1300 errorexit(); 1301 } 1302 hunk = h; 1303 nhunk = nh; 1304 thunk += nh; 1305 } 1306 1307 void 1308 doprof1(void) 1309 { 1310 Sym *s; 1311 long n; 1312 Prog *p, *q; 1313 1314 if(debug['v']) 1315 Bprint(&bso, "%5.2f profile 1\n", cputime()); 1316 Bflush(&bso); 1317 s = lookup("__mcount", 0); 1318 n = 1; 1319 for(p = firstp->link; p != P; p = p->link) { 1320 if(p->as == ATEXT) { 1321 q = prg(); 1322 q->line = p->line; 1323 q->link = datap; 1324 datap = q; 1325 q->as = ADATA; 1326 q->from.type = D_EXTERN; 1327 q->from.offset = n*4; 1328 q->from.sym = s; 1329 q->from.scale = 4; 1330 q->to = p->from; 1331 q->to.type = D_CONST; 1332 1333 q = prg(); 1334 q->line = p->line; 1335 q->pc = p->pc; 1336 q->link = p->link; 1337 p->link = q; 1338 p = q; 1339 p->as = AADDL; 1340 p->from.type = D_CONST; 1341 p->from.offset = 1; 1342 p->to.type = D_EXTERN; 1343 p->to.sym = s; 1344 p->to.offset = n*4 + 4; 1345 1346 n += 2; 1347 continue; 1348 } 1349 } 1350 q = prg(); 1351 q->line = 0; 1352 q->link = datap; 1353 datap = q; 1354 1355 q->as = ADATA; 1356 q->from.type = D_EXTERN; 1357 q->from.sym = s; 1358 q->from.scale = 4; 1359 q->to.type = D_CONST; 1360 q->to.offset = n; 1361 1362 s->type = SBSS; 1363 s->value = n*4; 1364 } 1365 1366 void 1367 doprof2(void) 1368 { 1369 Sym *s2, *s4; 1370 Prog *p, *q, *q2, *ps2, *ps4; 1371 1372 if(debug['v']) 1373 Bprint(&bso, "%5.2f profile 2\n", cputime()); 1374 Bflush(&bso); 1375 1376 if(debug['e']){ 1377 s2 = lookup("_tracein", 0); 1378 s4 = lookup("_traceout", 0); 1379 }else{ 1380 s2 = lookup("_profin", 0); 1381 s4 = lookup("_profout", 0); 1382 } 1383 if(s2->type != STEXT || s4->type != STEXT) { 1384 if(debug['e']) 1385 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type); 1386 else 1387 diag("_profin/_profout not defined"); 1388 return; 1389 } 1390 1391 ps2 = P; 1392 ps4 = P; 1393 for(p = firstp; p != P; p = p->link) { 1394 if(p->as == ATEXT) { 1395 if(p->from.sym == s2) { 1396 p->from.scale = 1; 1397 ps2 = p; 1398 } 1399 if(p->from.sym == s4) { 1400 p->from.scale = 1; 1401 ps4 = p; 1402 } 1403 } 1404 } 1405 for(p = firstp; p != P; p = p->link) { 1406 if(p->as == ATEXT) { 1407 curtext = p; 1408 1409 if(p->from.scale & NOPROF) { /* dont profile */ 1410 for(;;) { 1411 q = p->link; 1412 if(q == P) 1413 break; 1414 if(q->as == ATEXT) 1415 break; 1416 p = q; 1417 } 1418 continue; 1419 } 1420 1421 /* 1422 * JMPL profin 1423 */ 1424 q = prg(); 1425 q->line = p->line; 1426 q->pc = p->pc; 1427 q->link = p->link; 1428 if(debug['e']){ /* embedded tracing */ 1429 q2 = prg(); 1430 p->link = q2; 1431 q2->link = q; 1432 1433 q2->line = p->line; 1434 q2->pc = p->pc; 1435 1436 q2->as = AJMP; 1437 q2->to.type = D_BRANCH; 1438 q2->to.sym = p->to.sym; 1439 q2->pcond = q->link; 1440 }else 1441 p->link = q; 1442 p = q; 1443 p->as = ACALL; 1444 p->to.type = D_BRANCH; 1445 p->pcond = ps2; 1446 p->to.sym = s2; 1447 1448 continue; 1449 } 1450 if(p->as == ARET) { 1451 /* 1452 * RET (default) 1453 */ 1454 if(debug['e']){ /* embedded tracing */ 1455 q = prg(); 1456 q->line = p->line; 1457 q->pc = p->pc; 1458 q->link = p->link; 1459 p->link = q; 1460 p = q; 1461 } 1462 /* 1463 * RET 1464 */ 1465 q = prg(); 1466 q->as = ARET; 1467 q->from = p->from; 1468 q->to = p->to; 1469 q->link = p->link; 1470 p->link = q; 1471 1472 /* 1473 * JAL profout 1474 */ 1475 p->as = ACALL; 1476 p->from = zprg.from; 1477 p->to = zprg.to; 1478 p->to.type = D_BRANCH; 1479 p->pcond = ps4; 1480 p->to.sym = s4; 1481 1482 p = q; 1483 1484 continue; 1485 } 1486 } 1487 } 1488 1489 void 1490 nuxiinit(void) 1491 { 1492 int i, c; 1493 1494 for(i=0; i<4; i++) { 1495 c = find1(0x04030201L, i+1); 1496 if(i < 2) 1497 inuxi2[i] = c; 1498 if(i < 1) 1499 inuxi1[i] = c; 1500 inuxi4[i] = c; 1501 inuxi8[i] = c; 1502 inuxi8[i+4] = c+4; 1503 fnuxi4[i] = c; 1504 fnuxi8[i] = c; 1505 fnuxi8[i+4] = c+4; 1506 } 1507 if(debug['v']) { 1508 Bprint(&bso, "inuxi = "); 1509 for(i=0; i<1; i++) 1510 Bprint(&bso, "%d", inuxi1[i]); 1511 Bprint(&bso, " "); 1512 for(i=0; i<2; i++) 1513 Bprint(&bso, "%d", inuxi2[i]); 1514 Bprint(&bso, " "); 1515 for(i=0; i<4; i++) 1516 Bprint(&bso, "%d", inuxi4[i]); 1517 Bprint(&bso, " "); 1518 for(i=0; i<8; i++) 1519 Bprint(&bso, "%d", inuxi8[i]); 1520 Bprint(&bso, "\nfnuxi = "); 1521 for(i=0; i<4; i++) 1522 Bprint(&bso, "%d", fnuxi4[i]); 1523 Bprint(&bso, " "); 1524 for(i=0; i<8; i++) 1525 Bprint(&bso, "%d", fnuxi8[i]); 1526 Bprint(&bso, "\n"); 1527 } 1528 Bflush(&bso); 1529 } 1530 1531 int 1532 find1(long l, int c) 1533 { 1534 char *p; 1535 int i; 1536 1537 p = (char*)&l; 1538 for(i=0; i<4; i++) 1539 if(*p++ == c) 1540 return i; 1541 return 0; 1542 } 1543 1544 int 1545 find2(long l, int c) 1546 { 1547 short *p; 1548 int i; 1549 1550 p = (short*)&l; 1551 for(i=0; i<4; i+=2) { 1552 if(((*p >> 8) & 0xff) == c) 1553 return i; 1554 if((*p++ & 0xff) == c) 1555 return i+1; 1556 } 1557 return 0; 1558 } 1559 1560 long 1561 ieeedtof(Ieee *e) 1562 { 1563 int exp; 1564 long v; 1565 1566 if(e->h == 0) 1567 return 0; 1568 exp = (e->h>>20) & ((1L<<11)-1L); 1569 exp -= (1L<<10) - 2L; 1570 v = (e->h & 0xfffffL) << 3; 1571 v |= (e->l >> 29) & 0x7L; 1572 if((e->l >> 28) & 1) { 1573 v++; 1574 if(v & 0x800000L) { 1575 v = (v & 0x7fffffL) >> 1; 1576 exp++; 1577 } 1578 } 1579 if(exp <= -126 || exp >= 130) 1580 diag("double fp to single fp overflow"); 1581 v |= ((exp + 126) & 0xffL) << 23; 1582 v |= e->h & 0x80000000L; 1583 return v; 1584 } 1585 1586 double 1587 ieeedtod(Ieee *ieeep) 1588 { 1589 Ieee e; 1590 double fr; 1591 int exp; 1592 1593 if(ieeep->h & (1L<<31)) { 1594 e.h = ieeep->h & ~(1L<<31); 1595 e.l = ieeep->l; 1596 return -ieeedtod(&e); 1597 } 1598 if(ieeep->l == 0 && ieeep->h == 0) 1599 return 0; 1600 fr = ieeep->l & ((1L<<16)-1L); 1601 fr /= 1L<<16; 1602 fr += (ieeep->l>>16) & ((1L<<16)-1L); 1603 fr /= 1L<<16; 1604 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20); 1605 fr /= 1L<<21; 1606 exp = (ieeep->h>>20) & ((1L<<11)-1L); 1607 exp -= (1L<<10) - 2L; 1608 return ldexp(fr, exp); 1609 } 1610 1611 void 1612 undefsym(Sym *s) 1613 { 1614 int n; 1615 1616 n = imports; 1617 if(s->value != 0) 1618 diag("value != 0 on SXREF"); 1619 if(n >= 1<<Rindex) 1620 diag("import index %d out of range", n); 1621 s->value = n<<Roffset; 1622 s->type = SUNDEF; 1623 imports++; 1624 } 1625 1626 void 1627 zerosig(char *sp) 1628 { 1629 Sym *s; 1630 1631 s = lookup(sp, 0); 1632 s->sig = 0; 1633 } 1634 1635 void 1636 readundefs(char *f, int t) 1637 { 1638 int i, n; 1639 Sym *s; 1640 Biobuf *b; 1641 char *l, buf[256], *fields[64]; 1642 1643 if(f == nil) 1644 return; 1645 b = Bopen(f, OREAD); 1646 if(b == nil){ 1647 diag("could not open %s: %r", f); 1648 errorexit(); 1649 } 1650 while((l = Brdline(b, '\n')) != nil){ 1651 n = Blinelen(b); 1652 if(n >= sizeof(buf)){ 1653 diag("%s: line too long", f); 1654 errorexit(); 1655 } 1656 memmove(buf, l, n); 1657 buf[n-1] = '\0'; 1658 n = getfields(buf, fields, nelem(fields), 1, " \t\r\n"); 1659 if(n == nelem(fields)){ 1660 diag("%s: bad format", f); 1661 errorexit(); 1662 } 1663 for(i = 0; i < n; i++){ 1664 s = lookup(fields[i], 0); 1665 s->type = SXREF; 1666 s->subtype = t; 1667 if(t == SIMPORT) 1668 nimports++; 1669 else 1670 nexports++; 1671 } 1672 } 1673 Bterm(b); 1674 } 1675