Skip to content

Instantly share code, notes, and snippets.

@thestinger
Last active July 11, 2021 14:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thestinger/b8502a881d871fbc75d91bc00576157b to your computer and use it in GitHub Desktop.
Save thestinger/b8502a881d871fbc75d91bc00576157b to your computer and use it in GitHub Desktop.
-fstack-protector-all with return address XOR (per 1999 StackGuard)
  1. Tests!
  2. Configuration
  3. Clang user interface
  4. add a better heuristic to use with this than -fstack-protector-all ("can corrupt memory" -> canary)
  5. support leaving SelectionDAG SSP enabled for sibling call optimization compatibility

The AArch64 implementation is far from ideal performance-wise, since it depends on forcing the generation of a proper frame to store and load the return address. It's not clear how to improve this yet.

From bd09fa121deae36efa10d52b677faab55d86600b Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Sat, 2 Jul 2016 18:19:07 -0400
Subject: [PATCH] enhanced stack protector
This is an extension of the stack protector aimed at protecting the
return address against more than simple linear overflows. Immunix
StackGuard 1.21 from 1999 was an early implementation of this.
Before storing the canary value to the stack in the function prologue,
the return address of the function is mixed in with XOR. The epilogue
validates the canary by attempting to obtain the original canary value
via another XOR of the return address before checking it. This results
in the return address being validated directly.
This is primarily intended to be used with -fstack-protector-all, since
otherwise there will be unprotected return addresses.
A new internal returnaddress intrinsic is used in order to prevent the
load in the prologue and epilogue from being combined.
---
include/llvm/CodeGen/ISDOpcodes.h | 4 +++
include/llvm/IR/Intrinsics.td | 1 +
lib/CodeGen/IntrinsicLowering.cpp | 7 +++++-
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 2 ++
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 18 +++++++++++---
lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 1 +
lib/CodeGen/StackProtector.cpp | 31 +++++++++++++++++++-----
lib/Target/AArch64/AArch64ISelLowering.cpp | 25 +++++++++++++++++++
lib/Target/AArch64/AArch64ISelLowering.h | 1 +
lib/Target/X86/X86ISelLowering.cpp | 19 +++++++++++++++
lib/Target/X86/X86ISelLowering.h | 1 +
11 files changed, 100 insertions(+), 10 deletions(-)
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 89cb7a8..89b43c4 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -72,6 +72,10 @@ namespace ISD {
/// the parent's frame or return address, and so on.
FRAMEADDR, RETURNADDR,
+ // SSP_RETURNADDR - Represents the llvm.stackprotector_returnaddress
+ // intrinsic.
+ SSP_RETURNADDR,
+
/// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
/// Materializes the offset from the local object pointer of another
/// function to a particular local object passed to llvm.localescape. The
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index 5ece731..c7cfb3b 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -339,6 +339,7 @@ def int_assume : Intrinsic<[], [llvm_i1_ty], []>;
// guard to the correct place on the stack frame.
def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>;
def int_stackguard : Intrinsic<[llvm_ptr_ty], [], []>;
+def int_stackprotector_returnaddress : Intrinsic<[llvm_ptr_ty], [], []>;
// A counter increment for instrumentation based profiling.
def int_instrprof_increment : Intrinsic<[],
diff --git a/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp
index 2962f87..be48bdb 100644
--- a/lib/CodeGen/IntrinsicLowering.cpp
+++ b/lib/CodeGen/IntrinsicLowering.cpp
@@ -439,7 +439,12 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
CI->replaceAllUsesWith(ConstantPointerNull::get(
cast<PointerType>(CI->getType())));
break;
-
+ case Intrinsic::stackprotector_returnaddress:
+ errs() << "WARNING: this target does not support the"
+ " llvm.stackprotector_returnaddress intrinsic.\n";
+ CI->replaceAllUsesWith(ConstantPointerNull::get(
+ cast<PointerType>(CI->getType())));
+ break;
case Intrinsic::prefetch:
break; // Simply strip out prefetches on unsupported architectures
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index e81ea0d..b664be3 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1030,6 +1030,7 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
case ISD::ADJUST_TRAMPOLINE:
case ISD::FRAMEADDR:
case ISD::RETURNADDR:
+ case ISD::SSP_RETURNADDR:
// These operations lie about being legal: when they claim to be legal,
// they should actually be custom-lowered.
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
@@ -2760,6 +2761,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
break;
case ISD::FRAMEADDR:
case ISD::RETURNADDR:
+ case ISD::SSP_RETURNADDR:
case ISD::FRAME_TO_ARGS_OFFSET:
Results.push_back(DAG.getConstant(0, dl, Node->getValueType(0)));
break;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 27ee96d..6b3eb6c 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2080,7 +2080,8 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
// If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD.
// Otherwise, emit a volatile load to retrieve the stack guard value.
SDValue Chain = DAG.getEntryNode();
- if (TLI.useLoadStackGuardNode()) {
+ bool XorCanary = true;
+ if (TLI.useLoadStackGuardNode() && !XorCanary) {
Guard = getLoadStackGuard(DAG, dl, Chain);
} else {
const Value *IRGuard = TLI.getSDagStackGuard(M);
@@ -5354,7 +5355,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
MachineFunction &MF = DAG.getMachineFunction();
const Module &M = *MF.getFunction()->getParent();
SDValue Chain = getRoot();
- if (TLI.useLoadStackGuardNode()) {
+ bool XorCanary = true;
+ if (TLI.useLoadStackGuardNode() && !XorCanary) {
Res = getLoadStackGuard(DAG, sdl, Chain);
} else {
const Value *Global = TLI.getSDagStackGuard(M);
@@ -5374,7 +5376,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
EVT PtrTy = TLI.getPointerTy(DAG.getDataLayout());
SDValue Src, Chain = getRoot();
- if (TLI.useLoadStackGuardNode())
+ bool XorCanary = true;
+ if (TLI.useLoadStackGuardNode() && !XorCanary)
Src = getLoadStackGuard(DAG, sdl, Chain);
else
Src = getValue(I.getArgOperand(0)); // The guard's value.
@@ -5394,6 +5397,15 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
DAG.setRoot(Res);
return nullptr;
}
+ case Intrinsic::stackprotector_returnaddress: {
+ SDValue Chain = getRoot();
+ Res = DAG.getNode(ISD::SSP_RETURNADDR, sdl,
+ DAG.getVTList(TLI.getPointerTy(DAG.getDataLayout()), MVT::Other),
+ Chain);
+ setValue(&I, Res);
+ DAG.setRoot(Res.getValue(1));
+ return nullptr;
+ }
case Intrinsic::objectsize: {
// If we don't know by now, we're never going to know.
ConstantInt *CI = dyn_cast<ConstantInt>(I.getArgOperand(1));
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 401da05..bfdf694 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -100,6 +100,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::JumpTable: return "JumpTable";
case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
case ISD::RETURNADDR: return "RETURNADDR";
+ case ISD::SSP_RETURNADDR: return "SSP_RETURNADDR";
case ISD::FRAMEADDR: return "FRAMEADDR";
case ISD::LOCAL_RECOVER: return "LOCAL_RECOVER";
case ISD::READ_REGISTER: return "READ_REGISTER";
diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp
index 89868e4..e39ca9a 100644
--- a/lib/CodeGen/StackProtector.cpp
+++ b/lib/CodeGen/StackProtector.cpp
@@ -305,6 +305,18 @@ static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
return B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackguard));
}
+static Value *XorReturnAddress(Module *M, IRBuilder<> &B, Value *Ptr) {
+ const DataLayout &DL = M->getDataLayout();
+ Type *IntTy = DL.getIntPtrType(Ptr->getType());
+
+ Value *RetPtr = B.CreateCall(
+ Intrinsic::getDeclaration(M, Intrinsic::stackprotector_returnaddress));
+
+ Value *IntPtr = B.CreatePtrToInt(Ptr, IntTy);
+ Value *IntRetPtr = B.CreatePtrToInt(RetPtr, IntTy);
+ return B.CreateIntToPtr(B.CreateXor(IntPtr, IntRetPtr), Ptr->getType());
+}
+
/// Insert code into the entry block that stores the stack guard
/// variable onto the stack:
///
@@ -323,8 +335,10 @@ static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI,
AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP);
+ Value *XorGuard = XorReturnAddress(M, B, GuardSlot);
+
B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),
- {GuardSlot, AI});
+ {XorGuard, AI});
return SupportsSelectionDAGSP;
}
@@ -335,8 +349,9 @@ static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI,
/// - The epilogue checks the value stored in the prologue against the original
/// value. It calls __stack_chk_fail if they differ.
bool StackProtector::InsertStackProtectors() {
+ bool XorCanary = true;
bool SupportsSelectionDAGSP =
- EnableSelectionDAGSP && !TM->Options.EnableFastISel;
+ EnableSelectionDAGSP && !TM->Options.EnableFastISel && !XorCanary;
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
for (Function::iterator I = F->begin(), E = F->end(); I != E;) {
@@ -368,8 +383,10 @@ bool StackProtector::InsertStackProtectors() {
// Generate the function-based epilogue instrumentation.
// The target provides a guard check function, generate a call to it.
IRBuilder<> B(RI);
- LoadInst *Guard = B.CreateLoad(AI, true, "Guard");
- CallInst *Call = B.CreateCall(GuardCheck, {Guard});
+ Value *Guard = B.CreateLoad(AI, true, "Guard");
+ Value *XorGuard = XorReturnAddress(M, B, Guard);
+
+ CallInst *Call = B.CreateCall(GuardCheck, {XorGuard});
llvm::Function *Function = cast<llvm::Function>(GuardCheck);
Call->setAttributes(Function->getAttributes());
Call->setCallingConv(Function->getCallingConv());
@@ -424,8 +441,10 @@ bool StackProtector::InsertStackProtectors() {
// Generate the stack protector instructions in the old basic block.
IRBuilder<> B(BB);
Value *Guard = getStackGuard(TLI, M, B);
- LoadInst *LI2 = B.CreateLoad(AI, true);
- Value *Cmp = B.CreateICmpEQ(Guard, LI2);
+ Value *LI2 = B.CreateLoad(AI, true);
+ Value *XorGuard = XorReturnAddress(M, B, LI2);
+
+ Value *Cmp = B.CreateICmpEQ(Guard, XorGuard);
auto SuccessProb =
BranchProbabilityInfo::getBranchProbStackProtector(true);
auto FailureProb =
diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp
index d7d4032..e6119c0 100644
--- a/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2362,6 +2362,8 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
return LowerFRAMEADDR(Op, DAG);
case ISD::RETURNADDR:
return LowerRETURNADDR(Op, DAG);
+ case ISD::SSP_RETURNADDR:
+ return LowerSSP_RETURNADDR(Op, DAG);
case ISD::INSERT_VECTOR_ELT:
return LowerINSERT_VECTOR_ELT(Op, DAG);
case ISD::EXTRACT_VECTOR_ELT:
@@ -4424,6 +4426,29 @@ SDValue AArch64TargetLowering::LowerRETURNADDR(SDValue Op,
return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
}
+SDValue AArch64TargetLowering::LowerSSP_RETURNADDR(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDValue Chain = Op.getOperand(0);
+ SmallVector<SDValue, 2> Results;
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ MFI->setReturnAddressIsTaken(true);
+ MFI->setFrameAddressIsTaken(true);
+
+ EVT VT = Op.getValueType();
+ SDLoc DL(Op);
+
+ SDValue FrameAddr =
+ DAG.getCopyFromReg(DAG.getEntryNode(), DL, AArch64::FP, VT);
+ SDValue Offset = DAG.getConstant(8, DL, getPointerTy(DAG.getDataLayout()));
+
+ Results.push_back(DAG.getLoad(VT, DL, Chain,
+ DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset),
+ MachinePointerInfo(), true, false, false, 0));
+ Results.push_back(Chain);
+ return DAG.getMergeValues(Results, DL);
+}
+
/// LowerShiftRightParts - Lower SRA_PARTS, which returns two
/// i64 values and take a 2 x i64 value to shift plus a shift amount.
SDValue AArch64TargetLowering::LowerShiftRightParts(SDValue Op,
diff --git a/lib/Target/AArch64/AArch64ISelLowering.h b/lib/Target/AArch64/AArch64ISelLowering.h
index c87cfed..1c5177a 100644
--- a/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/lib/Target/AArch64/AArch64ISelLowering.h
@@ -495,6 +495,7 @@ private:
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSSP_RETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const;
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 975e61d..30ef45c 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -18582,6 +18582,24 @@ SDValue X86TargetLowering::LowerRETURNADDR(SDValue Op,
RetAddrFI, MachinePointerInfo(), false, false, false, 0);
}
+SDValue X86TargetLowering::LowerSSP_RETURNADDR(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDValue Chain = Op.getOperand(0);
+ SmallVector<SDValue, 2> Results;
+ MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+ MFI->setReturnAddressIsTaken(true);
+
+ SDLoc dl(Op);
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
+
+ // Just load the return address.
+ SDValue RetAddrFI = getReturnAddressFrameIndex(DAG);
+ Results.push_back(DAG.getLoad(PtrVT, dl, Chain,
+ RetAddrFI, MachinePointerInfo(), true, false, false, 0));
+ Results.push_back(Chain);
+ return DAG.getMergeValues(Results, dl);
+}
+
SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
@@ -21715,6 +21733,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::INTRINSIC_VOID:
case ISD::INTRINSIC_W_CHAIN: return LowerINTRINSIC_W_CHAIN(Op, Subtarget, DAG);
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
+ case ISD::SSP_RETURNADDR: return LowerSSP_RETURNADDR(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
case ISD::FRAME_TO_ARGS_OFFSET:
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index d826f1e..829cff7 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -1101,6 +1101,7 @@ namespace llvm {
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSSP_RETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
--
2.9.0
#include <stdio.h>
#include <string.h>
static void bar() {
puts("foobar");
}
static void foo(char *s) {
char array[20];
strcpy(array, s);
bar();
}
int main(int argc, char **argv) {
if (argc < 2)
return 1;
foo(argv[1]);
return 0;
}
--- old.s 2016-07-09 22:53:31.105305191 -0400
+++ new.s 2016-07-09 22:44:30.749344242 -0400
@@ -10,6 +10,7 @@
.Ltmp0:
.cfi_def_cfa_offset 32
movq %fs:40, %rax
+ xorq 24(%rsp), %rax
movq %rax, 16(%rsp)
movl $0, (%rsp)
movl %edi, 4(%rsp)
@@ -27,7 +28,9 @@
.LBB0_3:
movl (%rsp), %eax
movq %fs:40, %rcx
- cmpq 16(%rsp), %rcx
+ movq 16(%rsp), %rdx
+ xorq 24(%rsp), %rdx
+ cmpq %rdx, %rcx
jne .LBB0_5
# BB#4: # %SP_return
addq $24, %rsp
@@ -48,6 +51,7 @@
.cfi_def_cfa_offset 64
movq %rdi, %rax
movq %fs:40, %rcx
+ xorq 56(%rsp), %rcx
movq %rcx, 48(%rsp)
movq %rax, 8(%rsp)
leaq 16(%rsp), %rdi
@@ -55,7 +59,9 @@
callq strcpy
callq bar
movq %fs:40, %rax
- cmpq 48(%rsp), %rax
+ movq 48(%rsp), %rcx
+ xorq 56(%rsp), %rcx
+ cmpq %rcx, %rax
jne .LBB1_2
# BB#1: # %SP_return
addq $56, %rsp
@@ -75,11 +81,14 @@
.Ltmp2:
.cfi_def_cfa_offset 16
movq %fs:40, %rax
+ xorq 8(%rsp), %rax
movq %rax, (%rsp)
movl $.L.str, %edi
callq puts
movq %fs:40, %rax
- cmpq (%rsp), %rax
+ movq (%rsp), %rcx
+ xorq 8(%rsp), %rcx
+ cmpq %rcx, %rax
jne .LBB2_2
# BB#1: # %SP_return
popq %rax
--- aarch64_old_O2.s 2016-07-12 04:13:40.434404636 -0400
+++ aarch64_new_O2.s 2016-07-16 19:25:31.838997161 -0400
@@ -5,39 +5,43 @@
.type main,@function
main: // @main
// BB#0:
- sub sp, sp, #48 // =48
- adrp x8, __stack_chk_guard
- ldr x8, [x8, :lo12:__stack_chk_guard]
- stp x29, x30, [sp, #32] // 8-byte Folded Spill
- add x29, sp, #32 // =32
- stur x8, [x29, #-8]
+ sub sp, sp, #64 // =64
+ str x19, [sp, #32] // 8-byte Folded Spill
+ stp x29, x30, [sp, #48] // 8-byte Folded Spill
+ add x29, sp, #48 // =48
+ adrp x19, __stack_chk_guard
+ ldr x8, [x19, :lo12:__stack_chk_guard]
+ ldr x9, [x29, #8]
+ eor x8, x8, x9
+ str x8, [sp, #24]
mov w8, w0
- str w0, [sp, #16]
- stur wzr, [x29, #-12]
+ stp w0, wzr, [sp, #16]
str x1, [sp, #8]
cmp w8, #1 // =1
b.gt .LBB0_2
// BB#1:
orr w8, wzr, #0x1
- stur w8, [x29, #-12]
+ str w8, [sp, #20]
b .LBB0_3
.LBB0_2:
ldr x8, [sp, #8]
ldr x0, [x8, #8]
bl foo
- stur wzr, [x29, #-12]
+ str wzr, [sp, #20]
.LBB0_3:
- adrp x9, __stack_chk_guard
- ldur w0, [x29, #-12]
- ldur x8, [x29, #-8]
- ldr x9, [x9, :lo12:__stack_chk_guard]
- sub x8, x9, x8
- cbnz x8, .LBB0_5
-// BB#4:
- ldp x29, x30, [sp, #32] // 8-byte Folded Reload
- add sp, sp, #48 // =48
+ ldr w0, [sp, #20]
+ ldr x8, [x19, :lo12:__stack_chk_guard]
+ ldr x9, [sp, #24]
+ ldr x10, [x29, #8]
+ eor x9, x9, x10
+ cmp x8, x9
+ b.ne .LBB0_5
+// BB#4: // %SP_return
+ ldp x29, x30, [sp, #48] // 8-byte Folded Reload
+ ldr x19, [sp, #32] // 8-byte Folded Reload
+ add sp, sp, #64 // =64
ret
-.LBB0_5:
+.LBB0_5: // %CallStackCheckFailBlk
bl __stack_chk_fail
.Lfunc_end0:
.size main, .Lfunc_end0-main
@@ -46,28 +50,33 @@
.type foo,@function
foo: // @foo
// BB#0:
- sub sp, sp, #64 // =64
- adrp x9, __stack_chk_guard
- ldr x9, [x9, :lo12:__stack_chk_guard]
+ sub sp, sp, #80 // =80
+ str x19, [sp, #48] // 8-byte Folded Spill
+ stp x29, x30, [sp, #64] // 8-byte Folded Spill
+ add x29, sp, #64 // =64
+ adrp x19, __stack_chk_guard
+ ldr x9, [x19, :lo12:__stack_chk_guard]
+ ldr x10, [x29, #8]
mov x8, x0
- stp x29, x30, [sp, #48] // 8-byte Folded Spill
- add x29, sp, #48 // =48
add x0, sp, #20 // =20
mov x1, x8
- stur x9, [x29, #-8]
+ eor x9, x9, x10
+ stur x9, [x29, #-24]
str x8, [sp, #8]
bl strcpy
bl bar
- adrp x9, __stack_chk_guard
- ldur x8, [x29, #-8]
- ldr x9, [x9, :lo12:__stack_chk_guard]
- sub x8, x9, x8
- cbnz x8, .LBB1_2
-// BB#1:
- ldp x29, x30, [sp, #48] // 8-byte Folded Reload
- add sp, sp, #64 // =64
+ ldr x8, [x19, :lo12:__stack_chk_guard]
+ ldur x9, [x29, #-24]
+ ldr x10, [x29, #8]
+ eor x9, x9, x10
+ cmp x8, x9
+ b.ne .LBB1_2
+// BB#1: // %SP_return
+ ldp x29, x30, [sp, #64] // 8-byte Folded Reload
+ ldr x19, [sp, #48] // 8-byte Folded Reload
+ add sp, sp, #80 // =80
ret
-.LBB1_2:
+.LBB1_2: // %CallStackCheckFailBlk
bl __stack_chk_fail
.Lfunc_end1:
.size foo, .Lfunc_end1-foo
@@ -76,25 +85,30 @@
.type bar,@function
bar: // @bar
// BB#0:
- sub sp, sp, #32 // =32
- adrp x8, __stack_chk_guard
- ldr x8, [x8, :lo12:__stack_chk_guard]
+ sub sp, sp, #48 // =48
+ str x19, [sp, #16] // 8-byte Folded Spill
+ stp x29, x30, [sp, #32] // 8-byte Folded Spill
+ add x29, sp, #32 // =32
+ adrp x19, __stack_chk_guard
+ ldr x8, [x19, :lo12:__stack_chk_guard]
+ ldr x9, [x29, #8]
adrp x0, .L.str
add x0, x0, :lo12:.L.str
- stp x29, x30, [sp, #16] // 8-byte Folded Spill
- add x29, sp, #16 // =16
+ eor x8, x8, x9
str x8, [sp, #8]
bl puts
- adrp x9, __stack_chk_guard
- ldr x8, [sp, #8]
- ldr x9, [x9, :lo12:__stack_chk_guard]
- sub x8, x9, x8
- cbnz x8, .LBB2_2
-// BB#1:
- ldp x29, x30, [sp, #16] // 8-byte Folded Reload
- add sp, sp, #32 // =32
+ ldr x8, [x19, :lo12:__stack_chk_guard]
+ ldr x9, [sp, #8]
+ ldr x10, [x29, #8]
+ eor x9, x9, x10
+ cmp x8, x9
+ b.ne .LBB2_2
+// BB#1: // %SP_return
+ ldp x29, x30, [sp, #32] // 8-byte Folded Reload
+ ldr x19, [sp, #16] // 8-byte Folded Reload
+ add sp, sp, #48 // =48
ret
-.LBB2_2:
+.LBB2_2: // %CallStackCheckFailBlk
bl __stack_chk_fail
.Lfunc_end2:
.size bar, .Lfunc_end2-bar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment