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