home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OBJASM.ZIP / OUTARGET.C < prev    next >
C/C++ Source or Header  |  1990-11-10  |  21KB  |  623 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "o.h"
  5.  
  6. /*
  7. ** Local Prototypes
  8. */
  9. char *seg_name( int, unsigned int * );
  10. char *grp_name( int );
  11. void get_seg( char *, FIX_T *, int, void *, int );
  12. void assume( int, int, int );
  13.  
  14. FIXER_T fix_type[] = {
  15.     1, "db",     "low ",      /* LOBYTE  */
  16.     2, "dw",  "offset ",      /* OFFSET  */
  17.     2, "dw",     "seg ",      /* BASE    */
  18.     4, "dd",     "ptr ",      /* POINTER */
  19.     1, "db",    "high ",      /* HIBYTE  */
  20.     2, "dw",  "offset "  };   /* Loader-resolved */
  21.                               /*     OFFSET      */
  22.  
  23. char *seg_name( index, size )
  24.     int             index;
  25.     unsigned int    *size;
  26. {
  27.     SEG_T   *segment_rec;
  28.     NAME_T  *name_rec;
  29.  
  30.     seg_search.index = index;
  31.     segment_rec = (SEG_T *)find( (char *)&seg_search, segment_tree, 
  32.                                                         seg_compare, NULL );
  33.     if ( segment_rec == NULL ) fmt_error( "Undefinded segment" );
  34.     *size = segment_rec->length;
  35.     name_search.index = segment_rec->name;
  36.     name_rec = (NAME_T *)find( (char *)&name_search, name_tree, 
  37.                                                         name_compare, NULL );
  38.     if ( name_rec == NULL ) fmt_error( "Undefined segment name" );
  39.     return( name_rec->name );
  40. }
  41.  
  42. char *grp_name( index )
  43.     int     index;
  44. {
  45.     GRP_T   *grp_rec;
  46.     NAME_T  *name_rec;
  47.  
  48.     grp_search.index = index;
  49.     grp_rec = (GRP_T *)find( (char *)&grp_search, group_tree, 
  50.                                                         grp_compare, NULL );
  51.     if ( grp_rec == NULL ) fmt_error( "Undefined group" );
  52.     name_search.index = grp_rec->name;
  53.     name_rec = (NAME_T *)find( (char *)&name_search, name_tree, 
  54.                                                         name_compare, NULL );
  55.     if ( name_rec == NULL ) fmt_error( "Undefined group name" );
  56.     return( name_rec->name );
  57. }
  58.  
  59. char *mode_name( mode, index )
  60.     int             mode;
  61.     int             index;
  62. {
  63.     unsigned int    dummy;
  64.  
  65.     if ( index == 0 ) {
  66.         return( "NOTHING" );
  67.     }
  68.  
  69.     switch( mode ) {
  70.         case SEGMENT:   return( seg_name(index,&dummy) );       break;
  71.         case GROUP:     return( grp_name(index) );              break;
  72.         case LOCATION:  return( cseg_name );                    break;
  73.  
  74.         case EXTERNAL:
  75.         case FRAME:
  76.         case TARGET:
  77.         case NONE:      return( NULL );                 break;
  78.     }
  79. }
  80.  
  81. void assume( seg_reg, data_mode, data_index )
  82.     int             seg_reg;
  83.     int             data_mode;
  84.     int             data_index;
  85. {
  86.     char            *seg_name;
  87.     extern  char    *sregsc[];
  88.     char            operand[100];
  89.  
  90.     seg_name = mode_name( data_mode, data_index );
  91.     if (seg_name && compatibility != 2 && pass == 3 ) {
  92.         out_opcode( "assume" );
  93.         sprintf( operand, "%s %s", sregsc[seg_reg], seg_name );
  94.         out_operand( operand );
  95.         out_endline();
  96.     }
  97. }
  98.  
  99. void adjust_assumes()
  100. {
  101.     int     seg_reg;
  102.     int     new_mode;
  103.     int     new_index;
  104.  
  105.     for ( seg_reg = 0; seg_reg < MAX_SEG_REGS; seg_reg++ ) {
  106.         new_mode  = seg_rec->new_mode [seg_reg];
  107.         new_index = seg_rec->new_index[seg_reg];
  108.         if ( new_mode  != seg_rec->prv_mode [seg_reg] ||
  109.              new_index != seg_rec->prv_index[seg_reg] ) {
  110.             assume( seg_reg, new_mode, new_index );
  111.             seg_rec->prv_mode [seg_reg] = new_mode;
  112.             seg_rec->prv_index[seg_reg] = new_index;
  113.         }
  114.     }
  115. }
  116.  
  117. void abort_assumes()
  118. {
  119.     int     seg_reg;
  120.  
  121.     for ( seg_reg = 0; seg_reg < MAX_SEG_REGS; seg_reg++ ) {
  122.         seg_rec->new_mode [seg_reg] = seg_rec->prv_mode [seg_reg];
  123.         seg_rec->new_index[seg_reg] = seg_rec->prv_index[seg_reg];
  124.     }
  125. }
  126.  
  127. void get_seg( result, fixup, ref_mode, data, seg_reg )
  128.     char    *result;
  129.     FIX_T   *fixup;
  130.     int     ref_mode;
  131.     void    *data;
  132.     int     seg_reg;
  133. {
  134.     char    *this_name;
  135.     int     form;
  136.     int     mode;
  137.     int     index;
  138.     int     ref_seg;
  139.     EXT_T   *ext_rec;
  140.     PUB_T   *pub_rec;
  141.  
  142.     form  = fixup->form;
  143.     mode  = fixup->a_mode;
  144.     index = fixup->a_index;
  145.  
  146.     strcpy( result, "" );
  147.  
  148.     if ( mode == TARGET || mode == NONE ) {
  149.         return;
  150.     }
  151.  
  152.     /*
  153.     ** Check for Externals with implied or lacking segment
  154.     **  This means that the fixup tells that the external was defined in
  155.     **  that segment (for implied, SI:EI). Or that the external was defined
  156.     **  outside any segment (for lacking, EI:EI).
  157.     */
  158.     if ( fixup->b_mode == EXTERNAL ) {
  159.         ext_rec = data;
  160.         if ( mode == EXTERNAL ) {
  161.             /* Must be EI:EI */
  162.             ext_rec->used = -1;         /* Remove from any segments! */
  163.             return;
  164.         }
  165.         if ( mode == SEGMENT ) {
  166.             ext_rec->pos_abs = FALSE;
  167.             if ( ref_mode != 0 ) {
  168.                 /* Must be Segment:EI */
  169.                 if ( pass == 1 && ext_rec->used == 0 ) {
  170.                     sex_insert( index, ext_rec );
  171.                     ext_rec->used = index;
  172.                 }
  173.                 if ( ext_rec->used == index ) {
  174.                     return;
  175.                 }
  176.             }
  177.         }
  178.     } else {
  179.         if ( fixup->b_mode == SEGMENT ) {
  180.             pub_rec = data;
  181.             if ( ref_mode == 2 && (ref_mode == 1 && form == POINTER) ) {
  182.                 if ( pub_rec->seg_idx == index ) {
  183.                     return;
  184.                 }
  185.             }
  186.         }
  187.     }
  188.  
  189.     /*
  190.     ** On first important fixup, assign the "ASSIGN xx:" values
  191.     */
  192.     if ( ref_mode == 0 || (ref_mode == 1 && form != POINTER) ) {
  193.         ref_seg = seg_reg - ES;                 /* Convert to 0,1,2,3,etc */
  194.         seg_rec->new_mode [ref_seg] = mode;
  195.         seg_rec->new_index[ref_seg] = index;
  196.         if ( mode == SEGMENT ) {
  197.             if ( fixup->b_mode == EXTERNAL && ext_rec->used == index ) {
  198.                 return;
  199.             }
  200.         }
  201.         if ( mode == SEGMENT || mode == GROUP ) {
  202.             if ( fixup->b_mode == SEGMENT || fixup->b_mode == EXTERNAL ) {
  203.                 return;
  204.             }
  205.         }
  206.         /*
  207.         ** Frame on a code reference is always taken from the assume?
  208.         */
  209.     }
  210.  
  211.     if ( form == BASE ) {
  212.         if ( fixup->b_mode == mode && fixup->b_index == index ) {
  213.             return;
  214.         }
  215.     }
  216.  
  217.     this_name = mode_name( mode, index );
  218.     if ( this_name ) {
  219.         sprintf( result, "%s:", this_name );
  220.         return;
  221.     } else {
  222.         return;
  223.     }
  224. }
  225.  
  226. PUB_T *check_public( mode, index, displacement, label_char )
  227.     int             mode;
  228.     int             index;
  229.     long            displacement;
  230.     char            label_char;
  231. {
  232.     PUB_T           *new_pub_rec;
  233.     NODE_T          *new_node;
  234.     DAT_T           dat_search;
  235.     DAT_T           *dat_rec;
  236.     NODE_T          *dat_node;
  237.     FIX_T           *fix_rec;
  238.     NODE_T          *fix_node;
  239.     int             ref_seg;
  240.     char            label_name[10];
  241.     unsigned long   disp;
  242.     int             fix_count;
  243.  
  244. #ifdef DEBUG
  245. printf("--> check_public for [%04X:%04lX]\n", index, displacement );
  246. #endif
  247.  
  248.     if ( over_seg == -1 ) {
  249.         ref_seg = 2;
  250.     } else {
  251.         ref_seg = over_seg;
  252.     }
  253.  
  254.     if ( displacement < 0L ) {
  255.         disp = 0L;
  256.     } else {
  257.         disp = displacement;
  258.     }
  259.  
  260.     if ( mode == 2 ) {
  261.         index = seg_rec->prv_index[ref_seg];
  262.     }
  263.  
  264.     pub_search.seg_idx = index;
  265.     pub_search.offset  = disp;
  266.  
  267.     new_pub_rec = (PUB_T *)find( (char *)&pub_search, public_tree,
  268.                                                     pub_compare, &new_node );
  269.     if ( new_pub_rec ) {
  270.         return( new_pub_rec );
  271.     }
  272.     /*
  273.     ** If the address is just slightly past another public symbol, and
  274.     ** the address is less than the public symbols address + its size,
  275.     ** then it is probably a "public+x" type fixup.
  276.     */
  277.     if ( new_node != public_tree ) {
  278.         new_pub_rec = (PUB_T *)new_node->data;
  279.         if ( new_pub_rec->seg_idx == index ) {
  280.             if ( new_pub_rec->offset + type_to_size(new_pub_rec->type) > disp ) {
  281.                 return( new_pub_rec );
  282.             }
  283.         }
  284.     }
  285.     /*
  286.     ** Find the data record that that symbol probably belongs in
  287.     */
  288.     dat_search.seg_idx = index;
  289.     dat_search.offset = disp;
  290.     dat_rec = (DAT_T *)find( (char *)&dat_search, data_tree, 
  291.                                                     dat_compare, &dat_node );
  292.     if ( dat_node && dat_node != data_tree ) {
  293.         dat_rec = (DAT_T *)dat_node->data;
  294.         if ( dat_rec->seg_idx == index 
  295.              && dat_rec->offset+dat_rec->length > disp ) {
  296.             /*
  297.             ** Make sure the symbol is not in the middle of a fixup
  298.             */
  299.             fix_search.seg_idx    = index;
  300.             fix_search.dat_offset = dat_rec->offset;
  301.             fix_search.offset     = (int)(disp - (unsigned long)dat_rec->offset);
  302.             fix_rec = (FIX_T *)find( (char *)&fix_search, fix_tree,
  303.                                                       fix_compare, &fix_node );
  304.             if ( !fix_rec ) {
  305.                 if ( fix_node != fix_tree ) {
  306.                     fix_rec = (FIX_T *)fix_node->data;
  307.                     if ( fix_rec->seg_idx == index
  308.                          && fix_rec->dat_offset == dat_rec->offset ) {
  309.  
  310.                         fix_count = fix_type[fix_rec->form].num_bytes;
  311.  
  312.                         /*
  313.                         ** BASE types do not get larger
  314.                         */
  315.                         if ( fix_rec->extended && fix_rec->form != BASE ) {
  316.                             fix_count += 2;
  317.                         }
  318.                         if ( fix_search.offset > fix_rec->offset
  319.                           && fix_search.offset < fix_rec->offset+fix_count ) {
  320.                             return( new_pub_rec );
  321.                         }
  322.                     }
  323.                 }
  324.             }
  325.             /*
  326.             ** Make sure that public is not being placed inside an
  327.             ** iterated data block.  If it is, then retreat to the
  328.             ** start of the iterated data block.  In this way, labels
  329.             ** will never be generated inside iterated data blocks.
  330.             */
  331.             if ( dat_rec->type == ITERATED ) {
  332.                 if ( new_node == public_tree ) {
  333.                     return( NULL );
  334.                 }
  335.                 if ( new_pub_rec->seg_idx != index ) {
  336.                     return( NULL );
  337.                 }
  338.                 if ( new_pub_rec->offset >= dat_rec->offset ) {
  339.                     return( new_pub_rec );
  340.                 }
  341.                 disp = dat_rec->offset;
  342.             }
  343.         }
  344.     }
  345.  
  346.     /*
  347.     ** Create a local label (only happens on 1st pass!)
  348.     */
  349.     label_count++;
  350.     if ( compatibility == 2 ) {
  351.         sprintf( label_name, "@%c%d", label_char, label_count );
  352.     } else {
  353.         sprintf( label_name, "$%c%d", label_char, label_count );
  354.     }
  355. #ifdef DEBUG
  356. printf("Creating a new symbol <%s> at %d:%04X\n", label_name, index, disp);
  357. #endif
  358.  
  359.     new_node = pub_insert( index, disp, label_name, LOCAL, FALSE );
  360.  
  361.     new_pub_rec = (PUB_T *)find( (char *)&pub_search, public_tree,
  362.                                                         pub_compare, NULL );
  363.     if ( (pub_node == public_tree || index < pub_rec->seg_idx || 
  364.           (index == pub_rec->seg_idx && disp < pub_rec->offset)) &&
  365.            (index > segment || (index == segment && disp > inst_offset)) ) {
  366.         pub_node = new_node;
  367.         pub_rec  = new_pub_rec;
  368.     }
  369.     if ( index == segment && disp == inst_offset ) {
  370.         last_pub_rec = new_pub_rec;
  371.     }
  372.  
  373.     return( new_pub_rec );
  374. }
  375.  
  376. int find_member( text, structure, offset )
  377.     char    *text;
  378.     STRUC_T *structure;
  379.     long    *offset;
  380. {
  381.     int     type;
  382.     int     mem_cnt;
  383.     long    dup_cnt;
  384.     long     this_size;
  385.     char    *cp;
  386.     char    ch;
  387.  
  388.     mem_cnt = 0;
  389.     cp = structure->form;
  390.  
  391.     while ( (ch=*cp) != '\0' ) {
  392.         switch( ch ) {
  393.             case '(':
  394.                 dup_cnt = atol( cp+1 );
  395.                 break;
  396.             case ',':
  397.                 type = atoi( cp+1 );
  398.                 break;
  399.             case ')':
  400.                 this_size = type_to_size(type)*dup_cnt;
  401.                 if ( *offset < this_size ) {
  402.                     sprintf( text, ".s%dm_%d", structure->index, mem_cnt );
  403.                     return( type );
  404.                 }
  405.                 *offset -= this_size;
  406.                 mem_cnt++;
  407.             default:
  408.                 break;
  409.         }
  410.         cp++;
  411.     }
  412.  
  413.     strcpy( text, ".past struct" );
  414.  
  415.     return( UNKNOWN );
  416. }
  417.  
  418. void get_target( result, fixup, mode, data, pre_name, type, assign,
  419.                                                         type_known, seg_reg )
  420.     char        *result;        /* Output string                            */
  421.     FIX_T       *fixup;         /* Fixup to figure out                      */
  422.     int         mode;           /* 0 = Data Deref, 1 = Code, 2 = Data Ref   */
  423.     long        data;           /* Value added (fixups get added onto this) */
  424.     int         pre_name;       /* Are the fixup type words needed?         */
  425.     int         type;           /* type of value pointed to (word ptr, etc) */
  426.     int         assign;         /* Assign type if needed?                   */
  427.     int         *type_known;    /* Is the "word ptr" text needed? (result)  */
  428.     int         seg_reg;        /* Segment register used                    */
  429. {
  430.     int         index;
  431.     PUB_T       *pub_rec;
  432.     EXT_T       ext_search;
  433.     EXT_T       *ext_rec;
  434.     STRUC_T     *pub_struct;
  435.     char        *prefix;
  436.     char        this_seg[NAMESIZE+1+1];     /* 1 for ':', 1 for \0 */
  437.     char        this_member[NAMESIZE+1+1];  /* 1 for ., 1 for \0 */
  438.     unsigned int    seg_size;
  439.     char        *this_name;
  440.     char        *this_comment;
  441.     int         this_type;
  442.     char        sign;
  443.     long        disp;
  444.  
  445. #ifdef DEBUG
  446. printf("-> get_target for [%04X:%04X]\n", fix_rec->seg_idx, fix_rec->dat_offset );
  447. #endif
  448.  
  449.     disp = data;
  450.  
  451.     this_seg[0] = '\0';
  452.     this_member[0] = '\0';
  453.     this_comment = "";
  454.  
  455.     /*
  456.     ** Fixups cannot have a displacement value (stored with the fixup)
  457.     ** AND a value added (stored in the image to which the fixup is added)
  458.     */
  459.     if ( fixup->displacement != 0L ) {
  460.         if ( disp != 0L ) {
  461.             this_comment = "[MULTIPLE FIXUP]";
  462.         }
  463.         disp += fixup->displacement;
  464.     }
  465.  
  466.     if ( pre_name ) {
  467.         prefix = fix_type[fixup->form].prefix;
  468.     } else {
  469.         prefix = "";
  470.     }
  471.  
  472.     index = fixup->b_index;
  473.  
  474.     switch( fixup->b_mode ) {
  475.         case SEGMENT:           /* Segment Index and Displacement */
  476.             if ( fixup->form != BASE ) {
  477.                 /* PUBLIC names will be stored as segment + offset */
  478.                 pub_rec = check_public( 0, index, disp, 'S' );
  479.                 if ( pub_rec ) {
  480.                     this_name = pub_rec->name;
  481.                     disp -= (long)pub_rec->offset;
  482.                     pub_struct = pub_rec->structure;
  483.                     if ( pub_struct ) {
  484.                         this_type = find_member( this_member, pub_struct,
  485.                                                                       &disp );
  486.                     } else {
  487.                         if ( assign && ((type <= FAR && pub_rec->type > FAR)
  488.                                 || pub_rec->type == UNKNOWN) ) {
  489.                             pub_rec->type = type;
  490.                         }
  491.                         this_type = pub_rec->type;
  492.                     }
  493.                     if ( this_type != type ) {
  494.                         *type_known = FALSE;
  495.                     } else {
  496.                         *type_known = TRUE;
  497.                     }
  498.                     get_seg( this_seg, fixup, mode, pub_rec, seg_reg );
  499.                     break;
  500.                 }
  501.             }
  502.  
  503.             this_name = seg_name(index,&seg_size);
  504.             if ( fixup->form == BASE && fixup->displacement != 0 ) {
  505.                 prefix = "";        /* MASM generates seg length, if */
  506.                 disp -= seg_size;   /* "SEG" is missing, do the same */
  507.             }
  508.             this_seg[0] = '\0';
  509.             *type_known = TRUE;
  510.             break;
  511.         case GROUP:                     /* Group Index and Displacement */
  512.             this_name = grp_name(index);
  513.             *type_known = TRUE;
  514.             get_seg( this_seg, fixup, mode, NULL, seg_reg );
  515.             break;
  516.         case EXTERNAL:                  /* External Index and Displacement */
  517.             ext_search.index = index;
  518.             ext_rec = (EXT_T *)find( (char *)&ext_search, 
  519.                                         extern_tree, ext_compare, NULL );
  520.             if ( ext_rec == NULL ) fmt_error( "Undefined external" );
  521.  
  522.             this_name = ext_rec->name;
  523.  
  524.             if ( assign && ((type <= FAR && ext_rec->type > FAR)
  525.                             || ext_rec->type == UNKNOWN) ) {
  526.                 ext_rec->type = type;
  527.             }
  528.             if ( ext_rec->type != type ) {
  529.                 *type_known = FALSE;
  530.             } else {
  531.                 *type_known = TRUE;
  532.             }
  533.             get_seg( this_seg, fixup, mode, ext_rec, seg_reg );
  534.             break;
  535.         case FRAME:                     /* Frame Number and Displacement */
  536.             get_seg( this_seg, fixup, mode, NULL, seg_reg );
  537.             break;
  538.     }
  539.  
  540.     if ( disp == 0 ) {
  541.         sprintf( result, "%s%s%s%s%s", prefix, this_seg,
  542.                      this_name, this_member, this_comment );
  543.     } else {
  544.         if ( disp > 0L ) {
  545.             sign = '+';
  546.         } else {
  547.             sign = '-';
  548.             disp = -disp;
  549.         }
  550.         if ( disp > 32767L || disp < -32768L ) {
  551.             sprintf( result, "%s%s%s%s %c 0%08lXh%s",
  552.                                 prefix, this_seg,
  553.                                 this_name, this_member,
  554.                                 sign, disp,
  555.                                 this_comment );
  556.         } else {
  557.             sprintf( result, "%s%s%s%s %c 0%04lXh%s",
  558.                                 prefix, this_seg,
  559.                                 this_name, this_member,
  560.                                 sign, disp,
  561.                                 this_comment );
  562.         }
  563.     }
  564. #ifdef DEBUG
  565. printf("<- get_target [%04X:%04X]\n", fix_rec->seg_idx, fix_rec->dat_offset );
  566. #endif
  567.  
  568. }
  569.  
  570. int get_fix( result, mode, pre_name, size_bytes, size, assign, 
  571.                                                     size_known, seg_reg )
  572.     char            *result;        /* Resulting name will go here            */
  573.     int             mode;           /* 0 = Data Deref, 1 = Code, 2 = Data Ref */
  574.     int             pre_name;       /* Fixup type words needed?               */
  575.     int             size_bytes;     /* Word size (386=4 others=2)             */
  576.     int             size;           /* Size of expected value                 */
  577.     int             assign;         /* TRUE to set size, FALSE to ignore      */
  578.     int             *size_known;    /* Is "word ptr" text needed?             */
  579.     int             seg_reg;        /* Segment register used                  */
  580. {
  581.     unsigned long   data;
  582.     unsigned long   more;
  583.     int             fix_count;
  584.  
  585.     fix_count = fix_type[fix_rec->form].num_bytes;
  586.  
  587.     /*
  588.     ** BASE types do not get larger
  589.     */
  590.     if ( fix_rec->extended && fix_rec->form != BASE ) {
  591.         fix_count += 2;
  592.     } 
  593.  
  594.     switch( fix_count ) {
  595.         case 1: data = buff_getc();
  596.                 break;
  597.         case 2: data = buff_getc();
  598.                 data += (buff_getc() << 8);
  599.                 break;
  600.         case 4: data = buff_getc();
  601.                 data += (buff_getc() << 8);
  602.                 data += (buff_getc() << 16);
  603.                 data += (buff_getc() << 24);
  604.                 break;
  605.         case 6: data = buff_getc();
  606.                 data += (buff_getc() << 8);
  607.                 data += (buff_getc() << 16);
  608.                 data += (buff_getc() << 24);
  609.                 more = buff_getc();
  610.                 more += (buff_getc() << 8);
  611.                 break;
  612.         default:
  613.                 fmt_error( "Invalid fixup type" );
  614.                 break;
  615.     }
  616.  
  617.     get_target( result, fix_rec, mode, data, pre_name, size, assign, 
  618.                                                         size_known, seg_reg );
  619.     fix_advance();
  620.  
  621.     return( fix_count );
  622. }
  623.