home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / ld / syms.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  12KB  |  708 lines

  1.  
  2. /*
  3.  * Copyright (c) 1991 by Sozobon, Limited.  Author: Johann Ruegg
  4.  *
  5.  * Permission is granted to anyone to use this software for any purpose
  6.  * on any computer system, and to redistribute it freely, with the
  7.  * following restrictions:
  8.  * 1) No charge may be made other than reasonable charges for reproduction.
  9.  * 2) Modified versions must be clearly marked as such.
  10.  * 3) The authors are not responsible for any harmful consequences
  11.  *    of using this software, even if they result from defects in it.
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include "syms.h"
  16. #include "structs.h"
  17.  
  18. char *mlmalloc(), *mmalloc();
  19. extern int only8;
  20.  
  21. #ifdef NHASH
  22. /* NHASH must be a power of 2 */
  23. struct sinfo *ushead[NHASH];
  24. struct sinfo *dshead[NHASH];
  25. int hashv;
  26. #define USHEAD    ushead[hashv]
  27. #define DSHEAD    dshead[hashv]
  28. #else
  29. struct sinfo *ushead, *dshead;
  30. #define USHEAD    ushead
  31. #define DSHEAD    dshead
  32. #endif
  33.  
  34. extern int vflag;
  35.  
  36. getsyms(fd, size, spp)
  37. long size;
  38. struct symchunk **spp;
  39. {
  40.     struct symchunk *chp;
  41.     long n;
  42.     int k;
  43.  
  44.     n = size / SYMSIZE;
  45.     if (n == 0) {
  46.         *spp = 0;
  47.         return;
  48.     }
  49.  
  50.     do {
  51.         if (n > CHUNKMAX)
  52.             k = CHUNKMAX;
  53.         else
  54.             k = n;
  55.  
  56.         chp = (struct symchunk *)mmalloc(sizeof(struct symchunk) +
  57.                 ((k-1)*sizeof(struct sym)));
  58.         rread(fd, &chp->s[0], k * SYMSIZE);
  59. #ifdef UNIXHOST
  60.         symhacki(&chp->s[0], k);
  61. #endif
  62.         commhack(&chp->s[0], k);
  63.         chp->nsyms = k;
  64.         *spp = chp;
  65.         spp = &chp->next;
  66.         n -= k;
  67.     } while (n);
  68.  
  69.     chp->next = 0;
  70. }
  71.  
  72. commhack(sp, n)
  73. struct sym *sp;
  74. {
  75.     int i;
  76.  
  77.     /* Common def with value of 0 is really an external ref */
  78.  
  79.     for (i=0; i<n; i++) {
  80.         if (sp->flags == COMMDEF && sp->value == 0)
  81.             sp->flags = EXTREF;
  82.         sp++;
  83.     }
  84. }
  85.  
  86. symfree(chp)
  87. struct symchunk *chp;
  88. {
  89.     struct symchunk *next;
  90.  
  91.     while (chp) {
  92.         next = chp->next;
  93.         free(chp);
  94.         chp = next;
  95.     }
  96. }
  97.  
  98. chkx(chp)
  99. struct symchunk *chp;
  100. {
  101.     struct sym *sp;
  102.  
  103.     if (only8)
  104.         return 0;
  105.     if (chp == 0)
  106.         return 0;
  107.     sp = &chp->s[0];
  108.     if (sp->flags == XFLAGS && sp->value == XVALUE &&
  109.         strncmp(sp->name, XNAME, 8) == 0)
  110.         return 1;
  111.     return 0;
  112. }
  113.  
  114. struct sinfo *
  115. xlookup(head, s, x)
  116. struct sinfo *head;
  117. char *s, *x;
  118. {
  119.     while (head) {
  120.         if (smatch(head->name, s, x))
  121.             return head;
  122.         head = head->next;
  123.     }
  124.     return 0;
  125. }
  126.  
  127. smatch(old, s, x)
  128. char *old, *s, *x;
  129. {
  130.     int ol;
  131.  
  132.     ol = strlen(old);
  133.     if (ol < 8)
  134.         return strcmp(old, s) == 0;
  135.     if (strncmp(old, s, 8) != 0)
  136.         return 0;
  137.     if (strcmp(&old[8], x) == 0)
  138.         return 1;
  139.     else if (x[0] == '*')
  140.         return 1;
  141.     else if (old[8] == '*')
  142.         return 2;
  143.     return 0;
  144. }
  145.  
  146. struct sinfo *
  147. newsinfo(s, xp)
  148. char *s, *xp;
  149. {
  150.     int slen, xlen;
  151.     struct sinfo *sp;
  152.  
  153.     slen = strnlen(s, 8);
  154.     if (slen == 8 && xp)
  155.         xlen = strlen(xp);
  156.     else
  157.         xlen = 0;
  158.     sp = (struct sinfo *)mmalloc(slen+xlen+sizeof(struct sinfo));
  159.     bcopy(s, sp->name, slen);
  160.     sp->name[slen] = 0;
  161.     if (xlen)
  162.         strcpy(&sp->name[8], xp);
  163.  
  164.     sp->flags = sp->mark = 0;
  165.     sp->value = 0;
  166.     sp->obj = 0;
  167.     return sp;
  168. }
  169.  
  170. sundeff(s)
  171. char *s;
  172. {
  173.     hashv = hash(s);
  174.     if (strlen(s) > 8)
  175.         undeff(s, &s[8], 0L);
  176.     else
  177.         undeff(s, 0L, 0L);
  178. }
  179.  
  180. undeff(s, xp, op)    /* hashv set by caller */
  181. char *s;
  182. char *xp;
  183. struct oinfo *op;
  184. {
  185.     struct sinfo *sp;
  186.  
  187.     sp = newsinfo(s, xp);
  188.     sp->flags = EXTREF;
  189.     sp->obj = op;
  190.     listins(&USHEAD, sp);
  191.  
  192.     if (vflag > 1)
  193.         printf("und %s\n", sp->name);
  194. }
  195.  
  196. char *
  197. exten(chp, sp)
  198. struct symchunk *chp;
  199. struct sym *sp;
  200. {
  201.     static int maxlen = 0;
  202.     static char *cp = 0;
  203.     int k, i, n, slen;
  204.     struct symchunk *nchp;
  205.     struct sym *nsp;
  206.  
  207.     if (maxlen == 0) {
  208.         maxlen = 100;
  209.         cp = mmalloc(maxlen);
  210.     }
  211.  
  212. again:
  213.     k = chp->nsyms;
  214.     i = sp - &chp->s[0];
  215.     slen = 0;
  216.     cp[slen] = 0;
  217.     nchp = chp;  nsp = sp;
  218.  
  219.     while (slen+9 < maxlen) {
  220.         i++;
  221.         if (i < k) {
  222.             nsp++;
  223.         } else if (nchp->next == NULL) {
  224.             return cp;
  225.         } else {
  226.             nchp = nchp->next;
  227.             k = nchp->nsyms;
  228.             i = 0;
  229.             nsp = &nchp->s[0];
  230.         }
  231.  
  232.         if (nsp->flags != XFLAGS || nsp->value != XVALUE) {
  233.             return cp;
  234.         }
  235.         n = strnlen(nsp->name, 8);
  236.         bcopy(nsp->name, &cp[slen], n);
  237.         slen += n;
  238.         cp[slen] = 0;
  239.  
  240.         if (n != 8) {
  241.             return cp;
  242.         }
  243.     }
  244.  
  245.     /* buffer is too small */
  246.     free(cp);
  247.     maxlen += 100;
  248.     cp = mmalloc(maxlen);
  249.     goto again;
  250. }
  251.  
  252. needed(chp, havex)
  253. struct symchunk *chp;
  254. {
  255.     unsigned i;
  256.     int k;
  257.  
  258.     while (chp) {
  259.         k = chp->nsyms;
  260.         for (i=0; i<k; i++)
  261.             if (need1(&chp->s[i], chp, havex))
  262.                 return 1;
  263.         chp = chp->next;
  264.     }
  265.     return 0;
  266. }
  267.  
  268. char *
  269. getext(chp, sp, havex)
  270. struct symchunk *chp;
  271. struct sym *sp;
  272. {
  273.     char *extp;
  274.  
  275.     if (havex)
  276.         extp = exten(chp, sp);
  277.     else if (only8)
  278.         extp = "";
  279.     else
  280.         extp = "*";
  281.     return extp;
  282. }
  283.  
  284. need1(sp, chp, havex)
  285. struct sym *sp;
  286. struct symchunk *chp;
  287. {
  288.     char *extp;
  289.     struct sinfo *sip;
  290.  
  291. #ifdef NHASH
  292.     hashv = hash(sp->name);
  293. #endif
  294.  
  295.     if (notglob(sp->flags))
  296.         return 0;
  297.     if (sp->flags == EXTREF || sp->flags == COMMDEF)
  298.         return 0;
  299.     if (sp->name[7])
  300.         extp = getext(chp, sp, havex);
  301.     else
  302.         extp = 0;
  303.  
  304.     if ((sip = xlookup(USHEAD, sp->name, extp))) {
  305.         if (vflag > 1)
  306.             printf("Needed %s\n", sip->name);
  307.         return 1;
  308.     }
  309.     return 0;
  310. }
  311.  
  312. p1syms(chp, havex, op)
  313. struct symchunk *chp;
  314. struct oinfo *op;
  315. {
  316.     unsigned i;
  317.     int k;
  318.  
  319.     while (chp) {
  320.         k = chp->nsyms;
  321.         for (i=0; i<k; i++)
  322.             ap1sym(&chp->s[i], chp, havex, op);
  323.         chp = chp->next;
  324.     }
  325.     return 0;
  326. }
  327.  
  328. ap1sym(sp, chp, havex, op)
  329. struct sym *sp;
  330. struct symchunk *chp;
  331. struct oinfo *op;
  332. {
  333.     char *extp;
  334.     struct sinfo *sip;
  335.  
  336.     if (notglob(sp->flags))
  337.         return;
  338.     if (sp->name[7])
  339.         extp = getext(chp, sp, havex);
  340.     else
  341.         extp = 0;
  342. #ifdef NHASH
  343.     hashv = hash(sp->name);
  344. #endif
  345.     if (sp->flags == EXTREF) {
  346.         if (xlookup(USHEAD, sp->name, extp))
  347.             return;
  348.         else if (xlookup(DSHEAD, sp->name, extp))
  349.             ;
  350.         else
  351.             undeff(sp->name, extp, op);
  352.     } else {
  353.         sip = xlookup(USHEAD, sp->name, extp);
  354.         if (sip) {
  355.             listdel(&USHEAD, sip);
  356.             sip->flags = sp->flags;
  357.             sip->value = sp->value;
  358.             sip->obj = op;
  359.             listins(&DSHEAD, sip);
  360.  
  361.             if (vflag > 1)
  362.                 printf("u->d %s\n", sip->name);
  363.         } else {
  364.             sip = xlookup(DSHEAD, sp->name, extp);
  365.             if (sip)
  366.                 def2chk(sip, sp);
  367.             else
  368.                 newdef(sp, extp, op);
  369.         }
  370.     }
  371.     return 0;
  372. }
  373.  
  374. def2chk(sip, sp)
  375. struct sinfo *sip;
  376. struct sym *sp;
  377. {
  378.     if (sip->flags == COMMDEF && sp->flags == COMMDEF) {
  379.         if (sip->value != sp->value) {
  380.             warns("common sizes differ for", sip->name);
  381.             if (sp->value > sip->value)
  382.                 sip->value = sp->value;
  383.         }
  384.     } else
  385.         fatals("double definition of", sip->name);
  386. }
  387.  
  388. newdef(sp, extp, op)    /* hashv set by caller */
  389. struct sym *sp;
  390. char *extp;
  391. struct oinfo *op;
  392. {
  393.     struct sinfo *sip;
  394.  
  395.     sip = newsinfo(sp->name, extp);
  396.     sip->flags = sp->flags;
  397.     sip->value = sp->value;
  398.     sip->obj = op;
  399.     listins(&DSHEAD, sip);
  400.  
  401.     if (vflag > 1)
  402.         printf("def %s\n", sip->name);
  403. }
  404.  
  405. notglob(flags)
  406. {
  407.     if (flags & F_GLBL)
  408.         return 0;
  409.     if (flags == EXTREF)
  410.         return 0;
  411.     return 1;
  412. }
  413.  
  414. special(s)
  415. char *s;
  416. {
  417.     if (strcmp(s, "_end") == 0)
  418.         return 1;
  419.     if (strcmp(s, "_etext") == 0)
  420.         return 1;
  421.     if (strcmp(s, "_edata") == 0)
  422.         return 1;
  423.     return 0;
  424. }
  425.  
  426. end_sym(s, val, flag)
  427. char *s;
  428. long val;
  429. {
  430.     struct sinfo *sip;
  431.  
  432. #ifdef NHASH
  433.     hashv = hash(s);
  434. #endif
  435.  
  436.     sip = xlookup(USHEAD, s, 0L);
  437.     if (sip) {
  438.         listdel(&USHEAD, sip);
  439.         sip->flags = flag;
  440.         sip->value = val;
  441.         sip->obj = 0;
  442.         listins(&DSHEAD, sip);
  443.     }
  444. }
  445.  
  446. chk_undefs()
  447. {
  448.     struct sinfo *sp;
  449.     int any = 0;
  450.  
  451. #ifdef NHASH
  452.     for (hashv=0; hashv < NHASH; hashv++)
  453. #endif
  454.     {
  455.         sp = USHEAD;
  456.         while (sp) {
  457.         if (!special(sp->name)) {
  458.             any = 1;
  459.             printf("undefined symbol %s", sp->name);
  460.             if (sp->obj) {
  461.                 printf(" from %s", sp->obj->finfo->name);
  462.                 if (sp->obj->aname[0])
  463.                     printf("(%.14s)", sp->obj->aname);
  464.             }
  465.             putchar('\n');
  466.         }
  467.         sp = sp->next;
  468.         }
  469.     }
  470.     if (any)
  471.         fatal("load aborted due to undefined symbols");
  472. }
  473.  
  474. long
  475. mkcomm(where)
  476. long where;
  477. {
  478.     struct sinfo *sp;
  479.     long size, base, obase;
  480.  
  481.     base = obase = where;
  482. #ifdef NHASH
  483.     for (hashv=0; hashv < NHASH; hashv++)
  484. #endif
  485.     {
  486.         sp = DSHEAD;
  487.         while (sp) {
  488.         if (sp->flags == COMMDEF) {
  489.             size = sp->value;
  490.             sp->value = base;
  491.             sp->flags = (F_BSS|F_GLBL|F_DEF);
  492.             base += size;
  493.         }
  494.         sp = sp->next;
  495.         }
  496.     }
  497.     return base - obase;
  498. }
  499.  
  500. adjsyms()
  501. {
  502.     struct sinfo *sp;
  503.  
  504. #ifdef NHASH
  505.     for (hashv=0; hashv < NHASH; hashv++)
  506. #endif
  507.     {
  508.         sp = DSHEAD;
  509.         while (sp) {
  510.         switch (sp->flags & 7) {
  511.         case F_TEXT:
  512.             sp->value += sp->obj->tbase;
  513.             break;
  514.         case F_DATA:
  515.             sp->value += sp->obj->dbase;
  516.             break;
  517.         case F_BSS:
  518.             sp->value += sp->obj->bbase;
  519.             break;
  520.         }
  521.         sp = sp->next;
  522.         }
  523.     }
  524. }
  525.  
  526. long
  527. countsyms()
  528. {
  529.     long n;
  530.     struct sinfo *sp;
  531.  
  532.     if (only8)
  533.         n = 0;
  534.     else
  535.         n = 1;
  536.  
  537. #ifdef NHASH
  538.     for (hashv=0; hashv < NHASH; hashv++)
  539. #endif
  540.     {
  541.         sp = DSHEAD;
  542.         while (sp) {
  543.         n += count1(sp);
  544.         sp = sp->next;
  545.         }
  546.     }
  547.     return n * SYMSIZE;
  548. }
  549.  
  550. count1(sp)
  551. struct sinfo *sp;
  552. {
  553.     int n;
  554.  
  555.     if (only8)
  556.         return 1;
  557.     n = strlen(sp->name);
  558.     if (n == 9 && sp->name[8] == '*')
  559.         n = 8;
  560.     if (n == 0)
  561.         fatal("zero length name");
  562.     return (n+7)/8;
  563. }
  564.  
  565. char zname[8];
  566. #ifndef UNIXHOST
  567. #define FIXSYM(a)
  568. #else
  569. #define FIXSYM(a)    fixsym(a)
  570. #endif
  571.  
  572. wrsyms(fd)
  573. {
  574.     struct sinfo *sp;
  575.     struct sym s;
  576.  
  577.     if (!only8) {
  578.         bcopy(zname, s.name, 8);
  579.         strncpy(s.name, XNAME, 8);
  580.         s.flags = XFLAGS;
  581.         s.mark = 0;
  582.         s.value = XVALUE;
  583.         FIXSYM(&s);
  584.         write(fd, &s, SYMSIZE);
  585.     }
  586.  
  587. #ifdef NHASH
  588.     for (hashv=0; hashv < NHASH; hashv++)
  589. #endif
  590.     {
  591.         sp = DSHEAD;
  592.         while (sp) {
  593.         bcopy(zname, s.name, 8);
  594.         strncpy(s.name, sp->name, 8);
  595.         s.flags = sp->flags;
  596.         s.mark = 0;
  597.         s.value = sp->value;
  598.         FIXSYM(&s);
  599.         write(fd, &s, SYMSIZE);
  600.  
  601.         if (!only8) {
  602.             int n, i;
  603.  
  604.             n = strlen(sp->name);
  605.             if (n == 9 && sp->name[8] == '*')
  606.                 n = 8;
  607.             i = 8;
  608.             while (n > i) {
  609.                 bcopy(zname, s.name, 8);
  610.                 strncpy(s.name, &sp->name[i], 8);
  611.                 s.flags = XFLAGS;
  612.                 s.mark = 0;
  613.                 s.value = XVALUE;
  614.                 i += 8;
  615.  
  616.                 FIXSYM(&s);
  617.                 write(fd, &s, SYMSIZE);
  618.             }
  619.         }
  620.  
  621.         sp = sp->next;
  622.         }
  623.     }
  624. }
  625.  
  626. struct sym *
  627. chunki(x, chpp)
  628. unsigned x;
  629. struct symchunk **chpp;
  630. {
  631.     unsigned k, i;
  632.     struct sym *sp;
  633.     struct symchunk *chp;
  634.  
  635.     chp = *chpp;
  636.     i = 0;
  637.     while (chp) {
  638.         k = chp->nsyms;
  639.         if (x < i+k) {
  640.             sp = &chp->s[x-i];
  641.             *chpp = chp;
  642.             return sp;
  643.         }
  644.         i += k;
  645.         chp = chp->next;
  646.     }
  647.     fatal("bad relocation index");
  648. }
  649.  
  650. long
  651. findx(x, chp, havex, relp)
  652. unsigned short x;
  653. struct symchunk *chp;
  654. short *relp;
  655. {
  656.     struct sinfo *sip;
  657.     struct sym *sp;
  658.     char *extp;
  659.  
  660.     x >>= 3;
  661.     sp = chunki(x, &chp);
  662. #ifdef NHASH
  663.     hashv = hash(sp->name);
  664. #endif
  665.     if (sp->mark == 0) {
  666.         if (sp->name[7])
  667.             extp = getext(chp, sp, havex);
  668.         else
  669.             extp = 0;
  670.         sip = xlookup(DSHEAD, sp->name, extp);
  671.         if (sip == 0)
  672.             fatal("Cant find symbol");
  673.         switch (sip->flags & 7) {
  674.         case 1:
  675.             sp->mark = 3; break;
  676.         case 2:
  677.             sp->mark = 2; break;
  678.         case 4:
  679.             sp->mark = 1; break;
  680.         default:
  681.             fatal("Bad sym type");
  682.         }
  683.         sp->value = sip->value;
  684.     }
  685.     *relp = sp->mark;
  686.     return sp->value;
  687. }
  688.  
  689. #ifdef NHASH
  690.  
  691. /* only use 1st 8 chars for hash value! */
  692.  
  693. hash(s)
  694. unsigned char *s;
  695. {
  696.     unsigned char c;
  697.     register i, n = 0;
  698.  
  699.     for (i=1; i<5; i++) {
  700.         c = s[i];
  701.         if (!c)
  702.             break;
  703.         n = (n<<1)|c;
  704.     }
  705.     return n & (NHASH-1);
  706. }
  707. #endif
  708.