📄 smc1.c
字号:
/* Test Valgrind's ability to spot writes to code which has been translated, and discard the out-of-date translations. CORRECT output is in p 0 in q 1 in p 2 in q 3 in p 4 in q 5 in p 6 in q 7 in p 8 in q 9 WRONG output (if you fail to spot code-writes to code[0 .. 4]) is in p 0 in p 1 in p 2 in p 3 in p 4 in p 5 in p 6 in p 7 in p 8 in p 9*/#include <stdio.h>#include <assert.h>#include <sys/mman.h>typedef unsigned long long int Addr;typedef unsigned char UChar;void q ( int n ){ printf("in q %d\n", n);}void p ( int n ){ printf("in p %d\n", n);}// Unlike on x86, data areas aren't executable; have to put// code on the heap thereforestatic UChar* code;/* Make `code' be movabsq $dest, %rax ; pushq %rax ; ret */// This forces the branch onwards to be indirect, so vex can't chase itvoid set_dest ( Addr dest ){ assert(sizeof(Addr) == 8); /* movabsq $imm64, %rax */ code[0] = 0x48; code[1] = 0xB8; code[2] = (dest & 0xFF); code[3] = ((dest >> 8) & 0xFF); code[4] = ((dest >> 16) & 0xFF); code[5] = ((dest >> 24) & 0xFF); code[6] = ((dest >> 32) & 0xFF); code[7] = ((dest >> 40) & 0xFF); code[8] = ((dest >> 48) & 0xFF); code[9] = ((dest >> 56) & 0xFF); /* pushq %rax */ code[10] = 0x50; /* ret */ code[11] = 0xC3;}/* Calling aa gets eventually to the function residing in code[0..]. This indirection is necessary to defeat Vex's basic-block chasing optimisation. That will merge up to three basic blocks into the same IR superblock, which causes the test to succeed when it shouldn't if main calls code[] directly. */// force an indirect branch to code[0], so vex can't chase it__attribute__((noinline))void dd ( int x, void (*f)(int) ) { f(x); }__attribute__((noinline))void cc ( int x ) { dd(x, (void(*)(int)) &code[0]); }__attribute__((noinline))void bb ( int x ) { cc(x); }__attribute__((noinline))void aa ( int x ) { bb(x); }__attribute__((noinline))void diversion ( void ) { }int main ( void ){ int i; code = mmap(NULL, 20, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); assert(code != MAP_FAILED); for (i = 0; i < 10; i += 2) { set_dest ( (Addr)&p ); // diversion(); aa(i); set_dest ( (Addr)&q ); // diversion(); aa(i+1); } munmap(code, 20); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -