home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / dis88 / part01 / dismain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-23  |  17.0 KB  |  625 lines

  1. static char *sccsid =
  2.    "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01";
  3.  
  4.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  5.   *                                                         *
  6.   *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
  7.   *                                                         *
  8.   * Permission to copy and  redistribute is hereby granted, *
  9.   * provided full source code,  with all copyright notices, *
  10.   * accompanies any redistribution.                         *
  11.   *                                                         *
  12.   * This file  contains  the source  code for the  machine- *
  13.   * independent  portions of a disassembler  program to run *
  14.   * in a Unix (System III) environment.  It expects, as its *
  15.   * input, a file in standard a.out format, optionally con- *
  16.   * taining symbol table information.  If a symbol table is *
  17.   * present, it will be used in the disassembly; otherwise, *
  18.   * all address references will be literal (absolute).      *
  19.   *                                                         *
  20.   * The disassembler  program was originally written for an *
  21.   * Intel 8088 CPU.  However, all details of the actual CPU *
  22.   * architecture are hidden in three machine-specific files *
  23.   * named  distabs.c,  dishand.c,  and disfp.c  (the latter *
  24.   * file is specific to the 8087 numeric co-processor). The *
  25.   * code in this file is generic,  and should require mini- *
  26.   * mal revision if a different CPU is to be targeted. If a *
  27.   * different version of Unix is to be targeted, changes to *
  28.   * this file may be necessary, and if a completely differ- *
  29.   * ent OS is to be targeted, all bets are off.             *
  30.   *                                                         *
  31.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  32.  
  33. #include "dis.h"              /* Disassembler declarations  */
  34.  
  35. extern char *release;         /* Contains release string    */
  36.  
  37. static char *IFILE = NULL;    /* Points to input file name  */
  38.  
  39. static char *OFILE = NULL;    /* Points to output file name */
  40.  
  41. static char *PRG;             /* Name of invoking program   */
  42.  
  43. static unsigned long zcount;  /* Consecutive "0" byte count */
  44.  
  45. int objflg = 0;               /* Flag: output object bytes  */
  46.  
  47. #if unix && i8086 && ibmpc    /* Set the CPU identifier     */
  48. static int cpuid = 1;
  49. #else
  50. static int cpuid = 0;
  51. #endif
  52.  
  53.  /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */
  54.  
  55. static void
  56. usage(s)
  57.    register char *s;
  58. {
  59.    fprintf(stderr,"\07usage: %s [-o] ifile [ofile]\n",s);
  60.    exit(-1);
  61. }
  62.  
  63. static void
  64. fatal(s,t)
  65.    register char *s, *t;
  66. {
  67.    fprintf(stderr,"\07%s: %s\n",s,t);
  68.    exit(-1);
  69. }
  70.  
  71. static void
  72. zdump(beg)
  73.    unsigned long beg;
  74. {
  75.    beg = PC - beg;
  76.    if (beg > 1L)
  77.       printf("\t.zerow\t%ld\n",(beg >> 1));
  78.    if (beg & 1L)
  79.       printf("\t.byte\t0\n");
  80. }
  81.  
  82. static char *
  83. invoker(s)
  84.    register char *s;
  85. {
  86.    extern int strlen();
  87.    register int k;
  88.  
  89.    k = strlen(s);
  90.  
  91.    while (k--)
  92.       if (s[k] == '/')
  93.          {
  94.          s += k;
  95.          ++s;
  96.          break;
  97.          }
  98.  
  99.    return (s);
  100. }
  101.  
  102.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  103.   *                                                         *
  104.   * This rather tricky routine supports the disdata() func- *
  105.   * tion.  Its job is to output the code for a sequence  of *
  106.   * data bytes whenever the object buffer is full,  or when *
  107.   * a symbolic label is to be output. However, it must also *
  108.   * keep track of  consecutive  zero words so that  lengthy *
  109.   * stretches of null data can be  compressed by the use of *
  110.   * an  appropriate  assembler  pseudo-op.  It does this by *
  111.   * setting and testing a file-wide  flag which counts suc- *
  112.   * cessive full buffers of null data. The function returns *
  113.   * a logical  TRUE value if it outputs  anything,  logical *
  114.   * FALSE otherwise.  (This enables disdata()  to determine *
  115.   * whether to output a new  synthetic  label when there is *
  116.   * no symbol table.)                                       *
  117.   *                                                         *
  118.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  119.  
  120. static int
  121. objdump(c)
  122.  
  123.    register char *c;
  124.  
  125. {/* * * * * * * * * * START OF  objdump() * * * * * * * * * */
  126.  
  127.    register int k;
  128.    int retval = 0;
  129.  
  130.    if (objptr == OBJMAX)
  131.       {
  132.       for (k = 0; k < OBJMAX; ++k)
  133.          if (objbuf[k])
  134.             break;
  135.       if (k == OBJMAX)
  136.          {
  137.          zcount += k;
  138.          objptr = 0;
  139.          if (c == NULL)
  140.             return (retval);
  141.          }
  142.       }
  143.  
  144.    if (zcount)
  145.       {
  146.       printf("\t.zerow\t%ld\n",(zcount >> 1));
  147.       ++retval;
  148.       zcount = 0L;
  149.       }
  150.  
  151.    if (objptr)
  152.       {
  153.       printf("\t.byte\t");
  154.       ++retval;
  155.       }
  156.    else
  157.       return (retval);
  158.  
  159.    for (k = 0; k < objptr; ++k)
  160.       {
  161.       printf("0x%02.2x",objbuf[k]);
  162.       if (k < (objptr - 1))
  163.          putchar(',');
  164.       else
  165.          putchar('\n');
  166.       }
  167.  
  168.    objptr = 0;
  169.  
  170.    return (retval);
  171.  
  172. }/* * * * * * * * * *  END OF  objdump()  * * * * * * * * * */
  173.  
  174.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  175.   *                                                         *
  176.   * This  routine,  called  at the  beginning  of the input *
  177.   * cycle for each object byte,  and before any interpreta- *
  178.   * tion is  attempted,  searches  the symbol table for any *
  179.   * symbolic  name with a value  corresponding  to the cur- *
  180.   * rent PC and a type  corresponding  to the segment  type *
  181.   * (i.e.,  text, data, or bss) specified by the function's *
  182.   * argument. If any such name is found, a pointer to it is *
  183.   * returned; otherwise, a NULL pointer is returned.        *
  184.   *                                                         *
  185.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  186.  
  187. static char *
  188. getlab(type)
  189.  
  190.    register int type;
  191.  
  192. {/* * * * * * * * * *  START OF getlab()  * * * * * * * * * */
  193.  
  194.    register int k;
  195.    static char b[32], c[10];
  196.  
  197.    if (symptr < 0)
  198.       if ((type == N_TEXT)
  199.        || ((type == N_DATA) && ( ! objptr ) && ( ! zcount )))
  200.          {
  201.          if (type == N_TEXT)
  202.             sprintf(b,"T%05.5lx:",PC);
  203.          else
  204.             sprintf(b,"D%05.5lx:",PC);
  205.          return (b);
  206.          }
  207.       else
  208.          return (NULL);
  209.  
  210.    for (k = 0; k <= symptr; ++k)
  211.       if ((symtab[k].n_value == PC)
  212.        && ((symtab[k].n_sclass & N_SECT) == type))
  213.          {
  214.          sprintf(b,"%s:\n",getnam(k));
  215.          if (objflg && (type != N_TEXT))
  216.             sprintf(c,"| %05.5lx\n",PC);
  217.          strcat(b,c);
  218.          return (b);
  219.          }
  220.  
  221.    return (NULL);
  222.  
  223. }/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */
  224.  
  225.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  226.   *                                                         *
  227.   * This routine  performs a preliminary scan of the symbol *
  228.   * table,  before disassembly begins, and outputs declara- *
  229.   * tions of globals and constants.                         *
  230.   *                                                         *
  231.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  232.  
  233. static void
  234. prolog()
  235.  
  236. {/* * * * * * * * * *  START OF prolog()  * * * * * * * * * */
  237.  
  238.    register int j, flag;
  239.  
  240.    if (symptr < 0)
  241.       return;
  242.  
  243.    for (j = flag = 0; j <= symptr; ++j)
  244.       if ((symtab[j].n_sclass & N_CLASS) == C_EXT)
  245.          if (((symtab[j].n_sclass & N_SECT) > N_UNDF)
  246.           && ((symtab[j].n_sclass & N_SECT) < N_COMM))
  247.             {
  248.             char *c = getnam(j);
  249.             printf("\t.globl\t%s",c);
  250.             if (++flag == 1)
  251.                {
  252.                putchar('\t');
  253.                if (strlen(c) < 8)
  254.                   putchar('\t');
  255.                printf("| Internal global\n");
  256.                }
  257.             else
  258.                putchar('\n');
  259.             }
  260.          else
  261.             if (symtab[j].n_value)
  262.                {
  263.                char *c = getnam(j);
  264.                printf("\t.comm\t%s,0x%08.8lx",c,
  265.                 symtab[j].n_value);
  266.                if (++flag == 1)
  267.                   printf("\t| Internal global\n");
  268.                else
  269.                   putchar('\n');
  270.                }
  271.  
  272.    if (flag)
  273.       putchar('\n');
  274.  
  275.    for (j = flag = 0; j <= relptr; ++j)
  276.       if (relo[j].r_symndx < S_BSS)
  277.          {
  278.          char *c = getnam(relo[j].r_symndx);
  279.          ++flag;
  280.          printf("\t.globl\t%s",c);
  281.          putchar('\t');
  282.          if (strlen(c) < 8)
  283.             putchar('\t');
  284.          printf("| Undef: %05.5lx\n",relo[j].r_vaddr);
  285.          }
  286.  
  287.    if (flag)
  288.       putchar('\n');
  289.  
  290.    for (j = flag = 0; j <= symptr; ++j)
  291.       if ((symtab[j].n_sclass & N_SECT) == N_ABS)
  292.          {
  293.          char *c = getnam(j);
  294.          printf("%s=0x%08.8lx",c,symtab[j].n_value);
  295.          if (++flag == 1)
  296.             {
  297.             printf("\t\t");
  298.             if (strlen(c) < 5)
  299.                putchar('\t');
  300.             printf("| Literal\n");
  301.             }
  302.          else
  303.             putchar('\n');
  304.          }
  305.  
  306.    if (flag)
  307.       putchar('\n');
  308.  
  309. }/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */
  310.  
  311.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  312.   *                                                         *
  313.   * This function is  responsible  for  disassembly  of the *
  314.   * object file's text segment.                             *
  315.   *                                                         *
  316.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  317.  
  318. static void
  319. distext()
  320.  
  321. {/* * * * * * * * * * START OF  distext() * * * * * * * * * */
  322.  
  323.    char *c;
  324.    register int j;
  325.    register void (*f)();
  326.  
  327.    for (j = 0; j < (int)(HDR.a_hdrlen); ++j)
  328.       getchar();
  329.  
  330.    printf("| %s, %s\n\n",PRG,release);
  331.  
  332.    printf("| @(");
  333.  
  334.    printf("#)\tDisassembly of %s",IFILE);
  335.  
  336.    if (symptr < 0)
  337.       printf(" (no symbols)\n\n");
  338.    else
  339.       printf("\n\n");
  340.  
  341.    if (HDR.a_flags & A_EXEC)
  342.       printf("| File is executable\n\n");
  343.  
  344.    if (HDR.a_flags & A_SEP)
  345.       {
  346.       printf("| File has split I/D space, and may have\n");
  347.       printf("| extraneous instructions in text segment\n\n");
  348.       }
  349.  
  350.    prolog();
  351.  
  352.    printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  353.     PC,HDR.a_text);
  354.  
  355.    segflg = 0;
  356.  
  357.    for (PC = 0L; PC < HDR.a_text; ++PC)
  358.       {
  359.       j = getchar() & 0xff;
  360.       if ((j == 0) && ((PC + 1L) == HDR.a_text))
  361.          {
  362.          ++PC;
  363.          break;
  364.          }
  365.       if ((c = getlab(N_TEXT)) != NULL)
  366.          printf("%s",c);
  367.       f = optab[j].func;
  368.       (*f)(j);
  369.       }
  370.  
  371. }/* * * * * * * * * *  END OF  distext()  * * * * * * * * * */
  372.  
  373.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  374.   *                                                         *
  375.   * This  function  handles the object file's data segment. *
  376.   * There is no good way to disassemble a data segment, be- *
  377.   * cause it is  impossible  to tell,  from the object code *
  378.   * alone,  what each data byte refers to.  If it refers to *
  379.   * an external symbol,  the reference can be resolved from *
  380.   * the relocation table, if there is one.  However,  if it *
  381.   * refers to a static symbol,  it cannot be  distinguished *
  382.   * from numeric, character, or other pointer data. In some *
  383.   * cases,  one might make a semi-educated  guess as to the *
  384.   * nature of the data,  but such  guesses  are  inherently *
  385.   * haphazard,  and they are  bound to be wrong a good por- *
  386.   * tion of the time.  Consequently,  the data  segment  is *
  387.   * disassembled  as a byte  stream,  which will satisfy no *
  388.   * one but which, at least, will never mislead anyone.     *
  389.   *                                                         *
  390.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  391.  
  392. static void
  393. disdata()
  394.  
  395. {/* * * * * * * * * * START OF  disdata() * * * * * * * * * */
  396.  
  397.    register char *c;
  398.    register int j;
  399.    unsigned long end;
  400.  
  401.    putchar('\n');
  402.  
  403.    if (HDR.a_flags & A_SEP)
  404.       {
  405.       PC = 0L;
  406.       end = HDR.a_data;
  407.       }
  408.    else
  409.       end = HDR.a_text + HDR.a_data;
  410.  
  411.    printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  412.     PC,HDR.a_data);
  413.  
  414.    segflg = 0;
  415.  
  416.    for (objptr = 0, zcount = 0L; PC < end; ++PC)
  417.       {
  418.       if ((c = getlab(N_DATA)) != NULL)
  419.          {
  420.          objdump(c);
  421.          printf("%s",c);
  422.          }
  423.       if (objptr >= OBJMAX)
  424.          if (objdump(NULL) && (symptr < 0))
  425.             printf("D%05.5lx:",PC);
  426.       j = getchar() & 0xff;
  427.       objbuf[objptr++] = j;
  428.       }
  429.  
  430.    objdump("");
  431.  
  432. }/* * * * * * * * * *  END OF  disdata()  * * * * * * * * * */
  433.  
  434.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  435.   *                                                         *
  436.   * This  function  handles the object  file's bss segment. *
  437.   * Disassembly of the bss segment is easy,  because every- *
  438.   * thing in it is zero by definition.                      *
  439.   *                                                         *
  440.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  441.  
  442. static void
  443. disbss()
  444.  
  445. {/* * * * * * * * * *  START OF disbss()  * * * * * * * * * */
  446.  
  447.    register int j;
  448.    register char *c;
  449.    unsigned long beg, end;
  450.  
  451.    putchar('\n');
  452.  
  453.    if (HDR.a_flags & A_SEP)
  454.       end = HDR.a_data + HDR.a_bss;
  455.    else
  456.       end = HDR.a_text + HDR.a_data + HDR.a_bss;
  457.  
  458.    printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  459.     PC,HDR.a_bss);
  460.  
  461.    segflg = 0;
  462.  
  463.    for (beg = PC; PC < end; ++PC)
  464.       if ((c = getlab(N_BSS)) != NULL)
  465.          {
  466.          if (PC > beg)
  467.             {
  468.             zdump(beg);
  469.             beg = PC;
  470.             }
  471.          printf("%s",c);
  472.          }
  473.  
  474.    if (PC > beg)
  475.       zdump(beg);
  476.  
  477. }/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */
  478.  
  479.  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  480.   *                                                         *
  481.   * This is the program  entry  point.  The command line is *
  482.   * searched for an input file name, which must be present. *
  483.   * An optional output file name is also permitted; if none *
  484.   * is found, standard output is the default.  One command- *
  485.   * line option is available:  "-o",  which causes the pro- *
  486.   * gram to include  object code in comments along with its *
  487.   * mnemonic output.                                        *
  488.   *                                                         *
  489.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  490.  
  491. void
  492. main(argc,argv)
  493.  
  494.    int argc;                  /* Command-line args from OS  */
  495.    register char **argv;
  496.  
  497. {/* * * * * * * * * * * START OF main() * * * * * * * * * * */
  498.  
  499.    char a[1024];
  500.    register int fd;
  501.    long taboff, tabnum;
  502.    long reloff, relnum;
  503.  
  504.    PRG = invoker(*argv);
  505.  
  506.    while (*++argv != NULL)    /* Process command-line args  */
  507.       if (**argv == '-')
  508.          switch (*++*argv)
  509.             {
  510.             case 'o' :
  511.                if (*++*argv)
  512.                   usage(PRG);
  513.                else
  514.                   ++objflg;
  515.                break;
  516.             default :
  517.                usage(PRG);
  518.             }
  519.       else
  520.          if (IFILE == NULL)
  521.             IFILE = *argv;
  522.          else if (OFILE == NULL)
  523.             OFILE = *argv;
  524.          else
  525.             usage(PRG);
  526.  
  527.    if (IFILE == NULL)
  528.       usage(PRG);
  529.    else
  530.       if ((fd = open(IFILE,O_RDONLY)) < 0)
  531.          {
  532.          sprintf(a,"can't access input file %s",IFILE);
  533.          fatal(PRG,a);
  534.          }
  535.  
  536.    if (OFILE != NULL)
  537.       if (freopen(OFILE,"w",stdout) == NULL)
  538.          {
  539.          sprintf(a,"can't open output file %s",OFILE);
  540.          fatal(PRG,a);
  541.          }
  542.  
  543.    if ( ! cpuid )
  544.       fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG);
  545.  
  546.    read(fd,&HDR,sizeof(struct exec));
  547.  
  548.    if (BADMAG(HDR))
  549.       {
  550.       sprintf(a,"input file %s not in object format",IFILE);
  551.       fatal(PRG,a);
  552.       }
  553.  
  554.    if (HDR.a_cpu != A_I8086)
  555.       {
  556.       sprintf(a,"%s is not an 8086/8088 object file",IFILE);
  557.       fatal(PRG,a);
  558.       }
  559.  
  560.    if (HDR.a_hdrlen <= A_MINHDR)
  561.       HDR.a_trsize = HDR.a_drsize =
  562.       HDR.a_tbase = HDR.a_dbase =
  563.       HDR.a_lnums = HDR.a_toffs = 0L;
  564.  
  565.    reloff = HDR.a_text        /* Compute reloc data offset  */
  566.           + HDR.a_data
  567.           + (long)(HDR.a_hdrlen);
  568.  
  569.    relnum =
  570.       (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc);
  571.  
  572.    taboff = reloff            /* Compute name table offset  */
  573.           + HDR.a_trsize
  574.           + HDR.a_drsize;
  575.  
  576.    tabnum = HDR.a_syms / sizeof(struct nlist);
  577.  
  578.    if (relnum > MAXSYM)
  579.       fatal(PRG,"reloc table overflow");
  580.  
  581.    if (tabnum > MAXSYM)
  582.       fatal(PRG,"symbol table overflow");
  583.  
  584.    if (relnum)                            /* Get reloc data */
  585.       if (lseek(fd,reloff,0) != reloff)
  586.          fatal(PRG,"lseek error");
  587.       else
  588.          {
  589.          for (relptr = 0; relptr < relnum; ++relptr)
  590.             read(fd,&relo[relptr],sizeof(struct reloc));
  591.          relptr--;
  592.          }
  593.  
  594.    if (tabnum)                            /* Read in symtab */
  595.       if (lseek(fd,taboff,0) != taboff)
  596.          fatal(PRG,"lseek error");
  597.       else
  598.          {
  599.          for (symptr = 0; symptr < tabnum; ++symptr)
  600.             read(fd,&symtab[symptr],sizeof(struct nlist));
  601.          symptr--;
  602.          }
  603.    else
  604.       fprintf(stderr,"\07%s: warning: no symbols\n",PRG);
  605.  
  606.    close(fd);
  607.  
  608.    if (freopen(IFILE,"r",stdin) == NULL)
  609.       {
  610.       sprintf(a,"can't reopen input file %s",IFILE);
  611.       fatal(PRG,a);
  612.       }
  613.  
  614.    distext();
  615.  
  616.    disdata();
  617.  
  618.    disbss();
  619.  
  620.    exit(0);
  621.  
  622. }/* * * * * * * * * * *  END OF main()  * * * * * * * * * * */
  623.  
  624.  
  625.