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
usage(void)28 usage(void)
29 {
30 diag("usage: %s [-options] objects", argv0);
31 errorexit();
32 }
33
34 static int
isobjfile(char * f)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
main(int argc,char * argv[])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
addlibpath(char * arg)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*
findlib(char * file)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
loadlib(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
errorexit(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
objfile(char * file)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
zaddr(uchar * p,Adr * a,Sym * h[])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
addlib(char * obj)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
addhist(long line,int type)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
histtoauto(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
collapsefrog(Sym * s)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
nopout(Prog * p)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*
readsome(int f,uchar * buf,uchar * good,uchar * stop,int max)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
ldobj(int f,long c,char * pn)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*
lookup(char * symb,int v)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*
prg(void)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*
copyp(Prog * q)1263 copyp(Prog *q)
1264 {
1265 Prog *p;
1266
1267 p = prg();
1268 *p = *q;
1269 return p;
1270 }
1271
1272 Prog*
appendp(Prog * q)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
gethunk(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
doprof1(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
doprof2(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
nuxiinit(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
find1(long l,int c)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
find2(long l,int c)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
ieeedtof(Ieee * e)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
ieeedtod(Ieee * ieeep)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
undefsym(Sym * s)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
zerosig(char * sp)1627 zerosig(char *sp)
1628 {
1629 Sym *s;
1630
1631 s = lookup(sp, 0);
1632 s->sig = 0;
1633 }
1634
1635 void
readundefs(char * f,int t)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