OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * xed_tester.c | 8 * xed_tester.c |
9 * Implements a xed decoder that can be used as a NaClEnumeratorDecoder. | 9 * Implements a xed decoder that can be used as a NaClEnumeratorDecoder. |
10 */ | 10 */ |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 /* dstate.stack_addr_width = XED_ADDRESS_WIDTH_32b; */ | 53 /* dstate.stack_addr_width = XED_ADDRESS_WIDTH_32b; */ |
54 #if (NACL_TARGET_SUBARCH == 32) | 54 #if (NACL_TARGET_SUBARCH == 32) |
55 xed_decoder._xed_state.mmode = XED_MACHINE_MODE_LONG_COMPAT_32; | 55 xed_decoder._xed_state.mmode = XED_MACHINE_MODE_LONG_COMPAT_32; |
56 #endif | 56 #endif |
57 #if (NACL_TARGET_SUBARCH == 64) | 57 #if (NACL_TARGET_SUBARCH == 64) |
58 xed_decoder._xed_state.mmode = XED_MACHINE_MODE_LONG_64; | 58 xed_decoder._xed_state.mmode = XED_MACHINE_MODE_LONG_64; |
59 #endif | 59 #endif |
60 } | 60 } |
61 | 61 |
62 /* Defines the function to parse the first instruction. */ | 62 /* Defines the function to parse the first instruction. */ |
63 static void ParseInst(NaClEnumerator* enumerator, int pc_address) { | 63 static void ParseInst(const NaClEnumerator* enumerator, const int pc_address) { |
64 xed_decoder._has_xed_disasm = FALSE; | 64 xed_decoder._has_xed_disasm = FALSE; |
65 xed_decoder._pc_address = pc_address; | 65 xed_decoder._pc_address = pc_address; |
66 xed_decoder._xed_disasm[0] = 0; | 66 xed_decoder._xed_disasm[0] = 0; |
67 xed_decoder._xed_opcode[0] = 0; | 67 xed_decoder._xed_opcode[0] = 0; |
68 xed_decoder._xed_operands[0] = 0; | 68 xed_decoder._xed_operands[0] = 0; |
69 xed_decoder._xed_inst = NULL; | 69 xed_decoder._xed_inst = NULL; |
70 xed_decoded_inst_set_input_chip(&xed_decoder._xedd, XED_CHIP_CORE2); | 70 xed_decoded_inst_set_input_chip(&xed_decoder._xedd, XED_CHIP_CORE2); |
71 xed_decoded_inst_zero_set_mode(&xed_decoder._xedd, &xed_decoder._xed_state); | 71 xed_decoded_inst_zero_set_mode(&xed_decoder._xedd, &xed_decoder._xed_state); |
72 xed_decoder._xed_error = xed_decode | 72 xed_decoder._xed_error = xed_decode |
73 (&xed_decoder._xedd, (const xed_uint8_t*)enumerator->_itext, | 73 (&xed_decoder._xedd, (const xed_uint8_t*)enumerator->_itext, |
74 enumerator->_num_bytes); | 74 enumerator->_num_bytes); |
75 } | 75 } |
76 | 76 |
77 /* Returns true if the instruction parsed a legal instruction. */ | 77 /* Returns true if the instruction parsed a legal instruction. */ |
78 static Bool IsInstLegal(NaClEnumerator* enumerator) { | 78 static Bool IsInstLegal(const NaClEnumerator* enumerator) { |
79 return (xed_decoder._xedd._decoded_length != 0) && | 79 return (xed_decoder._xedd._decoded_length != 0) && |
80 (XED_ERROR_NONE == xed_decoder._xed_error); | 80 (XED_ERROR_NONE == xed_decoder._xed_error); |
81 } | 81 } |
82 | 82 |
83 /* Returns the disassembled instruction. */ | 83 /* Returns the disassembled instruction. */ |
84 static const char* Disassemble(NaClEnumerator* enumerator) { | 84 static const char* Disassemble(const NaClEnumerator* enumerator) { |
85 if (!xed_decoder._has_xed_disasm) { | 85 if (!xed_decoder._has_xed_disasm) { |
86 if (xed_decoder._xedd._decoded_length == 0) { | 86 if (xed_decoder._xedd._decoded_length == 0) { |
87 strcpy(xed_decoder._xed_disasm, "[illegal instruction]"); | 87 strcpy(xed_decoder._xed_disasm, "[illegal instruction]"); |
88 } | 88 } |
89 xed_format_intel(&xed_decoder._xedd, xed_decoder._xed_disasm, | 89 xed_format_intel(&xed_decoder._xedd, xed_decoder._xed_disasm, |
90 kBufferSize, xed_decoder._pc_address); | 90 kBufferSize, xed_decoder._pc_address); |
91 xed_decoder._has_xed_disasm = TRUE; | 91 xed_decoder._has_xed_disasm = TRUE; |
92 } | 92 } |
93 return xed_decoder._xed_disasm; | 93 return xed_decoder._xed_disasm; |
94 } | 94 } |
95 | 95 |
96 /* Returns the mnemonic name for the disassembled instruction. */ | 96 /* Returns the mnemonic name for the disassembled instruction. */ |
97 static const char* GetInstMnemonic(NaClEnumerator* enumerator) { | 97 static const char* GetInstMnemonic(const NaClEnumerator* enumerator) { |
98 char *allocated; | 98 char *allocated; |
99 char *xtmp; | 99 char *xtmp; |
100 char *prev_xtmp; | 100 char *prev_xtmp; |
101 int char0 = 0; | 101 int char0 = 0; |
102 | 102 |
103 /* First see if we have cached it. If so, return it. */ | 103 /* First see if we have cached it. If so, return it. */ |
104 if (xed_decoder._xed_opcode[0] != 0) return xed_decoder._xed_opcode; | 104 if (xed_decoder._xed_opcode[0] != 0) return xed_decoder._xed_opcode; |
105 | 105 |
106 /* If reached, we haven't cached it, so find the name from the | 106 /* If reached, we haven't cached it, so find the name from the |
107 * disassembled instruction, and cache it. | 107 * disassembled instruction, and cache it. |
(...skipping 27 matching lines...) Expand all Loading... |
135 CleanString(xtmp, "xmmword ptr "); | 135 CleanString(xtmp, "xmmword ptr "); |
136 CleanString(xtmp, "word ptr "); | 136 CleanString(xtmp, "word ptr "); |
137 CleanString(xtmp, "ptr "); | 137 CleanString(xtmp, "ptr "); |
138 CleanString(xtmp, "far "); | 138 CleanString(xtmp, "far "); |
139 | 139 |
140 cstrncpy(xed_decoder._xed_operands, strip(xtmp), kBufferSize); | 140 cstrncpy(xed_decoder._xed_operands, strip(xtmp), kBufferSize); |
141 free(allocated); | 141 free(allocated); |
142 return xed_decoder._xed_opcode; | 142 return xed_decoder._xed_opcode; |
143 } | 143 } |
144 | 144 |
145 static const char* GetInstOperandsText(NaClEnumerator* enumerator) { | 145 static const char* GetInstOperandsText(const NaClEnumerator* enumerator) { |
146 /* Force caching of operands and return. */ | 146 /* Force caching of operands and return. */ |
147 if (xed_decoder._xed_operands[0] == 0) GetInstMnemonic(enumerator); | 147 if (xed_decoder._xed_operands[0] == 0) GetInstMnemonic(enumerator); |
148 return xed_decoder._xed_operands; | 148 return xed_decoder._xed_operands; |
149 } | 149 } |
150 | 150 |
151 /* Prints out the disassembled instruction. */ | 151 /* Prints out the disassembled instruction. */ |
152 static void PrintInst(NaClEnumerator* enumerator) { | 152 static void PrintInst(const NaClEnumerator* enumerator) { |
153 int i; | 153 int i; |
154 if (enumerator->_print_opcode_bytes_only) { | 154 size_t opcode_size; |
155 for (i = 0; i < xed_decoder._xedd._decoded_length; ++i) { | 155 NaClPcAddress pc_address = (NaClPcAddress) xed_decoder._pc_address; |
156 printf("%02x", enumerator->_itext[i]); | 156 printf(" XED: %"NACL_PRIxNaClPcAddressAll": ", pc_address); |
157 } | 157 |
158 printf("\n"); | 158 /* Since xed doesn't print out opcode sequence, and it is |
159 } else { | 159 * useful to know, add it to the print out. Note: Use same |
160 size_t opcode_size; | 160 * spacing scheme as nacl decoder, so things line up. |
161 if (!enumerator->_print_enumerated_instruction) { | 161 */ |
162 NaClPcAddress pc_address = (NaClPcAddress) xed_decoder._pc_address; | 162 size_t num_bytes = MAX_INST_LENGTH; |
163 printf(" XED: %"NACL_PRIxNaClPcAddressAll": ", pc_address); | 163 if (enumerator->_num_bytes > num_bytes) |
164 } | 164 num_bytes = enumerator->_num_bytes; |
165 /* Since xed doesn't print out opcode sequence, and it is | 165 for (i = 0; i < num_bytes; ++i) { |
166 * useful to know, add it to the print out. Note: Use same | 166 if (i < xed_decoder._xedd._decoded_length) { |
167 * spacing scheme as nacl decoder, so things line up. | 167 printf("%02x ", enumerator->_itext[i]); |
168 */ | |
169 size_t num_bytes = MAX_INST_LENGTH; | |
170 if (enumerator->_num_bytes > num_bytes) | |
171 num_bytes = enumerator->_num_bytes; | |
172 for (i = 0; i < num_bytes; ++i) { | |
173 if (i < xed_decoder._xedd._decoded_length) { | |
174 printf("%02x ", enumerator->_itext[i]); | |
175 } else if (!enumerator->_print_enumerated_instruction) { | |
176 printf(" "); | |
177 } | |
178 } | |
179 if (enumerator->_print_enumerated_instruction) { | |
180 printf("#%s %s\n", GetInstMnemonic(enumerator), | |
181 GetInstOperandsText(enumerator)); | |
182 } else { | 168 } else { |
183 printf("%s\n", Disassemble(enumerator)); | 169 printf(" "); |
184 } | 170 } |
185 } | 171 } |
| 172 printf("%s\n", Disassemble(enumerator)); |
186 } | 173 } |
187 | 174 |
188 static size_t InstLength(NaClEnumerator* enumerator) { | 175 static size_t InstLength(const NaClEnumerator* enumerator) { |
189 return (size_t) xed_decoder._xedd._decoded_length; | 176 return (size_t) xed_decoder._xedd._decoded_length; |
190 } | 177 } |
191 | 178 |
192 static inline xed_inst_t const* GetXedInst() { | 179 static inline xed_inst_t const* GetXedInst() { |
193 if (xed_decoder._xed_inst == NULL) { | 180 if (xed_decoder._xed_inst == NULL) { |
194 xed_decoder._xed_inst = xed_decoded_inst_inst(&xed_decoder._xedd); | 181 xed_decoder._xed_inst = xed_decoded_inst_inst(&xed_decoder._xedd); |
195 } | 182 } |
196 return xed_decoder._xed_inst; | 183 return xed_decoder._xed_inst; |
197 } | 184 } |
198 | 185 |
199 static size_t GetNumOperands(NaClEnumerator* enumerator) { | 186 static size_t GetNumOperands(const NaClEnumerator* enumerator) { |
200 return (size_t) xed_inst_noperands(GetXedInst()); | 187 return (size_t) xed_inst_noperands(GetXedInst()); |
201 } | 188 } |
202 | 189 |
203 #if NACL_TARGET_SUBARCH == 64 | 190 #if NACL_TARGET_SUBARCH == 64 |
204 static int IsReservedReg(xed_reg_enum_t reg) { | 191 static int IsReservedReg(const xed_reg_enum_t reg) { |
205 switch (reg) { | 192 switch (reg) { |
206 case XED_REG_RSP: | 193 case XED_REG_RSP: |
207 case XED_REG_RBP: | 194 case XED_REG_RBP: |
208 case XED_REG_R15: | 195 case XED_REG_R15: |
209 return 1; | 196 return 1; |
210 } | 197 } |
211 return 0; | 198 return 0; |
212 } | 199 } |
213 | 200 |
214 | 201 |
215 static int IsWriteAction(xed_operand_action_enum_t rw) { | 202 static int IsWriteAction(const xed_operand_action_enum_t rw) { |
216 switch (rw) { | 203 switch (rw) { |
217 case XED_OPERAND_ACTION_RW: | 204 case XED_OPERAND_ACTION_RW: |
218 case XED_OPERAND_ACTION_W: | 205 case XED_OPERAND_ACTION_W: |
219 case XED_OPERAND_ACTION_RCW: | 206 case XED_OPERAND_ACTION_RCW: |
220 case XED_OPERAND_ACTION_CW: | 207 case XED_OPERAND_ACTION_CW: |
221 case XED_OPERAND_ACTION_CRW: | 208 case XED_OPERAND_ACTION_CRW: |
222 return 1; | 209 return 1; |
223 } | 210 } |
224 return 0; | 211 return 0; |
225 } | 212 } |
226 | 213 |
227 static Bool WritesToReservedReg(NaClEnumerator* enumerator, | 214 static Bool WritesToReservedReg(const NaClEnumerator* enumerator, |
228 size_t n) { | 215 const size_t n) { |
229 xed_inst_t const* xi = GetXedInst(); | 216 xed_inst_t const* xi = GetXedInst(); |
230 xed_operand_t const* op = xed_inst_operand(xi, n); | 217 xed_operand_t const* op = xed_inst_operand(xi, n); |
231 xed_operand_enum_t op_name = xed_operand_name(op); | 218 xed_operand_enum_t op_name = xed_operand_name(op); |
232 return xed_operand_is_register(op_name) && | 219 return xed_operand_is_register(op_name) && |
233 IsReservedReg(xed_decoded_inst_get_reg(&xed_decoder._xedd, op_name)) && | 220 IsReservedReg(xed_decoded_inst_get_reg(&xed_decoder._xedd, op_name)) && |
234 IsWriteAction(xed_operand_rw(op)); | 221 IsWriteAction(xed_operand_rw(op)); |
235 } | 222 } |
236 #elif NACL_TARGET_SUBARCH == 32 | 223 #elif NACL_TARGET_SUBARCH == 32 |
237 static Bool WritesToReservedReg(NaClEnumerator* enumerator, | 224 static Bool WritesToReservedReg(const NaClEnumerator* enumerator, |
238 size_t n) { | 225 const size_t n) { |
239 return FALSE; | 226 return FALSE; |
240 } | 227 } |
241 #else | 228 #else |
242 #error("Bad NACL_TARGET_SUBARCH") | 229 #error("Bad NACL_TARGET_SUBARCH") |
243 #endif | 230 #endif |
244 | 231 |
245 static const char* Usage() { | 232 static void InstallFlag(const NaClEnumerator* enumerator, |
246 return "Runs xed to decode instructions."; | |
247 } | |
248 | |
249 static void InstallFlag(NaClEnumerator* enumerator, | |
250 const char* flag_name, | 233 const char* flag_name, |
251 void* flag_address) { | 234 const void* flag_address) { |
252 } | 235 } |
253 | 236 |
254 /* Defines the registry function that creates a xed decoder, and returns | 237 /* Defines the registry function that creates a xed decoder, and returns |
255 * the decoder to be registered. | 238 * the decoder to be registered. |
256 */ | 239 */ |
257 NaClEnumeratorDecoder* RegisterXedDecoder() { | 240 NaClEnumeratorDecoder* RegisterXedDecoder() { |
258 XedSetup(); | 241 XedSetup(); |
259 xed_decoder._base._id_name = "xed"; | 242 xed_decoder._base._id_name = "xed"; |
260 xed_decoder._base._legal_only = TRUE; | |
261 xed_decoder._base._print_only = FALSE; | |
262 xed_decoder._base._parse_inst_fn = ParseInst; | 243 xed_decoder._base._parse_inst_fn = ParseInst; |
263 xed_decoder._base._inst_length_fn = InstLength; | 244 xed_decoder._base._inst_length_fn = InstLength; |
264 xed_decoder._base._print_inst_fn = PrintInst; | 245 xed_decoder._base._print_inst_fn = PrintInst; |
265 xed_decoder._base._get_inst_mnemonic_fn = GetInstMnemonic; | 246 xed_decoder._base._get_inst_mnemonic_fn = GetInstMnemonic; |
266 xed_decoder._base._get_inst_num_operands_fn = GetNumOperands; | 247 xed_decoder._base._get_inst_num_operands_fn = GetNumOperands; |
267 xed_decoder._base._get_inst_operands_text_fn = GetInstOperandsText; | 248 xed_decoder._base._get_inst_operands_text_fn = GetInstOperandsText; |
268 xed_decoder._base._writes_to_reserved_reg_fn = WritesToReservedReg; | 249 xed_decoder._base._writes_to_reserved_reg_fn = WritesToReservedReg; |
269 xed_decoder._base._is_inst_legal_fn = IsInstLegal; | 250 xed_decoder._base._is_inst_legal_fn = IsInstLegal; |
270 xed_decoder._base._maybe_inst_validates_fn = NULL; | 251 xed_decoder._base._maybe_inst_validates_fn = NULL; |
271 xed_decoder._base._segment_validates_fn = NULL; | 252 xed_decoder._base._segment_validates_fn = NULL; |
272 xed_decoder._base._install_flag_fn = InstallFlag; | 253 xed_decoder._base._install_flag_fn = InstallFlag; |
273 xed_decoder._base._usage_message = "Runs xed to decode instructions."; | 254 xed_decoder._base._usage_message = "Runs xed to decode instructions."; |
274 return &xed_decoder._base; | 255 return &xed_decoder._base; |
275 } | 256 } |
OLD | NEW |