|
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 |