home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / 68kdisassem / part2 / robj.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  18.0 KB  |  877 lines

  1. /*
  2.  *    SCCS:    @(#)robj.c    1.2    11/2/84    14:19:59
  3.  *    Read object files.
  4.  *
  5.  ***********************************************************************
  6.  *    This software is copyright of
  7.  *
  8.  *        John M Collins
  9.  *        47 Cedarwood Drive
  10.  *        St Albans
  11.  *        Herts, AL4 0DN
  12.  *        England            +44 727 57267
  13.  *
  14.  *    and is released into the public domain on the following conditions:
  15.  *
  16.  *        1.  No free maintenance will be guaranteed.
  17.  *        2.  Nothing may be based on this software without
  18.  *            acknowledgement, including incorporation of this
  19.  *            notice.
  20.  *
  21.  *    Notwithstanding the above, the author welcomes correspondence and bug
  22.  *    fixes.
  23.  ***********************************************************************
  24.  *
  25.  *    This particular module will obviously have to be munged beyond
  26.  *    recognition for another object format.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <a.out.h>
  31. #include "unc.h"
  32.  
  33. void    gette(), getde(), setde(), putte(), putde();
  34. long    gettw(), getdw();
  35. void    reallst(), lclash(), nomem(), unimpl();
  36. void    addit();
  37. char    *malloc();
  38. long    lseek();
  39.  
  40. int    par_entry, par_round, nmods, donedrel, donebrel;
  41. struct    commit    abstab, comtab, dreltab;
  42. long    trelpos, drelpos, brelpos;
  43.  
  44. ef_fids    mainfile;
  45.  
  46. symbol    lookup(), inventsymb(), getnsymb();
  47.  
  48. #define    DBSIZE    100
  49. #define    STINIT    20
  50.  
  51. /*
  52.  *    Read text segment.  Return 0 if not ok.
  53.  */
  54.  
  55. int    rtext(inf, offset, outf)
  56. int    inf;        /*  a.out file (possibly in library)  */
  57. long    offset;        /*  Offset from start of inf of a.out file  */
  58. ef_fid    outf;        /*  Output file descriptor  */
  59. {
  60.     t_entry        tstr;
  61.     struct    bhdr    filhdr;
  62.     register  long    size;
  63.     register  int    i, l;
  64.     unsigned  short    inbuf[DBSIZE/2];
  65.  
  66.     /*
  67.      *    Initialise fields in structure.
  68.      */
  69.     
  70.     tstr.t_type = T_UNKNOWN;
  71.     tstr.t_vins = 1;        /*  For the moment  */
  72.     tstr.t_bdest = 0;
  73.     tstr.t_gbdest = 0;
  74.     tstr.t_lng = 1;
  75.     tstr.t_reloc = R_NONE;
  76.     tstr.t_rdisp = 0;
  77.     tstr.t_isrel = 0;
  78.     tstr.t_amap = 0;
  79.     tstr.t_dref = 0;
  80.     tstr.t_relsymb = NULL;
  81.     tstr.t_reldisp = 0;
  82.     tstr.t_lab = NULL;
  83.     tstr.t_lsymb = 0;
  84.     tstr.t_refhi = 0;
  85.     tstr.t_reflo = 0x7fffffff;
  86.     tstr.t_match = 0;
  87.     
  88.     /*
  89.      *    Read a.out header.
  90.      */
  91.     
  92.     (void) lseek(inf, offset, 0);
  93.  
  94.     if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
  95.         return    0;
  96.  
  97.     if  (filhdr.fmagic != FMAGIC  &&  filhdr.fmagic != NMAGIC)
  98.         return    0;
  99.  
  100.     /*
  101.      *    Warn user if entry point does not tie up.
  102.      */
  103.     
  104.     if  (filhdr.entry != par_entry)
  105.         (void) fprintf(stderr, "Warning: File has -R%X\n", filhdr.entry);
  106.  
  107.     outf->ef_entry = filhdr.entry;
  108.     outf->ef_tbase = filhdr.entry;
  109.     outf->ef_dbase = filhdr.tsize + filhdr.entry;
  110.  
  111.     if  (filhdr.fmagic == NMAGIC)
  112.         outf->ef_dbase = (outf->ef_dbase + par_round) & (~par_round);
  113.  
  114.     outf->ef_bbase = outf->ef_dbase + filhdr.dsize;
  115.     outf->ef_end = outf->ef_bbase + filhdr.bsize;
  116.  
  117.     outf->ef_tsize = filhdr.tsize;
  118.     outf->ef_dsize = filhdr.dsize;
  119.     outf->ef_bsize = filhdr.bsize;
  120.     
  121.     (void) lseek(inf, offset + TEXTPOS, 0);
  122.     
  123.     size = outf->ef_tsize;
  124.     
  125.     while  (size > 1)  {
  126.         l = size > DBSIZE? DBSIZE: size;
  127.         if  (read(inf, (char *)inbuf, l) != l)
  128.             return    0;
  129.         l /= 2;
  130.         for  (i = 0;  i < l;  i++)  {
  131.             tstr.t_contents = inbuf[i];
  132.             (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
  133.         }
  134.         size -= l + l;
  135.     }
  136.     
  137.     /*
  138.      *    Extra one to cope with "etext".
  139.      */
  140.     
  141.     (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
  142.     return    1;
  143. }
  144.  
  145. /*
  146.  *    Same sort of thing for the data segment.
  147.  */
  148.  
  149. int    rdata(inf, offset, outf)
  150. int    inf;        /*  a.out file (possibly in library)  */
  151. long    offset;        /*  Offset from start of inf of a.out file  */
  152. ef_fid    outf;        /*  Output file descriptor  */
  153. {
  154.     d_entry        dstr;
  155.     struct    bhdr    filhdr;
  156.     register  long    size;
  157.     register  int    i, l;
  158.     unsigned  char    inbuf[DBSIZE];
  159.  
  160.     /*
  161.      *    Initialise fields in structure.
  162.      */
  163.     
  164.     dstr.d_type = D_BYTE;
  165.     dstr.d_reloc = R_NONE;
  166.     dstr.d_lng = 1;
  167.     dstr.d_relsymb = NULL;
  168.     dstr.d_reldisp = 0;
  169.     dstr.d_lab = NULL;
  170.     
  171.     /*
  172.      *    Read a.out header.
  173.      */
  174.     
  175.     (void) lseek(inf, offset, 0);
  176.  
  177.     if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
  178.         return    0;
  179.  
  180.     (void) lseek(inf, offset + DATAPOS, 0);
  181.     
  182.     size = outf->ef_dsize;
  183.     
  184.     while  (size > 0)  {
  185.         l = size > DBSIZE? DBSIZE: size;
  186.         if  (read(inf, (char *)inbuf, l) != l)
  187.             return    0;
  188.         for  (i = 0;  i < l;  i++)  {
  189.             dstr.d_contents = inbuf[i];
  190.             (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  191.         }
  192.         size -= l;
  193.     }
  194.     
  195.     /*
  196.      *    Repeat for BSS segment.
  197.      */
  198.  
  199.     dstr.d_contents = 0;
  200.     for  (size = outf->ef_bsize;  size > 0;  size--)
  201.         (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  202.     
  203.     /*
  204.      *    Extra one to cope with "end".
  205.      */
  206.     
  207.     (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  208.     return    1;
  209. }
  210.  
  211. /*
  212.  *    Process symbol table segment.
  213.  */
  214.  
  215. int    rsymb(inf, offset, dproc, outf)
  216. int    inf;        /*  a.out file (possibly in library)  */
  217. long    offset;        /*  Offset from start of inf of a.out file  */
  218. symbol    (*dproc)();
  219. register  ef_fid  outf;    /*  Output file descriptor  */
  220. {
  221.     register  symbol  csym;
  222.     struct    bhdr    filhdr;
  223.     struct    sym    isym;
  224.     register  long    size;
  225.     register  int    i, l;
  226.     char    inbuf[SYMLENGTH+1];
  227.  
  228.     /*
  229.      *    Read a.out header.
  230.      */
  231.     
  232.     (void) lseek(inf, offset, 0);
  233.  
  234.     if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
  235.         return    0;
  236.  
  237.     offset += SYMPOS;
  238.     size = filhdr.ssize;
  239.     if  (size <= 0)
  240.         return    1;
  241.  
  242.     /*
  243.      *    Guesstimate symbol table vector size.
  244.      */
  245.  
  246.     l = size / (sizeof(struct sym) + 4);
  247.     if  (l <= 0)
  248.         l = STINIT;
  249.  
  250.     outf->ef_stvec = (symbol *) malloc(l * sizeof(symbol));
  251.     if  (outf->ef_stvec == NULL)
  252.         nomem();
  253.  
  254.     outf->ef_stcnt = 0;
  255.     outf->ef_stmax = l;
  256.     
  257.     while  (size > sizeof(struct sym))  {
  258.         (void) lseek(inf, offset, 0);
  259.         if  (read(inf, (char *)&isym, sizeof(isym)) != sizeof(isym))
  260.             return    0;
  261.         size -= sizeof(isym);
  262.         l = SYMLENGTH;
  263.         if  (l > size)
  264.             l = size;
  265.         if  (read(inf, inbuf, l) != l)
  266.             return    0;
  267.         inbuf[l] = '\0';
  268.         for  (i = 0; inbuf[i] != '\0';  i++)
  269.             ;
  270.         size -= i + 1;
  271.         offset += sizeof(isym) + i + 1;
  272.         csym = (*dproc)(lookup(inbuf), isym.stype, isym.svalue, outf);
  273.         if  (outf->ef_stcnt >= outf->ef_stmax)
  274.             reallst(outf);
  275.         outf->ef_stvec[outf->ef_stcnt++] = csym;
  276.     }
  277.     return    1;
  278. }
  279.  
  280. /*
  281.  *    Process relocation stuff.  -1 error, 0 no relocation, 1 relocation.
  282.  */
  283.  
  284. int    rrel(inf, offset, outf)
  285. int    inf;        /*  a.out file (possibly in library)  */
  286. long    offset;        /*  Offset from start of inf of a.out file  */
  287. ef_fid    outf;        /*  Output file descriptor  */
  288. {
  289.     struct    bhdr    filhdr;
  290.     struct    reloc    crel;
  291.     t_entry    tstr;
  292.     d_entry    dstr;
  293.     register  long    size;
  294.     long    cont, pos;
  295.  
  296.     /*
  297.      *    Read a.out header.
  298.      */
  299.     
  300.     (void) lseek(inf, offset, 0);
  301.  
  302.     if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
  303.         return    -1;
  304.     if  (filhdr.rtsize <= 0  &&  filhdr.rdsize <= 0)
  305.         return    0;
  306.  
  307.     size  =  filhdr.rtsize;
  308.  
  309.     (void) lseek(inf, RTEXTPOS + offset, 0);
  310.     while  (size >= sizeof(struct reloc))  {
  311.         if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
  312.             return    -1;
  313.  
  314.         pos = crel.rpos + outf->ef_tbase;
  315.         gette(outf, pos, &tstr);
  316.         tstr.t_reloc = crel.rsize + 1;    /*  Fiddle!  YUK!!!  */
  317.         tstr.t_rdisp = crel.rdisp;
  318.         tstr.t_rptr = crel.rsegment;
  319.         if  (crel.rsegment == REXT)  {
  320.             if  (crel.rsymbol >= outf->ef_stcnt)
  321.                 return  -1;
  322.             tstr.t_relsymb = outf->ef_stvec[crel.rsymbol];
  323.             tstr.t_reldisp = gettw(outf, pos, (int)crel.rsize+1);
  324.         }
  325.         else  {
  326.             cont = gettw(outf, pos, (int)crel.rsize+1);
  327.             tstr.t_relsymb = getnsymb(outf, crel.rsegment, cont);
  328.         }
  329.         tstr.t_relsymb->s_used++;
  330.         putte(outf, pos, &tstr);
  331.         size -= sizeof(crel);
  332.     }
  333.     
  334.     /*
  335.      *    And now repeat all that for data relocations.
  336.      */
  337.     
  338.     size  =  filhdr.rdsize;
  339.     
  340.     (void) lseek(inf, RDATAPOS + offset, 0);
  341.     while  (size >= sizeof(struct reloc))  {
  342.         if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
  343.             return    -1;
  344.  
  345.         pos = crel.rpos + outf->ef_dbase;
  346.         getde(outf, pos, &dstr);
  347.         dstr.d_reloc = crel.rsize + 1;    /*  Fiddle!  YUK!!!  */
  348.         dstr.d_rptr = crel.rsegment;
  349.  
  350.         if  (crel.rsegment == REXT)  {
  351.             if  (crel.rsymbol >= outf->ef_stcnt)
  352.                 return  -1;
  353.             dstr.d_relsymb = outf->ef_stvec[crel.rsymbol];
  354.             dstr.d_reldisp = getdw(outf, pos, (int)crel.rsize+1);
  355.         }
  356.         else  {
  357.             cont = getdw(outf, pos, (int)crel.rsize+1);
  358.             dstr.d_relsymb = getnsymb(outf, crel.rsegment, cont);
  359.             if  (dstr.d_relsymb->s_type == TEXT)  {
  360.                 gette(outf, cont, &tstr);
  361.                 tstr.t_dref = 1;
  362.                 putte(outf, cont, &tstr);
  363.             }
  364.         }
  365.         switch  (crel.rsize)  {
  366.         default:
  367.             unimpl("Data byte relocation");
  368.             break;
  369.         case  RWORD:
  370.             unimpl("data word reloc");
  371.             dstr.d_type = D_WORD;
  372.             dstr.d_lng = 2;
  373.             setde(outf, pos+1, D_CONT, 1);
  374.             break;
  375.         case  RLONG:
  376.             dstr.d_type = D_ADDR;
  377.             dstr.d_lng = 4;
  378.             setde(outf, pos+1, D_CONT, 1);
  379.             setde(outf, pos+2, D_CONT, 1);
  380.             setde(outf, pos+3, D_CONT, 1);
  381.             break;
  382.         }
  383.         dstr.d_relsymb->s_used++;
  384.         putde(outf, pos, &dstr);
  385.         size -= sizeof(crel);
  386.     }
  387.     return 1;
  388. }
  389.  
  390. /*
  391.  *    Process a symbol.
  392.  */
  393.  
  394. symbol    dosymb(sy, type, val, fid)
  395. register  symbol  sy;
  396. int    type;
  397. long    val;
  398. ef_fid    fid;
  399. {
  400.     t_entry    tstr;
  401.     d_entry    dstr;
  402.     
  403.     if  (!sy->s_newsym)  {
  404.         if  (type & EXTERN)  {
  405.             (void) fprintf(stderr, "Duplicate symbol %s\n", sy->s_name);
  406.             exit(10);
  407.         }
  408.         if  (++sy->s_defs > nmods)
  409.             nmods = sy->s_defs;
  410.         sy = inventsymb("DUP");
  411.     }
  412.  
  413.     sy->s_value = val;
  414.     
  415.     switch  (type)  {
  416.     default:
  417.         return    NULL;
  418.         
  419.     case  EXTERN|UNDEF:
  420.         if  (val != 0)  {
  421.             sy->s_type = COMM;
  422.             addit(&comtab, sy);
  423.         }
  424.         else
  425.             sy->s_type = N_UNDF;
  426.         sy->s_glob = 1;
  427.         break;
  428.         
  429.     case  EXTERN|ABS:
  430.         sy->s_type = N_ABS;
  431.         sy->s_glob = 1;
  432.         addit(&abstab, sy);
  433.         break;
  434.         
  435.     case  ABS:
  436.         sy->s_type = N_ABS;
  437.         addit(&abstab, sy);
  438.         break;
  439.         
  440.     case  EXTERN|TEXT:
  441.     case  TEXT:
  442.         sy->s_type = N_TEXT;
  443.         gette(fid, val, &tstr);
  444.         tstr.t_bdest = 1;
  445.         if  (type & EXTERN)  {
  446.             tstr.t_gbdest = 1;
  447.             sy->s_glob = 1;
  448.         }
  449.         sy->s_link = tstr.t_lab;
  450.         tstr.t_lab = sy;
  451.         putte(fid, val, &tstr);
  452.         break;
  453.         
  454.     case  BSS:
  455.     case  EXTERN|BSS:
  456.         sy->s_type = N_BSS;
  457.         goto    datrest;
  458.     case  DATA:
  459.     case  EXTERN|DATA:
  460.         sy->s_type = N_DATA;
  461.     datrest:
  462.         getde(fid, val, &dstr);
  463.         if  (type & EXTERN)
  464.             sy->s_glob = 1;
  465.         sy->s_link = dstr.d_lab;
  466.         dstr.d_lab = sy;
  467.         putde(fid, val, &dstr);
  468.         break;
  469.     }
  470.     
  471.     sy->s_newsym = 0;
  472.     return    sy;
  473. }
  474.  
  475. /*
  476.  *    Process relocation stuff in putative library modules.
  477.  *    The main function of all this is to mark which bits of the text
  478.  *    not to look at as I compare the stuff.
  479.  *
  480.  *    As with "rrel", return -1 error, 0 no relocation, 1 relocation.
  481.  */
  482.  
  483. int    rrell1(inf, offset, outf)
  484. int    inf;        /*  a.out file (possibly in library)  */
  485. long    offset;        /*  Offset from start of inf of a.out file  */
  486. ef_fid    outf;        /*  Output file descriptor  */
  487. {
  488.     struct    bhdr    filhdr;
  489.     struct    reloc    crel;
  490.     t_entry    tstr;
  491.     register  long    size;
  492.     long    pos;
  493.  
  494.     /*
  495.      *    Read a.out header.
  496.      */
  497.     
  498.     (void) lseek(inf, offset, 0);
  499.  
  500.     if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
  501.         return    -1;
  502.     if  (filhdr.rtsize <= 0  &&  filhdr.rdsize <= 0)
  503.         return    0;
  504.  
  505.     size  =  filhdr.rtsize;
  506.  
  507.     (void) lseek(inf, RTEXTPOS + offset, 0);
  508.     while  (size >= sizeof(struct reloc))  {
  509.         if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
  510.             return    -1;
  511.  
  512.         pos = crel.rpos + outf->ef_tbase;
  513.         gette(outf, pos, &tstr);
  514.         tstr.t_reloc = crel.rsize + 1;    /*  Fiddle!  YUK!!!  */
  515.         tstr.t_rdisp = crel.rdisp;
  516.         tstr.t_rptr = crel.rsegment;
  517.         tstr.t_isrel = 1;
  518.         putte(outf, pos, &tstr);
  519.         if  (crel.rsize == RLONG)  {
  520.             gette(outf, pos+2, &tstr);
  521.             tstr.t_isrel = 1;
  522.             putte(outf, pos+2, &tstr);
  523.         }
  524.         size -= sizeof(crel);
  525.     }
  526.     
  527.     /*
  528.      *    Dont bother with data relocation at this stage. We'll
  529.      *    tie that up later.
  530.      */
  531.     
  532.     return 1;
  533. }
  534.  
  535. /*
  536.  *    Process a symbol in library file.  The extern variable trelpos gives
  537.  *    the place in the main file where the library module is relocated.
  538.  *    We don't know the data position until we do the final merge, perhaps
  539.  *    not even then.
  540.  */
  541.  
  542. symbol    dolsymb(sy, type, val, fid)
  543. register  symbol  sy;
  544. int    type;
  545. long    val;
  546. ef_fid    fid;
  547. {
  548.     t_entry    tstr;
  549.     
  550.     switch  (type)  {
  551.     default:
  552.         return    NULL;
  553.         
  554.     case  EXTERN|UNDEF:
  555.         if  (!sy->s_newsym)
  556.             return    sy;
  557.         sy->s_value = val;
  558.         if  (val != 0)  {
  559.             sy->s_type = COMM;
  560.             addit(&dreltab, sy);
  561.         }
  562.         else
  563.             sy->s_type = N_UNDF;
  564.         sy->s_glob = 1;
  565.         break;
  566.         
  567.     case  EXTERN|ABS:
  568.         if  (!sy->s_newsym)  {
  569.             if  (sy->s_type != N_ABS || sy->s_value != val)
  570.                 lclash("abs");
  571.         }
  572.         sy->s_type = N_ABS;
  573.         sy->s_value = val;
  574.         sy->s_glob = 1;
  575.         addit(&abstab, sy);
  576.         break;
  577.         
  578.     case  EXTERN|TEXT:
  579.         sy->s_type = N_TEXT;
  580.         val += trelpos - fid->ef_tbase;
  581.         if  (!sy->s_newsym)  {
  582.             if  (val != sy->s_value)
  583.                 lclash("tsym");
  584.             return    sy;
  585.         }
  586.         sy->s_value = val;
  587.         gette(&mainfile, val, &tstr);
  588.         tstr.t_bdest = 1;
  589.         tstr.t_gbdest = 1;
  590.         sy->s_glob = 1;
  591.         sy->s_link = tstr.t_lab;
  592.         tstr.t_lab = sy;
  593.         putte(&mainfile, val, &tstr);
  594.         break;
  595.  
  596.     case  EXTERN|BSS:
  597.         if  (!sy->s_newsym)
  598.             return    sy;
  599.         sy->s_type = N_BSS;
  600.         sy->s_value = val - fid->ef_bbase;
  601.         goto    datrest;
  602.  
  603.     case  EXTERN|DATA:
  604.         if  (!sy->s_newsym)
  605.             return    sy;
  606.         sy->s_type = N_DATA;
  607.         sy->s_value = val - fid->ef_dbase;
  608.     datrest:
  609.         sy->s_glob = 1;
  610.         addit(&dreltab, sy);
  611.         break;
  612.     }
  613.     
  614.     sy->s_newsym = 0;
  615.     return    sy;
  616. }
  617.  
  618. /*
  619.  *    Change definition of undefined symbol as we define it.
  620.  */
  621.  
  622. void    reassign(sy, val)
  623. register  symbol  sy;
  624. long    val;
  625. {
  626.     sy->s_value = val;
  627.  
  628.     if  (val < mainfile.ef_tbase)  {
  629.         sy->s_type = N_ABS;
  630.         addit(&abstab, sy);
  631.     }
  632.     else  if  (val < mainfile.ef_dbase)  {
  633.         t_entry    tstr;
  634.         
  635.         sy->s_type = N_TEXT;
  636.         gette(&mainfile, val, &tstr);
  637.         tstr.t_bdest = 1;
  638.         tstr.t_gbdest = 1;
  639.         sy->s_glob = 1;
  640.         sy->s_link = tstr.t_lab;
  641.         tstr.t_lab = sy;
  642.         putte(&mainfile, val, &tstr);
  643.     }
  644.     else  {
  645.         d_entry dstr;
  646.         
  647.         sy->s_type = val < mainfile.ef_bbase? N_DATA: N_BSS;
  648.         getde(&mainfile, val, &dstr);
  649.         sy->s_link = dstr.d_lab;
  650.         dstr.d_lab = sy;
  651.         putde(&mainfile, val, &dstr);
  652.     }
  653. }
  654.  
  655. /*
  656.  *    When we discover where bss or data come, reallocate the table.
  657.  */
  658.  
  659. void    zapdat(seg, inc)
  660. int    seg;
  661. long    inc;
  662. {
  663.     register  int    i;
  664.     register  symbol  csymb;
  665.     d_entry    dent;
  666.     
  667.     for  (i = 0;  i < dreltab.c_int;  i++) {
  668.         csymb = dreltab.c_symb[i];
  669.         if  (csymb->s_type != seg)
  670.             continue;
  671.         csymb->s_value += inc;
  672.         getde(&mainfile, csymb->s_value, &dent);
  673.         csymb->s_link = dent.d_lab;
  674.         dent.d_lab = csymb;
  675.         putde(&mainfile, csymb->s_value, &dent);
  676.     }
  677. }
  678.  
  679. /*
  680.  *    Process relocation stuff in library module which we are inserting.
  681.  *    Horrors if something goes wrong.
  682.  */
  683.  
  684. void    rrell2(inf, offset, outf)
  685. int    inf;        /*  a.out file (possibly in library)  */
  686. long    offset;        /*  Offset from start of inf of a.out file  */
  687. ef_fid    outf;        /*  Output file descriptor  */
  688. {
  689.     struct    bhdr    filhdr;
  690.     struct    reloc    crel;
  691.     t_entry    mtstr;
  692.     d_entry    mdstr;
  693.     register  long    size;
  694.     register  symbol  csymb;
  695.     long    pos, mpos, mval, lval;
  696.     int    dhere = 0;        /*  Mark whether bss done  */
  697.  
  698.     /*
  699.      *    Read a.out header.
  700.      */
  701.     
  702.     (void) lseek(inf, offset, 0);
  703.  
  704.     if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
  705.         return;
  706.     if  (filhdr.rtsize <= 0  &&  filhdr.rdsize <= 0)
  707.         return;
  708.  
  709.     size  =  filhdr.rtsize;
  710.  
  711.     (void) lseek(inf, RTEXTPOS + offset, 0);
  712.     for  (;  size >= sizeof(struct reloc);  size -= sizeof(crel))  {
  713.         if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
  714.             lclash("rd trel");
  715.  
  716.         pos = crel.rpos + outf->ef_tbase;
  717.         mpos = crel.rpos + trelpos;
  718.         gette(&mainfile, mpos, &mtstr);
  719.         lval = gettw(outf, pos, (int)crel.rsize+1);
  720.         mval = gettw(&mainfile, mpos, (int)crel.rsize+1);
  721.         
  722.         switch  (crel.rsegment)  {
  723.         case  RTEXT:
  724.             if  (lval + trelpos - outf->ef_tbase != mval)
  725.                 lclash("Trel");
  726.             continue;
  727.         case  RDATA:
  728.             if  (donedrel)  {
  729.                 if  (lval + drelpos - outf->ef_dbase != mval)
  730.                     lclash("Drel");
  731.             }
  732.             else  {
  733.                 donedrel++;
  734.                 drelpos = mval - lval + outf->ef_dbase;
  735.             }
  736.             continue;
  737.         case  RBSS:
  738.             if  (donebrel)  {
  739.                 if  (lval + brelpos - outf->ef_bbase != mval)
  740.                     lclash("brel");
  741.             }
  742.             else  {
  743.                 donebrel++;
  744.                 brelpos = mval - lval + outf->ef_bbase;
  745.             }
  746.             continue;
  747.         case  REXT:
  748.             if  (crel.rsymbol >= outf->ef_stcnt)
  749.                 lclash("Bad sy no");
  750.             csymb = outf->ef_stvec[crel.rsymbol];
  751.             if  (csymb == NULL)
  752.                 continue;
  753.             switch  (csymb->s_type)  {
  754.             case  N_UNDF:
  755.                 reassign(csymb, mval - lval);
  756.                 break;
  757.             case  N_ABS:
  758.                 if  (lval + csymb->s_value != mval)
  759.                     lclash("abs rel");
  760.                 break;
  761.             case  N_TEXT:
  762.                 if  (lval + csymb->s_value != mval)
  763.                     lclash("text rel");
  764.                 break;
  765.             case  N_DATA:
  766.                 if  (lval + csymb->s_value != mval)
  767.                     lclash("data rel");
  768.                 break;
  769.             case  N_BSS:
  770.                 if  (lval + csymb->s_value != mval)
  771.                     lclash("bss rel");
  772.                 break;
  773.             case  COMM:
  774.                 reassign(csymb, mval - lval);
  775.                 break;
  776.             }
  777.             mtstr.t_relsymb = csymb;
  778.             mtstr.t_reldisp = lval;
  779.             break;
  780.         }
  781.     }
  782.     
  783.     /*
  784.      *    Relocate data and bss if possible.
  785.      */
  786.     
  787.     if  (donebrel)  {
  788.         zapdat(N_BSS, brelpos);
  789.         dhere++;
  790.     }
  791.     
  792.     if  (!donedrel)
  793.         return;
  794.         
  795.  
  796.     zapdat(N_DATA, drelpos);
  797.     
  798.     /*
  799.      *    And now repeat all that for data relocations if possible
  800.      */
  801.     
  802.     size  =  filhdr.rdsize;
  803.     
  804.     (void) lseek(inf, RDATAPOS + offset, 0);
  805.     for  (;  size >= sizeof(struct reloc); size -= sizeof(crel))  {
  806.         if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
  807.             lclash("Rd drel");
  808.  
  809.         if  (crel.rsize != RLONG)
  810.             continue;
  811.  
  812.         pos = crel.rpos + outf->ef_dbase;
  813.         mpos = crel.rpos + drelpos;
  814.         getde(&mainfile, mpos, &mdstr);
  815.         lval = getdw(outf, pos, (int)crel.rsize+1);
  816.         mval = getdw(&mainfile, mpos, (int)crel.rsize+1);
  817.         switch  (crel.rsegment)  {
  818.         case  RTEXT:
  819.             if  (lval + trelpos - outf->ef_tbase != mval)
  820.                 lclash("Trel-d");
  821.             continue;
  822.         case  RDATA:
  823.             if  (lval + drelpos - outf->ef_dbase != mval)
  824.                 lclash("Drel-d");
  825.             continue;
  826.         case  RBSS:
  827.             if  (donebrel)  {
  828.                 if  (lval + brelpos - outf->ef_bbase != mval)
  829.                     lclash("brel");
  830.             }
  831.             else  {
  832.                 donebrel++;
  833.                 brelpos = mval - lval + outf->ef_bbase;
  834.             }
  835.             continue;
  836.         case  REXT:
  837.             if  (crel.rsymbol >= outf->ef_stcnt)
  838.                 lclash("Bad sy no");
  839.             csymb = outf->ef_stvec[crel.rsymbol];
  840.             if  (csymb == NULL)
  841.                 continue;
  842.             switch  (csymb->s_type)  {
  843.             case  N_UNDF:
  844.                 reassign(csymb, mval - lval);
  845.                 break;
  846.             case  N_ABS:
  847.                 if  (lval + csymb->s_value != mval)
  848.                     lclash("abs rel");
  849.                 break;
  850.             case  N_TEXT:
  851.                 if  (lval + csymb->s_value != mval)
  852.                     lclash("text rel");
  853.                 break;
  854.             case  N_DATA:
  855.                 if  (lval + csymb->s_value != mval)
  856.                     lclash("data rel");
  857.                 break;
  858.             case  N_BSS:
  859.                 if  (lval + csymb->s_value != mval)
  860.                     lclash("bss rel");
  861.                 break;
  862.             case  COMM:
  863.                 reassign(csymb, mval - lval);
  864.                 break;
  865.             }
  866.             mtstr.t_relsymb = csymb;
  867.             mtstr.t_reldisp = lval;
  868.             break;
  869.         }
  870.     }
  871.  
  872.     if  (dhere || !donebrel)
  873.         return;
  874.  
  875.     zapdat(N_BSS, brelpos);
  876. }
  877.