-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[aarch64] XOR the frame pointer with the stack cookie when protecting the stack #161114
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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-selectiondag @llvm/pr-subscribers-backend-aarch64 Author: Pan Tao (PanTao2) ChangesFull diff: https://github.com/llvm/llvm-project/pull/161114.diff 3 Files Affected:
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index a4c1e265f0e63..fffc060bbe7cd 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -28818,7 +28818,17 @@ void AArch64TargetLowering::ReplaceNodeResults(
bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const {
if (Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())
return TargetLowering::useLoadStackGuardNode(M);
- return true;
+ return false;
+}
+
+bool AArch64TargetLowering::useStackGuardXorFP() const { return true; }
+
+SDValue AArch64TargetLowering::emitStackGuardXorFP(SelectionDAG &DAG,
+ SDValue Val,
+ const SDLoc &DL) const {
+ return DAG.getNode(
+ ISD::XOR, DL, Val.getValueType(), Val,
+ DAG.getRegister(getStackPointerRegisterToSaveRestore(), MVT::i64));
}
unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const {
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index d8072d15853ee..8073b0677a11b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -349,6 +349,9 @@ class AArch64TargetLowering : public TargetLowering {
shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override;
bool useLoadStackGuardNode(const Module &M) const override;
+ bool useStackGuardXorFP() const override;
+ SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL) const override;
TargetLoweringBase::LegalizeTypeAction
getPreferredVectorAction(MVT VT) const override;
diff --git a/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp b/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp
index d3b1aa621b61a..163de52386221 100644
--- a/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp
@@ -32,7 +32,7 @@ AArch64SelectionDAGInfo::AArch64SelectionDAGInfo()
void AArch64SelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
const SDNode *N) const {
- SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N);
+ // SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N);
#ifndef NDEBUG
// Some additional checks not yet implemented by verifyTargetNode.
|
@efriedma-quic Could you please review this PR? Is AArch64SelectionDAGInfo::verifyTargetNode() necessary? Only RISCV and AArch64 have implemented this function. |
void AArch64SelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG, | ||
const SDNode *N) const { | ||
SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N); | ||
// SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N); |
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.
Not sure why you're commenting this out?
verifyTargetNode is there to allow targets to implement additional verification for target-specific nodes, to try to catch mistakes early. It isn't strictly necessary to implement it for new nodes, but it's nice to have.
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.
Thank you for your review and explanation!
There is fatal error:
LLVM ERROR: invalid node: operand #0 has invalid type; expected ch, got i64
t18: ch = AArch64ISD::BRCOND t3, BasicBlock:ch<entry 0x59e981fa35b0>, Constant:i32<1>, t16:1
t3: i64,ch = load<(volatile load (s64) from %stack.0.StackGuardSlot)> t0, FrameIndex:i64<0>, undef:i64
t16: i64,i32 = AArch64ISD::SUBS t8, t6
This fatal error is triggered by the following stack:
llvm::report_fatal_error
checkOperandType
llvm::SDNodeInfo::verifyNode "if (HasChain) checkOperandType(DAG, N, 0, MVT::Other);"
llvm::SelectionDAGGenTargetInfo::verifyTargetNode
llvm::AArch64SelectionDAGInfo::verifyTargetNode
What do you suggest in this situation?
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.
That's an actual issue with the structure of the DAG: a node which is supposed to have a chain as the first operand has an operand that isn't a chain. I suspect there's some code that's supposed to return the chain of the load, but is accidentally returning the value of the load instead. (An SDValue is a struct with two members: an SDNode*, and an integer for which result of the SDNode is being referenced.)
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.
This might not be relevant if you switch away from modifying useLoadStackGuardNode.
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.
Yes, this is not relevant after removing the modification of useLoadStackGuardNode.
; WINDOWS-AARCH64: adrp x8, __security_cookie | ||
; WINDOWS-AARCH64: ldr x8, [x8, :lo12:__security_cookie] | ||
; WINDOWS-AARCH64: adrp x19, __security_cookie | ||
; WINDOWS-AARCH64: ldr x8, [x19, :lo12:__security_cookie] |
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.
It's probably worth making the test check for the "eor" instruction.
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.
I added test check for the "eor" instruction.
@@ -28965,7 +28965,25 @@ void AArch64TargetLowering::ReplaceNodeResults( | |||
bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const { |
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.
I'd prefer not to disable useLoadStackGuardNode; it provides additional protection because it prevents later optimizations from incorrectly hoisting the address computations.
You can add the EOR instruction in AArch64InstrInfo::expandPostRAPseudo.
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.
I added the EOR instruction in AArch64InstrInfo::expandPostRAPseudo. Could you please further review it?
if (Subtarget.getTargetTriple().isOSMSVCRT() && | ||
!Subtarget.getTargetLowering() | ||
->getTargetMachine() | ||
.Options.EnableGlobalISel) { |
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.
Do we need the EnableGlobalISel check here?
Probably needs a comment explaining why we're doing this specifically for for MSVCRT targets (to match MSVC).
Can we move this outside the if statement, so it doesn't depend on the code model? We should usually be using small code model for Windows targets, due to the inherent limits of PE-COFF, but some unusual configs like JITs can use other code models.
This strengthens the guard and matches MSVC.
Fixes #156573 .