diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -331,6 +331,11 @@ cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_")); +static cl::opt ClKasanMemIntrinCallbackPrefix( + "asan-kernel-mem-intrinsic-prefix", + cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, + cl::init(false)); + static cl::opt ClInstrumentDynamicAllocas("asan-instrument-dynamic-allocas", cl::desc("instrument dynamic allocas"), @@ -2729,7 +2734,9 @@ } const std::string MemIntrinCallbackPrefix = - CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix; + (CompileKernel && !ClKasanMemIntrinCallbackPrefix) + ? std::string("") + : ClMemoryAccessCallbackPrefix; AsanMemmove = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy); diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -83,6 +83,11 @@ cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_")); +static cl::opt ClKasanMemIntrinCallbackPrefix( + "hwasan-kernel-mem-intrinsic-prefix", + cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, + cl::init(false)); + static cl::opt ClInstrumentWithCalls( "hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, @@ -723,7 +728,9 @@ ArrayType::get(IRB.getInt8Ty(), 0)); const std::string MemIntrinCallbackPrefix = - CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix; + (CompileKernel && !ClKasanMemIntrinCallbackPrefix) + ? std::string("") + : ClMemoryAccessCallbackPrefix; HWAsanMemmove = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy); diff --git a/llvm/test/Instrumentation/AddressSanitizer/basic.ll b/llvm/test/Instrumentation/AddressSanitizer/basic.ll --- a/llvm/test/Instrumentation/AddressSanitizer/basic.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/basic.ll @@ -160,43 +160,6 @@ ; CHECK-NOT: __asan_report ; CHECK: ret i32 -declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind -declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind -declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind - -define void @memintr_test(i8* %a, i8* %b) nounwind uwtable sanitize_address { - entry: - tail call void @llvm.memset.p0i8.i64(i8* %a, i8 0, i64 100, i1 false) - tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) - tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) - ret void -} - -; CHECK-LABEL: memintr_test -; CHECK: __asan_memset -; CHECK: __asan_memmove -; CHECK: __asan_memcpy -; CHECK: ret void - -declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture writeonly, i8, i64, i32) nounwind -declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind -declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind - -define void @memintr_element_atomic_test(i8* %a, i8* %b) nounwind uwtable sanitize_address { - ; This is a canary test to make sure that these don't get lowered into calls that don't - ; have the element-atomic property. Eventually, asan will have to be enhanced to lower - ; these properly. - ; CHECK-LABEL: memintr_element_atomic_test - ; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1) - ; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) - ; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) - ; CHECK-NEXT: ret void - tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1) - tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) - tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) - ret void -} - ; CHECK-LABEL: @test_swifterror ; CHECK-NOT: __asan_report_load diff --git a/llvm/test/Instrumentation/AddressSanitizer/mem-intrinsics.ll b/llvm/test/Instrumentation/AddressSanitizer/mem-intrinsics.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/AddressSanitizer/mem-intrinsics.ll @@ -0,0 +1,60 @@ +; Test memory intrinsics instrumentation + +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck --check-prefixes=CHECK,CHECK-PREFIX %s +; RUN: opt < %s -passes='asan-pipeline' -asan-kernel -S | FileCheck --check-prefixes=CHECK,CHECK-NOPREFIX %s +; RUN: opt < %s -passes='asan-pipeline' -asan-kernel -asan-kernel-mem-intrinsic-prefix -S | FileCheck --check-prefixes=CHECK,CHECK-PREFIX %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" + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind +declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind + +define void @memintr_test(i8* %a, i8* %b) nounwind uwtable sanitize_address { + entry: + tail call void @llvm.memset.p0i8.i64(i8* %a, i8 0, i64 100, i1 false) + tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) + ret void +} +; CHECK-LABEL: memintr_test +; CHECK-PREFIX: @__asan_memset +; CHECK-PREFIX: @__asan_memmove +; CHECK-PREFIX: @__asan_memcpy +; CHECK-NOPREFIX: @memset +; CHECK-NOPREFIX: @memmove +; CHECK-NOPREFIX: @memcpy +; CHECK: ret void + +define void @memintr_test_nosanitize(i8* %a, i8* %b) nounwind uwtable { + entry: + tail call void @llvm.memset.p0i8.i64(i8* %a, i8 0, i64 100, i1 false) + tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) + ret void +} +; CHECK-LABEL: memintr_test_nosanitize +; CHECK: @llvm.memset +; CHECK: @llvm.memmove +; CHECK: @llvm.memcpy +; CHECK: ret void + +declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture writeonly, i8, i64, i32) nounwind +declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind +declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind + +define void @memintr_element_atomic_test(i8* %a, i8* %b) nounwind uwtable sanitize_address { + ; This is a canary test to make sure that these don't get lowered into calls that don't + ; have the element-atomic property. Eventually, asan will have to be enhanced to lower + ; these properly. + ; CHECK-LABEL: memintr_element_atomic_test + ; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1) + ; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) + ; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) + ; CHECK-NEXT: ret void + tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1) + tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) + tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1) + ret void +} diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/mem-intrinsics.ll b/llvm/test/Instrumentation/HWAddressSanitizer/mem-intrinsics.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/mem-intrinsics.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/mem-intrinsics.ll @@ -1,10 +1,13 @@ -; RUN: opt -S -passes=hwasan -hwasan-use-stack-safety=0 %s | FileCheck %s +; RUN: opt -S -passes=hwasan -hwasan-use-stack-safety=0 %s | FileCheck --check-prefixes=CHECK,CHECK-PREFIX %s +; RUN: opt -S -passes=hwasan -hwasan-kernel -hwasan-use-stack-safety=0 %s | FileCheck --check-prefixes=CHECK,CHECK-NOPREFIX %s +; RUN: opt -S -passes=hwasan -hwasan-kernel -hwasan-kernel-mem-intrinsic-prefix -hwasan-use-stack-safety=0 %s | FileCheck --check-prefixes=CHECK,CHECK-PREFIX %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main() sanitize_hwaddress { +; CHECK-LABEL: main entry: %retval = alloca i32, align 4 %Q = alloca [10 x i8], align 1 @@ -13,20 +16,23 @@ %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %Q, i32 0, i32 0 call void @llvm.memset.p0i8.i64(i8* align 1 %arraydecay, i8 0, i64 10, i1 false) -; CHECK: call i8* @__hwasan_memset +; CHECK-PREFIX: call i8* @__hwasan_memset +; CHECK-NOPREFIX: call i8* @memset %arraydecay1 = getelementptr inbounds [10 x i8], [10 x i8]* %Q, i32 0, i32 0 %arraydecay2 = getelementptr inbounds [10 x i8], [10 x i8]* %Q, i32 0, i32 0 %add.ptr = getelementptr inbounds i8, i8* %arraydecay2, i64 5 call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 %arraydecay1, i8* align 1 %add.ptr, i64 5, i1 false) -; CHECK: call i8* @__hwasan_memmove +; CHECK-PREFIX: call i8* @__hwasan_memmove +; CHECK-NOPREFIX: call i8* @memmove %arraydecay3 = getelementptr inbounds [10 x i8], [10 x i8]* %P, i32 0, i32 0 %arraydecay4 = getelementptr inbounds [10 x i8], [10 x i8]* %Q, i32 0, i32 0 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %arraydecay3, i8* align 1 %arraydecay4, i64 10, i1 false) -; CHECK: call i8* @__hwasan_memcpy +; CHECK-PREFIX: call i8* @__hwasan_memcpy +; CHECK-NOPREFIX: call i8* @memcpy ret i32 0 } @@ -38,3 +44,16 @@ ; Function Attrs: argmemonly nounwind declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) #1 + +define void @memintr_test_nosanitize(i8* %a, i8* %b) nounwind uwtable { + entry: + tail call void @llvm.memset.p0i8.i64(i8* %a, i8 0, i64 100, i1 false) + tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false) + ret void +} +; CHECK-LABEL: memintr_test_nosanitize +; CHECK: @llvm.memset +; CHECK: @llvm.memmove +; CHECK: @llvm.memcpy +; CHECK: ret void