├── .gitattributes ├── volatile_checker ├── volatile_address_test_dir │ ├── array1.c │ ├── basic.out │ ├── access1.out │ ├── array1.out │ ├── basic.c │ ├── pointer1.out │ ├── bitfield1.out │ ├── unnamed1.out │ ├── struct1.c │ ├── struct1.out │ ├── pointer1.c │ ├── long_long_struct.out │ ├── access2.out │ ├── bitfield1.c │ ├── access1.c │ ├── unnamed1.c │ ├── array2.c │ ├── types.c │ ├── array3.c │ ├── access2.c │ ├── long_long_struct.c │ ├── struct2.c │ ├── array4.c │ ├── types.out │ ├── array3.out │ ├── array2.out │ ├── array4.out │ └── struct2.out ├── reorder_test_dir │ ├── array1.out │ ├── union2.out │ ├── reorder_test6.out │ ├── reorder_test5.c │ ├── reorder_test4.c │ ├── init1.out │ ├── init2.out │ ├── reorder4.out │ ├── binary1.c │ ├── func4.out │ ├── func5.c │ ├── union1.c │ ├── union2.c │ ├── comma1.out │ ├── func2.c │ ├── reorder2.out │ ├── reorder5.out │ ├── reorder_test7.out │ ├── func1.c │ ├── func2.out │ ├── reorder_test6.c │ ├── init1.c │ ├── func5.out │ ├── reorder_test4.out │ ├── reorder_test5.out │ ├── union1.out │ ├── array1.c │ ├── func6.out │ ├── reorder6.out │ ├── reorder_test1.c │ ├── binary1.out │ ├── init2.c │ ├── func6.c │ ├── func3.c │ ├── reorder_test7.c │ ├── comma1.c │ ├── func3.out │ ├── func7.out │ ├── func7.c │ ├── func1.out │ ├── reorder3.out │ ├── reorder4.c │ ├── func4.c │ ├── reorder6.c │ ├── 8.preprocessed.out │ ├── reorder_test1.out │ ├── reorder_func1.out │ ├── reorder1.out │ ├── 4.preprocessed.out │ ├── reorder_test3.out │ ├── reorder5.c │ ├── reorder_test2.out │ ├── reorder_func1.c │ ├── reorder2.c │ ├── 1.preprocessed.out │ ├── reorder_test3.c │ ├── reorder1.c │ ├── 7.preprocessed.out │ ├── reorder3.c │ ├── 5.preprocessed.out │ ├── 2.preprocessed.out │ ├── 3.preprocessed.out │ ├── reorder_test2.c │ └── 6.preprocessed.out ├── .gitignore ├── AccessOnceChecker.h ├── Checker.h ├── Checker.cpp ├── Makefile ├── CheckerManager.h ├── README.txt ├── VolatileReorderChecker.h ├── AccessOnceChecker.cpp ├── VolatileAddressChecker.h ├── VolatileChecker.cpp ├── test_checker.pl ├── CheckerManager.cpp └── VolatileAddressChecker.cpp ├── volatile_pintrace ├── unittest │ ├── bitfield5.out │ ├── bitfield9.out │ ├── bitfield1.out │ ├── bitfield2.out │ ├── bitfield5.all_vars.out │ ├── bitfield1.all_vars.out │ ├── bitfield2.all_vars.out │ ├── basic.out │ ├── basic.all_vars.out │ ├── bitfield11.out │ ├── bitfield12.out │ ├── bitfield13.out │ ├── bitfield9.all_vars.out │ ├── unnamed1.out │ ├── bitfield8.out │ ├── unnamed1.all_vars.out │ ├── bitfield8.all_vars.out │ ├── bitfield6.out │ ├── bitfield10.out │ ├── bitfield14.out │ ├── bitfield3.out │ ├── bitfield4.out │ ├── bitfield6.all_vars.out │ ├── bitfield11.all_vars.out │ ├── bitfield12.all_vars.out │ ├── bitfield13.all_vars.out │ ├── bitfield3.all_vars.out │ ├── bitfield4.all_vars.out │ ├── bitfield10.all_vars.out │ ├── bitfield14.all_vars.out │ ├── basic.c │ ├── bitfield9.c │ ├── unnamed1.c │ ├── bitfield2.c │ ├── bitfield5.c │ ├── bitfield1.c │ ├── bitfield3.c │ ├── bitfield4.c │ ├── bitfield6.c │ ├── bitfield10.c │ ├── bitfield11.c │ ├── struct1.c │ ├── bitfield12.c │ ├── bitfield13.c │ ├── bitfield14.c │ ├── bitfield7.out │ ├── struct1.out │ ├── bitfield7.c │ ├── bitfield8.c │ ├── bitfield7.all_vars.out │ └── struct1.all_vars.out ├── see_results.sh ├── all_addrs_unittest_dir │ ├── basic1.c │ ├── struct1.c │ ├── struct2.c │ ├── array1.c │ ├── struct_array1.c │ ├── basic2.c │ ├── struct_array2.c │ └── crc32.h ├── kill_voltest.pl ├── launchn.pl ├── pin.sh ├── install.pl ├── run_test.pl ├── do_all.pl ├── sample_test1.sh ├── README.txt ├── RunSafely └── test1.pl ├── .gitignore ├── patches ├── volatile_pintrace │ └── volatile_test.patch └── csmith │ ├── test-targets.patch │ └── volatile_pintrace.patch ├── ns ├── ubuntu12-d710.ns ├── ubuntu12-d820.ns └── ubuntu12-pc3000.ns ├── scripts ├── env.sh ├── run.sh ├── bootstrap.sh ├── vars.sh └── setup.sh ├── creduce ├── tests-from-log.awk ├── prep_reduction.sh ├── find-common-vars.pl └── showme.sh └── README /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array1.c: -------------------------------------------------------------------------------- 1 | 2 | volatile int a[10]; 3 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/array1.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/union2.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/basic.out: -------------------------------------------------------------------------------- 1 | g; 0; 32; non-pointer; non-bitfield 2 | Succeeded 3 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/access1.out: -------------------------------------------------------------------------------- 1 | g1; 0; 32; non-pointer; non-bitfield 2 | Succeeded 3 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array1.out: -------------------------------------------------------------------------------- 1 | a+; 0; 320; non-pointer; non-bitfield 2 | Succeeded 3 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test6.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/basic.c: -------------------------------------------------------------------------------- 1 | volatile g = 1; 2 | int foo(void) 3 | { 4 | return g; 5 | } 6 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield5.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer 2 | g1.f1; 0x402029; 1; non-pointer; f4 3 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield9.out: -------------------------------------------------------------------------------- 1 | g_5; 0x402028; 4; non-pointer 2 | g_403.; 0x402030; 1; non-pointer; 40 3 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield1.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; ff 2 | g1.f3; 0x402029; 1; non-pointer; fc 3 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield2.out: -------------------------------------------------------------------------------- 1 | g1.f2; 0x402028; 1; non-pointer; 7f 2 | g1.f3; 0x402029; 1; non-pointer; fc 3 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test5.c: -------------------------------------------------------------------------------- 1 | int *volatile g1; 2 | int foo(void) 3 | { 4 | return *g1 + *g1; 5 | } 6 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield5.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer 2 | g1.f1; 0x402029; 1; non-pointer; fc 3 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield1.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; ff 2 | g1.f3; 0x402029; 1; non-pointer; fc 3 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield2.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; ff 2 | g1.f3; 0x402029; 1; non-pointer; fc 3 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test4.c: -------------------------------------------------------------------------------- 1 | volatile int *volatile g1; 2 | int foo(void) 3 | { 4 | return *g1 + *g1; 5 | } 6 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/basic.out: -------------------------------------------------------------------------------- 1 | g1; 0x402068; 4; non-pointer 2 | g2; 0x40206c; 4; non-pointer 3 | g3+; 0x402040; 40; non-pointer 4 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/pointer1.out: -------------------------------------------------------------------------------- 1 | g3+; 0; 128; pointer; non-bitfield 2 | g4+; 0; 128; pointer; non-bitfield 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/basic.all_vars.out: -------------------------------------------------------------------------------- 1 | g1; 0x402068; 4; non-pointer 2 | g2; 0x40206c; 4; non-pointer 3 | g3+; 0x402040; 40; non-pointer 4 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/init1.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | bar : volatile access to g2 at line 12 3 | 4 | Succeeded 5 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/init2.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | bar : volatile access to g2 at line 15 3 | 4 | Succeeded 5 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/bitfield1.out: -------------------------------------------------------------------------------- 1 | g.f2; 10; 2; non-pointer; bitfield 2 | g.f3; 12; 13; non-pointer; bitfield 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/unnamed1.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0; 2; non-pointer; bitfield 2 | g1.f2; 32; 28; non-pointer; bitfield 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder4.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f7 : volatile access to g2.a1 at line 20 3 | 4 | Succeeded 5 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/struct1.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | volatile int f1; 3 | char f2; 4 | volatile int f3; 5 | }; 6 | 7 | struct S g1; 8 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/struct1.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0; 32; non-pointer; non-bitfield 2 | g1.f3; 64; 32; non-pointer; non-bitfield 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield11.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; fc 3 | g1.f6; 0x40202f; 1; non-pointer; 6 4 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield12.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; fc 3 | g1.f6; 0x40202f; 1; non-pointer; 6 4 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield13.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; fc 3 | g1.f6; 0x40202f; 1; non-pointer; 7 4 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield9.all_vars.out: -------------------------------------------------------------------------------- 1 | g_5; 0x402028; 4; non-pointer 2 | g_7; 0x40202c; 4; non-pointer 3 | g_403.; 0x402030; 1; non-pointer; c0 4 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/unnamed1.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; c0 2 | g1.f2; 0x40202c; 3; non-pointer 3 | g1.f2; 0x40202f; 1; non-pointer; f0 4 | -------------------------------------------------------------------------------- /volatile_checker/.gitignore: -------------------------------------------------------------------------------- 1 | # Additions to the patterns specified in the root `.gitignore' file. 2 | 3 | # Files made by compilation. 4 | volatile_checker 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield8.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; ff 2 | g1.f2; 0x402029; 1; non-pointer; ff 3 | g1.f5; 0x40202a; 1; non-pointer; f8 4 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/pointer1.c: -------------------------------------------------------------------------------- 1 | 2 | volatile int *g1; 3 | volatile int *g2[2]; 4 | volatile int * volatile g3[2]; 5 | int * volatile g4[2]; 6 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/unnamed1.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; c0 2 | g1.f2; 0x40202c; 3; non-pointer 3 | g1.f2; 0x40202f; 1; non-pointer; f0 4 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/binary1.c: -------------------------------------------------------------------------------- 1 | 2 | volatile int g1; 3 | volatile int g2; 4 | volatile int g3; 5 | void foo(void) 6 | { 7 | (g1 == 0) || (g2 == g3); 8 | } 9 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/long_long_struct.out: -------------------------------------------------------------------------------- 1 | g1.f2; 64; 64; non-pointer; non-bitfield 2 | g2.f2.f2; 128; 64; non-pointer; non-bitfield 3 | Succeeded 4 | -------------------------------------------------------------------------------- /volatile_pintrace/see_results.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | grep FAIL work*/output.txt | grep -v 'COMPILER FAILURE' 3 | echo -n 'tests: ' 4 | grep GOOD work*/output.txt | wc -l 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield8.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; ff 2 | g1.f2; 0x402029; 1; non-pointer; ff 3 | g1.f5; 0x40202a; 1; non-pointer; f8 4 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/access2.out: -------------------------------------------------------------------------------- 1 | g1; 0; 64; pointer; non-bitfield 2 | g2; 0; 64; pointer; non-bitfield 3 | g3; 0; 32; non-pointer; non-bitfield 4 | Succeeded 5 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/bitfield1.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | unsigned f1: 10; 3 | volatile unsigned f2: 2; 4 | volatile unsigned f3: 13; 5 | }; 6 | 7 | struct S g; 8 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield6.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer 2 | g1.f1; 0x402029; 1; non-pointer; f0 3 | g1.f3; 0x40202a; 1; non-pointer 4 | g1.f4; 0x40202b; 1; non-pointer 5 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func4.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1 at line 6 3 | f2 : volatile access to g2 at line 21 4 | 5 | Succeeded 6 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func5.c: -------------------------------------------------------------------------------- 1 | volatile int g; 2 | 3 | int foo(int p1) 4 | { 5 | return p1; 6 | } 7 | 8 | int bar(void) 9 | { 10 | return foo(g + foo(g)); 11 | } 12 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/union1.c: -------------------------------------------------------------------------------- 1 | union U1 { 2 | int f0; 3 | volatile short f1; 4 | }; 5 | 6 | union U1 g; 7 | int foo(void) 8 | { 9 | return g.f1 + g.f1; 10 | } 11 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/union2.c: -------------------------------------------------------------------------------- 1 | union U1 { 2 | int f0; 3 | volatile short f1; 4 | }; 5 | 6 | union U1 g; 7 | int foo(void) 8 | { 9 | return g.f0 + g.f0; 10 | } 11 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/access1.c: -------------------------------------------------------------------------------- 1 | 2 | #define ACCESS_ONCE(v) (*(volatile typeof(v) *)&(v)) 3 | 4 | int g1; 5 | int foo(void) 6 | { 7 | return ACCESS_ONCE(g1); 8 | } 9 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/unnamed1.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | volatile unsigned f1 : 2; 3 | volatile unsigned : 0; 4 | volatile unsigned f2 : 28; 5 | }; 6 | 7 | struct S g1; 8 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/comma1.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | foo : volatile access to g1 at line 4 3 | bar : volatile access to g1 at line 9 4 | 5 | Succeeded 6 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield10.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer 2 | g1.f1; 0x402029; 1; non-pointer; c0 3 | g1.f5; 0x40202c; 1; non-pointer; 1 4 | g1.f5; 0x40202d; 1; non-pointer; fe 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield14.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; fc 3 | g1.f6; 0x40202f; 1; non-pointer; 7 4 | g1.f7; 0x402030; 1; non-pointer; 80 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield3.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; ff 2 | g1.f2; 0x402029; 1; non-pointer; ff 3 | g1.f3; 0x40202a; 5; non-pointer 4 | g1.f3; 0x40202f; 1; non-pointer; fc 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield4.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402030; 1; non-pointer; ff 2 | g1.f2; 0x402031; 1; non-pointer; c0 3 | g1.f3; 0x402038; 6; non-pointer 4 | g1.f3; 0x40203e; 1; non-pointer; fe 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield6.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer 2 | g1.f1; 0x402029; 1; non-pointer; ff 3 | g1.f3; 0x40202a; 1; non-pointer 4 | g1.f4; 0x40202b; 1; non-pointer 5 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func2.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | volatile int g2; 3 | int foo(int p) 4 | { 5 | return g1; 6 | } 7 | 8 | void bar(void) 9 | { 10 | foo(foo(1)); 11 | } 12 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder2.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f7 : volatile access to g7.a1 at line 18 3 | f9 : volatile access to g8.a1 at line 30 4 | 5 | Succeeded 6 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder5.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1.a1 at line 21 3 | f2 : volatile access to g2.a1 at line 27 4 | 5 | Succeeded 6 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test7.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | foo : volatile access to p at line 9 3 | bar : volatile access to p at line 15 4 | 5 | Succeeded 6 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array2.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | int f1; 4 | volatile char f2; 5 | }; 6 | 7 | struct S2 { 8 | struct S1 f1[10]; 9 | }; 10 | 11 | struct S2 g; 12 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield11.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; ff 3 | g1.f5; 0x40202c; 3; non-pointer 4 | g1.f5; 0x40202f; 1; non-pointer; fe 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield12.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; ff 3 | g1.f5; 0x40202c; 3; non-pointer 4 | g1.f5; 0x40202f; 1; non-pointer; fe 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield13.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; ff 3 | g1.f5; 0x40202c; 3; non-pointer 4 | g1.f5; 0x40202f; 1; non-pointer; ff 5 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/types.c: -------------------------------------------------------------------------------- 1 | volatile char g1 = 0; 2 | volatile short g2 = 0; 3 | volatile int g3 = 0; 4 | volatile long g4 = 0; 5 | volatile long long g5 = 0; 6 | int * volatile p1; 7 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield3.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer; ff 2 | g1.f2; 0x402029; 1; non-pointer; ff 3 | g1.f3; 0x40202a; 5; non-pointer 4 | g1.f3; 0x40202f; 1; non-pointer; fc 5 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield4.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402030; 1; non-pointer; ff 2 | g1.f2; 0x402031; 1; non-pointer; c0 3 | g1.f3; 0x402038; 6; non-pointer 4 | g1.f3; 0x40203e; 1; non-pointer; fe 5 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func1.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | volatile int g2; 3 | int foo(int p) 4 | { 5 | return g1; 6 | } 7 | 8 | void bar(void) 9 | { 10 | foo(g2 == foo(foo(1))); 11 | } 12 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func2.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | foo : volatile access to g1 at line 5 3 | bar : volatile access to callee(s) has volatile accesses 4 | 5 | Succeeded 6 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array3.c: -------------------------------------------------------------------------------- 1 | 2 | struct S { 3 | volatile int f1; 4 | }; 5 | 6 | struct S g1[] = {1,2}; 7 | struct S g2[1][2] = {1,2}; 8 | struct S g3[2][2] = {1,2,3,4}; 9 | 10 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test6.c: -------------------------------------------------------------------------------- 1 | 2 | union U2 { 3 | const volatile int f0; 4 | }; 5 | union U2 g; 6 | void foo(void) 7 | { 8 | union U2 *l1; 9 | union U2 **l2 = &l1; 10 | *l2 = &g; 11 | } 12 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/init1.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | volatile int g2; 3 | 4 | int foo(void) 5 | { 6 | volatile int *l = &g1; 7 | return 1; 8 | } 9 | 10 | int bar(void) 11 | { 12 | return (g2 + foo()); 13 | } 14 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield10.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402028; 1; non-pointer 2 | g1.f1; 0x402029; 1; non-pointer; ff 3 | g1.f4; 0x40202a; 2; non-pointer 4 | g1.f4; 0x40202c; 1; non-pointer; ff 5 | g1.f5; 0x40202d; 1; non-pointer; fe 6 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield14.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f4; 0x402028; 3; non-pointer 2 | g1.f4; 0x40202b; 1; non-pointer; ff 3 | g1.f5; 0x40202c; 3; non-pointer 4 | g1.f5; 0x40202f; 1; non-pointer; ff 5 | g1.f7; 0x402030; 1; non-pointer; 80 6 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func5.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 10: foo(g + foo(g)) 2 | multiple volatile accesses: 3 | g 4 | g 5 | 6 | Functions that have volatile accesses: 7 | bar : volatile access to g at line 10 8 | 9 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test4.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 4: *g1 + *g1 2 | multiple volatile accesses: 3 | g1 4 | g1 5 | 6 | Functions that have volatile accesses: 7 | foo : volatile access to *g1 at line 4 8 | 9 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test5.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 4: *g1 + *g1 2 | multiple volatile accesses: 3 | g1 4 | g1 5 | 6 | Functions that have volatile accesses: 7 | foo : volatile access to g1 at line 4 8 | 9 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/union1.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 9: g.f1 + g.f1 2 | multiple volatile accesses: 3 | g.f1 4 | g.f1 5 | 6 | Functions that have volatile accesses: 7 | foo : volatile access to g.f1 at line 9 8 | 9 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/access2.c: -------------------------------------------------------------------------------- 1 | #define ACCESS_ONCE(v) (*(volatile typeof(v) *)&(v)) 2 | 3 | int *g1; 4 | int * volatile g2; 5 | int volatile g3; 6 | 7 | int foo(void) 8 | { 9 | return *(ACCESS_ONCE(g1)); 10 | } 11 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/long_long_struct.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | char f1; 4 | volatile long long f2; 5 | }; 6 | 7 | struct S2 { 8 | char f1; 9 | struct S1 f2; 10 | }; 11 | 12 | struct S1 g1; 13 | struct S2 g2; 14 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/array1.c: -------------------------------------------------------------------------------- 1 | 2 | union U1 { 3 | int f0; 4 | volatile int f1; 5 | }; 6 | 7 | static union U1 g1[1] = {{0x5605049BL}}; 8 | union U1 *g2 = &g1[0]; 9 | int foo(void) 10 | { 11 | return (g2 == &g1[0]); 12 | } 13 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func6.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1 at line 5 3 | f2 : volatile access to g1 at line 10 4 | f3 : volatile access to callee(s) has volatile accesses 5 | 6 | Succeeded 7 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder6.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f3 : volatile access to g3 at line 10 3 | f2 : volatile access to g2 at line 16 4 | f1 : volatile access to (volatile int)g1 at line 22 5 | 6 | Succeeded 7 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test1.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | 3 | int f1(void) 4 | { 5 | return g1 + g1; 6 | } 7 | 8 | int f2(void) 9 | { 10 | return f1(); 11 | } 12 | 13 | int f3(void) 14 | { 15 | return f2(); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/basic.c: -------------------------------------------------------------------------------- 1 | 2 | volatile int g1; 3 | volatile int g2; 4 | volatile int g3[10]; 5 | int foo(void) 6 | { 7 | return g1 + g2 + g3[3]; 8 | } 9 | 10 | int main(void) 11 | { 12 | int l = foo(); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/binary1.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 7: (g1 == 0) || (g2 == g3) 2 | multiple volatile accesses: 3 | g2 4 | g3 5 | 6 | Functions that have volatile accesses: 7 | foo : volatile access to g1 at line 7 8 | 9 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/basic1.c: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | 3 | int g_1 = 1; 4 | 5 | int main(void) 6 | { 7 | crc32_gentab(); 8 | crc32(g_1, sizeof(int)); 9 | print_checksum(crc32_context ^ 0xFFFFFFFFUL); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/init2.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | volatile int f; 3 | } g1; 4 | 5 | volatile int g2; 6 | 7 | int foo(void) 8 | { 9 | volatile int *l = &g1.f; 10 | return 1; 11 | } 12 | 13 | void bar(void) 14 | { 15 | g2 + foo(); 16 | } 17 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/struct2.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | long long f1; 3 | volatile char f2[3]; 4 | volatile short f3; 5 | }; 6 | 7 | struct S2 { 8 | volatile char f1[2]; 9 | struct S1 f2[3]; 10 | }; 11 | 12 | struct S2 g1[4]; 13 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield9.c: -------------------------------------------------------------------------------- 1 | struct S0 2 | { 3 | int:1; 4 | volatile int:1; 5 | }; 6 | volatile int g_5 = 0; 7 | int g_7 = 0; 8 | struct S0 g_403; 9 | int 10 | main () 11 | { 12 | for (g_7 = 0; g_7; g_7++); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func6.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | 3 | int f1(int p1) 4 | { 5 | return g1; 6 | } 7 | 8 | int f2(void) 9 | { 10 | return g1; 11 | } 12 | 13 | void f3(void) 14 | { 15 | int l; 16 | f1((l = (f2() && 1), 1)); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func3.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | volatile int g2; 3 | 4 | int f1(void) 5 | { 6 | return g1; 7 | } 8 | 9 | int f2(int p1, int p2) 10 | { 11 | return p1+p2; 12 | } 13 | 14 | int f3(void) 15 | { 16 | return f2(f1(), g2); 17 | } 18 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test7.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | volatile int f1; 4 | }; 5 | struct S1 g; 6 | struct S1 * volatile p = &g; 7 | void foo(void) 8 | { 9 | p = &g; 10 | } 11 | 12 | struct S1 **g1; 13 | void bar(void) 14 | { 15 | p = *g1; 16 | } 17 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/comma1.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | int foo(void) 3 | { 4 | return g1; 5 | } 6 | 7 | void bar(void) 8 | { 9 | (foo(), g1); 10 | (g1, foo()); 11 | (foo(), foo()); 12 | ((foo(), foo()), foo()); 13 | ((foo(), g1, g1, foo()), foo()); 14 | } 15 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func3.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 16: f2(f1(), g2) 2 | multiple volatile accesses: 3 | f1() 4 | g2 5 | 6 | Functions that have volatile accesses: 7 | f1 : volatile access to g1 at line 6 8 | f3 : volatile access to g2 at line 16 9 | 10 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func7.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1 at line 5 3 | f2 : volatile access to g1 at line 10 4 | f3 : volatile access to g1 at line 15 5 | f4 : volatile access to callee(s) has volatile accesses 6 | 7 | Succeeded 8 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array4.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | char f1; 4 | volatile int f2; 5 | long f3[10]; 6 | volatile char f4[2]; 7 | }; 8 | 9 | struct S2 { 10 | struct S1 f1; 11 | volatile char f2[3]; 12 | }; 13 | 14 | volatile struct S2 g1[2]; 15 | struct S2 g2; 16 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/types.out: -------------------------------------------------------------------------------- 1 | g1; 0; 8; non-pointer; non-bitfield 2 | g2; 0; 16; non-pointer; non-bitfield 3 | g3; 0; 32; non-pointer; non-bitfield 4 | g4; 0; 64; non-pointer; non-bitfield 5 | g5; 0; 64; non-pointer; non-bitfield 6 | p1; 0; 64; pointer; non-bitfield 7 | Succeeded 8 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/unnamed1.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | volatile unsigned f1 : 2; 3 | volatile unsigned : 0; 4 | volatile unsigned f2 : 28; 5 | }; 6 | 7 | struct S g1; 8 | int foo(void) 9 | { 10 | return g1.f2; 11 | } 12 | 13 | int main(void) 14 | { 15 | foo(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func7.c: -------------------------------------------------------------------------------- 1 | 2 | volatile int g1; 3 | int f1(int p1) 4 | { 5 | return g1; 6 | } 7 | 8 | int f2(int p1) 9 | { 10 | return g1; 11 | } 12 | 13 | int f3(int p1) 14 | { 15 | return g1; 16 | } 17 | 18 | void f4(void) 19 | { 20 | f1(f2((f3(1), 1))); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func1.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 10: foo(g2 == foo(foo(1))) 2 | multiple volatile accesses: 3 | g2 4 | foo(1) 5 | 6 | Functions that have volatile accesses: 7 | foo : volatile access to g1 at line 5 8 | bar : volatile access to g2 at line 10 9 | 10 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield2.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | unsigned f1:1; 3 | volatile unsigned f2:1; 4 | volatile unsigned f3:12; 5 | }; 6 | 7 | struct S1 g1; 8 | int foo(void) 9 | { 10 | return g1.f1 + g1.f2 + g1.f3; 11 | } 12 | 13 | int main(void) 14 | { 15 | foo(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield5.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile unsigned f1:12; 3 | unsigned f2:1; 4 | volatile unsigned f3:1; 5 | }; 6 | 7 | struct S1 g1; 8 | int foo(void) 9 | { 10 | return g1.f1 + g1.f2 + g1.f3; 11 | } 12 | 13 | int main(void) 14 | { 15 | foo(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /volatile_pintrace/kill_voltest.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | 5 | open INF, "ps axuww |" or die; 6 | while () { 7 | next if (!(/volatile\_test/)); 8 | my @l = split /\s+/; 9 | my $pid = $l[1]; 10 | print "killing $pid\n"; 11 | system "kill -9 $pid"; 12 | } 13 | close INF; 14 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield1.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile unsigned f1:1; 3 | volatile unsigned f2:1; 4 | volatile unsigned f3:12; 5 | }; 6 | 7 | struct S1 g1; 8 | int foo(void) 9 | { 10 | return g1.f1 + g1.f2 + g1.f3; 11 | } 12 | 13 | int main(void) 14 | { 15 | foo(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder3.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1 at line 13 3 | f2 : volatile access to g2 at line 19 4 | f3 : volatile access to g3 at line 30 5 | f4 : volatile access to g4 at line 42 6 | f5 : volatile access to g5 at line 47 7 | 8 | Succeeded 9 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder4.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | volatile int a1; 4 | int a2; 5 | }; 6 | 7 | struct S2 { 8 | struct S1 a1; 9 | }; 10 | 11 | struct S2 g2; 12 | /* no vol */ 13 | int f6(void) 14 | { 15 | return g2.a1.a2; 16 | } 17 | 18 | struct S1 f7(void) 19 | { 20 | return g2.a1; 21 | } 22 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield3.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile unsigned f1:1; 3 | volatile unsigned f2:9; 4 | volatile unsigned long f3:52; 5 | }; 6 | 7 | struct S1 g1; 8 | int foo(void) 9 | { 10 | return g1.f1 + g1.f2 + g1.f3; 11 | } 12 | 13 | int main(void) 14 | { 15 | foo(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield4.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile unsigned f1:1; 3 | volatile unsigned f2:9; 4 | volatile unsigned long f3:55; 5 | }; 6 | 7 | struct S1 g1; 8 | int foo(void) 9 | { 10 | return g1.f1 + g1.f2 + g1.f3; 11 | } 12 | 13 | int main(void) 14 | { 15 | foo(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/func4.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | volatile int g2; 3 | 4 | int f1(int p1) 5 | { 6 | return g1; 7 | } 8 | 9 | int f3(int p1) 10 | { 11 | return p1; 12 | } 13 | 14 | int f4(int p1, int p2) 15 | { 16 | return 0; 17 | } 18 | 19 | void f2(void) 20 | { 21 | f1(f1(f3(f4((5, 1), g2)))); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield6.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile unsigned f1:12; 3 | unsigned f2:4; 4 | volatile unsigned f3:8; 5 | volatile unsigned f4:8; 6 | }; 7 | 8 | struct S1 g1; 9 | int foo(void) 10 | { 11 | return g1.f1 + g1.f2 + g1.f3; 12 | } 13 | 14 | int main(void) 15 | { 16 | foo(); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder6.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | volatile int a1; 4 | int a2; 5 | }; 6 | 7 | struct S1 g3; 8 | struct S1 f3(void) 9 | { 10 | return g3; 11 | } 12 | 13 | volatile int g2; 14 | int f2(void) 15 | { 16 | return g2; 17 | } 18 | 19 | int g1; 20 | int f1(void) 21 | { 22 | int l = (volatile int)g1; 23 | return l; 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files made by `configure' and friends. 2 | # Makefile 3 | # autom4te.cache 4 | # config.h 5 | # config.log 6 | # config.status 7 | # libtool 8 | # stamp-h1 9 | 10 | # Files made by compilation. 11 | .deps/ 12 | .libs/ 13 | *.a 14 | *.la 15 | *.lo 16 | *.o 17 | *.obj 18 | 19 | # Files made by Eclipse CDT. 20 | .autotools 21 | .cproject 22 | .project 23 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/8.preprocessed.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | func_1 : volatile access to g_9 at line 2384 3 | func_10 : volatile access to *g_1342 at line 2471 4 | func_15 : volatile access to g_2115 at line 2615 5 | func_26 : volatile access to *g_841 at line 2886 6 | main : volatile access to g_9 at line 4039 7 | 8 | Succeeded 9 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test1.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 5: g1 + g1 2 | multiple volatile accesses: 3 | g1 4 | g1 5 | 6 | Functions that have volatile accesses: 7 | f1 : volatile access to g1 at line 5 8 | f2 : volatile access to callee(s) has volatile accesses 9 | f3 : volatile access to callee(s) has volatile accesses 10 | 11 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/struct1.c: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | 3 | struct S1 { 4 | char f1; 5 | int f2; 6 | }; 7 | 8 | struct S1 g_1 = {23, 9988}; 9 | 10 | int main(void) 11 | { 12 | crc32_gentab(); 13 | crc32(g_1.f1, sizeof(char)); 14 | crc32(g_1.f2, sizeof(int)); 15 | print_checksum(crc32_context ^ 0xFFFFFFFFUL); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_func1.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1 at line 5 3 | f2 : volatile access to callee(s) has volatile accesses 4 | f3 : volatile access to callee(s) has volatile accesses 5 | f6 : volatile access to callee(s) has volatile accesses 6 | main : volatile access to callee(s) has volatile accesses 7 | 8 | Succeeded 9 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield10.c: -------------------------------------------------------------------------------- 1 | #pragma pack(push) 2 | #pragma pack(1) 3 | struct S3 { 4 | volatile unsigned f1 : 10; 5 | signed f4 : 29; 6 | volatile unsigned f5 : 8; 7 | }; 8 | #pragma pack(pop) 9 | 10 | static struct S3 g1; 11 | 12 | unsigned int foo(void) 13 | { 14 | return g1.f1 + g1.f4 + g1.f5; 15 | } 16 | 17 | int main(void) 18 | { 19 | foo(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield11.c: -------------------------------------------------------------------------------- 1 | #pragma pack(push) 2 | #pragma pack(1) 3 | struct S0 { 4 | const volatile unsigned f4 : 30; 5 | unsigned f5 : 31; 6 | volatile signed f6 : 2; 7 | }; 8 | #pragma pack(pop) 9 | 10 | static struct S0 g1; 11 | 12 | unsigned int foo(void) 13 | { 14 | return g1.f4 + g1.f5 + g1.f6; 15 | } 16 | 17 | int main(void) 18 | { 19 | foo(); 20 | return 0; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder1.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1 at line 21 3 | f2 : volatile access to *g2 at line 26 4 | f3 : volatile access to g3 at line 31 5 | f4 : volatile access to *g4[0] at line 37 6 | f5 : volatile access to g5 at line 42 7 | f7 : volatile access to g7.a1 at line 52 8 | f8 : volatile access to g7 at line 57 9 | 10 | Succeeded 11 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/struct1.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | char f1; 3 | volatile int f2; 4 | unsigned f3:22; 5 | volatile unsigned f4:29; 6 | }; 7 | 8 | struct S2 { 9 | volatile short f1[2]; 10 | unsigned long long f2; 11 | struct S1 f3[3]; 12 | }; 13 | 14 | struct S2 g1; 15 | int foo(void) 16 | { 17 | return g1.f1[0] + g1.f3[1].f4; 18 | } 19 | 20 | int main(void) 21 | { 22 | foo(); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/4.preprocessed.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | func_1 : volatile access to g_2 at line 2555 3 | func_3 : volatile access to g_1366 at line 3450 4 | func_12 : volatile access to g_1310 at line 4844 5 | func_15 : volatile access to *g_189 at line 4959 6 | func_20 : volatile access to *g_582 at line 5171 7 | main : volatile access to g_2 at line 6676 8 | 9 | Succeeded 10 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test3.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 36: f5(g1, f4()) 2 | multiple volatile accesses: 3 | g1 4 | f4() 5 | 6 | Functions that have volatile accesses: 7 | f1 : volatile access to g1 at line 6 8 | f2 : volatile access to g1 at line 13 9 | f3 : volatile access to g1 at line 19 10 | f4 : volatile access to g1 at line 26 11 | f6 : volatile access to g1 at line 41 12 | 13 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder5.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | int a1; 3 | }; 4 | 5 | struct S2 { 6 | volatile struct S1 a1[10]; 7 | }; 8 | 9 | struct S3 { 10 | int a1; 11 | volatile int a2; 12 | }; 13 | 14 | struct S4 { 15 | volatile struct S1 a1; 16 | } 17 | 18 | struct S2 g1; 19 | struct S1 f1(void) 20 | { 21 | return g1.a1[0]; 22 | } 23 | 24 | struct S4 g2; 25 | int f2(void) 26 | { 27 | return g2.a1.a1; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array3.out: -------------------------------------------------------------------------------- 1 | (g1+0).f1; 0; 32; non-pointer; non-bitfield 2 | (g1+1).f1; 32; 32; non-pointer; non-bitfield 3 | (g2+0).f1; 0; 32; non-pointer; non-bitfield 4 | (g2+1).f1; 32; 32; non-pointer; non-bitfield 5 | (g3+0).f1; 0; 32; non-pointer; non-bitfield 6 | (g3+1).f1; 32; 32; non-pointer; non-bitfield 7 | (g3+2).f1; 64; 32; non-pointer; non-bitfield 8 | (g3+3).f1; 96; 32; non-pointer; non-bitfield 9 | Succeeded 10 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield12.c: -------------------------------------------------------------------------------- 1 | #pragma pack(push) 2 | #pragma pack(1) 3 | struct S0 { 4 | const volatile unsigned f4 : 30; 5 | unsigned f5 : 31; 6 | volatile signed f6 : 1; 7 | volatile signed f7 : 1; 8 | }; 9 | #pragma pack(pop) 10 | 11 | static struct S0 g1; 12 | 13 | unsigned int foo(void) 14 | { 15 | return g1.f4 + g1.f5 + g1.f6 + g1.f7; 16 | } 17 | 18 | int main(void) 19 | { 20 | foo(); 21 | return 0; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield13.c: -------------------------------------------------------------------------------- 1 | #pragma pack(push) 2 | #pragma pack(1) 3 | struct S0 { 4 | const volatile unsigned f4 : 30; 5 | unsigned f5 : 31; 6 | volatile signed f6 : 2; 7 | volatile signed f7 : 1; 8 | }; 9 | #pragma pack(pop) 10 | 11 | static struct S0 g1; 12 | 13 | unsigned int foo(void) 14 | { 15 | return g1.f4 + g1.f5 + g1.f6 + g1.f7; 16 | } 17 | 18 | int main(void) 19 | { 20 | foo(); 21 | return 0; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield14.c: -------------------------------------------------------------------------------- 1 | #pragma pack(push) 2 | #pragma pack(1) 3 | struct S0 { 4 | const volatile unsigned f4 : 30; 5 | unsigned f5 : 31; 6 | volatile signed f6 : 2; 7 | volatile signed f7 : 2; 8 | }; 9 | #pragma pack(pop) 10 | 11 | static struct S0 g1; 12 | 13 | unsigned int foo(void) 14 | { 15 | return g1.f4 + g1.f5 + g1.f6 + g1.f7; 16 | } 17 | 18 | int main(void) 19 | { 20 | foo(); 21 | return 0; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield7.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402040; 1; non-pointer 2 | g1.f1; 0x402041; 1; non-pointer; f0 3 | g1.f3; 0x402042; 1; non-pointer 4 | g1.f4; 0x402043; 1; non-pointer 5 | g2.f2.f1; 0x402034; 1; non-pointer 6 | g2.f2.f1; 0x402035; 1; non-pointer; f0 7 | g2.f2.f3; 0x402036; 1; non-pointer 8 | g2.f2.f4; 0x402037; 1; non-pointer 9 | g2.f3; 0x402038; 1; non-pointer 10 | g2.f3; 0x402039; 1; non-pointer; c0 11 | g2.f4; 0x40203c; 4; non-pointer 12 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/struct1.out: -------------------------------------------------------------------------------- 1 | g1.f1+; 0x402040; 4; non-pointer 2 | (g1.f3+0).f2; 0x402054; 4; non-pointer 3 | (g1.f3+0).f4; 0x40205c; 3; non-pointer 4 | (g1.f3+0).f4; 0x40205f; 1; non-pointer; f8 5 | (g1.f3+1).f2; 0x402064; 4; non-pointer 6 | (g1.f3+1).f4; 0x40206c; 3; non-pointer 7 | (g1.f3+1).f4; 0x40206f; 1; non-pointer; f8 8 | (g1.f3+2).f2; 0x402074; 4; non-pointer 9 | (g1.f3+2).f4; 0x40207c; 3; non-pointer 10 | (g1.f3+2).f4; 0x40207f; 1; non-pointer; f8 11 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test2.out: -------------------------------------------------------------------------------- 1 | Functions that have volatile accesses: 2 | f1 : volatile access to g1.a1.a1 at line 15 3 | f2 : volatile access to g2 at line 22 4 | f3 : volatile access to *g4 at line 29 5 | f4 : volatile access to **g5 at line 35 6 | f5 : volatile access to g5 at line 40 7 | f6 : volatile access to g6.a3 at line 55 8 | f7 : volatile access to g6.a2 at line 60 9 | f8 : volatile access to *g6.a1 at line 65 10 | 11 | Succeeded 12 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield7.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile unsigned f1:12; 3 | unsigned f2:4; 4 | volatile unsigned f3:8; 5 | volatile unsigned f4:8; 6 | }; 7 | 8 | struct S2 { 9 | char f1; 10 | struct S1 f2; 11 | volatile unsigned f3:10; 12 | volatile int f4; 13 | }; 14 | 15 | struct S1 g1; 16 | struct S2 g2; 17 | int foo(void) 18 | { 19 | return g1.f1 + g1.f2 + g1.f3 + g2.f4; 20 | } 21 | 22 | int main(void) 23 | { 24 | foo(); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/struct2.c: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | 3 | struct S1 { 4 | char f1; 5 | int f2; 6 | }; 7 | 8 | struct S2 { 9 | short f1; 10 | struct S1 f2; 11 | }; 12 | 13 | struct S2 g_1 = {23, {9988, 4466}}; 14 | 15 | int main(void) 16 | { 17 | crc32_gentab(); 18 | crc32(g_1.f1, sizeof(short)); 19 | crc32(g_1.f2.f1, sizeof(char)); 20 | crc32(g_1.f2.f2, sizeof(int)); 21 | print_checksum(crc32_context ^ 0xFFFFFFFFUL); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield8.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile unsigned f1:7; 3 | volatile unsigned f2:7; 4 | volatile unsigned f3:1; 5 | volatile unsigned f4:1; 6 | volatile unsigned f5:1; 7 | volatile unsigned f6:1; 8 | volatile unsigned f7:1; 9 | volatile unsigned f8:1; 10 | volatile unsigned f9:1; 11 | }; 12 | 13 | struct S1 g1; 14 | int foo(void) 15 | { 16 | return g1.f1 + g1.f2 + g1.f3; 17 | } 18 | 19 | int main(void) 20 | { 21 | foo(); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/bitfield7.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1; 0x402040; 1; non-pointer 2 | g1.f1; 0x402041; 1; non-pointer; ff 3 | g1.f3; 0x402042; 1; non-pointer 4 | g1.f4; 0x402043; 1; non-pointer 5 | g2.f1; 0x402030; 1; non-pointer 6 | g2.f2.f1; 0x402034; 1; non-pointer 7 | g2.f2.f1; 0x402035; 1; non-pointer; ff 8 | g2.f2.f3; 0x402036; 1; non-pointer 9 | g2.f2.f4; 0x402037; 1; non-pointer 10 | g2.f3; 0x402038; 1; non-pointer 11 | g2.f3; 0x402039; 1; non-pointer; c0 12 | g2.f4; 0x40203c; 4; non-pointer 13 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_func1.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | 3 | int f1(void) 4 | { 5 | return g1; 6 | } 7 | 8 | int f2(void) 9 | { 10 | return f1(); 11 | } 12 | 13 | int f3(void) 14 | { 15 | return f1(); 16 | } 17 | 18 | int f4(void) 19 | { 20 | return 1; 21 | } 22 | 23 | int f5(void) 24 | { 25 | return f4(); 26 | } 27 | 28 | int g2 = 1; 29 | int f6(void) 30 | { 31 | if (g2) 32 | return f2(); 33 | } 34 | 35 | int main(void) 36 | { 37 | return f1() + f5(); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder2.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | int a1; 4 | }; 5 | 6 | struct S2 { 7 | volatile int a1; 8 | int a2; 9 | }; 10 | 11 | struct S3 { 12 | volatile struct S1 a1; 13 | }; 14 | 15 | struct S2 g7; 16 | int f7(void) 17 | { 18 | return g7.a1; 19 | } 20 | 21 | /* no vol */ 22 | int f8(void) 23 | { 24 | return g7.a2; 25 | } 26 | 27 | struct S3 g8; 28 | struct S1 f9(void) 29 | { 30 | return g8.a1; 31 | } 32 | 33 | struct S1 g10; 34 | struct f10(void) 35 | { 36 | return g10; 37 | } 38 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/1.preprocessed.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 2461: ((*g_35) = ((*g_934) = (**g_117))) 2 | multiple volatile accesses: 3 | g_35 4 | g_117 5 | 6 | Functions that have volatile accesses: 7 | func_1 : volatile access to g_35 at line 2461 8 | func_3 : volatile access to g_1199 at line 2620 9 | func_26 : volatile access to g_35 at line 2684 10 | func_58 : volatile access to g_1158 at line 2788 11 | func_62 : volatile access to g_160 at line 2814 12 | main : volatile access to g_53 at line 3449 13 | 14 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/array1.c: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | 3 | char g_1[4] = {11,22,33,44}; 4 | int g_2[4] = {11122, 3344, 5566, 7788}; 5 | 6 | int main(void) 7 | { 8 | crc32_gentab(); 9 | crc32(g_1[0], sizeof(char)); 10 | crc32(g_1[1], sizeof(char)); 11 | crc32(g_1[2], sizeof(char)); 12 | crc32(g_1[3], sizeof(char)); 13 | crc32(g_2[0], sizeof(int)); 14 | crc32(g_2[1], sizeof(int)); 15 | crc32(g_2[2], sizeof(int)); 16 | crc32(g_2[3], sizeof(int)); 17 | print_checksum(crc32_context ^ 0xFFFFFFFFUL); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array2.out: -------------------------------------------------------------------------------- 1 | (g.f1+0).f2; 32; 8; non-pointer; non-bitfield 2 | (g.f1+1).f2; 96; 8; non-pointer; non-bitfield 3 | (g.f1+2).f2; 160; 8; non-pointer; non-bitfield 4 | (g.f1+3).f2; 224; 8; non-pointer; non-bitfield 5 | (g.f1+4).f2; 288; 8; non-pointer; non-bitfield 6 | (g.f1+5).f2; 352; 8; non-pointer; non-bitfield 7 | (g.f1+6).f2; 416; 8; non-pointer; non-bitfield 8 | (g.f1+7).f2; 480; 8; non-pointer; non-bitfield 9 | (g.f1+8).f2; 544; 8; non-pointer; non-bitfield 10 | (g.f1+9).f2; 608; 8; non-pointer; non-bitfield 11 | Succeeded 12 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test3.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | 3 | int f1(void) 4 | { 5 | int l; 6 | l = (g1, g1); 7 | return l; 8 | } 9 | 10 | int f2(void) 11 | { 12 | int l; 13 | l = (g1, g1, g1); 14 | return l; 15 | } 16 | 17 | int f3(void) 18 | { 19 | int l = g1; 20 | l = (l, g1); 21 | return l; 22 | } 23 | 24 | int f4(void) 25 | { 26 | return g1 && g1 || g1; 27 | } 28 | 29 | int f5(int p1, int p2) 30 | { 31 | return g1 + p; 32 | } 33 | 34 | int f6(void) 35 | { 36 | return f5(g1, f4()); 37 | } 38 | 39 | int f6(void) 40 | { 41 | int l[2] = {g1+g1, g1+g1}; 42 | return l[0]; 43 | } 44 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/struct_array1.c: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | 3 | struct S1 { 4 | char f1[4]; 5 | long f2; 6 | int f3[4]; 7 | }; 8 | 9 | struct S1 g_1 = {{11,22,33,44}, 1234567, {2233, 3344, 5566, 7788}}; 10 | 11 | int main(void) 12 | { 13 | crc32_gentab(); 14 | crc32(g_1.f1[0], sizeof(char)); 15 | crc32(g_1.f1[1], sizeof(char)); 16 | crc32(g_1.f1[2], sizeof(char)); 17 | crc32(g_1.f1[3], sizeof(char)); 18 | 19 | crc32(g_1.f2, sizeof(long)); 20 | 21 | crc32(g_1.f3[0], sizeof(int)); 22 | crc32(g_1.f3[1], sizeof(int)); 23 | crc32(g_1.f3[2], sizeof(int)); 24 | crc32(g_1.f3[3], sizeof(int)); 25 | print_checksum(crc32_context ^ 0xFFFFFFFFUL); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/array4.out: -------------------------------------------------------------------------------- 1 | (g1+0).f1.f1; 0; 8; non-pointer; non-bitfield 2 | (g1+0).f1.f2; 32; 32; non-pointer; non-bitfield 3 | (g1+0).f1.f3+; 64; 640; non-pointer; non-bitfield 4 | (g1+0).f1.f4+; 704; 16; non-pointer; non-bitfield 5 | (g1+0).f2+; 768; 24; non-pointer; non-bitfield 6 | (g1+1).f1.f1; 832; 8; non-pointer; non-bitfield 7 | (g1+1).f1.f2; 864; 32; non-pointer; non-bitfield 8 | (g1+1).f1.f3+; 896; 640; non-pointer; non-bitfield 9 | (g1+1).f1.f4+; 1536; 16; non-pointer; non-bitfield 10 | (g1+1).f2+; 1600; 24; non-pointer; non-bitfield 11 | g2.f1.f2; 32; 32; non-pointer; non-bitfield 12 | g2.f1.f4+; 704; 16; non-pointer; non-bitfield 13 | g2.f2+; 768; 24; non-pointer; non-bitfield 14 | Succeeded 15 | -------------------------------------------------------------------------------- /patches/volatile_pintrace/volatile_test.patch: -------------------------------------------------------------------------------- 1 | diff --git a/volatile_pintrace/volatile_test.pl b/volatile_pintrace/volatile_test.pl 2 | index 34ba969..e8aed90 100755 3 | --- a/volatile_pintrace/volatile_test.pl 4 | +++ b/volatile_pintrace/volatile_test.pl 5 | @@ -106,10 +106,17 @@ my @ccomp = ("ia32", 6 | "ccomp", 7 | \@ccomp_opts); 8 | 9 | +my @ubuntu_gcc44 = ( 10 | + "ia32", 11 | + "gcc", 12 | + "gcc-4.4", 13 | + \@gcc_opts); 14 | + 15 | my @compilers_to_test = ( 16 | - \@clang, 17 | - \@gcccurrent, 18 | - \@ccomp, 19 | + \@ubuntu_gcc44, 20 | + # \@clang, 21 | + # \@gcccurrent, 22 | + # \@ccomp, 23 | ); 24 | 25 | ######################################################### 26 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder1.c: -------------------------------------------------------------------------------- 1 | volatile int g1; 2 | volatile int *g2; 3 | volatile int g3[10]; 4 | volatile int *g4[10]; 5 | 6 | struct S1 { 7 | int a1; 8 | }; 9 | 10 | volatile struct S1 g5; 11 | volatile struct S1 *g6; 12 | 13 | struct S2 { 14 | volatile int a1; 15 | }; 16 | 17 | struct S2 g7; 18 | 19 | int f1(void) 20 | { 21 | return g1; 22 | } 23 | 24 | int f2(void) 25 | { 26 | return *g2; 27 | } 28 | 29 | int f3(void) 30 | { 31 | int x = g3[0]; 32 | return x; 33 | } 34 | 35 | int f4(void) 36 | { 37 | return *g4[0]; 38 | } 39 | 40 | struct S1 f5(void) 41 | { 42 | return g5; 43 | } 44 | 45 | volatile struct S1* f6(void) 46 | { 47 | return g6; 48 | } 49 | 50 | int f7(void) 51 | { 52 | return g7.a1; 53 | } 54 | 55 | struct S2 f8(void) 56 | { 57 | return g7; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /ns/ubuntu12-d710.ns: -------------------------------------------------------------------------------- 1 | ## -*- mode: Tcl -*- 2 | ## 3 | 4 | ############################################################################### 5 | 6 | set ns [new Simulator] 7 | source tb_compat.tcl 8 | 9 | set opt(MNT) "/disk2" 10 | 11 | set imp [$ns node] 12 | tb-set-hardware $imp d710 13 | tb-set-node-os $imp UBUNTU12-64-STD 14 | 15 | set fs [$ns blockstore] 16 | $fs set-class local 17 | $fs set-placement NONSYSVOL 18 | $fs set-mount-point $opt(MNT) 19 | $fs set-node $imp 20 | 21 | tb-set-node-startcmd $imp \ 22 | {scp -p users.emulab.net:/proj/$PID/startcmds/$EID.sh /tmp && \ 23 | chmod +x /tmp/$EID.sh && \ 24 | /tmp/$EID.sh $MNT/$PID >& /tmp/$EID.log} 25 | 26 | $ns rtproto Static 27 | $ns run 28 | 29 | ############################################################################### 30 | 31 | ## End of file. 32 | -------------------------------------------------------------------------------- /ns/ubuntu12-d820.ns: -------------------------------------------------------------------------------- 1 | ## -*- mode: Tcl -*- 2 | ## 3 | 4 | ############################################################################### 5 | 6 | set ns [new Simulator] 7 | source tb_compat.tcl 8 | 9 | set opt(MNT) "/disk2" 10 | 11 | set imp [$ns node] 12 | tb-set-hardware $imp d820 13 | tb-set-node-os $imp UBUNTU12-64-STD 14 | 15 | set fs [$ns blockstore] 16 | $fs set-class local 17 | $fs set-placement NONSYSVOL 18 | $fs set-mount-point $opt(MNT) 19 | $fs set-node $imp 20 | 21 | tb-set-node-startcmd $imp \ 22 | {scp -p users.emulab.net:/proj/$PID/startcmds/$EID.sh /tmp && \ 23 | chmod +x /tmp/$EID.sh && \ 24 | /tmp/$EID.sh $MNT/$PID >& /tmp/$EID.log} 25 | 26 | $ns rtproto Static 27 | $ns run 28 | 29 | ############################################################################### 30 | 31 | ## End of file. 32 | -------------------------------------------------------------------------------- /ns/ubuntu12-pc3000.ns: -------------------------------------------------------------------------------- 1 | ## -*- mode: Tcl -*- 2 | ## 3 | 4 | ############################################################################### 5 | 6 | set ns [new Simulator] 7 | source tb_compat.tcl 8 | 9 | set opt(MNT) "/disk2" 10 | 11 | set imp [$ns node] 12 | tb-set-hardware $imp pc3000 13 | tb-set-node-os $imp UBUNTU12-64-STD 14 | 15 | set fs [$ns blockstore] 16 | $fs set-class local 17 | $fs set-placement NONSYSVOL 18 | $fs set-mount-point $opt(MNT) 19 | $fs set-node $imp 20 | 21 | tb-set-node-startcmd $imp \ 22 | {scp -p users.emulab.net:/proj/$PID/startcmds/$EID.sh /tmp && \ 23 | chmod +x /tmp/$EID.sh && \ 24 | /tmp/$EID.sh $MNT/$PID >& /tmp/$EID.log} 25 | 26 | $ns rtproto Static 27 | $ns run 28 | 29 | ############################################################################### 30 | 31 | ## End of file. 32 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/7.preprocessed.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 2778: (*l_1243) = (func_15(&p_8, l_1145.f0, l_1238, (((void*)0 != l_1239) , l_1238), &g_522) , g_1241) 2 | multiple volatile accesses: 3 | *l_1243 4 | g_1241 5 | 6 | Functions that have volatile accesses: 7 | func_1 : volatile access to g_1241 at line 2475 8 | func_3 : volatile access to *g_372 at line 2662 9 | func_9 : volatile access to *g_372 at line 2902 10 | func_21 : volatile access to g_498 at line 3130 11 | func_26 : volatile access to g_35 at line 3249 12 | func_58 : volatile access to g_480 at line 3302 13 | func_62 : volatile access to g_412 at line 3354 14 | func_66 : volatile access to g_35 at line 3484 15 | func_69 : volatile access to g_35 at line 3691 16 | main : volatile access to g_53 at line 3762 17 | 18 | -------------------------------------------------------------------------------- /patches/csmith/test-targets.patch: -------------------------------------------------------------------------------- 1 | diff --git a/utah/scripts/old_john_driver/evaluate_program.pl b/utah/scripts/old_john_driver/evaluate_program.pl 2 | index 259b0b6..5dc85d6 100755 3 | --- a/utah/scripts/old_john_driver/evaluate_program.pl 4 | +++ b/utah/scripts/old_john_driver/evaluate_program.pl 5 | @@ -529,6 +529,12 @@ my @ccomp = ( 6 | "ccomp", 7 | \@ccomp_opts); 8 | 9 | +my @ubuntu_gcc44 = ( 10 | + "ia32", 11 | + "gcc", 12 | + "gcc-4.4", 13 | + \@gcc_opts2); 14 | + 15 | my @llvms = ( 16 | \@llvmgcc20, 17 | \@llvmgcc21, 18 | @@ -538,9 +544,11 @@ my @llvms = ( 19 | ); 20 | 21 | my @compilers_to_test = ( 22 | - 23 | - \@clang, 24 | - \@gcccurrent, 25 | + 26 | + \@ubuntu_gcc44, 27 | + 28 | + #\@clang, 29 | + #\@gcccurrent, 30 | 31 | #\@gcc320, 32 | #\@gcc330, 33 | -------------------------------------------------------------------------------- /scripts/env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## 3 | 4 | ############################################################################### 5 | 6 | if test -z "$VOLTEST_HOME"; then 7 | echo $0: '$VOLTEST_HOME' is not set 8 | exit 1 9 | fi 10 | if test ! -e "$VOLTEST_HOME/scripts/vars.sh"; then 11 | echo $0: '$VOLTEST_HOME/scripts/vars.sh' does not exist 12 | exit 1 13 | fi 14 | . "$VOLTEST_HOME/scripts/vars.sh" 15 | 16 | ############################################################################### 17 | 18 | export CSMITH_HOME 19 | export PIN_HOME 20 | 21 | # Old driver: 22 | # PATH="$CSMITH_HOME/utah/scripts/old_john_driver:$PATH" 23 | # New driver: 24 | PATH="$VOLATILE_PINTRACE_HOME:$VOLATILE_CHECKER_HOME:$PATH" 25 | export PATH 26 | 27 | ############################################################################### 28 | 29 | ## End of file. 30 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/basic2.c: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | 3 | unsigned char g_1 = 5; 4 | char g_2 = 50; 5 | unsigned short g_3 = 945; 6 | short g_4 = 445; 7 | unsigned int g_5 = 890; 8 | int g_6 = 123; 9 | unsigned long g_7 = 89089123; 10 | long g_8 = 1187123; 11 | unsigned long long g_9 = 9999990123; 12 | long long g_10 = 1111990123; 13 | 14 | int main(void) 15 | { 16 | crc32_gentab(); 17 | crc32(g_1, sizeof(unsigned char)); 18 | crc32(g_2, sizeof(char)); 19 | crc32(g_3, sizeof(unsigned short)); 20 | crc32(g_4, sizeof(short)); 21 | crc32(g_5, sizeof(unsigned int)); 22 | crc32(g_6, sizeof(int)); 23 | crc32(g_7, sizeof(unsigned long)); 24 | crc32(g_8, sizeof(long)); 25 | crc32(g_9, sizeof(unsigned long long)); 26 | crc32(g_10, sizeof(long long)); 27 | print_checksum(crc32_context ^ 0xFFFFFFFFUL); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder3.c: -------------------------------------------------------------------------------- 1 | struct S1 { 2 | volatile int a1; 3 | int a2; 4 | }; 5 | 6 | struct S2 { 7 | struct S1 a1; 8 | }; 9 | 10 | struct S1 g1; 11 | struct S1 f1(void) 12 | { 13 | return g1; 14 | } 15 | 16 | struct S2 g2; 17 | struct S2 f2(void) 18 | { 19 | return g2; 20 | } 21 | 22 | struct S3 { 23 | struct { 24 | volatile int a1; 25 | } a1; 26 | }; 27 | struct S3 g3; 28 | struct S3 f3(void) 29 | { 30 | return g3; 31 | } 32 | 33 | struct S4 { 34 | struct S5 { 35 | volatile int a1; 36 | int a2; 37 | } a1; 38 | }; 39 | struct S4 g4; 40 | struct S4 f4(void) 41 | { 42 | return g4; 43 | } 44 | struct S5 g5; 45 | struct S5 f5(void) 46 | { 47 | return g5; 48 | } 49 | 50 | /* no vol */ 51 | int f6(void) 52 | { 53 | return g2.a1.a2; 54 | } 55 | 56 | /* no vol */ 57 | int f7(void) 58 | { 59 | return g4.a1.a2; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /volatile_pintrace/unittest/struct1.all_vars.out: -------------------------------------------------------------------------------- 1 | g1.f1+; 0x402040; 4; non-pointer 2 | g1.f2; 0x402048; 8; non-pointer 3 | (g1.f3+0).f1; 0x402050; 1; non-pointer 4 | (g1.f3+0).f2; 0x402054; 4; non-pointer 5 | (g1.f3+0).f3; 0x402058; 2; non-pointer 6 | (g1.f3+0).f3; 0x40205a; 1; non-pointer; fc 7 | (g1.f3+0).f4; 0x40205c; 3; non-pointer 8 | (g1.f3+0).f4; 0x40205f; 1; non-pointer; f8 9 | (g1.f3+1).f1; 0x402060; 1; non-pointer 10 | (g1.f3+1).f2; 0x402064; 4; non-pointer 11 | (g1.f3+1).f3; 0x402068; 2; non-pointer 12 | (g1.f3+1).f3; 0x40206a; 1; non-pointer; fc 13 | (g1.f3+1).f4; 0x40206c; 3; non-pointer 14 | (g1.f3+1).f4; 0x40206f; 1; non-pointer; f8 15 | (g1.f3+2).f1; 0x402070; 1; non-pointer 16 | (g1.f3+2).f2; 0x402074; 4; non-pointer 17 | (g1.f3+2).f3; 0x402078; 2; non-pointer 18 | (g1.f3+2).f3; 0x40207a; 1; non-pointer; fc 19 | (g1.f3+2).f4; 0x40207c; 3; non-pointer 20 | (g1.f3+2).f4; 0x40207f; 1; non-pointer; f8 21 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/5.preprocessed.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 2785: (((void*)0 != l_2074) >= ((*l_2081) = (safe_rshift_func_uint16_t_u_s(func_44(((((*l_2026) = ((**g_525)--)) == func_44((g_264[3] = func_44(((*l_2079) &= 9UL))))) == func_19(((*g_574) , l_2080), &l_2080))), l_2080)))) 2 | multiple volatile accesses: 3 | *g_525 4 | func_44(((*l_2079) &= 9UL)) 5 | 6 | Functions that have volatile accesses: 7 | func_5 : volatile access to g_638 at line 2507 8 | func_27 : volatile access to *g_1715 at line 2983 9 | func_34 : volatile access to g_682 at line 3050 10 | func_44 : volatile access to g_638 at line 3384 11 | func_60 : volatile access to g_191 at line 3409 12 | func_66 : volatile access to g_638 at line 3535 13 | func_70 : volatile access to **g_103 at line 3615 14 | func_73 : volatile access to g_101 at line 4081 15 | main : volatile access to g_30 at line 4103 16 | 17 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/struct_array2.c: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | 3 | struct S1 { 4 | char f1[2]; 5 | long f2; 6 | int f3[2]; 7 | }; 8 | 9 | struct S2 { 10 | int f1; 11 | struct S1 f2[2]; 12 | }; 13 | 14 | struct S2 g_1 = {123, {{{11,22}, 987654, {99, 88}}, 15 | {{11,22}, 987654, {99, 88}}}}; 16 | 17 | int main(void) 18 | { 19 | crc32_gentab(); 20 | crc32(g_1.f1, sizeof(int)); 21 | 22 | crc32(g_1.f2[0].f1[0], sizeof(char)); 23 | crc32(g_1.f2[0].f1[1], sizeof(char)); 24 | crc32(g_1.f2[0].f2, sizeof(long)); 25 | crc32(g_1.f2[0].f3[0], sizeof(int)); 26 | crc32(g_1.f2[0].f3[1], sizeof(int)); 27 | 28 | crc32(g_1.f2[1].f1[0], sizeof(char)); 29 | crc32(g_1.f2[1].f1[1], sizeof(char)); 30 | crc32(g_1.f2[1].f2, sizeof(long)); 31 | crc32(g_1.f2[1].f3[0], sizeof(int)); 32 | crc32(g_1.f2[1].f3[1], sizeof(int)); 33 | 34 | print_checksum(crc32_context ^ 0xFFFFFFFFUL); 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/2.preprocessed.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 2702: (*p_8) = (safe_rshift_func_uint8_t_u_u((&l_1684[3][5] == (g_1695 = l_1686[4][3][3])), func_78((**l_1681), (p_9 = (func_45(l_1696, (*l_1681), (*l_1696), l_1696) < 4294967292UL)), (*l_1696), (*g_1011)))) 2 | multiple volatile accesses: 3 | func_45(l_1696, (*l_1681), (*l_1696), l_1696) 4 | g_1011 5 | 6 | Functions that have volatile accesses: 7 | func_6 : volatile access to g_1203 at line 2517 8 | func_11 : volatile access to g_591 at line 3100 9 | func_32 : volatile access to *g_74 at line 3343 10 | func_37 : volatile access to g_97 at line 3541 11 | func_45 : volatile access to *g_74 at line 3904 12 | func_51 : volatile access to *g_74 at line 3924 13 | func_61 : volatile access to g_86 at line 3990 14 | func_78 : volatile access to g_86 at line 4010 15 | func_106 : volatile access to g_86 at line 4065 16 | main : volatile access to g_86 at line 4271 17 | 18 | -------------------------------------------------------------------------------- /creduce/tests-from-log.awk: -------------------------------------------------------------------------------- 1 | #!/bin/awk 2 | # 3 | # grab.awk --- extract a script from a volatile-testing log file 4 | # 5 | # Run: awk -f grab.awk 6 | # 7 | 8 | ############################################################################### 9 | 10 | BEGIN { 11 | print "#!/bin/sh" 12 | } 13 | 14 | END { 15 | print "" 16 | print "# End of file." 17 | } 18 | 19 | /^------ RANDOM PROGRAM [0-9]+ ------$/ { 20 | test_num = $4 21 | test_timeout = 0 22 | } 23 | 24 | /^regenerate with: '.*'$/ { 25 | split($0,x,/'/) 26 | test_cmdline = x[2] 27 | } 28 | 29 | /^TIMEOUT/ { 30 | test_timeout = 1 31 | } 32 | 33 | /^INTERNAL VOLATILE FAILURE/ { 34 | print "" 35 | print "# random program", test_num 36 | print "#", $0 37 | if (test_timeout) { 38 | print "# timed out" 39 | } else { 40 | print test_cmdline 41 | } 42 | } 43 | 44 | ############################################################################### 45 | 46 | ## End of file. 47 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/3.preprocessed.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 2798: l_2086 = func_66(&l_1931, (l_2073 ^= ((((safe_add_func_uint32_t_u_u((p_7 > func_44((*l_2030))), ((*l_2079) , (**g_525)))) > (safe_sub_func_uint16_t_u_u((((func_19(l_2085, (l_2026 = &l_1956[4])) , (*l_2025)) || p_10) > 0x677657B0EC45A456LL), 6L))) >= p_8) & p_7)), g_1217) 2 | multiple volatile accesses: 3 | func_44((*l_2030)) 4 | *g_525 5 | 6 | Functions that have volatile accesses: 7 | func_1 : volatile access to g_1685 at line 2442 8 | func_5 : volatile access to g_638 at line 2487 9 | func_27 : volatile access to *g_1715 at line 2964 10 | func_34 : volatile access to g_682 at line 3031 11 | func_44 : volatile access to g_638 at line 3365 12 | func_60 : volatile access to g_191 at line 3390 13 | func_66 : volatile access to g_638 at line 3516 14 | func_70 : volatile access to **g_103 at line 3596 15 | func_73 : volatile access to g_101 at line 4062 16 | main : volatile access to g_30 at line 4084 17 | 18 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/reorder_test2.c: -------------------------------------------------------------------------------- 1 | 2 | struct S1 { 3 | volatile int a1; 4 | int a2; 5 | }; 6 | 7 | struct S2 { 8 | volatile struct S1 a1; 9 | }; 10 | 11 | volatile struct S2 g1; 12 | /* good */ 13 | int f1(void) 14 | { 15 | int l = g1.a1.a1; 16 | return g1.a1.a1 + l; 17 | } 18 | 19 | volatile int g2[2][2]; 20 | int f2(void) 21 | { 22 | return g2[0][0]; 23 | } 24 | 25 | volatile int g3; 26 | volatile int * volatile g4 = &g3; 27 | int f3(void) 28 | { 29 | return *g4; 30 | } 31 | 32 | volatile int * volatile * volatile g5 = &g4; 33 | int f4(void) 34 | { 35 | return **g5; 36 | } 37 | 38 | volatile int * volatile * volatile f5(void) 39 | { 40 | return g5; 41 | } 42 | 43 | struct S4 { 44 | int a1; 45 | }; 46 | 47 | struct S3 { 48 | volatile int *a1; 49 | volatile int a2[10]; 50 | volatile struct S4 a3; 51 | }; 52 | volatile struct S3 g6; 53 | struct S4 f6(void) 54 | { 55 | return g6.a3; 56 | } 57 | 58 | int f7(void) 59 | { 60 | return g6.a2[0]; 61 | } 62 | 63 | int f8(void) 64 | { 65 | return *g6.a1; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /scripts/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## 3 | 4 | ############################################################################### 5 | 6 | if test -z "$VOLTEST_HOME"; then 7 | echo $0: '$VOLTEST_HOME' is not set 8 | exit 1 9 | fi 10 | if test ! -e "$VOLTEST_HOME/scripts/vars.sh"; then 11 | echo $0: '$VOLTEST_HOME/scripts/vars.sh' does not exist 12 | exit 1 13 | fi 14 | # . "$VOLTEST_HOME/scripts/vars.sh" 15 | . "$VOLTEST_HOME/scripts/env.sh" 16 | 17 | ############################################################################### 18 | 19 | # Abort this script when any command fails. 20 | set -e 21 | # Abort this script when any unbound variable is used. 22 | set -u 23 | 24 | ############################################################################### 25 | 26 | # "launchn.pl" lives in $VOLATILE_PINTRACE_HOME 27 | cd "$WORK_RUN_HOME" 28 | launchn.pl -- \ 29 | --strict-volatile-rule \ 30 | --no-vol-struct-union-fields \ 31 | --use-pin-checksums 32 | 33 | # To stop the madness 34 | # 35 | # kill_voltest.pl 36 | 37 | ############################################################################### 38 | 39 | ## End of file. 40 | -------------------------------------------------------------------------------- /patches/csmith/volatile_pintrace.patch: -------------------------------------------------------------------------------- 1 | diff --git a/utah/scripts/old_john_driver/evaluate_program.pl b/utah/scripts/old_john_driver/evaluate_program.pl 2 | index 259b0b6..b30ae06 100755 3 | --- a/utah/scripts/old_john_driver/evaluate_program.pl 4 | +++ b/utah/scripts/old_john_driver/evaluate_program.pl 5 | @@ -52,7 +52,7 @@ my $NO_VOLCHECK = 0; 6 | my $USE_VOLCHECK = 1; 7 | my $USE_PINTOOL = 2; 8 | 9 | -my $CHECK_VOLATILE = $NO_VOLCHECK; 10 | +my $CHECK_VOLATILE = $USE_VOLCHECK; 11 | 12 | if (defined($ENV{"PIN_CMD"})) { 13 | $CHECK_VOLATILE = $USE_PINTOOL; 14 | diff --git a/utah/scripts/old_john_driver/random_test.pl b/utah/scripts/old_john_driver/random_test.pl 15 | index d5c35f8..8d7ab8f 100755 16 | --- a/utah/scripts/old_john_driver/random_test.pl 17 | +++ b/utah/scripts/old_john_driver/random_test.pl 18 | @@ -84,8 +84,8 @@ my $platform = "x86_64"; 19 | my $CSMITH_CCOMP = ""; 20 | 21 | # set up pintool for volatile testing 22 | -my $use_pintool = 0; 23 | -# my $use_pintool = 1; 24 | +# my $use_pintool = 0; 25 | +my $use_pintool = 1; 26 | 27 | #my $PIN_MODE = "-output_mode verbose"; # We are not supporting it right now 28 | my $PIN_MODE = ""; 29 | -------------------------------------------------------------------------------- /volatile_checker/reorder_test_dir/6.preprocessed.out: -------------------------------------------------------------------------------- 1 | Error: Offensive Expr is at line 2497: l_2574 = ((****g_1290) == (((safe_div_func_int32_t_s_s((l_2573[6][5][1] = (safe_lshift_func_uint16_t_u_u((safe_unary_minus_func_int16_t_s(4L)), (((((**g_689) = (safe_mod_func_int32_t_s_s(0x0C0B2188L, (safe_rshift_func_int8_t_s_s((g_2569 == (**g_419)), ((*l_2557) = (safe_unary_minus_func_int32_t_s(l_2571)))))))) < l_2572) >= 18446744073709551615UL) && (*l_2557))))), 0xF0B5EB35L)) >= (*g_271)) , l_2572)) 2 | multiple volatile accesses: 3 | *g_689 4 | g_2569 5 | 6 | Functions that have volatile accesses: 7 | func_1 : volatile access to g_11 at line 2470 8 | func_17 : volatile access to g_34 at line 2688 9 | func_40 : volatile access to *g_689 at line 2881 10 | func_46 : volatile access to g_1925 at line 3608 11 | func_50 : volatile access to g_297 at line 3748 12 | func_58 : volatile access to g_11 at line 3885 13 | func_63 : volatile access to g_541 at line 4314 14 | func_69 : volatile access to g_352 at line 4344 15 | func_77 : volatile access to g_34 at line 4393 16 | func_86 : volatile access to g_34 at line 4485 17 | main : volatile access to g_11 at line 4603 18 | 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | -*- mode: Text -*- 2 | 3 | A framework for performing volatile-testing experiments. 4 | 5 | To use: 6 | 7 | + Decide on the name of your Emulab experiment. Let's assume that you call 8 | decide to call it "exp" to run it in the "randtest" project. 9 | 10 | + Create a "bootstrap" file for your experiment. Copy `scripts/bootstrap.sh' 11 | to Emulab: put it in the `startcmds' subdirectory of your project directory 12 | and give it a name to match your experiment. So, for our example: 13 | 14 | scp -p scripts/bootstrap.sh \ 15 | users.emulab.net:/proj/randtest/startcmds/exp.sh 16 | 17 | + Use `ns/ubuntu12-pc3000.ns' or one of the other NS files to create and 18 | swap-in an Emulab experiment. 19 | 20 | + Login to your experiment: 21 | 22 | ssh imp.exp.randtest.emulab.net 23 | 24 | + Declare where to find the node-local clone of this repository: 25 | 26 | export VOLTEST_HOME=/disk2/randtest/src/voltest 27 | 28 | + Set up your environment (if you wish; scripts set their own): 29 | 30 | . $VOLTEST_HOME/scripts/env.sh 31 | 32 | + Install and configure the volatile-testing test harness: 33 | 34 | $VOLTEST_HOME/scripts/setup.sh 35 | 36 | + Run the test harness: 37 | 38 | $VOLTEST_HOME/scripts/run.sh 39 | 40 | To learn where things go, see `$VOLTEST_HOME/scripts/vars.sh'. 41 | 42 | ## End of file. 43 | -------------------------------------------------------------------------------- /volatile_checker/AccessOnceChecker.h: -------------------------------------------------------------------------------- 1 | #ifndef ACCESS_ONCE_CHECKER_H 2 | #define ACCESS_ONCE_CHECKER_H 3 | 4 | #include 5 | #include "llvm/ADT/StringRef.h" 6 | #include "Checker.h" 7 | 8 | namespace clang { 9 | class ASTContext; 10 | class DeclRefExpr; 11 | } 12 | 13 | class AccessOnceVisitor; 14 | 15 | class AccessOnceChecker : public Checker { 16 | friend class AccessOnceVisitor; 17 | 18 | public: 19 | 20 | AccessOnceChecker(const char *CheckerName, const char *Desc) 21 | : Checker(CheckerName, Desc), 22 | TheAccessOnceName("ACCESS_ONCE") 23 | { } 24 | 25 | ~AccessOnceChecker(); 26 | 27 | private: 28 | 29 | virtual void Initialize(clang::ASTContext &context); 30 | 31 | virtual void HandleTranslationUnit(clang::ASTContext &Ctx); 32 | 33 | virtual void printCmdOpts(); 34 | 35 | virtual bool handleValueCmdOpt(const std::string &ValueStr, 36 | size_t SepPos); 37 | 38 | void setAccessOnceVars(const std::string &VarsStr); 39 | 40 | bool checkVarAccess(clang::DeclRefExpr *DRE); 41 | 42 | StringSet VarNames; 43 | 44 | llvm::StringRef TheAccessOnceName; 45 | 46 | // Unimplemented 47 | AccessOnceChecker(); 48 | 49 | AccessOnceChecker(const AccessOnceChecker &); 50 | 51 | void operator=(const AccessOnceChecker &); 52 | }; 53 | 54 | #endif // ACCESS_ONCE_CHECKER_H 55 | 56 | -------------------------------------------------------------------------------- /volatile_pintrace/launchn.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # add options to backup or delete existing data 4 | 5 | use strict; 6 | use warnings; 7 | use Sys::CPU; 8 | 9 | my $NICE = ""; 10 | 11 | open INF, "ps axuww |" or die; 12 | while () { 13 | if (/volatile\_test/) { 14 | print "oops-- kill existing volatile_test.pl processes first!\n"; 15 | exit; 16 | } 17 | } 18 | close INF; 19 | 20 | sub usage () { 21 | die "usage: launchn.pl [--cpus=number] [--nice=number] [-- ]\n"; 22 | } 23 | 24 | my @VOLATILE_TEST_ARGS = (); 25 | my $NOT_PRINT_CHECKSUM = ""; 26 | my $CPUS = undef; 27 | 28 | my $opt; 29 | 30 | while(defined ($opt = shift @ARGV)) { 31 | if ($opt =~ m/^--(.+)=(.+)$/) { 32 | if ($1 eq "cpus") { 33 | $CPUS = $2; 34 | usage() if ($CPUS !~ m/^[0-9]+$/); 35 | } 36 | elsif ($1 eq "nice") { 37 | $NICE = "nice -$2"; 38 | usage() if ($2 !~ m/^[0-9]+$/); 39 | } 40 | else { 41 | usage(); 42 | } 43 | } 44 | elsif ($opt =~ m/^--$/) { 45 | # Everything after "--" passes thru to volatile_test.pl 46 | @VOLATILE_TEST_ARGS = @ARGV; 47 | @ARGV = (); 48 | } 49 | else { 50 | usage(); 51 | } 52 | } 53 | 54 | if (!defined($CPUS)) { 55 | $CPUS = Sys::CPU::cpu_count(); 56 | print "looks like we have $CPUS cpus\n"; 57 | } 58 | 59 | system "rm -rf work*"; 60 | 61 | for (my $i=0; $i<$CPUS; $i++) { 62 | my $dir = "work$i"; 63 | system "mkdir $dir"; 64 | system "$NICE nohup volatile_test.pl @VOLATILE_TEST_ARGS --work-dir=$dir > $dir/output.txt 2>&1 &"; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /volatile_checker/volatile_address_test_dir/struct2.out: -------------------------------------------------------------------------------- 1 | (g1+0).f1+; 0; 16; non-pointer; non-bitfield 2 | ((g1+0).f2+0).f2+; 128; 24; non-pointer; non-bitfield 3 | ((g1+0).f2+0).f3; 160; 16; non-pointer; non-bitfield 4 | ((g1+0).f2+1).f2+; 256; 24; non-pointer; non-bitfield 5 | ((g1+0).f2+1).f3; 288; 16; non-pointer; non-bitfield 6 | ((g1+0).f2+2).f2+; 384; 24; non-pointer; non-bitfield 7 | ((g1+0).f2+2).f3; 416; 16; non-pointer; non-bitfield 8 | (g1+1).f1+; 448; 16; non-pointer; non-bitfield 9 | ((g1+1).f2+0).f2+; 576; 24; non-pointer; non-bitfield 10 | ((g1+1).f2+0).f3; 608; 16; non-pointer; non-bitfield 11 | ((g1+1).f2+1).f2+; 704; 24; non-pointer; non-bitfield 12 | ((g1+1).f2+1).f3; 736; 16; non-pointer; non-bitfield 13 | ((g1+1).f2+2).f2+; 832; 24; non-pointer; non-bitfield 14 | ((g1+1).f2+2).f3; 864; 16; non-pointer; non-bitfield 15 | (g1+2).f1+; 896; 16; non-pointer; non-bitfield 16 | ((g1+2).f2+0).f2+; 1024; 24; non-pointer; non-bitfield 17 | ((g1+2).f2+0).f3; 1056; 16; non-pointer; non-bitfield 18 | ((g1+2).f2+1).f2+; 1152; 24; non-pointer; non-bitfield 19 | ((g1+2).f2+1).f3; 1184; 16; non-pointer; non-bitfield 20 | ((g1+2).f2+2).f2+; 1280; 24; non-pointer; non-bitfield 21 | ((g1+2).f2+2).f3; 1312; 16; non-pointer; non-bitfield 22 | (g1+3).f1+; 1344; 16; non-pointer; non-bitfield 23 | ((g1+3).f2+0).f2+; 1472; 24; non-pointer; non-bitfield 24 | ((g1+3).f2+0).f3; 1504; 16; non-pointer; non-bitfield 25 | ((g1+3).f2+1).f2+; 1600; 24; non-pointer; non-bitfield 26 | ((g1+3).f2+1).f3; 1632; 16; non-pointer; non-bitfield 27 | ((g1+3).f2+2).f2+; 1728; 24; non-pointer; non-bitfield 28 | ((g1+3).f2+2).f3; 1760; 16; non-pointer; non-bitfield 29 | Succeeded 30 | -------------------------------------------------------------------------------- /volatile_pintrace/all_addrs_unittest_dir/crc32.h: -------------------------------------------------------------------------------- 1 | #ifndef CRC32_H 2 | #define CRC32_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static uint32_t crc32_tab[256]; 10 | static uint32_t crc32_context = 0xFFFFFFFFUL; 11 | 12 | static void 13 | crc32_gentab (void) 14 | { 15 | uint32_t crc; 16 | const uint32_t poly = 0xEDB88320UL; 17 | int i, j; 18 | 19 | for (i = 0; i < 256; i++) { 20 | crc = i; 21 | for (j = 8; j > 0; j--) { 22 | if (crc & 1) 23 | crc = (crc >> 1) ^ poly; 24 | else 25 | crc >>= 1; 26 | } 27 | crc32_tab[i] = crc; 28 | } 29 | } 30 | 31 | static void 32 | crc32_byte (uint8_t b) { 33 | crc32_context = 34 | ((crc32_context >> 8) & 0x00FFFFFF) ^ 35 | crc32_tab[(crc32_context ^ b) & 0xFF]; 36 | } 37 | 38 | static void 39 | crc32_8bytes (uint64_t val) 40 | { 41 | crc32_byte ((val>>0) & 0xff); 42 | crc32_byte ((val>>8) & 0xff); 43 | crc32_byte ((val>>16) & 0xff); 44 | crc32_byte ((val>>24) & 0xff); 45 | crc32_byte ((val>>32) & 0xff); 46 | crc32_byte ((val>>40) & 0xff); 47 | crc32_byte ((val>>48) & 0xff); 48 | crc32_byte ((val>>56) & 0xff); 49 | } 50 | 51 | static void crc32(uint64_t val, size_t sz) 52 | { 53 | size_t i; 54 | /* assert((sz <= 8) && "Invalid sz!"); */ 55 | for (i = 0; i < sz; i++) { 56 | uint32_t tmp_v = 0; 57 | memcpy(&tmp_v, (char*)((char*)(&val) + i), 1); 58 | /* printf("value = %u\n", tmp_v); */ 59 | crc32_8bytes(tmp_v); 60 | } 61 | } 62 | 63 | static void 64 | print_checksum(uint32_t crc) 65 | { 66 | #ifndef NOT_PRINT_CHECKSUM 67 | printf ("checksum = %X\n", crc); 68 | #endif 69 | } 70 | 71 | #endif 72 | 73 | -------------------------------------------------------------------------------- /volatile_pintrace/pin.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # get the directory of this script 4 | origin=$0 5 | # If it does not begin with /, then it is relative to the current working directory 6 | if [ "${origin:0:1}" != "/" ]; then 7 | origin=$PWD/$origin 8 | fi 9 | origin=`dirname "$origin"` 10 | 11 | # Libraries are found relative to origin 12 | lib_base="$origin" 13 | elf_libs="$lib_base/ia32/runtime:$lib_base/intel64/runtime" 14 | if [ `$origin/source/tools/testGccVersion /usr/bin/gcc` -eq 1 ] 15 | then 16 | cpp_libs="$lib_base/ia32/runtime/cpplibs:$lib_base/intel64/runtime/cpplibs" 17 | else 18 | cpp_libs= 19 | fi 20 | glibc_libs="$lib_base/ia32/runtime/glibc:$lib_base/intel64/runtime/glibc" 21 | # vm/tool need elf, cpp and glibc libs 22 | export PIN_VM_LD_LIBRARY_PATH=$elf_libs:$cpp_libs:$glibc_libs:$LD_LIBRARY_PATH 23 | 24 | # If variables we are going to modify are set, save the value. They will be restored 25 | # after the injector starts 26 | export PIN_LD_RESTORE_REQUIRED=t 27 | if [ -n "${LD_LIBRARY_PATH+x}" ] 28 | then 29 | export PIN_APP_LD_LIBRARY_PATH=$LD_LIBRARY_PATH 30 | fi 31 | 32 | if [ -n "${LD_ASSUME_KERNEL+x}" ] 33 | then 34 | export PIN_APP_LD_ASSUME_KERNEL=$LD_ASSUME_KERNEL 35 | fi 36 | unset LD_ASSUME_KERNEL 37 | 38 | if [ -n "${LD_BIND_NOW+x}" ] 39 | then 40 | export PIN_APP_LD_BIND_NOW=$LD_BIND_NOW 41 | fi 42 | 43 | if [ -n "${LD_PRELOAD+x}" ] 44 | then 45 | export PIN_APP_LD_PRELOAD=$LD_PRELOAD 46 | fi 47 | unset LD_PRELOAD 48 | 49 | # injector just needs elf and cpp libs, it cannot use glibc libs 50 | export LD_LIBRARY_PATH=$elf_libs:$cpp_libs:$LD_LIBRARY_PATH 51 | 52 | "$origin"/ia32/bin/pinbin -p64 "$origin"/intel64/bin/pinbin "${@}" 53 | #"$origin"/intel64/bin/pinbin "${@}" 54 | -------------------------------------------------------------------------------- /volatile_checker/Checker.h: -------------------------------------------------------------------------------- 1 | #ifndef CHECKER_H 2 | #define CHECKER_H 3 | 4 | #include 5 | #include 6 | #include "clang/AST/ASTConsumer.h" 7 | #include "clang/Rewrite/Core/Rewriter.h" 8 | 9 | #ifndef ENABLE_CHECKER_ASSERT 10 | #define CheckerAssert(x) {if (!(x)) exit(0);} 11 | #else 12 | #define CheckerAssert(x) assert(x) 13 | #endif 14 | 15 | namespace clang { 16 | class ASTContext; 17 | class Expr; 18 | } 19 | 20 | class Checker : public clang::ASTConsumer { 21 | 22 | public: 23 | 24 | Checker(const char *CheckerName, const char *Desc) 25 | : Name(CheckerName), 26 | Success(true), 27 | CheckMsg(""), 28 | Context(NULL), 29 | DescriptionString(Desc) 30 | { 31 | // Nothing to do 32 | } 33 | 34 | virtual ~Checker(); 35 | 36 | bool isSuccess(std::string &ErrorMsg) { 37 | ErrorMsg = CheckMsg; 38 | return Success; 39 | } 40 | 41 | std::string &getDescription() { 42 | return DescriptionString; 43 | } 44 | 45 | virtual void printCmdOpts() { } 46 | 47 | bool handleCmdOpt(const std::string &Arg); 48 | 49 | protected: 50 | 51 | typedef std::set StringSet; 52 | 53 | void getExprString(const clang::Expr *E, std::string &ES); 54 | 55 | void getExprLineNumStr(const clang::Expr *E, std::string &ES); 56 | 57 | virtual bool handleValueCmdOpt(const std::string &/*ArgStr*/, 58 | size_t /*SepPos*/) { 59 | return false; 60 | } 61 | 62 | virtual bool handleNonValueCmdOpt(const std::string &/*Arg*/) { 63 | return false; 64 | } 65 | 66 | void splitString(const std::string &Str, char Delim, 67 | StringSet &Elems); 68 | 69 | virtual void Initialize(clang::ASTContext &context); 70 | 71 | const std::string Name; 72 | 73 | bool Success; 74 | 75 | std::string CheckMsg; 76 | 77 | clang::ASTContext *Context; 78 | 79 | std::string DescriptionString; 80 | 81 | clang::Rewriter TheRewriter; 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /volatile_pintrace/install.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use Cwd; 4 | use strict; 5 | use warnings; 6 | 7 | my $LLVM_PATH = $ENV{"LLVM_PATH"}; 8 | die "Please setup LLVM_PATH...\n" unless (defined($LLVM_PATH)); 9 | 10 | my $PIN_HOME = "pin-2.12-55942-gcc.4.4.7-linux"; 11 | my $SCRIPT_HOME = "volatile_pintrace"; 12 | my $CHECKER_HOME = "volatile_checker"; 13 | 14 | sub abort_if_fail ($) { 15 | my $cmd = shift; 16 | print(" runit:$cmd\n"); 17 | if ((system "$cmd") == -1) { 18 | die "FAILED: system '$cmd': $?"; 19 | } 20 | my $exit_value = $? >> 8; 21 | die "FAIL: system '$cmd': $exit_value" if ($exit_value); 22 | } 23 | 24 | sub chdir_or_die($) { 25 | my ($dir) = @_; 26 | print " cd $dir\n"; 27 | chdir $dir or die "failed to chdir $dir"; 28 | } 29 | 30 | sub setup_volatile_checker() { 31 | print "* Start building volatile_checker...\n"; 32 | my $cwd = cwd(); 33 | chdir_or_die($CHECKER_HOME); 34 | abort_if_fail("LLVM_PATH=$LLVM_PATH make > /dev/null 2>&1"); 35 | chdir_or_die($cwd); 36 | print "- Successfully built volatile_checker\n\n"; 37 | } 38 | 39 | sub setup_pintool() { 40 | print "* Start building pintool...\n"; 41 | my $pin_package = "$PIN_HOME.tar.gz"; 42 | if (!(-f $pin_package)) { 43 | abort_if_fail("wget http://software.intel.com/sites/landingpage/pintool/downloads/$pin_package > /dev/null 2>&1"); 44 | } 45 | if (!(-d $PIN_HOME)) { 46 | abort_if_fail("tar zxvf $pin_package > /dev/null 2>&1"); 47 | } 48 | my $cwd = cwd(); 49 | my $pin_dir = "$PIN_HOME/source/tools/ManualExamples"; 50 | abort_if_fail("cp -f $SCRIPT_HOME/pinatrace.cpp $pin_dir/"); 51 | chdir_or_die($pin_dir); 52 | abort_if_fail("make > /dev/null 2>&1"); 53 | abort_if_fail("TARGET=ia32 make > /dev/null 2>&1"); 54 | chdir_or_die("$cwd"); 55 | abort_if_fail("cp -f $SCRIPT_HOME/pin.sh $PIN_HOME/"); 56 | print "- Successfully built pin\n\n"; 57 | } 58 | 59 | sub main() { 60 | setup_pintool(); 61 | setup_volatile_checker(); 62 | } 63 | main(); 64 | -------------------------------------------------------------------------------- /volatile_pintrace/run_test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my $VOLATILE_TOOL_HOME = $ENV{"VOLATILE_TOOL_HOME"}; 7 | die "Please setup VOLATILE_TOOL_HOME...\n" 8 | unless (defined($VOLATILE_TOOL_HOME)); 9 | my $CSMITH_INCLUDE_DIR = $ENV{"CSMITH_INCLUDE_DIR"}; 10 | die "Please setup CSMITH_INCLUDE_DIR...\n" 11 | unless (defined($CSMITH_INCLUDE_DIR)); 12 | 13 | my $GCC = "gcc"; 14 | if (defined($ENV{"CC"})) { 15 | $GCC = $ENV{"CC"}; 16 | } 17 | 18 | my $PIN_HOME = "$VOLATILE_TOOL_HOME/pin-2.12-55942-gcc.4.4.7-linux"; 19 | my $CHECKER = "$VOLATILE_TOOL_HOME/volatile_checker/volatile_checker"; 20 | my $GEN_VOLATILE_ADDR = "$VOLATILE_TOOL_HOME/volatile_pintrace/gen_volatile_addr.pl"; 21 | my $PIN_BIN = "$PIN_HOME/pin.sh -injection child -t $PIN_HOME/source/tools/ManualExamples/obj-intel64/pinatrace.so"; 22 | 23 | sub runit ($) { 24 | my ($cmd) = @_; 25 | print "runit: $cmd\n"; 26 | if ((system "$cmd") != 0) { 27 | return -1; 28 | } 29 | my $exit_value = $? >> 8; 30 | return $exit_value; 31 | } 32 | 33 | sub abort_if_fail($) { 34 | my ($cmd) = @_; 35 | die "Fatal error!" if (runit($cmd)); 36 | } 37 | 38 | die "Usage: do_all.pl " unless (@ARGV == 3); 39 | 40 | my $mode = $ARGV[0]; 41 | my $cfile = $ARGV[1]; 42 | my $OPT = "-$ARGV[2]"; 43 | # summary, checksum, verbose 44 | my $PIN_OUTPUT_MODE = "-output_mode $mode"; 45 | my $base = $cfile; 46 | $base =~ s/.c$//; 47 | my $preprocessed_cfile = "$base.pre.i"; 48 | my $gcc_compile_output = "$base.gcc.compile.out"; 49 | my $clang_addr_file = "$base.clang.addr"; 50 | my $clang_all_addr_file = "$base.clang.all.addr"; 51 | my $addr_file = "$base.addr"; 52 | my $all_addr_file = "$base.all.addr"; 53 | my $exe_file = "$base.out"; 54 | my $pin_output = "$base.pin.out"; 55 | 56 | abort_if_fail("$GCC -I$CSMITH_INCLUDE_DIR -E $cfile > $preprocessed_cfile"); 57 | abort_if_fail("$CHECKER --checker=volatile-address --all-vars-output=$clang_all_addr_file > $clang_addr_file $preprocessed_cfile 2>&1"); 58 | abort_if_fail("$GCC $OPT $preprocessed_cfile -o $exe_file > $gcc_compile_output 2>&1"); 59 | abort_if_fail("$GEN_VOLATILE_ADDR --vars-file=$clang_addr_file --all-vars-file=$clang_all_addr_file --all-var-addrs-output=$all_addr_file $exe_file > $addr_file 2>&1"); 60 | abort_if_fail("$PIN_BIN -vol_input $addr_file $PIN_OUTPUT_MODE -- ./$exe_file > $pin_output 2>&1"); 61 | 62 | -------------------------------------------------------------------------------- /volatile_checker/Checker.cpp: -------------------------------------------------------------------------------- 1 | #include "Checker.h" 2 | 3 | #include 4 | 5 | #include "clang/AST/RecursiveASTVisitor.h" 6 | #include "clang/AST/ASTContext.h" 7 | #include "clang/Basic/SourceManager.h" 8 | #include "llvm/Support/raw_ostream.h" 9 | 10 | using namespace clang; 11 | 12 | void Checker::Initialize(ASTContext &context) 13 | { 14 | Context = &context; 15 | TheRewriter.setSourceMgr(Context->getSourceManager(), 16 | Context->getLangOpts()); 17 | } 18 | 19 | bool Checker::handleCmdOpt(const std::string &Arg) 20 | { 21 | if (Arg.compare(0, 2, "--")) 22 | return false; 23 | 24 | std::string SubArgStr = Arg.substr(2); 25 | if (!SubArgStr.length()) 26 | return false; 27 | 28 | size_t found; 29 | found = SubArgStr.find('='); 30 | if (found != std::string::npos) 31 | return handleValueCmdOpt(SubArgStr, found); 32 | else 33 | return handleNonValueCmdOpt(SubArgStr); 34 | } 35 | 36 | void Checker::splitString(const std::string &Str, char Delim, 37 | StringSet &Elems) 38 | { 39 | std::stringstream SS(Str); 40 | std::string OneElem; 41 | while(std::getline(SS, OneElem, Delim)) { 42 | if (OneElem.empty()) 43 | continue; 44 | Elems.insert(OneElem); 45 | } 46 | } 47 | 48 | void Checker::getExprLineNumStr(const Expr *E, std::string &ES) 49 | { 50 | ES = ""; 51 | SourceRange ExprRange = E->getSourceRange(); 52 | CheckerAssert(ExprRange.isValid() && "Invalid ExprRange!"); 53 | unsigned Ln = 54 | Context->getSourceManager().getSpellingLineNumber(ExprRange.getBegin()); 55 | llvm::raw_string_ostream SS(ES); 56 | SS << Ln; 57 | } 58 | 59 | void Checker::getExprString(const Expr *E, std::string &ES) 60 | { 61 | SourceRange ExprRange = E->getSourceRange(); 62 | int RangeSize = TheRewriter.getRangeSize(ExprRange); 63 | CheckerAssert((RangeSize != -1) && "Invalid Range Size!"); 64 | 65 | SourceLocation StartLoc = ExprRange.getBegin(); 66 | const char *StartBuf = 67 | Context->getSourceManager().getCharacterData(StartLoc); 68 | 69 | ES.assign(StartBuf, RangeSize); 70 | 71 | const BinaryOperator *BinOp = dyn_cast(E); 72 | 73 | // Keep the semantics of Comma operator 74 | if (BinOp && (BinOp->getOpcode() == BO_Comma)) 75 | ES = "(" + ES + ")"; 76 | } 77 | 78 | Checker::~Checker() 79 | { 80 | // Nothing to do 81 | } 82 | 83 | -------------------------------------------------------------------------------- /volatile_checker/Makefile: -------------------------------------------------------------------------------- 1 | ##===----------------------------------------------------------------------=== 2 | ## 3 | ## Copyright (c) 2012 The University of Utah 4 | ## All rights reserved. 5 | ## 6 | ## This file is distributed under the University of Illinois Open Source 7 | ## License. See LICENSE.TXT for details. 8 | ## 9 | ##===----------------------------------------------------------------------=== 10 | 11 | llvm_dir = ${LLVM_PATH} 12 | 13 | ENABLE_CHECKER_ASSERT = -DENABLE_CHECKER_ASSERT 14 | ifeq (${DISABLE_CHECKER_ASSERT}, 1) 15 | ENABLE_CHECKER_ASSERT = -DDISABLE_CHECKER_ASSERT 16 | endif 17 | 18 | CXX = g++ 19 | CXXFLAGS = -O0 -Wall -fno-strict-aliasing -g 20 | 21 | LLVM_CXXFLAGS = `${llvm_dir}/bin/llvm-config --cxxflags` 22 | LLVM_LDFLAGS = `${llvm_dir}/bin/llvm-config --ldflags` 23 | #LLVM_LIBS = `${llvm_dir}/bin/llvm-config --libs | tr " " "\n" | grep -v 'gtest\|LLVMIntelJITEvents\|LLVMOProfileJIT'` 24 | LLVM_LIBS = `${llvm_dir}/bin/llvm-config --libs` 25 | 26 | INCLUDES = ${LLVM_CXXFLAGS} -I${llvm_dir}/include/clang 27 | LDFLAGS = ${LLVM_LDFLAGS} 28 | LIBS = -lclangFrontendTool -lclangFrontend -lclangDriver -lclangSerialization \ 29 | -lclangCodeGen -lclangParse -lclangSema -lclangAnalysis \ 30 | -lclangEdit -lclangAST -lclangLex -lclangBasic -lclangRewriteCore \ 31 | ${LLVM_LIBS} -ldl 32 | 33 | CHECKER_HEADERS = AccessOnceChecker.h \ 34 | VolatileReorderChecker.h \ 35 | VolatileAddressChecker.h 36 | 37 | CHECKER_SOURCES = AccessOnceChecker.cpp \ 38 | VolatileReorderChecker.cpp \ 39 | VolatileAddressChecker.cpp 40 | 41 | CHECKER_OBJS = AccessOnceChecker.o \ 42 | VolatileReorderChecker.o \ 43 | VolatileAddressChecker.o 44 | 45 | OBJS = VolatileChecker.o \ 46 | CheckerManager.o \ 47 | Checker.o \ 48 | ${CHECKER_OBJS} 49 | 50 | CHECKER_DEPS = Checker.cpp Checker.h 51 | 52 | .SUFFIXES : .o .cpp 53 | .cpp.o : 54 | ${CXX} -g ${ENABLE_CHECKER_ASSERT} ${INCLUDES} ${CXXFLAGS} -c $< 55 | 56 | volatile_checker: ${OBJS} 57 | ${CXX} -o volatile_checker ${OBJS} ${LDFLAGS} ${LIBS} 58 | 59 | VolatileChecker.o: VolatileChecker.cpp 60 | 61 | CheckerManager.o: CheckerManager.cpp CheckerManager.h ${CHECKER_HEADERS} ${CHECKER_SOURCES} 62 | 63 | Checker.o: Checker.cpp Checker.h 64 | 65 | AccessOnceChecker.o: AccessOnceChecker.cpp AccessOnceChecker.h ${CHECKER_DEPS} 66 | 67 | VolatileReorderChecker.o: VolatileReorderChecker.cpp VolatileReorderChecker.h ${CHECKER_DEPS} 68 | 69 | VolatileAddressChecker.o: VolatileAddressChecker.cpp VolatileAddressChecker.h ${CHECKER_DEPS} 70 | 71 | clean: 72 | rm -rf *.o 73 | 74 | distclean: 75 | rm -rf *.o volatile_checker 76 | 77 | -------------------------------------------------------------------------------- /scripts/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## 3 | ## bootstrap.sh --- Bootstrap an Emulab node for volatile testing. 4 | ## 5 | ## This script is designed to be run as a node start-up command. It gets the 6 | ## `voltest' git repository onto the node; it may do more in the future. 7 | ## 8 | ## The NS files for volatile testing are written to expect that this file is 9 | ## copied to Emulab and renamed as described in this repo's top-level README. 10 | ## 11 | 12 | ############################################################################### 13 | 14 | if [ $# -ne 1 ]; then 15 | echo "usage: $0 " 16 | exit 1 17 | fi 18 | 19 | work_home="$1" 20 | 21 | if test -e "$work_home"; then 22 | echo "$0: \"$work_home\" already exists" 23 | exit 1 24 | fi 25 | 26 | ############################################################################### 27 | 28 | ## Validate the environment. 29 | 30 | if test -z "$PID"; then 31 | echo "$0: environment variable \$PID is not set" 32 | exit 1 33 | fi 34 | 35 | ############################################################################### 36 | 37 | # Abort this script when any command fails. 38 | set -e 39 | # Abort this script when any unbound variable is used. 40 | set -u 41 | 42 | # If you want a bunch of noise, set "quiet=". 43 | quiet=-q 44 | 45 | work_src_home="$work_home/src" 46 | work_run_home="$work_home/run" 47 | 48 | ##### 49 | 50 | VOLTEST_DIR=voltest 51 | 52 | # Where to download voltest from, via Git. 53 | VOLTEST_GIT=https://github.com/csmith-project/voltest.git 54 | # 55 | ## The following is unlikely to work, since a node startcmd probably does not 56 | ## have access to any SSH private key useful for authenticating to GitHub. 57 | # 58 | # VOLTEST_GIT=git@github.com:csmith-project/voltest.git 59 | 60 | VOLTEST_HOME="$work_src_home/$VOLTEST_DIR" 61 | 62 | # What voltest branch, tag, or commit to use? 63 | VOLTEST_REV=master 64 | 65 | ############################################################################### 66 | 67 | ## SET UP WORK DIRECTORIES 68 | 69 | time=`date +%H:%M:%S` 70 | echo "*** [$time]" "Setting up work directories..." 71 | 72 | umask 002 73 | 74 | sudo mkdir -p "$work_home" 75 | sudo chown "$USER:$PID" "$work_home" 76 | chmod ug+rwx "$work_home" 77 | 78 | mkdir "$work_src_home" 79 | 80 | mkdir "$work_run_home" 81 | 82 | ############################################################################### 83 | 84 | ## SET UP VOLTEST 85 | 86 | # Get voltest. 87 | # 88 | time=`date +%H:%M:%S` 89 | echo "*** [$time]" "Acquiring voltest sources (@ $VOLTEST_REV)..." 90 | # 91 | git clone $quiet "$VOLTEST_GIT" --no-checkout "$VOLTEST_HOME" 92 | cd "$VOLTEST_HOME" 93 | git checkout $quiet --detach "$VOLTEST_REV" 94 | 95 | ############################################################################### 96 | 97 | time=`date +%H:%M:%S` 98 | echo "*** [$time]" "Bootstrap complete." 99 | 100 | ############################################################################### 101 | 102 | ## End of file. 103 | -------------------------------------------------------------------------------- /volatile_pintrace/do_all.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | use warnings; 5 | 6 | #my $GCC = "/scratch/chenyang/compilers/compiler-install/gcc-481/bin/gcc"; 7 | #my $GCC = "/scratch/chenyang/compilers/compiler-install/llvm-r191259-install/bin/clang"; 8 | #my $GCC = "/scratch/chenyang/compilers/compiler-install/gcc-r202631-install/bin/gcc"; 9 | my $GCC = "/scratch/chenyang/compilers/compiler-install/compcert-2.0/bin/ccomp"; 10 | #my $OPT = "-O3 -Werror=uninitialized -fno-zero-initialized-in-bss -g -gdwarf-2"; 11 | #my $OPT = "-O2"; 12 | my $SCRATCH = "/scratch/chenyang"; 13 | my $CSMITH_HOME = "$SCRATCH/csmith"; 14 | my $PIN_HOME = "$SCRATCH/programs/pin-2.12-55942-gcc.4.4.7-linux"; 15 | my $CHECKER = "$SCRATCH/voltest/volatile_checker/volatile_checker"; 16 | my $GEN_VOLATILE_ADDR = "$SCRATCH/voltest/volatile_pintrace/gen_volatile_addr.pl"; 17 | #my $TARGET = "obj-intel64"; 18 | my $TARGET = "obj-ia32"; 19 | my $PIN_BIN = "$PIN_HOME/pin.sh -injection child -t $PIN_HOME/source/tools/ManualExamples/$TARGET/pinatrace.so"; 20 | #my $PIN_RANDOM_READ = "-random_read"; 21 | my $PIN_RANDOM_READ = ""; 22 | 23 | sub runit ($) { 24 | my ($cmd) = @_; 25 | print "runit: $cmd\n"; 26 | if ((system "$cmd") != 0) { 27 | return -1; 28 | } 29 | my $exit_value = $? >> 8; 30 | return $exit_value; 31 | } 32 | 33 | sub abort_if_fail($) { 34 | my ($cmd) = @_; 35 | die "Fatal error!" if (runit($cmd)); 36 | } 37 | 38 | die "Usage: do_all.pl " unless (@ARGV == 3); 39 | 40 | my $mode = $ARGV[0]; 41 | my $cfile = $ARGV[1]; 42 | my $OPT = "-$ARGV[2]"; 43 | my $CHECKER_OPT = ""; 44 | my $ARCH_OPT = ""; 45 | if ($TARGET =~ m/ia32/) { 46 | $OPT .= " -m32"; 47 | $CHECKER_OPT = "--m32"; 48 | $ARCH_OPT = "-m32"; 49 | } 50 | 51 | if ($GCC =~ m/compcert/) { 52 | $OPT = "-fall"; 53 | $ARCH_OPT = ""; 54 | } 55 | 56 | # summary, checksum, verbose 57 | my $PIN_OUTPUT_MODE = "-output_mode $mode"; 58 | my $base = $cfile; 59 | $base =~ s/.c$//; 60 | my $preprocessed_cfile = "$base.pre.c"; 61 | my $gcc_compile_output = "$base.gcc.compile.out"; 62 | my $clang_addr_file = "$base.clang.addr"; 63 | my $clang_all_addr_file = "$base.clang.all.addr"; 64 | my $addr_file = "$base.addr"; 65 | my $all_addr_file = "$base.all.addr"; 66 | my $exe_file = "$base.out"; 67 | my $pin_out = "$base.pin.out"; 68 | 69 | abort_if_fail("$GCC -I$CSMITH_HOME/runtime $ARCH_OPT -E $cfile > $preprocessed_cfile"); 70 | abort_if_fail("$CHECKER $CHECKER_OPT --checker=volatile-address --all-vars-output=$clang_all_addr_file > $clang_addr_file $preprocessed_cfile 2>&1"); 71 | abort_if_fail("$GCC $OPT $preprocessed_cfile -o $exe_file > $gcc_compile_output 2>&1"); 72 | abort_if_fail("$GEN_VOLATILE_ADDR --vars-file=$clang_addr_file --all-vars-file=$clang_all_addr_file --all-var-addrs-output=$all_addr_file $exe_file > $addr_file 2>&1"); 73 | if ($mode eq "checksum") { 74 | abort_if_fail("$PIN_BIN -vol_input $addr_file $PIN_OUTPUT_MODE $PIN_RANDOM_READ -- ./$exe_file 2>&1"); 75 | } 76 | else { 77 | abort_if_fail("$PIN_BIN -vol_input $addr_file $PIN_OUTPUT_MODE $PIN_RANDOM_READ -- ./$exe_file > $pin_out 2>&1"); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /volatile_checker/CheckerManager.h: -------------------------------------------------------------------------------- 1 | #ifndef CHECKER_MANAGER_H 2 | #define CHECKER_MANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "llvm/Support/raw_ostream.h" 9 | #include "llvm/ADT/SmallVector.h" 10 | 11 | class Checker; 12 | namespace clang { 13 | class CompilerInstance; 14 | class LangOptions; 15 | class PreprocessingRecord; 16 | } 17 | 18 | class CheckerManager { 19 | 20 | public: 21 | 22 | static CheckerManager *GetInstance(); 23 | 24 | static void Finalize(); 25 | 26 | static void registerChecker(const char *CheckerName, 27 | Checker *CheckerImpl); 28 | 29 | static bool isCXXLangOpt(); 30 | 31 | static bool isCLangOpt(); 32 | 33 | int doChecking(std::string &ErrorMsg); 34 | 35 | bool verify(std::string &ErrorMsg); 36 | 37 | int setChecker(const std::string &Checker) { 38 | if (CheckersMap.find(Checker.c_str()) == CheckersMap.end()) 39 | return -1; 40 | CurrentCheckerImpl = CheckersMap[Checker.c_str()]; 41 | return 0; 42 | } 43 | 44 | void setSrcFileName(const std::string &FileName) { 45 | assert(SrcFileName.empty() && "Could only process one file each time"); 46 | SrcFileName = FileName; 47 | } 48 | 49 | std::string getSrcFileName() { 50 | return SrcFileName; 51 | } 52 | 53 | void set32BitTarget() { 54 | Force32BitTarget = true; 55 | } 56 | 57 | bool handleCheckerCmdOpt(const std::string &Arg); 58 | 59 | void printCheckerOptions(); 60 | 61 | bool initializeCompilerInstance(llvm::SmallVector &Args, 62 | const std::string &Path, 63 | std::string &ErrorMsg); 64 | 65 | void printCheckers(); 66 | 67 | void printCheckerNames(); 68 | 69 | private: 70 | 71 | CheckerManager(); 72 | 73 | ~CheckerManager(); 74 | 75 | bool hasPPDirective(clang::PreprocessingRecord &PPCallbacks, 76 | std::string &ErrorMsg); 77 | 78 | static CheckerManager *Instance; 79 | 80 | static std::map *CheckersMapPtr; 81 | 82 | std::map CheckersMap; 83 | 84 | Checker *CurrentCheckerImpl; 85 | 86 | std::string SrcFileName; 87 | 88 | clang::CompilerInstance *ClangInstance; 89 | 90 | bool Force32BitTarget; 91 | 92 | // Unimplemented 93 | CheckerManager(const CheckerManager &); 94 | 95 | void operator=(const CheckerManager&); 96 | 97 | }; 98 | 99 | template 100 | class RegisterChecker { 101 | 102 | public: 103 | RegisterChecker(const char *CheckerName, const char *Desc) { 104 | Checker *CheckerImpl = new CheckerClass(CheckerName, Desc); 105 | assert(CheckerImpl && "Fail to create CheckerClass"); 106 | 107 | CheckerManager::registerChecker(CheckerName, CheckerImpl); 108 | } 109 | 110 | private: 111 | // Unimplemented 112 | RegisterChecker(const RegisterChecker &); 113 | 114 | void operator=(const RegisterChecker &); 115 | 116 | }; 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /volatile_checker/README.txt: -------------------------------------------------------------------------------- 1 | 2 | * volatile_checker is a tool that checks certain properties of volatile accesses. 3 | 4 | * how to build the tool: 5 | LLVM_PATH=/where/llvm-3.2/is/installed make 6 | 7 | * Currently, it supports three individual checkers: which can be invoked by 8 | 9 | - access-once: given some variables, this checker checks if these variables are only accessed 10 | through ACCESS_ONCE() macro. The checker exits with 0 upon success. 11 | 12 | which can be invoked using the command below: 13 | volatile_checker --checker=access-once --access-once-vars=x,y,z 14 | where x,y,z are vars to be checked 15 | 16 | - volatile-reorder: it checks that if there is at most one volatile access between two sequence points, 17 | and exits with 0 upon success. 18 | 19 | which can be invoked using the command below: 20 | volatile_checker --checker=volatile-reorder 21 | 22 | for example, if we apply the checker to foo.c, shown as below: 23 | /* foo.c */ 24 | volatile int g1; 25 | volatile int g2; 26 | int foo(int p) 27 | { 28 | return g1; 29 | } 30 | 31 | void bar(void) 32 | { 33 | foo(g2 == foo(foo(1))); 34 | } 35 | 36 | the checker will generate output like this: 37 | 38 | Functions that have volatile accesses: 39 | foo : volatile access to g1 at line 5 40 | bar : volatile access to g2 at line 10 41 | 42 | Error: Offensive Expr is at line 10: foo(g2 == foo(foo(1))) 43 | multiple volatile accesses: 44 | g2 45 | foo(1) 46 | 47 | also, `echo $?' returns 255. 48 | Note that in the above output, if a function has multiple volatile accesses, 49 | only one of these accesses is shown below "Function that have volatile accesses" 50 | 51 | The detailed output is for manual analysis, and checking the exit value should be sufficient 52 | for writing testing oracle such as test1.sh. 53 | 54 | - volatile-address: generates size/offset of each volatile variable. 55 | invoked using the command below: 56 | volatile_checker --checker=volatile-address [--address-output=filename] [--handle-access-once-vars=[all|none|only]] foo.c 57 | 58 | where --address-output and --handle-access-once-vars are optional: 59 | --address-output specifies where to dump the result. (default is stdout) 60 | --handle-access-once-vars=[all|none|only]: specifies the way to handle variables accessed through ACCESS_ONCE macro. 61 | [all]: the checker will output sizes/offsets of volatile variables and variables accessed through ACCESS_ONCE macro; (this is the default behavior) 62 | [none]: the checker will *not* output sizes/offsets of variables accessed through ACCESS_ONCE; 63 | [only]: the checker will output sizes/offset of *only* variables accessed through ACCESS_ONCE 64 | 65 | * Csmith command line option to generate programs which strictly conform with 66 | the one-access-between-two-sequence-points rule: 67 | 68 | csmith --strict-volatile-rule 69 | 70 | * Csmith command line option to generate programs with ACCESS_ONCE macros 71 | csmith --enable-access-once 72 | 73 | -------------------------------------------------------------------------------- /volatile_pintrace/sample_test1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PIN_CMD="/scratch/chenyang/programs/pin-2.12-55942-gcc.4.4.7-linux/pin.sh -injection child -t /scratch/chenyang/programs/pin-2.12-55942-gcc.4.4.7-linux/source/tools/ManualExamples/obj-intel64/pinatrace.so -output_mode checksum" 4 | 5 | rm -f out*.txt 6 | 7 | if 8 | clang -pedantic -Wall -O0 -c small.c >out.txt 2>&1 &&\ 9 | ! grep 'conversions than data arguments' out.txt &&\ 10 | ! grep 'incompatible redeclaration' out.txt &&\ 11 | ! grep 'ordered comparison between pointer' out.txt &&\ 12 | ! grep 'eliding middle term' out.txt &&\ 13 | ! grep 'end of non-void function' out.txt &&\ 14 | ! grep 'invalid in C99' out.txt &&\ 15 | ! grep 'specifies type' out.txt &&\ 16 | ! grep 'should return a value' out.txt &&\ 17 | ! grep 'uninitialized' out.txt &&\ 18 | ! grep 'incompatible pointer to' out.txt &&\ 19 | ! grep 'incompatible integer to' out.txt &&\ 20 | ! grep 'type specifier missing' out.txt &&\ 21 | gcc -Wall -Wextra -O2 small.c -o smallz >outa.txt 2>&1 &&\ 22 | ! grep uninitialized outa.txt &&\ 23 | ! grep 'without a cast' outa.txt &&\ 24 | ! grep 'control reaches end' outa.txt &&\ 25 | ! grep 'null argument' outa.txt &&\ 26 | ! grep 'return type defaults' outa.txt &&\ 27 | ! grep 'useless type name in empty declaration' outa.txt &&\ 28 | ! grep 'no semicolon at end' outa.txt &&\ 29 | ! grep 'type defaults to' outa.txt &&\ 30 | ! grep 'format' outa.txt &&\ 31 | ! grep 'incompatible pointer' outa.txt &&\ 32 | ! grep 'ordered comparison of pointer with integer' outa.txt &&\ 33 | ! grep 'declaration does not declare anything' outa.txt &&\ 34 | ! grep 'expects type' outa.txt &&\ 35 | ! grep 'pointer from integer' outa.txt &&\ 36 | ! grep 'incompatible implicit' outa.txt &&\ 37 | ! grep 'excess elements in struct initializer' outa.txt &&\ 38 | ! grep 'comparison between pointer and integer' outa.txt &&\ 39 | /scratch/chenyang/embedded_code_repo/yang/volatile_checker/volatile_checker --checker=volatile-address small.c > checker.out.txt 2>&1 &&\ 40 | clang -O0 -w small.c -o small1 > cc_out1.txt 2>&1 &&\ 41 | /scratch/chenyang/embedded_code_repo/yang/volatile_pintrace/gen_volatile_addr.pl --vars-file=checker.out.txt small1 > vol_addr_out1.txt 2>&1 &&\ 42 | RunSafely.sh 3 1 /dev/null out1.txt ${PIN_CMD} -vol_input vol_addr_out1.txt -- ./small1 >/dev/null 2>&1 &&\ 43 | clang -O1 small.c -o small2 > cc_out2.txt 2>&1 &&\ 44 | /scratch/chenyang/embedded_code_repo/yang/volatile_pintrace/gen_volatile_addr.pl --vars-file=checker.out.txt small2 > vol_addr_out2.txt 2>&1 &&\ 45 | RunSafely.sh 3 1 /dev/null out2.txt ${PIN_CMD} -vol_input vol_addr_out2.txt -- ./small2 >/dev/null 2>&1 &&\ 46 | ! diff -I "Pin child" out1.txt out2.txt &&\ 47 | cp small.c small-framac.c &&\ 48 | perl -pi.bak -e 's/int main \(int argc, char\* argv\[\]\)/int argc; char **argv; int main (void)/' small-framac.c &&\ 49 | RunSafely.sh 20 1 /dev/null out_framac.txt frama-c -cpp-command \"gcc -C -Dvolatile= -E -I.\" -val-signed-overflow-alarms -val -stop-at-first-alarm -no-val-show-progress -machdep x86_64 -obviously-terminates -precise-unions small-framac.c &&\ 50 | ! egrep -i '(user error|assert)' out_framac.txt >/dev/null 2>&1 51 | then 52 | exit 0 53 | else 54 | exit 1 55 | fi 56 | -------------------------------------------------------------------------------- /volatile_checker/VolatileReorderChecker.h: -------------------------------------------------------------------------------- 1 | #ifndef VOLATILE_REORDER_CHECKER_H 2 | #define VOLATILE_REORDER_CHECKER_H 3 | 4 | #include 5 | #include "llvm/ADT/StringRef.h" 6 | #include "llvm/ADT/SmallPtrSet.h" 7 | #include "llvm/ADT/SmallVector.h" 8 | #include "llvm/ADT/DenseMap.h" 9 | #include "Checker.h" 10 | 11 | namespace clang { 12 | class ASTContext; 13 | class DeclGroupRef; 14 | class FunctionDecl; 15 | class QualType; 16 | class RecordDecl; 17 | class CallGraph; 18 | class CallGraphNode; 19 | class Stmt; 20 | } 21 | 22 | class VolatileAccessCollector; 23 | class VolatileAccessVisitor; 24 | class VolatileAccessStmtVisitor; 25 | class ExpressionVolatileAccessVisitor; 26 | 27 | class VolatileReorderChecker : public Checker { 28 | friend class VolatileAccessCollector; 29 | friend class VolatileAccessVisitor; 30 | friend class VolatileAccessStmtVisitor; 31 | friend class ExpressionVolatileAccessVisitor; 32 | 33 | public: 34 | 35 | VolatileReorderChecker(const char *CheckerName, const char *Desc) 36 | : Checker(CheckerName, Desc), 37 | OffensiveExpr(NULL), 38 | MultipleVolAccesses(false) 39 | { } 40 | 41 | ~VolatileReorderChecker(); 42 | 43 | private: 44 | 45 | typedef llvm::SmallPtrSet FunctionSet; 46 | 47 | typedef llvm::SmallPtrSet RecordDeclSet; 48 | 49 | typedef llvm::DenseMap FunctionVolatileMap; 50 | 51 | typedef llvm::SmallVector ExprVector; 52 | 53 | typedef llvm::DenseMap ExprMap; 54 | 55 | virtual void Initialize(clang::ASTContext &context); 56 | 57 | virtual void HandleTranslationUnit(clang::ASTContext &Ctx); 58 | 59 | virtual bool HandleTopLevelDecl(clang::DeclGroupRef D); 60 | 61 | void printAllFuncsWithVols(); 62 | 63 | bool handleOneStmt(clang::Stmt *S); 64 | 65 | bool handleOneExpr(clang::Expr *E); 66 | 67 | bool handleOneQualType(const clang::FunctionDecl *CurrFD, 68 | const clang::Expr *E, 69 | const clang::QualType &QT); 70 | 71 | bool hasVolatileQual(const clang::QualType &QT); 72 | 73 | void updateFuncsWithVols(const clang::CallGraph &CG); 74 | 75 | void addOneVolExprStr(const clang::FunctionDecl *CurrFD, 76 | const clang::Expr *E); 77 | 78 | bool visitCallGraphNode(const clang::CallGraphNode *Node); 79 | 80 | FunctionVolatileMap FuncVol; 81 | 82 | ExprVector VolAccesses; 83 | 84 | FunctionSet FuncsWithVols; 85 | 86 | // record decls that have volatile fields (including sub-struct-field 87 | // with volatiles, recursively) 88 | RecordDeclSet RecordsWithVols; 89 | 90 | RecordDeclSet VisitedRecords; 91 | 92 | ExprMap VisitedCallExprs; 93 | 94 | ExprMap VisitedBinaryExprs; 95 | 96 | const clang::Expr *OffensiveExpr; 97 | 98 | bool MultipleVolAccesses; 99 | 100 | // Unimplemented 101 | VolatileReorderChecker(); 102 | 103 | VolatileReorderChecker(const VolatileReorderChecker &); 104 | 105 | void operator=(const VolatileReorderChecker &); 106 | }; 107 | 108 | #endif // VOLATILE_REORDER_CHECKER_H 109 | 110 | -------------------------------------------------------------------------------- /scripts/vars.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## 3 | 4 | ############################################################################### 5 | 6 | PROJECT=randtest 7 | PROJECT_HOME="/proj/$PROJECT" 8 | 9 | # Where do we find the package that goes along with this script? 10 | # VOLTEST_HOME="$PROJECT_HOME/voltest" 11 | 12 | ## 13 | 14 | WORK_DIR="$PROJECT" 15 | WORK_HOME="/disk2/$WORK_DIR" 16 | WORK_RUN_HOME="$WORK_HOME/run" 17 | WORK_SRC_HOME="$WORK_HOME/src" 18 | 19 | ############################################################################### 20 | 21 | ## C-REDUCE 22 | 23 | CREDUCE_DIR=creduce 24 | 25 | # Where to download C-Reduce from, via Git. 26 | CREDUCE_GIT=git@github.com:csmith-project/creduce.git 27 | 28 | CREDUCE_HOME="$WORK_SRC_HOME/$CREDUCE_DIR" 29 | 30 | # What C-Reduce branch, tag, or commit to use? 31 | CREDUCE_REV=master 32 | 33 | ############################################################################### 34 | 35 | ## CSMITH 36 | 37 | CSMITH_DIR=csmith 38 | 39 | # Where to download Csmith from, via Git. 40 | CSMITH_GIT=git@github.com:csmith-project/csmith.git 41 | 42 | CSMITH_HOME="$WORK_SRC_HOME/$CSMITH_DIR" 43 | 44 | # What Csmith branch, tag, or commit to use? 45 | CSMITH_REV=master 46 | 47 | ############################################################################### 48 | 49 | ## LLVM AND ITS PARTS 50 | 51 | LLVM_DIR=llvm-3.3.src 52 | LLVM_TGZ=llvm-3.3.src.tar.gz 53 | LLVM_URL="http://llvm.org/releases/3.3/$LLVM_TGZ" 54 | # 55 | LLVM_CLANG_DIR=cfe-3.3.src 56 | LLVM_CLANG_TGZ=cfe-3.3.src.tar.gz 57 | LLVM_CLANG_URL="http://llvm.org/releases/3.3/$LLVM_CLANG_TGZ" 58 | # 59 | LLVM_COMPILER_RT_DIR=compiler-rt-3.3.src 60 | LLVM_COMPILER_RT_TGZ=compiler-rt-3.3.src.tar.gz 61 | LLVM_COMPILER_RT_URL="http://llvm.org/releases/3.3/$LLVM_COMPILER_RT_TGZ" 62 | 63 | # Somehwat confusing. 64 | # LLVM_SRC_HOME is the source tree; LLVM_OBJ_HOME is the build tree; 65 | # LLVM_HOME is the install tree. 66 | # This is not entirely naming-consistent with $WORK_SRC_HOME, say, but it 67 | # mean that $LLVM_HOME is naming-consistent with CSMITH_HOME and so on. 68 | # 69 | LLVM_SRC_HOME="$WORK_SRC_HOME/$LLVM_DIR" 70 | LLVM_OBJ_HOME="$WORK_SRC_HOME/llvm-build" 71 | LLVM_HOME="$WORK_SRC_HOME/llvm-install" 72 | 73 | ############################################################################### 74 | 75 | ## PIN 76 | 77 | PIN_DIR=pin-2.12-55942-gcc.4.4.7-linux 78 | 79 | PIN_HOME="$WORK_SRC_HOME/$PIN_DIR" 80 | 81 | PIN_TGZ=pin-2.12-55942-gcc.4.4.7-linux.tar.gz 82 | PIN_URL="http://software.intel.com/sites/landingpage/pintool/downloads/$PIN_TGZ" 83 | 84 | ############################################################################### 85 | 86 | ## VOLTEST 87 | 88 | VOLTEST_DIR=voltest 89 | 90 | # Where to download voltest from, via Git. 91 | VOLTEST_GIT=git@github.com:csmith-project/voltest.git 92 | 93 | VOLTEST_HOME="$WORK_SRC_HOME/$VOLTEST_DIR" 94 | 95 | # What voltest branch, tag, or commit to use? 96 | VOLTEST_REV=master 97 | 98 | ############################################################################### 99 | 100 | ## VOLATILE_CHECKER, now a part of voltest 101 | 102 | VOLATILE_CHECKER_DIR=volatile_checker 103 | 104 | VOLATILE_CHECKER_HOME="$VOLTEST_HOME/$VOLATILE_CHECKER_DIR" 105 | 106 | ############################################################################### 107 | 108 | ## VOLATILE_PINTRACE, now a part of voltest 109 | 110 | VOLATILE_PINTRACE_DIR=volatile_pintrace 111 | 112 | VOLATILE_PINTRACE_HOME="$VOLTEST_HOME/$VOLATILE_PINTRACE_DIR" 113 | 114 | ############################################################################### 115 | 116 | ## End of file. 117 | -------------------------------------------------------------------------------- /creduce/prep_reduction.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## 3 | ## Copyright (c) 2013 The University of Utah 4 | ## All rights reserved. 5 | ## 6 | ## This is a predicate script for C-Reduce, for reducing programs that reveal 7 | ## "volatile defects" in C compilers. 8 | ## 9 | ## This script judges that the file named by its argument is interesting if: 10 | ## 11 | ## + it appears to be a valid, strictly conforming C program 12 | ## + the program compiles with both "gcc -O0" and "gcc -O2" 13 | ## + the output of the two compiled programs is the same 14 | ## + the "volatile access checksums" of the two compiled programs are 15 | ## different 16 | ## 17 | 18 | ############################################################################### 19 | 20 | ## Information about the test setup: the compilers under test and the 21 | ## environment for compiling and validating test programs. 22 | 23 | CCUT1="gcc-4.4 -O0" 24 | # CCUT2="gcc-4.4 -O2" 25 | 26 | CPPFLAGS="-DINLINE= -DCSMITH_MINIMAL -DWRAP_VOLATILES=0 -DNOT_PRINT_CHECKSUM -I/disk2/randtest/src/csmith/runtime" 27 | 28 | ############################################################################### 29 | 30 | ## Environment configuration. 31 | 32 | RM=rm 33 | 34 | ############################################################################### 35 | 36 | ## Options. 37 | 38 | # If `quiet' is true, this script is silent when the mutant is found to be 39 | # uninteresting --- i.e., uncompilable, sematically suspect, or without the 40 | # behavior we're looking for. 41 | quiet=1 42 | 43 | # If `neat' is true, this script deletes the temporary files it creates. 44 | neat=1 45 | 46 | # If `debug' is true, this script prints debugging output. 47 | debug=0 48 | 49 | ############################################################################### 50 | 51 | ## Parse and validate the command-line arguments. 52 | 53 | if [ $# -ne 1 ]; then 54 | echo "usage: $0 filename" 55 | exit 1 56 | fi 57 | 58 | filename="$1" 59 | 60 | if test ! -e "$filename"; then 61 | echo "$0: file \"$filename\" does not exist" 62 | exit 1 63 | fi 64 | if test ! -f "$filename"; then 65 | echo "$0: \"$filename\" is not a regular file" 66 | exit 1 67 | fi 68 | if test ! -r "$filename"; then 69 | echo "$0: file \"$filename\" is not readable" 70 | exit 1 71 | fi 72 | 73 | ############################################################################### 74 | 75 | ## Initialization. 76 | 77 | DEBUG_ECHO=echo 78 | if [ $debug -ne 0 ]; then 79 | DEBUG_ECHO=: 80 | fi 81 | 82 | QUIET_ECHO=echo 83 | if [ $quiet -ne 0 ]; then 84 | QUIET_ECHO=: 85 | fi 86 | 87 | NEAT_RM_OUTS="$RM -f *out*.exe *out*.txt" 88 | if [ $neat -eq 0 ]; then 89 | NEAT_RM_OUTS=: 90 | fi 91 | 92 | # ulimit -t 1 93 | # ulimit -v 2000000 94 | 95 | # Remove any lingering temporary files. 96 | $NEAT_RM_OUTS 97 | 98 | ############################################################################### 99 | 100 | ## Preprocess the input file using the compiler under test. 101 | 102 | filename_E="$filename-out.i" 103 | ccut1_out=ccut1-out.txt 104 | 105 | $CCUT1 -E \ 106 | $CPPFLAGS \ 107 | "$filename" \ 108 | -o "$filename_E" 109 | > "$ccut1_out" 2>&1 110 | if [ $? -ne 0 ]; then 111 | $QUIET_ECHO "$0: $CCUT1: could not preprocess \"$filename\"" 112 | $NEAT_RM_OUTS 113 | exit 1 114 | fi 115 | 116 | mv "$filename" "$filename.orig" 117 | mv "$filename_E" "$filename" 118 | 119 | ############################################################################### 120 | 121 | $QUIET_ECHO "$0: \"$filename\" successfully preprocessed" 122 | $NEAT_RM_OUTS 123 | 124 | exit 0 125 | 126 | ## End of file. 127 | -------------------------------------------------------------------------------- /volatile_checker/AccessOnceChecker.cpp: -------------------------------------------------------------------------------- 1 | #include "AccessOnceChecker.h" 2 | 3 | #include "clang/AST/RecursiveASTVisitor.h" 4 | #include "clang/AST/ASTContext.h" 5 | #include "clang/Lex/Lexer.h" 6 | 7 | #include "CheckerManager.h" 8 | 9 | using namespace clang; 10 | using namespace llvm; 11 | 12 | static const char *DescriptionMsg = 13 | "check the integrity of ACCESS_ONCE macro: \ 14 | check fails if any variable is accessed through both ACCESS_ONCE \ 15 | and regular way\n"; 16 | 17 | static RegisterChecker 18 | C("access-once", DescriptionMsg); 19 | 20 | class AccessOnceVisitor : public 21 | RecursiveASTVisitor { 22 | 23 | public: 24 | explicit AccessOnceVisitor(AccessOnceChecker *Instance) 25 | : ConsumerInstance(Instance) 26 | { } 27 | 28 | bool VisitDeclRefExpr(DeclRefExpr *DRE); 29 | 30 | private: 31 | AccessOnceChecker *ConsumerInstance; 32 | }; 33 | 34 | bool AccessOnceVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) 35 | { 36 | return ConsumerInstance->checkVarAccess(DRE); 37 | } 38 | 39 | void AccessOnceChecker::Initialize(ASTContext &context) 40 | { 41 | Checker::Initialize(context); 42 | } 43 | 44 | void AccessOnceChecker::HandleTranslationUnit(ASTContext &Ctx) 45 | { 46 | AccessOnceVisitor Visitor(this); 47 | Visitor.TraverseDecl(Ctx.getTranslationUnitDecl()); 48 | 49 | Ctx.getDiagnostics().setSuppressAllDiagnostics(false); 50 | 51 | if (Ctx.getDiagnostics().hasErrorOccurred() || 52 | Ctx.getDiagnostics().hasFatalErrorOccurred()) { 53 | CheckerAssert(0 && "Fatal error during checing!"); 54 | } 55 | } 56 | 57 | bool AccessOnceChecker::checkVarAccess(DeclRefExpr *DRE) 58 | { 59 | const VarDecl *VD = dyn_cast(DRE->getDecl()); 60 | if (!VD) 61 | return true; 62 | const std::string VarName = VD->getNameAsString(); 63 | if (!VarNames.count(VarName)) 64 | return true; 65 | 66 | // Var is accessed outside of a macro 67 | SourceLocation Loc = DRE->getLocation(); 68 | if (!Loc.isMacroID()) { 69 | CheckMsg = VarName + " is accessed outside ACCESS_ONCE macro"; 70 | Success = false; 71 | return false; 72 | } 73 | 74 | StringRef M = 75 | Lexer::getImmediateMacroName(Loc, 76 | Context->getSourceManager(), 77 | Context->getLangOpts()); 78 | 79 | // Var is accessed in another macro other than ACCESS_ONCE 80 | if (M != TheAccessOnceName) { 81 | CheckMsg = VarName + " is accessed in another macro other than ACCESS_ONCE"; 82 | Success = false; 83 | return false; 84 | } 85 | return true; 86 | } 87 | 88 | void AccessOnceChecker::printCmdOpts() 89 | { 90 | llvm::outs() << "option[s] supported in checker[" << Name << "]:\n"; 91 | llvm::outs() << " --access-once-vars=x,y,z where x,y,z are vars to be"; 92 | llvm::outs() << "checked\n"; 93 | } 94 | 95 | void AccessOnceChecker::setAccessOnceVars(const std::string &VarsStr) 96 | { 97 | splitString(VarsStr, ',', VarNames); 98 | } 99 | 100 | bool AccessOnceChecker::handleValueCmdOpt(const std::string &ArgStr, 101 | size_t SepPos) 102 | { 103 | if ((SepPos < 1) || (SepPos >= ArgStr.length())) 104 | return false; 105 | 106 | std::string ArgName, ArgValue; 107 | 108 | ArgName = ArgStr.substr(0, SepPos); 109 | ArgValue = ArgStr.substr(SepPos+1); 110 | 111 | if (!ArgName.compare("access-once-vars")) { 112 | setAccessOnceVars(ArgValue); 113 | return true; 114 | } 115 | else { 116 | return false; 117 | } 118 | } 119 | 120 | AccessOnceChecker::~AccessOnceChecker() 121 | { 122 | 123 | } 124 | 125 | -------------------------------------------------------------------------------- /volatile_checker/VolatileAddressChecker.h: -------------------------------------------------------------------------------- 1 | #ifndef VOLATILE_ADDRESS_CHECKER_H 2 | #define VOLATILE_ADDRESS_CHECKER_H 3 | 4 | #include 5 | #include 6 | #include "Checker.h" 7 | #include "llvm/ADT/SmallPtrSet.h" 8 | 9 | namespace clang { 10 | class ASTContext; 11 | class VarDecl; 12 | class DeclRefExpr; 13 | class Type; 14 | class DeclaratorDecl; 15 | class RecordDecl; 16 | class ArrayType; 17 | class QualType; 18 | } 19 | 20 | class VolatileAddressVisitor; 21 | class AccessOnceVarCollectionVisitor; 22 | 23 | class VolatileAddressChecker : public Checker { 24 | friend class VolatileAddressVisitor; 25 | friend class AccessOnceVarCollectionVisitor; 26 | 27 | typedef enum { 28 | ACC_VARS_ALL, /* including all access_once_vars and volatile vars */ 29 | ACC_VARS_NONE, /* exclude all access_once_vars */ 30 | ACC_VARS_ONLY, /* exclude all volatile vars */ 31 | } ACC_VAR_MODE; 32 | 33 | public: 34 | 35 | VolatileAddressChecker(const char *CheckerName, const char *Desc) 36 | : Checker(CheckerName, Desc), 37 | AccessOnceVarMode(ACC_VARS_ALL), 38 | OutFile(""), 39 | AllVarsOutFile(""), 40 | DumpAllVars(false), 41 | UnionLevelCount(0) 42 | { } 43 | 44 | ~VolatileAddressChecker(); 45 | 46 | private: 47 | 48 | typedef llvm::SmallPtrSet VarSet; 49 | 50 | virtual void Initialize(clang::ASTContext &context); 51 | 52 | virtual void HandleTranslationUnit(clang::ASTContext &Ctx); 53 | 54 | virtual void printCmdOpts(); 55 | 56 | virtual bool handleValueCmdOpt(const std::string &ValueStr, 57 | size_t SepPos); 58 | 59 | void handleOneVarDecl(const clang::VarDecl *VD); 60 | 61 | void handleOneDeclRefExpr(const clang::DeclRefExpr *DRE); 62 | 63 | void handleOneStructure(bool IsVol, 64 | const std::string &Prefix, 65 | uint64_t Offset, 66 | const clang::RecordDecl *RD); 67 | 68 | void handleOneUnion(bool IsVol, 69 | const std::string &Prefix, 70 | uint64_t Offset, 71 | const clang::RecordDecl *RD); 72 | 73 | void handleOneArray(bool IsVol, 74 | const std::string &Prefix, 75 | uint64_t Offset, 76 | const clang::ArrayType *AT); 77 | 78 | void handleOneDeclaratorDecl(bool IsVol, 79 | const std::string &Prefix, 80 | uint64_t Offset, 81 | const clang::DeclaratorDecl *DD); 82 | 83 | void addOneAddress(bool IsVol, 84 | bool IsBitField, 85 | const std::string &Name, 86 | uint64_t Offset, 87 | uint64_t Sz, 88 | const std::string &PtrStr); 89 | 90 | void addOneVolatileAddress(const std::string &Name, 91 | uint64_t Offset, 92 | uint64_t Sz, 93 | const std::string &PtrStr); 94 | 95 | void addOneNonVolatileAddress(const std::string &Name, 96 | uint64_t Offset, 97 | uint64_t Sz, 98 | const std::string &PtrStr); 99 | 100 | std::string getPointerStr(const clang::QualType &QT); 101 | 102 | bool setAccessOnceVarMode(const std::string &ModeStr); 103 | 104 | bool setOutput(const std::string &OutFile); 105 | 106 | bool setAllVarsOutput(const std::string &OutFile) { 107 | AllVarsOutFile = OutFile; 108 | DumpAllVars = true; 109 | return true; 110 | } 111 | 112 | void dumpAddresses(const std::vector &Addrs, 113 | llvm::raw_ostream &OS); 114 | 115 | void dumpAddrsToFile(const std::vector &Addrs, 116 | const std::string &FN); 117 | 118 | VarSet AccessOnceVars; 119 | 120 | VarSet VisitedVars; 121 | 122 | std::vector AllVolAddrs; 123 | 124 | std::vector AllNonVolAddrs; 125 | 126 | ACC_VAR_MODE AccessOnceVarMode; 127 | 128 | std::string OutFile; 129 | 130 | std::string AllVarsOutFile; 131 | 132 | bool DumpAllVars; 133 | 134 | int UnionLevelCount; 135 | 136 | // Unimplemented 137 | VolatileAddressChecker(); 138 | 139 | VolatileAddressChecker(const VolatileAddressChecker &); 140 | 141 | void operator=(const VolatileAddressChecker &); 142 | }; 143 | 144 | #endif // VOLATILE_ADDRESS_CHECKER_H 145 | 146 | -------------------------------------------------------------------------------- /volatile_checker/VolatileChecker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "llvm/Support/raw_ostream.h" 6 | #include "llvm/Support/Path.h" 7 | #include "CheckerManager.h" 8 | 9 | static CheckerManager *CheckerMgr; 10 | 11 | static void PrintHelpMessage() 12 | { 13 | llvm::outs() << "\n"; 14 | llvm::outs() << "Usage: \n"; 15 | llvm::outs() << " volatile_checker "; 16 | llvm::outs() << "--checker= "; 17 | llvm::outs() << "\n\n"; 18 | 19 | llvm::outs() << "volatile_checker options:\n"; 20 | 21 | llvm::outs() << " --help: "; 22 | llvm::outs() << "print this message\n"; 23 | 24 | llvm::outs() << " --checkers: "; 25 | llvm::outs() << "print the names of all available checkers\n"; 26 | 27 | llvm::outs() << " --verbose-checkers: "; 28 | llvm::outs() << "print verbose description messages for all checkers\n"; 29 | llvm::outs() << "\n"; 30 | 31 | CheckerMgr->printCheckerOptions(); 32 | llvm::outs() << "\n"; 33 | } 34 | 35 | static void DieOnBadCmdArg(const std::string &ArgStr) 36 | { 37 | llvm::errs() << "Error: Bad command line option `" << ArgStr << "`\n"; 38 | llvm::errs() << "\n"; 39 | PrintHelpMessage(); 40 | CheckerManager::Finalize(); 41 | exit(-1); 42 | } 43 | 44 | static void Die(const std::string &Message) 45 | { 46 | llvm::errs() << "Error: " << Message << "\n"; 47 | CheckerManager::Finalize(); 48 | exit(-1); 49 | } 50 | 51 | static bool HandleOneArgValue(const std::string &ArgValueStr, size_t SepPos) 52 | { 53 | if ((SepPos < 1) || (SepPos >= ArgValueStr.length())) { 54 | DieOnBadCmdArg("--" + ArgValueStr); 55 | } 56 | 57 | std::string ArgName, ArgValue; 58 | 59 | ArgName = ArgValueStr.substr(0, SepPos); 60 | ArgValue = ArgValueStr.substr(SepPos+1); 61 | 62 | if (!ArgName.compare("checker")) { 63 | if (CheckerMgr->setChecker(ArgValue)) 64 | Die("Invalid checker[" + ArgValue + "]"); 65 | return true; 66 | } 67 | else { 68 | return false; 69 | } 70 | } 71 | 72 | static bool HandleOneNonValueArg(const std::string &ArgStr) 73 | { 74 | if (!ArgStr.compare("help")) { 75 | PrintHelpMessage(); 76 | exit(0); 77 | } 78 | else if (!ArgStr.compare("checkers")) { 79 | CheckerMgr->printCheckerNames(); 80 | exit(0); 81 | } 82 | else if (!ArgStr.compare("verbose-checkers")) { 83 | CheckerMgr->printCheckers(); 84 | exit(0); 85 | } 86 | else if (!ArgStr.compare("m32")) { 87 | CheckerMgr->set32BitTarget(); 88 | return true; 89 | } 90 | else { 91 | return false; 92 | } 93 | } 94 | 95 | static bool HandleOneArg(const char *Arg) 96 | { 97 | std::string ArgStr(Arg); 98 | 99 | if (!ArgStr.compare(0, 2, "--")) { 100 | std::string SubArgStr = ArgStr.substr(2); 101 | if (!SubArgStr.length()) 102 | DieOnBadCmdArg(ArgStr); 103 | 104 | size_t found; 105 | found = SubArgStr.find('='); 106 | if (found != std::string::npos) 107 | return HandleOneArgValue(SubArgStr, found); 108 | else 109 | return HandleOneNonValueArg(SubArgStr); 110 | } 111 | else { 112 | CheckerMgr->setSrcFileName(ArgStr); 113 | return true; 114 | } 115 | } 116 | 117 | llvm::sys::Path GetExecutablePath(const char *Argv0) { 118 | void *MainAddr = (void*) (intptr_t) GetExecutablePath; 119 | return llvm::sys::Path::GetMainExecutable(Argv0, MainAddr); 120 | } 121 | 122 | int main(int argc, char **argv) 123 | { 124 | CheckerMgr = CheckerManager::GetInstance(); 125 | llvm::SmallVector UnresolvedArgs; 126 | 127 | for (int i = 1; i < argc; i++) { 128 | if (!HandleOneArg(argv[i])) 129 | UnresolvedArgs.push_back(argv[i]); 130 | } 131 | 132 | for (llvm::SmallVector::iterator I = UnresolvedArgs.begin(), 133 | E = UnresolvedArgs.end(); I != E; ++I) { 134 | if (!CheckerMgr->handleCheckerCmdOpt(*I)) 135 | DieOnBadCmdArg(*I); 136 | } 137 | 138 | std::string ErrorMsg; 139 | if (!CheckerMgr->verify(ErrorMsg)) 140 | Die(ErrorMsg); 141 | 142 | llvm::SmallVector Args; 143 | Args.push_back(argv[0]); 144 | Args.push_back(CheckerMgr->getSrcFileName().c_str()); 145 | Args.push_back("-fsyntax-only"); 146 | llvm::sys::Path Path = GetExecutablePath(argv[0]); 147 | if (!CheckerMgr->initializeCompilerInstance(Args, Path.str(), ErrorMsg)) 148 | Die(ErrorMsg); 149 | 150 | int RV = CheckerMgr->doChecking(ErrorMsg); 151 | if (RV) { 152 | llvm::errs() << "Error: " << ErrorMsg << "\n"; 153 | } 154 | else { 155 | llvm::outs() << "Succeeded\n"; 156 | } 157 | CheckerManager::Finalize(); 158 | return RV; 159 | } 160 | 161 | -------------------------------------------------------------------------------- /creduce/find-common-vars.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | ## 3 | ## Copyright (c) 2013 The University of Utah 4 | ## All rights reserved. 5 | ## 6 | ## This is a helper for a predicate script for C-Reduce, for reducing programs 7 | ## that reveal "volatile defects" in C compilers. 8 | ## 9 | ## This script's task is to filter a list of locations (variables) to include 10 | ## only those that are visible in two compiled versions of a test case. For 11 | ## this command line: 12 | ## 13 | ## find-common-vars.pl file1 file2 14 | ## 15 | ## where file1 contains location data for one compiled version of a test case, 16 | ## and file2 contains location data fro another compiled version of the same 17 | ## test case, this script outputs the locations in file1 that also appear in 18 | ## file2. 19 | ## 20 | ## Informally, this script intersects the variable sets in file1 and file2, and 21 | ## outputs a version of file1 where variables outside the intersection have 22 | ## been removed. 23 | ## 24 | ## Note that in general, the following two commands produce different output: 25 | ## 26 | ## find-common-vars.pl file1 file2 27 | ## find-common-vars.pl file2 file1 28 | ## 29 | ## Although the intersection of the variables is the same in each case, the 30 | ## output of the former contains the address of the variables found in file1, 31 | ## whereas the latter contains the addresses found in file2. 32 | ## 33 | ## TODO: This script could easily output both of the intersection files in one 34 | ## run, i.e., the outputs of both of the command lines shown above. This would 35 | ## be a small optimization to the reduction process. 36 | ## 37 | 38 | ############################################################################### 39 | 40 | use strict; 41 | use warnings; 42 | 43 | my @file1_table; 44 | my @file2_table; 45 | 46 | my %var_refcounts = (); 47 | 48 | ## Produce the key for an array that describes a location. 49 | ## 50 | sub var_key { 51 | # Join the name, size, and bitfield mask. Use ";" as the join character 52 | # because it is the field separator in our input files. 53 | my $key = join ";", $_[0], $_[2], $_[4]; 54 | return $key 55 | } 56 | 57 | ## Read the file that describes the global locations in a compiled program. 58 | ## Return a reference to an array that is the parsed representation of that 59 | ## data. 60 | ## 61 | ## Each element of the returned array is an array ref, representing an input 62 | ## line. An array that represents a line contains a record key followed by 63 | ## the fields parsed from the input file. 64 | ## 65 | sub read_vars_file($) { 66 | my ($filename) = @_; 67 | my @table = (); 68 | 69 | open FILE, "<$filename" or die "cannot open $filename"; 70 | while () { 71 | chomp; 72 | s/\s//g; 73 | my @record = split(/;/); 74 | die "$filename contains an invalid record" 75 | unless ((@record == 4) || (@record == 5)); 76 | # For internal representation, make our records uniform length. 77 | if (@record == 4) { 78 | push(@record, ""); 79 | } 80 | my $key = var_key(@record); 81 | unshift(@record, $key); 82 | push(@table, \@record); 83 | } 84 | close FILE; 85 | return @table; 86 | } 87 | 88 | ## Increment the reference count for every location described in the given 89 | ## array of locations. The argument to this function is an array of location 90 | ## data, representing the locations defined in some compiled program. 91 | ## 92 | sub collect_var_refcounts { 93 | foreach my $ref (@_) { 94 | my $key = $ref->[0]; 95 | my $count = $var_refcounts{$key}; 96 | if (defined($count)) { 97 | $var_refcounts{$key} = $count+1; 98 | } else { 99 | $var_refcounts{$key} = 1; 100 | } 101 | } 102 | } 103 | 104 | ## Output the data from a parsed location record. Basically, print everything 105 | ## but the location's key. 106 | ## 107 | sub print_record($) { 108 | my ($ref) = @_; 109 | if ($ref->[5] eq "") { 110 | print "$ref->[1]; $ref->[2]; $ref->[3]; $ref->[4]\n"; 111 | } else { 112 | print "$ref->[1]; $ref->[2]; $ref->[3]; $ref->[4]; $ref->[5]\n"; 113 | } 114 | } 115 | 116 | ############################################################################### 117 | 118 | if (@ARGV != 2) { 119 | print STDERR "usage: $0 \n"; 120 | exit 1; 121 | } 122 | 123 | @file1_table = read_vars_file(shift @ARGV); 124 | collect_var_refcounts(@file1_table); 125 | 126 | @file2_table = read_vars_file(shift @ARGV); 127 | collect_var_refcounts(@file2_table); 128 | 129 | ## When we run this script twice, like so: 130 | ## 131 | ## find-common-vars.pl file1 file2 132 | ## find-common-vars.pl file2 file1 133 | ## 134 | ## it is important that the common locations appear in the same order across 135 | ## the two invocations. The easiest way to ensure this is simply to sort the 136 | ## records by key. 137 | ## 138 | @file1_table = sort {$a->[0] cmp $b->[0]} @file1_table; 139 | 140 | ## Output the records for the common locations between file1 and file2. 141 | foreach my $ref (@file1_table) { 142 | my $key = $ref->[0]; 143 | my $count = $var_refcounts{$key}; 144 | if ($count == 2) { 145 | print_record($ref); 146 | } 147 | } 148 | 149 | exit 0; 150 | 151 | ############################################################################### 152 | 153 | ## End of file. 154 | -------------------------------------------------------------------------------- /volatile_pintrace/README.txt: -------------------------------------------------------------------------------- 1 | Volatile tests howto: 2 | 3 | - We use pintool to do volatile tests. 4 | 5 | Prepare pintool: 6 | 7 | * suppose the $PIN_HOME is where pintool is going to be installed 8 | * cd $PIN_HOME 9 | * download pintool from: 10 | wget http://software.intel.com/sites/landingpage/pintool/downloads/pin-2.12-55942-gcc.4.4.7-linux.tar.gz 11 | 12 | * cp pin.sh to $PIN_HOME/ 13 | (note: the new pin.sh only work on 64-bit system) 14 | 15 | * cp pinatrace.cpp to $PIN_HOME/source/tools/ManualExamples/ 16 | * cd $PIN_HOME/source/tools/ManualExamples 17 | * make 18 | (note: this will build intel64 obj. 19 | If you want to build ia32 obj, then do: 20 | TARGET=ia32 make 21 | ) 22 | 23 | * make sure to RunSafely is in the PATH env; 24 | 25 | To do volatile tests using volatile scripts, you only need to 26 | setup CSMITH_HOME, and either: 27 | 28 | * ./launchn.pl or 29 | 30 | * ./volatile_test.pl (use ./volatile_test.pl --help to check its usage) 31 | Note: if you want to disable volatile struct/union fields in random programs, 32 | pass --no-vol-struct-union-fields to this driver script 33 | 34 | - test case reduction using creduce 35 | make sure preprocess the random program first, then do reduction 36 | 37 | sample_test1.sh provides a sample test oracle. It shows: 38 | * how to invoke volatile_checker to generate volatile offsets/sizes; 39 | * how to invoke gen_volatile_addr.pl to generate actual volatile addresses; 40 | * how to invoke frama-c to avoid undefined behavior 41 | * also making sure exclude the line `Pin child' when diff out1.txt and out2.txt 42 | 43 | -------------------------------------------------------------------- 44 | Some details about pinatrace: 45 | 46 | How to invoke pinatrace hack standalone: 47 | 48 | $PIN_HOME/pin.sh -t $PIN_HOME/source/tools/ManualExamples/obj-intel64/pinatrace.so -vol_input vol_addr.txt [-output_mode checksum|verbose|summary] [-random_read] [-seed num] -- ./a.out 49 | 50 | on the latest Ubuntu 12.04.1, we have to use the following command: 51 | 52 | $PIN_HOME/pin -injection child -t $PIN_HOME/source/tools/ManualExamples/obj-intel64/pinatrace.so -vol_input vol_addr.txt [-output_mode checksum|verbose|summary] -- ./a.out 53 | 54 | (note: replace intel64 with ia32 if you are on a 32-bit machine) 55 | 56 | where: 57 | vol_addr.txt is generated by gen_volatile_addr.pl which contains volatile addresses. 58 | 59 | * -output_mode checksum [default] 60 | Compute a checksum over the numbers of reads/writes to volatile locations 61 | 62 | * -output_mode summary 63 | In the summary mode, only the number of a volatile access will be 64 | dumped. Volatile accesses are measured byte-wise, and reads/writes 65 | are aggregate counts over the entire run of a test case. For example: 66 | 67 | volatile int g; 68 | 69 | Then pintool will output something like: 70 | 71 | g: 0: 1 reads, 0 writes 72 | g: 1: 1 reads, 0 writes 73 | g: 2: 1 reads, 0 writes 74 | g: 3: 1 reads, 0 writes 75 | 76 | where the numbers on the second col are sequence number of g, 0 means that its the first byte of g, 77 | 1 means the second byte of g, and so on. 78 | 79 | * -output_mode verbose 80 | In the verbose mode, all values to be loaded and stored are also dumped. 81 | I didn't integrate the support to the verbose mode into volatile scripts. So the current 82 | volatile testing only work in the summary mode. 83 | 84 | * -random_read 85 | pass random values to volatile reads rather than original values 86 | To see how it work, you can try rand_val_test1.c: 87 | 88 | (1) gcc rand_val_test1.c 89 | (2) $PIN_HOME/pin.sh -injection child -t $PIN_HOME/source/tools/ManualExamples/obj-intel64/pinatrace.so -vol_input vol_addr.txt -output_mode checksum -random_read -- ./a.out 90 | 91 | * -seed num 92 | pintool will use the passed seed rather than a random one 93 | 94 | * -all_vars_input 95 | if this options is given, the pintool will read all memory values based on the 96 | given addr file, and compute value checksums. 97 | 98 | -------------------------------------------------------------------- 99 | gen_volatile_addr.pl: invokes `nm' to generate actual volatile addresses 100 | based on the output from `volatile_checker --checker=volatile-address' 101 | 102 | Usage: 103 | gen_volatile_addr.pl --vars-file= [--all-vars-file=] exec 104 | 105 | where: 106 | is generated by volatile_checker 107 | 108 | exec is the executable 109 | 110 | [--all-vars-file=] is optional and 115 | 116 | More options: gen_volatile_addr.pl --help 117 | 118 | output format: 119 | name; addr; sz; pointer_or_not; bitfield_pattern 120 | g1.f2; 0x402028; 1; non-pointer; 7f 121 | 122 | where: 123 | sz is in bytes; 124 | 125 | the last item bitfield_pattern exists only if this 126 | line represents some bitfields. The pintool runtime 127 | will only read the bit value whose corresponding bit 128 | is `1' in bitfield_pattern (in binary format) 129 | 130 | -------------------------------------------------------------------------------- /volatile_pintrace/RunSafely: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Program: RunSafely.sh 4 | # 5 | # Synopsis: This script simply runs another program. If the program works 6 | # correctly, this script has no effect, otherwise it will do things 7 | # like print a stack trace of a core dump. It always returns 8 | # "successful" so that tests will continue to be run. 9 | # 10 | # This script funnels stdout and stderr from the program into the 11 | # fourth argument specified, and outputs a .time file which 12 | # contains a timing of the program and the program's exit code. 13 | # 14 | # If the parameter is 0 then this script always returns 0, 15 | # regardless of the actual exit of the . 16 | # If the parameter is non-zero then this script returns 17 | # the exit code of the . If there is an error in getting 18 | # the 's exit code, this script returns 99. 19 | # 20 | # If optional parameters -r -l are 21 | # specified, it execute the program remotely using rsh. 22 | # 23 | # Syntax: 24 | # 25 | # RunSafely.sh [-r ] [-l ] 26 | # 27 | # 28 | # where: 29 | # is the remote host to execute the program 30 | # is the username on the remote host 31 | # is the maximum number of seconds to let the run 32 | # is 1 if the program must exit with 0 return code 33 | # is a file from which standard input is directed 34 | # is a file to which standard output and error are directed 35 | # is the path to the program to run 36 | # are the arguments to pass to the program. 37 | # 38 | if [ $# -lt 4 ]; then 39 | echo "./RunSafely.sh " 40 | exit 1 41 | fi 42 | 43 | DIR=${0%%`basename $0`} 44 | 45 | RHOST= 46 | RUSER=`id -un` 47 | FLAG=$1 48 | if [ $1 = "-r" ]; then 49 | RHOST=$2 50 | shift 2 51 | fi 52 | if [ $1 = "-l" ]; then 53 | RUSER=$2 54 | shift 2 55 | fi 56 | 57 | ULIMIT=$1 58 | EXITOK=$2 59 | INFILE=$3 60 | OUTFILE=$4 61 | PROGRAM=$5 62 | shift 5 63 | SYSTEM=`uname -s` 64 | 65 | ULIMITCMD="" 66 | case $SYSTEM in 67 | CYGWIN*) 68 | ;; 69 | Darwin*) 70 | # Disable core file emission, the script doesn't find it anyway because it is put 71 | # into /cores. 72 | ULIMITCMD="$ULIMITCMD ulimit -c 0;" 73 | ULIMITCMD="$ULIMITCMD ulimit -t $ULIMIT;" 74 | # To prevent infinite loops which fill up the disk, specify a limit on size of 75 | # files being output by the tests. 10 MB should be enough for anybody. ;) 76 | ULIMITCMD="$ULIMITCMD ulimit -f 10485760;" 77 | ;; 78 | *) 79 | ULIMITCMD="$ULIMITCMD ulimit -t $ULIMIT;" 80 | ULIMITCMD="$ULIMITCMD ulimit -c unlimited;" 81 | # To prevent infinite loops which fill up the disk, specify a limit on size of 82 | # files being output by the tests. 10 MB should be enough for anybody. ;) 83 | ULIMITCMD="$ULIMITCMD ulimit -f 10485760;" 84 | 85 | #ULIMITCMD="$ULIMITCMD ulimit -m 2000000 -v 2000000;" 86 | #ULIMITCMD="$ULIMITCMD ulimit -m 2000000 -v 2000000;" 87 | esac 88 | rm -f core core.* 89 | 90 | # 91 | # Run the command, timing its execution. 92 | # The standard output and standard error of $PROGRAM should go in $OUTFILE, 93 | # and the standard error of time should go in $OUTFILE.time. Note that the 94 | # return code of the program is appended to the $OUTFILE on an "Exit Val =" 95 | # line. 96 | # 97 | # To get the time program and the specified program different output filenames, 98 | # we tell time to launch a shell which in turn executes $PROGRAM with the 99 | # necessary I/O redirection. 100 | # 101 | PWD=`pwd` 102 | COMMAND="$PROGRAM $*" 103 | if [ "$SYSTEM" = "Darwin" ]; then 104 | COMMAND="${DIR}TimedExec.sh $ULIMIT $PWD $COMMAND" 105 | fi 106 | 107 | if [ "x$RHOST" = x ] ; then 108 | ( sh -c "$ULIMITCMD $COMMAND >$OUTFILE 2>&1 < $INFILE; echo exit \$?" ) 2>&1 \ 109 | | awk -- '\ 110 | BEGIN { cpu = 0.0; } 111 | /^user/ { cpu += $2; print; } 112 | /^sys/ { cpu += $2; print; } 113 | !/^user/ && !/^sys/ { print; } 114 | END { printf("cpu time= %f\n", cpu); }' > ${OUTFILE}.time 115 | else 116 | rm -f "$PWD/${PROGRAM}.command" 117 | rm -f "$PWD/${PROGRAM}.remote" 118 | rm -f "$PWD/${PROGRAM}.remote.time" 119 | echo "$ULIMITCMD cd $PWD; (time -p ($COMMAND > $OUTFILE.remote 2>&1 < $INFILE;); echo exit $?) > $OUTFILE.remote.time 2>&1" > "$PWD/${PROGRAM}.command" 120 | chmod +x "$PWD/${PROGRAM}.command" 121 | 122 | ( rsh -l $RUSER $RHOST "ls $PWD/${PROGRAM}.command" ) > /dev/null 2>&1 123 | ( rsh -l $RUSER $RHOST "$PWD/${PROGRAM}.command" ) 124 | cat $OUTFILE.remote.time | awk -- '\ 125 | BEGIN { cpu = 0.0; } 126 | /^user/ { cpu += $2; print; } 127 | /^sys/ { cpu += $2; print; } 128 | !/^user/ && !/^sys/ { print; } 129 | END { printf("program %f\n", cpu); }' > ${OUTFILE}.time 130 | sleep 1 131 | cp -f $OUTFILE.remote $OUTFILE 132 | rm -f $OUTFILE.remote 133 | rm -f $OUTFILE.remote.time 134 | fi 135 | 136 | exitval=`grep '^exit ' $OUTFILE.time | sed -e 's/^exit //'` 137 | if [ -z "$exitval" ] ; then 138 | exitval=99 139 | echo "TEST $PROGRAM failed: CAN'T GET EXIT CODE!" 140 | fi 141 | echo "exit $exitval" >> $OUTFILE 142 | 143 | if [ "$EXITOK" -ne 0 ] ; then 144 | if test "$exitval" -ne 0 ; then 145 | echo "test $PROGRAM failed: EXIT != 0" 146 | fi 147 | else 148 | exitval=0 149 | fi 150 | 151 | if ls | egrep "^core" > /dev/null 152 | then 153 | # If we are on a sun4u machine (UltraSparc), then the code we're generating 154 | # is 64 bit code. In that case, use gdb-64 instead of gdb. 155 | myarch=`uname -m` 156 | if [ "$myarch" = "sun4u" ] 157 | then 158 | GDB="gdb-64" 159 | else 160 | GDB=gdb 161 | fi 162 | 163 | corefile=`ls core* | head -n 1` 164 | echo "where 100" > StackTrace.$$ 165 | $GDB -q -batch --command=StackTrace.$$ --core=$corefile $PROGRAM < /dev/null 166 | rm -f StackTrace.$$ $corefile 167 | fi 168 | exit "$exitval" 169 | -------------------------------------------------------------------------------- /volatile_checker/test_checker.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use Cwd; 4 | use strict; 5 | use warnings; 6 | 7 | my %tests_dir = ( 8 | "reorder_test_dir" => "volatile-reorder", 9 | "volatile_address_test_dir" => "volatile-address" 10 | ); 11 | 12 | my %extra_opts = ( 13 | "volatile-reorder" => "", 14 | "volatile-address" => "--all-vars-output=all_vars_addr.txt" 15 | ); 16 | 17 | my @failed_tests; 18 | my $SAVE_TEMP = 0; 19 | 20 | sub runit ($) { 21 | my $cmd = shift; 22 | if ((system "$cmd") == -1) { 23 | print "FAIL: system '$cmd': $?"; 24 | return -1; 25 | } 26 | my $exit_value = $? >> 8; 27 | return $exit_value; 28 | } 29 | 30 | sub do_one_csmith_test($$$) { 31 | my ($checker, $csmith_home, $n) = @_; 32 | 33 | my $strict = ""; 34 | if ($checker eq "volatile-reorder") { 35 | $strict = "--strict-volatile-rule --paranoid"; 36 | } 37 | my $subdir = sprintf "%05d", $n; 38 | mkdir "$subdir" or die; 39 | chdir $subdir or die; 40 | my $csmith_cmd = "$csmith_home/src/csmith $strict --output $n.c"; 41 | die "Csmith crashed!" if runit($csmith_cmd); 42 | 43 | my $gcc_cmd = "gcc $n.c -I$csmith_home/runtime -o $n.exe > /dev/null 2>&1"; 44 | if (runit($gcc_cmd)) { 45 | die "iteration [$n] failed: cannot compile $n.exe\n"; 46 | } 47 | 48 | my $res = runit("RunSafely.sh 10 1 /dev/null $n.run.out $n.exe"); 49 | if ($res == 137) { 50 | print "iteration [$n] timeout\n"; 51 | } 52 | elsif ($res != 0) { 53 | die "failed to run exe!"; 54 | } 55 | 56 | my $extra_opt = $extra_opts{$checker}; 57 | die "preprocessing failed" if (runit("gcc -E -I$csmith_home/runtime $n.c > $n.preprocessed.c")); 58 | my $checker_cmd = "../../volatile_checker --checker=$checker $extra_opt $n.preprocessed.c > $n.checker.out 2>&1"; 59 | # print "$checker_cmd\n"; 60 | die "checker failed!" if (runit($checker_cmd)); 61 | print "iteration [$n] succeeded\n"; 62 | 63 | out: 64 | chdir ".." or die; 65 | system "rm -rf $subdir" unless ($SAVE_TEMP); 66 | } 67 | 68 | sub test_against_csmith($$) { 69 | my ($test, $iteration) = @_; 70 | 71 | my $checker = $tests_dir{$test}; 72 | die unless defined($checker); 73 | my $csmith_home = $ENV{"CSMITH_HOME"}; 74 | die "please set CSMITH_HOME env first!" unless (defined($csmith_home)); 75 | print "Starting testing $checker checker with Csmith...\n"; 76 | 77 | my $working_dir = "tmp_csmith_testing"; 78 | if (-d $working_dir) { 79 | system "rm -rf $working_dir/*"; 80 | } 81 | else { 82 | mkdir $working_dir or die; 83 | } 84 | chdir $working_dir or die; 85 | for (my $i = 0; $i < $iteration; $i++) { 86 | do_one_csmith_test($checker, $csmith_home, $i); 87 | } 88 | chdir ".." or die; 89 | print "cwd: " . cwd() . "\n"; 90 | print "All $iteration tests passed!\n"; 91 | } 92 | 93 | sub test_one_dir($$$) { 94 | my ($dir, $checker, $regenerate) = @_; 95 | 96 | my @test_files = glob("*.c"); 97 | for (my $i = 0; $i < @test_files; $i++) { 98 | my $test = $test_files[$i]; 99 | print " [$i]: $test ..."; 100 | my $out = $test; 101 | $out =~ s/\.c$/\.out/; 102 | if ($regenerate) { 103 | runit("../volatile_checker --checker=$checker $test > $out 2>&1"); 104 | print "done\n"; 105 | next; 106 | } 107 | 108 | if (!(-e $out)) { 109 | push @failed_tests, $test; 110 | print "failed\n"; 111 | next; 112 | } 113 | 114 | my $new_out = "$out.new"; 115 | runit("../volatile_checker --checker=$checker $test > $new_out 2>&1"); 116 | if (runit("diff $new_out $out")) { 117 | push @failed_tests, $test; 118 | print "failed\n"; 119 | } 120 | else { 121 | print "succeeded\n"; 122 | } 123 | system ("rm -rf $new_out"); 124 | } 125 | } 126 | 127 | sub do_unit_test($$) { 128 | my ($test, $regenerate) = @_; 129 | 130 | my $msg; 131 | if ($regenerate) { 132 | $msg = "regenerating"; 133 | } 134 | else { 135 | $msg = "testing"; 136 | } 137 | print "Start $msg...\n"; 138 | 139 | my $cwd = cwd(); 140 | foreach my $dir (keys %tests_dir) { 141 | if (defined($test)) { 142 | next if ($dir ne $test); 143 | } 144 | print "[*]$msg dir $dir\n"; 145 | chdir $dir or die; 146 | my $checker = $tests_dir{$dir}; 147 | test_one_dir($dir, $checker, $regenerate); 148 | chdir $cwd or die; 149 | } 150 | 151 | print "-------------------------------\n"; 152 | print "Testing result:\n"; 153 | if (@failed_tests == 0) { 154 | print "All tests passed!\n"; 155 | } 156 | else { 157 | print "failed tests:\n"; 158 | foreach my $test (@failed_tests) { 159 | print " $test\n"; 160 | } 161 | } 162 | } 163 | 164 | my $help_msg = ' 165 | Usage: test_checker.pl 166 | options: 167 | --with-csmith: test checkers agains csmith with --strict-volatile-rules 168 | --iteration: only work with --with-csmith option, determine the number of testing iteration (default: 100) 169 | --save-temp: only work with --with-csmith option, save temp files. 170 | --regenerate-test-output: re-generate test output 171 | --test=[test-dir]: do unit test for one test dir 172 | '; 173 | 174 | sub die_with_help($) { 175 | my ($opt) = @_; 176 | 177 | print "Invalid option: $opt"; 178 | print $help_msg; 179 | die; 180 | } 181 | 182 | sub main() { 183 | my $opt; 184 | my @unused = (); 185 | my $with_csmith = 0; 186 | my $regenerate = 0; 187 | my $iteration = 100; 188 | my $test = undef; 189 | 190 | while(defined ($opt = shift @ARGV)) { 191 | if ($opt =~ m/^--(.+)=(.+)$/) { 192 | if ($1 eq "iteration") { 193 | $iteration = $2; 194 | } 195 | elsif ($1 eq "test") { 196 | $test = $2; 197 | } 198 | else { 199 | die_with_help($opt); 200 | } 201 | } 202 | elsif ($opt =~ m/^--(.+)$/) { 203 | if ($1 eq "with-csmith") { 204 | $with_csmith = 1; 205 | } 206 | elsif ($1 eq "save-temp") { 207 | $SAVE_TEMP = 1; 208 | } 209 | elsif ($1 eq "regenerate-test-output") { 210 | $regenerate = 1; 211 | } 212 | elsif ($1 eq "help") { 213 | print $help_msg; 214 | return; 215 | } 216 | else { 217 | die_with_help($opt); 218 | } 219 | } 220 | else { 221 | push @unused, $opt; 222 | } 223 | } 224 | 225 | die_with_help("$ARGV[0]") if (@ARGV != 0); 226 | if (defined($test)) { 227 | die "Invalid test dir[$test]!" unless defined($tests_dir{$test}); 228 | } 229 | 230 | if ($with_csmith) { 231 | $test = "reorder_test_dir" if (!defined($test)); 232 | test_against_csmith($test, $iteration); 233 | } 234 | else { 235 | do_unit_test($test, $regenerate); 236 | } 237 | } 238 | 239 | main(); 240 | -------------------------------------------------------------------------------- /volatile_pintrace/test1.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my $TEST_INPUT = "small.c"; 7 | my $SCRATCH = "/scratch/chenyang"; 8 | my %COMPILERS = ( 9 | "gcc" => "$SCRATCH/compilers/compiler-install/gcc-r202631-install/bin/gcc -O0", 10 | "clang" => "$SCRATCH/compilers/compiler-install/llvm-r191259-install/bin/clang -O0", 11 | "ccomp" => "$SCRATCH/compilers/compiler-install/compcert-2.0/bin/ccomp", 12 | ); 13 | my $ARCH32 = 1; 14 | my $CHECK_CHECKSUM = 1; 15 | 16 | my $PIN_HOME = "$SCRATCH/programs/pin-2.12-55942-gcc.4.4.7-linux"; 17 | my $CHECKER = "$SCRATCH/voltest/volatile_checker/volatile_checker"; 18 | my $GEN_VOLATILE_ADDR = "$SCRATCH/voltest/volatile_pintrace/gen_volatile_addr.pl"; 19 | my $RUN_SAFELY = "$SCRATCH/voltest/volatile_pintrace/RunSafely"; 20 | my $CHECKER_ADDR_OUT = "checker.addr.out.txt"; 21 | my $VOL_ADDR_OUT_PREFIX = "vol_addr_out"; 22 | 23 | my $PIN_MODE = "checksum"; 24 | my $ARCH_OPT = ""; 25 | my $ARCH_CHECKER_OPT = ""; 26 | my $PIN_BIN = ""; 27 | 28 | sub runit ($) { 29 | my $cmd = shift; 30 | print "runit:[$cmd]\n"; 31 | if ((system "$cmd") == -1) { 32 | return -1; 33 | } 34 | my $exit_value = $? >> 8; 35 | return $exit_value; 36 | } 37 | 38 | sub abort_if_fail($) { 39 | my ($cmd) = @_; 40 | exit(1) if (runit($cmd)); 41 | } 42 | 43 | sub has_warning($$) { 44 | my ($out_fn, $warnings) = @_; 45 | my $bad = 0; 46 | open INF, "<$out_fn" or exit(1); 47 | while (my $line = ) { 48 | chomp $line; 49 | if (grep { $line =~ m/$_/} @$warnings) { 50 | $bad = 1; 51 | last; 52 | } 53 | } 54 | close INF; 55 | return $bad; 56 | } 57 | 58 | sub pre_check() { 59 | my $pre_out = "pre_out.clang.txt"; 60 | abort_if_fail("clang -pedantic -Wall -O0 -c $TEST_INPUT >$pre_out 2>&1"); 61 | my @clang_warnings = ( 62 | 'conversions than data arguments', 63 | 'incompatible redeclaration', 64 | 'ordered comparison between pointer', 65 | 'eliding middle term', 66 | 'end of non-void function', 67 | 'invalid in C99', 68 | 'specifies type', 69 | 'should return a value', 70 | 'uninitialized', 71 | 'incompatible pointer to', 72 | 'incompatible integer to', 73 | 'type specifier missing', 74 | ); 75 | exit(1) if has_warning($pre_out, \@clang_warnings); 76 | 77 | $pre_out = "pre_out.gcc.txt"; 78 | abort_if_fail("gcc -Wall -Wextra -O2 $TEST_INPUT >$pre_out 2>&1"); 79 | my @gcc_warnings = ( 80 | 'uninitialized', 81 | 'without a cast', 82 | 'control reaches end', 83 | 'null argument', 84 | 'return type defaults', 85 | 'useless type name in empty declaration', 86 | 'no semicolon at end', 87 | 'type defaults to', 88 | 'format', 89 | #'incompatible pointer', 90 | 'ordered comparison of pointer with integer', 91 | 'declaration does not declare anything', 92 | 'expects type', 93 | 'pointer from integer', 94 | 'incompatible implicit', 95 | 'excess elements in struct initializer', 96 | 'comparison between pointer and integer', 97 | ); 98 | exit(1) if has_warning($pre_out, \@gcc_warnings); 99 | } 100 | 101 | sub do_one_compiler($$) { 102 | my ($comp_name, $all_out_files) = @_; 103 | my $comp_cmd = $COMPILERS{$comp_name}; 104 | my $input_root = $TEST_INPUT; 105 | $input_root =~ s/\.c$//; 106 | 107 | if ($comp_name =~ m/ccomp/) { 108 | abort_if_fail("$comp_cmd -fall $TEST_INPUT -o ${input_root}_$comp_name > cc_out.$comp_name.txt 2>&1"); 109 | } 110 | else { 111 | abort_if_fail("$comp_cmd $ARCH_OPT $TEST_INPUT -w -o ${input_root}_$comp_name > cc_out.$comp_name.txt 2>&1"); 112 | } 113 | abort_if_fail("$GEN_VOLATILE_ADDR --vars-file=$CHECKER_ADDR_OUT ${input_root}_$comp_name > $VOL_ADDR_OUT_PREFIX.$comp_name.txt"); 114 | abort_if_fail("$RUN_SAFELY 20 1 /dev/null out.$comp_name.txt $PIN_BIN -vol_input $VOL_ADDR_OUT_PREFIX.$comp_name.txt -output_mode $PIN_MODE -- ./${input_root}_$comp_name > /dev/null 2>&1"); 115 | $all_out_files->{$comp_name} = "out.$comp_name.txt"; 116 | } 117 | 118 | sub get_checksums($) { 119 | my ($fname) = @_; 120 | my $checksum = undef; 121 | my $vol_checksum = undef; 122 | 123 | open INF, "<$fname" or exit 1; 124 | while (my $line = ) { 125 | chomp $line; 126 | if ($line =~ m/vol_access_checksum = ([0-9a-fA-F]+)/) { 127 | $vol_checksum = $1; 128 | } 129 | elsif ($line =~ m/checksum = ([0-9a-fA-F]+)/) { 130 | $checksum = $1; 131 | } 132 | } 133 | close INF; 134 | exit 1 unless (defined $vol_checksum); 135 | return ($checksum, $vol_checksum); 136 | } 137 | 138 | sub check_outputs($) { 139 | my ($all_out_files) = @_; 140 | my %all_vol_checksums = (); 141 | my %compiler_to_vol_checksum = (); 142 | my %all_checksums = (); 143 | exit 1 if (scalar(keys %$all_out_files) < 1); 144 | foreach my $comp_name (sort keys %$all_out_files) { 145 | my ($tmp_checksum, $tmp_vol_checksum) = get_checksums($all_out_files->{$comp_name}); 146 | if ($CHECK_CHECKSUM) { 147 | exit 1 unless (defined($tmp_checksum)); 148 | $all_checksums{$tmp_checksum} = 1; 149 | } 150 | $all_vol_checksums{$tmp_vol_checksum} = 1; 151 | $compiler_to_vol_checksum{$comp_name} = $tmp_vol_checksum; 152 | } 153 | if ($CHECK_CHECKSUM) { 154 | exit 1 if (scalar(keys %all_checksums) != 1); 155 | } 156 | 157 | # exit 1 if (scalar(keys %all_vol_checksums) == 1); 158 | 159 | # a stronger invariant: each compiler produces a different vol_checksum 160 | # (if we have more than 2 compilers) 161 | # exit 1 if (scalar(keys %COMPILERS) != scalar(keys %all_vol_checksums)); 162 | 163 | if (($compiler_to_vol_checksum{"gcc"} eq $compiler_to_vol_checksum{"clang"}) && 164 | ($compiler_to_vol_checksum{"gcc"} ne $compiler_to_vol_checksum{"ccomp"})) { 165 | # good 166 | } 167 | else { 168 | exit 1; 169 | } 170 | } 171 | 172 | sub run_framac() { 173 | my $framac_input = $TEST_INPUT; 174 | $framac_input =~ s/\.c$/-framac.c/; 175 | abort_if_fail("cp -f $TEST_INPUT $framac_input"); 176 | my $s = ""; 177 | open INF, "<$framac_input" or exit 1; 178 | while (my $line = ) { 179 | chomp $line; 180 | if ($line =~ m/int main \(int argc, char\* argv\[\]\)/) { 181 | $s .= "int argc; char **argv; int main (void)\n"; 182 | } 183 | else { 184 | $s .= "$line\n"; 185 | } 186 | } 187 | close INF; 188 | 189 | open OUTF, ">$framac_input" or exit 1; 190 | print OUTF $s; 191 | close OUTF; 192 | 193 | my $framac_out = "out_framac.txt"; 194 | my $framac_mach = "x86_64"; 195 | if ($ARCH32) { 196 | $framac_mach = "x86_32"; 197 | } 198 | abort_if_fail("RunSafely.sh 20 1 /dev/null $framac_out frama-c -cpp-command \\\"gcc -C -Dvolatile= -E -I.\\\" -val-signed-overflow-alarms -val -stop-at-first-alarm -no-val-show-progress -machdep $framac_mach -obviously-terminates -precise-unions $framac_input"); 199 | 200 | my $bad = 0; 201 | open INF, "<$framac_out" or exit 1; 202 | while (my $line = ) { 203 | chomp $line; 204 | if ($line =~ m/user error|assert/) { 205 | $bad = 1; 206 | last; 207 | } 208 | } 209 | close INF; 210 | exit 1 if ($bad); 211 | } 212 | 213 | sub go() { 214 | system("rm -f out*.txt"); 215 | my $pin_target = "obj-intel64"; 216 | if ($ARCH32) { 217 | $ARCH_OPT = "-m32"; 218 | $ARCH_CHECKER_OPT = "--m32"; 219 | $pin_target = "obj-ia32"; 220 | } 221 | $PIN_BIN = "$PIN_HOME/pin.sh -injection child -t $PIN_HOME/source/tools/ManualExamples/$pin_target/pinatrace.so"; 222 | 223 | pre_check(); 224 | abort_if_fail("$CHECKER $ARCH_CHECKER_OPT --checker=volatile-address $TEST_INPUT > $CHECKER_ADDR_OUT 2>&1"); 225 | 226 | my %all_out_files = (); 227 | foreach my $comp_name (sort keys %COMPILERS) { 228 | do_one_compiler($comp_name, \%all_out_files); 229 | } 230 | check_outputs(\%all_out_files); 231 | run_framac(); 232 | } 233 | 234 | go(); 235 | 236 | -------------------------------------------------------------------------------- /scripts/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## 3 | ## TODOs: 4 | ## + Move downloaded tarballs to a downloads directory? 5 | ## + Delete the downloaded tarballs? 6 | ## + Remove the llvm-build directory? 7 | ## + Build less of LLVM+Clang? 8 | 9 | ############################################################################### 10 | 11 | if test -z "$VOLTEST_HOME"; then 12 | echo $0: '$VOLTEST_HOME' is not set 13 | exit 1 14 | fi 15 | if test ! -e "$VOLTEST_HOME/scripts/vars.sh"; then 16 | echo $0: '$VOLTEST_HOME/scripts/vars.sh' does not exist 17 | exit 1 18 | fi 19 | . "$VOLTEST_HOME/scripts/vars.sh" 20 | 21 | ############################################################################### 22 | 23 | # Abort this script when any command fails. 24 | set -e 25 | # Abort this script when any unbound variable is used. 26 | set -u 27 | 28 | # If you want a bunch of noise, set "quiet=" and "silent=". 29 | quiet=-q 30 | silent=-s 31 | 32 | # To make `apt-get' be really quiet, one must use "-q -q". 33 | very_quiet="$quiet $quiet" 34 | 35 | ncpus=1 36 | if test -e /proc/cpuinfo; then 37 | # Get the number of (virtual) CPUs on Linux. 38 | ncpus=`cat /proc/cpuinfo | grep processor | wc -l` 39 | fi 40 | 41 | ############################################################################### 42 | 43 | ## SET UP WORK DIRECTORIES 44 | 45 | ## Now all done by `bootstrap.sh'. 46 | # 47 | # time=`date +%H:%M:%S` 48 | # echo "*** [$time]" "Setting up work directories..." 49 | # 50 | # umask 002 51 | # 52 | # sudo mkdir "$WORK_HOME" 53 | # sudo chown "$USER:$PROJECT" "$WORK_HOME" 54 | # chmod ug+rwx "$WORK_HOME" 55 | # 56 | # mkdir "$WORK_SRC_HOME" 57 | # 58 | # mkdir "$WORK_RUN_HOME" 59 | 60 | ############################################################################### 61 | 62 | ## SET UP APT-GET 63 | 64 | time=`date +%H:%M:%S` 65 | echo "*** [$time]" "Running \`apt-get update'..." 66 | 67 | # Make sure that this node's package lists are up to date. 68 | # 69 | sudo apt-get $very_quiet -y update 70 | 71 | ############################################################################### 72 | 73 | ## SET UP CSMITH 74 | 75 | time=`date +%H:%M:%S` 76 | echo "*** [$time]" "Setting up Csmith..." 77 | 78 | # Get Csmith. 79 | # 80 | time=`date +%H:%M:%S` 81 | echo "*** [$time]" " Acquiring Csmith sources (@ $CSMITH_REV)..." 82 | # 83 | git clone $quiet "$CSMITH_GIT" --no-checkout "$CSMITH_HOME" 84 | cd "$CSMITH_HOME" 85 | git checkout $quiet --detach "$CSMITH_REV" 86 | 87 | # Install things required by test driver scripts. 88 | # 89 | time=`date +%H:%M:%S` 90 | echo "*** [$time]" " Installing Csmith dependencies..." 91 | # 92 | sudo apt-get $very_quiet -y install libsys-cpu-perl 93 | sudo apt-get $very_quiet -y install liblockfile-simple-perl 94 | 95 | # Building in a separate object tree sets up a failure later on because 96 | # the `evaluate_program.pl' script expects to find `csmith.h' and whatnot in 97 | # $CSMITH_HOME/runtime'. 98 | # 99 | # Installing into a separate directory is also a failure, because the 100 | # `random_test.pl' script looks for "$CSMITH_HOME/src/csmith". 101 | # 102 | # Just do it solution: build and run in the source tree. 103 | # 104 | # Ultimate solution: set a CSMITH envvar, which can find things in bin or src 105 | # then point to the installed tree. 106 | # 107 | # cd .. 108 | # mkdir obj 109 | # cd obj 110 | # mkdir csmith 111 | # cd csmith 112 | 113 | # Configure. 114 | # 115 | time=`date +%H:%M:%S` 116 | echo "*** [$time]" " Configuring Csmith..." 117 | # 118 | cd "$CSMITH_HOME" 119 | ./configure > Configure.errs 120 | 121 | # Compile. 122 | # 123 | time=`date +%H:%M:%S` 124 | echo "*** [$time]" " Compiling Csmith..." 125 | # 126 | make > Make.errs 2>&1 127 | # make install 128 | 129 | # Issue: important scripts are not installed? evaluate_program.pl? Everything 130 | # in utah/scripts/old_john_driver? 131 | 132 | ############################################################################### 133 | 134 | ## SET UP PIN AND VOLATILE_PINTRACE 135 | 136 | time=`date +%H:%M:%S` 137 | echo "*** [$time]" "Setting up volatile_pintrace..." 138 | 139 | # Get Pin. Assumes that PIN_HOME == "$WORK_SRC_DIR/$PIN_DIR". 140 | # 141 | time=`date +%H:%M:%S` 142 | echo "*** [$time]" " Acquiring Pin..." 143 | # 144 | cd "$WORK_SRC_HOME" 145 | wget $quiet "$PIN_URL" 146 | tar zxf "$PIN_TGZ" 147 | 148 | # Install files as directed by `volatile_pintrace/README.txt'. 149 | # 150 | time=`date +%H:%M:%S` 151 | echo "*** [$time]" " Patching Pin..." 152 | # 153 | cp -p "$VOLATILE_PINTRACE_HOME/pin.sh" \ 154 | "$PIN_HOME" 155 | cp -p "$VOLATILE_PINTRACE_HOME/pinatrace.cpp" \ 156 | "$PIN_HOME/source/tools/ManualExamples/" 157 | 158 | # Compile as directed by `volatile_pintrace/README.txt'. 159 | # 160 | time=`date +%H:%M:%S` 161 | echo "*** [$time]" " Compiling volatile_pintrace..." 162 | # 163 | cd "$PIN_HOME/source/tools/ManualExamples" 164 | make > Make.errs 2>&1 165 | 166 | # Edit Csmith driver scripts as directed by `volatile_pintrace/README.txt'. 167 | # 168 | time=`date +%H:%M:%S` 169 | echo "*** [$time]" " Patching Csmith test driver for volatile_pintrace..." 170 | # 171 | patch $silent -d "$CSMITH_HOME/utah/scripts/old_john_driver" < \ 172 | "$VOLTEST_HOME/patches/csmith/volatile_pintrace.patch" 173 | 174 | ############################################################################### 175 | 176 | ## SET UP LLVM/CLANG (FOR C-REDUCE) 177 | 178 | time=`date +%H:%M:%S` 179 | echo "*** [$time]" "Setting up LLVM/Clang..." 180 | 181 | # Get LLVM. 182 | # 183 | time=`date +%H:%M:%S` 184 | echo "*** [$time]" " Acquiring LLVM sources..." 185 | # 186 | cd "$WORK_SRC_HOME" 187 | wget $quiet "$LLVM_URL" 188 | tar zxf "$LLVM_TGZ" 189 | 190 | # Get Clang. 191 | # 192 | time=`date +%H:%M:%S` 193 | echo "*** [$time]" " Acquiring Clang sources..." 194 | # 195 | cd "$WORK_SRC_HOME" 196 | wget $quiet "$LLVM_CLANG_URL" 197 | tar zxf "$LLVM_CLANG_TGZ" 198 | # Move this into the LLVM source tree; part of the LLVM/Clang build procedure. 199 | # See . 200 | mv "$LLVM_CLANG_DIR" "$LLVM_SRC_HOME/tools/clang" 201 | 202 | # Get Compiler RT. 203 | # 204 | time=`date +%H:%M:%S` 205 | echo "*** [$time]" " Acquiring Compiler RT sources..." 206 | # 207 | cd "$WORK_SRC_HOME" 208 | wget $quiet "$LLVM_COMPILER_RT_URL" 209 | tar zxf "$LLVM_COMPILER_RT_TGZ" 210 | # Move into the LLVM source tree; part of the LLVM/Clang build procedure. 211 | # See . 212 | mv "$LLVM_COMPILER_RT_DIR" "$LLVM_SRC_HOME/projects/compiler-rt" 213 | 214 | # Make LLVM+Clang+Compiler-RT build tree. 215 | # 216 | mkdir "$LLVM_OBJ_HOME" 217 | 218 | # Configure. 219 | # 220 | time=`date +%H:%M:%S` 221 | echo "*** [$time]" " Configuring LLVM+Clang+Compiler-RT..." 222 | # 223 | cd "$LLVM_OBJ_HOME" 224 | "$LLVM_SRC_HOME"/configure --prefix="$LLVM_HOME" > Configure.errs 225 | 226 | # Compile. 227 | ## LLVM 3.2 228 | # make : This takes about 120 minutes on a pc3000. 229 | # make -j2 : This takes about 82 minutes on a pc3000. 230 | # make : This takes about 50 minutes on a d710. 231 | # make -j4 : This takes about 15 minutes on a d710. 232 | # make -j8 : This takes about 12 minutes on a d710. 233 | # make -j64 : This takes about 3.5 minutes on a d820. 234 | ## LLVM 3.3 235 | # make -j64 : This takes about 4 minutes on a d820. 236 | # 237 | time=`date +%H:%M:%S` 238 | echo "*** [$time]" " Compiling LLVM+Clang+Compiler-RT (-j$ncpus)..." 239 | # 240 | make -j"$ncpus" > Make.errs 2>&1 241 | 242 | # Install. 243 | # The C-Reduce build system only works against an installed LLVM/Clang, 244 | # not an LLVM+Clang build tree. 245 | # 246 | time=`date +%H:%M:%S` 247 | echo "*** [$time]" " Installing LLVM+Clang+Compiler-RT..." 248 | # 249 | make install > Make-install.errs 2>&1 250 | 251 | ############################################################################### 252 | 253 | ## SET UP C-REDUCE 254 | 255 | time=`date +%H:%M:%S` 256 | echo "*** [$time]" "Setting up C-Reduce..." 257 | 258 | # Get C-Reduce. 259 | # 260 | time=`date +%H:%M:%S` 261 | echo "*** [$time]" " Acquiring C-Reduce sources (@ $CREDUCE_REV)..." 262 | # 263 | git clone $quiet "$CREDUCE_GIT" --no-checkout "$CREDUCE_HOME" 264 | cd "$CREDUCE_HOME" 265 | git checkout $quiet --detach "$CREDUCE_REV" 266 | 267 | # Install things required by C-Reduce. 268 | # 269 | time=`date +%H:%M:%S` 270 | echo "*** [$time]" " Installing C-Reduce dependencies..." 271 | # 272 | sudo apt-get $very_quiet -y install \ 273 | astyle \ 274 | delta \ 275 | indent \ 276 | libbenchmark-timer-perl \ 277 | libexporter-lite-perl \ 278 | libfile-which-perl \ 279 | libgetopt-tabular-perl \ 280 | libregexp-common-perl \ 281 | libsys-cpu-perl 282 | 283 | # Configure. 284 | # 285 | time=`date +%H:%M:%S` 286 | echo "*** [$time]" " Configuring C-Reduce..." 287 | # 288 | cd "$CREDUCE_HOME" 289 | ./configure --with-llvm="$LLVM_HOME" > Configure.errs 290 | 291 | # Compile. 292 | # 293 | time=`date +%H:%M:%S` 294 | echo "*** [$time]" " Compiling C-Reduce (-j$ncpus)..." 295 | # 296 | make -j"$ncpus" > Make.errs 2>&1 297 | # make install 298 | 299 | ############################################################################### 300 | 301 | ## SET UP FRAMA-C 302 | 303 | time=`date +%H:%M:%S` 304 | echo "*** [$time]" "Setting up Frama-C..." 305 | 306 | # Install Frama-C. The "frama-c" package has many, many dependencies. 307 | # 308 | time=`date +%H:%M:%S` 309 | echo "*** [$time]" " Installing Frama-C..." 310 | # 311 | sudo apt-get $very_quiet -y install frama-c 312 | 313 | ############################################################################### 314 | 315 | ## SET UP VOLATILE_CHECKER 316 | 317 | time=`date +%H:%M:%S` 318 | echo "*** [$time]" "Setting up volatile_checker..." 319 | 320 | # Compile as directed by `volatile_checker/README.txt'. 321 | # 322 | time=`date +%H:%M:%S` 323 | echo "*** [$time]" " Compiling volatile_checker..." 324 | # 325 | cd "$VOLATILE_CHECKER_HOME" 326 | make LLVM_PATH="$LLVM_HOME" > Make.errs 2>&1 327 | 328 | ############################################################################### 329 | 330 | ## SET UP TEST DRIVER 331 | 332 | time=`date +%H:%M:%S` 333 | echo "*** [$time]" "Patching Csmith test driver to configure targets..." 334 | 335 | # Edit `evaluate_program.pl' to describe what you want to test. 336 | # 337 | patch $silent -d "$CSMITH_HOME/utah/scripts/old_john_driver" < \ 338 | "$VOLTEST_HOME/patches/csmith/test-targets.patch" 339 | 340 | time=`date +%H:%M:%S` 341 | echo "*** [$time]" "Patching volatile_pintrace test driver to configure targets..." 342 | 343 | # Edit `volatile_test.pl' to describe what you want to test. 344 | # 345 | patch $silent -d "$VOLATILE_PINTRACE_HOME" < \ 346 | "$VOLTEST_HOME/patches/volatile_pintrace/volatile_test.patch" 347 | 348 | ############################################################################### 349 | 350 | time=`date +%H:%M:%S` 351 | echo "*** [$time]" "Setup complete." 352 | 353 | ############################################################################### 354 | 355 | ## End of file. 356 | -------------------------------------------------------------------------------- /volatile_checker/CheckerManager.cpp: -------------------------------------------------------------------------------- 1 | #include "CheckerManager.h" 2 | 3 | #include 4 | 5 | #include "clang/Basic/Diagnostic.h" 6 | #include "clang/Basic/TargetInfo.h" 7 | #include "clang/Lex/Preprocessor.h" 8 | #include "clang/Frontend/CompilerInstance.h" 9 | #include "clang/Parse/ParseAST.h" 10 | #include "clang/Serialization/ASTReader.h" 11 | #include "clang/Frontend/TextDiagnosticPrinter.h" 12 | #include "clang/Driver/Compilation.h" 13 | #include "clang/Driver/Driver.h" 14 | #include "clang/Driver/Tool.h" 15 | 16 | #include "llvm/Config/config.h" 17 | 18 | #include "Checker.h" 19 | 20 | using namespace clang::driver; 21 | using namespace clang; 22 | 23 | CheckerManager* CheckerManager::Instance; 24 | 25 | std::map * 26 | CheckerManager::CheckersMapPtr; 27 | 28 | CheckerManager *CheckerManager::GetInstance() 29 | { 30 | if (CheckerManager::Instance) 31 | return CheckerManager::Instance; 32 | 33 | CheckerManager::Instance = new CheckerManager(); 34 | CheckerAssert(CheckerManager::Instance && "NULL Instance"); 35 | CheckerAssert(CheckerManager::CheckersMapPtr && "NULL CheckersMapPtr"); 36 | 37 | CheckerManager::Instance->CheckersMap = 38 | *CheckerManager::CheckersMapPtr; 39 | return CheckerManager::Instance; 40 | } 41 | 42 | bool CheckerManager::isCXXLangOpt() 43 | { 44 | CheckerAssert(CheckerManager::Instance && "Invalid Instance!"); 45 | CheckerAssert(CheckerManager::Instance->ClangInstance && 46 | "Invalid ClangInstance!"); 47 | return (CheckerManager::Instance->ClangInstance->getLangOpts() 48 | .CPlusPlus); 49 | } 50 | 51 | bool CheckerManager::isCLangOpt() 52 | { 53 | CheckerAssert(CheckerManager::Instance && "Invalid Instance!"); 54 | CheckerAssert(CheckerManager::Instance->ClangInstance && 55 | "Invalid ClangInstance!"); 56 | return (CheckerManager::Instance->ClangInstance->getLangOpts() 57 | .C99); 58 | } 59 | 60 | bool CheckerManager::initializeCompilerInstance( 61 | llvm::SmallVector &Args, 62 | const std::string &Path, 63 | std::string &ErrorMsg) 64 | { 65 | // some code to construct CompilerInvocation instance was 66 | // copied from clang/examples/clang-interpreter/main.cpp 67 | IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); 68 | TextDiagnosticPrinter *DiagClient = 69 | new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); 70 | 71 | IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); 72 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); 73 | Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), 74 | "a.out", Diags); 75 | TheDriver.setTitle(Args[0]); 76 | 77 | OwningPtr Comp(TheDriver.BuildCompilation(Args)); 78 | CheckerAssert(Comp && "NULL Compilation instance!"); 79 | 80 | const driver::JobList &Jobs = Comp->getJobs(); 81 | 82 | if ((Jobs.size() != 1) || !isa(*Jobs.begin())) { 83 | ErrorMsg = "Bad joblist!"; 84 | return false; 85 | } 86 | 87 | const driver::Command *Cmd = cast(*Jobs.begin()); 88 | CheckerAssert((llvm::StringRef(Cmd->getCreator().getName()) == "clang") && 89 | "Invalid Cmd!"); 90 | 91 | const driver::ArgStringList &CCArgs = Cmd->getArguments(); 92 | OwningPtr CI(new CompilerInvocation); 93 | CompilerInvocation::CreateFromArgs(*CI, 94 | const_cast(CCArgs.data()), 95 | const_cast(CCArgs.data()) + 96 | CCArgs.size(), 97 | Diags); 98 | 99 | ClangInstance = new CompilerInstance(); 100 | ClangInstance->setInvocation(CI.take()); 101 | 102 | // Create the compilers actual diagnostics engine. 103 | ClangInstance->createDiagnostics(); 104 | CheckerAssert(ClangInstance->hasDiagnostics() && 105 | "failed to create Diagnostics!"); 106 | #if 0 107 | // Just backup some code to hard-code search paths to system headers. 108 | // TheDriver handles all of these. 109 | HeaderSearchOptions &HeaderOpts = ClangInstance->getHeaderSearchOpts(); 110 | HeaderOpts.AddPath("/usr/local/include", frontend::System, /*IsUserSupplied=*/false, 111 | /*IsFramework=*/false, /*IgnoreSysRoot=*/true, 112 | /*IsInternal=*/true, /*ImplicitExternC=*/false); 113 | HeaderOpts.AddPath("/usr/include/x86_64-linux-gnu", 114 | frontend::System, /*IsUserSupplied=*/false, 115 | /*IsFramework=*/false, /*IgnoreSysRoot=*/true, 116 | /*IsInternal=*/true, /*ImplicitExternC=*/true); 117 | HeaderOpts.AddPath("/include", frontend::System, /*IsUserSupplied=*/false, 118 | /*IsFramework=*/false, /*IgnoreSysRoot=*/true, 119 | /*IsInternal=*/true, /*ImplicitExternC=*/true); 120 | HeaderOpts.AddPath("/usr/include", frontend::System, /*IsUserSupplied=*/false, 121 | /*IsFramework=*/false, /*IgnoreSysRoot=*/true, 122 | /*IsInternal=*/true, /*ImplicitExternC=*/true); 123 | #endif 124 | 125 | TargetOptions &TargetOpts = ClangInstance->getTargetOpts(); 126 | llvm::Triple DefaultTriple(LLVM_DEFAULT_TARGET_TRIPLE); 127 | if (Force32BitTarget && !DefaultTriple.isArch32Bit()) { 128 | llvm::Triple Triple32 = DefaultTriple.get32BitArchVariant(); 129 | TargetOpts.Triple = Triple32.getTriple(); 130 | } 131 | else { 132 | TargetOpts.Triple = LLVM_DEFAULT_TARGET_TRIPLE; 133 | } 134 | 135 | TargetInfo *Target = 136 | TargetInfo::CreateTargetInfo(ClangInstance->getDiagnostics(), 137 | &TargetOpts); 138 | ClangInstance->setTarget(Target); 139 | ClangInstance->createFileManager(); 140 | ClangInstance->createSourceManager(ClangInstance->getFileManager()); 141 | ClangInstance->createPreprocessor(); 142 | 143 | DiagnosticConsumer &DgClient = ClangInstance->getDiagnosticClient(); 144 | DgClient.BeginSourceFile(ClangInstance->getLangOpts(), 145 | &ClangInstance->getPreprocessor()); 146 | ClangInstance->createASTContext(); 147 | 148 | assert(CurrentCheckerImpl && "Bad checker instance!"); 149 | ClangInstance->setASTConsumer(CurrentCheckerImpl); 150 | Preprocessor &PP = ClangInstance->getPreprocessor(); 151 | PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), 152 | PP.getLangOpts()); 153 | 154 | InputKind IK = FrontendOptions::getInputKindForExtension( 155 | StringRef(SrcFileName).rsplit('.').second); 156 | if (!((IK == IK_C) || (IK == IK_PreprocessedC) || 157 | (IK == IK_CXX) || (IK == IK_PreprocessedCXX))) { 158 | ErrorMsg = "Unsupported file type!"; 159 | return false; 160 | } 161 | if (!ClangInstance->InitializeSourceManager( 162 | FrontendInputFile(SrcFileName, IK))) { 163 | ErrorMsg = "Cannot open source file!"; 164 | return false; 165 | } 166 | return true; 167 | } 168 | 169 | void CheckerManager::printCheckerOptions() 170 | { 171 | CheckerAssert(CheckerManager::Instance); 172 | 173 | std::map::iterator I, E; 174 | for (I = Instance->CheckersMap.begin(), 175 | E = Instance->CheckersMap.end(); 176 | I != E; ++I) { 177 | (*I).second->printCmdOpts(); 178 | } 179 | } 180 | 181 | void CheckerManager::Finalize() 182 | { 183 | CheckerAssert(CheckerManager::Instance); 184 | 185 | std::map::iterator I, E; 186 | for (I = Instance->CheckersMap.begin(), 187 | E = Instance->CheckersMap.end(); 188 | I != E; ++I) { 189 | // CurrentCheckerImpl will be freed by ClangInstance 190 | if ((*I).second != Instance->CurrentCheckerImpl) 191 | delete (*I).second; 192 | } 193 | if (Instance->CheckersMapPtr) 194 | delete Instance->CheckersMapPtr; 195 | 196 | delete Instance->ClangInstance; 197 | 198 | delete Instance; 199 | Instance = NULL; 200 | } 201 | 202 | // Currently only check macro definitions and inclusion directives, 203 | // which include #include, #import, #include_next and #include_macros. 204 | // If we need, will check on others such as #if, #pragma etc. 205 | bool CheckerManager::hasPPDirective(PreprocessingRecord &PPCallbacks, 206 | std::string &ErrorMsg) 207 | { 208 | ErrorMsg = ""; 209 | SourceManager &SrcMgr = ClangInstance->getSourceManager(); 210 | FileID FID = SrcMgr.getMainFileID(); 211 | 212 | for (PreprocessingRecord::iterator I = PPCallbacks.local_begin(), 213 | E = PPCallbacks.local_end(); I != E; ++I) { 214 | const PreprocessedEntity *PE = (*I); 215 | PreprocessedEntity::EntityKind K = PE->getKind(); 216 | if (K == PreprocessedEntity::MacroDefinitionKind) { 217 | if (!PPCallbacks.isEntityInFileID(I, FID)) { 218 | // llvm::outs() << MDName << "\n"; 219 | continue; 220 | } 221 | 222 | const MacroDefinition *MD = dyn_cast(PE); 223 | std::string MDName = MD->getName()->getName(); 224 | // skip ACCESS_ONCE macro 225 | if (MDName == "ACCESS_ONCE") 226 | continue; 227 | 228 | ErrorMsg = "Has macro definition directive:" + MDName; 229 | return true; 230 | } 231 | if (K == PreprocessedEntity::InclusionDirectiveKind) { 232 | const InclusionDirective *IncDirective = 233 | dyn_cast(PE); 234 | std::string Str = ""; 235 | InclusionDirective::InclusionKind IncK = IncDirective->getKind(); 236 | switch (IncK) { 237 | case InclusionDirective::Include: 238 | Str = "#include"; 239 | break; 240 | case InclusionDirective::Import: 241 | Str = "#import"; 242 | break; 243 | case InclusionDirective::IncludeNext: 244 | Str = "#include_next"; 245 | break; 246 | case InclusionDirective::IncludeMacros: 247 | Str = "#__include_macros"; 248 | break; 249 | default: 250 | CheckerAssert(0 && "Unknown InclusionKind!"); 251 | return true; 252 | } 253 | Str += " "; 254 | Str += IncDirective->getFileName(); 255 | ErrorMsg = "Has inclusion directive:" + Str; 256 | return true; 257 | } 258 | } 259 | return false; 260 | } 261 | 262 | int CheckerManager::doChecking(std::string &ErrorMsg) 263 | { 264 | Preprocessor &PP = ClangInstance->getPreprocessor(); 265 | PreprocessingRecord *PPCallbacks = 266 | new PreprocessingRecord(ClangInstance->getSourceManager()); 267 | PP.addPPCallbacks(PPCallbacks); 268 | 269 | ClangInstance->createSema(TU_Complete, 0); 270 | ClangInstance->getDiagnostics().setSuppressAllDiagnostics(true); 271 | #if 0 272 | ClangInstance->getDiagnostics().setSuppressAllDiagnostics(false); 273 | if (ClangInstance->getDiagnostics().hasErrorOccurred() || 274 | ClangInstance->getDiagnostics().hasFatalErrorOccurred()) { 275 | CheckerAssert(0 && "Fatal error during checing!"); 276 | } 277 | #endif 278 | 279 | ParseAST(ClangInstance->getSema()); 280 | ClangInstance->getDiagnosticClient().EndSourceFile(); 281 | 282 | if (hasPPDirective(*PPCallbacks, ErrorMsg)) { 283 | return -1; 284 | } 285 | if (!CurrentCheckerImpl->isSuccess(ErrorMsg)) 286 | return -1; 287 | return 0; 288 | } 289 | 290 | bool CheckerManager::handleCheckerCmdOpt(const std::string &Arg) 291 | { 292 | if (!CurrentCheckerImpl) 293 | return false; 294 | return CurrentCheckerImpl->handleCmdOpt(Arg); 295 | } 296 | 297 | bool CheckerManager::verify(std::string &ErrorMsg) 298 | { 299 | if (!CurrentCheckerImpl) { 300 | ErrorMsg = "Empty checker instance!"; 301 | return false; 302 | } 303 | if (SrcFileName.empty()) { 304 | ErrorMsg = "No input file!"; 305 | return false; 306 | } 307 | return true; 308 | } 309 | 310 | void CheckerManager::registerChecker( 311 | const char *CheckerName, 312 | Checker *CheckerImpl) 313 | { 314 | if (!CheckerManager::CheckersMapPtr) { 315 | CheckerManager::CheckersMapPtr = 316 | new std::map(); 317 | } 318 | 319 | assert((CheckerImpl != NULL) && "NULL Checker!"); 320 | assert((CheckerManager::CheckersMapPtr->find(CheckerName) == 321 | CheckerManager::CheckersMapPtr->end()) && 322 | "Duplicated checker!"); 323 | (*CheckerManager::CheckersMapPtr)[CheckerName] = CheckerImpl; 324 | } 325 | 326 | void CheckerManager::printCheckers() 327 | { 328 | llvm::outs() << "Registered Checkers:\n"; 329 | 330 | std::map::iterator I, E; 331 | for (I = CheckersMap.begin(), 332 | E = CheckersMap.end(); 333 | I != E; ++I) { 334 | llvm::outs() << " [" << (*I).first << "]: "; 335 | llvm::outs() << (*I).second->getDescription() << "\n"; 336 | } 337 | } 338 | 339 | void CheckerManager::printCheckerNames() 340 | { 341 | std::map::iterator I, E; 342 | for (I = CheckersMap.begin(), 343 | E = CheckersMap.end(); 344 | I != E; ++I) { 345 | llvm::outs() << (*I).first << "\n"; 346 | } 347 | } 348 | 349 | CheckerManager::CheckerManager() 350 | : CurrentCheckerImpl(NULL), 351 | SrcFileName(""), 352 | ClangInstance(NULL), 353 | Force32BitTarget(false) 354 | { 355 | // Nothing to do 356 | } 357 | 358 | CheckerManager::~CheckerManager() 359 | { 360 | // Nothing to do 361 | } 362 | 363 | -------------------------------------------------------------------------------- /volatile_checker/VolatileAddressChecker.cpp: -------------------------------------------------------------------------------- 1 | #include "VolatileAddressChecker.h" 2 | 3 | #include 4 | #include "clang/AST/RecursiveASTVisitor.h" 5 | #include "clang/AST/ASTContext.h" 6 | #include "clang/Lex/Lexer.h" 7 | #include "clang/AST/RecordLayout.h" 8 | 9 | #include "CheckerManager.h" 10 | 11 | using namespace clang; 12 | using namespace llvm; 13 | 14 | static const char *DescriptionMsg = 15 | "output the offset and size of each volatile var, \ 16 | including struct fields\n"; 17 | 18 | static RegisterChecker 19 | C("volatile-address", DescriptionMsg); 20 | 21 | class AccessOnceVarCollectionVisitor : public 22 | RecursiveASTVisitor { 23 | 24 | public: 25 | explicit AccessOnceVarCollectionVisitor(VolatileAddressChecker *Instance) 26 | : ConsumerInstance(Instance) 27 | { } 28 | 29 | bool VisitDeclRefExpr(DeclRefExpr *DRE); 30 | 31 | private: 32 | VolatileAddressChecker *ConsumerInstance; 33 | }; 34 | 35 | bool AccessOnceVarCollectionVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) 36 | { 37 | ConsumerInstance->handleOneDeclRefExpr(DRE); 38 | return true; 39 | } 40 | 41 | class VolatileAddressVisitor : public 42 | RecursiveASTVisitor { 43 | 44 | public: 45 | explicit VolatileAddressVisitor(VolatileAddressChecker *Instance) 46 | : ConsumerInstance(Instance) 47 | { } 48 | 49 | bool VisitVarDecl(VarDecl *VD); 50 | 51 | private: 52 | VolatileAddressChecker *ConsumerInstance; 53 | }; 54 | 55 | bool VolatileAddressVisitor::VisitVarDecl(VarDecl *VD) 56 | { 57 | if (VD->hasLocalStorage()) 58 | return true; 59 | 60 | ConsumerInstance->handleOneVarDecl(VD); 61 | return true; 62 | } 63 | 64 | void VolatileAddressChecker::Initialize(ASTContext &context) 65 | { 66 | Checker::Initialize(context); 67 | } 68 | 69 | void VolatileAddressChecker::HandleTranslationUnit(ASTContext &Ctx) 70 | { 71 | if (AccessOnceVarMode != ACC_VARS_NONE) { 72 | AccessOnceVarCollectionVisitor V(this); 73 | V.TraverseDecl(Ctx.getTranslationUnitDecl()); 74 | } 75 | 76 | VolatileAddressVisitor Visitor(this); 77 | Visitor.TraverseDecl(Ctx.getTranslationUnitDecl()); 78 | 79 | Ctx.getDiagnostics().setSuppressAllDiagnostics(false); 80 | 81 | if (Ctx.getDiagnostics().hasErrorOccurred() || 82 | Ctx.getDiagnostics().hasFatalErrorOccurred()) { 83 | CheckerAssert(0 && "Fatal error during checing!"); 84 | } 85 | 86 | if (DumpAllVars) 87 | dumpAddrsToFile(AllNonVolAddrs, AllVarsOutFile); 88 | 89 | if (OutFile == "") 90 | dumpAddresses(AllVolAddrs, llvm::outs()); 91 | else 92 | dumpAddrsToFile(AllVolAddrs, OutFile); 93 | } 94 | 95 | void VolatileAddressChecker::dumpAddrsToFile(const std::vector &Addrs, 96 | const std::string &FN) 97 | { 98 | std::string Err; 99 | llvm::raw_fd_ostream *Out = 100 | new llvm::raw_fd_ostream(FN.c_str(), Err); 101 | CheckerAssert(Err.empty() && "Cannot open output file!"); 102 | dumpAddresses(Addrs, *Out); 103 | delete Out; 104 | } 105 | 106 | void VolatileAddressChecker::dumpAddresses(const std::vector &Addrs, 107 | llvm::raw_ostream &OS) 108 | { 109 | for (std::vector::const_iterator I = Addrs.begin(), 110 | E = Addrs.end(); I != E; ++I) { 111 | OS << (*I); 112 | } 113 | } 114 | 115 | void VolatileAddressChecker::addOneAddress(bool IsVol, 116 | bool IsBitField, 117 | const std::string &Name, 118 | uint64_t Offset, 119 | uint64_t Sz, 120 | const std::string &PtrStr) 121 | { 122 | CheckerAssert((UnionLevelCount >= 0) && "Invalid UnionLevelCount!"); 123 | 124 | std::stringstream SS; 125 | SS << Name << "; "; 126 | SS << Offset << "; "; 127 | SS << Sz << "; "; 128 | SS << PtrStr << "; "; 129 | if (IsBitField) 130 | SS << "bitfield\n"; 131 | else 132 | SS << "non-bitfield\n"; 133 | 134 | if (DumpAllVars) 135 | AllNonVolAddrs.push_back(SS.str()); 136 | // TODO: omit volatile unions for now 137 | if (UnionLevelCount > 0) 138 | return; 139 | 140 | if (IsVol) { 141 | AllVolAddrs.push_back(SS.str()); 142 | } 143 | } 144 | 145 | void VolatileAddressChecker::addOneVolatileAddress(const std::string &Name, 146 | uint64_t Offset, 147 | uint64_t Sz, 148 | const std::string &PtrStr) 149 | { 150 | // TODO: omit volatile unions for now 151 | if (UnionLevelCount > 0) 152 | return; 153 | 154 | std::stringstream SS; 155 | SS << Name << "; "; 156 | SS << Offset << "; "; 157 | SS << Sz << "; "; 158 | SS << PtrStr << "; "; 159 | SS << "non-bitfield" << "\n"; 160 | AllVolAddrs.push_back(SS.str()); 161 | } 162 | 163 | void VolatileAddressChecker::handleOneUnion(bool IsVol, 164 | const std::string &Prefix, 165 | uint64_t Offset, 166 | const RecordDecl *RD) 167 | { 168 | if (!RD->getDefinition()) 169 | return; 170 | 171 | const ASTRecordLayout &Info = Context->getASTRecordLayout(RD); 172 | unsigned Count = Info.getFieldCount(); (void)Count; 173 | uint64_t MaxSz = 0; 174 | const FieldDecl *MaxFD = NULL; 175 | 176 | for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 177 | I != E; ++I) { 178 | const FieldDecl *FD = (*I); 179 | uint64_t FieldSz; 180 | if (FD->isBitField()) 181 | FieldSz = FD->getBitWidthValue(*Context); 182 | else 183 | FieldSz = Context->getTypeSize(FD->getType()); 184 | 185 | if (FieldSz > MaxSz) { 186 | MaxSz = FieldSz; 187 | MaxFD = FD; 188 | } 189 | } 190 | if (!MaxFD || !MaxSz) 191 | return; 192 | 193 | QualType QT = MaxFD->getType(); 194 | IsVol = IsVol || QT.isVolatileQualified(); 195 | // TODO: skip volatile for now; 196 | if (IsVol) 197 | return; 198 | 199 | if (MaxFD->isBitField()) { 200 | addOneAddress(QT.isVolatileQualified(), 201 | true, 202 | Prefix + MaxFD->getNameAsString(), 203 | Offset, 204 | MaxSz, 205 | "non-pointer"); 206 | } 207 | else { 208 | UnionLevelCount++; 209 | handleOneDeclaratorDecl(IsVol, 210 | Prefix, 211 | Offset, 212 | MaxFD); 213 | UnionLevelCount--; 214 | CheckerAssert((UnionLevelCount >= 0) && "Bad UnionLevelCount"); 215 | } 216 | } 217 | 218 | void VolatileAddressChecker::handleOneStructure(bool IsVol, 219 | const std::string &Prefix, 220 | uint64_t Offset, 221 | const RecordDecl *RD) 222 | { 223 | if (!RD->getDefinition()) 224 | return; 225 | 226 | const ASTRecordLayout &Info = Context->getASTRecordLayout(RD); 227 | unsigned Count = Info.getFieldCount(); (void)Count; 228 | 229 | for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 230 | I != E; ++I) { 231 | const FieldDecl *FD = (*I); 232 | unsigned Idx = FD->getFieldIndex(); 233 | CheckerAssert((Idx < Count) && "Invalid Field Index!"); 234 | uint64_t Field_Off = Offset + Info.getFieldOffset(Idx); 235 | QualType QT = FD->getType(); 236 | bool IsVolFD = IsVol || QT.isVolatileQualified(); 237 | 238 | if (FD->isBitField()) { 239 | uint64_t Field_Sz = FD->getBitWidthValue(*Context); 240 | // omit zero-sz bitfield 241 | if (!Field_Sz) 242 | continue; 243 | 244 | addOneAddress(IsVolFD, 245 | true, 246 | Prefix + FD->getNameAsString(), 247 | Field_Off, 248 | Field_Sz, 249 | "non-pointer"); 250 | } 251 | else { 252 | handleOneDeclaratorDecl(IsVolFD, 253 | Prefix, 254 | Field_Off, 255 | FD); 256 | } 257 | } 258 | } 259 | 260 | void VolatileAddressChecker::handleOneArray(bool IsVol, 261 | const std::string &Prefix, 262 | uint64_t Offset, 263 | const ArrayType *AT) 264 | { 265 | // currently only handle ConstanceArrayType 266 | const ConstantArrayType *T = dyn_cast(AT); 267 | if (!T) 268 | return; 269 | 270 | QualType ElemQT = Context->getBaseElementType(T); 271 | const Type *ElemTy = ElemQT.getTypePtr(); 272 | const RecordType *ST = ElemTy->getAsStructureType(); 273 | const RecordType *UT = ElemTy->getAsUnionType(); 274 | if (!ST && !UT) { 275 | IsVol = IsVol || ElemQT.isVolatileQualified(); 276 | addOneAddress(IsVol, false, Prefix, Offset, 277 | Context->getTypeSize(T), 278 | getPointerStr(Context->getBaseElementType(T))); 279 | return; 280 | } 281 | 282 | uint64_t Count = Context->getConstantArrayElementCount(T); 283 | for (uint64_t I = 0; I < Count; ++I) { 284 | uint64_t Elem_Off = Offset + I * Context->getTypeSize(ElemTy); 285 | std::stringstream SS; 286 | SS << I; 287 | if (ST) { 288 | handleOneStructure(IsVol, "(" + Prefix + SS.str() + ").", 289 | Elem_Off, ST->getDecl()); 290 | } 291 | else { 292 | handleOneUnion(IsVol, "(" + Prefix + SS.str() + ").", 293 | Elem_Off, UT->getDecl()); 294 | } 295 | } 296 | } 297 | 298 | void VolatileAddressChecker::handleOneDeclaratorDecl(bool IsVol, 299 | const std::string &Prefix, 300 | uint64_t Offset, 301 | const DeclaratorDecl *DD) 302 | { 303 | QualType QT = DD->getType(); 304 | IsVol = IsVol || QT.isVolatileQualified(); 305 | 306 | #if 0 307 | if (IsVol) { 308 | addOneAddress(IsVol, 309 | false, 310 | Prefix + DD->getNameAsString(), 311 | Offset, 312 | Context->getTypeSize(QT), 313 | getPointerStr(QT)); 314 | return; 315 | } 316 | #endif 317 | 318 | const Type *Ty = QT.getTypePtr(); 319 | if (const RecordType *RT = Ty->getAsStructureType()) { 320 | const RecordDecl *RD = RT->getDecl(); 321 | handleOneStructure(IsVol, Prefix + DD->getNameAsString() + ".", Offset, RD); 322 | return; 323 | } 324 | 325 | if (const RecordType *RT = Ty->getAsUnionType()) { 326 | const RecordDecl *RD = RT->getDecl(); 327 | handleOneUnion(IsVol, Prefix + DD->getNameAsString() + ".", Offset, RD); 328 | return; 329 | } 330 | 331 | if (const ArrayType *AT = Context->getAsArrayType(QT)) { 332 | handleOneArray(IsVol, Prefix + DD->getNameAsString() + "+", Offset, AT); 333 | return; 334 | } 335 | 336 | // CheckerAssert(!IsVol && "No volatile var here!"); 337 | addOneAddress(IsVol, 338 | false, 339 | Prefix + DD->getNameAsString(), 340 | Offset, 341 | Context->getTypeSize(QT), 342 | getPointerStr(QT)); 343 | } 344 | 345 | void VolatileAddressChecker::handleOneVarDecl(const VarDecl *VD) 346 | { 347 | if (!VD->isThisDeclarationADefinition()) 348 | return; 349 | 350 | const VarDecl *CanonicalVD = VD->getCanonicalDecl(); 351 | if (VisitedVars.count(CanonicalVD)) 352 | return; 353 | VisitedVars.insert(CanonicalVD); 354 | 355 | if ((AccessOnceVarMode == ACC_VARS_NONE) && 356 | AccessOnceVars.count(CanonicalVD)) 357 | return; 358 | if ((AccessOnceVarMode == ACC_VARS_ONLY) && 359 | !AccessOnceVars.count(CanonicalVD)) 360 | return; 361 | 362 | if (AccessOnceVars.count(CanonicalVD)) { 363 | QualType QT = VD->getType(); 364 | // ISSUE: we may also need to consider a struct var 365 | // where the struct has bit-fields. 366 | // for example, invoke handleOneDeclarationDecl with 367 | // true IsVol 368 | addOneVolatileAddress(VD->getNameAsString(), 369 | 0, 370 | Context->getTypeSize(QT), 371 | getPointerStr(QT)); 372 | return; 373 | } 374 | 375 | handleOneDeclaratorDecl(false, "", 0, VD); 376 | } 377 | 378 | std::string VolatileAddressChecker::getPointerStr(const QualType &QT) 379 | { 380 | const Type *Ty; 381 | if (const ArrayType *AT = Context->getAsArrayType(QT)) 382 | Ty = Context->getBaseElementType(AT).getTypePtr(); 383 | else 384 | Ty = QT.getTypePtr(); 385 | 386 | if (Ty->isPointerType()) 387 | return "pointer"; 388 | else 389 | return "non-pointer"; 390 | } 391 | 392 | void VolatileAddressChecker::handleOneDeclRefExpr(const DeclRefExpr *DRE) 393 | { 394 | const VarDecl *VD = dyn_cast(DRE->getDecl()); 395 | if (!VD) 396 | return; 397 | 398 | SourceLocation Loc = DRE->getLocation(); 399 | // access is outside a macro 400 | if (!Loc.isMacroID()) 401 | return; 402 | 403 | StringRef M = 404 | Lexer::getImmediateMacroName(Loc, 405 | Context->getSourceManager(), 406 | Context->getLangOpts()); 407 | 408 | if (M == "ACCESS_ONCE") { 409 | const VarDecl *CanonicalVD = VD->getCanonicalDecl(); 410 | AccessOnceVars.insert(CanonicalVD); 411 | } 412 | } 413 | 414 | void VolatileAddressChecker::printCmdOpts() 415 | { 416 | llvm::outs() << "option[s] supported in checker[" << Name << "]:\n"; 417 | llvm::outs() << " --handle-access-once-vars=[all|none|only]\n"; 418 | llvm::outs() << " where\n"; 419 | llvm::outs() << " all: output volatile vars and vars accessed through "; 420 | llvm::outs() << "ACCESS_ONCE macro [default]\n"; 421 | llvm::outs() << " none: exclude vars accessed through ACCESS_ONCE\n"; 422 | llvm::outs() << " only: only output the addresses of vars accessed "; 423 | llvm::outs() << "through ACCESS_ONCE macro\n"; 424 | llvm::outs() << " --address-output=\n"; 425 | llvm::outs() << " specifies where to output the result [default:stdout]\n"; 426 | llvm::outs() << " --all-vars-output=\n"; 427 | llvm::outs() << " specifies where to output the addresses/offsets of all vars\n"; 428 | } 429 | 430 | bool VolatileAddressChecker::setAccessOnceVarMode(const std::string &ModeStr) 431 | { 432 | if (ModeStr == "all") 433 | AccessOnceVarMode = ACC_VARS_ALL; 434 | else if (ModeStr == "none") 435 | AccessOnceVarMode = ACC_VARS_NONE; 436 | else if (ModeStr == "only") 437 | AccessOnceVarMode = ACC_VARS_ONLY; 438 | else 439 | return false; 440 | 441 | return true; 442 | } 443 | 444 | bool VolatileAddressChecker::setOutput(const std::string &OutFile) 445 | { 446 | this->OutFile = OutFile; 447 | return true; 448 | } 449 | 450 | bool VolatileAddressChecker::handleValueCmdOpt(const std::string &ArgStr, 451 | size_t SepPos) 452 | { 453 | if ((SepPos < 1) || (SepPos >= ArgStr.length())) 454 | return false; 455 | 456 | std::string ArgName, ArgValue; 457 | 458 | ArgName = ArgStr.substr(0, SepPos); 459 | ArgValue = ArgStr.substr(SepPos+1); 460 | 461 | if (!ArgName.compare("handle-access-once-vars")) { 462 | return setAccessOnceVarMode(ArgValue); 463 | } 464 | else if (!ArgName.compare("address-output")) { 465 | return setOutput(ArgValue); 466 | } 467 | else if (!ArgName.compare("all-vars-output")) { 468 | return setAllVarsOutput(ArgValue); 469 | } 470 | else { 471 | return false; 472 | } 473 | } 474 | 475 | VolatileAddressChecker::~VolatileAddressChecker() 476 | { 477 | 478 | } 479 | 480 | -------------------------------------------------------------------------------- /creduce/showme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## 3 | ## Copyright (c) 2013 The University of Utah 4 | ## All rights reserved. 5 | ## 6 | ## This is a predicate script for C-Reduce, for reducing programs that reveal 7 | ## "volatile defects" in C compilers. 8 | ## 9 | ## This script judges that the file named by its argument is interesting if: 10 | ## 11 | ## + it appears to be a valid, strictly conforming C program 12 | ## + the program compiles with both "gcc -O0" and "gcc -O2" 13 | ## + the output of the two compiled programs is the same 14 | ## + the "volatile access checksums" of the two compiled programs are 15 | ## different 16 | ## 17 | 18 | ############################################################################### 19 | 20 | if test -z "$VOLTEST_HOME"; then 21 | echo $0: '$VOLTEST_HOME' is not set 22 | exit 1 23 | fi 24 | 25 | ############################################################################### 26 | 27 | ## Information about the test setup: the compilers under test and the 28 | ## environment for compiling and validating test programs. 29 | 30 | CCUT1="gcc-4.4 -O0" 31 | CCUT2="gcc-4.4 -O2" 32 | 33 | CPPFLAGS="-DINLINE= -DCSMITH_MINIMAL -DWRAP_VOLATILES=0 -DNOT_PRINT_CHECKSUM -I/disk2/randtest/src/csmith/runtime" 34 | 35 | # PIN_HOME: inherit this from the environment. 36 | 37 | TIMEOUT=5 38 | 39 | TIMEOUT_FRAMAC=125 40 | 41 | ############################################################################### 42 | 43 | ## Environment configuration. 44 | 45 | CLANG=/disk2/randtest/src/llvm-install/bin/clang 46 | CMP=cmp 47 | FRAMAC=/usr/bin/frama-c 48 | GCC=gcc 49 | GREP=grep 50 | RM=rm 51 | 52 | FIND_COMMON_VARS="$VOLTEST_HOME"/creduce/find-common-vars.pl 53 | 54 | RUNSAFELY=RunSafely 55 | 56 | VOL_CHECKER=/disk2/randtest/src/volatile_checker/volatile_checker 57 | VOL_ADDR_GEN=/disk2/randtest/src/volatile_pintrace/gen_volatile_addr.pl 58 | 59 | ############################################################################### 60 | 61 | ## Options. 62 | 63 | # If `quiet' is true, this script is silent when the mutant is found to be 64 | # uninteresting --- i.e., uncompilable, sematically suspect, or without the 65 | # behavior we're looking for. 66 | quiet=0 67 | 68 | # If `neat' is true, this script deletes the temporary files it creates. 69 | neat=0 70 | 71 | # If `debug' is true, this script prints debugging output. 72 | debug=0 73 | 74 | ############################################################################### 75 | 76 | ## Parse and validate the command-line arguments. 77 | 78 | if [ $# -ne 1 ]; then 79 | echo "usage: $0 filename" 80 | exit 1 81 | fi 82 | 83 | filename="$1" 84 | 85 | if test ! -e "$filename"; then 86 | echo "$0: file \"$filename\" does not exist" 87 | exit 1 88 | fi 89 | if test ! -f "$filename"; then 90 | echo "$0: \"$filename\" is not a regular file" 91 | exit 1 92 | fi 93 | if test ! -r "$filename"; then 94 | echo "$0: file \"$filename\" is not readable" 95 | exit 1 96 | fi 97 | 98 | ############################################################################### 99 | 100 | ## Validate the environment. 101 | 102 | if test -z "$PIN_HOME"; then 103 | echo "$0: environment variable \$PIN_HOME is not set" 104 | exit 1 105 | fi 106 | if test ! -e "$PIN_HOME/pin.sh"; then 107 | echo "$0: \"\$PIN_HOME/pin.sh\" does not exist" 108 | exit 1 109 | fi 110 | 111 | ############################################################################### 112 | 113 | ## Initialization. 114 | 115 | DEBUG_ECHO=echo 116 | if [ $debug -ne 0 ]; then 117 | DEBUG_ECHO=: 118 | fi 119 | 120 | QUIET_ECHO=echo 121 | if [ $quiet -ne 0 ]; then 122 | QUIET_ECHO=: 123 | fi 124 | 125 | NEAT_RM_OUTS="$RM -f *out*.exe *out*.txt framac-prog.c" 126 | if [ $neat -eq 0 ]; then 127 | NEAT_RM_OUTS=: 128 | fi 129 | 130 | # ulimit -t 1 131 | # ulimit -v 2000000 132 | 133 | # Remove any lingering temporary files. 134 | $NEAT_RM_OUTS 135 | 136 | ############################################################################### 137 | 138 | ## Use Clang to weed out "broken" programs. 139 | 140 | clang_out=clang-out.txt 141 | 142 | $CLANG -c -pedantic -Wall -O0 $CPPFLAGS \ 143 | "$filename" \ 144 | -o /dev/null \ 145 | > "$clang_out" 2>&1 146 | if [ $? -ne 0 ]; then 147 | $QUIET_ECHO "$0: clang could not compile \"$filename\"" 148 | $NEAT_RM_OUTS 149 | exit 1 150 | fi 151 | 152 | $GREP -q \ 153 | -e 'incompatible redeclaration' \ 154 | -e 'ordered comparison between pointer' \ 155 | -e 'eliding middle term' \ 156 | -e 'end of non-void function' \ 157 | -e 'invalid in C99' \ 158 | -e 'specifies type' \ 159 | -e 'should return a value' \ 160 | -e 'too few argument' \ 161 | -e 'too many argument' \ 162 | -e "return type of 'main" \ 163 | -e 'uninitialized' \ 164 | -e 'incompatible pointer to' \ 165 | -e 'incompatible integer to' \ 166 | -e 'type specifier missing' \ 167 | -e 'discards qualifiers' \ 168 | "$clang_out" 169 | if [ $? -ne 1 ]; then 170 | $QUIET_ECHO "$0: unacceptable output warning from clang" 171 | $NEAT_RM_OUTS 172 | exit 1 173 | fi 174 | 175 | ############################################################################### 176 | 177 | ## Use GCC to weed out "broken" programs. 178 | 179 | gcc_out=gcc-out.txt 180 | 181 | $GCC -c -Wall -Wextra -O1 $CPPFLAGS \ 182 | "$filename" \ 183 | -o /dev/null \ 184 | > "$gcc_out" 2>&1 185 | if [ $? -ne 0 ]; then 186 | $QUIET_ECHO "$0: gcc could not compile \"$filename\"" 187 | $NEAT_RM_OUTS 188 | exit 1 189 | fi 190 | 191 | $GREP -q \ 192 | -e 'uninitialized' \ 193 | -e 'control reaches end' \ 194 | -e 'no semicolon at end' \ 195 | -e 'incompatible pointer' \ 196 | -e 'cast from pointer to integer' \ 197 | -e 'ordered comparison of pointer with integer' \ 198 | -e 'declaration does not declare anything' \ 199 | -e 'expects type' \ 200 | -e 'assumed to have one element' \ 201 | -e 'division by zero' \ 202 | -e 'pointer from integer' \ 203 | -e 'incompatible implicit' \ 204 | -e 'excess elements in struct initializer' \ 205 | -e 'comparison between pointer and integer' \ 206 | -e "discards '.*' qualifier" \ 207 | "$gcc_out" 208 | if [ $? -ne 1 ]; then 209 | $QUIET_ECHO "$0: unacceptable output warning from gcc" 210 | $NEAT_RM_OUTS 211 | exit 1 212 | fi 213 | 214 | ############################################################################### 215 | 216 | ## Use our volatile_checker tool to weed out "broken" programs. 217 | 218 | checker_out=checker-out.txt 219 | 220 | $VOL_CHECKER --checker=volatile-reorder "$filename" > "$checker_out" 2>&1 221 | if [ $? -ne 0 ]; then 222 | $QUIET_ECHO "$0: \"$filename\" contains ill-ordered volatile accesses" 223 | $NEAT_RM_OUTS 224 | exit 1 225 | fi 226 | 227 | ############################################################################### 228 | 229 | ## Use Clang's address sanitizer to weed out "broken" programs. 230 | 231 | asan_exe=clang-asan-out.exe 232 | asan_out=clang-asan-out.txt 233 | 234 | $CLANG -O0 -fsanitize=address $CPPFLAGS \ 235 | "$filename" \ 236 | -o "$asan_exe" \ 237 | > "$asan_out" 2>&1 238 | if [ $? -ne 0 ]; then 239 | $QUIET_ECHO "$0: clang -fsanitize=address could not compile \"$filename\"" 240 | $NEAT_RM_OUTS 241 | exit 1 242 | fi 243 | 244 | # The output of the program produced by clang -fsanitize=address. 245 | asan_exe_out=clang-asan-exe-out.txt 246 | 247 | $RUNSAFELY $TIMEOUT 1 /dev/null "$asan_exe_out" \ 248 | "$asan_exe" \ 249 | > /dev/null 2>&1 250 | if [ $? -ne 0 ]; then 251 | $QUIET_ECHO "$0: clang -fsanitize=address: program is unsanitary" 252 | $NEAT_RM_OUTS 253 | exit 1 254 | fi 255 | 256 | ############################################################################### 257 | 258 | ## Use Frama-C to weed out "broken" programs. 259 | 260 | framac_filename=framac-prog.c 261 | framac_out=framac-out.txt 262 | 263 | # For whatever reason, Frama-C does not like `main' to have arguments! 264 | # 265 | cp "$filename" "$framac_filename" 266 | if [ $? -ne 0 ]; then 267 | $QUIET_ECHO "$0: failed to copy \"$filename\" for Frama-C" 268 | $NEAT_RM_OUTS 269 | exit 1 270 | fi 271 | 272 | perl -pi \ 273 | -e 's/int main \(int argc, char\* argv\[\]\)/int argc; char **argv; int main (void)/' \ 274 | "$framac_filename" 275 | if [ $? -ne 0 ]; then 276 | $QUIET_ECHO "$0: failed to edit \"$framac_filename\" for Frama-C" 277 | $NEAT_RM_OUTS 278 | exit 1 279 | fi 280 | 281 | # XXX: `RunSafely' has some serious problems with shell quoting! 282 | # Note the funky (basically, wrong) quoting of the -cpp-command value, which is 283 | # needed to get it through RunSafely. Fix RunSafely. 284 | # 285 | $RUNSAFELY $TIMEOUT_FRAMAC 1 /dev/null "$framac_out" \ 286 | $FRAMAC \ 287 | -cpp-command \"gcc -C -Dvolatile= -E -I.\" \ 288 | -val-signed-overflow-alarms -val -stop-at-first-alarm -no-val-show-progress \ 289 | -machdep x86_64 \ 290 | -obviously-terminates \ 291 | -precise-unions \ 292 | "$framac_filename" \ 293 | > /dev/null 2>&1 294 | if [ $? -ne 0 ]; then 295 | $QUIET_ECHO "$0: Frama-C failed to vet the program" 296 | $NEAT_RM_OUTS 297 | exit 1 298 | fi 299 | 300 | $GREP -q \ 301 | -e 'user error' \ 302 | -e 'assert' \ 303 | "$framac_out" 304 | if [ $? -ne 1 ]; then 305 | $QUIET_ECHO "$0: unacceptable output warning from Frama-C" 306 | $NEAT_RM_OUTS 307 | exit 1 308 | fi 309 | 310 | ############################################################################### 311 | 312 | ## Extract information about the volatiles (and all variables) in the program. 313 | 314 | all_vars=all-vars-out.txt 315 | vol_vars=vol-vars-out.txt 316 | 317 | $VOL_CHECKER \ 318 | --checker=volatile-address \ 319 | --all-vars-output="$all_vars" \ 320 | "$filename" \ 321 | > "$vol_vars" 2>&1 322 | if [ $? -ne 0 ]; then 323 | $QUIET_ECHO "$0: volatile-variable extractor failed" 324 | $NEAT_RM_OUTS 325 | exit 1 326 | fi 327 | 328 | ############################################################################### 329 | 330 | ## Compile the mutant using first compiler under test. 331 | 332 | # The outputs of the first compiler under test. 333 | ccut1_exe=ccut1-out.exe 334 | ccut1_out=ccut1-out.txt 335 | 336 | $CCUT1 \ 337 | -w $CPPFLAGS \ 338 | "$filename" \ 339 | -o "$ccut1_exe" \ 340 | > "$ccut1_out" 2>&1 341 | if [ $? -ne 0 ]; then 342 | $QUIET_ECHO "$0: $CCUT1: could not compile \"$filename\"" 343 | $NEAT_RM_OUTS 344 | exit 1 345 | fi 346 | 347 | # The addresses of volatile objects (and normal objects, too) in the program 348 | # produced by the first compiler under test. 349 | ccut1_exe_all_addrs=ccut1-exe-all-addrs-out.txt 350 | ccut1_exe_vol_addrs=ccut1-exe-vol-addrs-out.txt 351 | 352 | $VOL_ADDR_GEN \ 353 | --vars-file="$vol_vars" \ 354 | --all-vars-file="$all_vars" \ 355 | --all-var-addrs-output="$ccut1_exe_all_addrs" \ 356 | "$ccut1_exe" \ 357 | > "$ccut1_exe_vol_addrs" 2>&1 358 | if [ $? -ne 0 ]; then 359 | $QUIET_ECHO "$0: $CCUT1: volatile-address extractor failed" 360 | $NEAT_RM_OUTS 361 | exit 1 362 | fi 363 | 364 | ############################################################################### 365 | 366 | ## Compile the mutant using second compiler under test. 367 | 368 | # The outputs of the second compiler under test. 369 | ccut2_exe=ccut2-out.exe 370 | ccut2_out=ccut2-out.txt 371 | 372 | $CCUT2 \ 373 | -w $CPPFLAGS \ 374 | "$filename" \ 375 | -o "$ccut2_exe" \ 376 | > "$ccut2_out" 2>&1 377 | if [ $? -ne 0 ]; then 378 | $QUIET_ECHO "$0: $CCUT2: could not compile \"$filename\"" 379 | $NEAT_RM_OUTS 380 | exit 1 381 | fi 382 | 383 | # The addresses of volatile objects (and normal objects, too) in the program 384 | # produced by the second compiler under test. 385 | ccut2_exe_all_addrs=ccut2-exe-all-addrs-out.txt 386 | ccut2_exe_vol_addrs=ccut2-exe-vol-addrs-out.txt 387 | 388 | $VOL_ADDR_GEN \ 389 | --vars-file="$vol_vars" \ 390 | --all-vars-file="$all_vars" \ 391 | --all-var-addrs-output="$ccut2_exe_all_addrs" \ 392 | "$ccut2_exe" \ 393 | > "$ccut2_exe_vol_addrs" 2>&1 394 | if [ $? -ne 0 ]; then 395 | $QUIET_ECHO "$0: $CCUT2: volatile-address extractor failed" 396 | $NEAT_RM_OUTS 397 | exit 1 398 | fi 399 | 400 | ############################################################################### 401 | 402 | ## Find the set of globals that are visible in both compiled programs. 403 | ## Pin can compute the value checksum only over the state that is visible 404 | ## in both programs. 405 | 406 | # The addresses of "common" objects in each compiled program. A "common" 407 | # object is one that appears in both of the compiled programs, although it 408 | # might have different locations across the two programs. 409 | ccut1_exe_com_addrs=ccut1-exe-com-addrs-out.txt 410 | ccut2_exe_com_addrs=ccut2-exe-com-addrs-out.txt 411 | 412 | $FIND_COMMON_VARS "$ccut1_exe_all_addrs" "$ccut2_exe_all_addrs" \ 413 | > "$ccut1_exe_com_addrs" 2>&1 414 | if [ $? -ne 0 ]; then 415 | $QUIET_ECHO "$0: $CCUT1: common-object extractor failed" 416 | $NEAT_RM_OUTS 417 | exit 1 418 | fi 419 | 420 | $FIND_COMMON_VARS "$ccut2_exe_all_addrs" "$ccut1_exe_all_addrs" \ 421 | > "$ccut2_exe_com_addrs" 2>&1 422 | if [ $? -ne 0 ]; then 423 | $QUIET_ECHO "$0: $CCUT2: common-object extractor failed" 424 | $NEAT_RM_OUTS 425 | exit 1 426 | fi 427 | 428 | ############################################################################### 429 | 430 | ## Run the mutant using the first compiler under test. 431 | 432 | # The output of the program produced by the first compiler under test. 433 | ccut1_exe_out=ccut1-exe-out.txt 434 | 435 | $RUNSAFELY $TIMEOUT 1 /dev/null "$ccut1_exe_out" \ 436 | "$PIN_HOME/pin.sh" \ 437 | -injection child \ 438 | -t "$PIN_HOME/source/tools/ManualExamples/obj-intel64/pinatrace.so" \ 439 | -vol_input "$ccut1_exe_vol_addrs" \ 440 | -all_vars_input "$ccut1_exe_com_addrs" \ 441 | -output_mode checksum \ 442 | -- "$ccut1_exe" \ 443 | > /dev/null 2>&1 444 | if [ $? -ne 0 ]; then 445 | $QUIET_ECHO "$0: $CCUT1: compiled program failed to run correctly" 446 | $NEAT_RM_OUTS 447 | exit 1 448 | fi 449 | 450 | # The regular and volatile checksums of the program produced by the first 451 | # compiler under test. 452 | ccut1_exe_chk=ccut1-exe-out-chk.txt 453 | ccut1_exe_vchk=ccut1-exe-out-vchk.txt 454 | 455 | $GREP -e "^checksum" "$ccut1_exe_out" > "$ccut1_exe_chk" 456 | # $? is 0 is lines were matched; 1 if no lines matched; >1 if error. 457 | if [ $? -ne 0 ]; then 458 | $QUIET_ECHO "$0: $CCUT1: compiled program produced no checksum" 459 | $NEAT_RM_OUTS 460 | exit 1 461 | fi 462 | 463 | $GREP -e "^vol_access_checksum" "$ccut1_exe_out" > "$ccut1_exe_vchk" 464 | # $? is 0 is lines were matched; 1 if no lines matched; >1 if error. 465 | if [ $? -ne 0 ]; then 466 | $QUIET_ECHO "$0: $CCUT1: compiled program produced no volatile checksum" 467 | $NEAT_RM_OUTS 468 | exit 1 469 | fi 470 | 471 | ############################################################################### 472 | 473 | ## Run the mutant using the second compiler under test. 474 | 475 | # The output of the program produced by the second compiler under test. 476 | ccut2_exe_out=ccut2-exe-out.txt 477 | 478 | $RUNSAFELY $TIMEOUT 1 /dev/null "$ccut2_exe_out" \ 479 | "$PIN_HOME/pin.sh" \ 480 | -injection child \ 481 | -t "$PIN_HOME/source/tools/ManualExamples/obj-intel64/pinatrace.so" \ 482 | -vol_input "$ccut2_exe_vol_addrs" \ 483 | -all_vars_input "$ccut2_exe_com_addrs" \ 484 | -output_mode checksum \ 485 | -- "$ccut2_exe" \ 486 | > /dev/null 2>&1 487 | if [ $? -ne 0 ]; then 488 | $QUIET_ECHO "$0: $CCUT2: compiled program failed to run correctly" 489 | $NEAT_RM_OUTS 490 | exit 1 491 | fi 492 | 493 | # The regular and volatile checksums of the program produced by the second 494 | # compiler under test. 495 | ccut2_exe_chk=ccut2-exe-out-chk.txt 496 | ccut2_exe_vchk=ccut2-exe-out-vchk.txt 497 | 498 | $GREP -e "^checksum" "$ccut2_exe_out" > "$ccut2_exe_chk" 499 | # $? is 0 is lines were matched; 1 if no lines matched; >1 if error. 500 | if [ $? -ne 0 ]; then 501 | $QUIET_ECHO "$0: $CCUT2: compiled program produced no checksum" 502 | $NEAT_RM_OUTS 503 | exit 1 504 | fi 505 | 506 | $GREP -e "^vol_access_checksum" "$ccut2_exe_out" > "$ccut2_exe_vchk" 507 | # $? is 0 is lines were matched; 1 if no lines matched; >1 if error. 508 | if [ $? -ne 0 ]; then 509 | $QUIET_ECHO "$0: $CCUT2: compiled program produced no volatile checksum" 510 | $NEAT_RM_OUTS 511 | exit 1 512 | fi 513 | 514 | ############################################################################### 515 | 516 | ## Compare the regular and volatile checksums of the two compiled programs. 517 | 518 | # If the regular checksums differ, this mutant is bad. 519 | $CMP -s "$ccut1_exe_chk" "$ccut2_exe_chk" 520 | if [ $? -ne 0 ]; then 521 | $QUIET_ECHO "$0: compiled programs output different checksums" 522 | exit 1 523 | fi 524 | 525 | # If the volatile checksums are *not* different, this mutant is bad. 526 | $CMP -s "$ccut1_exe_vchk" "$ccut2_exe_vchk" 527 | if [ $? -eq 0 ]; then 528 | $QUIET_ECHO "$0: compiled programs yield the same volatile checksum" 529 | exit 1 530 | fi 531 | 532 | ############################################################################### 533 | 534 | $QUIET_ECHO "$0: \"$filename\" is good" 535 | $NEAT_RM_OUTS 536 | 537 | exit 0 538 | 539 | ## End of file. 540 | --------------------------------------------------------------------------------