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