OLD | NEW |
(Empty) | |
| 1 //===-- ARMNaClRewritePass.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 "arm-sfi" |
| 25 #include "ARM.h" |
| 26 #include "ARMBaseInstrInfo.h" |
| 27 #include "ARMNaClRewritePass.h" |
| 28 #include "llvm/CodeGen/MachineFunctionPass.h" |
| 29 #include "llvm/CodeGen/MachineInstrBuilder.h" |
| 30 #include "llvm/IR/Function.h" |
| 31 #include "llvm/Support/Debug.h" |
| 32 #include "llvm/Support/raw_ostream.h" |
| 33 #include "llvm/Target/TargetSubtargetInfo.h" |
| 34 #include <set> |
| 35 #include <stdio.h> |
| 36 |
| 37 using namespace llvm; |
| 38 |
| 39 namespace { |
| 40 class ARMNaClRewritePass : public MachineFunctionPass { |
| 41 public: |
| 42 static char ID; |
| 43 ARMNaClRewritePass() : MachineFunctionPass(ID) {} |
| 44 |
| 45 const ARMBaseInstrInfo *TII; |
| 46 const TargetRegisterInfo *TRI; |
| 47 virtual void getAnalysisUsage(AnalysisUsage &AU) const; |
| 48 virtual bool runOnMachineFunction(MachineFunction &Fn); |
| 49 |
| 50 virtual const char *getPassName() const { |
| 51 return "ARM Native Client Rewrite Pass"; |
| 52 } |
| 53 |
| 54 private: |
| 55 |
| 56 bool SandboxMemoryReferencesInBlock(MachineBasicBlock &MBB); |
| 57 void SandboxMemory(MachineBasicBlock &MBB, |
| 58 MachineBasicBlock::iterator MBBI, |
| 59 MachineInstr &MI, |
| 60 int AddrIdx, |
| 61 bool IsLoad); |
| 62 |
| 63 bool SandboxBranchesInBlock(MachineBasicBlock &MBB); |
| 64 bool SandboxStackChangesInBlock(MachineBasicBlock &MBB); |
| 65 |
| 66 void SandboxStackChange(MachineBasicBlock &MBB, |
| 67 MachineBasicBlock::iterator MBBI); |
| 68 void LightweightVerify(MachineFunction &MF); |
| 69 }; |
| 70 char ARMNaClRewritePass::ID = 0; |
| 71 } |
| 72 |
| 73 static bool IsReturn(const MachineInstr &MI) { |
| 74 return (MI.getOpcode() == ARM::BX_RET); |
| 75 } |
| 76 |
| 77 static bool IsIndirectJump(const MachineInstr &MI) { |
| 78 switch (MI.getOpcode()) { |
| 79 default: return false; |
| 80 case ARM::BX: |
| 81 case ARM::TAILJMPr: |
| 82 return true; |
| 83 } |
| 84 } |
| 85 |
| 86 static bool IsIndirectCall(const MachineInstr &MI) { |
| 87 return MI.getOpcode() == ARM::BLX; |
| 88 } |
| 89 |
| 90 static bool IsDirectCall(const MachineInstr &MI) { |
| 91 switch (MI.getOpcode()) { |
| 92 default: return false; |
| 93 case ARM::BL: |
| 94 case ARM::BL_pred: |
| 95 case ARM::TPsoft: |
| 96 return true; |
| 97 } |
| 98 } |
| 99 |
| 100 static void DumpInstructionVerbose(const MachineInstr &MI) { |
| 101 DEBUG({ |
| 102 dbgs() << MI; |
| 103 dbgs() << MI.getNumOperands() << " operands:" << "\n"; |
| 104 for (unsigned i = 0; i < MI.getNumOperands(); ++i) { |
| 105 const MachineOperand& op = MI.getOperand(i); |
| 106 dbgs() << " " << i << "(" << (unsigned)op.getType() << "):" << op |
| 107 << "\n"; |
| 108 } |
| 109 dbgs() << "\n"; |
| 110 }); |
| 111 } |
| 112 |
| 113 static void DumpBasicBlockVerbose(const MachineBasicBlock &MBB) { |
| 114 DEBUG({ |
| 115 dbgs() << "\n<<<<< DUMP BASIC BLOCK START\n"; |
| 116 for (MachineBasicBlock::const_iterator |
| 117 MBBI = MBB.begin(), MBBE = MBB.end(); |
| 118 MBBI != MBBE; |
| 119 ++MBBI) { |
| 120 DumpInstructionVerbose(*MBBI); |
| 121 } |
| 122 dbgs() << "<<<<< DUMP BASIC BLOCK END\n\n"; |
| 123 }); |
| 124 } |
| 125 |
| 126 /**********************************************************************/ |
| 127 /* Exported functions */ |
| 128 |
| 129 namespace ARM_SFI { |
| 130 |
| 131 bool IsStackChange(const MachineInstr &MI, const TargetRegisterInfo *TRI) { |
| 132 return MI.modifiesRegister(ARM::SP, TRI); |
| 133 } |
| 134 |
| 135 bool NextInstrMasksSP(const MachineInstr &MI) { |
| 136 MachineBasicBlock::const_iterator It = &MI; |
| 137 const MachineBasicBlock *MBB = MI.getParent(); |
| 138 |
| 139 MachineBasicBlock::const_iterator next = ++It; |
| 140 if (next == MBB->end()) { |
| 141 return false; |
| 142 } |
| 143 |
| 144 const MachineInstr &next_instr = *next; |
| 145 unsigned opcode = next_instr.getOpcode(); |
| 146 return (opcode == ARM::SFI_DATA_MASK) && |
| 147 (next_instr.getOperand(0).getReg() == ARM::SP); |
| 148 } |
| 149 |
| 150 bool IsSandboxedStackChange(const MachineInstr &MI) { |
| 151 // Calls do not change the stack on ARM but they have implicit-defs, so |
| 152 // make sure they do not get sandboxed. |
| 153 if (MI.getDesc().isCall()) |
| 154 return true; |
| 155 |
| 156 unsigned opcode = MI.getOpcode(); |
| 157 switch (opcode) { |
| 158 default: break; |
| 159 |
| 160 // Our mask instructions correctly update the stack pointer. |
| 161 case ARM::SFI_DATA_MASK: |
| 162 return true; |
| 163 |
| 164 // These just bump SP by a little (and access the stack), |
| 165 // so that is okay due to guard pages. |
| 166 case ARM::STMIA_UPD: |
| 167 case ARM::STMDA_UPD: |
| 168 case ARM::STMDB_UPD: |
| 169 case ARM::STMIB_UPD: |
| 170 |
| 171 case ARM::VSTMDIA_UPD: |
| 172 case ARM::VSTMDDB_UPD: |
| 173 case ARM::VSTMSIA_UPD: |
| 174 case ARM::VSTMSDB_UPD: |
| 175 return true; |
| 176 |
| 177 // Similar, unless it is a load into SP... |
| 178 case ARM::LDMIA_UPD: |
| 179 case ARM::LDMDA_UPD: |
| 180 case ARM::LDMDB_UPD: |
| 181 case ARM::LDMIB_UPD: |
| 182 |
| 183 case ARM::VLDMDIA_UPD: |
| 184 case ARM::VLDMDDB_UPD: |
| 185 case ARM::VLDMSIA_UPD: |
| 186 case ARM::VLDMSDB_UPD: { |
| 187 bool dest_SP = false; |
| 188 // Dest regs start at operand index 4. |
| 189 for (unsigned i = 4; i < MI.getNumOperands(); ++i) { |
| 190 const MachineOperand &DestReg = MI.getOperand(i); |
| 191 dest_SP = dest_SP || (DestReg.getReg() == ARM::SP); |
| 192 } |
| 193 if (dest_SP) { |
| 194 break; |
| 195 } |
| 196 return true; |
| 197 } |
| 198 |
| 199 // Some localmods *should* prevent selecting a reg offset |
| 200 // (see SelectAddrMode2 in ARMISelDAGToDAG.cpp). |
| 201 // Otherwise, the store is already a potential violation. |
| 202 case ARM::STR_PRE_REG: |
| 203 case ARM::STR_PRE_IMM: |
| 204 |
| 205 case ARM::STRH_PRE: |
| 206 |
| 207 case ARM::STRB_PRE_REG: |
| 208 case ARM::STRB_PRE_IMM: |
| 209 return true; |
| 210 |
| 211 // Similar, unless it is a load into SP... |
| 212 case ARM::LDRi12: |
| 213 case ARM::LDR_PRE_REG: |
| 214 case ARM::LDR_PRE_IMM: |
| 215 case ARM::LDRH_PRE: |
| 216 case ARM::LDRB_PRE_REG: |
| 217 case ARM::LDRB_PRE_IMM: |
| 218 case ARM::LDRSH_PRE: |
| 219 case ARM::LDRSB_PRE: { |
| 220 const MachineOperand &DestReg = MI.getOperand(0); |
| 221 if (DestReg.getReg() == ARM::SP) { |
| 222 break; |
| 223 } |
| 224 return true; |
| 225 } |
| 226 |
| 227 // Here, if SP is the base / write-back reg, we need to check if |
| 228 // a reg is used as offset (otherwise it is not a small nudge). |
| 229 case ARM::STR_POST_REG: |
| 230 case ARM::STR_POST_IMM: |
| 231 case ARM::STRH_POST: |
| 232 case ARM::STRB_POST_REG: |
| 233 case ARM::STRB_POST_IMM: { |
| 234 const MachineOperand &WBReg = MI.getOperand(0); |
| 235 const MachineOperand &OffReg = MI.getOperand(3); |
| 236 if (WBReg.getReg() == ARM::SP && OffReg.getReg() != 0) { |
| 237 break; |
| 238 } |
| 239 return true; |
| 240 } |
| 241 |
| 242 // Similar, but also check that DestReg is not SP. |
| 243 case ARM::LDR_POST_REG: |
| 244 case ARM::LDR_POST_IMM: |
| 245 case ARM::LDRB_POST_REG: |
| 246 case ARM::LDRB_POST_IMM: |
| 247 case ARM::LDRH_POST: |
| 248 case ARM::LDRSH_POST: |
| 249 case ARM::LDRSB_POST: { |
| 250 const MachineOperand &DestReg = MI.getOperand(0); |
| 251 if (DestReg.getReg() == ARM::SP) { |
| 252 break; |
| 253 } |
| 254 const MachineOperand &WBReg = MI.getOperand(1); |
| 255 const MachineOperand &OffReg = MI.getOperand(3); |
| 256 if (WBReg.getReg() == ARM::SP && OffReg.getReg() != 0) { |
| 257 break; |
| 258 } |
| 259 return true; |
| 260 } |
| 261 } |
| 262 |
| 263 return (NextInstrMasksSP(MI)); |
| 264 } |
| 265 |
| 266 bool NeedSandboxStackChange(const MachineInstr &MI, |
| 267 const TargetRegisterInfo *TRI) { |
| 268 return (IsStackChange(MI, TRI) && !IsSandboxedStackChange(MI)); |
| 269 } |
| 270 |
| 271 } // namespace ARM_SFI |
| 272 |
| 273 /**********************************************************************/ |
| 274 |
| 275 void ARMNaClRewritePass::getAnalysisUsage(AnalysisUsage &AU) const { |
| 276 // Slight (possibly unnecessary) efficiency tweak: |
| 277 // Promise not to modify the CFG. |
| 278 AU.setPreservesCFG(); |
| 279 MachineFunctionPass::getAnalysisUsage(AU); |
| 280 } |
| 281 |
| 282 /* |
| 283 * A primitive validator to catch problems at compile time. |
| 284 * E.g., it could be used along with bugpoint to reduce a bitcode file. |
| 285 */ |
| 286 void ARMNaClRewritePass::LightweightVerify(MachineFunction &MF) { |
| 287 DEBUG({ |
| 288 for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end(); |
| 289 MFI != MFE; |
| 290 ++MFI) { |
| 291 MachineBasicBlock &MBB = *MFI; |
| 292 for (MachineBasicBlock::iterator MBBI = MBB.begin(), MBBE = MBB.end(); |
| 293 MBBI != MBBE; |
| 294 ++MBBI) { |
| 295 MachineInstr &MI = *MBBI; |
| 296 if (ARM_SFI::NeedSandboxStackChange(MI, TRI)) { |
| 297 dbgs() << "LightWeightVerify for function: " |
| 298 << MF.getFunction()->getName() << " (BAD STACK CHANGE)\n"; |
| 299 DumpInstructionVerbose(MI); |
| 300 DumpBasicBlockVerbose(MBB); |
| 301 } |
| 302 } |
| 303 } |
| 304 }); |
| 305 } |
| 306 |
| 307 void ARMNaClRewritePass::SandboxStackChange(MachineBasicBlock &MBB, |
| 308 MachineBasicBlock::iterator MBBI) { |
| 309 // (1) Ensure there is room in the bundle for a data mask instruction |
| 310 // (nop'ing to the next bundle if needed). |
| 311 // (2) Do a data mask on SP after the instruction that updated SP. |
| 312 MachineInstr &MI = *MBBI; |
| 313 |
| 314 // Use same predicate as current instruction. |
| 315 unsigned PredReg = 0; |
| 316 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg); |
| 317 |
| 318 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 319 TII->get(ARM::SFI_NOP_IF_AT_BUNDLE_END)); |
| 320 |
| 321 // Get to next instr. |
| 322 MachineBasicBlock::iterator MBBINext = (++MBBI); |
| 323 |
| 324 BuildMI(MBB, MBBINext, MI.getDebugLoc(), |
| 325 TII->get(ARM::SFI_DATA_MASK)) |
| 326 .addReg(ARM::SP, RegState::Define) // modify SP (as dst) |
| 327 .addReg(ARM::SP, RegState::Kill) // start with SP (as src) |
| 328 .addImm((int64_t) Pred) // predicate condition |
| 329 .addReg(PredReg); // predicate source register (CPSR) |
| 330 } |
| 331 |
| 332 bool ARMNaClRewritePass::SandboxStackChangesInBlock(MachineBasicBlock &MBB) { |
| 333 bool Modified = false; |
| 334 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
| 335 MBBI != E; |
| 336 ++MBBI) { |
| 337 MachineInstr &MI = *MBBI; |
| 338 if (ARM_SFI::NeedSandboxStackChange(MI, TRI)) { |
| 339 SandboxStackChange(MBB, MBBI); |
| 340 Modified |= true; |
| 341 } |
| 342 } |
| 343 return Modified; |
| 344 } |
| 345 |
| 346 bool ARMNaClRewritePass::SandboxBranchesInBlock(MachineBasicBlock &MBB) { |
| 347 bool Modified = false; |
| 348 |
| 349 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
| 350 MBBI != E; |
| 351 ++MBBI) { |
| 352 MachineInstr &MI = *MBBI; |
| 353 // Use same predicate as current instruction. |
| 354 unsigned PredReg = 0; |
| 355 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg); |
| 356 |
| 357 if (IsReturn(MI)) { |
| 358 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 359 TII->get(ARM::SFI_GUARD_RETURN)) |
| 360 .addImm((int64_t) Pred) // predicate condition |
| 361 .addReg(PredReg); // predicate source register (CPSR) |
| 362 Modified = true; |
| 363 } |
| 364 |
| 365 if (IsIndirectJump(MI)) { |
| 366 unsigned Addr = MI.getOperand(0).getReg(); |
| 367 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 368 TII->get(ARM::SFI_GUARD_INDIRECT_JMP)) |
| 369 .addReg(Addr, RegState::Define) // Destination definition (as dst) |
| 370 .addReg(Addr, RegState::Kill) // Destination read (as src) |
| 371 .addImm((int64_t) Pred) // predicate condition |
| 372 .addReg(PredReg); // predicate source register (CPSR) |
| 373 Modified = true; |
| 374 } |
| 375 |
| 376 if (IsDirectCall(MI)) { |
| 377 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 378 TII->get(ARM::SFI_GUARD_CALL)) |
| 379 .addImm((int64_t) Pred) // predicate condition |
| 380 .addReg(PredReg); // predicate source register (CPSR) |
| 381 Modified = true; |
| 382 } |
| 383 |
| 384 if (IsIndirectCall(MI)) { |
| 385 unsigned Addr = MI.getOperand(0).getReg(); |
| 386 BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 387 TII->get(ARM::SFI_GUARD_INDIRECT_CALL)) |
| 388 .addReg(Addr, RegState::Define) // Destination definition (as dst) |
| 389 .addReg(Addr, RegState::Kill) // Destination read (as src) |
| 390 .addImm((int64_t) Pred) // predicate condition |
| 391 .addReg(PredReg); // predicate source register (CPSR) |
| 392 Modified = true; |
| 393 } |
| 394 } |
| 395 |
| 396 return Modified; |
| 397 } |
| 398 |
| 399 static bool IsDangerousLoad(const MachineInstr &MI, int *AddrIdx) { |
| 400 unsigned Opcode = MI.getOpcode(); |
| 401 switch (Opcode) { |
| 402 default: return false; |
| 403 |
| 404 // Instructions with base address register in position 0... |
| 405 case ARM::LDMIA: |
| 406 case ARM::LDMDA: |
| 407 case ARM::LDMDB: |
| 408 case ARM::LDMIB: |
| 409 |
| 410 case ARM::VLDMDIA: |
| 411 case ARM::VLDMSIA: |
| 412 |
| 413 case ARM::PLDi12: |
| 414 case ARM::PLDWi12: |
| 415 case ARM::PLIi12: |
| 416 *AddrIdx = 0; |
| 417 break; |
| 418 // Instructions with base address register in position 1... |
| 419 case ARM::LDMIA_UPD: // same reg at position 0 and position 1 |
| 420 case ARM::LDMDA_UPD: |
| 421 case ARM::LDMDB_UPD: |
| 422 case ARM::LDMIB_UPD: |
| 423 |
| 424 case ARM::LDRSB: |
| 425 case ARM::LDRH: |
| 426 case ARM::LDRSH: |
| 427 |
| 428 case ARM::LDRi12: |
| 429 case ARM::LDRrs: |
| 430 case ARM::LDRBi12: |
| 431 case ARM::LDRBrs: |
| 432 case ARM::VLDMDIA_UPD: |
| 433 case ARM::VLDMDDB_UPD: |
| 434 case ARM::VLDMSIA_UPD: |
| 435 case ARM::VLDMSDB_UPD: |
| 436 case ARM::VLDRS: |
| 437 case ARM::VLDRD: |
| 438 |
| 439 case ARM::LDREX: |
| 440 case ARM::LDREXB: |
| 441 case ARM::LDREXH: |
| 442 case ARM::LDREXD: |
| 443 *AddrIdx = 1; |
| 444 break; |
| 445 |
| 446 // Instructions with base address register in position 2... |
| 447 case ARM::LDR_PRE_REG: |
| 448 case ARM::LDR_PRE_IMM: |
| 449 case ARM::LDR_POST_REG: |
| 450 case ARM::LDR_POST_IMM: |
| 451 |
| 452 case ARM::LDRB_PRE_REG: |
| 453 case ARM::LDRB_PRE_IMM: |
| 454 case ARM::LDRB_POST_REG: |
| 455 case ARM::LDRB_POST_IMM: |
| 456 case ARM::LDRSB_PRE: |
| 457 case ARM::LDRSB_POST: |
| 458 |
| 459 case ARM::LDRH_PRE: |
| 460 case ARM::LDRH_POST: |
| 461 case ARM::LDRSH_PRE: |
| 462 case ARM::LDRSH_POST: |
| 463 |
| 464 case ARM::LDRD: |
| 465 *AddrIdx = 2; |
| 466 break; |
| 467 |
| 468 // |
| 469 // NEON loads |
| 470 // |
| 471 |
| 472 // VLD1 |
| 473 case ARM::VLD1d8: |
| 474 case ARM::VLD1d16: |
| 475 case ARM::VLD1d32: |
| 476 case ARM::VLD1d64: |
| 477 case ARM::VLD1q8: |
| 478 case ARM::VLD1q16: |
| 479 case ARM::VLD1q32: |
| 480 case ARM::VLD1q64: |
| 481 *AddrIdx = 1; |
| 482 break; |
| 483 |
| 484 case ARM::VLD1d8wb_fixed: |
| 485 case ARM::VLD1d16wb_fixed: |
| 486 case ARM::VLD1d32wb_fixed: |
| 487 case ARM::VLD1d64wb_fixed: |
| 488 case ARM::VLD1q8wb_fixed: |
| 489 case ARM::VLD1q16wb_fixed: |
| 490 case ARM::VLD1q32wb_fixed: |
| 491 case ARM::VLD1q64wb_fixed: |
| 492 case ARM::VLD1d8wb_register: |
| 493 case ARM::VLD1d16wb_register: |
| 494 case ARM::VLD1d32wb_register: |
| 495 case ARM::VLD1d64wb_register: |
| 496 case ARM::VLD1q8wb_register: |
| 497 case ARM::VLD1q16wb_register: |
| 498 case ARM::VLD1q32wb_register: |
| 499 case ARM::VLD1q64wb_register: |
| 500 *AddrIdx = 2; |
| 501 break; |
| 502 |
| 503 // VLD1T |
| 504 case ARM::VLD1d8T: |
| 505 case ARM::VLD1d16T: |
| 506 case ARM::VLD1d32T: |
| 507 case ARM::VLD1d64T: |
| 508 *AddrIdx = 1; |
| 509 break; |
| 510 |
| 511 case ARM::VLD1d8Twb_fixed: |
| 512 case ARM::VLD1d16Twb_fixed: |
| 513 case ARM::VLD1d32Twb_fixed: |
| 514 case ARM::VLD1d64Twb_fixed: |
| 515 case ARM::VLD1d8Twb_register: |
| 516 case ARM::VLD1d16Twb_register: |
| 517 case ARM::VLD1d32Twb_register: |
| 518 case ARM::VLD1d64Twb_register: |
| 519 *AddrIdx = 2; |
| 520 break; |
| 521 |
| 522 // VLD1Q |
| 523 case ARM::VLD1d8Q: |
| 524 case ARM::VLD1d16Q: |
| 525 case ARM::VLD1d32Q: |
| 526 case ARM::VLD1d64Q: |
| 527 *AddrIdx = 1; |
| 528 break; |
| 529 |
| 530 case ARM::VLD1d8Qwb_fixed: |
| 531 case ARM::VLD1d16Qwb_fixed: |
| 532 case ARM::VLD1d32Qwb_fixed: |
| 533 case ARM::VLD1d64Qwb_fixed: |
| 534 case ARM::VLD1d8Qwb_register: |
| 535 case ARM::VLD1d16Qwb_register: |
| 536 case ARM::VLD1d32Qwb_register: |
| 537 case ARM::VLD1d64Qwb_register: |
| 538 *AddrIdx = 2; |
| 539 break; |
| 540 |
| 541 // VLD1LN |
| 542 case ARM::VLD1LNd8: |
| 543 case ARM::VLD1LNd16: |
| 544 case ARM::VLD1LNd32: |
| 545 case ARM::VLD1LNd8_UPD: |
| 546 case ARM::VLD1LNd16_UPD: |
| 547 case ARM::VLD1LNd32_UPD: |
| 548 |
| 549 // VLD1DUP |
| 550 case ARM::VLD1DUPd8: |
| 551 case ARM::VLD1DUPd16: |
| 552 case ARM::VLD1DUPd32: |
| 553 case ARM::VLD1DUPq8: |
| 554 case ARM::VLD1DUPq16: |
| 555 case ARM::VLD1DUPq32: |
| 556 case ARM::VLD1DUPd8wb_fixed: |
| 557 case ARM::VLD1DUPd16wb_fixed: |
| 558 case ARM::VLD1DUPd32wb_fixed: |
| 559 case ARM::VLD1DUPq8wb_fixed: |
| 560 case ARM::VLD1DUPq16wb_fixed: |
| 561 case ARM::VLD1DUPq32wb_fixed: |
| 562 case ARM::VLD1DUPd8wb_register: |
| 563 case ARM::VLD1DUPd16wb_register: |
| 564 case ARM::VLD1DUPd32wb_register: |
| 565 case ARM::VLD1DUPq8wb_register: |
| 566 case ARM::VLD1DUPq16wb_register: |
| 567 case ARM::VLD1DUPq32wb_register: |
| 568 |
| 569 // VLD2 |
| 570 case ARM::VLD2d8: |
| 571 case ARM::VLD2d16: |
| 572 case ARM::VLD2d32: |
| 573 case ARM::VLD2b8: |
| 574 case ARM::VLD2b16: |
| 575 case ARM::VLD2b32: |
| 576 case ARM::VLD2q8: |
| 577 case ARM::VLD2q16: |
| 578 case ARM::VLD2q32: |
| 579 *AddrIdx = 1; |
| 580 break; |
| 581 |
| 582 case ARM::VLD2d8wb_fixed: |
| 583 case ARM::VLD2d16wb_fixed: |
| 584 case ARM::VLD2d32wb_fixed: |
| 585 case ARM::VLD2b8wb_fixed: |
| 586 case ARM::VLD2b16wb_fixed: |
| 587 case ARM::VLD2b32wb_fixed: |
| 588 case ARM::VLD2q8wb_fixed: |
| 589 case ARM::VLD2q16wb_fixed: |
| 590 case ARM::VLD2q32wb_fixed: |
| 591 case ARM::VLD2d8wb_register: |
| 592 case ARM::VLD2d16wb_register: |
| 593 case ARM::VLD2d32wb_register: |
| 594 case ARM::VLD2b8wb_register: |
| 595 case ARM::VLD2b16wb_register: |
| 596 case ARM::VLD2b32wb_register: |
| 597 case ARM::VLD2q8wb_register: |
| 598 case ARM::VLD2q16wb_register: |
| 599 case ARM::VLD2q32wb_register: |
| 600 *AddrIdx = 2; |
| 601 break; |
| 602 |
| 603 // VLD2LN |
| 604 case ARM::VLD2LNd8: |
| 605 case ARM::VLD2LNd16: |
| 606 case ARM::VLD2LNd32: |
| 607 case ARM::VLD2LNq16: |
| 608 case ARM::VLD2LNq32: |
| 609 *AddrIdx = 2; |
| 610 break; |
| 611 |
| 612 case ARM::VLD2LNd8_UPD: |
| 613 case ARM::VLD2LNd16_UPD: |
| 614 case ARM::VLD2LNd32_UPD: |
| 615 case ARM::VLD2LNq16_UPD: |
| 616 case ARM::VLD2LNq32_UPD: |
| 617 *AddrIdx = 3; |
| 618 break; |
| 619 |
| 620 // VLD2DUP |
| 621 case ARM::VLD2DUPd8: |
| 622 case ARM::VLD2DUPd16: |
| 623 case ARM::VLD2DUPd32: |
| 624 case ARM::VLD2DUPd8x2: |
| 625 case ARM::VLD2DUPd16x2: |
| 626 case ARM::VLD2DUPd32x2: |
| 627 *AddrIdx = 1; |
| 628 break; |
| 629 |
| 630 case ARM::VLD2DUPd8wb_fixed: |
| 631 case ARM::VLD2DUPd16wb_fixed: |
| 632 case ARM::VLD2DUPd32wb_fixed: |
| 633 case ARM::VLD2DUPd8wb_register: |
| 634 case ARM::VLD2DUPd16wb_register: |
| 635 case ARM::VLD2DUPd32wb_register: |
| 636 case ARM::VLD2DUPd8x2wb_fixed: |
| 637 case ARM::VLD2DUPd16x2wb_fixed: |
| 638 case ARM::VLD2DUPd32x2wb_fixed: |
| 639 case ARM::VLD2DUPd8x2wb_register: |
| 640 case ARM::VLD2DUPd16x2wb_register: |
| 641 case ARM::VLD2DUPd32x2wb_register: |
| 642 *AddrIdx = 2; |
| 643 break; |
| 644 |
| 645 // VLD3 |
| 646 case ARM::VLD3d8: |
| 647 case ARM::VLD3d16: |
| 648 case ARM::VLD3d32: |
| 649 case ARM::VLD3q8: |
| 650 case ARM::VLD3q16: |
| 651 case ARM::VLD3q32: |
| 652 case ARM::VLD3d8_UPD: |
| 653 case ARM::VLD3d16_UPD: |
| 654 case ARM::VLD3d32_UPD: |
| 655 case ARM::VLD3q8_UPD: |
| 656 case ARM::VLD3q16_UPD: |
| 657 case ARM::VLD3q32_UPD: |
| 658 |
| 659 // VLD3LN |
| 660 case ARM::VLD3LNd8: |
| 661 case ARM::VLD3LNd16: |
| 662 case ARM::VLD3LNd32: |
| 663 case ARM::VLD3LNq16: |
| 664 case ARM::VLD3LNq32: |
| 665 *AddrIdx = 3; |
| 666 break; |
| 667 |
| 668 case ARM::VLD3LNd8_UPD: |
| 669 case ARM::VLD3LNd16_UPD: |
| 670 case ARM::VLD3LNd32_UPD: |
| 671 case ARM::VLD3LNq16_UPD: |
| 672 case ARM::VLD3LNq32_UPD: |
| 673 *AddrIdx = 4; |
| 674 break; |
| 675 |
| 676 // VLD3DUP |
| 677 case ARM::VLD3DUPd8: |
| 678 case ARM::VLD3DUPd16: |
| 679 case ARM::VLD3DUPd32: |
| 680 case ARM::VLD3DUPq8: |
| 681 case ARM::VLD3DUPq16: |
| 682 case ARM::VLD3DUPq32: |
| 683 *AddrIdx = 3; |
| 684 break; |
| 685 |
| 686 case ARM::VLD3DUPd8_UPD: |
| 687 case ARM::VLD3DUPd16_UPD: |
| 688 case ARM::VLD3DUPd32_UPD: |
| 689 case ARM::VLD3DUPq8_UPD: |
| 690 case ARM::VLD3DUPq16_UPD: |
| 691 case ARM::VLD3DUPq32_UPD: |
| 692 *AddrIdx = 4; |
| 693 break; |
| 694 |
| 695 // VLD4 |
| 696 case ARM::VLD4d8: |
| 697 case ARM::VLD4d16: |
| 698 case ARM::VLD4d32: |
| 699 case ARM::VLD4q8: |
| 700 case ARM::VLD4q16: |
| 701 case ARM::VLD4q32: |
| 702 *AddrIdx = 4; |
| 703 break; |
| 704 |
| 705 case ARM::VLD4d8_UPD: |
| 706 case ARM::VLD4d16_UPD: |
| 707 case ARM::VLD4d32_UPD: |
| 708 case ARM::VLD4q8_UPD: |
| 709 case ARM::VLD4q16_UPD: |
| 710 case ARM::VLD4q32_UPD: |
| 711 *AddrIdx = 5; |
| 712 break; |
| 713 |
| 714 // VLD4LN |
| 715 case ARM::VLD4LNd8: |
| 716 case ARM::VLD4LNd16: |
| 717 case ARM::VLD4LNd32: |
| 718 case ARM::VLD4LNq16: |
| 719 case ARM::VLD4LNq32: |
| 720 *AddrIdx = 4; |
| 721 break; |
| 722 |
| 723 case ARM::VLD4LNd8_UPD: |
| 724 case ARM::VLD4LNd16_UPD: |
| 725 case ARM::VLD4LNd32_UPD: |
| 726 case ARM::VLD4LNq16_UPD: |
| 727 case ARM::VLD4LNq32_UPD: |
| 728 *AddrIdx = 5; |
| 729 break; |
| 730 |
| 731 case ARM::VLD4DUPd8: |
| 732 case ARM::VLD4DUPd16: |
| 733 case ARM::VLD4DUPd32: |
| 734 case ARM::VLD4DUPq16: |
| 735 case ARM::VLD4DUPq32: |
| 736 *AddrIdx = 4; |
| 737 break; |
| 738 |
| 739 case ARM::VLD4DUPd8_UPD: |
| 740 case ARM::VLD4DUPd16_UPD: |
| 741 case ARM::VLD4DUPd32_UPD: |
| 742 case ARM::VLD4DUPq16_UPD: |
| 743 case ARM::VLD4DUPq32_UPD: |
| 744 *AddrIdx = 5; |
| 745 break; |
| 746 } |
| 747 |
| 748 if (MI.getOperand(*AddrIdx).getReg() == ARM::SP) { |
| 749 // The contents of SP do not require masking. |
| 750 return false; |
| 751 } |
| 752 |
| 753 return true; |
| 754 } |
| 755 |
| 756 /* |
| 757 * Sandboxes a memory reference instruction by inserting an appropriate mask |
| 758 * or check operation before it. |
| 759 */ |
| 760 void ARMNaClRewritePass::SandboxMemory(MachineBasicBlock &MBB, |
| 761 MachineBasicBlock::iterator MBBI, |
| 762 MachineInstr &MI, |
| 763 int AddrIdx, |
| 764 bool IsLoad) { |
| 765 unsigned Addr = MI.getOperand(AddrIdx).getReg(); |
| 766 |
| 767 if (Addr == ARM::R9) { |
| 768 // R9-relative loads are no longer sandboxed. |
| 769 assert(IsLoad && "There should be no r9-relative stores"); |
| 770 } else { |
| 771 unsigned Opcode; |
| 772 if (IsLoad && (MI.getOperand(0).getReg() == ARM::SP)) { |
| 773 Opcode = ARM::SFI_GUARD_SP_LOAD; |
| 774 } else { |
| 775 Opcode = ARM::SFI_GUARD_LOADSTORE; |
| 776 } |
| 777 // Use same predicate as current instruction. |
| 778 unsigned PredReg = 0; |
| 779 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg); |
| 780 // Use the older BIC sandbox, which is universal, but incurs a stall. |
| 781 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode)) |
| 782 .addReg(Addr, RegState::Define) // Address definition (as dst). |
| 783 .addReg(Addr, RegState::Kill) // Address read (as src). |
| 784 .addImm((int64_t) Pred) // predicate condition |
| 785 .addReg(PredReg); // predicate source register (CPSR) |
| 786 |
| 787 /* |
| 788 * This pseudo-instruction is intended to generate something resembling the |
| 789 * following, but with alignment enforced. |
| 790 * TODO(cbiffle): move alignment into this function, use the code below. |
| 791 * |
| 792 * // bic<cc> Addr, Addr, #0xC0000000 |
| 793 * BuildMI(MBB, MBBI, MI.getDebugLoc(), |
| 794 * TII->get(ARM::BICri)) |
| 795 * .addReg(Addr) // rD |
| 796 * .addReg(Addr) // rN |
| 797 * .addImm(0xC0000000) // imm |
| 798 * .addImm((int64_t) Pred) // predicate condition |
| 799 * .addReg(PredReg) // predicate source register (CPSR) |
| 800 * .addReg(0); // flag output register (0 == no flags) |
| 801 */ |
| 802 } |
| 803 } |
| 804 |
| 805 static bool IsDangerousStore(const MachineInstr &MI, int *AddrIdx) { |
| 806 unsigned Opcode = MI.getOpcode(); |
| 807 switch (Opcode) { |
| 808 default: return false; |
| 809 |
| 810 // Instructions with base address register in position 0... |
| 811 case ARM::STMIA: |
| 812 case ARM::STMDA: |
| 813 case ARM::STMDB: |
| 814 case ARM::STMIB: |
| 815 |
| 816 case ARM::VSTMDIA: |
| 817 case ARM::VSTMSIA: |
| 818 *AddrIdx = 0; |
| 819 break; |
| 820 |
| 821 // Instructions with base address register in position 1... |
| 822 case ARM::STMIA_UPD: // same reg at position 0 and position 1 |
| 823 case ARM::STMDA_UPD: |
| 824 case ARM::STMDB_UPD: |
| 825 case ARM::STMIB_UPD: |
| 826 |
| 827 case ARM::STRH: |
| 828 case ARM::STRi12: |
| 829 case ARM::STRrs: |
| 830 case ARM::STRBi12: |
| 831 case ARM::STRBrs: |
| 832 case ARM::VSTMDIA_UPD: |
| 833 case ARM::VSTMDDB_UPD: |
| 834 case ARM::VSTMSIA_UPD: |
| 835 case ARM::VSTMSDB_UPD: |
| 836 case ARM::VSTRS: |
| 837 case ARM::VSTRD: |
| 838 *AddrIdx = 1; |
| 839 break; |
| 840 |
| 841 // |
| 842 // NEON stores |
| 843 // |
| 844 |
| 845 // VST1 |
| 846 case ARM::VST1d8: |
| 847 case ARM::VST1d16: |
| 848 case ARM::VST1d32: |
| 849 case ARM::VST1d64: |
| 850 case ARM::VST1q8: |
| 851 case ARM::VST1q16: |
| 852 case ARM::VST1q32: |
| 853 case ARM::VST1q64: |
| 854 *AddrIdx = 0; |
| 855 break; |
| 856 |
| 857 case ARM::VST1d8wb_fixed: |
| 858 case ARM::VST1d16wb_fixed: |
| 859 case ARM::VST1d32wb_fixed: |
| 860 case ARM::VST1d64wb_fixed: |
| 861 case ARM::VST1q8wb_fixed: |
| 862 case ARM::VST1q16wb_fixed: |
| 863 case ARM::VST1q32wb_fixed: |
| 864 case ARM::VST1q64wb_fixed: |
| 865 case ARM::VST1d8wb_register: |
| 866 case ARM::VST1d16wb_register: |
| 867 case ARM::VST1d32wb_register: |
| 868 case ARM::VST1d64wb_register: |
| 869 case ARM::VST1q8wb_register: |
| 870 case ARM::VST1q16wb_register: |
| 871 case ARM::VST1q32wb_register: |
| 872 case ARM::VST1q64wb_register: |
| 873 *AddrIdx = 1; |
| 874 break; |
| 875 |
| 876 // VST1LN |
| 877 case ARM::VST1LNd8: |
| 878 case ARM::VST1LNd16: |
| 879 case ARM::VST1LNd32: |
| 880 *AddrIdx = 0; |
| 881 break; |
| 882 |
| 883 case ARM::VST1LNd8_UPD: |
| 884 case ARM::VST1LNd16_UPD: |
| 885 case ARM::VST1LNd32_UPD: |
| 886 *AddrIdx = 1; |
| 887 break; |
| 888 |
| 889 // VST2 |
| 890 case ARM::VST2d8: |
| 891 case ARM::VST2d16: |
| 892 case ARM::VST2d32: |
| 893 case ARM::VST2q8: |
| 894 case ARM::VST2q16: |
| 895 case ARM::VST2q32: |
| 896 *AddrIdx = 0; |
| 897 break; |
| 898 |
| 899 case ARM::VST2d8wb_fixed: |
| 900 case ARM::VST2d16wb_fixed: |
| 901 case ARM::VST2d32wb_fixed: |
| 902 case ARM::VST2q8wb_fixed: |
| 903 case ARM::VST2q16wb_fixed: |
| 904 case ARM::VST2q32wb_fixed: |
| 905 case ARM::VST2d8wb_register: |
| 906 case ARM::VST2d16wb_register: |
| 907 case ARM::VST2d32wb_register: |
| 908 case ARM::VST2q8wb_register: |
| 909 case ARM::VST2q16wb_register: |
| 910 case ARM::VST2q32wb_register: |
| 911 *AddrIdx = 1; |
| 912 break; |
| 913 |
| 914 // VST2LN |
| 915 case ARM::VST2LNd8: |
| 916 case ARM::VST2LNd16: |
| 917 case ARM::VST2LNq16: |
| 918 case ARM::VST2LNd32: |
| 919 case ARM::VST2LNq32: |
| 920 *AddrIdx = 0; |
| 921 break; |
| 922 |
| 923 case ARM::VST2LNd8_UPD: |
| 924 case ARM::VST2LNd16_UPD: |
| 925 case ARM::VST2LNq16_UPD: |
| 926 case ARM::VST2LNd32_UPD: |
| 927 case ARM::VST2LNq32_UPD: |
| 928 *AddrIdx = 1; |
| 929 break; |
| 930 |
| 931 // VST3 |
| 932 case ARM::VST3d8: |
| 933 case ARM::VST3d16: |
| 934 case ARM::VST3d32: |
| 935 case ARM::VST3q8: |
| 936 case ARM::VST3q16: |
| 937 case ARM::VST3q32: |
| 938 *AddrIdx = 0; |
| 939 break; |
| 940 |
| 941 case ARM::VST3d8_UPD: |
| 942 case ARM::VST3d16_UPD: |
| 943 case ARM::VST3d32_UPD: |
| 944 case ARM::VST3q8_UPD: |
| 945 case ARM::VST3q16_UPD: |
| 946 case ARM::VST3q32_UPD: |
| 947 *AddrIdx = 1; |
| 948 break; |
| 949 |
| 950 // VST3LN |
| 951 case ARM::VST3LNd8: |
| 952 case ARM::VST3LNd16: |
| 953 case ARM::VST3LNq16: |
| 954 case ARM::VST3LNd32: |
| 955 case ARM::VST3LNq32: |
| 956 *AddrIdx = 0; |
| 957 break; |
| 958 |
| 959 case ARM::VST3LNd8_UPD: |
| 960 case ARM::VST3LNd16_UPD: |
| 961 case ARM::VST3LNq16_UPD: |
| 962 case ARM::VST3LNd32_UPD: |
| 963 case ARM::VST3LNq32_UPD: |
| 964 *AddrIdx = 1; |
| 965 break; |
| 966 |
| 967 // VST4 |
| 968 case ARM::VST4d8: |
| 969 case ARM::VST4d16: |
| 970 case ARM::VST4d32: |
| 971 case ARM::VST4q8: |
| 972 case ARM::VST4q16: |
| 973 case ARM::VST4q32: |
| 974 *AddrIdx = 0; |
| 975 break; |
| 976 |
| 977 case ARM::VST4d8_UPD: |
| 978 case ARM::VST4d16_UPD: |
| 979 case ARM::VST4d32_UPD: |
| 980 case ARM::VST4q8_UPD: |
| 981 case ARM::VST4q16_UPD: |
| 982 case ARM::VST4q32_UPD: |
| 983 *AddrIdx = 1; |
| 984 break; |
| 985 |
| 986 // VST4LN |
| 987 case ARM::VST4LNd8: |
| 988 case ARM::VST4LNd16: |
| 989 case ARM::VST4LNq16: |
| 990 case ARM::VST4LNd32: |
| 991 case ARM::VST4LNq32: |
| 992 *AddrIdx = 0; |
| 993 break; |
| 994 |
| 995 case ARM::VST4LNd8_UPD: |
| 996 case ARM::VST4LNd16_UPD: |
| 997 case ARM::VST4LNq16_UPD: |
| 998 case ARM::VST4LNd32_UPD: |
| 999 case ARM::VST4LNq32_UPD: |
| 1000 *AddrIdx = 1; |
| 1001 break; |
| 1002 |
| 1003 // Instructions with base address register in position 2... |
| 1004 case ARM::STR_PRE_REG: |
| 1005 case ARM::STR_PRE_IMM: |
| 1006 case ARM::STR_POST_REG: |
| 1007 case ARM::STR_POST_IMM: |
| 1008 |
| 1009 case ARM::STRB_PRE_REG: |
| 1010 case ARM::STRB_PRE_IMM: |
| 1011 case ARM::STRB_POST_REG: |
| 1012 case ARM::STRB_POST_IMM: |
| 1013 |
| 1014 case ARM::STRH_PRE: |
| 1015 case ARM::STRH_POST: |
| 1016 |
| 1017 |
| 1018 case ARM::STRD: |
| 1019 case ARM::STREX: |
| 1020 case ARM::STREXB: |
| 1021 case ARM::STREXH: |
| 1022 case ARM::STREXD: |
| 1023 *AddrIdx = 2; |
| 1024 break; |
| 1025 } |
| 1026 |
| 1027 if (MI.getOperand(*AddrIdx).getReg() == ARM::SP) { |
| 1028 // The contents of SP do not require masking. |
| 1029 return false; |
| 1030 } |
| 1031 |
| 1032 return true; |
| 1033 } |
| 1034 |
| 1035 bool ARMNaClRewritePass::SandboxMemoryReferencesInBlock( |
| 1036 MachineBasicBlock &MBB) { |
| 1037 bool Modified = false; |
| 1038 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
| 1039 MBBI != E; |
| 1040 ++MBBI) { |
| 1041 MachineInstr &MI = *MBBI; |
| 1042 int AddrIdx; |
| 1043 |
| 1044 if (IsDangerousLoad(MI, &AddrIdx)) { |
| 1045 SandboxMemory(MBB, MBBI, MI, AddrIdx, true); |
| 1046 Modified = true; |
| 1047 } |
| 1048 if (IsDangerousStore(MI, &AddrIdx)) { |
| 1049 SandboxMemory(MBB, MBBI, MI, AddrIdx, false); |
| 1050 Modified = true; |
| 1051 } |
| 1052 } |
| 1053 return Modified; |
| 1054 } |
| 1055 |
| 1056 /**********************************************************************/ |
| 1057 |
| 1058 bool ARMNaClRewritePass::runOnMachineFunction(MachineFunction &MF) { |
| 1059 TII = static_cast<const ARMBaseInstrInfo*>(MF.getSubtarget().getInstrInfo()); |
| 1060 TRI = MF.getSubtarget().getRegisterInfo(); |
| 1061 |
| 1062 bool Modified = false; |
| 1063 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); |
| 1064 MFI != E; |
| 1065 ++MFI) { |
| 1066 MachineBasicBlock &MBB = *MFI; |
| 1067 |
| 1068 if (MBB.hasAddressTaken()) { |
| 1069 //FIXME: use symbolic constant or get this value from some configuration |
| 1070 MBB.setAlignment(4); |
| 1071 Modified = true; |
| 1072 } |
| 1073 |
| 1074 Modified |= SandboxMemoryReferencesInBlock(MBB); |
| 1075 Modified |= SandboxBranchesInBlock(MBB); |
| 1076 Modified |= SandboxStackChangesInBlock(MBB); |
| 1077 } |
| 1078 DEBUG(LightweightVerify(MF)); |
| 1079 return Modified; |
| 1080 } |
| 1081 |
| 1082 /// createARMNaClRewritePass - returns an instance of the NaClRewritePass. |
| 1083 FunctionPass *llvm::createARMNaClRewritePass() { |
| 1084 return new ARMNaClRewritePass(); |
| 1085 } |
OLD | NEW |