diff --git a/compiler-rt/test/dfsan/event_callbacks.c b/compiler-rt/test/dfsan/event_callbacks.c --- a/compiler-rt/test/dfsan/event_callbacks.c +++ b/compiler-rt/test/dfsan/event_callbacks.c @@ -57,6 +57,13 @@ fprintf(stderr, "Label %u copied to memory\n", Start[0]); } +void __dfsan_cmp_callback(dfsan_label CombinedLabel) { + if (!CombinedLabel) + return; + + fprintf(stderr, "Label %u used for branching\n", CombinedLabel); +} + #else // Compile this code with DFSan and -dfsan-event-callbacks to insert the // callbacks. @@ -82,12 +89,14 @@ volatile int Sink = I; // CHECK: Label 1 loaded from memory + // CHECK: Label 1 used for branching assert(Sink == 1); // CHECK: Label 2 stored to memory Sink = J; // CHECK: Label 2 loaded from memory + // CHECK: Label 2 used for branching assert(Sink == 2); // CHECK: Label 2 loaded from memory @@ -95,8 +104,12 @@ Sink += I; // CHECK: Label 3 loaded from memory + // CHECK: Label 3 used for branching assert(Sink == 3); + // CHECK: Label 3 used for branching + assert(I != J); + LenArgv = strlen(Argv[1]); LabelArgv = dfsan_create_label("Argv", 0); dfsan_set_label(LabelArgv, Argv[1], LenArgv); diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -163,14 +163,15 @@ cl::Hidden); // Experimental feature that inserts callbacks for certain data events. -// Currently callbacks are only inserted for loads, stores, and memory transfers -// (i.e. memcpy and memmove). +// Currently callbacks are only inserted for loads, stores, memory transfers +// (i.e. memcpy and memmove), and comparisons. // // If this flag is set to true, the user must provide definitions for the // following callback functions: // void __dfsan_load_callback(dfsan_label Label); // void __dfsan_store_callback(dfsan_label Label); // void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len); +// void __dfsan_cmp_callback(dfsan_label CombinedLabel); static cl::opt ClEventCallbacks( "dfsan-event-callbacks", cl::desc("Insert calls to __dfsan_*_callback functions on data events."), @@ -359,7 +360,7 @@ FunctionType *DFSanSetLabelFnTy; FunctionType *DFSanNonzeroLabelFnTy; FunctionType *DFSanVarargWrapperFnTy; - FunctionType *DFSanLoadStoreCallbackFnTy; + FunctionType *DFSanLoadStoreCmpCallbackFnTy; FunctionType *DFSanMemTransferCallbackFnTy; FunctionCallee DFSanUnionFn; FunctionCallee DFSanCheckedUnionFn; @@ -371,6 +372,7 @@ FunctionCallee DFSanLoadCallbackFn; FunctionCallee DFSanStoreCallbackFn; FunctionCallee DFSanMemTransferCallbackFn; + FunctionCallee DFSanCmpCallbackFn; MDNode *ColdCallWeights; DFSanABIList ABIList; DenseMap UnwrappedFnMap; @@ -457,7 +459,10 @@ return DFSF.F->getParent()->getDataLayout(); } - void visitOperandShadowInst(Instruction &I); + // Combines shadow values for all of I's operands. Returns the combined shadow + // value. + Value *visitOperandShadowInst(Instruction &I); + void visitUnaryOperator(UnaryOperator &UO); void visitBinaryOperator(BinaryOperator &BO); void visitCastInst(CastInst &CI); @@ -602,7 +607,7 @@ Type::getVoidTy(*Ctx), None, /*isVarArg=*/false); DFSanVarargWrapperFnTy = FunctionType::get( Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false); - DFSanLoadStoreCallbackFnTy = + DFSanLoadStoreCmpCallbackFnTy = FunctionType::get(Type::getVoidTy(*Ctx), ShadowTy, /*isVarArg=*/false); Type *DFSanMemTransferCallbackArgs[2] = {ShadowPtrTy, IntptrTy}; DFSanMemTransferCallbackFnTy = @@ -809,11 +814,13 @@ DFSanVarargWrapperFnTy); DFSanLoadCallbackFn = Mod->getOrInsertFunction("__dfsan_load_callback", - DFSanLoadStoreCallbackFnTy); - DFSanStoreCallbackFn = Mod->getOrInsertFunction("__dfsan_store_callback", - DFSanLoadStoreCallbackFnTy); + DFSanLoadStoreCmpCallbackFnTy); + DFSanStoreCallbackFn = Mod->getOrInsertFunction( + "__dfsan_store_callback", DFSanLoadStoreCmpCallbackFnTy); DFSanMemTransferCallbackFn = Mod->getOrInsertFunction( "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy); + DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback", + DFSanLoadStoreCmpCallbackFnTy); std::vector FnsToInstrument; SmallPtrSet FnsWithNativeABI; @@ -828,7 +835,8 @@ &i != DFSanVarargWrapperFn.getCallee()->stripPointerCasts() && &i != DFSanLoadCallbackFn.getCallee()->stripPointerCasts() && &i != DFSanStoreCallbackFn.getCallee()->stripPointerCasts() && - &i != DFSanMemTransferCallbackFn.getCallee()->stripPointerCasts()) + &i != DFSanMemTransferCallbackFn.getCallee()->stripPointerCasts() && + &i != DFSanCmpCallbackFn.getCallee()->stripPointerCasts()) FnsToInstrument.push_back(&i); } @@ -1212,9 +1220,10 @@ return Shadow; } -void DFSanVisitor::visitOperandShadowInst(Instruction &I) { +Value *DFSanVisitor::visitOperandShadowInst(Instruction &I) { Value *CombinedShadow = DFSF.combineOperandShadows(&I); DFSF.setShadow(&I, CombinedShadow); + return CombinedShadow; } // Generates IR to load shadow corresponding to bytes [Addr, Addr+Size), where @@ -1451,7 +1460,13 @@ void DFSanVisitor::visitCastInst(CastInst &CI) { visitOperandShadowInst(CI); } -void DFSanVisitor::visitCmpInst(CmpInst &CI) { visitOperandShadowInst(CI); } +void DFSanVisitor::visitCmpInst(CmpInst &CI) { + Value *CombinedShadow = visitOperandShadowInst(CI); + if (ClEventCallbacks) { + IRBuilder<> IRB(&CI); + IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow); + } +} void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) { visitOperandShadowInst(GEPI);