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