| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 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 * This file contains includes, static functions, and constants that are used | 8 * This file contains includes, static functions, and constants that are used |
| 9 * in nc_inst_state.c, but have been factored out and put into this file, so | 9 * in nc_inst_state.c, but have been factored out and put into this file, so |
| 10 * that we can test them. That is, to allow nc_inst_state.c and | 10 * that we can test them. That is, to allow nc_inst_state.c and |
| 11 * nc_inst_state_Tests.cc to use them. | 11 * nc_inst_state_Tests.cc to use them. |
| 12 */ | 12 */ |
| 13 | 13 |
| 14 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATICS_C_
_ | 14 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATICS_C_
_ |
| 15 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATICS_C_
_ | 15 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATICS_C_
_ |
| 16 | 16 |
| 17 #include <stdio.h> | 17 #include <stdio.h> |
| 18 #include <assert.h> | 18 #include <assert.h> |
| 19 #include "native_client/src/shared/platform/nacl_log.h" | 19 #include "native_client/src/shared/platform/nacl_log.h" |
| 20 #include "native_client/src/shared/utils/debugging.h" | 20 #include "native_client/src/shared/utils/debugging.h" |
| 21 #include "native_client/src/trusted/validator/x86/decoder/nc_decode_tables.h" | 21 #include "native_client/src/trusted/validator/x86/decoder/nc_decode_tables.h" |
| 22 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" | 22 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" |
| 23 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | 23 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" |
| 24 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h" | 24 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h" |
| 25 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" | 25 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" |
| 26 #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc.h" | 26 #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc.h" |
| 27 #include "native_client/src/trusted/validator/x86/nc_segment.h" | 27 #include "native_client/src/trusted/validator/x86/nc_segment.h" |
| 28 #include "native_client/src/trusted/validator/x86/x86_insts_inl.h" |
| 28 | 29 |
| 29 EXTERN_C_BEGIN | 30 EXTERN_C_BEGIN |
| 30 | 31 |
| 31 /* Given the current location of the instruction iterator, initialize | 32 /* Given the current location of the instruction iterator, initialize |
| 32 * the given state (to match). | 33 * the given state (to match). |
| 33 */ | 34 */ |
| 34 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) { | 35 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) { |
| 35 NaClMemorySize limit; | 36 NaClMemorySize limit; |
| 36 NCInstBytesInit(&state->bytes); | 37 NCInstBytesInit(&state->bytes); |
| 37 state->decoder_tables = iter->decoder_tables; | 38 state->decoder_tables = iter->decoder_tables; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 /* Has modrm byte. */ | 442 /* Has modrm byte. */ |
| 442 if (state->bytes.length >= state->length_limit) { | 443 if (state->bytes.length >= state->length_limit) { |
| 443 DEBUG(NaClLog(LOG_INFO, "Can't read mod/rm, no more bytes!\n")); | 444 DEBUG(NaClLog(LOG_INFO, "Can't read mod/rm, no more bytes!\n")); |
| 444 return FALSE; | 445 return FALSE; |
| 445 } | 446 } |
| 446 byte = NCInstBytesPeek(&state->bytes, 0); | 447 byte = NCInstBytesPeek(&state->bytes, 0); |
| 447 | 448 |
| 448 /* Note: Some instructions only allow values where the ModRm mod field | 449 /* Note: Some instructions only allow values where the ModRm mod field |
| 449 * is 0x3. Others only allow values where the ModRm mod field isn't 0x3. | 450 * is 0x3. Others only allow values where the ModRm mod field isn't 0x3. |
| 450 */ | 451 */ |
| 451 if (modrm_mod(byte) == 0x3) { | 452 if (modrm_modInline(byte) == 0x3) { |
| 452 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIsnt0x3))) { | 453 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIsnt0x3))) { |
| 453 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field is 0x3\n")); | 454 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field is 0x3\n")); |
| 454 return FALSE; | 455 return FALSE; |
| 455 } | 456 } |
| 456 } else { | 457 } else { |
| 457 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIs0x3))) { | 458 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIs0x3))) { |
| 458 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field not 0x3\n")); | 459 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field not 0x3\n")); |
| 459 return FALSE; | 460 return FALSE; |
| 460 } | 461 } |
| 461 } | 462 } |
| 462 if ((NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmRegSOperand))) && | 463 if ((NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmRegSOperand))) && |
| 463 (modrm_reg(byte) > 5)) { | 464 (modrm_regInline(byte) > 5)) { |
| 464 DEBUG(NaClLog(LOG_INFO, | 465 DEBUG(NaClLog(LOG_INFO, |
| 465 "Can't match, modrm reg field doesn't index segment\n")); | 466 "Can't match, modrm reg field doesn't index segment\n")); |
| 466 return FALSE; | 467 return FALSE; |
| 467 } | 468 } |
| 468 state->modrm = NCInstBytesRead(&state->bytes); | 469 state->modrm = NCInstBytesRead(&state->bytes); |
| 469 state->num_disp_bytes = 0; | 470 state->num_disp_bytes = 0; |
| 470 state->first_disp_byte = 0; | 471 state->first_disp_byte = 0; |
| 471 state->sib = 0; | 472 state->sib = 0; |
| 472 state->has_sib = FALSE; | 473 state->has_sib = FALSE; |
| 473 DEBUG(NaClLog(LOG_INFO, "consume modrm = %02"NACL_PRIx8"\n", state->modrm)); | 474 DEBUG(NaClLog(LOG_INFO, "consume modrm = %02"NACL_PRIx8"\n", state->modrm)); |
| 474 | 475 |
| 475 /* Consume the remaining opcode value in the mod/rm byte | 476 /* Consume the remaining opcode value in the mod/rm byte |
| 476 * if applicable. | 477 * if applicable. |
| 477 */ | 478 */ |
| 478 if (state->inst->flags & NACL_IFLAG(OpcodeInModRm)) { | 479 if (state->inst->flags & NACL_IFLAG(OpcodeInModRm)) { |
| 479 const NaClInst* inst = state->inst; | 480 const NaClInst* inst = state->inst; |
| 480 if (modrm_opcode(state->modrm) != | 481 if (modrm_opcodeInline(state->modrm) != |
| 481 NaClGetOpcodeInModRm(inst->opcode_ext)) { | 482 NaClGetOpcodeInModRm(inst->opcode_ext)) { |
| 482 DEBUG( | 483 DEBUG( |
| 483 NaClLog(LOG_INFO, | 484 NaClLog(LOG_INFO, |
| 484 "Discarding, opcode in mrm byte (%02"NACL_PRIx8") " | 485 "Discarding, opcode in mrm byte (%02"NACL_PRIx8") " |
| 485 "does not match\n", | 486 "does not match\n", |
| 486 modrm_opcode(state->modrm))); | 487 modrm_opcodeInline(state->modrm))); |
| 487 return FALSE; | 488 return FALSE; |
| 488 } | 489 } |
| 489 if (state->inst->flags & NACL_IFLAG(OpcodeInModRmRm)) { | 490 if (state->inst->flags & NACL_IFLAG(OpcodeInModRmRm)) { |
| 490 if (modrm_rm(state->modrm) != | 491 if (modrm_rmInline(state->modrm) != |
| 491 NaClGetOpcodeInModRmRm(inst->opcode_ext)) { | 492 NaClGetOpcodeInModRmRm(inst->opcode_ext)) { |
| 492 DEBUG(NaClLog(LOG_INFO, | 493 DEBUG(NaClLog(LOG_INFO, |
| 493 "Discarding, opcode in mrm rm field (%02"NACL_PRIx8") " | 494 "Discarding, opcode in mrm rm field (%02"NACL_PRIx8") " |
| 494 "does not match\n", | 495 "does not match\n", |
| 495 modrm_rm(state->modrm))); | 496 modrm_rmInline(state->modrm))); |
| 496 return FALSE; | 497 return FALSE; |
| 497 } | 498 } |
| 498 } | 499 } |
| 499 } | 500 } |
| 500 } | 501 } |
| 501 return TRUE; | 502 return TRUE; |
| 502 } | 503 } |
| 503 | 504 |
| 504 /* Returns true if the instruction requires a SIB bytes. */ | 505 /* Returns true if the instruction requires a SIB bytes. */ |
| 505 static Bool NaClInstRequiresSib(NaClInstState* state) { | 506 static Bool NaClInstRequiresSib(NaClInstState* state) { |
| 506 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit | 507 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit |
| 507 * addressing. Hence, required for all but 16-bit addressing, when | 508 * addressing. Hence, required for all but 16-bit addressing, when |
| 508 * the right modrm bytes are specified. | 509 * the right modrm bytes are specified. |
| 509 */ | 510 */ |
| 510 return (Bool) | 511 return (Bool) |
| 511 (NaClInstRequiresModRm(state) && (16 != state->address_size) && | 512 (NaClInstRequiresModRm(state) && (16 != state->address_size) && |
| 512 (modrm_rm(state->modrm) == 0x04 && modrm_mod(state->modrm) != 0x3)); | 513 (modrm_rmInline(state->modrm) == |
| 514 0x04 && modrm_modInline(state->modrm) != 0x3)); |
| 513 } | 515 } |
| 514 | 516 |
| 515 /* Consume the SIB byte of the instruction, if applicable. Aborts the pattern | 517 /* Consume the SIB byte of the instruction, if applicable. Aborts the pattern |
| 516 * match if any problems are found. | 518 * match if any problems are found. |
| 517 */ | 519 */ |
| 518 static Bool NaClConsumeSib(NaClInstState* state) { | 520 static Bool NaClConsumeSib(NaClInstState* state) { |
| 519 /* First check that the opcode (instruction) pattern specifies that | 521 /* First check that the opcode (instruction) pattern specifies that |
| 520 * a SIB byte is needed, and that reading it will not walk past | 522 * a SIB byte is needed, and that reading it will not walk past |
| 521 * the end of the code segment. | 523 * the end of the code segment. |
| 522 */ | 524 */ |
| 523 state->sib = 0; | 525 state->sib = 0; |
| 524 state->has_sib = NaClInstRequiresSib(state); | 526 state->has_sib = NaClInstRequiresSib(state); |
| 525 DEBUG(NaClLog(LOG_INFO, "has sib = %d\n", (int) state->has_sib)); | 527 DEBUG(NaClLog(LOG_INFO, "has sib = %d\n", (int) state->has_sib)); |
| 526 if (state->has_sib) { | 528 if (state->has_sib) { |
| 527 if (state->bytes.length >= state->length_limit) { | 529 if (state->bytes.length >= state->length_limit) { |
| 528 DEBUG(NaClLog(LOG_INFO, "Can't consume sib, no more bytes!\n")); | 530 DEBUG(NaClLog(LOG_INFO, "Can't consume sib, no more bytes!\n")); |
| 529 return FALSE; | 531 return FALSE; |
| 530 } | 532 } |
| 531 /* Read the SIB byte and record. */ | 533 /* Read the SIB byte and record. */ |
| 532 state->sib = NCInstBytesRead(&state->bytes); | 534 state->sib = NCInstBytesRead(&state->bytes); |
| 533 DEBUG(NaClLog(LOG_INFO, "sib = %02"NACL_PRIx8"\n", state->sib)); | 535 DEBUG(NaClLog(LOG_INFO, "sib = %02"NACL_PRIx8"\n", state->sib)); |
| 534 if (sib_base(state->sib) == 0x05 && modrm_mod(state->modrm) > 2) { | 536 if (sib_base(state->sib) == 0x05 && modrm_modInline(state->modrm) > 2) { |
| 535 DEBUG(NaClLog(LOG_INFO, | 537 DEBUG(NaClLog(LOG_INFO, |
| 536 "Sib byte implies modrm.mod field <= 2, match fails\n")); | 538 "Sib byte implies modrm.mod field <= 2, match fails\n")); |
| 537 return FALSE; | 539 return FALSE; |
| 538 } | 540 } |
| 539 } | 541 } |
| 540 return TRUE; | 542 return TRUE; |
| 541 } | 543 } |
| 542 | 544 |
| 543 static int NaClGetNumDispBytes(NaClInstState* state) { | 545 static int NaClGetNumDispBytes(NaClInstState* state) { |
| 544 if (NaClInstRequiresModRm(state)) { | 546 if (NaClInstRequiresModRm(state)) { |
| 545 if (16 == state->address_size) { | 547 if (16 == state->address_size) { |
| 546 /* Corresponding to table 2-1 of the Intel manual. */ | 548 /* Corresponding to table 2-1 of the Intel manual. */ |
| 547 switch (modrm_mod(state->modrm)) { | 549 switch (modrm_modInline(state->modrm)) { |
| 548 case 0x0: | 550 case 0x0: |
| 549 if (modrm_rm(state->modrm) == 0x06) { | 551 if (modrm_rmInline(state->modrm) == 0x06) { |
| 550 return 4; /* disp16 */ | 552 return 4; /* disp16 */ |
| 551 } | 553 } |
| 552 break; | 554 break; |
| 553 case 0x1: | 555 case 0x1: |
| 554 return 1; /* disp8 */ | 556 return 1; /* disp8 */ |
| 555 case 0x2: | 557 case 0x2: |
| 556 return 2; /* disp16 */ | 558 return 2; /* disp16 */ |
| 557 default: | 559 default: |
| 558 break; | 560 break; |
| 559 } | 561 } |
| 560 } else { | 562 } else { |
| 561 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit | 563 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit |
| 562 * addressing. Hence, this section covers the 32-bit addressing. | 564 * addressing. Hence, this section covers the 32-bit addressing. |
| 563 */ | 565 */ |
| 564 switch(modrm_mod(state->modrm)) { | 566 switch(modrm_modInline(state->modrm)) { |
| 565 case 0x0: | 567 case 0x0: |
| 566 if (modrm_rm(state->modrm) == 0x05) { | 568 if (modrm_rmInline(state->modrm) == 0x05) { |
| 567 return 4; /* disp32 */ | 569 return 4; /* disp32 */ |
| 568 } else if (state->has_sib && sib_base(state->sib) == 0x5) { | 570 } else if (state->has_sib && sib_base(state->sib) == 0x5) { |
| 569 return 4; | 571 return 4; |
| 570 } | 572 } |
| 571 break; | 573 break; |
| 572 case 0x1: | 574 case 0x1: |
| 573 return 1; /* disp8 */ | 575 return 1; /* disp8 */ |
| 574 case 0x2: | 576 case 0x2: |
| 575 return 4; /* disp32 */ | 577 return 4; /* disp32 */ |
| 576 default: | 578 default: |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 state->inst = matching_inst; | 921 state->inst = matching_inst; |
| 920 NCInstBytesReadBytes(matching_length, &state->bytes); | 922 NCInstBytesReadBytes(matching_length, &state->bytes); |
| 921 DEBUG(NaClLog(LOG_INFO, "matched inst sequence [%d]!\n", matching_length)); | 923 DEBUG(NaClLog(LOG_INFO, "matched inst sequence [%d]!\n", matching_length)); |
| 922 return TRUE; | 924 return TRUE; |
| 923 } | 925 } |
| 924 } | 926 } |
| 925 | 927 |
| 926 EXTERN_C_END | 928 EXTERN_C_END |
| 927 | 929 |
| 928 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATIC
S_C__ */ | 930 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATIC
S_C__ */ |
| OLD | NEW |