Valgrind has a lot of heuristics to optimise the speed of the JIT-ted code.
One of these heuristics is to chase jumps/calls to known destination.

This is somewhat similar to inlining performed by the compiler,
but performed by valgrind at runtime, when it encounters a new call/jump.

In this case, the function f1 is inlined twice following this heuristic.
So, the second inlining is using the modified function.

If you disable chasing, then the code prints twice the same value:
  valgrind --tool=none --smc-check=none --vex-guest-chase=no ...
produces twice 4660 as output.

Also, if you do a loop 
  for (int j = 0; j < 2; j++) {
     f1();
     .... here modify f1 code
  }

then valgrind inserts only once the code of f1, and it prints twice the same
value, whatever the parameter --vex-guest-chase

The code that does the self modifying code check is in the function 
needs_self_check
in m_translate.c.  This function is called by VEX.

Philippe


On Fri, 2020-08-28 at 12:15 +0200, Duc Nguyen wrote:
> Hello everyone,
> 
> I am trying the self-modifying-code check of Valgrind but I am not sure if I 
> understand the definition of  self-modifying-code in Valgrind correctly. 
> 
> I had prepared an example (see below) that has function f1 that is first 
> executed in main, outputs something (number 4660). Afterward, two 
> instructions of f1 are modified, and f1 is then executed one more time. It 
> then outputs something (number 22068) that is different from the first time. 
> 
> When I run Valgrind with --smc-check=all and  --smc-check=none I do not see 
> any difference in the outputs of Valgrind e.g., both times f1 produces 
> different numbers (e.g., self-modifying-code successfully runs despite the 
> --smc-check if turned on or off)
> 
> Could someone please let me know if this behavior is expected from Valgrind?
> 
> I further looked into the source code and found 
> valgrind\VEX\priv\guest_generic_bb_to_IR.c that generates the code to check. 
> However, I do not know where such a check is executed. It would be great if 
> somebody knows where such a check takes place, and where we can modify the 
> source code to just simply say e.g., self-modifying-code is found.
> 
> Thank you very much in advance.
> 
> Best regards,
> Duc
> 
> 
> =============================
> Self-modifying-code example
> -------
> 
> 
> 
> #include <stdio.h>
> #include <sys/mman.h>
> #include <unistd.h>
> 
> __asm__( ".text" );
> __asm__( ".align 4096" );
> 
> void f1( void )
> {
>   printf( "%d\n", 0x1234 );
> }
> void f2( void ){
>   printf("this is just a dummy function");
> }
> 
> int main( void )
> {
>   int rc;
>   int pagesize;
>   char *p;
>   int i;
> 
>   printf( "f1=0x%08X.\n", f1 );
> 
>   f1( );
> 
>   pagesize = sysconf( _SC_PAGE_SIZE );
>   printf( "pagesize=%d (0x%08X).\n", pagesize, pagesize );
>   if( pagesize == -1 )
>     return( 2 );
> 
>   p = (char*) f1;
>   rc = mprotect( p, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC );
>   printf( "rc=%d.\n", rc );
>   if( rc != 0 )
>     return( 2 );
>   printf( "'mprotect()' succeeded.\n" );
> 
> 
>   for( i = 0; i+1 < (size_t) f2- (size_t)f1; i++ ) {
>      if( ((char*) f1)[ i ] == 0x34  && ((char*) f1)[ i+1 ] == 0x12 ) {        
>  
>          ((char*) f1)[ i+1 ] =0x78;//here performs self-modifying-code
>          ((char*) f1)[ i+1 ] =0x56;//here performs self-modifying-code
>      }
>    }
>   
>   f1( );//here the output of f1 will be different from the first f1() call
> 
>   printf( "Call succeeded.\n" );
>   return( 0 );
> }    
> 
> 
> _______________________________________________
> Valgrind-users mailing list
> Valgrind-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/valgrind-users



_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to