LLVM API Documentation
00001 //===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements MCELFStreamer for Mips NaCl. It emits .o object files 00011 // as required by NaCl's SFI sandbox. It inserts address-masking instructions 00012 // before dangerous control-flow and memory access instructions. It inserts 00013 // address-masking instructions after instructions that change the stack 00014 // pointer. It ensures that the mask and the dangerous instruction are always 00015 // emitted in the same bundle. It aligns call + branch delay to the bundle end, 00016 // so that return address is always aligned to the start of next bundle. 00017 // 00018 //===----------------------------------------------------------------------===// 00019 00020 #include "Mips.h" 00021 #include "MipsELFStreamer.h" 00022 #include "MipsMCNaCl.h" 00023 #include "llvm/MC/MCELFStreamer.h" 00024 00025 using namespace llvm; 00026 00027 #define DEBUG_TYPE "mips-mc-nacl" 00028 00029 namespace { 00030 00031 const unsigned IndirectBranchMaskReg = Mips::T6; 00032 const unsigned LoadStoreStackMaskReg = Mips::T7; 00033 00034 /// Extend the generic MCELFStreamer class so that it can mask dangerous 00035 /// instructions. 00036 00037 class MipsNaClELFStreamer : public MipsELFStreamer { 00038 public: 00039 MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, 00040 MCCodeEmitter *Emitter, const MCSubtargetInfo &STI) 00041 : MipsELFStreamer(Context, TAB, OS, Emitter, STI), PendingCall(false) {} 00042 00043 ~MipsNaClELFStreamer() {} 00044 00045 private: 00046 // Whether we started the sandboxing sequence for calls. Calls are bundled 00047 // with branch delays and aligned to the bundle end. 00048 bool PendingCall; 00049 00050 bool isIndirectJump(const MCInst &MI) { 00051 if (MI.getOpcode() == Mips::JALR) { 00052 // MIPS32r6/MIPS64r6 doesn't have a JR instruction and uses JALR instead. 00053 // JALR is an indirect branch if the link register is $0. 00054 assert(MI.getOperand(0).isReg()); 00055 return MI.getOperand(0).getReg() == Mips::ZERO; 00056 } 00057 return MI.getOpcode() == Mips::JR; 00058 } 00059 00060 bool isStackPointerFirstOperand(const MCInst &MI) { 00061 return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg() 00062 && MI.getOperand(0).getReg() == Mips::SP); 00063 } 00064 00065 bool isCall(const MCInst &MI, bool *IsIndirectCall) { 00066 unsigned Opcode = MI.getOpcode(); 00067 00068 *IsIndirectCall = false; 00069 00070 switch (Opcode) { 00071 default: 00072 return false; 00073 00074 case Mips::JAL: 00075 case Mips::BAL: 00076 case Mips::BAL_BR: 00077 case Mips::BLTZAL: 00078 case Mips::BGEZAL: 00079 return true; 00080 00081 case Mips::JALR: 00082 // JALR is only a call if the link register is not $0. Otherwise it's an 00083 // indirect branch. 00084 assert(MI.getOperand(0).isReg()); 00085 if (MI.getOperand(0).getReg() == Mips::ZERO) 00086 return false; 00087 00088 *IsIndirectCall = true; 00089 return true; 00090 } 00091 } 00092 00093 void emitMask(unsigned AddrReg, unsigned MaskReg, 00094 const MCSubtargetInfo &STI) { 00095 MCInst MaskInst; 00096 MaskInst.setOpcode(Mips::AND); 00097 MaskInst.addOperand(MCOperand::CreateReg(AddrReg)); 00098 MaskInst.addOperand(MCOperand::CreateReg(AddrReg)); 00099 MaskInst.addOperand(MCOperand::CreateReg(MaskReg)); 00100 MipsELFStreamer::EmitInstruction(MaskInst, STI); 00101 } 00102 00103 // Sandbox indirect branch or return instruction by inserting mask operation 00104 // before it. 00105 void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) { 00106 unsigned AddrReg = MI.getOperand(0).getReg(); 00107 00108 EmitBundleLock(false); 00109 emitMask(AddrReg, IndirectBranchMaskReg, STI); 00110 MipsELFStreamer::EmitInstruction(MI, STI); 00111 EmitBundleUnlock(); 00112 } 00113 00114 // Sandbox memory access or SP change. Insert mask operation before and/or 00115 // after the instruction. 00116 void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx, 00117 const MCSubtargetInfo &STI, bool MaskBefore, 00118 bool MaskAfter) { 00119 EmitBundleLock(false); 00120 if (MaskBefore) { 00121 // Sandbox memory access. 00122 unsigned BaseReg = MI.getOperand(AddrIdx).getReg(); 00123 emitMask(BaseReg, LoadStoreStackMaskReg, STI); 00124 } 00125 MipsELFStreamer::EmitInstruction(MI, STI); 00126 if (MaskAfter) { 00127 // Sandbox SP change. 00128 unsigned SPReg = MI.getOperand(0).getReg(); 00129 assert((Mips::SP == SPReg) && "Unexpected stack-pointer register."); 00130 emitMask(SPReg, LoadStoreStackMaskReg, STI); 00131 } 00132 EmitBundleUnlock(); 00133 } 00134 00135 public: 00136 /// This function is the one used to emit instruction data into the ELF 00137 /// streamer. We override it to mask dangerous instructions. 00138 void EmitInstruction(const MCInst &Inst, 00139 const MCSubtargetInfo &STI) override { 00140 // Sandbox indirect jumps. 00141 if (isIndirectJump(Inst)) { 00142 if (PendingCall) 00143 report_fatal_error("Dangerous instruction in branch delay slot!"); 00144 sandboxIndirectJump(Inst, STI); 00145 return; 00146 } 00147 00148 // Sandbox loads, stores and SP changes. 00149 unsigned AddrIdx; 00150 bool IsStore; 00151 bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx, 00152 &IsStore); 00153 bool IsSPFirstOperand = isStackPointerFirstOperand(Inst); 00154 if (IsMemAccess || IsSPFirstOperand) { 00155 bool MaskBefore = (IsMemAccess 00156 && baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx) 00157 .getReg())); 00158 bool MaskAfter = IsSPFirstOperand && !IsStore; 00159 if (MaskBefore || MaskAfter) { 00160 if (PendingCall) 00161 report_fatal_error("Dangerous instruction in branch delay slot!"); 00162 sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter); 00163 return; 00164 } 00165 // fallthrough 00166 } 00167 00168 // Sandbox calls by aligning call and branch delay to the bundle end. 00169 // For indirect calls, emit the mask before the call. 00170 bool IsIndirectCall; 00171 if (isCall(Inst, &IsIndirectCall)) { 00172 if (PendingCall) 00173 report_fatal_error("Dangerous instruction in branch delay slot!"); 00174 00175 // Start the sandboxing sequence by emitting call. 00176 EmitBundleLock(true); 00177 if (IsIndirectCall) { 00178 unsigned TargetReg = Inst.getOperand(1).getReg(); 00179 emitMask(TargetReg, IndirectBranchMaskReg, STI); 00180 } 00181 MipsELFStreamer::EmitInstruction(Inst, STI); 00182 PendingCall = true; 00183 return; 00184 } 00185 if (PendingCall) { 00186 // Finish the sandboxing sequence by emitting branch delay. 00187 MipsELFStreamer::EmitInstruction(Inst, STI); 00188 EmitBundleUnlock(); 00189 PendingCall = false; 00190 return; 00191 } 00192 00193 // None of the sandboxing applies, just emit the instruction. 00194 MipsELFStreamer::EmitInstruction(Inst, STI); 00195 } 00196 }; 00197 00198 } // end anonymous namespace 00199 00200 namespace llvm { 00201 00202 bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx, 00203 bool *IsStore) { 00204 if (IsStore) 00205 *IsStore = false; 00206 00207 switch (Opcode) { 00208 default: 00209 return false; 00210 00211 // Load instructions with base address register in position 1. 00212 case Mips::LB: 00213 case Mips::LBu: 00214 case Mips::LH: 00215 case Mips::LHu: 00216 case Mips::LW: 00217 case Mips::LWC1: 00218 case Mips::LDC1: 00219 case Mips::LL: 00220 case Mips::LL_R6: 00221 case Mips::LWL: 00222 case Mips::LWR: 00223 *AddrIdx = 1; 00224 return true; 00225 00226 // Store instructions with base address register in position 1. 00227 case Mips::SB: 00228 case Mips::SH: 00229 case Mips::SW: 00230 case Mips::SWC1: 00231 case Mips::SDC1: 00232 case Mips::SWL: 00233 case Mips::SWR: 00234 *AddrIdx = 1; 00235 if (IsStore) 00236 *IsStore = true; 00237 return true; 00238 00239 // Store instructions with base address register in position 2. 00240 case Mips::SC: 00241 case Mips::SC_R6: 00242 *AddrIdx = 2; 00243 if (IsStore) 00244 *IsStore = true; 00245 return true; 00246 } 00247 } 00248 00249 bool baseRegNeedsLoadStoreMask(unsigned Reg) { 00250 // The contents of SP and thread pointer register do not require masking. 00251 return Reg != Mips::SP && Reg != Mips::T8; 00252 } 00253 00254 MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, 00255 raw_ostream &OS, 00256 MCCodeEmitter *Emitter, 00257 const MCSubtargetInfo &STI, 00258 bool RelaxAll, bool NoExecStack) { 00259 MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter, 00260 STI); 00261 if (RelaxAll) 00262 S->getAssembler().setRelaxAll(true); 00263 if (NoExecStack) 00264 S->getAssembler().setNoExecStack(true); 00265 00266 // Set bundle-alignment as required by the NaCl ABI for the target. 00267 S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN); 00268 00269 return S; 00270 } 00271 00272 }