766 |
|
#endif |
767 |
|
|
768 |
|
// Decode instruction |
769 |
+ |
int target_size = SIZE_UNKNOWN; |
770 |
|
switch (eip[0]) { |
771 |
|
case 0x0f: |
772 |
+ |
target_size = transfer_size; |
773 |
|
switch (eip[1]) { |
774 |
+ |
case 0xbe: // MOVSX r32, r/m8 |
775 |
|
case 0xb6: // MOVZX r32, r/m8 |
776 |
+ |
transfer_size = SIZE_BYTE; |
777 |
+ |
goto do_mov_extend; |
778 |
|
case 0xb7: // MOVZX r32, r/m16 |
779 |
< |
switch (eip[2] & 0xc0) { |
780 |
< |
case 0x80: |
781 |
< |
reg = (eip[2] >> 3) & 7; |
782 |
< |
transfer_type = SIGSEGV_TRANSFER_LOAD; |
783 |
< |
break; |
784 |
< |
case 0x40: |
785 |
< |
reg = (eip[2] >> 3) & 7; |
786 |
< |
transfer_type = SIGSEGV_TRANSFER_LOAD; |
787 |
< |
break; |
788 |
< |
case 0x00: |
789 |
< |
reg = (eip[2] >> 3) & 7; |
790 |
< |
transfer_type = SIGSEGV_TRANSFER_LOAD; |
791 |
< |
break; |
792 |
< |
} |
793 |
< |
len += 3 + ix86_step_over_modrm(eip + 2); |
794 |
< |
break; |
779 |
> |
transfer_size = SIZE_WORD; |
780 |
> |
goto do_mov_extend; |
781 |
> |
do_mov_extend: |
782 |
> |
switch (eip[2] & 0xc0) { |
783 |
> |
case 0x80: |
784 |
> |
reg = (eip[2] >> 3) & 7; |
785 |
> |
transfer_type = SIGSEGV_TRANSFER_LOAD; |
786 |
> |
break; |
787 |
> |
case 0x40: |
788 |
> |
reg = (eip[2] >> 3) & 7; |
789 |
> |
transfer_type = SIGSEGV_TRANSFER_LOAD; |
790 |
> |
break; |
791 |
> |
case 0x00: |
792 |
> |
reg = (eip[2] >> 3) & 7; |
793 |
> |
transfer_type = SIGSEGV_TRANSFER_LOAD; |
794 |
> |
break; |
795 |
> |
} |
796 |
> |
len += 3 + ix86_step_over_modrm(eip + 2); |
797 |
> |
break; |
798 |
|
} |
799 |
|
break; |
800 |
|
case 0x8a: // MOV r8, r/m8 |
836 |
|
len += 2 + ix86_step_over_modrm(eip + 1); |
837 |
|
break; |
838 |
|
} |
839 |
+ |
if (target_size == SIZE_UNKNOWN) |
840 |
+ |
target_size = transfer_size; |
841 |
|
|
842 |
|
if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) { |
843 |
|
// Unknown machine code, let it crash. Then patch the decoder |
865 |
|
// Set 0 to the relevant register part |
866 |
|
// NOTE: this is only valid for MOV alike instructions |
867 |
|
int rloc = x86_reg_map[reg]; |
868 |
< |
switch (transfer_size) { |
868 |
> |
switch (target_size) { |
869 |
|
case SIZE_BYTE: |
870 |
|
if (has_rex || reg < 4) |
871 |
|
regs[rloc] = (regs[rloc] & ~0x00ffL); |