OLD | NEW |
(Empty) | |
| 1 //===-- MipsNaClRewritePass.cpp - Native Client Rewrite Pass ------*- C++ -*-=/
/ |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // Native Client Rewrite Pass |
| 11 // This final pass inserts the sandboxing instructions needed to run inside |
| 12 // the Native Client sandbox. Native Client requires certain software fault |
| 13 // isolation (SFI) constructions to be put in place, to prevent escape from |
| 14 // the sandbox. Native Client refuses to execute binaries without the correct |
| 15 // SFI sequences. |
| 16 // |
| 17 // Potentially dangerous operations which are protected include: |
| 18 // * Stores |
| 19 // * Branches |
| 20 // * Changes to SP |
| 21 // |
| 22 //===----------------------------------------------------------------------===// |
| 23 |
| 24 #define DEBUG_TYPE "mips-sfi" |
| 25 #include "Mips.h" |
| 26 #include "MipsInstrInfo.h" |
| 27 #include "MipsNaClRewritePass.h" |
| 28 #include "llvm/CodeGen/MachineFunctionPass.h" |
| 29 #include "llvm/CodeGen/MachineInstrBuilder.h" |
| 30 #include "llvm/CodeGen/MachineJumpTableInfo.h" |
| 31 #include "llvm/Function.h" |
| 32 #include "llvm/Support/Debug.h" |
| 33 #include "llvm/Support/raw_ostream.h" |
| 34 #include "llvm/Support/CommandLine.h" |
| 35 |
| 36 using namespace llvm; |
| 37 |
| 38 unsigned Mips::LoadStoreStackMaskReg = Mips::T4; |
| 39 unsigned Mips::IndirectBranchMaskReg = Mips::T3; |
| 40 |
| 41 namespace { |
| 42 class MipsNaClRewritePass : public MachineFunctionPass { |
| 43 public: |
| 44 static char ID; |
| 45 MipsNaClRewritePass() : MachineFunctionPass(ID) {} |
| 46 |
| 47 const MipsInstrInfo *TII; |
| 48 const TargetRegisterInfo *TRI; |
| 49 virtual bool runOnMachineFunction(MachineFunction &Fn); |
| 50 |
| 51 virtual const char *getPassName() const { |
| 52 return "Mips Native Client Rewrite Pass"; |
| 53 } |
| 54 |
| 55 private: |
| 56 |
| 57 bool SandboxLoadsInBlock(MachineBasicBlock &MBB); |
| 58 bool SandboxStoresInBlock(MachineBasicBlock &MBB); |
| 59 void SandboxLoadStore(MachineBasicBlock &MBB, |
| 60 MachineBasicBlock::iterator MBBI, |
| 61 MachineInstr &MI, |
| 62 int AddrIdx); |
| 63 |
| 64 bool SandboxBranchesInBlock(MachineBasicBlock &MBB); |
| 65 bool SandboxStackChangesInBlock(MachineBasicBlock &MBB); |
| 66 |
| 67 void SandboxStackChange(MachineBasicBlock &MBB, |
| 68 MachineBasicBlock::iterator MBBI); |
| 69 void AlignAllJumpTargets(MachineFunction &MF); |
| 70 }; |
| 71 char MipsNaClRewritePass::ID = 0; |
| 72 } |
| 73 |
| 74 static bool IsReturn(const MachineInstr &MI) { |
| 75 return (MI.getOpcode() == Mips::RET); |
| 76 } |
| 77 |
| 78 static bool IsIndirectJump(const MachineInstr &MI) { |
| 79 return (MI.getOpcode() == Mips::JR); |
| 80 } |
| 81 |
| 82 static bool IsIndirectCall(const MachineInstr &MI) { |
| 83 return (MI.getOpcode() == Mips::JALR); |
| 84 } |
| 85 |
| 86 static bool IsDirectCall(const MachineInstr &MI) { |
| 87 return (MI.getOpcode() == Mips::JAL); |
| 88 } |
| 89 |
| 90 static bool IsStackMask(const MachineInstr &MI) { |
| 91 return (MI.getOpcode() == Mips::SFI_DATA_MASK); |
| 92 } |
| 93 |
| 94 static bool IsStackChange(const MachineInstr &MI, |
| 95 const TargetRegisterInfo *TRI) { |
| 96 return MI.modifiesRegister(Mips::SP, TRI); |
| 97 } |
| 98 |
| 99 static bool NeedSandboxStackChange(const MachineInstr &MI, |
| 100 const TargetRegisterInfo *TRI) { |
| 101 return (IsStackChange(MI, TRI) && !IsStackMask(MI)); |
| 102 } |
| 103 |
| 104 void MipsNaClRewritePass::SandboxStackChange(MachineBasicBlock &MBB, |
| 105 MachineBasicBlock::iterator MBBI) { |
| 106 MachineInstr &MI = *MBBI; |
| 107 |
| 108 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 109 TII->get(Mips::SFI_NOP_IF_AT_BUNDLE_END)); |
| 110 |
| 111 // Get to next instr (one + to get the original, and one more + to get past). |
| 112 MachineBasicBlock::iterator MBBINext = (MBBI++); |
| 113 MachineBasicBlock::iterator MBBINext2 = (MBBI++); |
| 114 |
| 115 BuildMI(MBB, MBBINext2, MI.getDebugLoc(), |
| 116 TII->get(Mips::SFI_DATA_MASK), Mips::SP) |
| 117 .addReg(Mips::SP) |
| 118 .addReg(Mips::LoadStoreStackMaskReg); |
| 119 return; |
| 120 } |
| 121 |
| 122 bool MipsNaClRewritePass::SandboxStackChangesInBlock(MachineBasicBlock &MBB) { |
| 123 bool Modified = false; |
| 124 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
| 125 MBBI != E; ++MBBI) { |
| 126 MachineInstr &MI = *MBBI; |
| 127 if (NeedSandboxStackChange(MI, TRI)) { |
| 128 SandboxStackChange(MBB, MBBI); |
| 129 Modified |= true; |
| 130 } |
| 131 } |
| 132 return Modified; |
| 133 } |
| 134 |
| 135 bool MipsNaClRewritePass::SandboxBranchesInBlock(MachineBasicBlock &MBB) { |
| 136 bool Modified = false; |
| 137 |
| 138 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
| 139 MBBI != E; ++MBBI) { |
| 140 MachineInstr &MI = *MBBI; |
| 141 |
| 142 if (IsReturn(MI)) { |
| 143 unsigned AddrReg = MI.getOperand(0).getReg(); |
| 144 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 145 TII->get(Mips::SFI_GUARD_RETURN), AddrReg) |
| 146 .addReg(AddrReg) |
| 147 .addReg(Mips::IndirectBranchMaskReg); |
| 148 Modified = true; |
| 149 } |
| 150 |
| 151 if (IsIndirectJump(MI)) { |
| 152 unsigned AddrReg = MI.getOperand(0).getReg(); |
| 153 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 154 TII->get(Mips::SFI_GUARD_INDIRECT_JMP), AddrReg) |
| 155 .addReg(AddrReg) |
| 156 .addReg(Mips::IndirectBranchMaskReg); |
| 157 Modified = true; |
| 158 } |
| 159 |
| 160 if (IsDirectCall(MI)) { |
| 161 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 162 TII->get(Mips::SFI_GUARD_CALL)); |
| 163 Modified = true; |
| 164 } |
| 165 |
| 166 if (IsIndirectCall(MI)) { |
| 167 unsigned AddrReg = MI.getOperand(0).getReg(); |
| 168 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 169 TII->get(Mips::SFI_GUARD_INDIRECT_CALL), AddrReg) |
| 170 .addReg(AddrReg) |
| 171 .addReg(Mips::IndirectBranchMaskReg); |
| 172 Modified = true; |
| 173 } |
| 174 } |
| 175 |
| 176 return Modified; |
| 177 } |
| 178 |
| 179 /* |
| 180 * Sandboxes a load or store instruction by inserting an appropriate mask |
| 181 * operation before it. |
| 182 */ |
| 183 void MipsNaClRewritePass::SandboxLoadStore(MachineBasicBlock &MBB, |
| 184 MachineBasicBlock::iterator MBBI, |
| 185 MachineInstr &MI, |
| 186 int AddrIdx) { |
| 187 unsigned BaseReg = MI.getOperand(AddrIdx).getReg(); |
| 188 |
| 189 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 190 TII->get(Mips::SFI_GUARD_LOAD_STORE), BaseReg) |
| 191 .addReg(BaseReg) |
| 192 .addReg(Mips::LoadStoreStackMaskReg); |
| 193 return; |
| 194 } |
| 195 |
| 196 static bool IsDangerousLoad(const MachineInstr &MI, int *AddrIdx) { |
| 197 unsigned Opcode = MI.getOpcode(); |
| 198 switch (Opcode) { |
| 199 default: return false; |
| 200 |
| 201 // Instructions with base address register in position 1 |
| 202 case Mips::LB: |
| 203 case Mips::LBu: |
| 204 case Mips::LH: |
| 205 case Mips::LHu: |
| 206 case Mips::LW: |
| 207 case Mips::LWC1: |
| 208 case Mips::LDC1: |
| 209 case Mips::LL: |
| 210 *AddrIdx = 1; |
| 211 break; |
| 212 } |
| 213 |
| 214 if (MI.getOperand(*AddrIdx).getReg() == Mips::SP) { |
| 215 // The contents of SP do not require masking. |
| 216 return false; |
| 217 } |
| 218 |
| 219 return true; |
| 220 } |
| 221 |
| 222 static bool IsDangerousStore(const MachineInstr &MI, int *AddrIdx) { |
| 223 unsigned Opcode = MI.getOpcode(); |
| 224 switch (Opcode) { |
| 225 default: return false; |
| 226 |
| 227 // Instructions with base address register in position 1 |
| 228 case Mips::SB: |
| 229 case Mips::SH: |
| 230 case Mips::SW: |
| 231 case Mips::SWC1: |
| 232 case Mips::SDC1: |
| 233 *AddrIdx = 1; |
| 234 break; |
| 235 |
| 236 case Mips::SC: |
| 237 *AddrIdx = 2; |
| 238 break; |
| 239 } |
| 240 |
| 241 if (MI.getOperand(*AddrIdx).getReg() == Mips::SP) { |
| 242 // The contents of SP do not require masking. |
| 243 return false; |
| 244 } |
| 245 |
| 246 return true; |
| 247 } |
| 248 |
| 249 bool MipsNaClRewritePass::SandboxLoadsInBlock(MachineBasicBlock &MBB) { |
| 250 bool Modified = false; |
| 251 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
| 252 MBBI != E; |
| 253 ++MBBI) { |
| 254 MachineInstr &MI = *MBBI; |
| 255 int AddrIdx; |
| 256 |
| 257 if (IsDangerousLoad(MI, &AddrIdx)) { |
| 258 SandboxLoadStore(MBB, MBBI, MI, AddrIdx); |
| 259 Modified = true; |
| 260 } |
| 261 } |
| 262 return Modified; |
| 263 } |
| 264 |
| 265 bool MipsNaClRewritePass::SandboxStoresInBlock(MachineBasicBlock &MBB) { |
| 266 bool Modified = false; |
| 267 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
| 268 MBBI != E; |
| 269 ++MBBI) { |
| 270 MachineInstr &MI = *MBBI; |
| 271 int AddrIdx; |
| 272 |
| 273 if (IsDangerousStore(MI, &AddrIdx)) { |
| 274 SandboxLoadStore(MBB, MBBI, MI, AddrIdx); |
| 275 Modified = true; |
| 276 } |
| 277 } |
| 278 return Modified; |
| 279 } |
| 280 |
| 281 // Make sure all jump targets are aligned |
| 282 void MipsNaClRewritePass::AlignAllJumpTargets(MachineFunction &MF) { |
| 283 // JUMP TABLE TARGETS |
| 284 MachineJumpTableInfo *jt_info = MF.getJumpTableInfo(); |
| 285 if (jt_info) { |
| 286 const std::vector<MachineJumpTableEntry> &JT = jt_info->getJumpTables(); |
| 287 for (unsigned i=0; i < JT.size(); ++i) { |
| 288 std::vector<MachineBasicBlock*> MBBs = JT[i].MBBs; |
| 289 |
| 290 for (unsigned j=0; j < MBBs.size(); ++j) { |
| 291 MBBs[j]->setAlignment(16); |
| 292 } |
| 293 } |
| 294 } |
| 295 |
| 296 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); |
| 297 I != E; ++I) { |
| 298 MachineBasicBlock &MBB = *I; |
| 299 if (MBB.hasAddressTaken()) |
| 300 MBB.setAlignment(16); |
| 301 } |
| 302 } |
| 303 |
| 304 bool MipsNaClRewritePass::runOnMachineFunction(MachineFunction &MF) { |
| 305 TII = static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); |
| 306 TRI = MF.getTarget().getRegisterInfo(); |
| 307 |
| 308 bool Modified = false; |
| 309 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); |
| 310 MFI != E; |
| 311 ++MFI) { |
| 312 MachineBasicBlock &MBB = *MFI; |
| 313 |
| 314 if (FlagSfiLoad) |
| 315 Modified |= SandboxLoadsInBlock(MBB); |
| 316 if (FlagSfiStore) |
| 317 Modified |= SandboxStoresInBlock(MBB); |
| 318 if (FlagSfiBranch) |
| 319 Modified |= SandboxBranchesInBlock(MBB); |
| 320 if (FlagSfiStack) |
| 321 Modified |= SandboxStackChangesInBlock(MBB); |
| 322 } |
| 323 |
| 324 if (FlagSfiBranch) |
| 325 AlignAllJumpTargets(MF); |
| 326 |
| 327 return Modified; |
| 328 } |
| 329 |
| 330 /// createMipsNaClRewritePass - returns an instance of the NaClRewritePass. |
| 331 FunctionPass *llvm::createMipsNaClRewritePass() { |
| 332 return new MipsNaClRewritePass(); |
| 333 } |
OLD | NEW |