diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2015-02-20 20:30:56 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2015-02-20 20:30:56 +0000 |
commit | a4ccff32818c05c9f2d7a2a6503866d13636b664 (patch) | |
tree | d0853e78880e850956141ea043fecb36250e5842 /clang/test/CodeGenCXX/cfi-vptr.cpp | |
parent | e6909c8e8ba07acb5e6366186fe186c91054e93c (diff) | |
download | bcm5719-llvm-a4ccff32818c05c9f2d7a2a6503866d13636b664.tar.gz bcm5719-llvm-a4ccff32818c05c9f2d7a2a6503866d13636b664.zip |
Implement Control Flow Integrity for virtual calls.
This patch introduces the -fsanitize=cfi-vptr flag, which enables a control
flow integrity scheme that checks that virtual calls take place using a vptr of
the correct dynamic type. More details in the new docs/ControlFlowIntegrity.rst
file.
It also introduces the -fsanitize=cfi flag, which is currently a synonym for
-fsanitize=cfi-vptr, but will eventually cover all CFI checks implemented
in Clang.
Differential Revision: http://reviews.llvm.org/D7424
llvm-svn: 230055
Diffstat (limited to 'clang/test/CodeGenCXX/cfi-vptr.cpp')
-rw-r--r-- | clang/test/CodeGenCXX/cfi-vptr.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/cfi-vptr.cpp b/clang/test/CodeGenCXX/cfi-vptr.cpp new file mode 100644 index 00000000000..545f22c3c72 --- /dev/null +++ b/clang/test/CodeGenCXX/cfi-vptr.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vptr -emit-llvm -o - %s | FileCheck %s + +struct A { + A(); + virtual void f(); +}; + +struct B : virtual A { + B(); +}; + +struct C : virtual A { + C(); +}; + +namespace { + +struct D : B, C { + D(); + virtual void f(); +}; + +} + +A::A() {} +B::B() {} +C::C() {} +D::D() {} + +void A::f() { +} + +void D::f() { +} + +// CHECK: define void @_Z2afP1A +void af(A *a) { + // CHECK: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1A") + // CHECK-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ]*]] + + // CHECK: [[TRAPBB]] + // CHECK-NEXT: call void @llvm.trap() + // CHECK-NEXT: unreachable + + // CHECK: [[CONTBB]] + // CHECK: call void % + a->f(); +} + +// CHECK: define internal void @_Z2dfPN12_GLOBAL__N_11DE +void df(D *d) { + // CHECK: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"[{{.*}}cfi-vptr.cpp]N12_GLOBAL__N_11DE") + d->f(); +} + +D d; + +void foo() { + df(&d); +} + +// CHECK-DAG: !{!"1A", [3 x i8*]* @_ZTV1A, i64 16} +// CHECK-DAG: !{!"1A", [5 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} +// CHECK-DAG: !{!"1B", [5 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} +// CHECK-DAG: !{!"1A", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 64} +// CHECK-DAG: !{!"1C", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 32} +// CHECK-DAG: !{!"1A", [10 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} +// CHECK-DAG: !{!"1B", [10 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} +// CHECK-DAG: !{!"1C", [10 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 72} +// CHECK-DAG: !{!"[{{.*}}cfi-vptr.cpp]N12_GLOBAL__N_11DE", [10 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} +// CHECK-DAG: !{!"1A", [5 x i8*]* @_ZTV1B, i64 32} +// CHECK-DAG: !{!"1B", [5 x i8*]* @_ZTV1B, i64 32} +// CHECK-DAG: !{!"1A", [5 x i8*]* @_ZTV1C, i64 32} +// CHECK-DAG: !{!"1C", [5 x i8*]* @_ZTV1C, i64 32} |