Hello tech,

The patch below teaches clang to treat padding between functions
differently than padding inside functions. Padding between functions is
completely filled with trap instructions, and padding inside functions
is padded as usual (trapsleds on X86, NOPs on everything else). This
means that the trapsleds between functions no longer start with a short
JMP, but are instead completely filled with int3 (0xCC), which makes them
slightly more ROP unfriendly.

This has been through a bulk build on amd64, and I have been running
base + kernel build with this for about a week without issue, so this
change seems to be stable. I would interested to get feedback from
someone running arm64, since this change does touch some generic code
shared across architectures, but there shouldn't be any binary changes
outside X86.

Any other feedback / bikeshedding is welcome.

ok?

Todd

Index: include/llvm/CodeGen/AsmPrinter.h
===================================================================
RCS file: /cvs/src/gnu/llvm/include/llvm/CodeGen/AsmPrinter.h,v
retrieving revision 1.1.1.4
diff -u -p -u -p -r1.1.1.4 AsmPrinter.h
--- include/llvm/CodeGen/AsmPrinter.h   14 Mar 2017 08:08:02 -0000      1.1.1.4
+++ include/llvm/CodeGen/AsmPrinter.h   10 Jul 2017 01:12:02 -0000
@@ -297,6 +297,11 @@ public:
   ///
   void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const;
 
+  /// Emit an alinment directive to the specified power of two boundary,
+  /// like EmitAlignment, but call EmitTrapToAlignment to fill with
+  /// trap instructions instead of NOPs.
+  void EmitTrapAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) 
const;
+
   /// Lower the specified LLVM Constant to an MCExpr.
   virtual const MCExpr *lowerConstant(const Constant *CV);
 
@@ -354,6 +359,11 @@ public:
   virtual void EmitInstruction(const MachineInstr *) {
     llvm_unreachable("EmitInstruction not implemented");
   }
+
+  /// Emit an alignment directive to the specified power
+  /// of two boundary, but use Trap instructions for alignment
+  /// sections that should never be executed.
+  virtual void EmitTrapToAlignment(unsigned NumBits) const;
 
   /// Return the symbol for the specified constant pool entry.
   virtual MCSymbol *GetCPISymbol(unsigned CPID) const;
Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
RCS file: /cvs/src/gnu/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp,v
retrieving revision 1.1.1.4
diff -u -p -u -p -r1.1.1.4 AsmPrinter.cpp
--- lib/CodeGen/AsmPrinter/AsmPrinter.cpp       14 Mar 2017 08:08:14 -0000      
1.1.1.4
+++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp       10 Jul 2017 01:12:02 -0000
@@ -590,7 +590,7 @@ void AsmPrinter::EmitFunctionHeader() {
 
   EmitLinkage(F, CurrentFnSym);
   if (MAI->hasFunctionAlignment())
-    EmitAlignment(MF->getAlignment(), F);
+    EmitTrapAlignment(MF->getAlignment(), F);
 
   if (MAI->hasDotTypeDotSizeDirective())
     OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
@@ -1759,6 +1759,33 @@ void AsmPrinter::EmitAlignment(unsigned 
   else
     OutStreamer->EmitValueToAlignment(1u << NumBits);
 }
+
+//===----------------------------------------------------------------------===//
+/// EmitTrapAlignment - Emit an alignment directive to the specified power of
+/// two boundary, but call EmitTrapToAlignment to fill with Trap instructions
+/// if the Target implements EmitTrapToAlignment.
+void AsmPrinter::EmitTrapAlignment(unsigned NumBits, const GlobalObject *GV) 
const {
+  if (GV)
+    NumBits = getGVAlignmentLog2(GV, GV->getParent()->getDataLayout(), 
NumBits);
+
+  if (NumBits == 0) return;   // 1-byte aligned: no need to emit alignment.
+
+  assert(NumBits <
+             static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
+         "undefined behavior");
+  EmitTrapToAlignment(NumBits);
+}
+
+//===----------------------------------------------------------------------===//
+/// EmitTrapToAlignment - Emit an alignment directive to the specified power
+/// of two boundary. This default implementation calls EmitCodeAlignment on
+/// the OutStreamer, but can be overridden by Target implementations.
+void AsmPrinter::EmitTrapToAlignment(unsigned NumBits) const {
+  if (NumBits == 0) return;
+  OutStreamer->EmitCodeAlignment(1u << NumBits);
+}
+
+
 
 
//===----------------------------------------------------------------------===//
 // Constant emission.
Index: lib/Target/X86/X86AsmPrinter.h
===================================================================
RCS file: /cvs/src/gnu/llvm/lib/Target/X86/X86AsmPrinter.h,v
retrieving revision 1.1.1.3
diff -u -p -u -p -r1.1.1.3 X86AsmPrinter.h
--- lib/Target/X86/X86AsmPrinter.h      24 Jan 2017 08:33:28 -0000      1.1.1.3
+++ lib/Target/X86/X86AsmPrinter.h      10 Jul 2017 01:12:02 -0000
@@ -113,6 +113,8 @@ public:
 
   void EmitInstruction(const MachineInstr *MI) override;
 
+  void EmitTrapToAlignment(unsigned NumBits) const override;
+
   void EmitBasicBlockEnd(const MachineBasicBlock &MBB) override {
     SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());
   }
Index: lib/Target/X86/X86MCInstLower.cpp
===================================================================
RCS file: /cvs/src/gnu/llvm/lib/Target/X86/X86MCInstLower.cpp,v
retrieving revision 1.1.1.4
diff -u -p -u -p -r1.1.1.4 X86MCInstLower.cpp
--- lib/Target/X86/X86MCInstLower.cpp   14 Mar 2017 08:08:07 -0000      1.1.1.4
+++ lib/Target/X86/X86MCInstLower.cpp   10 Jul 2017 01:12:02 -0000
@@ -1308,7 +1308,7 @@ void X86AsmPrinter::EmitInstruction(cons
     const X86FrameLowering* FrameLowering =
         MF->getSubtarget<X86Subtarget>().getFrameLowering();
     bool hasFP = FrameLowering->hasFP(*MF);
-    
+
     // TODO: This is needed only if we require precise CFA.
     bool HasActiveDwarfFrame = OutStreamer->getNumFrameInfos() &&
                                !OutStreamer->getDwarfFrameInfos().back().End;
@@ -1735,4 +1735,10 @@ void X86AsmPrinter::EmitInstruction(cons
   }
 
   EmitAndCountInstruction(TmpInst);
+}
+
+/// Emit Trap bytes to the specified power of two alignment
+void X86AsmPrinter::EmitTrapToAlignment(unsigned NumBits) const {
+  if (NumBits == 0) return;
+  OutStreamer->EmitValueToAlignment(1u << NumBits, 0xCC, 1);
 }

Reply via email to