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