home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / 68kdisassem / part1 / heur.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  9.7 KB  |  528 lines

  1. /*
  2.  *    SCCS:    @(#)heur.c    1.2    11/2/84    14:17:46
  3.  *    Attempt to guess things about the file.
  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.  
  26. #include <stdio.h>
  27. #include <a.out.h>
  28. #include "unc.h"
  29.  
  30. #define    INITDAT    256
  31. #define    INCDAT    128
  32.  
  33. #define    STRSCNT    3
  34. #define    STRECNT    3
  35.  
  36. char    *malloc(), *realloc();
  37.  
  38. void    gette(), getde(), setde(), putte(), putde();
  39. void    nomem();
  40. long    getdw();
  41. symbol    inventsymb();
  42.  
  43. long    endt;
  44. ef_fids    mainfile;
  45.  
  46. /*
  47.  *    Talk about implemented things.....
  48.  */
  49.  
  50. void    unimpl(msg)
  51. char    *msg;
  52. {
  53.     (void) fprintf(stderr, "Warning: handling of \"%s\" not implemented\n", msg);
  54. }
  55.  
  56. /*
  57.  *    Return 1 if string char, otherwise 0.
  58.  */
  59.  
  60. int    possstr(x)
  61. unsigned  x;
  62. {
  63.     if  (x >= ' '  &&  x <= '~')
  64.         return    1;
  65.     if  (x == '\n'  ||  x == '\t')
  66.         return    1;
  67.     return    0;
  68. }
  69.  
  70. /*
  71.  *    Guess things about data files.
  72.  */
  73.  
  74. void    intudat(fid)
  75. ef_fid  fid;
  76. {
  77.     register  int    i, j;
  78.     int    lt, input, invcnt;
  79.     long    offs, soffs, endd;
  80.     d_entry    fdat;
  81.     unsigned  char    *inbuf;
  82.     int    ibsize;
  83.     
  84.     inbuf = (unsigned  char *)malloc(INITDAT);
  85.     if  (inbuf == NULL)
  86.         nomem();
  87.     ibsize = INITDAT;
  88.     
  89.     offs = fid->ef_dbase;
  90.     endd = fid->ef_bbase;
  91.  
  92.     while  (offs < endd)  {
  93.         getde(fid, offs, &fdat);
  94.         if  (fdat.d_type != D_BYTE)  {
  95.             offs += fdat.d_lng;
  96.             continue;
  97.         }
  98.         
  99.         /*
  100.          *    Looks like general data.  Read in as much as possible.
  101.          */
  102.         
  103.         input = 0;
  104.         soffs = offs;
  105.         do  {
  106.             if  (input >= ibsize)  {
  107.                 ibsize += INCDAT;
  108.                 inbuf = (unsigned  char *)
  109.                     realloc((char *)inbuf, (unsigned)ibsize);
  110.                 if  (inbuf == NULL)
  111.                     nomem();
  112.             }
  113.             inbuf[input++] = fdat.d_contents;
  114.             offs++;
  115.             if  (offs >= endd)
  116.                 break;
  117.             getde(fid, offs, &fdat);
  118.         }  while  (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
  119.         
  120.         /*
  121.          *    Now split up the data.
  122.          */
  123.         
  124.         for  (i = 0;  i < input;  )  {
  125.             
  126.             /*
  127.              *    Might be a string.
  128.              */
  129.             
  130.             if  (possstr(inbuf[i]))  {
  131.                 lt = input;
  132.                 if  (i + STRSCNT < lt)
  133.                     lt = i + STRSCNT;
  134.                 for  (j = i + 1;  j < lt;  j++)  {
  135.                     if  (inbuf[j] == '\0')
  136.                         break;
  137.                     if  (!possstr(inbuf[j]))
  138.                         goto  notstr;
  139.                 }
  140.                 
  141.                 /*
  142.                  *    Looks like a string then.
  143.                  */
  144.                 
  145.                 invcnt = 0;
  146.                 for  (j = i + 1; j < input;  j++)  {
  147.                     if  (inbuf[j] == '\0')  {
  148.                         j++;
  149.                         break;
  150.                     }
  151.                     if  (possstr(inbuf[j]))
  152.                         invcnt = 0;
  153.                     else  {
  154.                         invcnt++;
  155.                         if  (invcnt >= STRECNT)  {
  156.                             j -= invcnt - 1;
  157.                             break;
  158.                         }
  159.                     }
  160.                 }
  161.  
  162.                 setde(fid,
  163.                       soffs+i,
  164.                       (unsigned)(inbuf[j-1]=='\0'?D_ASCZ:D_ASC),
  165.                       j - i);
  166.                 for  (i++;  i < j;  i++)
  167.                     setde(fid, soffs+i, D_CONT, 1); 
  168.                 continue;
  169.             }
  170.  
  171. notstr:
  172.             /*
  173.              *    If on odd boundary, treat as a byte.
  174.              */
  175.             
  176.             if  ((soffs + i) & 1  ||  i + 1 >= input)  {
  177.                 setde(fid, soffs + i, D_BYTE, 1);
  178.                 i++;
  179.                 continue;
  180.             }
  181.  
  182.             /*
  183.              *    Treat as longs unless not enough.
  184.              */
  185.             
  186.             if  (i + 3 >= input)  {
  187.                 setde(fid, soffs + i, D_WORD, 2);
  188.                 setde(fid, soffs + i + 1, D_CONT, -1);
  189.                 i += 2;
  190.                 continue;
  191.             }
  192.  
  193.             /*
  194.              *    Treat as a long but mark changable.
  195.              */
  196.             
  197.             setde(fid, soffs + i, D_LONG, 4);
  198.             for  (j = 1;  j < 4;  j++)
  199.                 setde(fid, soffs + i + j, D_CONT, -j);
  200.             i += 4;
  201.         }
  202.     }
  203.     free((char *)inbuf);
  204.     
  205.     /*
  206.      *    Now zap bss segment.
  207.      */
  208.     
  209.     offs = fid->ef_bbase;
  210.     endd = fid->ef_end;
  211.  
  212.     while  (offs < endd)  {
  213.         getde(fid, offs, &fdat);
  214.         if  (fdat.d_type != D_BYTE)  {
  215.             offs += fdat.d_lng;
  216.             continue;
  217.         }
  218.  
  219.         soffs = offs;
  220.         do  {
  221.             offs++;
  222.             if  (offs >= endd)
  223.                 break;
  224.             getde(fid, offs, &fdat);
  225.         }  while  (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
  226.         
  227.         setde(fid, soffs, D_BYTE, (int)(offs-soffs));
  228.         for  (i = -1, soffs++;  soffs < offs; i--, soffs++)
  229.             setde(fid, soffs, D_CONT, i); 
  230.     }
  231. }
  232.  
  233. /*
  234.  *    For non relocatable files, try to identify address pointers in
  235.  *    the data.
  236.  */
  237.  
  238. void    inturdat(fid)
  239. ef_fid    fid;
  240. {
  241.     register  long    offs = fid->ef_dbase;
  242.     register  int    i;
  243.     register  symbol  ds;
  244.     long  endd = fid->ef_bbase;
  245.     long  cont;
  246.     d_entry    dent, refdent;
  247.  
  248.     while  (offs < endd)  {
  249.         getde(fid, offs, &dent);
  250.         if  (dent.d_type != D_LONG)
  251.             goto  endit;
  252.         cont = getdw(fid, offs, R_LONG);
  253.         if  (cont < fid->ef_dbase || cont > fid->ef_end)
  254.             goto  endit;
  255.         getde(fid, cont, &refdent);
  256.         if  (refdent.d_type == D_CONT)  {
  257.             d_entry    pdent;
  258.             int    siz;
  259.             
  260.             if  (refdent.d_lng >= 0)
  261.                 goto  endit;
  262.             getde(fid, cont+refdent.d_lng, &pdent);
  263.             i = -refdent.d_lng;
  264.             refdent.d_lng += pdent.d_lng;
  265.             pdent.d_lng = i;
  266.             if  (pdent.d_type == D_LONG  &&  i == 2)
  267.                 siz = D_WORD;
  268.             else
  269.                 siz = D_BYTE;
  270.             refdent.d_type = siz;
  271.             pdent.d_type = siz;
  272.             putde(fid, cont - i, &pdent);
  273.             for  (i = 1;  i < refdent.d_lng;  i++)
  274.                 setde(fid, cont+i, D_CONT, -i);
  275.         }
  276.         if  ((ds = refdent.d_lab) == NULL)  {
  277.             if  (cont >= fid->ef_bbase)  {
  278.                 ds = inventsymb("BS");
  279.                 ds->s_type = BSS;
  280.             }
  281.             else  {
  282.                 ds = inventsymb("DS");
  283.                 ds->s_type = DATA;
  284.             }
  285.             ds->s_value = cont;
  286.             refdent.d_lab = ds;
  287.             putde(fid, cont, &refdent);
  288.         }
  289.         else
  290.             ds->s_used++;
  291.         dent.d_type = D_ADDR;
  292.         dent.d_relsymb = ds;
  293.         dent.d_rptr = ds->s_type;
  294.         putde(fid, offs, &dent);
  295.         for  (i = 1;  i < 4;  i++)
  296.             setde(fid, offs+i, D_CONT, 1);
  297. endit:
  298.         offs += dent.d_lng;
  299.     }
  300. }
  301.  
  302. /*
  303.  *    Recursively follow through the code, stopping at unconditional
  304.  *    branches and invalid instructions.
  305.  */
  306.  
  307. void    follseq(pos)
  308. long    pos;
  309. {
  310.     t_entry    tent;
  311.     int    lng;
  312.     long    npos;
  313.  
  314.     while  (pos < endt)  {
  315.         gette(&mainfile, pos, &tent);
  316.         if  (tent.t_amap)    /*  Been here  */
  317.             return;
  318.         tent.t_amap = 1;
  319.         lng = findinst(&tent, pos);
  320.         npos = pos + lng*2;
  321.         if  (npos > endt)  {
  322.             tent.t_vins = 0;
  323.             tent.t_lng = 1;
  324.             tent.t_type = T_UNKNOWN;
  325.             lng = 0;
  326.             npos = endt;
  327.         }
  328.         putte(&mainfile, pos, &tent);
  329.         pos = npos;
  330.         
  331.         if  (lng <= 0)
  332.             return;
  333.  
  334.         switch  (tent.t_bchtyp)  {
  335.         case  T_UNBR:
  336.             if  (tent.t_relsymb == NULL)
  337.                 return;
  338.             pos = tent.t_relsymb->s_value;
  339.             continue;
  340.         case  T_JSR:
  341.             if  (tent.t_relsymb != NULL)
  342.                 follseq(tent.t_relsymb->s_value);
  343.             continue;
  344.         case  T_CONDBR:
  345.             follseq(tent.t_relsymb->s_value);
  346.         default:
  347.             continue;
  348.         }
  349.     }
  350. }
  351.             
  352.             
  353. /*
  354.  *    Try to work out things about text files.
  355.  */
  356.  
  357. void    intutext()
  358. {
  359.     long    pos;
  360.     t_entry    tent;
  361.     int    lng;
  362.     
  363.     endt = mainfile.ef_tbase + mainfile.ef_tsize;
  364.     pos = mainfile.ef_entry;
  365. nextv:
  366.     for  (;  pos < endt;)  {
  367.         gette(&mainfile, pos, &tent);
  368.         if  (!tent.t_amap && tent.t_vins)  {
  369.             follseq(pos);
  370.             pos += 2;
  371.             goto  nextiv;
  372.         }
  373.         pos += tent.t_lng * 2;
  374.         if  (tent.t_bchtyp == T_UNBR)
  375.             goto  nextiv;
  376.     }
  377.     goto    dorest;
  378. nextiv:
  379.     for  (;  pos < endt;  pos += 2)  {
  380.         gette(&mainfile, pos, &tent);
  381.         if  (tent.t_bdest)
  382.             goto  nextv;
  383.     }
  384. dorest:
  385.     /*
  386.      *    Deal with unmapped instructions.
  387.      */
  388.     
  389.     for  (pos = 0;  pos < endt;)  {
  390.         gette(&mainfile, pos, &tent);
  391.         switch  (tent.t_type)  {
  392.         case  T_BEGIN:
  393.             pos += tent.t_lng * 2;
  394.             continue;
  395.         case  T_UNKNOWN:
  396.             if  (tent.t_vins)  {
  397.                 lng = findinst(&tent, pos);
  398.                 putte(&mainfile, pos, &tent);
  399.                 if  (lng > 0)  {
  400.                     pos += lng * 2;
  401.                     continue;
  402.                 }
  403.             }
  404.         default:
  405.             pos += 2;
  406.             continue;
  407.         }
  408.     }
  409. }
  410.  
  411. /*
  412.  *    Invent local symbols.
  413.  */
  414.  
  415. void    intlsym()
  416. {
  417.     long    bpos, epos, hiref, hipos;
  418.     unsigned  llnum;
  419.     t_entry    tent;
  420.     register  symbol  tl;
  421.     
  422.     endt = mainfile.ef_tbase + mainfile.ef_tsize;
  423.     epos = mainfile.ef_entry;
  424.     for  (;;)  {
  425.         bpos = epos;
  426.         hiref = bpos;
  427.         if  (epos >= endt)
  428.             return;
  429.         gette(&mainfile, epos, &tent);
  430.         epos += tent.t_lng * 2;
  431.         for  (;  epos < endt;)  {
  432.             gette(&mainfile, epos, &tent);
  433.             if  (tent.t_gbdest  ||  tent.t_dref)
  434.                 break;
  435.             if  (tent.t_reflo < bpos)
  436.                 break;
  437.             if  (tent.t_refhi > hiref)  {
  438.                 hiref = tent.t_refhi;
  439.                 hipos = epos;
  440.             }
  441.             epos += tent.t_lng * 2;
  442.         }
  443.         if  (hiref > epos)
  444.             epos = hipos;
  445.         llnum = 0;
  446.         for  (hipos = bpos;  hipos < epos;)  {
  447.             gette(&mainfile, hipos, &tent);
  448.             if  (!tent.t_gbdest && !tent.t_dref &&
  449.              tent.t_reflo >= bpos && tent.t_refhi < epos &&
  450.              (tl = tent.t_lab) != NULL)
  451.                 tl->s_lsymb = ++llnum;
  452.             hipos += tent.t_lng * 2;
  453.         }
  454.     }
  455. }
  456.  
  457. /*
  458.  *    Given the main file, a possible candidate for matching in the
  459.  *    file and an offset, see if text matches.  Return 1 if matches,
  460.  *    or 0 if no match.
  461.  */
  462.  
  463. int    matchup(mf, lf, startpos)
  464. register  ef_fid  mf, lf;
  465. long    startpos;
  466. {
  467.     register  int    i, matches = 0;
  468.     t_entry    ltent, mtent;
  469.  
  470.     if  (lf->ef_tsize > mf->ef_tsize - startpos + mf->ef_tbase)
  471.         return    0;    /*  At end - can't fit  */
  472.  
  473.     for  (i = 0;  i < lf->ef_tsize;  i += 2)  {
  474.         gette(lf, lf->ef_tbase + i, <ent);
  475.         if  (ltent.t_isrel)
  476.             continue;
  477.         gette(mf, startpos + i, &mtent);
  478.         if  (mtent.t_contents != ltent.t_contents)
  479.             return    0;
  480.         matches++;
  481.     }
  482.     
  483.     /*
  484.      *    Give up on zero length or all relocatable files.
  485.      */
  486.     
  487.     return    matches > 0;
  488. }
  489.  
  490. /*
  491.  *    Scan through main file looking for a match.
  492.  */
  493.  
  494. long    findstart(mf, lf)
  495. register  ef_fid  mf, lf;
  496. {
  497.     register  long    res = mf->ef_tbase;
  498.     long    lim = mf->ef_tbase + mf->ef_tsize - lf->ef_tsize;
  499.     t_entry    tent;
  500.     
  501. restart:
  502.     for  (;  res <= lim;  res += 2)  {
  503.         gette(mf, res, &tent);
  504.         if  (tent.t_match != 0)  {
  505.             res += tent.t_match;
  506.             goto  restart;
  507.         }
  508.         if  (matchup(mf, lf, res))
  509.             return    res;
  510.     }
  511.     return    -1;
  512. }
  513.  
  514. /*
  515.  *    Mark the head of a matched module to save searching.
  516.  */
  517.  
  518. void    markmatch(mf, lf, pos)
  519. ef_fid    mf, lf;
  520. long    pos;
  521. {
  522.     t_entry    tent;
  523.     
  524.     gette(mf, pos, &tent);
  525.     tent.t_match = (unsigned) lf->ef_tsize;
  526.     putte(mf, pos, &tent);
  527. }
  528.