[PATCH] D45239: AArch64: Implement support for the shadowcallstack attribute.

2018-04-04 Thread Peter Collingbourne via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL329236: AArch64: Implement support for the shadowcallstack 
attribute. (authored by pcc, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D45239?vs=141063&id=141068#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D45239

Files:
  cfe/trunk/docs/ShadowCallStack.rst
  cfe/trunk/lib/Driver/SanitizerArgs.cpp
  cfe/trunk/lib/Driver/ToolChain.cpp
  cfe/trunk/test/Driver/sanitizer-ld.c
  llvm/trunk/include/llvm/Support/TargetParser.h
  llvm/trunk/lib/Support/TargetParser.cpp
  llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td
  llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp
  llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp
  llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp
  llvm/trunk/test/CodeGen/AArch64/shadow-call-stack.ll

Index: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td
===
--- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td
+++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td
@@ -349,3 +349,18 @@
 : CalleeSavedRegs<(add (sequence "X%u", 0, 15),
(sequence "X%u", 18, 28), FP, SP,
(sequence "Q%u", 0, 31))>;
+
+// Variants of the standard calling conventions for shadow call stack.
+// These all preserve x18 in addition to any other registers.
+def CSR_AArch64_NoRegs_SCS
+: CalleeSavedRegs<(add CSR_AArch64_NoRegs, X18)>;
+def CSR_AArch64_AllRegs_SCS
+: CalleeSavedRegs<(add CSR_AArch64_AllRegs, X18)>;
+def CSR_AArch64_CXX_TLS_Darwin_SCS
+: CalleeSavedRegs<(add CSR_AArch64_CXX_TLS_Darwin, X18)>;
+def CSR_AArch64_AAPCS_SwiftError_SCS
+: CalleeSavedRegs<(add CSR_AArch64_AAPCS_SwiftError, X18)>;
+def CSR_AArch64_RT_MostRegs_SCS
+: CalleeSavedRegs<(add CSR_AArch64_RT_MostRegs, X18)>;
+def CSR_AArch64_AAPCS_SCS
+: CalleeSavedRegs<(add CSR_AArch64_AAPCS, X18)>;
Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp
===
--- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -75,21 +75,25 @@
 const uint32_t *
 AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
   CallingConv::ID CC) const {
+  bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
   if (CC == CallingConv::GHC)
 // This is academic because all GHC calls are (supposed to be) tail calls
-return CSR_AArch64_NoRegs_RegMask;
+return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
   if (CC == CallingConv::AnyReg)
-return CSR_AArch64_AllRegs_RegMask;
+return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
   if (CC == CallingConv::CXX_FAST_TLS)
-return CSR_AArch64_CXX_TLS_Darwin_RegMask;
+return SCS ? CSR_AArch64_CXX_TLS_Darwin_SCS_RegMask
+   : CSR_AArch64_CXX_TLS_Darwin_RegMask;
   if (MF.getSubtarget().getTargetLowering()
   ->supportSwiftError() &&
   MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
-return CSR_AArch64_AAPCS_SwiftError_RegMask;
+return SCS ? CSR_AArch64_AAPCS_SwiftError_SCS_RegMask
+   : CSR_AArch64_AAPCS_SwiftError_RegMask;
   if (CC == CallingConv::PreserveMost)
-return CSR_AArch64_RT_MostRegs_RegMask;
+return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
+   : CSR_AArch64_RT_MostRegs_RegMask;
   else
-return CSR_AArch64_AAPCS_RegMask;
+return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
 }
 
 const uint32_t *AArch64RegisterInfo::getTLSCallPreservedMask() const {
Index: llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp
===
--- llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -414,6 +414,14 @@
 static MachineBasicBlock::iterator convertCalleeSaveRestoreToSPPrePostIncDec(
 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
 const DebugLoc &DL, const TargetInstrInfo *TII, int CSStackSizeInc) {
+  // Ignore instructions that do not operate on SP, i.e. shadow call stack
+  // instructions.
+  while (MBBI->getOpcode() == AArch64::STRXpost ||
+ MBBI->getOpcode() == AArch64::LDRXpre) {
+assert(MBBI->getOperand(0).getReg() != AArch64::SP);
+++MBBI;
+  }
+
   unsigned NewOpc;
   bool NewIsUnscaled = false;
   switch (MBBI->getOpcode()) {
@@ -481,6 +489,14 @@
 static void fixupCalleeSaveRestoreStackOffset(MachineInstr &MI,
   unsigned LocalStackSize) {
   unsigned Opc = MI.getOpcode();
+
+  // Ignore instructions that do not operate on SP, i.e. shadow call stack
+  // instructions.
+  if (Opc == AArch64::STRXpost || Opc == AArch64::LDRXpre

[PATCH] D45239: AArch64: Implement support for the shadowcallstack attribute.

2018-04-04 Thread Peter Collingbourne via Phabricator via cfe-commits
pcc updated this revision to Diff 141063.
pcc marked 3 inline comments as done.
pcc added a comment.

- Addres review comments


https://reviews.llvm.org/D45239

Files:
  clang/docs/ShadowCallStack.rst
  clang/lib/Driver/SanitizerArgs.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/test/Driver/sanitizer-ld.c
  llvm/include/llvm/Support/TargetParser.h
  llvm/lib/Support/TargetParser.cpp
  llvm/lib/Target/AArch64/AArch64CallingConvention.td
  llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
  llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
  llvm/lib/Target/AArch64/AArch64Subtarget.cpp
  llvm/test/CodeGen/AArch64/shadow-call-stack.ll

Index: llvm/test/CodeGen/AArch64/shadow-call-stack.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/shadow-call-stack.ll
@@ -0,0 +1,47 @@
+; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-linux-gnu -mattr=+reserve-x18 | FileCheck %s
+
+define void @f1() shadowcallstack {
+  ; CHECK: f1:
+  ; CHECK-NOT: x18
+  ; CHECK: ret
+  ret void
+}
+
+declare void @foo()
+
+define void @f2() shadowcallstack {
+  ; CHECK: f2:
+  ; CHECK-NOT: x18
+  ; CHECK: b foo
+  tail call void @foo()
+  ret void
+}
+
+declare i32 @bar()
+
+define i32 @f3() shadowcallstack {
+  ; CHECK: f3:
+  ; CHECK: str x30, [x18], #8
+  ; CHECK: str x30, [sp, #-16]!
+  %res = call i32 @bar()
+  %res1 = add i32 %res, 1
+  ; CHECK: ldr x30, [sp], #16
+  ; CHECK: ldr x30, [x18, #-8]!
+  ; CHECK: ret
+  ret i32 %res
+}
+
+define i32 @f4() shadowcallstack {
+  ; CHECK: f4:
+  %res1 = call i32 @bar()
+  %res2 = call i32 @bar()
+  %res3 = call i32 @bar()
+  %res4 = call i32 @bar()
+  %res12 = add i32 %res1, %res2
+  %res34 = add i32 %res3, %res4
+  %res1234 = add i32 %res12, %res34
+  ; CHECK: ldp {{.*}}x30, [sp
+  ; CHECK: ldr x30, [x18, #-8]!
+  ; CHECK: ret
+  ret i32 %res1234
+}
Index: llvm/lib/Target/AArch64/AArch64Subtarget.cpp
===
--- llvm/lib/Target/AArch64/AArch64Subtarget.cpp
+++ llvm/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
 #include "llvm/CodeGen/MachineScheduler.h"
 #include "llvm/IR/GlobalValue.h"
+#include "llvm/Support/TargetParser.h"
 
 using namespace llvm;
 
@@ -151,8 +152,8 @@
const std::string &FS,
const TargetMachine &TM, bool LittleEndian)
 : AArch64GenSubtargetInfo(TT, CPU, FS),
-  ReserveX18(TT.isOSDarwin() || TT.isOSFuchsia() || TT.isOSWindows()),
-  IsLittle(LittleEndian), TargetTriple(TT), FrameLowering(),
+  ReserveX18(AArch64::isX18ReservedByDefault(TT)), IsLittle(LittleEndian),
+  TargetTriple(TT), FrameLowering(),
   InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
   TLInfo(TM, *this) {
   CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering()));
Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
===
--- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -75,21 +75,25 @@
 const uint32_t *
 AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
   CallingConv::ID CC) const {
+  bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
   if (CC == CallingConv::GHC)
 // This is academic because all GHC calls are (supposed to be) tail calls
-return CSR_AArch64_NoRegs_RegMask;
+return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
   if (CC == CallingConv::AnyReg)
-return CSR_AArch64_AllRegs_RegMask;
+return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
   if (CC == CallingConv::CXX_FAST_TLS)
-return CSR_AArch64_CXX_TLS_Darwin_RegMask;
+return SCS ? CSR_AArch64_CXX_TLS_Darwin_SCS_RegMask
+   : CSR_AArch64_CXX_TLS_Darwin_RegMask;
   if (MF.getSubtarget().getTargetLowering()
   ->supportSwiftError() &&
   MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
-return CSR_AArch64_AAPCS_SwiftError_RegMask;
+return SCS ? CSR_AArch64_AAPCS_SwiftError_SCS_RegMask
+   : CSR_AArch64_AAPCS_SwiftError_RegMask;
   if (CC == CallingConv::PreserveMost)
-return CSR_AArch64_RT_MostRegs_RegMask;
+return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
+   : CSR_AArch64_RT_MostRegs_RegMask;
   else
-return CSR_AArch64_AAPCS_RegMask;
+return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
 }
 
 const uint32_t *AArch64RegisterInfo::getTLSCallPreservedMask() const {
Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
===
--- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -414,6 +414,14 @@
 static MachineBasicB

[PATCH] D45239: AArch64: Implement support for the shadowcallstack attribute.

2018-04-04 Thread Evgenii Stepanov via Phabricator via cfe-commits
eugenis added inline comments.



Comment at: clang/docs/ShadowCallStack.rst:12
 ShadowCallStack is an **experimental** instrumentation pass, currently only
 implemented for x86_64, that protects programs against return address
 overwrites (e.g. stack buffer overflows.) It works by saving a function's 
return

vlad.tsyrklevich wrote:
> Should also mention aarch64 here.
needs update



Comment at: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp:1153
+report_fatal_error("Must reserve x18 to use shadow call stack");
+  NeedSCSProlog = true;
+}

That's way too cryptic, please call it NeedShadowCallStackProlog or something 
similar.


https://reviews.llvm.org/D45239



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45239: AArch64: Implement support for the shadowcallstack attribute.

2018-04-04 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich accepted this revision.
vlad.tsyrklevich added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/docs/ShadowCallStack.rst:12
 ShadowCallStack is an **experimental** instrumentation pass, currently only
 implemented for x86_64, that protects programs against return address
 overwrites (e.g. stack buffer overflows.) It works by saving a function's 
return

Should also mention aarch64 here.



Comment at: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp:78
   CallingConv::ID CC) const {
+  bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
   if (CC == CallingConv::GHC)

It's sort of a stretch to construct a scenario where this is likely to happen, 
but is it possible that a runtime function marked with 
`__attribute__((no_sanitize("shadowcallstack")))` would spill x18 across a 
function call because of this mask if it's referenced before and after? If that 
was a concern, we could make this test `hasAttr(SCS) || hasFlag(fFixedx18)`


https://reviews.llvm.org/D45239



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45239: AArch64: Implement support for the shadowcallstack attribute.

2018-04-03 Thread Peter Collingbourne via Phabricator via cfe-commits
pcc created this revision.
pcc added reviewers: vlad.tsyrklevich, eugenis, kcc, t.p.northover, olista01.
Herald added subscribers: hiraditya, kristof.beyls, javed.absar, rengolin.

The implementation of shadow call stack on aarch64 is quite different to
the implementation on x86_64. Instead of reserving a segment register for
the shadow call stack, we reserve the platform register, x18. Any function
that spills lr to sp also spills it to the shadow call stack, a pointer to
which is stored in x18.


https://reviews.llvm.org/D45239

Files:
  clang/docs/ShadowCallStack.rst
  clang/lib/Driver/SanitizerArgs.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/test/Driver/sanitizer-ld.c
  llvm/include/llvm/Support/TargetParser.h
  llvm/lib/Support/TargetParser.cpp
  llvm/lib/Target/AArch64/AArch64CallingConvention.td
  llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
  llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
  llvm/lib/Target/AArch64/AArch64Subtarget.cpp
  llvm/test/CodeGen/AArch64/shadow-call-stack.ll

Index: llvm/test/CodeGen/AArch64/shadow-call-stack.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/shadow-call-stack.ll
@@ -0,0 +1,47 @@
+; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-linux-gnu -mattr=+reserve-x18 | FileCheck %s
+
+define void @f1() shadowcallstack {
+  ; CHECK: f1:
+  ; CHECK-NOT: x18
+  ; CHECK: ret
+  ret void
+}
+
+declare void @foo()
+
+define void @f2() shadowcallstack {
+  ; CHECK: f2:
+  ; CHECK-NOT: x18
+  ; CHECK: b foo
+  tail call void @foo()
+  ret void
+}
+
+declare i32 @bar()
+
+define i32 @f3() shadowcallstack {
+  ; CHECK: f3:
+  ; CHECK: str x30, [x18], #8
+  ; CHECK: str x30, [sp, #-16]!
+  %res = call i32 @bar()
+  %res1 = add i32 %res, 1
+  ; CHECK: ldr x30, [sp], #16
+  ; CHECK: ldr x30, [x18, #-8]!
+  ; CHECK: ret
+  ret i32 %res
+}
+
+define i32 @f4() shadowcallstack {
+  ; CHECK: f4:
+  %res1 = call i32 @bar()
+  %res2 = call i32 @bar()
+  %res3 = call i32 @bar()
+  %res4 = call i32 @bar()
+  %res12 = add i32 %res1, %res2
+  %res34 = add i32 %res3, %res4
+  %res1234 = add i32 %res12, %res34
+  ; CHECK: ldp {{.*}}x30, [sp
+  ; CHECK: ldr x30, [x18, #-8]!
+  ; CHECK: ret
+  ret i32 %res1234
+}
Index: llvm/lib/Target/AArch64/AArch64Subtarget.cpp
===
--- llvm/lib/Target/AArch64/AArch64Subtarget.cpp
+++ llvm/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
 #include "llvm/CodeGen/MachineScheduler.h"
 #include "llvm/IR/GlobalValue.h"
+#include "llvm/Support/TargetParser.h"
 
 using namespace llvm;
 
@@ -151,8 +152,8 @@
const std::string &FS,
const TargetMachine &TM, bool LittleEndian)
 : AArch64GenSubtargetInfo(TT, CPU, FS),
-  ReserveX18(TT.isOSDarwin() || TT.isOSFuchsia() || TT.isOSWindows()),
-  IsLittle(LittleEndian), TargetTriple(TT), FrameLowering(),
+  ReserveX18(AArch64::isX18ReservedByDefault(TT)), IsLittle(LittleEndian),
+  TargetTriple(TT), FrameLowering(),
   InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
   TLInfo(TM, *this) {
   CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering()));
Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
===
--- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -75,21 +75,25 @@
 const uint32_t *
 AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
   CallingConv::ID CC) const {
+  bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
   if (CC == CallingConv::GHC)
 // This is academic because all GHC calls are (supposed to be) tail calls
-return CSR_AArch64_NoRegs_RegMask;
+return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
   if (CC == CallingConv::AnyReg)
-return CSR_AArch64_AllRegs_RegMask;
+return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
   if (CC == CallingConv::CXX_FAST_TLS)
-return CSR_AArch64_CXX_TLS_Darwin_RegMask;
+return SCS ? CSR_AArch64_CXX_TLS_Darwin_SCS_RegMask
+   : CSR_AArch64_CXX_TLS_Darwin_RegMask;
   if (MF.getSubtarget().getTargetLowering()
   ->supportSwiftError() &&
   MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
-return CSR_AArch64_AAPCS_SwiftError_RegMask;
+return SCS ? CSR_AArch64_AAPCS_SwiftError_SCS_RegMask
+   : CSR_AArch64_AAPCS_SwiftError_RegMask;
   if (CC == CallingConv::PreserveMost)
-return CSR_AArch64_RT_MostRegs_RegMask;
+return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
+   : CSR_AArch64_RT_MostRegs_RegMask;
   else
-return CSR_AArch64_AAPCS_RegMask;
+return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : C