-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[AArch64][PAC][GISel] Add missing clobbering info to LOADgotAUTH #157433
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
Here is an example of incorrect code generation: extern unsigned long pac_field_mask;
static void f() {}
unsigned long get_non_signed_function_pointer(void) {
return ((unsigned long)f) & ~pac_field_mask;
} Compiled at
With this patch applied
Compiled with
With this patch applied
|
@llvm/pr-subscribers-llvm-globalisel @llvm/pr-subscribers-backend-aarch64 Author: Anatoly Trosinenko (atrosinenko) ChangesWhen LOADgotAUTH is selected by GlobalISel, the existing MachineInstr is updated in-place instead of constructing a fresh instance by calling MIB.buildInstr(). This way, implicit-def operands have to be added manually for register allocator to take them into account. This patch fixes miscompilation possibility observed when compiling with GlobalISel enabled or at -O0 optimization level. Full diff: https://github.com/llvm/llvm-project/pull/157433.diff 2 Files Affected:
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 5748556d07285..b1843d92e2a93 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2914,10 +2914,15 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
}
if (OpFlags & AArch64II::MO_GOT) {
- I.setDesc(TII.get(MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
- ? AArch64::LOADgotAUTH
- : AArch64::LOADgot));
+ bool GOTIsSigned = MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT();
+ I.setDesc(TII.get(GOTIsSigned ? AArch64::LOADgotAUTH : AArch64::LOADgot));
I.getOperand(1).setTargetFlags(OpFlags);
+ if (GOTIsSigned) {
+ MachineInstrBuilder MIB(MF, I);
+ MIB.addDef(AArch64::X16, RegState::Implicit);
+ MIB.addDef(AArch64::X17, RegState::Implicit);
+ MIB.addDef(AArch64::NZCV, RegState::Implicit);
+ }
} else if (TM.getCodeModel() == CodeModel::Large &&
!TM.isPositionIndependent()) {
// Materialize the global using movz/movk instructions.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-elf-got.mir b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-elf-got.mir
new file mode 100644
index 0000000000000..faf2cb8221ec7
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-elf-got.mir
@@ -0,0 +1,23 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
+# RUN: llc -O0 -mtriple=aarch64-linux-gnu -relocation-model=pic -run-pass=instruction-select -global-isel-abort=1 -verify-machineinstrs %s -o - | FileCheck %s
+
+--- |
+ @var_got = external global i8
+ define ptr @loadgotauth_implicit_defs() { ret ptr null }
+
+ !llvm.module.flags = !{!0}
+ !0 = !{i32 8, !"ptrauth-elf-got", i32 1}
+...
+
+---
+name: loadgotauth_implicit_defs
+legalized: true
+regBankSelected: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: loadgotauth_implicit_defs
+ ; CHECK: [[LOADgotAUTH:%[0-9]+]]:gpr64common = LOADgotAUTH target-flags(aarch64-got) @var_got, implicit-def $x16, implicit-def $x17, implicit-def $nzcv
+ ; CHECK-NEXT: $x0 = COPY [[LOADgotAUTH]]
+ %0:gpr(p0) = G_GLOBAL_VALUE @var_got
+ $x0 = COPY %0(p0)
+...
|
I.getOperand(1).setTargetFlags(OpFlags); | ||
if (GOTIsSigned) { | ||
MachineInstrBuilder MIB(MF, I); | ||
MIB.addDef(AArch64::X16, RegState::Implicit); |
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.
Use addImplicitDefUseOperands, or build a fresh instruction instead of hardcoding this list of registers?
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.
Updated in 79230eb, thank you!
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 when objections from other reviewers are resolved
I.setDesc(TII.get(MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT() | ||
? AArch64::LOADgotAUTH | ||
: AArch64::LOADgot)); | ||
bool GOTIsSigned = MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT(); |
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.
Nit: maybe IsGOTSigned
would look better (having flag identifiers starting with 'is', 'has', ... seems to be a common convention).
This is completely optional and feel free to ignore.
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.
Sounds reasonable, thanks!
Restarted UPD:
with two failed test cases in each:
Furthermore, both Attempt 1 and Attempt 3 mention the same commit hash in its "Fetching the repository" build step:
I will try rebasing and re-pushing my branch to trigger a completely fresh re-run of the tests (assuming it may be the mainline commit that fails those tests). |
When LOADgotAUTH is selected by GlobalISel, the existing MachineInstr is updated in-place instead of constructing a fresh instance by calling MIB.buildInstr(). This way, implicit-def operands have to be added manually for register allocator to take them into account. This patch fixes miscompilation possibility observed when compiling with GlobalISel enabled or at -O0 optimization level.
79230eb
to
cafdddb
Compare
It finally helped to push the rebased branch to trigger a completely fresh run of the tests. |
bool IsGOTSigned = MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT(); | ||
I.setDesc(TII.get(IsGOTSigned ? AArch64::LOADgotAUTH : AArch64::LOADgot)); | ||
I.getOperand(1).setTargetFlags(OpFlags); | ||
if (IsGOTSigned) |
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.
Just do it unconditionally
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.
Updated in 4ef4947.
Ping. |
/cherry-pick cff5a43 |
/pull-request #160668 |
…m#157433) When LOADgotAUTH is selected by GlobalISel, the existing MachineInstr is updated in-place instead of constructing a fresh instance by calling MIB.buildInstr(). This way, implicit-def operands have to be added manually for machine passes to take them into account. This patch fixes miscompilation possibility observed when compiling with GlobalISel enabled or at -O0 optimization level.
When LOADgotAUTH is selected by GlobalISel, the existing MachineInstr is updated in-place instead of constructing a fresh instance by calling MIB.buildInstr(). This way, implicit-def operands have to be added manually for machine passes to take them into account.
This patch fixes miscompilation possibility observed when compiling with GlobalISel enabled or at -O0 optimization level.