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