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