[llvm] r202479 - [mips] Implement NaCl sandboxing of indirect jumps:

Sasa Stankovic Sasa.Stankovic at imgtec.com
Fri Feb 28 02:00:38 PST 2014


Author: sstankovic
Date: Fri Feb 28 04:00:38 2014
New Revision: 202479

URL: http://llvm.org/viewvc/llvm-project?rev=202479&view=rev
Log:
[mips] Implement NaCl sandboxing of indirect jumps:

  * Align targets of indirect jumps to instruction bundle boundaries (in MI layer).
  * Add masking instructions before indirect jumps (in MC layer).

Differential Revision: http://llvm-reviews.chandlerc.com/D2847

Added:
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
    llvm/trunk/test/MC/Mips/nacl-align.ll
    llvm/trunk/test/MC/Mips/nacl-mask.s
Modified:
    llvm/trunk/include/llvm/MC/MCELFStreamer.h
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
    llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp
    llvm/trunk/lib/Target/Mips/MipsAsmPrinter.h

Modified: llvm/trunk/include/llvm/MC/MCELFStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCELFStreamer.h?rev=202479&r1=202478&r2=202479&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCELFStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCELFStreamer.h Fri Feb 28 04:00:38 2014
@@ -84,14 +84,14 @@ public:
 
   virtual void FinishImpl();
 
-private:
-  virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &);
-  virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &);
-
   virtual void EmitBundleAlignMode(unsigned AlignPow2);
   virtual void EmitBundleLock(bool AlignToEnd);
   virtual void EmitBundleUnlock();
 
+private:
+  virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &);
+  virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &);
+
   void fixSymbolsInTLSFixups(const MCExpr *expr);
 
   bool SeenIdent;

Added: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h?rev=202479&view=auto
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h (added)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h Fri Feb 28 04:00:38 2014
@@ -0,0 +1,28 @@
+//===-- MipsMCNaCl.h - NaCl-related declarations --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSMCNACL_H
+#define MIPSMCNACL_H
+
+#include "llvm/MC/MCELFStreamer.h"
+
+namespace llvm {
+
+// Log2 of the NaCl MIPS sandbox's instruction bundle size.
+static const unsigned MIPS_NACL_BUNDLE_ALIGN = 4u;
+
+// This function creates an MCELFStreamer for Mips NaCl.
+MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
+                                         raw_ostream &OS,
+                                         MCCodeEmitter *Emitter,
+                                         bool RelaxAll, bool NoExecStack);
+
+}
+
+#endif

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp?rev=202479&r1=202478&r2=202479&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp Fri Feb 28 04:00:38 2014
@@ -11,9 +11,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "MipsMCTargetDesc.h"
 #include "InstPrinter/MipsInstPrinter.h"
 #include "MipsMCAsmInfo.h"
+#include "MipsMCNaCl.h"
+#include "MipsMCTargetDesc.h"
 #include "MipsTargetStreamer.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/MC/MCCodeGenInfo.h"
@@ -109,8 +110,12 @@ static MCStreamer *createMCStreamer(cons
                                     raw_ostream &OS, MCCodeEmitter *Emitter,
                                     const MCSubtargetInfo &STI,
                                     bool RelaxAll, bool NoExecStack) {
-  MCStreamer *S =
-      createELFStreamer(Context, MAB, OS, Emitter, RelaxAll, NoExecStack);
+  MCStreamer *S;
+  if (!Triple(TT).isOSNaCl())
+    S = createELFStreamer(Context, MAB, OS, Emitter, RelaxAll, NoExecStack);
+  else
+    S = createMipsNaClELFStreamer(Context, MAB, OS, Emitter, RelaxAll,
+                                  NoExecStack);
   new MipsTargetELFStreamer(*S, STI);
   return S;
 }

