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 @@ -169,8 +169,8 @@ // // 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_load_callback(dfsan_label Label, void* addr); +// void __dfsan_store_callback(dfsan_label Label, void* addr); // void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len); // void __dfsan_cmp_callback(dfsan_label CombinedLabel); static cl::opt ClEventCallbacks( @@ -353,6 +353,7 @@ Module *Mod; LLVMContext *Ctx; + Type *Int8Ptr; IntegerType *ShadowTy; PointerType *ShadowPtrTy; IntegerType *IntptrTy; @@ -372,7 +373,8 @@ FunctionType *DFSanSetLabelFnTy; FunctionType *DFSanNonzeroLabelFnTy; FunctionType *DFSanVarargWrapperFnTy; - FunctionType *DFSanLoadStoreCmpCallbackFnTy; + FunctionType *DFSanCmpCallbackFnTy; + FunctionType *DFSanLoadStoreCallbackFnTy; FunctionType *DFSanMemTransferCallbackFnTy; FunctionCallee DFSanUnionFn; FunctionCallee DFSanCheckedUnionFn; @@ -575,6 +577,7 @@ Mod = &M; Ctx = &M.getContext(); + Int8Ptr = Type::getInt8PtrTy(*Ctx); ShadowTy = IntegerType::get(*Ctx, ShadowWidthBits); ShadowPtrTy = PointerType::getUnqual(ShadowTy); IntptrTy = DL.getIntPtrType(*Ctx); @@ -605,8 +608,12 @@ Type::getVoidTy(*Ctx), None, /*isVarArg=*/false); DFSanVarargWrapperFnTy = FunctionType::get( Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false); - DFSanLoadStoreCmpCallbackFnTy = - FunctionType::get(Type::getVoidTy(*Ctx), ShadowTy, /*isVarArg=*/false); + DFSanCmpCallbackFnTy = FunctionType::get(Type::getVoidTy(*Ctx), ShadowTy, + /*isVarArg=*/false); + Type *DFSanLoadStoreCallbackArgs[2] = {ShadowTy, Int8Ptr}; + DFSanLoadStoreCallbackFnTy = + FunctionType::get(Type::getVoidTy(*Ctx), DFSanLoadStoreCallbackArgs, + /*isVarArg=*/false); Type *DFSanMemTransferCallbackArgs[2] = {ShadowPtrTy, IntptrTy}; DFSanMemTransferCallbackFnTy = FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs, @@ -792,13 +799,13 @@ // Initializes event callback functions and declare them in the module void DataFlowSanitizer::initializeCallbackFunctions(Module &M) { DFSanLoadCallbackFn = Mod->getOrInsertFunction("__dfsan_load_callback", - DFSanLoadStoreCmpCallbackFnTy); - DFSanStoreCallbackFn = Mod->getOrInsertFunction( - "__dfsan_store_callback", DFSanLoadStoreCmpCallbackFnTy); + DFSanLoadStoreCallbackFnTy); + DFSanStoreCallbackFn = Mod->getOrInsertFunction("__dfsan_store_callback", + DFSanLoadStoreCallbackFnTy); DFSanMemTransferCallbackFn = Mod->getOrInsertFunction( "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy); - DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback", - DFSanLoadStoreCmpCallbackFnTy); + DFSanCmpCallbackFn = + Mod->getOrInsertFunction("__dfsan_cmp_callback", DFSanCmpCallbackFnTy); } bool DataFlowSanitizer::runImpl(Module &M) { @@ -1404,7 +1411,8 @@ DFSF.setShadow(&LI, Shadow); if (ClEventCallbacks) { IRBuilder<> IRB(&LI); - IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, Shadow); + Value *Addr8 = IRB.CreateBitCast(LI.getPointerOperand(), DFSF.DFS.Int8Ptr); + IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {Shadow, Addr8}); } } @@ -1477,7 +1485,8 @@ DFSF.storeShadow(SI.getPointerOperand(), Size, Alignment, Shadow, &SI); if (ClEventCallbacks) { IRBuilder<> IRB(&SI); - IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, Shadow); + Value *Addr8 = IRB.CreateBitCast(SI.getPointerOperand(), DFSF.DFS.Int8Ptr); + IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {Shadow, Addr8}); } } diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll b/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -dfsan -dfsan-event-callbacks=1 -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-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i8 @load8(i8* %p) { + ; CHECK: call void @__dfsan_load_callback(i16 %{{.*}}, i8* %p) + ; CHECK: %a = load i8, i8* %p + + %a = load i8, i8* %p + ret i8 %a +} + +define void @store8(i8* %p, i8 %a) { + ; CHECK: store i16 %[[l:.*]], i16* %{{.*}} + ; CHECK: call void @__dfsan_store_callback(i16 %[[l]], i8* %p) + ; CHECK: store i8 %a, i8* %p + + store i8 %a, i8* %p + ret void +} + +define i1 @cmp(i8 %a, i8 %b) { + ; CHECK: call void @__dfsan_cmp_callback(i16 %[[l:.*]]) + ; CHECK: %c = icmp ne i8 %a, %b + ; CHECK: store i16 %[[l]], i16* @__dfsan_retval_tls + + %c = icmp ne i8 %a, %b + ret i1 %c +} \ No newline at end of file