@ -655,13 +655,15 @@ ShemuSetGprValue(
bool High8
)
{
uint32_t bit ;
switch ( Size )
{
case 1 :
if ( High8 )
{
// AH, CH, DH or BH accessed.
* ( ( uint8_t * ) ( & Context - > Registers . RegRax + Reg - 4 ) + 1 ) = Value & 0x FF ;
* ( ( uint8_t * ) ( & Context - > Registers . RegRax + Reg - 4 ) + 1 ) = Value & 0x ff ;
}
else
{
@ -682,6 +684,55 @@ ShemuSetGprValue(
* ( & Context - > Registers . RegRax + Reg ) = Value ;
break ;
}
if ( High8 )
{
bit = Reg - 4 ;
}
else
{
bit = Reg ;
}
// Mark the GPR as being dirty/written.
Context - > DirtyGprBitmap | = ( 1 < < bit ) ;
}
//
// ShemuCmpGprValue
//
static bool
ShemuCmpGprValue (
SHEMU_CONTEXT * Context ,
uint32_t Reg ,
uint32_t Size ,
uint64_t Value ,
bool High8
)
{
switch ( Size )
{
case 1 :
if ( High8 )
{
// AH, CH, DH or BH.
return * ( ( uint8_t * ) ( & Context - > Registers . RegRax + Reg - 4 ) + 1 ) = = ( Value & 0xff ) ;
}
else
{
return * ( ( uint8_t * ) ( & Context - > Registers . RegRax + Reg ) ) = = ( Value & 0xff ) ;
}
case 2 :
return * ( ( uint16_t * ) ( & Context - > Registers . RegRax + Reg ) ) = = ( Value & 0xffff ) ;
case 4 :
return * ( ( uint32_t * ) ( & Context - > Registers . RegRax + Reg ) ) = = ( Value & 0xffffffff ) ;
default :
return * ( & Context - > Registers . RegRax + Reg ) = = Value ;
}
}
@ -1299,6 +1350,8 @@ ShemuSetOperandValue(
// Handle RIP save on the stack.
if ( ShemuIsStackPtr ( Context , gla , MAX ( op - > Size , Context - > Instruction . WordLength ) ) )
{
uint8_t stckstrlen = 0 ;
// Note: only Context->Instruction.WordLength bits are flagged as RIP, as that is the RIP size.
if ( Context - > Instruction . Instruction = = ND_INS_CALLNR | |
Context - > Instruction . Instruction = = ND_INS_CALLNI )
@ -1327,6 +1380,9 @@ ShemuSetOperandValue(
// ...
// PUSH strn
// Other variants may exist, but all we care about are stores on the stack, and all are checked.
// Note that we will ignore registers which have not been modified during emulation; those are considered
// input values for the emulated code, and may be pointers or other data. We are interested only in
// stack values built within the emulate code.
for ( uint32_t i = 0 ; i < Value - > Size ; i + + )
{
unsigned char c = Value - > Value . Bytes [ i ] ;
@ -1334,18 +1390,40 @@ ShemuSetOperandValue(
if ( ( c > = ' a ' & & c < = ' z ' ) | | ( c > = ' A ' & & c < = ' Z ' ) | | ( c > = ' 0 ' & & c < = ' 9 ' ) | |
c = = ' \\ ' | | c = = ' / ' | | c = = ' : ' | | c = = ' ' )
{
Context - > StrLength + + ;
stckstrlen + + ;
}
else
{
break ;
}
}
if ( Context - > StrLength > = Context - > StrThreshold )
if ( stckstrlen = = Value - > Size )
{
// Make sure the value is not present inside a non-dirty GPR.
for ( uint32_t i = 0 ; i < 16 ; i + + )
{
if ( ShemuCmpGprValue ( Context , i , Value - > Size , Value - > Value . Qwords [ 0 ] , false ) & &
( 0 = = ( Context - > DirtyGprBitmap & ( 1 < < i ) ) ) )
{
Context - > Flags | = SHEMU_FLAG_STACK_STR ;
// A register is saved on the stack, but that register wasn't written during the emulation.
stckstrlen = 0 ;
break ;
}
}
else
{
Context - > StrLength = 0 ;
}
}
Context - > StrLength + = stckstrlen ;
if ( Context - > StrLength > = Context - > StrThreshold )
{
Context - > Flags | = SHEMU_FLAG_STACK_STR ;
}
if ( stckstrlen ! = Value - > Size )
{
// Not a full string stored on the stack, reset the counter.
Context - > StrLength = 0 ;
}
}