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