[AArch64][PAC] Emit !dbg locations in *_vfpthunk_ functions#179688
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Anatoly Trosinenko (atrosinenko) ChangesIn absence of 2 Files Affected:
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index a6c80cd083bb8..63cb4b6989917 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3479,6 +3479,10 @@ ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
FunctionArgs, MD->getLocation(), SourceLocation());
+
+ // Emit an artificial location for this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
+
llvm::Value *ThisVal = loadIncomingCXXThis(CGF);
setCXXABIThisValue(CGF, ThisVal);
diff --git a/clang/test/DebugInfo/CXX/ptrauth-member-function-pointer-debuglocs.cpp b/clang/test/DebugInfo/CXX/ptrauth-member-function-pointer-debuglocs.cpp
new file mode 100644
index 0000000000000..cfc10a5207087
--- /dev/null
+++ b/clang/test/DebugInfo/CXX/ptrauth-member-function-pointer-debuglocs.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \
+// RUN: -emit-llvm -std=c++11 -O1 -disable-llvm-passes \
+// RUN: -debug-info-kind=limited %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
+// RUN: -emit-llvm -std=c++11 -O1 -disable-llvm-passes \
+// RUN: -debug-info-kind=limited %s -o - | FileCheck %s
+
+// Check that compiler-generated *_vfpthunk_ function has a !dbg location
+// attached to the call instruction.
+
+// CHECK: define {{.*}}@_ZN1A2f0Ev_vfpthunk_{{.*}} !dbg
+// CHECK-NOT: define
+// CHECK: musttail call void %{{[0-9]+}}(ptr
+// CHECK-SAME: [ "ptrauth"(i32 0, i64 %{{[0-9]+}}) ]
+// CHECK-SAME: !dbg
+
+volatile long T;
+
+struct A {
+ virtual void f0() {
+ T = 0;
+ }
+};
+typedef void (A::*MFP)();
+
+void caller() {
+ A a;
+
+ MFP x = &A::f0;
+ (a.*x)();
+}
|
ojhunt
left a comment
There was a problem hiding this comment.
Code change is fine, but I'd like the test to be a bit more thorough about verifying the emitted info and info linkage
| FunctionArgs, MD->getLocation(), SourceLocation()); | ||
|
|
||
| // Emit an artificial location for this function. | ||
| auto AL = ApplyDebugLocation::CreateArtificial(CGF); |
There was a problem hiding this comment.
Is there really nothing better that we can do? I guess not as anything else would be confusing.
It would be nice if there was a way do say
// Compiler generated code
T virtual_member_thunk_for_X(this, ...) {
return this->virtualFunction(); // You are here
}But that's so very far outside of the scope of this PR :D
| // CHECK: define {{.*}}@_ZN1A2f0Ev_vfpthunk_{{.*}} !dbg | ||
| // CHECK-NOT: define | ||
| // CHECK: musttail call void %{{[0-9]+}}(ptr | ||
| // CHECK-SAME: [ "ptrauth"(i32 0, i64 %{{[0-9]+}}) ] |
There was a problem hiding this comment.
I would prefer to include the diversifier here
There was a problem hiding this comment.
Added matching of the corresponding call to @llvm.ptrauth.blend in ee7d2b7.
| // CHECK-NOT: define | ||
| // CHECK: musttail call void %{{[0-9]+}}(ptr | ||
| // CHECK-SAME: [ "ptrauth"(i32 0, i64 %{{[0-9]+}}) ] | ||
| // CHECK-SAME: !dbg |
There was a problem hiding this comment.
include the debug info index and the required debug identities so we can record that the pseudo address correctly ties to the thunk scope
e.g.
musttail .... !dbg [[DEBUG_INDEX:![0-9]+]]
[[SCOPE_INDEX:![0-9]+]] = distinct !DISubprogram(linkageName: "_ZN1A2f0Ev_vfpthunk_",
[[DEBUG_INDEX]] = !DILocation(line: 0, scope: [[SCOPE_INDEX]])There was a problem hiding this comment.
Added more checks in ee7d2b7, thank you.
For the record, here is the code that is generated for both triples (except for the difference in the particular metadata indices):
define linkonce_odr hidden void @_ZN1A2f0Ev_vfpthunk_(ptr noundef %this) #3 !dbg !63 {
entry:
%this.addr = alloca ptr, align 8
store ptr %this, ptr %this.addr, align 8, !tbaa !58
%this1 = load ptr, ptr %this.addr, align 8, !dbg !65
%0 = load ptr, ptr %this.addr, align 8, !dbg !65, !tbaa !58
%vtable = load ptr, ptr %this1, align 8, !dbg !65, !tbaa !49
%1 = ptrtoint ptr %vtable to i64, !dbg !65
%2 = call i64 @llvm.ptrauth.auth(i64 %1, i32 2, i64 0), !dbg !65
%3 = inttoptr i64 %2 to ptr, !dbg !65
%vfn = getelementptr inbounds ptr, ptr %3, i64 0, !dbg !65
%4 = load ptr, ptr %vfn, align 8, !dbg !65
%5 = ptrtoint ptr %vfn to i64, !dbg !65
%6 = call i64 @llvm.ptrauth.blend(i64 %5, i64 9385), !dbg !65
musttail call void %4(ptr noundef nonnull align 8 dereferenceable(8) %0) [ "ptrauth"(i32 0, i64 %6) ], !dbg !65
ret void, !dbg !65
7: ; No predecessors!
ret void, !dbg !65
8: ; No predecessors!
ret void, !dbg !65
}That is, alloca and store has no !dbg attached, all other instructions refer to !65 and the function itself refers to !63. Here are metadata nodes:
!63 = distinct !DISubprogram(linkageName: "_ZN1A2f0Ev_vfpthunk_", scope: !10, file: !10, line: 28, type: !64, flags: DIFlagArtificial | DIFlagThunk, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
!64 = !DISubroutineType(types: !51)
!65 = !DILocation(line: 0, scope: !63)There was a problem hiding this comment.
It would be nice if the PR description could be slightly enhanced. Particularly, these things do not seem clear for me after reading the PR description:
- Why is this issue specific for virtual function pointer thunks
- Why the issue is pauth-specific and does not occur with pauth disabled
I would be happy to take another look at the changes when we have answers for these questions.
ee7d2b7 to
271506f
Compare
atrosinenko
left a comment
There was a problem hiding this comment.
@kovdan01 Clarified the description, thanks! Hopefully this resolves your other questions as well.
|
Thanks @atrosinenko for answering my previous questions! Everything became much clearer, and I've resolved my previous comments. The changes LGTM if nobody else has objections on merging this. I also suppose that you might want to rebase the changes in order to re-trigger CI builds - current failures seem unrelated (smth wrong with lldb) |
|
@ojhunt Could you please take another look at the PR? You've previously requested changes for this PR and, as far as I can see, your previous comments should now be addressed. |
In absence of `!dbg` metadata, it is possible for indirect
authenticated call to be replaced with a direct call instruction
without `!dbg` metadata. This may result in an error reported by
LLVM IR verifier ("inlinable function call in a function with
debug info must have a !dbg location") or an assertion triggered
after inlining this call ("!dbg attachment points at wrong
subprogram for function").
271506f to
b0d0e2e
Compare
|
Ping |
|
Ping. |
…-pauthtest' builder. Added '-fno-inline' compiler flag to avoid clang crash. See: llvm/llvm-project#179688
…-pauthtest' builder. (#773) Added '-fno-inline' compiler flag to avoid clang crash. See: llvm/llvm-project#179688
|
@ojhunt Could you please take another look at the PR? You've previously requested changes for this PR and, as far as I can see, your previous comments should now be addressed. While this PR is unmerged, the pauthtest buildbot has to use |
…aarch64-pauthtest' builder. Added '-fno-inline' compiler flag to avoid clang crash. See: llvm/llvm-project#179688 Reland PR llvm#773 with fixed options for the testsuite compiler llvm#773
…aarch64-pauthtest' builder. (#774) Added '-fno-inline' compiler flag to avoid clang crash. See: llvm/llvm-project#179688 Reland PR #773 with fixed options for the testsuite compiler (#773)
|
/cherry-pick 903acc2 |
|
/pull-request #184166 |
…#179688) The usage of pointers to member functions with Pointer Authentication requires generation of `*_vfpthunk_` functions. These thunk functions can be later inlined and optimized by replacing the indirect call instruction with a direct one and then inlining that function call. In absence of `!dbg` metadata attached to the original call instruction, such inlining ultimately results in an assertion "!dbg attachment points at wrong subprogram for function" in the assertions-enabled builds. By manually executing `opt` with `-verify-each` option on the LLVM IR produced by the frontend, an actual issue can be observed: "inlinable function call in a function with debug info must have a !dbg location" after the replacement of indirect call instruction with the direct one takes place. This commit fixes the issue by attaching artificial `!dbg` locations to the original call instruction (as well as most other instructions in `*_vfpthunk_` function) the same way it is done for other compiler-generated helper functions.
…#179688) The usage of pointers to member functions with Pointer Authentication requires generation of `*_vfpthunk_` functions. These thunk functions can be later inlined and optimized by replacing the indirect call instruction with a direct one and then inlining that function call. In absence of `!dbg` metadata attached to the original call instruction, such inlining ultimately results in an assertion "!dbg attachment points at wrong subprogram for function" in the assertions-enabled builds. By manually executing `opt` with `-verify-each` option on the LLVM IR produced by the frontend, an actual issue can be observed: "inlinable function call in a function with debug info must have a !dbg location" after the replacement of indirect call instruction with the direct one takes place. This commit fixes the issue by attaching artificial `!dbg` locations to the original call instruction (as well as most other instructions in `*_vfpthunk_` function) the same way it is done for other compiler-generated helper functions.
…#179688) The usage of pointers to member functions with Pointer Authentication requires generation of `*_vfpthunk_` functions. These thunk functions can be later inlined and optimized by replacing the indirect call instruction with a direct one and then inlining that function call. In absence of `!dbg` metadata attached to the original call instruction, such inlining ultimately results in an assertion "!dbg attachment points at wrong subprogram for function" in the assertions-enabled builds. By manually executing `opt` with `-verify-each` option on the LLVM IR produced by the frontend, an actual issue can be observed: "inlinable function call in a function with debug info must have a !dbg location" after the replacement of indirect call instruction with the direct one takes place. This commit fixes the issue by attaching artificial `!dbg` locations to the original call instruction (as well as most other instructions in `*_vfpthunk_` function) the same way it is done for other compiler-generated helper functions. (cherry picked from commit 903acc2)
The usage of pointers to member functions with Pointer Authentication requires generation of
*_vfpthunk_functions. These thunk functions can be later inlined and optimized by replacing the indirect call instruction with a direct one and then inlining that function call.In absence of
!dbgmetadata attached to the original call instruction, such inlining ultimately results in an assertion "!dbg attachment points at wrong subprogram for function" in the assertions-enabled builds. By manually executingoptwith-verify-eachoption on the LLVM IR produced by the frontend, an actual issue can be observed: "inlinable function call in a function with debug info must have a !dbg location" after the replacement of indirect call instruction with the direct one takes place.This commit fixes the issue by attaching artificial
!dbglocations to the original call instruction (as well as most other instructions in*_vfpthunk_function) the same way it is done for other compiler-generated helper functions.