-
Notifications
You must be signed in to change notification settings - Fork 15.2k
release/21.x: [CodeGen][ARM64EC] Don't treat guest exit thunks as indirect calls (#165885) #168371
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
Conversation
…lvm#165885) Guest exit thunks serve as glue for performing direct calls, so they shouldn’t treat the target as an indirect one. Spotted by @coneco-cy in llvm#165504. (cherry picked from commit 6152999)
|
@efriedma-quic What do you think about merging this PR to the release branch? |
|
@llvm/pr-subscribers-backend-aarch64 Author: None (llvmbot) ChangesBackport 6152999 Requested by: @cjacek Full diff: https://github.com/llvm/llvm-project/pull/168371.diff 2 Files Affected:
diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
index 509cbb092705d..b4e1e3517fa64 100644
--- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
@@ -632,16 +632,10 @@ Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *F) {
BasicBlock *BB = BasicBlock::Create(M->getContext(), "", GuestExit);
IRBuilder<> B(BB);
- // Load the global symbol as a pointer to the check function.
- Value *GuardFn;
- if (cfguard_module_flag == 2 && !F->hasFnAttribute("guard_nocf"))
- GuardFn = GuardFnCFGlobal;
- else
- GuardFn = GuardFnGlobal;
- LoadInst *GuardCheckLoad = B.CreateLoad(PtrTy, GuardFn);
-
- // Create new call instruction. The CFGuard check should always be a call,
- // even if the original CallBase is an Invoke or CallBr instruction.
+ // Create new call instruction. The call check should always be a call,
+ // even if the original CallBase is an Invoke or CallBr instructio.
+ // This is treated as a direct call, so do not use GuardFnCFGlobal.
+ LoadInst *GuardCheckLoad = B.CreateLoad(PtrTy, GuardFnGlobal);
Function *Thunk = buildExitThunk(F->getFunctionType(), F->getAttributes());
CallInst *GuardCheck = B.CreateCall(
GuardFnType, GuardCheckLoad, {F, Thunk});
diff --git a/llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll b/llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll
index bdbc99e2d98b0..75e7ac902274d 100644
--- a/llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll
+++ b/llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll
@@ -2,15 +2,58 @@
declare void @called()
declare void @escaped()
-define void @f(ptr %dst) {
+define void @f(ptr %dst, ptr readonly %f) {
call void @called()
+; CHECK: bl "#called"
store ptr @escaped, ptr %dst
- ret void
+ call void %f()
+; CHECK: adrp x10, $iexit_thunk$cdecl$v$v
+; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$v
+; CHECK-NEXT: str x8, [x20]
+; CHECK-NEXT: adrp x8, __os_arm64x_check_icall_cfg
+; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall_cfg]
+; CHECK-NEXT: mov x11,
+; CHECK-NEXT: blr x8
+; CHECK-NEXT: blr x11
+ ret void
}
+; CHECK-LABEL: .def "#called$exit_thunk";
+; CHECK-NEXT: .scl 2;
+; CHECK-NEXT: .type 32;
+; CHECK-NEXT: .endef
+; CHECK-NEXT: .section .wowthk$aa,"xr",discard,"#called$exit_thunk"
+; CHECK-NEXT: .globl "#called$exit_thunk" // -- Begin function #called$exit_thunk
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: "#called$exit_thunk": // @"#called$exit_thunk"
+; CHECK-NEXT: .weak_anti_dep called
+; CHECK-NEXT: called = "#called"
+; CHECK-NEXT: .weak_anti_dep "#called"
+; CHECK-NEXT: "#called" = "#called$exit_thunk"
+; CHECK-NEXT: .seh_proc "#called$exit_thunk"
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT: .seh_save_reg_x x30, 16
+; CHECK-NEXT: .seh_endprologue
+; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
+; CHECK-NEXT: adrp x11, called
+; CHECK-NEXT: add x11, x11, :lo12:called
+; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
+; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$v
+; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$v
+; CHECK-NEXT: blr x8
+; CHECK-NEXT: .seh_startepilogue
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: .seh_save_reg_x x30, 16
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: br x11
+; CHECK-NEXT: .seh_endfunclet
+; CHECK-NEXT: .seh_endproc
+
!llvm.module.flags = !{!0}
-!0 = !{i32 2, !"cfguard", i32 1}
+!0 = !{i32 2, !"cfguard", i32 2}
; CHECK-LABEL: .section .gfids$y,"dr"
; CHECK-NEXT: .symidx escaped
+; CHECK-NEXT: .symidx $iexit_thunk$cdecl$v$v
; CHECK-NOT: .symidx
|
efriedma-quic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This is a simple bugfix, and it obviously has no impact on non-ARM64EC targets.
|
Hi, at this point in the 21.x release branch we are only accepting patches that fix regressions or major issues. Was the problem being fixed here a recent regression? From a quick look at the history, the code being replaced was introduced around the LLVM 18 time frame, so it has been around for a while. What are the implications if we do not accept this change into the 21.x release branch? Would something be broken that cannot be worked around or otherwise fixed without it? At this point, I am leaning towards not including the fix and waiting for LLVM 22 for it, but if you feel strongly that it should be included, please let us know why and I can consult with the other release managers to see how they feel on the issue. |
|
Waiting for LLVM 22 is fine with me. It seemed safe enough and fixes issue #165504, but at the same time it shouldn’t affect properly written code (the repro in the report doesn’t follow the ARM64EC convention). |
Backport 6152999
Requested by: @cjacek