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 
x86_insn_is_valid(x86_insn_t * insn)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 
x86_get_address(x86_insn_t * insn)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 
x86_get_rel_offset(x86_insn_t * insn)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 
x86_get_branch_target(x86_insn_t * insn)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 }
x86_get_imm(x86_insn_t * insn)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 */
x86_get_raw_imm(x86_insn_t * insn)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 
x86_operand_size(x86_op_t * op)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 
x86_set_insn_addr(x86_insn_t * insn,uint32_t addr)155 void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr ) {
156         if ( insn ) insn->addr = addr;
157 }
158 
x86_set_insn_offset(x86_insn_t * insn,unsigned int offset)159 void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset ){
160         if ( insn ) insn->offset = offset;
161 }
162 
x86_set_insn_function(x86_insn_t * insn,void * func)163 void x86_set_insn_function( x86_insn_t *insn, void * func ){
164         if ( insn ) insn->function = func;
165 }
166 
x86_set_insn_block(x86_insn_t * insn,void * block)167 void x86_set_insn_block( x86_insn_t *insn, void * block ){
168         if ( insn ) insn->block = block;
169 }
170 
x86_tag_insn(x86_insn_t * insn)171 void x86_tag_insn( x86_insn_t *insn ){
172         if ( insn ) insn->tag = 1;
173 }
174 
x86_untag_insn(x86_insn_t * insn)175 void x86_untag_insn( x86_insn_t *insn ){
176         if ( insn ) insn->tag = 0;
177 }
178 
x86_insn_is_tagged(x86_insn_t * insn)179 int x86_insn_is_tagged( x86_insn_t *insn ){
180         return insn->tag;
181 }
182 
183