home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 303_01 / heur.c < prev    next >
Text File  |  1990-05-15  |  13KB  |  638 lines

  1. /*
  2.  *    SCCS:    %W%    %G%    %U%
  3.  *    Attempt to guess things about the file.
  4.  *
  5.  *EMACS_MODES:c
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <a.out.h>
  10. #ifdef    COFF
  11. #include <ldfcn.h>
  12. #endif    /*  COFF  */
  13. #include "unc.h"
  14.  
  15. #define    INITDAT    256
  16. #define    INCDAT    128
  17.  
  18. #define    STRSCNT    3
  19. #define    STRECNT    3
  20.  
  21. char    *malloc(), *realloc();
  22.  
  23. void    gette(), getde(), setde(), putte(), putde();
  24. void    nomem();
  25. long    getdw();
  26. symbol    inventsymb();
  27.  
  28. long    endt;
  29. ef_fids    mainfile;
  30.  
  31. /*
  32.  *    Talk about implemented things.....
  33.  */
  34.  
  35. void    unimpl(msg)
  36. char    *msg;
  37. {
  38.     (void) fprintf(stderr, "Warning: handling of \"%s\" not implemented\n", msg);
  39. }
  40.  
  41. /*
  42.  *    Return 1 if string char, otherwise 0.
  43.  */
  44.  
  45. int    possstr(x)
  46. unsigned  x;
  47. {
  48.     if  (x >= ' '  &&  x <= '~')
  49.         return    1;
  50.     if  (x == '\n'  ||  x == '\t')
  51.         return    1;
  52.     return    0;
  53. }
  54.  
  55. /*
  56.  *    Guess things about data files.
  57.  */
  58.  
  59. void    intudat(fid)
  60. ef_fid  fid;
  61. {
  62.     register  int    i, j;
  63.     int    lt, input, invcnt;
  64.     long    offs, soffs, endd;
  65.     d_entry    fdat;
  66.     unsigned  char    *inbuf;
  67.     int    ibsize;
  68.     
  69.     inbuf = (unsigned  char *)malloc(INITDAT);
  70.     if  (inbuf == NULL)
  71.         nomem();
  72.     ibsize = INITDAT;
  73.     
  74.     offs = fid->ef_dbase;
  75.     endd = fid->ef_bbase;
  76.  
  77.     while  (offs < endd)  {
  78.         getde(fid, offs, &fdat);
  79.         if  (fdat.d_type != D_BYTE)  {
  80.             offs += fdat.d_lng;
  81.             continue;
  82.         }
  83.         
  84.         /*
  85.          *    Looks like general data.  Read in as much as possible.
  86.          */
  87.         
  88.         input = 0;
  89.         soffs = offs;
  90.         do  {
  91.             if  (input >= ibsize)  {
  92.                 ibsize += INCDAT;
  93.                 inbuf = (unsigned  char *)
  94.                     realloc((char *)inbuf, (unsigned)ibsize);
  95.                 if  (inbuf == NULL)
  96.                     nomem();
  97.             }
  98.             inbuf[input++] = fdat.d_contents;
  99.             offs++;
  100.             if  (offs >= endd)
  101.                 break;
  102.             getde(fid, offs, &fdat);
  103.         }  while  (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
  104.         
  105.         /*
  106.          *    Now split up the data.
  107.          */
  108.         
  109.         for  (i = 0;  i < input;  )  {
  110.             
  111.             /*
  112.              *    Might be a string.
  113.              */
  114.             
  115.             if  (possstr(inbuf[i]))  {
  116.                 lt = input;
  117.                 if  (i + STRSCNT < lt)
  118.                     lt = i + STRSCNT;
  119.                 for  (j = i + 1;  j < lt;  j++)  {
  120.                     if  (inbuf[j] == '\0')
  121.                         break;
  122.                     if  (!possstr(inbuf[j]))
  123.                         goto  notstr;
  124.                 }
  125.                 
  126.                 /*
  127.                  *    Looks like a string then.
  128.                  */
  129.                 
  130.                 invcnt = 0;
  131.                 for  (j = i + 1; j < input;  j++)  {
  132.                     if  (inbuf[j] == '\0')  {
  133.                         j++;
  134.                         break;
  135.                     }
  136.                     if  (possstr(inbuf[j]))
  137.                         invcnt = 0;
  138.                     else  {
  139.                         invcnt++;
  140.                         if  (invcnt >= STRECNT)  {
  141.                             j -= invcnt - 1;
  142.                             break;
  143.                         }
  144.                     }
  145.                 }
  146.  
  147.                 setde(fid,
  148.                       soffs+i,
  149.                       (unsigned)(inbuf[j-1]=='\0'?D_ASCZ:D_ASC),
  150.                       j - i);
  151.                 for  (i++;  i < j;  i++)
  152.                     setde(fid, soffs+i, D_CONT, 1); 
  153.                 continue;
  154.             }
  155.  
  156. notstr:
  157.             /*
  158.              *    If on odd boundary, treat as a byte.
  159.              */
  160.             
  161.             if  ((soffs + i) & 1  ||  i + 1 >= input)  {
  162.                 setde(fid, soffs + i, D_BYTE, 1);
  163.                 i++;
  164.                 continue;
  165.             }
  166.  
  167.             /*
  168.              *    Treat as longs unless not enough.
  169.              */
  170.             
  171.             if  (i + 3 >= input)  {
  172.                 setde(fid, soffs + i, D_WORD, 2);
  173.                 setde(fid, soffs + i + 1, D_CONT, -1);
  174.                 i += 2;
  175.                 continue;
  176.             }
  177.  
  178.             /*
  179.              *    Treat as a long but mark changable.
  180.              */
  181.             
  182.             setde(fid, soffs + i, D_LONG, 4);
  183.             for  (j = 1;  j < 4;  j++)
  184.                 setde(fid, soffs + i + j, D_CONT, -j);
  185.             i += 4;
  186.         }
  187.     }
  188.     free((char *)inbuf);
  189.     
  190.     /*
  191.      *    Now zap bss segment.
  192.      */
  193.     
  194.     offs = fid->ef_bbase;
  195.     endd = fid->ef_end;
  196.  
  197.     while  (offs < endd)  {
  198.         getde(fid, offs, &fdat);
  199.         if  (fdat.d_type != D_BYTE)  {
  200.             offs += fdat.d_lng;
  201.             continue;
  202.         }
  203.  
  204.         soffs = offs;
  205.         do  {
  206.             offs++;
  207.             if  (offs >= endd)
  208.                 break;
  209.             getde(fid, offs, &fdat);
  210.         }  while  (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
  211.         
  212.         setde(fid, soffs, D_BYTE, (int)(offs-soffs));
  213.         for  (i = -1, soffs++;  soffs < offs; i--, soffs++)
  214.             setde(fid, soffs, D_CONT, i); 
  215.     }
  216. }
  217.  
  218. /*
  219.  *    For non relocatable files, try to identify address pointers in
  220.  *    the data.
  221.  */
  222.  
  223. void    inturdat(fid)
  224. ef_fid    fid;
  225. {
  226.     register  long    offs = fid->ef_dbase;
  227.     register  int    i;
  228.     register  symbol  ds;
  229.     long  endd = fid->ef_bbase;
  230.     long  cont;
  231.     d_entry    dent, refdent;
  232.  
  233.     while  (offs < endd)  {
  234.         getde(fid, offs, &dent);
  235.         if  (dent.d_type != D_LONG)
  236.             goto  endit;
  237.         cont = getdw(fid, offs, R_LONG);
  238.         if  (cont < fid->ef_dbase || cont > fid->ef_end)
  239.             goto  endit;
  240.         getde(fid, cont, &refdent);
  241.         if  (refdent.d_type == D_CONT)  {
  242.             d_entry    pdent;
  243.             int    siz;
  244.             
  245.             if  (refdent.d_lng >= 0)
  246.                 goto  endit;
  247.             getde(fid, cont+refdent.d_lng, &pdent);
  248.             i = -refdent.d_lng;
  249.             refdent.d_lng += pdent.d_lng;
  250.             pdent.d_lng = i;
  251.             if  (pdent.d_type == D_LONG  &&  i == 2)
  252.                 siz = D_WORD;
  253.             else
  254.                 siz = D_BYTE;
  255.             refdent.d_type = siz;
  256.             pdent.d_type = siz;
  257.             putde(fid, cont - i, &pdent);
  258.             for  (i = 1;  i < refdent.d_lng;  i++)
  259.                 setde(fid, cont+i, D_CONT, -i);
  260.         }
  261.         if  ((ds = refdent.d_lab) == NULL)  {
  262.             if  (cont >= fid->ef_bbase)  {
  263.                 ds = inventsymb("BS");
  264. #ifdef    COFF
  265.                 ds->s_type = S_BSS;
  266. #else    /*  !COFF  */
  267.                 ds->s_type = BSS;
  268. #endif    /*  !COFF  */
  269.             }
  270.             else  {
  271.                 ds = inventsymb("DS");
  272. #ifdef    COFF
  273.                 ds->s_type = S_DATA;
  274. #else    /*  !COFF  */
  275.                 ds->s_type = DATA;
  276. #endif    /*  !COFF  */
  277.             }
  278.             ds->s_value = cont;
  279.             refdent.d_lab = ds;
  280.             putde(fid, cont, &refdent);
  281.         }
  282.         else
  283.             ds->s_used++;
  284.         dent.d_type = D_ADDR;
  285.         dent.d_relsymb = ds;
  286.         dent.d_rptr = ds->s_type;
  287.         putde(fid, offs, &dent);
  288.         for  (i = 1;  i < 4;  i++)
  289.             setde(fid, offs+i, D_CONT, 1);
  290. endit:
  291.         offs += dent.d_lng;
  292.     }
  293. }
  294.  
  295. /*
  296.  *    Recursively follow through the code, stopping at unconditional
  297.  *    branches and invalid instructions.
  298.  */
  299.  
  300. void    follseq(pos)
  301. long    pos;
  302. {
  303.     t_entry    tent;
  304.     int    lng;
  305.     long    npos;
  306.  
  307.     while  (pos < endt)  {
  308.         gette(&mainfile, pos, &tent);
  309.         if  (tent.t_amap)    /*  Been here  */
  310.             return;
  311.         tent.t_amap = 1;
  312.         lng = findinst(&tent, pos);
  313.         npos = pos + lng*2;
  314.         if  (npos > endt)  {
  315.             tent.t_vins = 0;
  316.             tent.t_lng = 1;
  317.             tent.t_type = T_UNKNOWN;
  318.             lng = 0;
  319.             npos = endt;
  320.         }
  321.         putte(&mainfile, pos, &tent);
  322.         pos = npos;
  323.         
  324.         if  (lng <= 0)
  325.             return;
  326.  
  327.         switch  (tent.t_bchtyp)  {
  328.         case  T_UNBR:
  329.             if  (tent.t_relsymb == NULL)
  330.                 return;
  331.             pos = tent.t_relsymb->s_value;
  332.             continue;
  333.         case  T_JSR:
  334.             if  (tent.t_relsymb != NULL)
  335.                 follseq(tent.t_relsymb->s_value);
  336.             continue;
  337.         case  T_CONDBR:
  338.             follseq(tent.t_relsymb->s_value);
  339.         default:
  340.             continue;
  341.         }
  342.     }
  343. }
  344.             
  345.             
  346. /*
  347.  *    Try to work out things about text files.
  348.  */
  349.  
  350. void    intutext()
  351. {
  352.     long    pos;
  353.     t_entry    tent;
  354.     int    lng;
  355.     
  356.     endt = mainfile.ef_tbase + mainfile.ef_tsize;
  357.     pos = mainfile.ef_entry;
  358. nextv:
  359.     for  (;  pos < endt;)  {
  360.         gette(&mainfile, pos, &tent);
  361.         if  (!tent.t_amap && tent.t_vins)  {
  362.             follseq(pos);
  363.             pos += 2;
  364.             goto  nextiv;
  365.         }
  366.         pos += tent.t_lng * 2;
  367.         if  (tent.t_bchtyp == T_UNBR)
  368.             goto  nextiv;
  369.     }
  370.     goto    dorest;
  371. nextiv:
  372.     for  (;  pos < endt;  pos += 2)  {
  373.         gette(&mainfile, pos, &tent);
  374.         if  (tent.t_bdest)
  375.             goto  nextv;
  376.     }
  377. dorest:
  378.     /*
  379.      *    Deal with unmapped instructions.
  380.      */
  381.     
  382. #ifdef    COFF
  383.      for  (pos = mainfile.ef_tbase;  pos < endt;)  {
  384. #else    /*  !COFF  */
  385.     for  (pos = 0;  pos < endt;)  {
  386.     for  (pos = mainfile.ef_entry;  pos < endt;)  {
  387. #endif    /*  !COFF  */
  388.         gette(&mainfile, pos, &tent);
  389.         switch  (tent.t_type)  {
  390.         case  T_BEGIN:
  391.             pos += tent.t_lng * 2;
  392.             continue;
  393.         case  T_UNKNOWN:
  394.             if  (tent.t_vins)  {
  395.                 lng = findinst(&tent, pos);
  396.                 putte(&mainfile, pos, &tent);
  397.                 if  (lng > 0)  {
  398.                     pos += lng * 2;
  399.                     continue;
  400.                 }
  401.             }
  402.         default:
  403.             pos += 2;
  404.             continue;
  405.         }
  406.     }
  407. }
  408.  
  409. /*
  410.  *    Invent local symbols.
  411.  */
  412.  
  413. void    intlsym()
  414. {
  415.     long    bpos, epos, hiref, hipos;
  416.     unsigned  llnum;
  417.     t_entry    tent;
  418.     register  symbol  tl;
  419.     
  420.     endt = mainfile.ef_tbase + mainfile.ef_tsize;
  421.     epos = mainfile.ef_entry;
  422.     for  (;;)  {
  423.         bpos = epos;
  424.         hiref = bpos;
  425.         if  (epos >= endt)
  426.             return;
  427.         gette(&mainfile, epos, &tent);
  428.         epos += tent.t_lng * 2;
  429.         for  (;  epos < endt;)  {
  430.             gette(&mainfile, epos, &tent);
  431.             if  (tent.t_gbdest  ||  tent.t_dref)
  432.                 break;
  433.             if  (tent.t_reflo < bpos)
  434.                 break;
  435.             if  (tent.t_refhi > hiref)  {
  436.                 hiref = tent.t_refhi;
  437.                 hipos = epos;
  438.             }
  439.             epos += tent.t_lng * 2;
  440.         }
  441.         if  (hiref > epos)
  442.             epos = hipos;
  443.         llnum = 0;
  444.         for  (hipos = bpos;  hipos < epos;)  {
  445.             gette(&mainfile, hipos, &tent);
  446.             if  (!tent.t_gbdest && !tent.t_dref &&
  447.              tent.t_reflo >= bpos && tent.t_refhi < epos &&
  448.              (tl = tent.t_lab) != NULL)
  449.                 tl->s_lsymb = ++llnum;
  450.             hipos += tent.t_lng * 2;
  451.         }
  452.     }
  453. }
  454.  
  455. /*
  456.  *    Given the main file, and a possible candidate for matching in the
  457.  *    file, see where we can get.  Return text offset where match occured
  458.  *    or -1 if no match.
  459.  *    Given the main file, a possible candidate for matching in the
  460.  *    file and an offset, see if text matches.  Return 1 if matches,
  461.  *    or 0 if no match.
  462.  */
  463.  
  464. #define    BFSIZ    30        /*  Buffer size  */
  465.  
  466. long    matchup(mf, lf, startpos)
  467. ef_fid    mf, lf;
  468. int    matchup(mf, lf, startpos)
  469. register  ef_fid  mf, lf;
  470. long    startpos;
  471. {
  472.     register  int    i, lbcnt;
  473.     unsigned  short     lbufw[BFSIZ], startw;
  474.     register  int    i, matches = 0;
  475.     t_entry    ltent, mtent;
  476.     long    lfoffs, lfend, lcurr, bgpos, pos, startmain, endmain;
  477.     
  478.     lfoffs = lf->ef_tbase;
  479.     lfend = lfoffs + lf->ef_tsize;
  480.  
  481.     while  (lfoffs < lfend)  {
  482.         gette(lf, lfoffs, <ent);
  483.         if  (!ltent.t_isrel)
  484.             goto  gotstart;
  485.         lfoffs += sizeof(unsigned  short);
  486.     }
  487.     return    -1;    /*  Either empty or all relocatable  */
  488.     
  489. gotstart:
  490.     if  (lf->ef_tsize > mf->ef_tsize - startpos + mf->ef_tbase)
  491.         return    0;    /*  At end - can't fit  */
  492.  
  493.     /*
  494.      *    Read in a wodge of words from the library file, stopping
  495.      *    at the end of the file or if we hit a relocatable bit.
  496.      */
  497.     
  498.     lbcnt = 1;
  499.     startw = lbufw[0] = ltent.t_contents;
  500.     lcurr = lfoffs + 2;
  501.  
  502.     do  {
  503.         if  (lcurr >= lfend)
  504.             break;
  505.         gette(lf, lcurr, <ent);
  506.     for  (i = 0;  i < lf->ef_tsize;  i += 2)  {
  507.         gette(lf, lf->ef_tbase + i, <ent);
  508.         if  (ltent.t_isrel)
  509.             break;
  510.         lbufw[lbcnt++] = ltent.t_contents;
  511.         lcurr += 2;
  512.     }  while  (lbcnt < BFSIZ);
  513.             continue;
  514.         gette(mf, startpos + i, &mtent);
  515.         if  (mtent.t_contents != ltent.t_contents)
  516.             return    0;
  517.         matches++;
  518.     }
  519.     
  520.     /*
  521.      *    Having got that far, read the text file looking for the start
  522.      *    word.
  523.      *    Give up on zero length or all relocatable files.
  524.      */
  525.     
  526.     startmain = mf->ef_tbase + lfoffs - lf->ef_tbase;
  527.     endmain = startmain + mf->ef_tsize - lf->ef_tsize+lfoffs-lf->ef_tbase+2;
  528.     
  529.     bgpos = startpos + lfoffs - lf->ef_tbase;
  530.     
  531.     for  (pos = bgpos;  pos < endmain;  pos += 2)  {
  532.         gette(mf, pos, &mtent);
  533.         if  (mtent.t_contents != startw)
  534.             continue;
  535.         /*
  536.          *    Matched first word, try rest.
  537.          */
  538.     return    matches > 0;
  539. }
  540.  
  541.         for  (i = 1;  i < lbcnt;  i++)  {
  542.             gette(mf, pos+i+i, &mtent);
  543.             if  (mtent.t_contents != lbufw[i])
  544.                 goto  nomatch1;
  545.         }
  546. /*
  547.  *    Scan through main file looking for a match.
  548.  */
  549.  
  550.         pos += lbcnt*2;
  551.         for  (;  lcurr < lfend;  lcurr += 2, pos += 2)  {
  552.             gette(lf, lcurr, <ent);
  553.             if  (ltent.t_isrel)
  554.                 continue;
  555.             gette(mf, pos, &mtent);
  556.             if  (mtent.t_contents != ltent.t_contents)
  557.                 goto  nomatch1;
  558.         }
  559.         
  560.         /*
  561.          *    Hit the jackpot folks!
  562.          */
  563.         
  564.         return    pos - lf->ef_tsize;
  565. nomatch1:
  566.         ;
  567.     }
  568. long    findstart(mf, lf)
  569. register  ef_fid  mf, lf;
  570. {
  571.     register  long    res = mf->ef_tbase;
  572.     long    lim = mf->ef_tbase + mf->ef_tsize - lf->ef_tsize;
  573.     t_entry    tent;
  574.     
  575.     /*
  576.      *    Wrap around file. The next bit of code is the sort of
  577.      *    situation which annoys me where you have to choose between
  578.      *    having a routine with 200 parameters, or put all sorts of
  579.      *    fancy tests at each loop. The code, of course is identical.
  580.      */
  581.     
  582.     for  (pos = startmain;  pos < bgpos;  pos += 2)  {
  583.         gette(mf, pos, &mtent);
  584.         if  (mtent.t_contents != startw)
  585.             continue;
  586.         /*
  587.          *    Matched first word, try rest.
  588.          */
  589.         for  (i = 1;  i < lbcnt;  i++)  {
  590.             gette(mf, pos+i+i, &mtent);
  591.             if  (mtent.t_contents != lbufw[i])
  592.                 goto  nomatch2;
  593. restart:
  594.     for  (;  res <= lim;  res += 2)  {
  595.         gette(mf, res, &tent);
  596.         if  (tent.t_match != 0)  {
  597.             res += tent.t_match;
  598.             goto  restart;
  599.         }
  600.         pos += lbcnt*2;
  601.         for  (;  lcurr < lfend;  lcurr += 2, pos += 2)  {
  602.             gette(lf, lcurr, <ent);
  603.             if  (ltent.t_isrel)
  604.                 continue;
  605.             gette(mf, pos, &mtent);
  606.             if  (mtent.t_contents != ltent.t_contents)
  607.                 goto  nomatch2;
  608.         }
  609.         
  610.         /*
  611.          *    Hit the jackpot folks!
  612.          */
  613.         
  614.         return    pos - lf->ef_tsize;
  615. nomatch2:
  616.         ;
  617.         if  (matchup(mf, lf, res))
  618.             return    res;
  619.     }
  620.  
  621.     return    -1;
  622. }
  623.  
  624. /*
  625.  *    Mark the head of a matched module to save searching.
  626.  */
  627.  
  628. void    markmatch(mf, lf, pos)
  629. ef_fid    mf, lf;
  630. long    pos;
  631. {
  632.     t_entry    tent;
  633.     
  634.     gette(mf, pos, &tent);
  635.     tent.t_match = (unsigned) lf->ef_tsize;
  636.     putte(mf, pos, &tent);
  637. }
  638.