Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: llvm/lib/Target/Mips/MipsNaClRewritePass.cpp

Issue 8273005: [MIPS] Initial support for MIPS architecture. (Closed)
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « llvm/lib/Target/Mips/MipsNaClRewritePass.h ('k') | llvm/lib/Target/Mips/MipsRegisterInfo.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: llvm/lib/Target/Mips/MipsNaClRewritePass.cpp
===================================================================
new file mode 100755
--- /dev/null
+++ b/llvm/lib/Target/Mips/MipsNaClRewritePass.cpp
@@ -0,0 +1,333 @@
+//===-- MipsNaClRewritePass.cpp - Native Client Rewrite Pass ------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Native Client Rewrite Pass
+// This final pass inserts the sandboxing instructions needed to run inside
+// the Native Client sandbox. Native Client requires certain software fault
+// isolation (SFI) constructions to be put in place, to prevent escape from
+// the sandbox. Native Client refuses to execute binaries without the correct
+// SFI sequences.
+//
+// Potentially dangerous operations which are protected include:
+// * Stores
+// * Branches
+// * Changes to SP
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-sfi"
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsNaClRewritePass.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/Function.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+
+unsigned Mips::LoadStoreStackMaskReg = Mips::T4;
+unsigned Mips::IndirectBranchMaskReg = Mips::T3;
+
+namespace {
+ class MipsNaClRewritePass : public MachineFunctionPass {
+ public:
+ static char ID;
+ MipsNaClRewritePass() : MachineFunctionPass(ID) {}
+
+ const MipsInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ virtual bool runOnMachineFunction(MachineFunction &Fn);
+
+ virtual const char *getPassName() const {
+ return "Mips Native Client Rewrite Pass";
+ }
+
+ private:
+
+ bool SandboxLoadsInBlock(MachineBasicBlock &MBB);
+ bool SandboxStoresInBlock(MachineBasicBlock &MBB);
+ void SandboxLoadStore(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ MachineInstr &MI,
+ int AddrIdx);
+
+ bool SandboxBranchesInBlock(MachineBasicBlock &MBB);
+ bool SandboxStackChangesInBlock(MachineBasicBlock &MBB);
+
+ void SandboxStackChange(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI);
+ void AlignAllJumpTargets(MachineFunction &MF);
+ };
+ char MipsNaClRewritePass::ID = 0;
+}
+
+static bool IsReturn(const MachineInstr &MI) {
+ return (MI.getOpcode() == Mips::RET);
+}
+
+static bool IsIndirectJump(const MachineInstr &MI) {
+ return (MI.getOpcode() == Mips::JR);
+}
+
+static bool IsIndirectCall(const MachineInstr &MI) {
+ return (MI.getOpcode() == Mips::JALR);
+}
+
+static bool IsDirectCall(const MachineInstr &MI) {
+ return (MI.getOpcode() == Mips::JAL);
+}
+
+static bool IsStackMask(const MachineInstr &MI) {
+ return (MI.getOpcode() == Mips::SFI_DATA_MASK);
+}
+
+static bool IsStackChange(const MachineInstr &MI,
+ const TargetRegisterInfo *TRI) {
+ return MI.modifiesRegister(Mips::SP, TRI);
+}
+
+static bool NeedSandboxStackChange(const MachineInstr &MI,
+ const TargetRegisterInfo *TRI) {
+ return (IsStackChange(MI, TRI) && !IsStackMask(MI));
+}
+
+void MipsNaClRewritePass::SandboxStackChange(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI) {
+ MachineInstr &MI = *MBBI;
+
+ BuildMI(MBB, MBBI, MI.getDebugLoc(),
+ TII->get(Mips::SFI_NOP_IF_AT_BUNDLE_END));
+
+ // Get to next instr (one + to get the original, and one more + to get past).
+ MachineBasicBlock::iterator MBBINext = (MBBI++);
+ MachineBasicBlock::iterator MBBINext2 = (MBBI++);
+
+ BuildMI(MBB, MBBINext2, MI.getDebugLoc(),
+ TII->get(Mips::SFI_DATA_MASK), Mips::SP)
+ .addReg(Mips::SP)
+ .addReg(Mips::LoadStoreStackMaskReg);
+ return;
+}
+
+bool MipsNaClRewritePass::SandboxStackChangesInBlock(MachineBasicBlock &MBB) {
+ bool Modified = false;
+ for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
+ MBBI != E; ++MBBI) {
+ MachineInstr &MI = *MBBI;
+ if (NeedSandboxStackChange(MI, TRI)) {
+ SandboxStackChange(MBB, MBBI);
+ Modified |= true;
+ }
+ }
+ return Modified;
+}
+
+bool MipsNaClRewritePass::SandboxBranchesInBlock(MachineBasicBlock &MBB) {
+ bool Modified = false;
+
+ for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
+ MBBI != E; ++MBBI) {
+ MachineInstr &MI = *MBBI;
+
+ if (IsReturn(MI)) {
+ unsigned AddrReg = MI.getOperand(0).getReg();
+ BuildMI(MBB, MBBI, MI.getDebugLoc(),
+ TII->get(Mips::SFI_GUARD_RETURN), AddrReg)
+ .addReg(AddrReg)
+ .addReg(Mips::IndirectBranchMaskReg);
+ Modified = true;
+ }
+
+ if (IsIndirectJump(MI)) {
+ unsigned AddrReg = MI.getOperand(0).getReg();
+ BuildMI(MBB, MBBI, MI.getDebugLoc(),
+ TII->get(Mips::SFI_GUARD_INDIRECT_JMP), AddrReg)
+ .addReg(AddrReg)
+ .addReg(Mips::IndirectBranchMaskReg);
+ Modified = true;
+ }
+
+ if (IsDirectCall(MI)) {
+ BuildMI(MBB, MBBI, MI.getDebugLoc(),
+ TII->get(Mips::SFI_GUARD_CALL));
+ Modified = true;
+ }
+
+ if (IsIndirectCall(MI)) {
+ unsigned AddrReg = MI.getOperand(0).getReg();
+ BuildMI(MBB, MBBI, MI.getDebugLoc(),
+ TII->get(Mips::SFI_GUARD_INDIRECT_CALL), AddrReg)
+ .addReg(AddrReg)
+ .addReg(Mips::IndirectBranchMaskReg);
+ Modified = true;
+ }
+ }
+
+ return Modified;
+}
+
+/*
+ * Sandboxes a load or store instruction by inserting an appropriate mask
+ * operation before it.
+ */
+void MipsNaClRewritePass::SandboxLoadStore(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ MachineInstr &MI,
+ int AddrIdx) {
+ unsigned BaseReg = MI.getOperand(AddrIdx).getReg();
+
+ BuildMI(MBB, MBBI, MI.getDebugLoc(),
+ TII->get(Mips::SFI_GUARD_LOAD_STORE), BaseReg)
+ .addReg(BaseReg)
+ .addReg(Mips::LoadStoreStackMaskReg);
+ return;
+}
+
+static bool IsDangerousLoad(const MachineInstr &MI, int *AddrIdx) {
+ unsigned Opcode = MI.getOpcode();
+ switch (Opcode) {
+ default: return false;
+
+ // Instructions with base address register in position 1
+ case Mips::LB:
+ case Mips::LBu:
+ case Mips::LH:
+ case Mips::LHu:
+ case Mips::LW:
+ case Mips::LWC1:
+ case Mips::LDC1:
+ case Mips::LL:
+ *AddrIdx = 1;
+ break;
+ }
+
+ if (MI.getOperand(*AddrIdx).getReg() == Mips::SP) {
+ // The contents of SP do not require masking.
+ return false;
+ }
+
+ return true;
+}
+
+static bool IsDangerousStore(const MachineInstr &MI, int *AddrIdx) {
+ unsigned Opcode = MI.getOpcode();
+ switch (Opcode) {
+ default: return false;
+
+ // Instructions with base address register in position 1
+ case Mips::SB:
+ case Mips::SH:
+ case Mips::SW:
+ case Mips::SWC1:
+ case Mips::SDC1:
+ *AddrIdx = 1;
+ break;
+
+ case Mips::SC:
+ *AddrIdx = 2;
+ break;
+ }
+
+ if (MI.getOperand(*AddrIdx).getReg() == Mips::SP) {
+ // The contents of SP do not require masking.
+ return false;
+ }
+
+ return true;
+}
+
+bool MipsNaClRewritePass::SandboxLoadsInBlock(MachineBasicBlock &MBB) {
+ bool Modified = false;
+ for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
+ MBBI != E;
+ ++MBBI) {
+ MachineInstr &MI = *MBBI;
+ int AddrIdx;
+
+ if (IsDangerousLoad(MI, &AddrIdx)) {
+ SandboxLoadStore(MBB, MBBI, MI, AddrIdx);
+ Modified = true;
+ }
+ }
+ return Modified;
+}
+
+bool MipsNaClRewritePass::SandboxStoresInBlock(MachineBasicBlock &MBB) {
+ bool Modified = false;
+ for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
+ MBBI != E;
+ ++MBBI) {
+ MachineInstr &MI = *MBBI;
+ int AddrIdx;
+
+ if (IsDangerousStore(MI, &AddrIdx)) {
+ SandboxLoadStore(MBB, MBBI, MI, AddrIdx);
+ Modified = true;
+ }
+ }
+ return Modified;
+}
+
+// Make sure all jump targets are aligned
+void MipsNaClRewritePass::AlignAllJumpTargets(MachineFunction &MF) {
+ // JUMP TABLE TARGETS
+ MachineJumpTableInfo *jt_info = MF.getJumpTableInfo();
+ if (jt_info) {
+ const std::vector<MachineJumpTableEntry> &JT = jt_info->getJumpTables();
+ for (unsigned i=0; i < JT.size(); ++i) {
+ std::vector<MachineBasicBlock*> MBBs = JT[i].MBBs;
+
+ for (unsigned j=0; j < MBBs.size(); ++j) {
+ MBBs[j]->setAlignment(16);
+ }
+ }
+ }
+
+ for (MachineFunction::iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ MachineBasicBlock &MBB = *I;
+ if (MBB.hasAddressTaken())
+ MBB.setAlignment(16);
+ }
+}
+
+bool MipsNaClRewritePass::runOnMachineFunction(MachineFunction &MF) {
+ TII = static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
+ TRI = MF.getTarget().getRegisterInfo();
+
+ bool Modified = false;
+ for (MachineFunction::iterator MFI = MF.begin(), E = MF.end();
+ MFI != E;
+ ++MFI) {
+ MachineBasicBlock &MBB = *MFI;
+
+ if (FlagSfiLoad)
+ Modified |= SandboxLoadsInBlock(MBB);
+ if (FlagSfiStore)
+ Modified |= SandboxStoresInBlock(MBB);
+ if (FlagSfiBranch)
+ Modified |= SandboxBranchesInBlock(MBB);
+ if (FlagSfiStack)
+ Modified |= SandboxStackChangesInBlock(MBB);
+ }
+
+ if (FlagSfiBranch)
+ AlignAllJumpTargets(MF);
+
+ return Modified;
+}
+
+/// createMipsNaClRewritePass - returns an instance of the NaClRewritePass.
+FunctionPass *llvm::createMipsNaClRewritePass() {
+ return new MipsNaClRewritePass();
+}
« no previous file with comments | « llvm/lib/Target/Mips/MipsNaClRewritePass.h ('k') | llvm/lib/Target/Mips/MipsRegisterInfo.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698