r240109 - Implement diagnostic mode for -fsanitize=cfi*, -fsanitize=cfi-diag.
Peter Collingbourne
peter at pcc.me.uk
Thu Jun 18 18:51:55 PDT 2015
Author: pcc
Date: Thu Jun 18 20:51:54 2015
New Revision: 240109
URL: http://llvm.org/viewvc/llvm-project?rev=240109&view=rev
Log:
Implement diagnostic mode for -fsanitize=cfi*, -fsanitize=cfi-diag.
This causes programs compiled with this flag to print a diagnostic when
a control flow integrity check fails instead of aborting. Diagnostics are
printed using UBSan's runtime library.
The main motivation of this feature over -fsanitize=vptr is fidelity with
the -fsanitize=cfi implementation: the diagnostics are printed under exactly
the same conditions as those which would cause -fsanitize=cfi to abort the
program. This means that the same restrictions apply regarding compiling
all translation units with -fsanitize=cfi, cross-DSO virtual calls are
forbidden, etc.
Differential Revision: http://reviews.llvm.org/D10268
Modified:
cfe/trunk/docs/UsersManual.rst
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/CGClass.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
cfe/trunk/lib/Driver/SanitizerArgs.cpp
cfe/trunk/test/CodeGenCXX/cfi-cast.cpp
cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp
Modified: cfe/trunk/docs/UsersManual.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.rst?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/docs/UsersManual.rst (original)
+++ cfe/trunk/docs/UsersManual.rst Thu Jun 18 20:51:54 2015
@@ -1108,10 +1108,12 @@ are listed below.
the binary size increase caused by the sanitizer runtime is a concern.
This flag is only compatible with ``local-bounds``,
- ``unsigned-integer-overflow`` and sanitizers in the ``undefined``
- group other than ``vptr``. If this flag is supplied together with
- ``-fsanitize=undefined``, the ``vptr`` sanitizer will be implicitly
- disabled.
+ ``unsigned-integer-overflow``, sanitizers in the ``cfi`` group and
+ sanitizers in the ``undefined`` group other than ``vptr``. If this flag
+ is supplied together with ``-fsanitize=undefined``, the ``vptr`` sanitizer
+ will be implicitly disabled.
+
+ This flag is enabled by default for sanitizers in the ``cfi`` group.
**-f[no-]sanitize-coverage=[type,features,...]**
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Thu Jun 18 20:51:54 2015
@@ -366,7 +366,8 @@ public:
virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) = 0;
+ llvm::Type *Ty,
+ SourceLocation Loc) = 0;
/// Emit the ABI-specific virtual destructor call.
virtual llvm::Value *
Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Thu Jun 18 20:51:54 2015
@@ -2134,17 +2134,21 @@ LeastDerivedClassWithSameLayout(const CX
}
void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXMethodDecl *MD,
- llvm::Value *VTable) {
+ llvm::Value *VTable,
+ CFITypeCheckKind TCK,
+ SourceLocation Loc) {
const CXXRecordDecl *ClassDecl = MD->getParent();
if (!SanOpts.has(SanitizerKind::CFICastStrict))
ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
- EmitVTablePtrCheck(ClassDecl, VTable);
+ EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);
}
void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T,
llvm::Value *Derived,
- bool MayBeNull) {
+ bool MayBeNull,
+ CFITypeCheckKind TCK,
+ SourceLocation Loc) {
if (!getLangOpts().CPlusPlus)
return;
@@ -2184,7 +2188,7 @@ void CodeGenFunction::EmitVTablePtrCheck
}
llvm::Value *VTable = GetVTablePtr(Derived, Int8PtrTy);
- EmitVTablePtrCheck(ClassDecl, VTable);
+ EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);
if (MayBeNull) {
Builder.CreateBr(ContBlock);
@@ -2193,11 +2197,15 @@ void CodeGenFunction::EmitVTablePtrCheck
}
void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
- llvm::Value *VTable) {
+ llvm::Value *VTable,
+ CFITypeCheckKind TCK,
+ SourceLocation Loc) {
// FIXME: Add blacklisting scheme.
if (RD->isInStdNamespace())
return;
+ SanitizerScope SanScope(this);
+
std::string OutName;
llvm::raw_string_ostream Out(OutName);
CGM.getCXXABI().getMangleContext().mangleCXXVTableBitSet(RD, Out);
@@ -2205,20 +2213,34 @@ void CodeGenFunction::EmitVTablePtrCheck
llvm::Value *BitSetName = llvm::MetadataAsValue::get(
getLLVMContext(), llvm::MDString::get(getLLVMContext(), Out.str()));
- llvm::Value *BitSetTest = Builder.CreateCall(
- CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
- {Builder.CreateBitCast(VTable, CGM.Int8PtrTy), BitSetName});
-
- llvm::BasicBlock *ContBlock = createBasicBlock("vtable.check.cont");
- llvm::BasicBlock *TrapBlock = createBasicBlock("vtable.check.trap");
-
- Builder.CreateCondBr(BitSetTest, ContBlock, TrapBlock);
-
- EmitBlock(TrapBlock);
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap), {});
- Builder.CreateUnreachable();
+ llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
+ llvm::Value *BitSetTest =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
+ {CastedVTable, BitSetName});
+
+ SanitizerMask M;
+ switch (TCK) {
+ case CFITCK_VCall:
+ M = SanitizerKind::CFIVCall;
+ break;
+ case CFITCK_NVCall:
+ M = SanitizerKind::CFINVCall;
+ break;
+ case CFITCK_DerivedCast:
+ M = SanitizerKind::CFIDerivedCast;
+ break;
+ case CFITCK_UnrelatedCast:
+ M = SanitizerKind::CFIUnrelatedCast;
+ break;
+ }
- EmitBlock(ContBlock);
+ llvm::Constant *StaticData[] = {
+ EmitCheckSourceLocation(Loc),
+ EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
+ llvm::ConstantInt::get(Int8Ty, TCK),
+ };
+ EmitCheck(std::make_pair(BitSetTest, M), "cfi_bad_type", StaticData,
+ CastedVTable);
}
// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jun 18 20:51:54 2015
@@ -3035,7 +3035,8 @@ LValue CodeGenFunction::EmitCastLValue(c
Derived, E->getType());
if (SanOpts.has(SanitizerKind::CFIDerivedCast))
- EmitVTablePtrCheckForCast(E->getType(), Derived, /*MayBeNull=*/false);
+ EmitVTablePtrCheckForCast(E->getType(), Derived, /*MayBeNull=*/false,
+ CFITCK_DerivedCast, E->getLocStart());
return MakeAddrLValue(Derived, E->getType());
}
@@ -3048,7 +3049,8 @@ LValue CodeGenFunction::EmitCastLValue(c
ConvertType(CE->getTypeAsWritten()));
if (SanOpts.has(SanitizerKind::CFIUnrelatedCast))
- EmitVTablePtrCheckForCast(E->getType(), V, /*MayBeNull=*/false);
+ EmitVTablePtrCheckForCast(E->getType(), V, /*MayBeNull=*/false,
+ CFITCK_UnrelatedCast, E->getLocStart());
return MakeAddrLValue(V, E->getType());
}
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Jun 18 20:51:54 2015
@@ -254,12 +254,13 @@ RValue CodeGenFunction::EmitCXXMemberOrO
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
} else if (UseVirtualCall) {
- Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty);
+ Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty,
+ CE->getLocStart());
} else {
if (SanOpts.has(SanitizerKind::CFINVCall) &&
MD->getParent()->isDynamicClass()) {
llvm::Value *VTable = GetVTablePtr(This, Int8PtrTy);
- EmitVTablePtrCheckForCall(MD, VTable);
+ EmitVTablePtrCheckForCall(MD, VTable, CFITCK_NVCall, CE->getLocStart());
}
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Jun 18 20:51:54 2015
@@ -1386,7 +1386,9 @@ Value *ScalarExprEmitter::VisitCastExpr(
if (CGF.SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
if (auto PT = DestTy->getAs<PointerType>())
CGF.EmitVTablePtrCheckForCast(PT->getPointeeType(), Src,
- /*MayBeNull=*/true);
+ /*MayBeNull=*/true,
+ CodeGenFunction::CFITCK_UnrelatedCast,
+ CE->getLocStart());
}
return Builder.CreateBitCast(Src, DstTy);
@@ -1420,7 +1422,9 @@ Value *ScalarExprEmitter::VisitCastExpr(
if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast))
CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived,
- /*MayBeNull=*/true);
+ /*MayBeNull=*/true,
+ CodeGenFunction::CFITCK_DerivedCast,
+ CE->getLocStart());
return Derived;
}
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Jun 18 20:51:54 2015
@@ -1311,19 +1311,29 @@ public:
/// to by This.
llvm::Value *GetVTablePtr(llvm::Value *This, llvm::Type *Ty);
+ enum CFITypeCheckKind {
+ CFITCK_VCall,
+ CFITCK_NVCall,
+ CFITCK_DerivedCast,
+ CFITCK_UnrelatedCast,
+ };
+
/// \brief Derived is the presumed address of an object of type T after a
/// cast. If T is a polymorphic class type, emit a check that the virtual
/// table for Derived belongs to a class derived from T.
void EmitVTablePtrCheckForCast(QualType T, llvm::Value *Derived,
- bool MayBeNull);
+ bool MayBeNull, CFITypeCheckKind TCK,
+ SourceLocation Loc);
/// EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.
/// If vptr CFI is enabled, emit a check that VTable is valid.
- void EmitVTablePtrCheckForCall(const CXXMethodDecl *MD, llvm::Value *VTable);
+ void EmitVTablePtrCheckForCall(const CXXMethodDecl *MD, llvm::Value *VTable,
+ CFITypeCheckKind TCK, SourceLocation Loc);
/// EmitVTablePtrCheck - Emit a check that VTable is a valid virtual table for
/// RD using llvm.bitset.test.
- void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable);
+ void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable,
+ CFITypeCheckKind TCK, SourceLocation Loc);
/// CanDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
/// expr can be devirtualized.
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Jun 18 20:51:54 2015
@@ -204,7 +204,8 @@ public:
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) override;
+ llvm::Type *Ty,
+ SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
@@ -1439,13 +1440,15 @@ llvm::GlobalVariable *ItaniumCXXABI::get
llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) {
+ llvm::Type *Ty,
+ SourceLocation Loc) {
GD = GD.getCanonicalDecl();
Ty = Ty->getPointerTo()->getPointerTo();
llvm::Value *VTable = CGF.GetVTablePtr(This, Ty);
if (CGF.SanOpts.has(SanitizerKind::CFIVCall))
- CGF.EmitVTablePtrCheckForCall(cast<CXXMethodDecl>(GD.getDecl()), VTable);
+ CGF.EmitVTablePtrCheckForCall(cast<CXXMethodDecl>(GD.getDecl()), VTable,
+ CodeGenFunction::CFITCK_VCall, Loc);
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFuncPtr =
@@ -1463,7 +1466,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualD
Dtor, getFromDtorType(DtorType));
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
llvm::Value *Callee =
- getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty);
+ getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty,
+ CE ? CE->getLocStart() : SourceLocation());
CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This,
/*ImplicitParam=*/nullptr, QualType(), CE);
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Thu Jun 18 20:51:54 2015
@@ -221,8 +221,8 @@ public:
CharUnits VPtrOffset) override;
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
- llvm::Value *This,
- llvm::Type *Ty) override;
+ llvm::Value *This, llvm::Type *Ty,
+ SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
@@ -1588,7 +1588,8 @@ llvm::GlobalVariable *MicrosoftCXXABI::g
llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) {
+ llvm::Type *Ty,
+ SourceLocation Loc) {
GD = GD.getCanonicalDecl();
CGBuilderTy &Builder = CGF.Builder;
@@ -1616,7 +1617,8 @@ llvm::Value *MicrosoftCXXABI::EmitVirtua
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, StructorType::Deleting);
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
- llvm::Value *Callee = getVirtualFunctionPointer(CGF, GD, This, Ty);
+ llvm::Value *Callee = getVirtualFunctionPointer(
+ CGF, GD, This, Ty, CE ? CE->getLocStart() : SourceLocation());
ASTContext &Context = getContext();
llvm::Value *ImplicitParam = llvm::ConstantInt::get(
Modified: cfe/trunk/lib/Driver/SanitizerArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.cpp (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.cpp Thu Jun 18 20:51:54 2015
@@ -25,7 +25,7 @@ using namespace clang::driver;
using namespace llvm::opt;
enum : SanitizerMask {
- NeedsUbsanRt = Undefined | Integer,
+ NeedsUbsanRt = Undefined | Integer | CFI,
NotAllowedWithTrap = Vptr,
RequiresPIE = Memory | DataFlow,
NeedsUnwindTables = Address | Thread | Memory | DataFlow,
@@ -35,7 +35,8 @@ enum : SanitizerMask {
LegacyFsanitizeRecoverMask = Undefined | Integer,
NeedsLTO = CFI,
TrappingSupported =
- (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds,
+ (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
+ TrappingDefault = CFI,
};
enum CoverageFeature {
@@ -166,6 +167,9 @@ static SanitizerMask parseSanitizeTrapAr
}
}
+ // Apply default trapping behavior.
+ TrappingKinds |= TrappingDefault & ~TrapRemove;
+
return TrappingKinds;
}
Modified: cfe/trunk/test/CodeGenCXX/cfi-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cfi-cast.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cfi-cast.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cfi-cast.cpp Thu Jun 18 20:51:54 2015
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-derived-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-DCAST %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast,cfi-cast-strict -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST-STRICT %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-DCAST %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast -fsanitize-trap=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast,cfi-cast-strict -fsanitize-trap=cfi-unrelated-cast,cfi-cast-strict -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST-STRICT %s
// In this test the main thing we are searching for is something like
// 'metadata !"1B"' where "1B" is the mangled name of the class we are
@@ -19,7 +19,7 @@ struct C : A {};
// CHECK-DCAST-LABEL: define void @_Z3abpP1A
void abp(A *a) {
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B")
- // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ]*]]
+ // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-DCAST: [[TRAPBB]]
// CHECK-DCAST-NEXT: call void @llvm.trap()
@@ -33,7 +33,7 @@ void abp(A *a) {
// CHECK-DCAST-LABEL: define void @_Z3abrR1A
void abr(A &a) {
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B")
- // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ]*]]
+ // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-DCAST: [[TRAPBB]]
// CHECK-DCAST-NEXT: call void @llvm.trap()
@@ -47,7 +47,7 @@ void abr(A &a) {
// CHECK-DCAST-LABEL: define void @_Z4abrrO1A
void abrr(A &&a) {
// CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B")
- // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ]*]]
+ // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-DCAST: [[TRAPBB]]
// CHECK-DCAST-NEXT: call void @llvm.trap()
@@ -61,7 +61,7 @@ void abrr(A &&a) {
// CHECK-UCAST-LABEL: define void @_Z3vbpPv
void vbp(void *p) {
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B")
- // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ]*]]
+ // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-UCAST: [[TRAPBB]]
// CHECK-UCAST-NEXT: call void @llvm.trap()
@@ -75,7 +75,7 @@ void vbp(void *p) {
// CHECK-UCAST-LABEL: define void @_Z3vbrRc
void vbr(char &r) {
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B")
- // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ]*]]
+ // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-UCAST: [[TRAPBB]]
// CHECK-UCAST-NEXT: call void @llvm.trap()
@@ -89,7 +89,7 @@ void vbr(char &r) {
// CHECK-UCAST-LABEL: define void @_Z4vbrrOc
void vbrr(char &&r) {
// CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B")
- // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ]*]]
+ // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-UCAST: [[TRAPBB]]
// CHECK-UCAST-NEXT: call void @llvm.trap()
Modified: cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp?rev=240109&r1=240108&r2=240109&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp Thu Jun 18 20:51:54 2015
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NDIAG %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=DIAG --check-prefix=DIAG-ABORT %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s
struct A {
A();
@@ -33,14 +35,23 @@ void A::f() {
void D::f() {
}
+// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}test/CodeGenCXX/cfi-vcall.cpp\00", align 1
+// DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" }
+// DIAG: @[[BADTYPESTATIC:.*]] = private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8 } { { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 58, i32 3 }, { i16, i16, [4 x i8] }* @[[TYPE]], i8 0 }
+
// 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: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"1A")
+ // CHECK-NEXT: br i1 [[P]], label %[[CONTBB:[^ ,]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK: [[TRAPBB]]
- // CHECK-NEXT: call void @llvm.trap()
- // CHECK-NEXT: unreachable
+ // NDIAG-NEXT: call void @llvm.trap()
+ // NDIAG-NEXT: unreachable
+ // DIAG-NEXT: [[VTINT:%[^ ]*]] = ptrtoint i8* [[VT]] to i64
+ // DIAG-ABORT-NEXT: call void @__ubsan_handle_cfi_bad_type_abort(i8* bitcast ({{.*}} @[[BADTYPESTATIC]] to i8*), i64 [[VTINT]])
+ // DIAG-ABORT-NEXT: unreachable
+ // DIAG-RECOVER-NEXT: call void @__ubsan_handle_cfi_bad_type(i8* bitcast ({{.*}} @[[BADTYPESTATIC]] to i8*), i64 [[VTINT]])
+ // DIAG-RECOVER-NEXT: br label %[[CONTBB]]
// CHECK: [[CONTBB]]
// CHECK: call void %
More information about the cfe-commits
mailing list