changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/7l/obj.c

changeset 4275: d1102fefd6c1
parent: eaccc3e8d226
author: cinap_lenrek@felloff.net
date: Tue, 17 Feb 2015 22:13:35 +0100
permissions: -rw-r--r--
description: [125678kqv][cl]: fix sprint() and strcpy() buffer overflows
1 #include "l.h"
2 #include <ar.h>
3 
4 #ifndef DEFAULT
5 #define DEFAULT '9'
6 #endif
7 
8 char *noname = "<none>";
9 char symname[] = SYMDEF;
10 char thechar = '7';
11 char *thestring = "alpha";
12 
13 /*
14  * -H0 -T0x12000004C -D0x140000000 is abbrev unix
15  * -H1 -T0x20000000 -R4 is bootp() format
16  * -H2 -T8224 -R8192 is plan9 format
17  */
18 
19 void
20 main(int argc, char *argv[])
21 {
22  int c;
23  char *a;
24 
25  Binit(&bso, 1, OWRITE);
26  cout = -1;
27  listinit();
28  outfile = 0;
29  nerrors = 0;
30  curtext = P;
31  HEADTYPE = -1;
32  INITTEXT = -1;
33  INITDAT = -1;
34  INITRND = -1;
35  INITENTRY = 0;
36 
37  ARGBEGIN {
38  default:
39  c = ARGC();
40  if(c >= 0 && c < sizeof(debug))
41  debug[c]++;
42  break;
43  case 'o':
44  outfile = ARGF();
45  break;
46  case 'E':
47  a = ARGF();
48  if(a)
49  INITENTRY = a;
50  break;
51  case 'T':
52  a = ARGF();
53  if(a)
54  INITTEXT = atolwhex(a);
55  break;
56  case 'D':
57  a = ARGF();
58  if(a)
59  INITDAT = atolwhex(a);
60  break;
61  case 'R':
62  a = ARGF();
63  if(a)
64  INITRND = atolwhex(a);
65  break;
66  case 'H':
67  a = ARGF();
68  if(a)
69  HEADTYPE = atolwhex(a);
70  /* do something about setting INITTEXT */
71  break;
72  } ARGEND
73 
74  USED(argc);
75 
76  if(*argv == 0) {
77  diag("usage: 7l [-options] objects");
78  errorexit();
79  }
80  if(!debug['9'] && !debug['B'] && !debug['U'])
81  debug[DEFAULT] = 1;
82  if(HEADTYPE == -1) {
83  if(debug['U'])
84  HEADTYPE = 0;
85  if(debug['B'])
86  HEADTYPE = 1;
87  if(debug['9'])
88  HEADTYPE = 2;
89  }
90  switch(HEADTYPE) {
91  default:
92  diag("unknown -H option");
93  errorexit();
94 
95  case 0: /* unix simple */
96  HEADR = 32L+80L;
97  if(INITTEXT == -1)
98  INITTEXT = 0x120000070LL; /* BUG */
99  if(INITDAT == -1)
100  INITDAT = 0x140000000LL; /* BUG */
101  if(INITRND == -1)
102  INITRND = 0;
103  break;
104 
105  case 1: /* boot */
106  HEADR = 32L+84L;
107  if(INITTEXT == -1)
108  INITTEXT = 0x20000074L;
109  if(INITDAT == -1)
110  INITDAT = 0;
111  if(INITRND == -1)
112  INITRND = 8;
113  break;
114  case 2: /* plan 9 */
115  HEADR = 32L;
116  if(INITTEXT == -1)
117  INITTEXT = 8224;
118  if(INITDAT == -1)
119  INITDAT = 0;
120  if(INITRND == -1)
121  INITRND = 8192;
122  break;
123  case 3: /* ``headerless'' tftp boot -- uses branch as magic */
124  HEADR = 32L;
125  if(INITTEXT == -1)
126  INITTEXT = 0x20000020L;
127  if(INITDAT == -1)
128  INITDAT = 0;
129  if(INITRND == -1)
130  INITRND = 8;
131  break;
132  }
133  if(INITDAT != 0 && INITRND != 0)
134  print("warning: -D0x%lux is ignored because of -R0x%lux\n",
135  INITDAT, INITRND);
136  if(debug['v'])
137  Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
138  HEADTYPE, INITTEXT, INITDAT, INITRND);
139  Bflush(&bso);
140  zprg.as = AGOK;
141  zprg.reg = NREG;
142  zprg.from.name = D_NONE;
143  zprg.from.type = D_NONE;
144  zprg.from.reg = NREG;
145  zprg.to = zprg.from;
146  buildop();
147  histgen = 0;
148  textp = P;
149  datap = P;
150  pc = 0;
151  dtype = 4;
152  if(outfile == 0)
153  outfile = "7.out";
154  cout = create(outfile, 1, 0775);
155  if(cout < 0) {
156  diag("%s: cannot create", outfile);
157  errorexit();
158  }
159  nuxiinit();
160 
161  version = 0;
162  cbp = buf.cbuf;
163  cbc = sizeof(buf.cbuf);
164  firstp = prg();
165  lastp = firstp;
166 
167  if(INITENTRY == 0) {
168  INITENTRY = "_main";
169  if(debug['p'])
170  INITENTRY = "_mainp";
171  if(!debug['l'])
172  lookup(INITENTRY, 0)->type = SXREF;
173  } else
174  lookup(INITENTRY, 0)->type = SXREF;
175 
176  while(*argv)
177  objfile(*argv++);
178  if(!debug['l'])
179  loadlib();
180  firstp = firstp->link;
181  if(firstp == P)
182  goto out;
183  patch();
184  if(debug['p'])
185  if(debug['1'])
186  doprof1();
187  else
188  doprof2();
189  follow();
190  if(firstp == P)
191  goto out;
192  noops();
193  dodata(); /* is before follow() on other arch */
194  span();
195  asmb();
196  undef();
197 
198 out:
199  if(debug['v']) {
200  Bprint(&bso, "%5.2f cpu time\n", cputime());
201  Bprint(&bso, "%ld memory used\n", thunk);
202  Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
203  Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
204  }
205  Bflush(&bso);
206  errorexit();
207 }
208 
209 void
210 loadlib(void)
211 {
212  int i;
213  long h;
214  Sym *s;
215 
216 loop:
217  xrefresolv = 0;
218  for(i=0; i<libraryp; i++) {
219  if(debug['v'])
220  Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
221  objfile(library[i]);
222  }
223  if(xrefresolv)
224  for(h=0; h<nelem(hash); h++)
225  for(s = hash[h]; s != S; s = s->link)
226  if(s->type == SXREF)
227  goto loop;
228 }
229 
230 void
231 errorexit(void)
232 {
233 
234  Bflush(&bso);
235  if(nerrors) {
236  if(cout >= 0)
237  remove(outfile);
238  exits("error");
239  }
240  exits(0);
241 }
242 
243 void
244 objfile(char *file)
245 {
246  long off, esym, cnt, l;
247  int f, work;
248  Sym *s;
249  char magbuf[SARMAG];
250  char name[100], pname[150];
251  struct ar_hdr arhdr;
252  char *e, *start, *stop;
253 
254  if(file[0] == '-' && file[1] == 'l') {
255  if(debug['9'])
256  snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
257  else
258  snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
259  file = name;
260  }
261  if(debug['v'])
262  Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
263  Bflush(&bso);
264  f = open(file, 0);
265  if(f < 0) {
266  diag("cannot open file: %s", file);
267  errorexit();
268  }
269  l = read(f, magbuf, SARMAG);
270  if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
271  /* load it as a regular file */
272  l = seek(f, 0L, 2);
273  seek(f, 0L, 0);
274  ldobj(f, l, file);
275  close(f);
276  return;
277  }
278 
279  if(debug['v'])
280  Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
281  l = read(f, &arhdr, SAR_HDR);
282  if(l != SAR_HDR) {
283  diag("%s: short read on archive file symbol header", file);
284  goto out;
285  }
286  if(strncmp(arhdr.name, symname, strlen(symname))) {
287  diag("%s: first entry not symbol header", file);
288  goto out;
289  }
290 
291  esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
292  off = SARMAG + SAR_HDR;
293 
294  /*
295  * just bang the whole symbol file into memory
296  */
297  seek(f, off, 0);
298  cnt = esym - off;
299  start = malloc(cnt + 10);
300  cnt = read(f, start, cnt);
301  if(cnt <= 0){
302  close(f);
303  return;
304  }
305  stop = &start[cnt];
306  memset(stop, 0, 10);
307 
308  work = 1;
309  while(work){
310  if(debug['v'])
311  Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
312  Bflush(&bso);
313  work = 0;
314  for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
315  s = lookup(e+5, 0);
316  if(s->type != SXREF)
317  continue;
318  snprint(pname, sizeof pname, "%s(%s)", file, s->name);
319  if(debug['v'])
320  Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
321  Bflush(&bso);
322  l = e[1] & 0xff;
323  l |= (e[2] & 0xff) << 8;
324  l |= (e[3] & 0xff) << 16;
325  l |= (e[4] & 0xff) << 24;
326  seek(f, l, 0);
327  l = read(f, &arhdr, SAR_HDR);
328  if(l != SAR_HDR)
329  goto bad;
330  if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
331  goto bad;
332  l = atolwhex(arhdr.size);
333  ldobj(f, l, pname);
334  if(s->type == SXREF) {
335  diag("%s: failed to load: %s", file, s->name);
336  errorexit();
337  }
338  work = 1;
339  xrefresolv = 1;
340  }
341  }
342  return;
343 
344 bad:
345  diag("%s: bad or out of date archive", file);
346 out:
347  close(f);
348 }
349 
350 int
351 zaddr(uchar *p, Adr *a, Sym *h[])
352 {
353  int i, c;
354  vlong l;
355  Sym *s;
356  Auto *u;
357 
358  c = p[2];
359  if(c < 0 || c > NSYM){
360  print("sym out of range: %d\n", c);
361  p[0] = ALAST+1;
362  return 0;
363  }
364  a->type = p[0];
365  a->reg = p[1];
366  a->sym = h[p[2]];
367  a->name = p[3];
368  c = 4;
369 
370  if(a->reg < 0 || a->reg > NREG) {
371  print("register out of range %d\n", a->reg);
372  p[0] = ALAST+1;
373  return 0; /* force real diagnostic */
374  }
375 
376  switch(a->type) {
377  default:
378  print("unknown type %d\n", a->type);
379  p[0] = ALAST+1;
380  return 0; /* force real diagnostic */
381 
382  case D_NONE:
383  case D_REG:
384  case D_FREG:
385  case D_PREG:
386  case D_FCREG:
387  case D_PCC:
388  break;
389 
390  case D_BRANCH:
391  case D_OREG:
392  case D_CONST:
393  a->offset = (uvlong)p[4] | ((uvlong)p[5]<<8L) |
394  ((uvlong) p[6]<<16L) | ((uvlong) p[7]<<24L) |
395  ((uvlong) p[8]<<32L) | ((uvlong) p[9]<<40L) |
396  ((uvlong) p[10]<<48L) | ((uvlong) p[11]<<56L);
397  c += 8;
398  break;
399 
400  case D_SCONST:
401  while(nhunk < NSNAME)
402  gethunk();
403  a->sval = (char*)hunk;
404  nhunk -= NSNAME;
405  hunk += NSNAME;
406 
407  memmove(a->sval, p+4, NSNAME);
408  c += NSNAME;
409  break;
410 
411  case D_FCONST:
412  while(nhunk < sizeof(Ieee))
413  gethunk();
414  a->ieee = (Ieee*)hunk;
415  nhunk -= sizeof(Ieee);
416  hunk += sizeof(Ieee);
417 
418  a->ieee->l = p[4] | (p[5]<<8) |
419  (p[6]<<16) | (p[7]<<24);
420  a->ieee->h = p[8] | (p[9]<<8) |
421  (p[10]<<16) | (p[11]<<24);
422  c += 8;
423  break;
424  }
425  s = a->sym;
426  if(s == S)
427  return c;
428  i = a->name;
429  if(i != D_AUTO && i != D_PARAM)
430  return c;
431 
432  l = a->offset;
433  for(u=curauto; u; u=u->link)
434  if(u->sym == s)
435  if(u->type == i) {
436  if(u->offset > l)
437  u->offset = l;
438  return c;
439  }
440 
441  while(nhunk < sizeof(Auto))
442  gethunk();
443  u = (Auto*)hunk;
444  nhunk -= sizeof(Auto);
445  hunk += sizeof(Auto);
446 
447  u->link = curauto;
448  curauto = u;
449  u->sym = s;
450  u->offset = l;
451  u->type = i;
452  return c;
453 }
454 
455 void
456 addlib(char *obj)
457 {
458  char name[1024], comp[256], *p;
459  int i;
460 
461  if(histfrogp <= 0)
462  return;
463 
464  if(histfrog[0]->name[1] == '/') {
465  name[0] = 0;
466  i = 1;
467  } else
468  if(histfrog[0]->name[1] == '.') {
469  snprint(name, sizeof name, ".");
470  i = 0;
471  } else {
472  if(debug['9'])
473  snprint(name, sizeof name, "/%s/lib", thestring);
474  else
475  snprint(name, sizeof name, "/usr/%clib", thechar);
476  i = 0;
477  }
478 
479  for(; i<histfrogp; i++) {
480  snprint(comp, sizeof comp, histfrog[i]->name+1);
481  for(;;) {
482  p = strstr(comp, "$O");
483  if(p == 0)
484  break;
485  memmove(p+1, p+2, strlen(p+2)+1);
486  p[0] = thechar;
487  }
488  for(;;) {
489  p = strstr(comp, "$M");
490  if(p == 0)
491  break;
492  if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
493  diag("library component too long");
494  return;
495  }
496  memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
497  memmove(p, thestring, strlen(thestring));
498  }
499  if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
500  diag("library component too long");
501  return;
502  }
503  strcat(name, "/");
504  strcat(name, comp);
505  }
506  for(i=0; i<libraryp; i++)
507  if(strcmp(name, library[i]) == 0)
508  return;
509  if(libraryp == nelem(library)){
510  diag("too many autolibs; skipping %s", name);
511  return;
512  }
513 
514  p = malloc(strlen(name) + 1);
515  strcpy(p, name);
516  library[libraryp] = p;
517  p = malloc(strlen(obj) + 1);
518  strcpy(p, obj);
519  libraryobj[libraryp] = p;
520  libraryp++;
521 }
522 
523 void
524 addhist(long line, int type)
525 {
526  Auto *u;
527  Sym *s;
528  int i, j, k;
529 
530  u = malloc(sizeof(Auto));
531  s = malloc(sizeof(Sym));
532  s->name = malloc(2*(histfrogp+1) + 1);
533 
534  u->sym = s;
535  u->type = type;
536  u->offset = line;
537  u->link = curhist;
538  curhist = u;
539 
540  j = 1;
541  for(i=0; i<histfrogp; i++) {
542  k = histfrog[i]->value;
543  s->name[j+0] = k>>8;
544  s->name[j+1] = k;
545  j += 2;
546  }
547 }
548 
549 void
550 histtoauto(void)
551 {
552  Auto *l;
553 
554  while(l = curhist) {
555  curhist = l->link;
556  l->link = curauto;
557  curauto = l;
558  }
559 }
560 
561 void
562 collapsefrog(Sym *s)
563 {
564  int i;
565 
566  /*
567  * bad encoding of path components only allows
568  * MAXHIST components. if there is an overflow,
569  * first try to collapse xxx/..
570  */
571  for(i=1; i<histfrogp; i++)
572  if(strcmp(histfrog[i]->name+1, "..") == 0) {
573  memmove(histfrog+i-1, histfrog+i+1,
574  (histfrogp-i-1)*sizeof(histfrog[0]));
575  histfrogp--;
576  goto out;
577  }
578 
579  /*
580  * next try to collapse .
581  */
582  for(i=0; i<histfrogp; i++)
583  if(strcmp(histfrog[i]->name+1, ".") == 0) {
584  memmove(histfrog+i, histfrog+i+1,
585  (histfrogp-i-1)*sizeof(histfrog[0]));
586  goto out;
587  }
588 
589  /*
590  * last chance, just truncate from front
591  */
592  memmove(histfrog+0, histfrog+1,
593  (histfrogp-1)*sizeof(histfrog[0]));
594 
595 out:
596  histfrog[histfrogp-1] = s;
597 }
598 
599 void
600 nopout(Prog *p)
601 {
602  p->as = ANOP;
603  p->from.type = D_NONE;
604  p->to.type = D_NONE;
605 }
606 
607 uchar*
608 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
609 {
610  int n;
611 
612  n = stop - good;
613  memmove(buf, good, stop - good);
614  stop = buf + n;
615  n = MAXIO - n;
616  if(n > max)
617  n = max;
618  n = read(f, stop, n);
619  if(n <= 0)
620  return 0;
621  return stop + n;
622 }
623 
624 void
625 ldobj(int f, long c, char *pn)
626 {
627  long ipc;
628  Prog *p, *t;
629  uchar *bloc, *bsize, *stop;
630  Sym *h[NSYM], *s, *di;
631  int v, o, r, skip;
632 
633  bsize = buf.xbuf;
634  bloc = buf.xbuf;
635  di = S;
636 
637 newloop:
638  memset(h, 0, sizeof(h));
639  version++;
640  histfrogp = 0;
641  ipc = pc;
642  skip = 0;
643 
644 loop:
645  if(c <= 0)
646  goto eof;
647  r = bsize - bloc;
648  if(r < 100 && r < c) { /* enough for largest prog */
649  bsize = readsome(f, buf.xbuf, bloc, bsize, c);
650  if(bsize == 0)
651  goto eof;
652  bloc = buf.xbuf;
653  goto loop;
654  }
655  o = bloc[0]; /* as */
656  if(o <= AXXX || o >= ALAST) {
657  diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
658  print(" probably not a .7 file\n");
659  errorexit();
660  }
661  if(o == ANAME) {
662  stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
663  if(stop == 0){
664  bsize = readsome(f, buf.xbuf, bloc, bsize, c);
665  if(bsize == 0)
666  goto eof;
667  bloc = buf.xbuf;
668  stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
669  if(stop == 0){
670  fprint(2, "%s: name too long\n", pn);
671  errorexit();
672  }
673  }
674  v = bloc[1]; /* type */
675  o = bloc[2]; /* sym */
676  bloc += 3;
677  c -= 3;
678 
679  r = 0;
680  if(v == D_STATIC)
681  r = version;
682  s = lookup((char*)bloc, r);
683  c -= &stop[1] - bloc;
684  bloc = stop + 1;
685 
686  if(debug['W'])
687  print(" ANAME %s\n", s->name);
688  h[o] = s;
689  if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
690  s->type = SXREF;
691  if(v == D_FILE) {
692  if(s->type != SFILE) {
693  histgen++;
694  s->type = SFILE;
695  s->value = histgen;
696  }
697  if(histfrogp < MAXHIST) {
698  histfrog[histfrogp] = s;
699  histfrogp++;
700  } else
701  collapsefrog(s);
702  }
703  goto loop;
704  }
705 
706  if(nhunk < sizeof(Prog))
707  gethunk();
708  p = (Prog*)hunk;
709  nhunk -= sizeof(Prog);
710  hunk += sizeof(Prog);
711 
712  p->as = o;
713  p->reg = bloc[1] & 0x7f;
714  if(bloc[1] & 0x80)
715  p->mark = NOSCHED;
716  p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
717 
718  r = zaddr(bloc+6, &p->from, h) + 6;
719  r += zaddr(bloc+r, &p->to, h);
720  bloc += r;
721  c -= r;
722 
723  if(p->reg < 0 || p->reg > NREG)
724  diag("register out of range %d", p->reg);
725 
726  p->link = P;
727  p->cond = P;
728 
729  if(debug['W'])
730  print("%P\n", p);
731 
732  switch(o) {
733  case AHISTORY:
734  if(p->to.offset == -1) {
735  addlib(pn);
736  histfrogp = 0;
737  goto loop;
738  }
739  addhist(p->line, D_FILE); /* 'z' */
740  if(p->to.offset)
741  addhist(p->to.offset, D_PREG); /* 'Z' */
742  histfrogp = 0;
743  goto loop;
744 
745  case AEND:
746  histtoauto();
747  if(curtext != P)
748  curtext->to.autom = curauto;
749  curauto = 0;
750  curtext = P;
751  if(c)
752  goto newloop;
753  return;
754 
755  case AGLOBL:
756  s = p->from.sym;
757  if(s == S) {
758  diag("GLOBL must have a name\n%P", p);
759  errorexit();
760  }
761  if(s->type == 0 || s->type == SXREF) {
762  s->type = SBSS;
763  s->value = 0;
764  }
765  if(s->type != SBSS) {
766  diag("redefinition: %s\n%P", s->name, p);
767  s->type = SBSS;
768  s->value = 0;
769  }
770  if(p->to.offset > s->value)
771  s->value = p->to.offset;
772  break;
773 
774  case ADYNT:
775  if(p->to.sym == S) {
776  diag("DYNT without a sym\n%P", p);
777  break;
778  }
779  di = p->to.sym;
780  p->reg = 4;
781  if(di->type == SXREF) {
782  if(debug['z'])
783  Bprint(&bso, "%P set to %d\n", p, dtype);
784  di->type = SCONST;
785  di->value = dtype;
786  dtype += 4;
787  }
788  if(p->from.sym == S)
789  break;
790 
791  p->from.offset = di->value;
792  p->from.sym->type = SDATA;
793  if(curtext == P) {
794  diag("DYNT not in text: %P", p);
795  break;
796  }
797  p->to.sym = curtext->from.sym;
798  p->to.type = D_CONST;
799  p->link = datap;
800  datap = p;
801  break;
802 
803  case AINIT:
804  if(p->from.sym == S) {
805  diag("INIT without a sym\n%P", p);
806  break;
807  }
808  if(di == S) {
809  diag("INIT without previous DYNT\n%P", p);
810  break;
811  }
812  p->from.offset = di->value;
813  p->from.sym->type = SDATA;
814  p->link = datap;
815  datap = p;
816  break;
817 
818  case ADATA:
819  if(p->from.sym == S) {
820  diag("DATA without a sym\n%P", p);
821  break;
822  }
823  p->link = datap;
824  datap = p;
825  break;
826 
827  case AGOK:
828  diag("unknown opcode\n%P", p);
829  p->pc = pc;
830  pc++;
831  break;
832 
833  case ATEXT:
834  if(curtext != P) {
835  histtoauto();
836  curtext->to.autom = curauto;
837  curauto = 0;
838  }
839  skip = 0;
840  curtext = p;
841  autosize = (p->to.offset+3L) & ~3L;
842  if (autosize & 4)
843  autosize += 4;
844  p->to.offset = autosize;
845  autosize += 8;
846  s = p->from.sym;
847  if(s == S) {
848  diag("TEXT must have a name\n%P", p);
849  errorexit();
850  }
851  if(s->type != 0 && s->type != SXREF) {
852  if(p->reg & DUPOK) {
853  skip = 1;
854  goto casedef;
855  }
856  diag("redefinition: %s\n%P", s->name, p);
857  }
858  s->type = STEXT;
859  s->value = pc;
860  lastp->link = p;
861  lastp = p;
862  p->pc = pc;
863  pc++;
864  if(textp == P) {
865  textp = p;
866  etextp = p;
867  goto loop;
868  }
869  etextp->cond = p;
870  etextp = p;
871  break;
872 
873  case AMOVS:
874  if(skip)
875  goto casedef;
876 
877  if(p->from.type == D_FCONST) {
878  /* size sb 9 max */
879  snprint(literal, sizeof literal, "$%lux", ieeedtof(p->from.ieee));
880  s = lookup(literal, 0);
881  if(s->type == 0) {
882  s->type = SBSS;
883  s->value = 4;
884  t = prg();
885  t->as = ADATA;
886  t->line = p->line;
887  t->from.type = D_OREG;
888  t->from.sym = s;
889  t->from.name = D_EXTERN;
890  t->reg = 4;
891  t->to = p->from;
892  t->link = datap;
893  datap = t;
894  }
895  p->from.type = D_OREG;
896  p->from.sym = s;
897  p->from.name = D_EXTERN;
898  p->from.offset = 0;
899  }
900  goto casedef;
901 
902  case AMOVT:
903  if(skip)
904  goto casedef;
905 
906  if(p->from.type == D_FCONST) {
907  /* size sb 18 max */
908  snprint(literal, sizeof literal, "$%lux.%lux",
909  p->from.ieee->l, p->from.ieee->h);
910  s = lookup(literal, 0);
911  if(s->type == 0) {
912  s->type = SBSS;
913  s->value = 8;
914  t = prg();
915  t->as = ADATA;
916  t->line = p->line;
917  t->from.type = D_OREG;
918  t->from.sym = s;
919  t->from.name = D_EXTERN;
920  t->reg = 8;
921  t->to = p->from;
922  t->link = datap;
923  datap = t;
924  }
925  p->from.type = D_OREG;
926  p->from.sym = s;
927  p->from.name = D_EXTERN;
928  p->from.offset = 0;
929  }
930  goto casedef;
931 
932  case AMOVQ:
933  if(skip)
934  goto casedef;
935 
936  if (p->from.type == D_FREG || p->to.type == D_FREG)
937  p->as = AMOVT; /* stupid compiler optimiser kkludge */
938 
939  case AMOVL:
940  case AMOVW:
941  case AMOVB:
942  /* BOTCH */
943  if (p->from.type == D_CONST)
944  if (p->from.offset == 0LL && p->from.name == D_NONE) {
945  p->from.type = D_REG;
946  p->from.reg = REGZERO;
947  }
948  goto casedef;
949 
950  default:
951  casedef:
952  if(skip)
953  nopout(p);
954 
955  if(p->to.type == D_BRANCH)
956  p->to.offset += ipc;
957  lastp->link = p;
958  lastp = p;
959  p->pc = pc;
960  pc++;
961  break;
962  }
963  goto loop;
964 
965 eof:
966  diag("truncated object file: %s", pn);
967 }
968 
969 Sym*
970 lookup(char *symb, int v)
971 {
972  Sym *s;
973  char *p;
974  long h;
975  int c0, l;
976 
977  h = v;
978  for(p=symb; c0 = *p; p++)
979  h = h+h+h + c0;
980  l = (p - symb) + 1;
981  if(h < 0)
982  h = ~h;
983  h %= NHASH;
984  for(s = hash[h]; s != S; s = s->link)
985  if(s->version == v)
986  if(memcmp(s->name, symb, l) == 0)
987  return s;
988 
989  while(nhunk < sizeof(Sym))
990  gethunk();
991  s = (Sym*)hunk;
992  nhunk -= sizeof(Sym);
993  hunk += sizeof(Sym);
994 
995  s->name = malloc(l);
996  memmove(s->name, symb, l);
997 
998  s->link = hash[h];
999  s->type = 0;
1000  s->version = v;
1001  s->value = 0;
1002  hash[h] = s;
1003  return s;
1004 }
1005 
1006 Prog*
1007 prg(void)
1008 {
1009  Prog *p;
1010 
1011  while(nhunk < sizeof(Prog))
1012  gethunk();
1013  p = (Prog*)hunk;
1014  nhunk -= sizeof(Prog);
1015  hunk += sizeof(Prog);
1016 
1017  *p = zprg;
1018  return p;
1019 }
1020 
1021 void
1022 gethunk(void)
1023 {
1024  char *h;
1025  long nh;
1026 
1027  nh = NHUNK;
1028  if(thunk >= 5L*NHUNK) {
1029  nh = 5L*NHUNK;
1030  if(thunk >= 25L*NHUNK)
1031  nh = 25L*NHUNK;
1032  }
1033  h = mysbrk(nh);
1034  if(h == (char*)-1) {
1035  diag("out of memory");
1036  errorexit();
1037  }
1038  hunk = h;
1039  nhunk = nh;
1040  thunk += nh;
1041 }
1042 
1043 void
1044 doprof1(void)
1045 {
1046  Sym *s;
1047  long n;
1048  Prog *p, *q;
1049 
1050  if(debug['v'])
1051  Bprint(&bso, "%5.2f profile 1\n", cputime());
1052  Bflush(&bso);
1053  s = lookup("__mcount", 0);
1054  n = 1;
1055  for(p = firstp->link; p != P; p = p->link) {
1056  if(p->as == ATEXT) {
1057  q = prg();
1058  q->line = p->line;
1059  q->link = datap;
1060  datap = q;
1061  q->as = ADATA;
1062  q->from.type = D_OREG;
1063  q->from.name = D_EXTERN;
1064  q->from.offset = n*4;
1065  q->from.sym = s;
1066  q->reg = 4;
1067  q->to = p->from;
1068  q->to.type = D_CONST;
1069 
1070  q = prg();
1071  q->line = p->line;
1072  q->pc = p->pc;
1073  q->link = p->link;
1074  p->link = q;
1075  p = q;
1076  p->as = AMOVL;
1077  p->from.type = D_OREG;
1078  p->from.name = D_EXTERN;
1079  p->from.sym = s;
1080  p->from.offset = n*4 + 4;
1081  p->to.type = D_REG;
1082  p->to.reg = REGTMP;
1083 
1084  q = prg();
1085  q->line = p->line;
1086  q->pc = p->pc;
1087  q->link = p->link;
1088  p->link = q;
1089  p = q;
1090  p->as = AADDQ;
1091  p->from.type = D_CONST;
1092  p->from.offset = 1;
1093  p->to.type = D_REG;
1094  p->to.reg = REGTMP;
1095 
1096  q = prg();
1097  q->line = p->line;
1098  q->pc = p->pc;
1099  q->link = p->link;
1100  p->link = q;
1101  p = q;
1102  p->as = AMOVL;
1103  p->from.type = D_REG;
1104  p->from.reg = REGTMP;
1105  p->to.type = D_OREG;
1106  p->to.name = D_EXTERN;
1107  p->to.sym = s;
1108  p->to.offset = n*4 + 4;
1109 
1110  n += 2;
1111  continue;
1112  }
1113  }
1114  q = prg();
1115  q->line = 0;
1116  q->link = datap;
1117  datap = q;
1118 
1119  q->as = ADATA;
1120  q->from.type = D_OREG;
1121  q->from.name = D_EXTERN;
1122  q->from.sym = s;
1123  q->reg = 4;
1124  q->to.type = D_CONST;
1125  q->to.offset = n;
1126 
1127  s->type = SBSS;
1128  s->value = n*4;
1129 }
1130 
1131 void
1132 doprof2(void)
1133 {
1134  Sym *s2, *s4;
1135  Prog *p, *q, *q2, *ps2, *ps4;
1136 
1137  if(debug['v'])
1138  Bprint(&bso, "%5.2f profile 2\n", cputime());
1139  Bflush(&bso);
1140 
1141  if(debug['e']){
1142  s2 = lookup("_tracein", 0);
1143  s4 = lookup("_traceout", 0);
1144  }else{
1145  s2 = lookup("_profin", 0);
1146  s4 = lookup("_profout", 0);
1147  }
1148  if(s2->type != STEXT || s4->type != STEXT) {
1149  if(debug['e'])
1150  diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1151  else
1152  diag("_profin/_profout not defined");
1153  return;
1154  }
1155 
1156  ps2 = P;
1157  ps4 = P;
1158  for(p = firstp; p != P; p = p->link) {
1159  if(p->as == ATEXT) {
1160  if(p->from.sym == s2) {
1161  ps2 = p;
1162  p->reg = 1;
1163  }
1164  if(p->from.sym == s4) {
1165  ps4 = p;
1166  p->reg = 1;
1167  }
1168  }
1169  }
1170  for(p = firstp; p != P; p = p->link) {
1171  if(p->as == ATEXT) {
1172  if(p->reg != NREG) {
1173  for(;;) {
1174  q = p->link;
1175  if(q == P)
1176  break;
1177  if(q->as == ATEXT)
1178  break;
1179  p = q;
1180  }
1181  continue;
1182  }
1183 
1184  /*
1185  * JSR profin, R2
1186  */
1187  q = prg();
1188  q->line = p->line;
1189  q->pc = p->pc;
1190  q->link = p->link;
1191  if(debug['e']){ /* embedded tracing */
1192  q2 = prg();
1193  p->link = q2;
1194  q2->link = q;
1195 
1196  q2->line = p->line;
1197  q2->pc = p->pc;
1198 
1199  q2->as = AJMP;
1200  q2->to.type = D_BRANCH;
1201  q2->to.sym = p->to.sym;
1202  q2->cond = q->link;
1203  }else
1204  p->link = q;
1205  p = q;
1206  p->as = AJSR;
1207  p->to.type = D_BRANCH;
1208  p->cond = ps2;
1209  p->to.sym = s2;
1210 
1211  continue;
1212  }
1213  if(p->as == ARET) {
1214  /*
1215  * JSR (default)
1216  */
1217  if(debug['e']){ /* embedded tracing */
1218  q = prg();
1219  q->line = p->line;
1220  q->pc = p->pc;
1221  q->link = p->link;
1222  p->link = q;
1223  p = q;
1224  }
1225  /*
1226  * JSR profout
1227  */
1228  p->as = AJSR;
1229  p->to.type = D_BRANCH;
1230  p->cond = ps4;
1231  p->to.sym = s4;
1232 
1233 
1234  /*
1235  * RET
1236  */
1237  q = prg();
1238  q->line = p->line;
1239  q->pc = p->pc;
1240  q->link = p->link;
1241  p->link = q;
1242  p = q;
1243  p->as = ARET;
1244 
1245  continue;
1246  }
1247  }
1248 }
1249 
1250 void
1251 nuxiinit(void)
1252 {
1253  int i, c;
1254 
1255  for(i=0; i<4; i++) {
1256  c = find1(0x04030201L, i+1);
1257  if(i <= 4)
1258  inuxi4[i] = c;
1259  if(i <= 2)
1260  inuxi2[i] = c;
1261  if(i <= 1)
1262  inuxi1[i] = c;
1263  }
1264  for (i = 0; i < 4; i++) {
1265  c = find1(0x04030201L, i+1);
1266  fnuxi8[i] = c;
1267  fnuxi8[i+4] = c + sizeof(long);
1268  }
1269 
1270  if(debug['v']) {
1271  Bprint(&bso, "inuxi = ");
1272  for(i=0; i<1; i++)
1273  Bprint(&bso, "%d", inuxi1[i]);
1274  Bprint(&bso, " ");
1275  for(i=0; i<2; i++)
1276  Bprint(&bso, "%d", inuxi2[i]);
1277  Bprint(&bso, " ");
1278  for(i=0; i<4; i++)
1279  Bprint(&bso, "%d", inuxi4[i]);
1280  Bprint(&bso, " ");
1281  Bprint(&bso, "\nfnuxi = ");
1282  for(i=0; i<8; i++)
1283  Bprint(&bso, "%d", fnuxi8[i]);
1284  Bprint(&bso, "\n");
1285  }
1286  Bflush(&bso);
1287 }
1288 
1289 find1(long l, int c)
1290 {
1291  char *p;
1292  int i;
1293 
1294  p = (char*)&l;
1295  for(i=0; i<4; i++)
1296  if(*p++ == c)
1297  return i;
1298  return 0;
1299 }
1300 
1301 long
1302 ieeedtof(Ieee *ieee)
1303 {
1304  int exp;
1305  long v;
1306 
1307  if(ieee->h == 0)
1308  return 0;
1309  exp = (ieee->h>>20) & ((1L<<11)-1L);
1310  exp -= (1L<<10) - 2L;
1311  v = (ieee->h & 0xfffffL) << 3;
1312  v |= (ieee->l >> 29) & 0x7L;
1313  if((ieee->l >> 28) & 1) {
1314  v++;
1315  if(v & 0x800000L) {
1316  v = (v & 0x7fffffL) >> 1;
1317  exp++;
1318  }
1319  }
1320  if(exp <= -126 || exp >= 130)
1321  diag("double fp to single fp overflow");
1322  v |= ((exp + 126) & 0xffL) << 23;
1323  v |= ieee->h & 0x80000000L;
1324  return v;
1325 }
1326 
1327 double
1328 ieeedtod(Ieee *ieee)
1329 {
1330  Ieee e;
1331  double fr;
1332  int exp;
1333 
1334  if(ieee->h & (1L<<31)) {
1335  e.h = ieee->h & ~(1L<<31);
1336  e.l = ieee->l;
1337  return -ieeedtod(&e);
1338  }
1339  if(ieee->l == 0 && ieee->h == 0)
1340  return 0;
1341  fr = ieee->l & ((1L<<16)-1L);
1342  fr /= 1L<<16;
1343  fr += (ieee->l>>16) & ((1L<<16)-1L);
1344  fr /= 1L<<16;
1345  fr += (ieee->h & (1L<<20)-1L) | (1L<<20);
1346  fr /= 1L<<21;
1347  exp = (ieee->h>>20) & ((1L<<11)-1L);
1348  exp -= (1L<<10) - 2L;
1349  return ldexp(fr, exp);
1350 }