Added: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp?rev=202479&view=auto
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp (added)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp Fri Feb 28 04:00:38 2014
@@ -0,0 +1,97 @@
+//===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements MCELFStreamer for Mips NaCl.  It emits .o object files
+// as required by NaCl's SFI sandbox.  It inserts address-masking instructions
+// before dangerous control-flow instructions.  It aligns on bundle size all
+// functions and all targets of indirect branches.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-mc-nacl"
+
+#include "Mips.h"
+#include "MipsMCNaCl.h"
+#include "llvm/MC/MCELFStreamer.h"
+
+using namespace llvm;
+
+namespace {
+
+const unsigned IndirectBranchMaskReg = Mips::T6;
+
+/// Extend the generic MCELFStreamer class so that it can mask dangerous
+/// instructions.
+
+class MipsNaClELFStreamer : public MCELFStreamer {
+public:
+  MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
+                      MCCodeEmitter *Emitter)
+    : MCELFStreamer(Context, TAB, OS, Emitter) {}
+
+  ~MipsNaClELFStreamer() {}
+
+private:
+  bool isIndirectJump(const MCInst &MI) {
+    return MI.getOpcode() == Mips::JR || MI.getOpcode() == Mips::RET;
+  }
+
+  void emitMask(unsigned AddrReg, unsigned MaskReg,
+                const MCSubtargetInfo &STI) {
+    MCInst MaskInst;
+    MaskInst.setOpcode(Mips::AND);
+    MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
+    MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
+    MaskInst.addOperand(MCOperand::CreateReg(MaskReg));
+    MCELFStreamer::EmitInstruction(MaskInst, STI);
+  }
+
+  // Sandbox indirect branch or return instruction by inserting mask operation
+  // before it.
+  void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) {
+    unsigned AddrReg = MI.getOperand(0).getReg();
+
+    EmitBundleLock(false);
+    emitMask(AddrReg, IndirectBranchMaskReg, STI);
+    MCELFStreamer::EmitInstruction(MI, STI);
+    EmitBundleUnlock();
+  }
+
+public:
+  /// This function is the one used to emit instruction data into the ELF
+  /// streamer.  We override it to mask dangerous instructions.
+  virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) {
+    if (isIndirectJump(Inst))
+      sandboxIndirectJump(Inst, STI);
+    else
+      MCELFStreamer::EmitInstruction(Inst, STI);
+  }
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
+                                         raw_ostream &OS,
+                                         MCCodeEmitter *Emitter, bool RelaxAll,
+                                         bool NoExecStack) {
+  MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter);
+  if (RelaxAll)
+    S->getAssembler().setRelaxAll(true);
+  if (NoExecStack)
+    S->getAssembler().setNoExecStack(true);
+
+  // Set bundle-alignment as required by the NaCl ABI for the target.
+  S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN);
+
+  return S;
+}
+
+}

Modified: llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp?rev=202479&r1=202478&r2=202479&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp Fri Feb 28 04:00:38 2014
@@ -15,6 +15,7 @@
 #define DEBUG_TYPE "mips-asm-printer"
 #include "InstPrinter/MipsInstPrinter.h"
 #include "MCTargetDesc/MipsBaseInfo.h"
+#include "MCTargetDesc/MipsMCNaCl.h"
 #include "Mips.h"
 #include "MipsAsmPrinter.h"
 #include "MipsInstrInfo.h"
@@ -27,6 +28,7 @@
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineMemOperand.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/DataLayout.h"
@@ -72,6 +74,11 @@ bool MipsAsmPrinter::runOnMachineFunctio
         StubsNeeded[Symbol] = Signature;
     }
   MCP = MF.getConstantPool();
+
+  // In NaCl, all indirect jump targets must be aligned to bundle size.
+  if (Subtarget->isTargetNaCl())
+    NaClAlignIndirectJumpTargets(MF);
+
   AsmPrinter::runOnMachineFunction(MF);
   return true;
 }
@@ -270,6 +277,12 @@ const char *MipsAsmPrinter::getCurrentAB
 
 void MipsAsmPrinter::EmitFunctionEntryLabel() {
   MipsTargetStreamer &TS = getTargetStreamer();
+
+  // NaCl sandboxing requires that indirect call instructions are masked.
+  // This means that function entry points should be bundle-aligned.
+  if (Subtarget->isTargetNaCl())
+    EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN));
+
   if (Subtarget->inMicroMipsMode())
     TS.emitDirectiveSetMicroMips();
   // leave out until FSF available gas has micromips changes
@@ -906,6 +919,28 @@ void MipsAsmPrinter::PrintDebugValueComm
   // TODO: implement
 }
 
+// Align all targets of indirect branches on bundle size.  Used only if target
+// is NaCl.
+void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) {
+  // Align all blocks that are jumped to through jump table.
+  if (MachineJumpTableInfo *JtInfo = MF.getJumpTableInfo()) {
+    const std::vector<MachineJumpTableEntry> &JT = JtInfo->getJumpTables();
+    for (unsigned I = 0; I < JT.size(); ++I) {
+      const std::vector<MachineBasicBlock*> &MBBs = JT[I].MBBs;
+
+      for (unsigned J = 0; J < MBBs.size(); ++J)
+        MBBs[J]->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
+    }
+  }
+
+  // If basic block address is taken, block can be target of indirect branch.
+  for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
+                                 MBB != E; ++MBB) {
+    if (MBB->hasAddressTaken())
+      MBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
+  }
+}
+
 // Force static initialization.
 extern "C" void LLVMInitializeMipsAsmPrinter() {
   RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget);

Modified: llvm/trunk/lib/Target/Mips/MipsAsmPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsAsmPrinter.h?rev=202479&r1=202478&r2=202479&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsAsmPrinter.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsAsmPrinter.h Fri Feb 28 04:00:38 2014
@@ -73,6 +73,8 @@ private:
 
   void EmitFPCallStub(const char *, const Mips16HardFloatInfo::FuncSignature *);
 
