home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OBJASM.ZIP / OMAIN.C < prev    next >
C/C++ Source or Header  |  1991-01-03  |  17KB  |  447 lines

  1. /*
  2. ** OBJASM - Utility to create .ASM files out of .OBJ files.
  3. **          Options are:
  4. **
  5. **              -r = Create RASM86 compatible output (.A86 instead of .ASM)
  6. **              -4 = Make compatible with MASM v4.0 (no retf)
  7. **              -a = Add labels for un-named data references
  8. **              -h = Hex output as comments
  9. **              -v = 486 instructions
  10. **             -s# = Minimum string size in data segment
  11. **             -c# = Minimum string size in code segment
  12. **    -f(filename) = Additional information filename (w/paren.)
  13. **
  14. **    Includes 8086/80186/80286/80386/80486
  15. **    and 8087/80287/80387 coprocessor instructions
  16. **    See OBJASM.DOC for a more detailed description.
  17. **    (C) Copyright 1988,1989,1990,1991 by Robert F. Day, All rights reserved.
  18. **
  19. **          Send/phone questions, comments, and bugs to:
  20. **
  21. **              Robert F. Day
  22. **              19906 Filbert Dr.
  23. **              Bothell, WA 98012
  24. **              (206) 481-8431
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <malloc.h>
  31. #include "o.h"
  32.  
  33.                                     /*--- Expanded INTEL OMF record types --*/
  34. #define RHEADR  0x6E                /*   R-Module Header Record             */
  35. #define REGINT  0x70                /*   Register Initialization Record     */
  36. #define REDATA  0x72                /*   Relocatable Enumerated Data Record */
  37. #define RIDATA  0x74                /*   Relocatable Iterated Data Record   */
  38. #define OVLDEF  0x76                /*   Overlay Definition Record          */
  39. #define ENDREC  0x78                /*   End Record                         */
  40. #define BLKREC  0x7A                /*   Block Definition Record            */
  41. #define BKLEND  0x7C                /*   Block End Record                   */
  42. #define DEBSYM  0x7E                /*   Debug Symbols Record               */
  43. #define THEADR  0x80                /* x T-Module Header Record             */
  44. #define LHEADR  0x82                /*   L-Module Header Record             */
  45. #define PEDATA  0x84                /*   Physical Enumerated Data (?)       */
  46. #define PIDATA  0x86                /*   Physical Iterated Data (?)         */
  47. #define COMENT  0x88                /* x Comment Record                     */
  48. #define MODEND  0x8A                /* x Module End Record                  */
  49. #define MODENDL 0x8B                /* l Module End Record                  */
  50. #define EXTDEF  0x8C                /* x External Names Definition Record   */
  51. #define TYPDEF  0x8E                /*   Type Definitions Record            */
  52. #define PUBDEF  0x90                /* x Public Names Definition Record     */
  53. #define PUBDEFL 0x91                /* l Public Names Definition Record     */
  54. #define LOCSYM  0x92                /*   Local Symbols Record               */
  55. #define LINNUM  0x94                /*   Line Numbers Record                */
  56. #define LNAMES  0x96                /* x List of Names Record               */
  57. #define SEGDEF  0x98                /* x Segment Definition Record          */
  58. #define SEGDEFL 0x99                /* l Segment Definition Record          */
  59. #define GRPDEF  0x9A                /* x Group Definition Record            */
  60. #define FIXUPP  0x9C                /* x Fix-Up Record                      */
  61. #define FIXUPPL 0x9D                /* l Fix-Up Record                      */
  62. #define LEDATA  0xA0                /* x Logical Enumerated Data            */
  63. #define LEDATAL 0xA1                /* l Logical Enumerated Data            */
  64. #define LIDATA  0xA2                /* x Logical Iterated Data              */
  65. #define LIDATAL 0xA3                /* l Logical Iterated Data              */
  66. #define LIBHED  0xA4                /*   Library Header Record              */
  67. #define LIBNAM  0xA6                /*   Library Module Names Record        */
  68. #define LIBLOC  0xA8                /*   Library Module Locations Record    */
  69. #define LIBDIC  0xAA                /*   Library Dictionary Record          */
  70. #define COMDEF  0xB0                /* m Communal Data Definition Record    */
  71. #define LEXTDEF 0xB4                /* m Local External Definition          */
  72. #define LPUBDEF 0xB6                /* m Local Public Definition            */
  73. #define LPUBDF2 0xB7                /* m Local Public Definition (2nd case?)*/
  74. #define LCOMDEF 0xB8                /* m Local Communal Data Definition     */
  75. #define LIBHDR  0xF0                /* m Library Header Record              */
  76. #define LIBEND  0xF1                /* m Library Trailer Record             */
  77.  
  78.                                     /* x = Intel OMF used by Microsoft      */
  79.                                     /* m = Microsoft Additions to Intel OMF */
  80.                                     /* l = Later extensions by Microsoft    */
  81. /*
  82. ** Local Prototypes
  83. */
  84. int main( int, char *[] );
  85.  
  86. FILE    *o_file;                    /* .OBJ file that we are processing */
  87. long    o_position;                 /* Position in file of current data */
  88.  
  89. NODE_T  *name_tree;
  90. NODE_T  *segment_tree;
  91. NODE_T  *group_tree;
  92. NODE_T  *public_tree;
  93. NODE_T  *extern_tree;
  94. NODE_T  *sex_tree;
  95. NODE_T  *data_tree;
  96. NODE_T  *struc_tree;
  97. NODE_T  *fix_tree;
  98. NODE_T  *hint_tree;
  99. NODE_T  *type_tree;
  100. NODE_T  *block_tree;
  101.  
  102. SEG_T   *seg_rec;
  103. SEG_T   seg_search;
  104. GRP_T   grp_search;
  105.  
  106. NODE_T  *pub_node;
  107. PUB_T   *pub_rec;
  108. PUB_T   *last_pub_rec;
  109. PUB_T   pub_search;
  110.  
  111. NODE_T  *hint_node;
  112. HINT_T  *hint_rec;
  113. HINT_T  hint_search;
  114.  
  115. THREAD_T threads[2][4] = {0};
  116.  
  117. NODE_T  *fix_node;
  118. FIX_T   *fix_rec;
  119. FIX_T   fix_search;
  120.  
  121. NAME_T  name_search;
  122.  
  123. int      label_count = 0;
  124.  
  125. int             segment;
  126. unsigned long   inst_offset;
  127. int             processor_mode = 0;
  128. int             segment_mode;
  129. int             segment_bytes;
  130.  
  131. char            *cseg_name;
  132. PUB_T           *start_pub = NULL;
  133.  
  134. unsigned int    code_string = 40;   /* Stringizing Limit in Code */
  135. unsigned int    data_string =  3;   /* Stringizing Limit in Data */
  136.  
  137. int     pass;                       /* 1=Building Labels, 2=Generating Output */
  138. int     processor_type_comment_occurred = FALSE;    /* No processor spec yet */
  139.  
  140. int     hex_finish;                 /* For hex comments */
  141.  
  142. int     tab_offset = 0;             /* Current tab offset, 0 = none */
  143.  
  144. int     compatibility = 0;          /* 0 = MASM 5.0+ (Microsoft) */
  145.                                     /* 1 = MASM 4.0  (Microsoft) */
  146.                                     /* 2 = RASM86 (Digital Research) */
  147.  
  148. int     add_labels = FALSE;         /* No, treat as .obj translator       */
  149.                                     /* Otherwise, treat as .asm creator   */  
  150.                                     /* Translator is a strict translation */
  151.  
  152. int     hex_output = FALSE;         /* Display hex code as comments? */
  153.  
  154. char    extra_filename[65] = {'\0'};/* Additional information file */
  155.  
  156. /*
  157. ** ------- Exit values -------- **
  158. ** 0 = Successful operation     **
  159. ** 1 = Improper Usage           **
  160. ** 2 = Unable to open OBJ file  **
  161. ** 3 = Premature end of file    **
  162. ** 4 = Out of memory            **
  163. ** 5 = .OBJ Format error        **
  164. ** 6 = Unable to open ADD file  **
  165. ** 7 = Syntax error in ADD file **
  166. ** ------- Exit values -------- **
  167. */
  168.  
  169.  
  170.  
  171. int main( argc, argv )
  172.     int     argc;
  173.     char    *argv[];
  174. {
  175.     char            *argp;
  176.     int             name_arg;
  177.     int             argi;
  178.     int             bad_args;
  179.     char            *fnamep;
  180.     unsigned long   position;
  181.     int             at_eof;
  182.     int             rec_type;
  183.     unsigned int    rec_length;
  184.     char            temp_name[50];
  185.     char            ch;
  186.     int             i486;
  187.  
  188.     bad_args = FALSE;
  189.     argi = 1;
  190.     name_arg = 0;
  191.     i486 = FALSE;
  192.     while ( argi < argc ) {
  193.         argp = argv[argi];
  194.         if ( *argp++ == '-' ) {
  195.             while ( *argp ) {
  196.                 switch ( *argp ) {
  197.                     case 'a':
  198.                         add_labels = TRUE;
  199.                         break;
  200.                     case '4':
  201.                         compatibility = 1;
  202.                         break;
  203.                     case 'r':
  204.                         compatibility = 2;
  205.                         break;
  206.                     case 'h':
  207.                         hex_output = TRUE;
  208.                         break;
  209.                     case 'v':
  210.                         i486 = TRUE;
  211.                         break;
  212.                     case 'c':
  213.                         code_string = atoi(argp+1);
  214.                         while ( (ch = *(argp+1)) != '\0' ) {
  215.                             if ( ch < '0' || ch > '9' ) {
  216.                                 break;
  217.                             }
  218.                             argp++;
  219.                         }
  220.                         break;
  221.                     case 's':
  222.                         code_string = atoi(argp+1);
  223.                         while ( (ch = *(argp+1)) != '\0' ) {
  224.                             if ( ch < '0' || ch > '9' ) {
  225.                                 break;
  226.                             }
  227.                             argp++;
  228.                         }
  229.                         break;
  230.                     case 'f':
  231.                         argp++;
  232.                         if ( *argp != '(' ) {
  233.                             bad_args = TRUE;
  234.                             break;
  235.                         }
  236.                         fnamep = extra_filename;
  237.                         while ( (ch = *(argp+1)) != '\0' ) {
  238.                             argp++;
  239.                             if ( ch == ')' ) {
  240.                                 *fnamep = '\0';
  241.                                 break;
  242.                             }
  243.                             *fnamep++ = ch;
  244.                         }
  245.                         if ( ch == '\0' ) {
  246.                             bad_args = TRUE;
  247.                         }
  248.                         break;
  249.                     default:
  250.                         bad_args = TRUE;
  251.                         break;
  252.                 }
  253.                 argp++;
  254.             }
  255.         } else {
  256.             if ( name_arg == 0 ) {
  257.                 name_arg = argi;
  258.             } else {
  259.                 bad_args = TRUE;
  260.             }
  261.         }
  262.         argi++;
  263.     }
  264.  
  265.     if ( name_arg == 0 ) {
  266.         bad_args = TRUE;
  267.     }
  268.  
  269.     if ( bad_args ) {
  270.         fprintf( stderr, "Usage:  %s [-options] [objfilename]\n", argv[0] );
  271.         fprintf( stderr, "where -options are:\n" );
  272.         fprintf( stderr, "           -4 Make MASM 4.0 compatible (no RETF)\n" );
  273.         fprintf( stderr, "           -a Add labels for un-named data references\n");
  274.         fprintf( stderr, "           -h Hex output in comments\n");
  275.         fprintf( stderr, "           -r Make RASM86 compatible\n" );
  276.         fprintf( stderr, "           -v Include 486 instructions\n" );
  277.         fprintf( stderr, "          -c# Minimum string size in a code segment (default=40)\n");
  278.         fprintf( stderr, "          -s# Mimimum string size in a data segment (default=3)\n");
  279.         fprintf( stderr, " -f(filename) Additional information filename (w/paren.)\n");
  280.         fprintf( stderr, "\n" );
  281.         fprintf( stderr, "Additional information file lines:\n");
  282.         fprintf( stderr, "SEG sname CODE                named segment is a code segment\n");
  283.         fprintf( stderr, "SEG sname DATA                named segment is a data segment\n");
  284.         fprintf( stderr, "var=sname:####                creates a local label in segment name\n");
  285.         fprintf( stderr, "sname:####:DB/DW/DD/DF/DQ/DT  directs dis-assembly into data\n");
  286.         fprintf( stderr, "... (for more info, read OBJASM.DOC)\n");
  287.         exit(1);
  288.     }
  289.  
  290.     switch( compatibility ) {
  291.         case 0:             /* MASM 5.0+ */
  292.             if ( i486 ) {
  293.                 ex_instr[0x08].text = "invd";
  294.                 ex_instr[0x09].text = "wbinvd";
  295.                 op_grp[6][7] = "invlpg";
  296.                 ex_instr[0xA6].text = "cmpxchg";
  297.                 ex_instr[0xA7].text = "cmpxchg";
  298.                 ex_instr[0xC0].text = "xadd";
  299.                 ex_instr[0xC1].text = "xadd";
  300.                 ex_instr[0xC8].text = "bswap";
  301.                 ex_instr[0xC9].text = "bswap";
  302.                 ex_instr[0xCA].text = "bswap";
  303.                 ex_instr[0xCB].text = "bswap";
  304.                 ex_instr[0xCC].text = "bswap";
  305.                 ex_instr[0xCD].text = "bswap";
  306.                 ex_instr[0xCE].text = "bswap";
  307.                 ex_instr[0xCF].text = "bswap";
  308.  
  309.             }
  310.             break;
  311.         case 1:             /* MASM 4.0  */
  312.             /*
  313.             ** Make far return only a comment
  314.             */
  315.             instr[0xCB].text = "ret\t; (retf)";
  316.             break;
  317.         case 2:             /* RASM86 */
  318.             /*
  319.             ** Make xlat a xlat bx
  320.             */
  321.             instr[0xD7].text = "xlat\tbx";
  322.             /*
  323.             ** Make short jmp a jmps
  324.             */
  325.             instr[0xEB].text = "jmps";
  326.             /*
  327.             ** Make far jmp a jmpf
  328.             */
  329.             op_grp[4][5] = "jmpf";
  330.             break;
  331.     }
  332.  
  333.     strcpy( temp_name, argv[name_arg] );
  334.     if ( strchr(temp_name,'.') == NULL ) {  /* Append ".obj" if no extension */
  335.         strcat( temp_name, ".obj" );        /* is supplied                   */
  336.     }
  337.  
  338.     o_file = fopen( temp_name, "rb" );
  339.     if ( o_file == NULL ) {
  340.         fprintf( stderr, "%s: Cannot open %s\n", argv[0], temp_name );
  341.         exit(2);
  342.     }
  343.  
  344.     /* Print copyright message */
  345.     printf("; OBJASM version 2.0 released on Jan 3, 1991\n");
  346.     printf("; (C) Copyright 1988,1989,1990,1991 by Robert F. Day.  All rights reserved\n\n");
  347.  
  348.     init_trees();                   /* Initialize all trees */
  349.  
  350.     at_eof = FALSE;
  351.     position = 0;
  352.  
  353.     while ( !at_eof ) {
  354.         fseek( o_file, position, L_SET );
  355.  
  356.         rec_type = fgetc( o_file );
  357.  
  358.         if ( rec_type == EOF ) {
  359.             at_eof = TRUE;
  360.         } else {
  361.             rec_length = getw( o_file );
  362.  
  363.             o_position = position + 3;      /* (1 rec_type) + (2 rec_length) */
  364.  
  365. #ifdef DEBUG
  366.             printf("PROCESSING rec_type [%02X] rec_length [%04X]\n", 
  367.                                                     rec_type, rec_length );
  368. #endif
  369.  
  370.             switch( rec_type ) {
  371.               case THEADR:  theadr();                       break;
  372.               case LNAMES:  lnames( rec_length );           break;
  373.               case GRPDEF:  grpdef( rec_length );           break;
  374.               case SEGDEF:  segdef();                       break;
  375.               case SEGDEFL: segdef();                       break;
  376.               case PUBDEF:  pubdef( rec_length, TRUE );     break;
  377.               case PUBDEFL: pubdef( rec_length, TRUE );     break;
  378.               case LPUBDEF: pubdef( rec_length, FALSE );    break;
  379.               case LPUBDF2: pubdef( rec_length, FALSE );    break;
  380.               case EXTDEF:  extdef( rec_length, TRUE );     break;
  381.               case LEXTDEF: extdef( rec_length, FALSE );    break;
  382.               case LEDATA:  ledata( rec_length, REGULAR );  break;
  383.               case LEDATAL: ledata( rec_length, LARGER );   break;
  384.               case LIDATA:  lidata( rec_length, REGULAR );  break;
  385.               case LIDATAL: lidata( rec_length, LARGER );   break;
  386.               case FIXUPP:  fixupp( rec_length, REGULAR );  break;
  387.               case FIXUPPL: fixupp( rec_length, LARGER );   break;
  388.               case COMENT:  coment( rec_length );           break;
  389.               case COMDEF:  comdef( rec_length, TRUE );     break;
  390.               case LCOMDEF: comdef( rec_length, FALSE );    break;
  391.               case MODEND:  modend( rec_length, REGULAR );
  392.                             at_eof = TRUE;                  break;
  393.               case MODENDL: modend( rec_length, LARGER );
  394.                             at_eof = TRUE;                  break;
  395.               case TYPDEF:                                  break;
  396.               default:  printf( "Bad record type: [%08lX:%02X:%04X]\n", 
  397.                                 position, rec_type, rec_length          );
  398.                         break;
  399.             }
  400.             position += 3 + rec_length;
  401.         }
  402.     }
  403.  
  404. #ifdef DEBUG
  405.     printf("PROCESSING dis-assembly, pass 1\n");
  406. #endif
  407.  
  408.     if ( strlen(extra_filename) != 0 ) {
  409.         load_extra( argv[0], extra_filename );
  410.     }
  411.  
  412.     pass = 1;
  413.     process();                      /* First pass: Processing */
  414.  
  415.     pass = 2;
  416.     process();                      /* Second pass: Figure out labels */
  417.  
  418. #ifdef DEBUG
  419.     printf("PROCESSING listing externals\n");
  420. #endif
  421.  
  422.     list_ext();                     /* Show EXTERNAL's */
  423.  
  424. #ifdef DEBUG
  425.     printf("PROCESSING listing publics and communal definitions\n");
  426. #endif
  427.  
  428.     list_pub();                     /* Show PUBLIC's */
  429.  
  430.     list_struc();                   /* Show STRUC's */
  431.  
  432. #ifdef DEBUG
  433.     printf("PROCESSING dis-assembly, pass 2 (last)\n");
  434. #endif
  435.  
  436.     pass = 3;
  437.     process();                      /* Third pass: Output */
  438.  
  439.     fclose( o_file );
  440.  
  441. #ifdef DEBUG
  442.     printf("END OF RUN\n");
  443. #endif
  444.  
  445.     return(0);
  446. }
  447.