Skip to content

[ASan][AMDGPU] Fix Assertion Failure. #78710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 0 commits into from

Conversation

ampandey-1995
Copy link
Contributor

Assertion failure `(i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && "Calling a function with a bad signature!"'. The 'llvm.memcpy' intercepted by ASan instrumentation pass is implemented by it's own __asan_memcpy implementation. The second argument of llvm.memcpy accepts ptr to addrspace(4), __asan_memcpy also has to follow ptr to addrspace(4) convention.

@ampandey-1995 ampandey-1995 requested a review from arsenm January 19, 2024 12:57
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Jan 19, 2024

@llvm/pr-subscribers-llvm-transforms
@llvm/pr-subscribers-compiler-rt-sanitizer

@llvm/pr-subscribers-backend-amdgpu

Author: None (ampandey-1995)

Changes

Assertion failure `(i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && "Calling a function with a bad signature!"'. The 'llvm.memcpy' intercepted by ASan instrumentation pass is implemented by it's own __asan_memcpy implementation. The second argument of llvm.memcpy accepts ptr to addrspace(4), __asan_memcpy also has to follow ptr to addrspace(4) convention.


Full diff: https://github.com/llvm/llvm-project/pull/78710.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp (+2-1)
  • (added) llvm/test/Instrumentation/AddressSanitizer/AMDGPU/asan_instrument_mem_intrinsics.ll (+67)
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index caab98c732eeeb..4a9e8119203438 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1255,7 +1255,8 @@ void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
   InstrumentationIRBuilder IRB(MI);
   if (isa<MemTransferInst>(MI)) {
     IRB.CreateCall(isa<MemMoveInst>(MI) ? AsanMemmove : AsanMemcpy,
-                   {MI->getOperand(0), MI->getOperand(1),
+                   {IRB.CreateAddrSpaceCast(MI->getOperand(0), PtrTy),
+                    IRB.CreateAddrSpaceCast(MI->getOperand(1), PtrTy),
                     IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
   } else if (isa<MemSetInst>(MI)) {
     IRB.CreateCall(
diff --git a/llvm/test/Instrumentation/AddressSanitizer/AMDGPU/asan_instrument_mem_intrinsics.ll b/llvm/test/Instrumentation/AddressSanitizer/AMDGPU/asan_instrument_mem_intrinsics.ll
new file mode 100644
index 00000000000000..f2f30592f500e8
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/AMDGPU/asan_instrument_mem_intrinsics.ll
@@ -0,0 +1,67 @@
+;RUN: opt < %s -passes=asan -S | FileCheck %s
+
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
+target triple = "amdgcn-amd-amdhsa"
+
+@__const.__src__0 = private unnamed_addr constant [12 x i8] c"oldstring_0\00", align 16
+@__const.__dest__0 = private unnamed_addr constant [12 x i8] c"newstring_0\00", align 16
+@__const.__src__1 = private unnamed_addr addrspace(4) constant [12 x i8] c"oldstring_1\00", align 16
+@__const.__dest__1 = private unnamed_addr addrspace(4) constant [12 x i8] c"newstring_1\00", align 16
+
+declare void @llvm.memcpy.p0.p0.i64(ptr addrspace(4) noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
+declare void @llvm.memcpy.p0.p1.i64(ptr noalias nocapture writeonly, ptr addrspace(4) noalias nocapture readonly, i64, i1 immarg)
+declare void @llvm.memcpy.p0.p2.i64(ptr addrspace(4) noalias nocapture writeonly, ptr addrspace(4) noalias nocapture readonly, i64, i1 immarg)
+
+declare void @llvm.memcpy.p0.p0.i32(ptr addrspace(4) noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
+declare void @llvm.memcpy.p0.p1.i32(ptr noalias nocapture writeonly, ptr addrspace(4) noalias nocapture readonly, i32, i1 immarg)
+declare void @llvm.memcpy.p0.p2.i32(ptr addrspace(4) noalias nocapture writeonly, ptr addrspace(4) noalias nocapture readonly, i32, i1 immarg)
+
+declare void @llvm.memmove.p0.p0.i64(ptr addrspace(4) nocapture writeonly, ptr nocapture readonly, i64, i1 immarg)
+declare void @llvm.memmove.p0.p1.i64(ptr nocapture writeonly, ptr addrspace(4) nocapture readonly, i64, i1 immarg)
+declare void @llvm.memmove.p0.p2.i64(ptr addrspace(4) nocapture writeonly, ptr addrspace(4) nocapture readonly, i64, i1 immarg)
+
+declare void @llvm.memmove.p0.p0.i32(ptr addrspace(4) nocapture writeonly, ptr nocapture readonly, i32, i1 immarg)
+declare void @llvm.memmove.p0.p1.i32(ptr nocapture writeonly, ptr addrspace(4) nocapture readonly, i32, i1 immarg)
+declare void @llvm.memmove.p0.p2.i32(ptr addrspace(4) nocapture writeonly, ptr addrspace(4) nocapture readonly, i32, i1 immarg)
+
+define weak hidden void @test_mem_intrinsic_memcpy() sanitize_address {
+; CHECK: define weak hidden void @test_mem_intrinsic_memcpy() #0 {
+; CHECK-NEXT:	entry:
+; CHECK-NEXT: %0 = call ptr @__asan_memcpy(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr @__const.__src__0, i64 12)
+; CHECK-NEXT: %1 = call ptr @__asan_memcpy(ptr @__const.__dest__0, ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: %2 = call ptr @__asan_memcpy(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: %3 = call ptr @__asan_memcpy(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr @__const.__src__0, i64 12)
+; CHECK-NEXT: %4 = call ptr @__asan_memcpy(ptr @__const.__dest__0, ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: %5 = call ptr @__asan_memcpy(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: ret void
+entry:
+  call void @llvm.memcpy.p0.p0.i64(ptr addrspace(4) align 16 @__const.__dest__1, ptr align 16 @__const.__src__0, i64 12, i1 false)
+  call void @llvm.memcpy.p0.p1.i64(ptr align 16 @__const.__dest__0, ptr addrspace(4) align 16 @__const.__src__1, i64 12, i1 false)
+  call void @llvm.memcpy.p0.p2.i64(ptr addrspace(4) align 16 @__const.__dest__1, ptr addrspace(4) align 16 @__const.__src__1, i64 12, i1 false)
+  call void @llvm.memcpy.p0.p0.i32(ptr addrspace(4) align 16 @__const.__dest__1, ptr align 16 @__const.__src__0, i32 12, i1 false)
+  call void @llvm.memcpy.p0.p1.i32(ptr align 16 @__const.__dest__0, ptr addrspace(4) align 16 @__const.__src__1, i32 12, i1 false)
+  call void @llvm.memcpy.p0.p2.i32(ptr addrspace(4) align 16 @__const.__dest__1, ptr addrspace(4) align 16 @__const.__src__1, i32 12, i1 false)
+  ret void
+}
+
+define dso_local void @test_mem_intrinsic_memmove() sanitize_address {
+; CHECK: define dso_local void @test_mem_intrinsic_memmove() #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %0 = call ptr @__asan_memmove(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr @__const.__src__0, i64 12)
+; CHECK-NEXT: %1 = call ptr @__asan_memmove(ptr @__const.__dest__0, ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: %2 = call ptr @__asan_memmove(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: %3 = call ptr @__asan_memmove(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr @__const.__src__0, i64 12)
+; CHECK-NEXT: %4 = call ptr @__asan_memmove(ptr @__const.__dest__0, ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: %5 = call ptr @__asan_memmove(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
+; CHECK-NEXT: ret void
+entry:
+  call void @llvm.memmove.p0.p0.i64(ptr addrspace(4) align 16 @__const.__dest__1, ptr align 16 @__const.__src__0, i64 12, i1 false)
+  call void @llvm.memmove.p0.p1.i64(ptr align 16 @__const.__dest__0, ptr addrspace(4) align 16 @__const.__src__1, i64 12, i1 false)
+  call void @llvm.memmove.p0.p2.i64(ptr addrspace(4) align 16 @__const.__dest__1, ptr addrspace(4) align 16 @__const.__src__1, i64 12, i1 false)
+  call void @llvm.memmove.p0.p0.i32(ptr addrspace(4) align 16 @__const.__dest__1, ptr align 16 @__const.__src__0, i32 12, i1 false)
+  call void @llvm.memmove.p0.p1.i32(ptr align 16 @__const.__dest__0, ptr addrspace(4) align 16 @__const.__src__1, i32 12, i1 false)
+  call void @llvm.memmove.p0.p2.i32(ptr addrspace(4) align 16 @__const.__dest__1, ptr addrspace(4) align 16 @__const.__src__1, i32 12, i1 false)
+  ret void
+}
+
+attributes #0 = { sanitize_address }

; CHECK-NEXT: %5 = call ptr @__asan_memcpy(ptr addrspacecast (ptr addrspace(4) @__const.__dest__1 to ptr), ptr addrspacecast (ptr addrspace(4) @__const.__src__1 to ptr), i64 12)
; CHECK-NEXT: ret void
entry:
call void @llvm.memcpy.p0.p0.i64(ptr addrspace(4) align 16 @__const.__dest__1, ptr align 16 @__const.__src__0, i64 12, i1 false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be more helpful to test with a non-constant pointer value, such that a true instruction needs to be emitted and not a ConstantExp. The ConstantExpr avoids testing the instruction placement

@@ -1255,7 +1255,8 @@ void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
InstrumentationIRBuilder IRB(MI);
if (isa<MemTransferInst>(MI)) {
IRB.CreateCall(isa<MemMoveInst>(MI) ? AsanMemmove : AsanMemcpy,
{MI->getOperand(0), MI->getOperand(1),
{IRB.CreateAddrSpaceCast(MI->getOperand(0), PtrTy),
IRB.CreateAddrSpaceCast(MI->getOperand(1), PtrTy),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need it in memset?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need currently this for memset.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be needed for any memory intrinsic

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be needed for any memory intrinsic

Logically we should never see an attempt to set memory with a pointer to constant memory, but I think we need to handle memset otherwise.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess never-const applies to the first arg of memcpy, but the patch adds CreateAddrSpaceCast?
So maybe use CreateAddrSpaceCast for all intrinsics for consistency

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be needed for any memory intrinsic

Logically we should never see an attempt to set memory with a pointer to constant memory, but I think we need to handle memset otherwise.

The "constant" part here isn't what matters, it's the non-0 address space

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi all,

The latest PR is #79795 to fix this issue.
Thanks again for all of your inputs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants