Home | History | Annotate | Download | only in libdisasm
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #include "libdis.h"
      5 
      6 #ifdef _MSC_VER
      7         #define snprintf        _snprintf
      8         #define inline          __inline
      9 #endif
     10 
     11 int x86_insn_is_valid( x86_insn_t *insn ) {
     12 	if ( insn && insn->type != insn_invalid && insn->size > 0 ) {
     13 		return 1;
     14 	}
     15 
     16 	return 0;
     17 }
     18 
     19 uint32_t x86_get_address( x86_insn_t *insn ) {
     20 	x86_oplist_t *op_lst;
     21         if (! insn || ! insn->operands ) {
     22         	return 0;
     23         }
     24 
     25 	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
     26 		if ( op_lst->op.type == op_offset ) {
     27 			return op_lst->op.data.offset;
     28 		} else if ( op_lst->op.type == op_absolute ) {
     29 			if ( op_lst->op.datatype == op_descr16 ) {
     30 				return (uint32_t)
     31 					op_lst->op.data.absolute.offset.off16;
     32 			}
     33 			return op_lst->op.data.absolute.offset.off32;
     34 		}
     35 	}
     36 
     37 	return 0;
     38 }
     39 
     40 int32_t x86_get_rel_offset( x86_insn_t *insn ) {
     41 	x86_oplist_t *op_lst;
     42         if (! insn || ! insn->operands ) {
     43         	return 0;
     44         }
     45 
     46 	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
     47 		if ( op_lst->op.type == op_relative_near ) {
     48 			return (int32_t) op_lst->op.data.relative_near;
     49 		} else if ( op_lst->op.type == op_relative_far ) {
     50 			return op_lst->op.data.relative_far;
     51 		}
     52 	}
     53 
     54 	return 0;
     55 }
     56 
     57 x86_op_t * x86_get_branch_target( x86_insn_t *insn ) {
     58 	x86_oplist_t *op_lst;
     59         if (! insn || ! insn->operands ) {
     60         	return NULL;
     61         }
     62 
     63 	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
     64 		if ( op_lst->op.access & op_execute ) {
     65 			return &(op_lst->op);
     66 		}
     67 	}
     68 
     69 	return NULL;
     70 }
     71 x86_op_t * x86_get_imm( x86_insn_t *insn ) {
     72 	x86_oplist_t *op_lst;
     73         if (! insn || ! insn->operands ) {
     74         	return NULL;
     75         }
     76 
     77 	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
     78 		if ( op_lst->op.type == op_immediate ) {
     79 			return &(op_lst->op);
     80 		}
     81 	}
     82 
     83 	return NULL;
     84 }
     85 
     86 #define IS_PROPER_IMM( x ) \
     87 	x->op.type == op_immediate && ! (x->op.flags & op_hardcode)
     88 
     89 
     90 /* if there is an immediate value in the instruction, return a pointer to
     91  * it */
     92 unsigned char * x86_get_raw_imm( x86_insn_t *insn ) {
     93         int size, offset;
     94         x86_op_t *op  = NULL;
     95 
     96         if (! insn || ! insn->operands ) {
     97         	return(NULL);
     98         }
     99 
    100 	/* a bit inelegant, but oh well... */
    101 	if ( IS_PROPER_IMM( insn->operands ) ) {
    102 		op = &insn->operands->op;
    103 	} else if ( insn->operands->next ) {
    104 		if ( IS_PROPER_IMM( insn->operands->next ) ) {
    105 			op = &insn->operands->next->op;
    106 		} else if ( insn->operands->next->next &&
    107 			    IS_PROPER_IMM( insn->operands->next->next ) ) {
    108 			op = &insn->operands->next->next->op;
    109 		}
    110 	}
    111 
    112 	if (! op ) {
    113 		return( NULL );
    114 	}
    115 
    116 	/* immediate data is at the end of the insn */
    117 	size = x86_operand_size( op );
    118 	offset = insn->size - size;
    119 	return( &insn->bytes[offset] );
    120 }
    121 
    122 
    123 unsigned int x86_operand_size( x86_op_t *op ) {
    124         switch (op->datatype ) {
    125                 case op_byte:    return 1;
    126                 case op_word:    return 2;
    127                 case op_dword:   return 4;
    128                 case op_qword:   return 8;
    129                 case op_dqword:  return 16;
    130                 case op_sreal:   return 4;
    131                 case op_dreal:   return 8;
    132                 case op_extreal: return 10;
    133                 case op_bcd:     return 10;
    134                 case op_ssimd:   return 16;
    135                 case op_dsimd:   return 16;
    136                 case op_sssimd:  return 4;
    137                 case op_sdsimd:  return 8;
    138                 case op_descr32: return 6;
    139                 case op_descr16: return 4;
    140                 case op_pdescr32: return 6;
    141                 case op_pdescr16: return 6;
    142 		case op_bounds16: return 4;
    143 		case op_bounds32: return 8;
    144                 case op_fpuenv16:  return 14;
    145                 case op_fpuenv32:  return 28;
    146                 case op_fpustate16:  return 94;
    147                 case op_fpustate32:  return 108;
    148                 case op_fpregset: return 512;
    149 		case op_fpreg: return 10;
    150 		case op_none: return 0;
    151         }
    152         return(4);      /* default size */
    153 }
    154 
    155 void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr ) {
    156         if ( insn ) insn->addr = addr;
    157 }
    158 
    159 void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset ){
    160         if ( insn ) insn->offset = offset;
    161 }
    162 
    163 void x86_set_insn_function( x86_insn_t *insn, void * func ){
    164         if ( insn ) insn->function = func;
    165 }
    166 
    167 void x86_set_insn_block( x86_insn_t *insn, void * block ){
    168         if ( insn ) insn->block = block;
    169 }
    170 
    171 void x86_tag_insn( x86_insn_t *insn ){
    172         if ( insn ) insn->tag = 1;
    173 }
    174 
    175 void x86_untag_insn( x86_insn_t *insn ){
    176         if ( insn ) insn->tag = 0;
    177 }
    178 
    179 int x86_insn_is_tagged( x86_insn_t *insn ){
    180         return insn->tag;
    181 }
    182 
    183