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 |