+  void NaClAlignIndirectJumpTargets(MachineFunction &MF);
+
 public:
 
   const MipsSubtarget *Subtarget;

Added: llvm/trunk/test/MC/Mips/nacl-align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/nacl-align.ll?rev=202479&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/nacl-align.ll (added)
+++ llvm/trunk/test/MC/Mips/nacl-align.ll Fri Feb 28 04:00:38 2014
@@ -0,0 +1,96 @@
+; RUN: llc -filetype=asm -mtriple=mipsel-none-nacl -relocation-model=static \
+; RUN:     -O3 < %s
+
+
+; This test tests that NaCl functions are bundle-aligned.
+
+define void @test0() {
+  ret void
+
+; CHECK:          .align  4
+; CHECK-NOT:      .align
+; CHECK-LABEL:    test0:
+
+}
+
+
+; This test tests that blocks that are jumped to through jump table are
+; bundle-aligned.
+
+define i32 @test1(i32 %i) {
+entry:
+  switch i32 %i, label %default [
+    i32 0, label %bb1
+    i32 1, label %bb2
+    i32 2, label %bb3
+    i32 3, label %bb4
+  ]
+
+bb1:
+  ret i32 111
+bb2:
+  ret i32 222
+bb3:
+  ret i32 333
+bb4:
+  ret i32 444
+default:
+  ret i32 555
+
+
+; CHECK-LABEL:       test1:
+
+; CHECK:             .align  4
+; CHECK-NEXT:    ${{BB[0-9]+_[0-9]+}}:
+; CHECK-NEXT:        jr      $ra
+; CHECK-NEXT:        addiu   $2, $zero, 111
+; CHECK-NEXT:        .align  4
+; CHECK-NEXT:    ${{BB[0-9]+_[0-9]+}}:
+; CHECK-NEXT:        jr      $ra
+; CHECK-NEXT:        addiu   $2, $zero, 222
+; CHECK-NEXT:        .align  4
+; CHECK-NEXT:    ${{BB[0-9]+_[0-9]+}}:
+; CHECK-NEXT:        jr      $ra
+; CHECK-NEXT:        addiu   $2, $zero, 333
+; CHECK-NEXT:        .align  4
+; CHECK-NEXT:    ${{BB[0-9]+_[0-9]+}}:
+; CHECK-NEXT:        jr      $ra
+; CHECK-NEXT:        addiu   $2, $zero, 444
+
+}
+
+
+; This test tests that a block whose address is taken is bundle-aligned in NaCl.
+
+ at bb_array = constant [2 x i8*] [i8* blockaddress(@test2, %bb1),
+                                i8* blockaddress(@test2, %bb2)], align 4
+
+define i32 @test2(i32 %i) {
+entry:
+  %elementptr = getelementptr inbounds [2 x i8*]* @bb_array, i32 0, i32 %i
+  %0 = load i8** %elementptr, align 4
+  indirectbr i8* %0, [label %bb1, label %bb2]
+
+bb1:
+  ret i32 111
+bb2:
+  ret i32 222
+
+
+; CHECK-LABEL:       test2:
+
+; Note that there are two consecutive labels - one temporary and one for
+; basic block.
+
+; CHECK:             .align  4
+; CHECK-NEXT:    ${{[a-zA-Z0-9]+}}:
+; CHECK-NEXT:    ${{BB[0-9]+_[0-9]+}}:
+; CHECK-NEXT:        jr      $ra
+; CHECK-NEXT:        addiu   $2, $zero, 111
+; CHECK-NEXT:        .align  4
+; CHECK-NEXT:    ${{[a-zA-Z0-9]+}}:
+; CHECK-NEXT:    ${{BB[0-9]+_[0-9]+}}:
+; CHECK-NEXT:        jr      $ra
+; CHECK-NEXT:        addiu   $2, $zero, 222
+
+}

Added: llvm/trunk/test/MC/Mips/nacl-mask.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/nacl-mask.s?rev=202479&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/nacl-mask.s (added)
+++ llvm/trunk/test/MC/Mips/nacl-mask.s Fri Feb 28 04:00:38 2014
@@ -0,0 +1,28 @@
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-nacl %s \
+# RUN:  | llvm-objdump -triple mipsel -disassemble -no-show-raw-insn - \
+# RUN:  | FileCheck %s
+
+# This test tests that address-masking sandboxing is added when given assembly
+# input.
+
+test1:
+	.set	noreorder
+
+        jr	$a0
+        nop
+        jr	$ra
+        nop
+
+# CHECK-LABEL:   test1:
+
+# CHECK:         and     $4, $4, $14
+# CHECK-NEXT:    jr      $4
+
+# Check that additional nop is inserted, to align mask and jr to the next
+# bundle.
+
+# CHECK-NEXT:    nop
+# CHECK-NEXT:    nop
+
+# CHECK:         and     $ra, $ra, $14
+# CHECK-NEXT:    jr      $ra





More information about the llvm-commits mailing list