Rename !ubsan metadata to more generic and appropriate !nosanitize.
http://reviews.llvm.org/D4544
Files:
lib/Transforms/Instrumentation/AddressSanitizer.cpp
test/Instrumentation/AddressSanitizer/ubsan.ll
tools/clang/lib/CodeGen/CGBuiltin.cpp
tools/clang/lib/CodeGen/CGExpr.cpp
tools/clang/lib/CodeGen/CGExprScalar.cpp
tools/clang/lib/CodeGen/CodeGenFunction.cpp
tools/clang/lib/CodeGen/CodeGenFunction.h
tools/clang/test/CodeGen/catch-undef-behavior.c
Index: test/Instrumentation/AddressSanitizer/ubsan.ll
===================================================================
--- /dev/null
+++ test/Instrumentation/AddressSanitizer/ubsan.ll
@@ -0,0 +1,52 @@
+; ASan shouldn't instrument code added by UBSan.
+
+; RUN: opt < %s -asan -asan-module -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.A = type { i32 (...)** }
+declare void @__ubsan_handle_dynamic_type_cache_miss(i8*, i64, i64) uwtable
+@__ubsan_vptr_type_cache = external global [128 x i64]
[email protected] = private unnamed_addr constant [19 x i8] c"tmp/ubsan/vptr.cpp\00", align 1
+@0 = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" }
+@_ZTI1A = external constant i8*
+@1 = private unnamed_addr global { { [19 x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { { [19 x i8]*, i32, i32 } { [19 x i8]* @.src, i32 2, i32 18 }, { i16, i16, [4 x i8] }* @0, i8* bitcast (i8** @_ZTI1A to i8*), i8 4 }
+
+define void @_Z3BarP1A(%struct.A* %a) uwtable sanitize_address {
+; CHECK-LABEL: define void @_Z3BarP1A
+entry:
+ %0 = bitcast %struct.A* %a to void (%struct.A*)***
+ %vtable = load void (%struct.A*)*** %0, align 8
+; CHECK: __asan_report_load8
+ %1 = load void (%struct.A*)** %vtable, align 8
+; CHECK: __asan_report_load8
+ %2 = ptrtoint void (%struct.A*)** %vtable to i64
+ %3 = xor i64 %2, -303164226014115343, !nosanitize !0
+ %4 = mul i64 %3, -7070675565921424023, !nosanitize !0
+ %5 = lshr i64 %4, 47, !nosanitize !0
+ %6 = xor i64 %4, %2, !nosanitize !0
+ %7 = xor i64 %6, %5, !nosanitize !0
+ %8 = mul i64 %7, -7070675565921424023, !nosanitize !0
+ %9 = lshr i64 %8, 47, !nosanitize !0
+ %10 = xor i64 %9, %8, !nosanitize !0
+ %11 = mul i64 %10, -7070675565921424023, !nosanitize !0
+ %12 = and i64 %11, 127, !nosanitize !0
+ %13 = getelementptr inbounds [128 x i64]* @__ubsan_vptr_type_cache, i64 0, i64 %12, !nosanitize !0
+; CHECK-NOT: __asan_report_load8
+ %14 = load i64* %13, align 8, !nosanitize !0
+ %15 = icmp eq i64 %14, %11, !nosanitize !0
+ br i1 %15, label %cont, label %handler.dynamic_type_cache_miss, !nosanitize !0
+
+handler.dynamic_type_cache_miss: ; preds = %entry
+ %16 = ptrtoint %struct.A* %a to i64, !nosanitize !0
+ tail call void @__ubsan_handle_dynamic_type_cache_miss(i8* bitcast ({ { [19 x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 }* @1 to i8*), i64 %16, i64 %11) #2, !nosanitize !0
+ br label %cont, !nosanitize !0
+
+cont: ; preds = %handler.dynamic_type_cache_miss, %entry
+ tail call void %1(%struct.A* %a)
+; CHECK: ret void
+ ret void
+}
+
+!0 = metadata !{}
Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp
===================================================================
--- lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -655,6 +655,9 @@
// and set IsWrite/Alignment. Otherwise return NULL.
static Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
unsigned *Alignment) {
+ // Skip memory accesses inserted by another instrumentation.
+ if (I->getMetadata("nosanitize"))
+ return nullptr;
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
if (!ClInstrumentReads) return nullptr;
*IsWrite = false;
Index: tools/clang/test/CodeGen/catch-undef-behavior.c
===================================================================
--- tools/clang/test/CodeGen/catch-undef-behavior.c
+++ tools/clang/test/CodeGen/catch-undef-behavior.c
@@ -49,7 +49,7 @@
// CHECK-TRAP-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0
// CHECK: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]]
- // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]]
+ // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize
// CHECK-TRAP: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]]
// CHECK-TRAP-NEXT: br i1 %[[OK]], {{.*}}
@@ -311,7 +311,7 @@
// CHECK: %[[LE:.*]] = fcmp olt x86_fp80 %[[F]], 0xK401E8000000000000000
// CHECK: and i1 %[[GE]], %[[LE]]
- // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]]
+ // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]], !nosanitize
// CHECK: %[[ARG:.*]] = ptrtoint x86_fp80* %[[ALLOCA]] to i64
// CHECK: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]]
Index: tools/clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- tools/clang/lib/CodeGen/CodeGenFunction.h
+++ tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -247,6 +247,17 @@
/// \brief Sanitizer options to use for this function.
const SanitizerOptions *SanOpts;
+ /// \brief True if CodeGen currently emits code implementing sanitizer checks.
+ bool IsSanitizerScope;
+
+ /// \brief RAII object to set/unset CodeGenFunction::IsSanitizerScope.
+ class SanitizerScope {
+ CodeGenFunction *CGF;
+ public:
+ SanitizerScope(CodeGenFunction *CGF);
+ ~SanitizerScope();
+ };
+
/// In ARC, whether we should autorelease the return value.
bool AutoreleaseResult;
Index: tools/clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- tools/clang/lib/CodeGen/CGBuiltin.cpp
+++ tools/clang/lib/CodeGen/CGBuiltin.cpp
@@ -447,11 +447,12 @@
return RValue::get(Builder.CreateCall(F));
}
case Builtin::BI__builtin_unreachable: {
- if (SanOpts->Unreachable)
+ if (SanOpts->Unreachable) {
+ SanitizerScope SanScope(this);
EmitCheck(Builder.getFalse(), "builtin_unreachable",
EmitCheckSourceLocation(E->getExprLoc()),
ArrayRef<llvm::Value *>(), CRK_Unrecoverable);
- else
+ } else
Builder.CreateUnreachable();
// We do need to preserve an insertion point.
Index: tools/clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- tools/clang/lib/CodeGen/CodeGenFunction.cpp
+++ tools/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -36,8 +36,9 @@
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
: CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
Builder(cgm.getModule().getContext(), llvm::ConstantFolder(),
- CGBuilderInserterTy(this)), CapturedStmtInfo(nullptr),
- SanOpts(&CGM.getLangOpts().Sanitize), AutoreleaseResult(false), BlockInfo(nullptr),
+ CGBuilderInserterTy(this)),
+ CapturedStmtInfo(nullptr), SanOpts(&CGM.getLangOpts().Sanitize),
+ IsSanitizerScope(false), AutoreleaseResult(false), BlockInfo(nullptr),
BlockPointer(nullptr), LambdaThisCaptureField(nullptr),
NormalCleanupDest(nullptr), NextCleanupDestIndex(1),
FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr),
@@ -843,11 +844,12 @@
// function call is used by the caller, the behavior is undefined.
if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() &&
!FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
- if (SanOpts->Return)
+ if (SanOpts->Return) {
+ SanitizerScope SanScope(this);
EmitCheck(Builder.getFalse(), "missing_return",
EmitCheckSourceLocation(FD->getLocation()),
ArrayRef<llvm::Value *>(), CRK_Unrecoverable);
- else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ } else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap));
Builder.CreateUnreachable();
Builder.ClearInsertionPoint();
@@ -1499,6 +1501,7 @@
// greater than zero.
if (SanOpts->VLABound &&
size->getType()->isSignedIntegerType()) {
+ SanitizerScope SanScope(this);
llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType());
llvm::Constant *StaticArgs[] = {
EmitCheckSourceLocation(size->getLocStart()),
@@ -1637,11 +1640,26 @@
CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
+CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF)
+ : CGF(CGF) {
+ assert(!CGF->IsSanitizerScope);
+ CGF->IsSanitizerScope = true;
+}
+
+CodeGenFunction::SanitizerScope::~SanitizerScope() {
+ CGF->IsSanitizerScope = false;
+}
+
void CodeGenFunction::InsertHelper(llvm::Instruction *I,
const llvm::Twine &Name,
llvm::BasicBlock *BB,
llvm::BasicBlock::iterator InsertPt) const {
LoopStack.InsertHelper(I);
+ if (IsSanitizerScope) {
+ I->setMetadata(
+ CGM.getModule().getMDKindID("nosanitize"),
+ llvm::MDNode::get(CGM.getLLVMContext(), ArrayRef<llvm::Value *>()));
+ }
}
template <bool PreserveNames>
Index: tools/clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- tools/clang/lib/CodeGen/CGExprScalar.cpp
+++ tools/clang/lib/CodeGen/CGExprScalar.cpp
@@ -554,6 +554,7 @@
Value *Src, QualType SrcType,
QualType DstType,
llvm::Type *DstTy) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
using llvm::APFloat;
using llvm::APSInt;
@@ -835,6 +836,7 @@
/// might actually be a unary increment which has been lowered to a binary
/// operation). The check passes if \p Check, which is an \c i1, is \c true.
void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) {
+ assert(CGF.IsSanitizerScope);
StringRef CheckName;
SmallVector<llvm::Constant *, 4> StaticData;
SmallVector<llvm::Value *, 2> DynamicData;
@@ -2146,15 +2148,18 @@
}
Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
- if ((CGF.SanOpts->IntegerDivideByZero ||
- CGF.SanOpts->SignedIntegerOverflow) &&
- Ops.Ty->isIntegerType()) {
- llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
- EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true);
- } else if (CGF.SanOpts->FloatDivideByZero &&
- Ops.Ty->isRealFloatingType()) {
- llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
- EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
+ {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+ if ((CGF.SanOpts->IntegerDivideByZero ||
+ CGF.SanOpts->SignedIntegerOverflow) &&
+ Ops.Ty->isIntegerType()) {
+ llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
+ EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true);
+ } else if (CGF.SanOpts->FloatDivideByZero &&
+ Ops.Ty->isRealFloatingType()) {
+ llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
+ EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
+ }
}
if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
@@ -2178,6 +2183,7 @@
Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
// Rem in C can't be a floating point type: C99 6.5.5p2.
if (CGF.SanOpts->IntegerDivideByZero) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
if (Ops.Ty->isIntegerType())
@@ -2235,9 +2241,10 @@
if (handlerName->empty()) {
// If the signed-integer-overflow sanitizer is enabled, emit a call to its
// runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
- if (!isSigned || CGF.SanOpts->SignedIntegerOverflow)
+ if (!isSigned || CGF.SanOpts->SignedIntegerOverflow) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
EmitBinOpCheck(Builder.CreateNot(overflow), Ops);
- else
+ } else
CGF.EmitTrapCheck(Builder.CreateNot(overflow));
return result;
}
@@ -2589,6 +2596,7 @@
if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS);
llvm::Value *Valid = Builder.CreateICmpULE(RHS, WidthMinusOne);
@@ -2640,8 +2648,10 @@
RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL &&
- isa<llvm::IntegerType>(Ops.LHS->getType()))
+ isa<llvm::IntegerType>(Ops.LHS->getType())) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops);
+ }
// OpenCL 6.3j: shift values are effectively % word size of LHS.
if (CGF.getLangOpts().OpenCL)
Index: tools/clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- tools/clang/lib/CodeGen/CGExpr.cpp
+++ tools/clang/lib/CodeGen/CGExpr.cpp
@@ -458,6 +458,8 @@
if (Address->getType()->getPointerAddressSpace())
return;
+ SanitizerScope SanScope(this);
+
llvm::Value *Cond = nullptr;
llvm::BasicBlock *Done = nullptr;
@@ -654,6 +656,7 @@
bool Accessed) {
assert(SanOpts->ArrayBounds &&
"should not be called unless adding bounds checks");
+ SanitizerScope SanScope(this);
QualType IndexedType;
llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType);
@@ -1129,6 +1132,7 @@
if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) ||
(SanOpts->Enum && Ty->getAs<EnumType>())) {
+ SanitizerScope SanScope(this);
llvm::APInt Min, End;
if (getRangeForType(*this, Ty, Min, End, true)) {
--End;
@@ -2183,6 +2187,7 @@
ArrayRef<llvm::Value *> DynamicArgs,
CheckRecoverableKind RecoverKind) {
assert(SanOpts != &SanitizerOptions::Disabled);
+ assert(IsSanitizerScope);
if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
assert (RecoverKind != CRK_AlwaysRecoverable &&
@@ -3231,6 +3236,7 @@
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
if (llvm::Constant *PrefixSig =
CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
+ SanitizerScope SanScope(this);
llvm::Constant *FTRTTIConst =
CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true);
llvm::Type *PrefixStructTyElems[] = {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits