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