Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
|
Dmitry Polukhin
2012/11/02 17:31:06
I think this test need to be converted to C++ and
| |
| 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 #include <assert.h> | 7 #include <assert.h> |
| 8 #include <stdio.h> | 8 #include <stdio.h> |
| 9 #include <stdarg.h> | 9 #include <stdarg.h> |
| 10 #include <stdlib.h> | 10 #include <stdlib.h> |
| 11 #include <string.h> | 11 #include <string.h> |
| 12 | 12 |
| 13 #include "native_client/src/include/elf32.h" | 13 #include "native_client/src/include/elf32.h" |
| 14 #include "native_client/src/include/elf64.h" | 14 #include "native_client/src/include/elf64.h" |
| 15 #include "native_client/src/shared/platform/nacl_check.h" | 15 #include "native_client/src/shared/platform/nacl_check.h" |
| 16 #include "native_client/src/shared/utils/types.h" | 16 #include "native_client/src/shared/utils/types.h" |
| 17 #include "native_client/src/trusted/validator_ragel/unreviewed/decoder.h" | 17 #include "native_client/src/trusted/validator_ragel/decoder.h" |
| 18 | 18 |
| 19 /* This is a copy of NaClLog from shared/platform/nacl_log.c to avoid | 19 /* This is a copy of NaClLog from shared/platform/nacl_log.c to avoid |
| 20 * linking in code in NaCl shared code in the unreviewed/Makefile and be able to | 20 * linking in code in NaCl shared code in the unreviewed/Makefile and be able to |
| 21 * use CHECK(). | 21 * use CHECK(). |
| 22 | 22 |
| 23 * TODO(khim): remove the copy of NaClLog implementation as soon as | 23 * TODO(khim): remove the copy of NaClLog implementation as soon as |
| 24 * unreviewed/Makefile is eliminated. | 24 * unreviewed/Makefile is eliminated. |
| 25 */ | 25 */ |
| 26 void NaClLog(int detail_level, char const *fmt, ...) { | 26 void NaClLog(int detail_level, char const *fmt, ...) { |
| 27 va_list ap; | 27 va_list ap; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 NULL, "cr15", "db15", "tr15" } | 124 NULL, "cr15", "db15", "tr15" } |
| 125 }; | 125 }; |
| 126 assert(kRegisterNames[name][type]); | 126 assert(kRegisterNames[name][type]); |
| 127 return kRegisterNames[name][type]; | 127 return kRegisterNames[name][type]; |
| 128 } else { | 128 } else { |
| 129 assert(FALSE); | 129 assert(FALSE); |
| 130 return NULL; | 130 return NULL; |
| 131 } | 131 } |
| 132 } | 132 } |
| 133 | 133 |
| 134 Bool IsNameInList(const char *name, ...) { | 134 Bool IsNameInList(const char *name, ...) { |
|
Brad Chen
2012/10/22 21:29:05
Could you use an array rather than varargs here? I
Dmitry Polukhin
2012/11/02 17:31:06
This function can be converted to function with tw
| |
| 135 va_list value_list; | 135 va_list value_list; |
| 136 | 136 |
| 137 va_start(value_list, name); | 137 va_start(value_list, name); |
| 138 | 138 |
| 139 for (;;) { | 139 for (;;) { |
| 140 const char *element = va_arg(value_list, const char*); | 140 const char *element = va_arg(value_list, const char*); |
| 141 if (element) { | 141 if (element) { |
| 142 if (strcmp(name, element) == 0) { | 142 if (strcmp(name, element) == 0) { |
| 143 va_end(value_list); | 143 va_end(value_list); |
| 144 return TRUE; | 144 return TRUE; |
| 145 } | 145 } |
| 146 } else { | 146 } else { |
| 147 va_end(value_list); | 147 va_end(value_list); |
| 148 return FALSE; | 148 return FALSE; |
| 149 } | 149 } |
| 150 } | 150 } |
| 151 } | 151 } |
| 152 | 152 |
| 153 /* | |
| 154 * "fwait" is nasty: few of them will be included in other X87 instructions | |
| 155 * ("fclex", "finit", "fstcw", "fstsw", "fsave" have two names, other | |
| 156 * instructions are unchanged) - but if after them we see regular instruction | |
| 157 * then we must print them all. This convoluted logic is not needed when we | |
| 158 * don't print anything so decoder does not include it. | |
| 159 */ | |
| 160 static Bool ProcessFWait(const uint8_t **begin, const uint8_t *end, | |
|
Dmitry Polukhin
2012/11/02 17:31:06
Too many arguments, class with state should solve
| |
| 161 struct Instruction *instruction, | |
| 162 struct DecodeState *userdata, | |
| 163 unsigned char *rex_prefix, Bool *spurious_rex_prefix, | |
| 164 enum OperandName *rm_base, | |
| 165 enum OperandName *rm_index) { | |
| 166 /* Instruction is "fwait" if it's 0x9b or if it's REX prefix plus 0x9b. */ | |
| 167 if (((end == *begin + 1) && ((*begin)[0] == 0x9b)) || | |
| 168 ((end == *begin + 2) && | |
| 169 (((*begin)[0] & 0xf0) == 0x40) && ((*begin)[1] == 0x9b))) { | |
| 170 if (!(userdata->fwait)) { | |
| 171 userdata->fwait = *begin; | |
| 172 } | |
| 173 return TRUE; | |
| 174 } else if (userdata->fwait) { | |
| 175 /* | |
| 176 * If it's x87 instruction then we can fold some fwait's in the instruction | |
| 177 * itself. | |
| 178 * | |
| 179 * Instruction is x87 instruction if it has opcode from 0xd8 to 0xdf, but it | |
| 180 * can include either 0x66 prefix or REX prefix, or both. | |
| 181 */ | |
| 182 if ((((*begin)[0] & 0xf8) == 0xd8) || | |
| 183 (((((*begin)[0] & 0xf0) == 0x40) || ((*begin)[0] == 0x66)) && | |
| 184 (((*begin)[1] & 0xf8) == 0xd8)) || | |
| 185 (((*begin)[0] == 0x66) && (((*begin)[1] & 0xf0) == 0x40) && | |
| 186 (((*begin)[2] & 0xf8) == 0xd8))) { | |
| 187 /* | |
| 188 * fwait "prefix" can only include two 0x9b bytes or one rex byte - and | |
| 189 * then only if the instruction itself have no rex prefix. | |
| 190 */ | |
| 191 int fwait_count = !!(instruction->prefix.data16); | |
| 192 int rex_count = (!!*rex_prefix) | (!!(instruction->prefix.data16)); | |
| 193 for (;;) { | |
| 194 if (*begin == userdata->fwait) | |
| 195 break; | |
| 196 if (((*begin)[-1]) == 0x9b) { | |
| 197 if (fwait_count < 2) { | |
| 198 --*begin; | |
| 199 ++fwait_count; | |
| 200 if (((*begin)[1] & 0xf0) == 0x40) | |
| 201 break; | |
| 202 } else { | |
| 203 break; | |
| 204 } | |
| 205 } else if (((*begin)[-1] & 0xf0) == 0x40) { | |
| 206 if (rex_count >= 1) | |
| 207 break; | |
| 208 --*begin; | |
| 209 ++rex_count; | |
| 210 if (!*rex_prefix) { | |
| 211 *rex_prefix = **begin; | |
| 212 /* | |
| 213 * Bug-to-bug compatibility: objdump will erroneously use bits from | |
| 214 * first REX prefix (attached to "fwait") and not from the | |
| 215 * second REX prefix (attached to the instruction itself). | |
| 216 * | |
| 217 * Duplicate this error here till it'll be fixed in objdump. | |
| 218 */ | |
| 219 if ((*rex_prefix & 0x01) && (*rm_base <= REG_RDI)) { | |
| 220 if (instruction->operands_count == 1 && | |
| 221 instruction->operands[0].name == REG_RM) | |
| 222 *rm_base |= REG_R8; | |
| 223 else | |
| 224 *spurious_rex_prefix = TRUE; | |
| 225 } | |
| 226 if (*rex_prefix & 0x02) { | |
| 227 if (instruction->operands_count == 1 && | |
| 228 instruction->operands[0].name == REG_RM) { | |
| 229 if (*rm_index <= REG_RDI) | |
| 230 *rm_index |= REG_R8; | |
| 231 else if (*rm_index == REG_RIZ) | |
| 232 *rm_index = REG_R12; | |
| 233 else if (*rm_index == NO_REG) | |
| 234 *spurious_rex_prefix = TRUE; | |
| 235 } else { | |
| 236 *spurious_rex_prefix = TRUE; | |
| 237 } | |
| 238 } | |
| 239 if (*rex_prefix & 0x0c) | |
| 240 *spurious_rex_prefix = TRUE; | |
| 241 } | |
| 242 } | |
| 243 } | |
| 244 if (*begin != userdata->fwait) { | |
| 245 while (userdata->fwait < *begin) { | |
| 246 printf("%*lx:\t%02x \tfwait\n", | |
| 247 userdata->width, (long)(userdata->fwait - userdata->offset), | |
| 248 *userdata->fwait); | |
| 249 ++(userdata->fwait); | |
| 250 } | |
| 251 } | |
| 252 } else { | |
| 253 while ((userdata->fwait) < *begin) { | |
| 254 printf("%*lx:\t%02x \tfwait\n", | |
| 255 userdata->width, (long)(userdata->fwait - userdata->offset), | |
| 256 *userdata->fwait); | |
| 257 ++(userdata->fwait); | |
| 258 } | |
| 259 } | |
| 260 userdata->fwait = FALSE; | |
| 261 } | |
| 262 return FALSE; | |
| 263 } | |
| 264 | |
| 153 void ProcessInstruction(const uint8_t *begin, const uint8_t *end, | 265 void ProcessInstruction(const uint8_t *begin, const uint8_t *end, |
|
Dmitry Polukhin
2012/11/02 17:31:06
I think it should be converted to so class Instruc
| |
| 154 struct Instruction *instruction, void *userdata) { | 266 struct Instruction *instruction, void *callback_data) { |
| 267 struct DecodeState *userdata = callback_data; | |
| 155 const char *instruction_name = instruction->name; | 268 const char *instruction_name = instruction->name; |
| 156 unsigned char operands_count = instruction->operands_count; | 269 unsigned char operands_count = instruction->operands_count; |
| 157 unsigned char rex_prefix = instruction->prefix.rex; | 270 unsigned char rex_prefix = instruction->prefix.rex; |
| 158 enum OperandName rm_index = instruction->rm.index; | 271 enum OperandName rm_index = instruction->rm.index; |
| 159 enum OperandName rm_base = instruction->rm.base; | 272 enum OperandName rm_base = instruction->rm.base; |
| 160 Bool data16_prefix = instruction->prefix.data16; | 273 Bool data16_prefix = instruction->prefix.data16; |
| 161 const uint8_t *p; | 274 const uint8_t *p; |
| 162 char delimeter = ' '; | 275 char delimeter = ' '; |
| 163 Bool print_rip = FALSE; | 276 Bool print_rip = FALSE; |
| 164 Bool empty_rex_prefix_ok = FALSE; | 277 Bool empty_rex_prefix_ok = FALSE; |
| 165 Bool spurious_rex_prefix = FALSE; | 278 Bool spurious_rex_prefix = FALSE; |
| 166 #define print_name(x) (printf((x)), shown_name += strlen((x))) | 279 #define print_name(x) (printf((x)), shown_name += strlen((x))) |
|
Brad Chen
2012/10/22 21:29:05
What is your goal in making this a macro rather th
| |
| 167 size_t shown_name = 0; | 280 size_t shown_name = 0; |
| 168 int i, operand_type; | 281 int i, operand_type; |
| 169 | 282 |
| 283 if (ProcessFWait(&begin, end, instruction, callback_data, | |
| 284 &rex_prefix, &spurious_rex_prefix, &rm_base, &rm_index)) | |
| 285 return; | |
| 286 | |
| 170 /* | 287 /* |
| 171 * "fwait" is nasty: few of them will be included in other X87 instructions | 288 * Objdump will print data16 (0x66) prefix on a separate line for "fbld", |
| 172 * ("fclex", "finit", "fstcw", "fstsw", "fsave" have two names, other | 289 * "fbstp", "fild", "fistp", "fld", and "fstp" instructions. |
| 173 * instructions are unchanged) - but if after them we see regular instruction | |
| 174 * then we must print them all. This convoluted logic is not needed when we | |
| 175 * don't print anything so decoder does not include it. | |
| 176 */ | 290 */ |
| 177 if (((end == begin + 1) && (begin[0] == 0x9b)) || | |
| 178 ((end == begin + 2) && | |
| 179 ((begin[0] & 0xf0) == 0x40) && (begin[1] == 0x9b))) { | |
| 180 if (!(((struct DecodeState *)userdata)->fwait)) { | |
| 181 ((struct DecodeState *)userdata)->fwait = begin; | |
| 182 } | |
| 183 return; | |
| 184 } else if (((struct DecodeState *)userdata)->fwait) { | |
| 185 /* If it's x87 instruction then we can fold some fwait's in the instruction | |
| 186 itself. */ | |
| 187 if (((begin[0] >= 0xd8) && (begin[0] <= 0xdf)) || | |
| 188 ((((begin[0] & 0xf0) == 0x40) || (begin[0] == 0x66)) && | |
| 189 (begin[1] >= 0xd8) && (begin[1] <= 0xdf)) || | |
| 190 ((begin[0] == 0x66) || ((begin[1] & 0xf0) == 0x40) || | |
| 191 (begin[2] >= 0xd8) || (begin[2] <= 0xdf))) { | |
| 192 /* fwait "prefix" can only include two 0x9b bytes or one rex byte - and | |
| 193 * then only if the instruction itself have no rex prefix. */ | |
| 194 int fwait_count = !!data16_prefix; | |
| 195 int rex_count = (!!rex_prefix) | (!!data16_prefix); | |
| 196 for (;;) { | |
| 197 if (begin == ((struct DecodeState *)userdata)->fwait) | |
| 198 break; | |
| 199 if ((begin[-1]) == 0x9b) { | |
| 200 if (fwait_count < 2) { | |
| 201 --begin; | |
| 202 ++fwait_count; | |
| 203 if ((begin[1] & 0xf0) == 0x40) | |
| 204 break; | |
| 205 } else { | |
| 206 break; | |
| 207 } | |
| 208 } else if ((begin[-1] & 0xf0) == 0x40) { | |
| 209 if (rex_count >= 1) | |
| 210 break; | |
| 211 --begin; | |
| 212 ++rex_count; | |
| 213 if (!rex_prefix) { | |
| 214 rex_prefix = *begin; | |
| 215 /* Bug-to-bug compatibility, fun... */ | |
| 216 if ((rex_prefix & 0x01) && (rm_base <= REG_RDI)) { | |
| 217 if (operands_count == 1 && | |
| 218 instruction->operands[0].name == REG_RM) | |
| 219 rm_base |= REG_R8; | |
| 220 else | |
| 221 spurious_rex_prefix = TRUE; | |
| 222 } | |
| 223 if (rex_prefix & 0x02) { | |
| 224 if (operands_count == 1 && | |
| 225 instruction->operands[0].name == REG_RM) { | |
| 226 if (rm_index <= REG_RDI) | |
| 227 rm_index |= REG_R8; | |
| 228 else if (rm_index == REG_RIZ) | |
| 229 rm_index = REG_R12; | |
| 230 else if (rm_index == NO_REG) | |
| 231 spurious_rex_prefix = TRUE; | |
| 232 } else { | |
| 233 spurious_rex_prefix = TRUE; | |
| 234 } | |
| 235 } | |
| 236 if (rex_prefix & 0x0c) | |
| 237 spurious_rex_prefix = TRUE; | |
| 238 } | |
| 239 } | |
| 240 } | |
| 241 if (begin != ((struct DecodeState *)userdata)->fwait) { | |
| 242 while ((((struct DecodeState *)userdata)->fwait) < begin) { | |
| 243 printf("%*lx:\t%02x \tfwait\n", | |
| 244 ((struct DecodeState *)userdata)->width, | |
| 245 (long)((((struct DecodeState *)userdata)->fwait) - | |
| 246 (((struct DecodeState *)userdata)->offset)), | |
| 247 *((struct DecodeState *)userdata)->fwait); | |
| 248 ++(((struct DecodeState *)userdata)->fwait); | |
| 249 } | |
| 250 } | |
| 251 } else { | |
| 252 while ((((struct DecodeState *)userdata)->fwait) < begin) { | |
| 253 printf("%*lx:\t%02x \tfwait\n", | |
| 254 ((struct DecodeState *)userdata)->width, | |
| 255 (long)((((struct DecodeState *)userdata)->fwait) - | |
| 256 (((struct DecodeState *)userdata)->offset)), | |
| 257 *((struct DecodeState *)userdata)->fwait); | |
| 258 ++(((struct DecodeState *)userdata)->fwait); | |
| 259 } | |
| 260 } | |
| 261 ((struct DecodeState *)userdata)->fwait = FALSE; | |
| 262 } | |
| 263 | |
| 264 if ((data16_prefix) && (begin[0] == 0x66) && (!(rex_prefix & 0x08)) && | 291 if ((data16_prefix) && (begin[0] == 0x66) && (!(rex_prefix & 0x08)) && |
| 265 (IsNameInList(instruction_name, | 292 (IsNameInList(instruction_name, |
| 266 "fbld", "fbstp", "fild", "fistp", "fld", "fstp", NULL))) { | 293 "fbld", "fbstp", "fild", "fistp", "fld", "fstp", NULL))) { |
| 267 printf("%*lx:\t66 \tdata16\n", | 294 printf("%*lx:\t66 \tdata16\n", |
| 268 ((struct DecodeState *)userdata)->width, | 295 userdata->width, (long)(begin - userdata->offset)); |
| 269 (long)(begin - (((struct DecodeState *)userdata)->offset))); | |
| 270 data16_prefix = FALSE; | 296 data16_prefix = FALSE; |
| 271 ++begin; | 297 ++begin; |
| 272 } | 298 } |
| 273 printf("%*lx:\t", ((struct DecodeState *)userdata)->width, | 299 |
| 274 (long)(begin - (((struct DecodeState *)userdata)->offset))); | 300 /* Start the main processing part: print offset here. */ |
| 301 printf("%*lx:\t", userdata->width, (long)(begin - userdata->offset)); | |
| 275 for (p = begin; p < begin + 7; ++p) { | 302 for (p = begin; p < begin + 7; ++p) { |
| 276 if (p >= end) | 303 if (p >= end) |
| 277 printf(" "); | 304 printf(" "); |
| 278 else | 305 else |
| 279 printf("%02x ", *p); | 306 printf("%02x ", *p); |
| 280 } | 307 } |
| 281 printf("\t"); | 308 printf("\t"); |
| 309 | |
| 282 /* | 310 /* |
| 283 * "pclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, | 311 * "pclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, |
| 284 * 0x10, and 0x11. Objdump incorrectly mixes them up with 0x2 and 0x03. | 312 * 0x10, and 0x11. Objdump incorrectly mixes them up with 0x2 and 0x03. |
| 285 */ | 313 */ |
| 286 if (!strcmp(instruction_name, "pclmulqdq")) { | 314 if (!strcmp(instruction_name, "pclmulqdq")) { |
| 287 if (instruction->imm[0] < 0x04) { | 315 if (instruction->imm[0] < 0x04) { |
| 288 switch (instruction->imm[0]) { | 316 switch (instruction->imm[0]) { |
| 289 case 0x02: instruction_name = "pclmullqhqdq"; break; | 317 case 0x02: instruction_name = "pclmullqhqdq"; break; |
| 290 case 0x03: instruction_name = "pclmulhqhqdq"; break; | 318 case 0x03: instruction_name = "pclmulhqhqdq"; break; |
| 291 } | 319 } |
| 292 --operands_count; | 320 --operands_count; |
| 293 } | 321 } |
| 294 } | 322 } |
| 323 | |
| 295 /* | 324 /* |
| 296 * "vpclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, | 325 * "vpclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, |
| 297 * 0x10, and 0x11. Objdump mixes them with 0x2 and 0x03. | 326 * 0x10, and 0x11. Objdump mixes them with 0x2 and 0x03. |
| 298 */ | 327 */ |
| 299 if (!strcmp(instruction_name, "vpclmulqdq")) { | 328 if (!strcmp(instruction_name, "vpclmulqdq")) { |
| 300 if (instruction->imm[0] < 0x04) { | 329 if (instruction->imm[0] < 0x04) { |
| 301 switch (instruction->imm[0]) { | 330 switch (instruction->imm[0]) { |
| 302 case 0x02: instruction_name = "vpclmullqhqdq"; break; | 331 case 0x02: instruction_name = "vpclmullqhqdq"; break; |
| 303 case 0x03: instruction_name = "vpclmulhqhqdq"; break; | 332 case 0x03: instruction_name = "vpclmulhqhqdq"; break; |
| 304 } | 333 } |
| 305 --operands_count; | 334 --operands_count; |
| 306 } | 335 } |
| 307 } | 336 } |
| 337 | |
| 308 spurious_rex_prefix |= | 338 spurious_rex_prefix |= |
| 309 rex_prefix && | 339 rex_prefix && |
| 310 (instruction->prefix.rex_b_spurious || | 340 (instruction->prefix.rex_b_spurious || |
| 311 instruction->prefix.rex_x_spurious || | 341 instruction->prefix.rex_x_spurious || |
| 312 instruction->prefix.rex_r_spurious || | 342 instruction->prefix.rex_r_spurious || |
| 313 instruction->prefix.rex_w_spurious); | 343 instruction->prefix.rex_w_spurious); |
| 344 | |
| 345 /* | |
| 346 * Objdump sometimes does not show spurious rex prefixes. Adjust the | |
| 347 * spurious_rex_prefix variable here for these cases. | |
| 348 */ | |
| 314 if (operands_count > 0) { | 349 if (operands_count > 0) { |
| 315 if (!((struct DecodeState *)userdata)->ia32_mode) | 350 if (!userdata->ia32_mode) |
| 316 for (i=0; i<operands_count; ++i) | 351 for (i=0; i<operands_count; ++i) |
| 317 /* | 352 /* |
| 318 * Objdump mistakenly allows "lock" with "mov %crX,%rXX" only in ia32 | 353 * Objdump mistakenly allows "lock" with "mov %crX,%rXX" only in ia32 |
| 319 * mode. It's perfectly valid in amd64, too, so instead of changing | 354 * mode. It's perfectly valid in amd64, too, so instead of changing |
| 320 * the decoder we fix it here. | 355 * the decoder we fix it here. |
| 321 */ | 356 */ |
| 322 if (instruction->operands[i].type == OPERAND_TYPE_CONTROL_REGISTER && | 357 if (instruction->operands[i].type == OPERAND_TYPE_CONTROL_REGISTER && |
| 323 *begin == 0xf0 && !instruction->prefix.lock) { | 358 *begin == 0xf0 && !instruction->prefix.lock) { |
| 324 print_name("lock "); | 359 print_name("lock "); |
| 325 if (rex_prefix & 0x04) { | 360 if (rex_prefix & 0x04) { |
| 326 if (!instruction->prefix.rex_b_spurious && | 361 if (!instruction->prefix.rex_b_spurious && |
| 327 instruction->prefix.rex_r_spurious && | 362 instruction->prefix.rex_r_spurious && |
| 328 !instruction->prefix.rex_x_spurious && | 363 !instruction->prefix.rex_x_spurious && |
| 329 !instruction->prefix.rex_w_spurious) | 364 !instruction->prefix.rex_w_spurious) |
| 330 spurious_rex_prefix = FALSE; | 365 spurious_rex_prefix = FALSE; |
| 331 } else { | 366 } else { |
| 332 instruction->operands[i].name -= 8; | 367 instruction->operands[i].name -= 8; |
| 333 } | 368 } |
| 334 } | 369 } |
| 335 } | 370 } |
| 336 /* Only few rare instructions show spurious REX.B in objdump. */ | 371 |
| 337 if (!spurious_rex_prefix && instruction->prefix.rex_b_spurious) | |
| 338 if (IsNameInList(instruction_name, | |
| 339 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", | |
| 340 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", | |
| 341 "jecxz", "jrcxz", "loop", "loope", "loopne", NULL)) | |
| 342 spurious_rex_prefix = TRUE; | |
| 343 /* Some instructions don't show spurious REX.B in objdump. */ | 372 /* Some instructions don't show spurious REX.B in objdump. */ |
| 344 if (spurious_rex_prefix && | 373 if (spurious_rex_prefix && |
| 345 instruction->prefix.rex_b_spurious && | 374 instruction->prefix.rex_b_spurious && |
| 346 !instruction->prefix.rex_r_spurious && | 375 !instruction->prefix.rex_r_spurious && |
| 347 !instruction->prefix.rex_x_spurious && | 376 !instruction->prefix.rex_x_spurious && |
| 348 !instruction->prefix.rex_w_spurious) { | 377 !instruction->prefix.rex_w_spurious) { |
| 349 if (operands_count > 0) | 378 if (operands_count > 0) |
| 350 for (i=0; i<operands_count; ++i) | 379 for (i=0; i<operands_count; ++i) |
| 351 if (instruction->operands[i].name == REG_RM && | 380 if (instruction->operands[i].name == REG_RM && |
| 352 instruction->rm.disp_type != DISP64) { | 381 instruction->rm.disp_type != DISP64) { |
| 353 spurious_rex_prefix = FALSE; | 382 spurious_rex_prefix = FALSE; |
| 354 break; | 383 break; |
| 355 } | 384 } |
| 356 } | 385 } |
| 386 | |
| 357 /* Some instructions don't show spurious REX.W in objdump. */ | 387 /* Some instructions don't show spurious REX.W in objdump. */ |
| 358 if (spurious_rex_prefix && | 388 if (spurious_rex_prefix && |
| 359 !instruction->prefix.rex_b_spurious && | 389 !instruction->prefix.rex_b_spurious && |
| 360 !instruction->prefix.rex_r_spurious && | 390 !instruction->prefix.rex_r_spurious && |
| 361 !instruction->prefix.rex_x_spurious && | 391 !instruction->prefix.rex_x_spurious && |
| 362 instruction->prefix.rex_w_spurious) { | 392 instruction->prefix.rex_w_spurious) { |
| 363 if (IsNameInList(instruction_name, | 393 if (IsNameInList(instruction_name, |
| 364 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", | 394 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", |
| 365 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", | 395 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", |
| 366 "jecxz", "jrcxz", "loop", "loope", "loopne", | 396 "jecxz", "jrcxz", "loop", "loope", "loopne", |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 387 if (!spurious_rex_prefix && (rex_prefix & 0x08) && | 417 if (!spurious_rex_prefix && (rex_prefix & 0x08) && |
| 388 ((IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && | 418 ((IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && |
| 389 instruction->operands[0].name != JMP_TO) || | 419 instruction->operands[0].name != JMP_TO) || |
| 390 IsNameInList(instruction_name, | 420 IsNameInList(instruction_name, |
| 391 "fldenvs", "fnstenvs", "fnsaves", | 421 "fldenvs", "fnstenvs", "fnsaves", |
| 392 "frstors", "fsaves", "fstenvs", | 422 "frstors", "fsaves", "fstenvs", |
| 393 "in", "ins", "out", "outs", | 423 "in", "ins", "out", "outs", |
| 394 "popf", "push", "pushf", NULL))) | 424 "popf", "push", "pushf", NULL))) |
| 395 spurious_rex_prefix = TRUE; | 425 spurious_rex_prefix = TRUE; |
| 396 | 426 |
| 427 /* | |
| 428 * Print prefixes. For the case where two prefixes are present we must print | |
| 429 * them in a corrent order. First print prefixes from begin[0], then handle | |
| 430 * prefixes from begin[1] (at this point we don't support more then two | |
| 431 * prefixes). | |
| 432 */ | |
| 397 if (instruction->prefix.lock && (begin[0] == 0xf0)) | 433 if (instruction->prefix.lock && (begin[0] == 0xf0)) |
| 398 print_name("lock "); | 434 print_name("lock "); |
| 399 if (instruction->prefix.repnz && (begin[0] == 0xf2)) | 435 if (instruction->prefix.repnz && (begin[0] == 0xf2)) |
| 400 print_name("repnz "); | 436 print_name("repnz "); |
| 401 if (instruction->prefix.repz && (begin[0] == 0xf3)) { | 437 if (instruction->prefix.repz && (begin[0] == 0xf3)) { |
| 402 /* | 438 /* |
| 403 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other | 439 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other |
| 404 * instructions print "repz". | 440 * instructions print "repz". |
| 405 */ | 441 */ |
| 406 if (IsNameInList(instruction_name, | 442 if (IsNameInList(instruction_name, |
| 407 "ins", "lods", "movs", "outs", "stos", NULL)) | 443 "ins", "lods", "movs", "outs", "stos", NULL)) |
| 408 print_name("rep "); | 444 print_name("rep "); |
| 409 else | 445 else |
| 410 print_name("repz "); | 446 print_name("repz "); |
| 411 } | 447 } |
| 412 | |
| 413 if (((data16_prefix) && (rex_prefix & 0x08)) && | 448 if (((data16_prefix) && (rex_prefix & 0x08)) && |
| 414 !IsNameInList(instruction_name, | 449 !IsNameInList(instruction_name, |
| 415 "bsf", "bsr", "fldenvs", "fnstenvs", "fnsaves", "frstors", | 450 "bsf", "bsr", "fldenvs", "fnstenvs", "fnsaves", "frstors", |
| 416 "fsaves", "fstenvs", "movbe", NULL)) { | 451 "fsaves", "fstenvs", "movbe", NULL)) { |
| 417 if ((end - begin) != 3 || | 452 if ((end - begin) != 3 || |
| 418 (begin[0] != 0x66) || ((begin[1] & 0x48) != 0x48) || (begin[2] != 0x90)) | 453 (begin[0] != 0x66) || ((begin[1] & 0x48) != 0x48) || (begin[2] != 0x90)) |
| 419 print_name("data32 "); | 454 print_name("data32 "); |
| 420 } | 455 } |
| 421 | |
| 422 if (instruction->prefix.lock && (begin[0] != 0xf0)) { | 456 if (instruction->prefix.lock && (begin[0] != 0xf0)) { |
| 423 print_name("lock "); | 457 print_name("lock "); |
| 424 } | 458 } |
| 425 if (instruction->prefix.repnz && (begin[0] != 0xf2)) { | 459 if (instruction->prefix.repnz && (begin[0] != 0xf2)) { |
| 426 print_name("repnz "); | 460 print_name("repnz "); |
| 427 } | 461 } |
| 428 if (instruction->prefix.repz && (begin[0] != 0xf3)) { | 462 if (instruction->prefix.repz && (begin[0] != 0xf3)) { |
| 429 /* | 463 /* |
| 430 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other | 464 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other |
| 431 * instructions print "repz". | 465 * instructions print "repz". |
| 432 */ | 466 */ |
| 433 if (IsNameInList(instruction_name, | 467 if (IsNameInList(instruction_name, |
| 434 "ins", "lods", "movs", "outs", "stos", NULL)) | 468 "ins", "lods", "movs", "outs", "stos", NULL)) |
| 435 print_name("rep "); | 469 print_name("rep "); |
| 436 else | 470 else |
| 437 print_name("repz "); | 471 print_name("repz "); |
| 438 } | 472 } |
| 439 | 473 |
| 474 /* | |
| 475 * REX prefix. Empty REX prefix (without REX.B, REX.X, REX.R, or REX.W bits) | |
| 476 * is not always spurious: it can be used to select between 8-bit registers | |
| 477 * (%ah vs %spl, %ch vs %bpl, %dh vs %dil, and %bh vs %sil). | |
| 478 */ | |
| 440 if (rex_prefix == 0x40) { | 479 if (rex_prefix == 0x40) { |
| 441 if (operands_count > 0) | 480 if (operands_count > 0) |
| 442 for (i=0; i<operands_count; ++i) | 481 for (i=0; i<operands_count; ++i) |
| 443 /* | 482 /* |
| 444 * "Empty" rex prefix (0x40) is used to select "sil"/"dil"/"spl"/"bpl". | 483 * "Empty" rex prefix (0x40) is used to select "sil"/"dil"/"spl"/"bpl". |
| 445 */ | 484 */ |
| 446 if (instruction->operands[i].type == OPERAND_TYPE_8_BIT && | 485 if (instruction->operands[i].type == OPERAND_TYPE_8_BIT && |
| 447 instruction->operands[i].name <= REG_RDI) { | 486 instruction->operands[i].name <= REG_RDI) { |
| 448 empty_rex_prefix_ok = TRUE; | 487 empty_rex_prefix_ok = TRUE; |
| 449 } | 488 } |
| 450 if (!empty_rex_prefix_ok) | 489 if (!empty_rex_prefix_ok) |
| 451 print_name("rex "); | 490 print_name("rex "); |
| 491 /* | |
| 492 * Non-empty REX prefix is shown if and only if if it's spurious. | |
|
Brad Chen
2012/10/22 21:29:05
if if
| |
| 493 */ | |
| 452 } else if (spurious_rex_prefix) { | 494 } else if (spurious_rex_prefix) { |
| 453 print_name("rex."); | 495 print_name("rex."); |
| 454 if (rex_prefix & 0x08) { | 496 if (rex_prefix & 0x08) { |
| 455 print_name("W"); | 497 print_name("W"); |
| 456 } | 498 } |
| 457 if (rex_prefix & 0x04) { | 499 if (rex_prefix & 0x04) { |
| 458 print_name("R"); | 500 print_name("R"); |
| 459 } | 501 } |
| 460 if (rex_prefix & 0x02) { | 502 if (rex_prefix & 0x02) { |
| 461 print_name("X"); | 503 print_name("X"); |
| 462 } | 504 } |
| 463 if (rex_prefix & 0x01) { | 505 if (rex_prefix & 0x01) { |
| 464 print_name("B"); | 506 print_name("B"); |
| 465 } | 507 } |
| 466 print_name(" "); | 508 print_name(" "); |
| 467 } | 509 } |
| 468 | 510 |
| 511 /* Prefixes are printed. Print the instruction name. */ | |
| 469 printf("%s", instruction_name); | 512 printf("%s", instruction_name); |
| 470 shown_name += strlen(instruction_name); | 513 shown_name += strlen(instruction_name); |
| 471 | 514 |
| 515 /* In some cases AT&T instruction uses suffix to show the size of operand. */ | |
|
Brad Chen
2012/10/22 21:29:05
It looks to me like it may be the case that the st
| |
| 472 if (instruction->att_instruction_suffix) { | 516 if (instruction->att_instruction_suffix) { |
| 517 /* But special versions of "nop" never use these suffixes. */ | |
| 473 if (!IsNameInList(instruction_name, | 518 if (!IsNameInList(instruction_name, |
| 474 "nopw 0x0(%eax,%eax,1)", | 519 "nopw 0x0(%eax,%eax,1)", |
| 475 "nopw 0x0(%rax,%rax,1)", | 520 "nopw 0x0(%rax,%rax,1)", |
| 476 NULL)) { | 521 NULL)) { |
| 477 printf("%s", instruction->att_instruction_suffix); | 522 printf("%s", instruction->att_instruction_suffix); |
| 478 shown_name += strlen(instruction->att_instruction_suffix); | 523 shown_name += strlen(instruction->att_instruction_suffix); |
| 479 } | 524 } |
| 480 } else { | 525 } else { |
| 481 /* | 526 /* |
| 482 * Objdump prints size suffixes for "crc32" instruction even when it's | 527 * Objdump prints size suffixes for "crc32" instruction even when it's |
| 483 * not really needed. | 528 * not really needed. |
| 484 */ | 529 */ |
| 485 if (strcmp(instruction_name, "crc32") == 0) { | 530 if (strcmp(instruction_name, "crc32") == 0) { |
| 486 if (instruction->operands[1].type == OPERAND_TYPE_8_BIT) | 531 if (instruction->operands[1].type == OPERAND_TYPE_8_BIT) |
| 487 print_name("b"); | 532 print_name("b"); |
| 488 else if (instruction->operands[1].type == OPERAND_TYPE_16_BIT) | 533 else if (instruction->operands[1].type == OPERAND_TYPE_16_BIT) |
| 489 print_name("w"); | 534 print_name("w"); |
| 490 else if (instruction->operands[1].type == OPERAND_TYPE_32_BIT) | 535 else if (instruction->operands[1].type == OPERAND_TYPE_32_BIT) |
| 491 print_name("l"); | 536 print_name("l"); |
| 492 else if (instruction->operands[1].type == OPERAND_TYPE_64_BIT) | 537 else if (instruction->operands[1].type == OPERAND_TYPE_64_BIT) |
| 493 print_name("q"); | 538 print_name("q"); |
| 494 } | 539 } |
| 495 } | 540 } |
| 541 | |
| 542 /* Regular "mov" with 64-bit immediate is printed as "movabs" by objdump. */ | |
| 496 if (strcmp(instruction_name, "mov") == 0 && | 543 if (strcmp(instruction_name, "mov") == 0 && |
| 497 instruction->operands[1].name == REG_IMM && | 544 instruction->operands[1].name == REG_IMM && |
| 498 instruction->operands[1].type == OPERAND_TYPE_64_BIT) | 545 instruction->operands[1].type == OPERAND_TYPE_64_BIT) |
| 499 print_name("abs"); | 546 print_name("abs"); |
| 500 | 547 |
| 548 /* | |
| 549 * Jump instructions can use branch-prediction prefixes. They are shown as | |
| 550 * suffixes by objdump. | |
| 551 */ | |
| 501 if (IsNameInList(instruction_name, | 552 if (IsNameInList(instruction_name, |
| 502 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", | 553 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", |
| 503 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", | 554 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", |
| 504 "jecxz", "jrcxz", "loop", "loope", "loopne", NULL)) { | 555 "jecxz", "jrcxz", "loop", "loope", "loopne", NULL)) { |
| 505 if (instruction->prefix.branch_not_taken) | 556 if (instruction->prefix.branch_not_taken) |
| 506 print_name(",pn"); | 557 print_name(",pn"); |
| 507 else if (instruction->prefix.branch_taken) | 558 else if (instruction->prefix.branch_taken) |
| 508 print_name(",pt"); | 559 print_name(",pt"); |
| 509 } | 560 } |
| 561 #undef print_name | |
| 510 | 562 |
| 511 #undef print_name | 563 /* Objdump does not print spaces after some "special" instructions. */ |
| 512 if ((strcmp(instruction_name, "nop") != 0 || operands_count != 0) && | 564 if ((strcmp(instruction_name, "nop") != 0 || operands_count != 0) && |
| 513 !IsNameInList( | 565 !IsNameInList( |
| 514 instruction_name, | 566 instruction_name, |
| 515 "fwait", | 567 "fwait", |
| 516 "nopw 0x0(%eax,%eax,1)", | 568 "nopw 0x0(%eax,%eax,1)", |
| 517 "nopw 0x0(%rax,%rax,1)", | 569 "nopw 0x0(%rax,%rax,1)", |
| 518 "nopw %cs:0x0(%eax,%eax,1)", | 570 "nopw %cs:0x0(%eax,%eax,1)", |
| 519 "nopw %cs:0x0(%rax,%rax,1)", | 571 "nopw %cs:0x0(%rax,%rax,1)", |
| 520 "nopw %cs:0x0(%eax,%eax,1)", | 572 "nopw %cs:0x0(%eax,%eax,1)", |
| 521 "nopw %cs:0x0(%rax,%rax,1)", | 573 "nopw %cs:0x0(%rax,%rax,1)", |
| 522 "data32 nopw %cs:0x0(%eax,%eax,1)", | 574 "data32 nopw %cs:0x0(%eax,%eax,1)", |
| 523 "data32 nopw %cs:0x0(%rax,%rax,1)", | 575 "data32 nopw %cs:0x0(%rax,%rax,1)", |
| 524 "data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 576 "data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
| 525 "data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 577 "data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
| 526 "data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 578 "data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
| 527 "data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 579 "data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
| 528 "data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 580 "data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
| 529 "data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 581 "data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
| 530 "data32 data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 582 "data32 data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
| 531 "data32 data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 583 "data32 data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
| 532 NULL)) { | 584 NULL)) { |
| 585 /* | |
| 586 * In this is "regular" instruction with a short name then it's operands are | |
| 587 * aligned. | |
| 588 */ | |
| 533 while (shown_name < 6) { | 589 while (shown_name < 6) { |
| 534 printf(" "); | 590 printf(" "); |
| 535 ++shown_name; | 591 ++shown_name; |
| 536 } | 592 } |
| 537 if (operands_count == 0) | 593 if (operands_count == 0) |
| 538 printf(" "); | 594 printf(" "); |
| 539 } | 595 } |
| 596 | |
| 597 /* Print instruction operands. */ | |
| 540 for (i=operands_count-1; i>=0; --i) { | 598 for (i=operands_count-1; i>=0; --i) { |
| 541 printf("%c", delimeter); | 599 printf("%c", delimeter); |
| 600 /* If the instruction is "call" or "jmp" then we need to print asterics. */ | |
| 542 if (IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && | 601 if (IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && |
| 543 instruction->operands[i].name != JMP_TO) | 602 instruction->operands[i].name != JMP_TO) |
| 544 printf("*"); | 603 printf("*"); |
| 545 /* | 604 /* |
| 546 * Both AMD manual and Intel manual agree that mov from general purpose | 605 * Both AMD manual and Intel manual agree that mov from general purpose |
| 547 * register to segment register has signature "mov Ew Sw", but objdump | 606 * register to segment register has signature "mov Ew Sw", but objdump |
| 548 * insists on 32bit/64 bit. This is clearly an error in objdump so we fix | 607 * insists on 32bit/64 bit. This is clearly an error in objdump so we fix |
| 549 * it here and not in decoder. | 608 * it here and not in decoder. |
| 550 */ | 609 */ |
| 551 if ((begin[0] >= 0x48) && (begin[0] <= 0x4f) && (begin[1] == 0x8e) && | 610 if ((begin[0] >= 0x48) && (begin[0] <= 0x4f) && (begin[1] == 0x8e) && |
| 552 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { | 611 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { |
| 553 operand_type = OPERAND_TYPE_64_BIT; | 612 operand_type = OPERAND_TYPE_64_BIT; |
| 554 } else if (((begin[0] == 0x8e) || | 613 } else if (((begin[0] == 0x8e) || |
| 555 ((begin[0] >= 0x40) && (begin[0] <= 0x4f) && (begin[1] == 0x8e))) && | 614 ((begin[0] >= 0x40) && (begin[0] <= 0x4f) && (begin[1] == 0x8e))) && |
| 556 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { | 615 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { |
| 557 operand_type = OPERAND_TYPE_32_BIT; | 616 operand_type = OPERAND_TYPE_32_BIT; |
| 558 } else { | 617 } else { |
| 559 operand_type = instruction->operands[i].type; | 618 operand_type = instruction->operands[i].type; |
| 560 } | 619 } |
| 620 | |
| 621 /* All the special cases are handled, let's print the normal operands! */ | |
| 561 switch (instruction->operands[i].name) { | 622 switch (instruction->operands[i].name) { |
| 562 case REG_RAX: | 623 case REG_RAX: |
| 563 case REG_RCX: | 624 case REG_RCX: |
| 564 case REG_RDX: | 625 case REG_RDX: |
| 565 case REG_RBX: | 626 case REG_RBX: |
| 566 case REG_RSP: | 627 case REG_RSP: |
| 567 case REG_RBP: | 628 case REG_RBP: |
| 568 case REG_RSI: | 629 case REG_RSI: |
| 569 case REG_RDI: | 630 case REG_RDI: |
| 570 case REG_R8: | 631 case REG_R8: |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 583 printf("%%st"); | 644 printf("%%st"); |
| 584 break; | 645 break; |
| 585 case REG_RM: | 646 case REG_RM: |
| 586 if (instruction->rm.disp_type != DISPNONE) { | 647 if (instruction->rm.disp_type != DISPNONE) { |
| 587 if ((instruction->rm.disp_type == DISP64) || | 648 if ((instruction->rm.disp_type == DISP64) || |
| 588 (instruction->rm.offset >= 0)) | 649 (instruction->rm.offset >= 0)) |
| 589 printf("0x%"NACL_PRIx64, instruction->rm.offset); | 650 printf("0x%"NACL_PRIx64, instruction->rm.offset); |
| 590 else | 651 else |
| 591 printf("-0x%"NACL_PRIx64, -instruction->rm.offset); | 652 printf("-0x%"NACL_PRIx64, -instruction->rm.offset); |
| 592 } | 653 } |
| 593 if (((struct DecodeState *)userdata)->ia32_mode) { | 654 if (userdata->ia32_mode) { |
| 594 if ((rm_base != NO_REG) || | 655 if ((rm_base != NO_REG) || |
| 595 (rm_index != NO_REG) || | 656 (rm_index != NO_REG) || |
| 596 (instruction->rm.scale != 0)) | 657 (instruction->rm.scale != 0)) |
| 597 printf("("); | 658 printf("("); |
| 598 if (rm_base != NO_REG) | 659 if (rm_base != NO_REG) |
| 599 printf("%%%s", | 660 printf("%%%s", |
| 600 RegisterNameAsString(rm_base, OPERAND_TYPE_32_BIT, FALSE)); | 661 RegisterNameAsString(rm_base, OPERAND_TYPE_32_BIT, FALSE)); |
| 601 if (rm_index == REG_RIZ) { | 662 if (rm_index == REG_RIZ) { |
| 602 if ((rm_base != REG_RSP) || (instruction->rm.scale != 0)) | 663 if ((rm_base != REG_RSP) || (instruction->rm.scale != 0)) |
| 603 printf(",%%eiz,%d", 1 << instruction->rm.scale); | 664 printf(",%%eiz,%d", 1 << instruction->rm.scale); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 642 case REG_IMM: | 703 case REG_IMM: |
| 643 printf("$0x%"NACL_PRIx64,instruction->imm[0]); | 704 printf("$0x%"NACL_PRIx64,instruction->imm[0]); |
| 644 break; | 705 break; |
| 645 case REG_IMM2: | 706 case REG_IMM2: |
| 646 printf("$0x%"NACL_PRIx64,instruction->imm[1]); | 707 printf("$0x%"NACL_PRIx64,instruction->imm[1]); |
| 647 break; | 708 break; |
| 648 case REG_PORT_DX: | 709 case REG_PORT_DX: |
| 649 printf("(%%dx)"); | 710 printf("(%%dx)"); |
| 650 break; | 711 break; |
| 651 case REG_DS_RBX: | 712 case REG_DS_RBX: |
| 652 if (((struct DecodeState *)userdata)->ia32_mode) | 713 if (userdata->ia32_mode) |
| 653 printf("%%ds:(%%ebx)"); | 714 printf("%%ds:(%%ebx)"); |
| 654 else | 715 else |
| 655 printf("%%ds:(%%rbx)"); | 716 printf("%%ds:(%%rbx)"); |
| 656 break; | 717 break; |
| 657 case REG_ES_RDI: | 718 case REG_ES_RDI: |
| 658 if (((struct DecodeState *)userdata)->ia32_mode) | 719 if (userdata->ia32_mode) |
| 659 printf("%%es:(%%edi)"); | 720 printf("%%es:(%%edi)"); |
| 660 else | 721 else |
| 661 printf("%%es:(%%rdi)"); | 722 printf("%%es:(%%rdi)"); |
| 662 break; | 723 break; |
| 663 case REG_DS_RSI: | 724 case REG_DS_RSI: |
| 664 if (((struct DecodeState *)userdata)->ia32_mode) | 725 if (userdata->ia32_mode) |
| 665 printf("%%ds:(%%esi)"); | 726 printf("%%ds:(%%esi)"); |
| 666 else | 727 else |
| 667 printf("%%ds:(%%rsi)"); | 728 printf("%%ds:(%%rsi)"); |
| 668 break; | 729 break; |
| 669 case JMP_TO: | 730 case JMP_TO: |
| 670 if (instruction->operands[0].type == OPERAND_TYPE_16_BIT) | 731 if (instruction->operands[0].type == OPERAND_TYPE_16_BIT) |
| 671 printf("0x%lx", (long)((end + instruction->rm.offset - | 732 printf("0x%lx", (long)((end + instruction->rm.offset - |
| 672 (((struct DecodeState *)userdata)->offset)) & 0xffff)); | 733 (userdata->offset)) & 0xffff)); |
| 673 else | 734 else |
| 674 printf("0x%lx", (long)(end + instruction->rm.offset - | 735 printf("0x%lx", (long)(end + instruction->rm.offset - |
| 675 (((struct DecodeState *)userdata)->offset))); | 736 (userdata->offset))); |
| 676 break; | 737 break; |
| 677 case REG_RIP: | 738 case REG_RIP: |
| 678 case REG_RIZ: | 739 case REG_RIZ: |
| 679 case NO_REG: | 740 case NO_REG: |
| 680 assert(FALSE); | 741 assert(FALSE); |
| 681 } | 742 } |
| 682 delimeter = ','; | 743 delimeter = ','; |
| 683 } | 744 } |
| 745 | |
| 746 /* | |
| 747 * If %rip was used then objdump will show the actual address as the comment. | |
| 748 */ | |
| 684 if (print_rip) { | 749 if (print_rip) { |
| 685 printf(" # 0x%8"NACL_PRIx64, | 750 printf(" # 0x%8"NACL_PRIx64, |
| 686 (uint64_t) (end + instruction->rm.offset - | 751 (uint64_t) (end + instruction->rm.offset - |
| 687 (((struct DecodeState *)userdata)->offset))); | 752 (userdata->offset))); |
| 688 } | 753 } |
| 754 | |
| 755 /* First line of instruction decoding is printed. Finish the line. */ | |
| 689 printf("\n"); | 756 printf("\n"); |
| 690 begin += 7; | 757 begin += 7; |
| 758 /* if there are more then seven bytes we need to print the rest. */ | |
| 691 while (begin < end) { | 759 while (begin < end) { |
| 692 printf("%*"NACL_PRIx64":\t", ((struct DecodeState *)userdata)->width, | 760 printf("%*"NACL_PRIx64":\t", userdata->width, |
| 693 (uint64_t) (begin - (((struct DecodeState *)userdata)->offset))); | 761 (uint64_t) (begin - (userdata->offset))); |
| 694 for (p = begin; p < begin + 7; ++p) { | 762 for (p = begin; p < begin + 7; ++p) { |
| 695 if (p >= end) { | 763 if (p >= end) { |
| 696 printf("\n"); | 764 printf("\n"); |
| 697 return; | 765 return; |
| 698 } else { | 766 } else { |
| 699 printf("%02x ", *p); | 767 printf("%02x ", *p); |
| 700 } | 768 } |
| 701 } | 769 } |
| 702 printf("\n"); | 770 printf("\n"); |
| 703 if (p >= end) | 771 if (p >= end) |
| 704 return; | 772 return; |
| 705 begin += 7; | 773 begin += 7; |
| 706 } | 774 } |
| 707 } | 775 } |
| 708 | 776 |
| 709 void ProcessError (const uint8_t *ptr, void *userdata) { | 777 void ProcessError (const uint8_t *ptr, void *userdata) { |
| 710 printf("rejected at %"NACL_PRIx64" (byte 0x%02"NACL_PRIx32")\n", | 778 printf("rejected at %"NACL_PRIx64" (byte 0x%02"NACL_PRIx32")\n", |
| 711 (uint64_t) (ptr - (((struct DecodeState *)userdata)->offset)), | 779 (uint64_t) (ptr - (((struct DecodeState *)userdata)->offset)), |
| 712 *ptr); | 780 *ptr); |
| 713 } | 781 } |
| 714 | 782 |
| 715 int DecodeFile(const char *filename, int repeat_count) { | 783 int DecodeFile(const char *filename, int repeat_count) { |
|
Brad Chen
2012/10/22 21:29:05
The two if statements that follow the calls to Che
| |
| 716 size_t data_size; | 784 size_t data_size; |
| 717 uint8_t *data; | 785 uint8_t *data; |
| 718 int count; | 786 int count; |
| 719 | 787 |
| 720 ReadImage(filename, &data, &data_size); | 788 ReadImage(filename, &data, &data_size); |
| 721 if (data[4] == 1) { | 789 if (data[4] == 1) { |
| 722 for (count = 0; count < repeat_count; ++count) { | 790 for (count = 0; count < repeat_count; ++count) { |
| 723 Elf32_Ehdr *header; | 791 Elf32_Ehdr *header; |
| 724 int index; | 792 int index; |
| 725 | 793 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 816 return 0; | 884 return 0; |
| 817 } | 885 } |
| 818 | 886 |
| 819 int main(int argc, char **argv) { | 887 int main(int argc, char **argv) { |
| 820 int index, initial_index = 1, repeat_count = 1; | 888 int index, initial_index = 1, repeat_count = 1; |
| 821 if (argc == 1) { | 889 if (argc == 1) { |
| 822 printf("%s: no input files\n", argv[0]); | 890 printf("%s: no input files\n", argv[0]); |
| 823 exit(1); | 891 exit(1); |
| 824 } | 892 } |
| 825 if (!strcmp(argv[1], "--repeat")) | 893 if (!strcmp(argv[1], "--repeat")) |
| 826 repeat_count = atoi(argv[2]), | 894 repeat_count = atoi(argv[2]), |
|
Dmitry Polukhin
2012/11/02 17:31:06
Please don't use comma to separate statements. Thi
| |
| 827 initial_index += 2; | 895 initial_index += 2; |
| 828 for (index = initial_index; index < argc; ++index) { | 896 for (index = initial_index; index < argc; ++index) { |
| 829 const char *filename = argv[index]; | 897 const char *filename = argv[index]; |
| 830 int rc = DecodeFile(filename, repeat_count); | 898 int rc = DecodeFile(filename, repeat_count); |
| 831 if (!rc) { | 899 if (!rc) { |
| 832 printf("file '%s' can not be fully decoded\n", filename); | 900 printf("file '%s' can not be fully decoded\n", filename); |
| 833 return 1; | 901 return 1; |
| 834 } | 902 } |
| 835 } | 903 } |
| 836 return 0; | 904 return 0; |
| 837 } | 905 } |
| OLD | NEW |