1 //===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements MCELFStreamer for Mips NaCl. It emits .o object files
11 // as required by NaCl's SFI sandbox. It inserts address-masking instructions
12 // before dangerous control-flow and memory access instructions. It inserts
13 // address-masking instructions after instructions that change the stack
14 // pointer. It ensures that the mask and the dangerous instruction are always
15 // emitted in the same bundle.
17 //===----------------------------------------------------------------------===//
19 #define DEBUG_TYPE "mips-mc-nacl"
22 #include "MipsMCNaCl.h"
23 #include "llvm/MC/MCELFStreamer.h"
29 const unsigned IndirectBranchMaskReg = Mips::T6;
30 const unsigned LoadStoreStackMaskReg = Mips::T7;
32 /// Extend the generic MCELFStreamer class so that it can mask dangerous
35 class MipsNaClELFStreamer : public MCELFStreamer {
37 MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
38 MCCodeEmitter *Emitter)
39 : MCELFStreamer(Context, TAB, OS, Emitter) {}
41 ~MipsNaClELFStreamer() {}
44 bool isIndirectJump(const MCInst &MI) {
45 return MI.getOpcode() == Mips::JR || MI.getOpcode() == Mips::RET;
48 bool isStackPointerFirstOperand(const MCInst &MI) {
49 return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg()
50 && MI.getOperand(0).getReg() == Mips::SP);
53 void emitMask(unsigned AddrReg, unsigned MaskReg,
54 const MCSubtargetInfo &STI) {
56 MaskInst.setOpcode(Mips::AND);
57 MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
58 MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
59 MaskInst.addOperand(MCOperand::CreateReg(MaskReg));
60 MCELFStreamer::EmitInstruction(MaskInst, STI);
63 // Sandbox indirect branch or return instruction by inserting mask operation
65 void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) {
66 unsigned AddrReg = MI.getOperand(0).getReg();
68 EmitBundleLock(false);
69 emitMask(AddrReg, IndirectBranchMaskReg, STI);
70 MCELFStreamer::EmitInstruction(MI, STI);
74 // Sandbox memory access or SP change. Insert mask operation before and/or
75 // after the instruction.
76 void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx,
77 const MCSubtargetInfo &STI, bool MaskBefore,
79 EmitBundleLock(false);
81 // Sandbox memory access.
82 unsigned BaseReg = MI.getOperand(AddrIdx).getReg();
83 emitMask(BaseReg, LoadStoreStackMaskReg, STI);
85 MCELFStreamer::EmitInstruction(MI, STI);
88 unsigned SPReg = MI.getOperand(0).getReg();
89 assert((Mips::SP == SPReg) && "Unexpected stack-pointer register.");
90 emitMask(SPReg, LoadStoreStackMaskReg, STI);
96 /// This function is the one used to emit instruction data into the ELF
97 /// streamer. We override it to mask dangerous instructions.
98 virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) {
99 // Sandbox indirect jumps.
100 if (isIndirectJump(Inst)) {
101 sandboxIndirectJump(Inst, STI);
105 // Sandbox loads, stores and SP changes.
108 bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx,
110 bool IsSPFirstOperand = isStackPointerFirstOperand(Inst);
111 if (IsMemAccess || IsSPFirstOperand) {
112 bool MaskBefore = (IsMemAccess
113 && baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx)
115 bool MaskAfter = IsSPFirstOperand && !IsStore;
116 if (MaskBefore || MaskAfter)
117 sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter);
119 MCELFStreamer::EmitInstruction(Inst, STI);
123 // None of the sandboxing applies, just emit the instruction.
124 MCELFStreamer::EmitInstruction(Inst, STI);
128 } // end anonymous namespace
132 bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
141 // Load instructions with base address register in position 1.
155 // Store instructions with base address register in position 1.
168 // Store instructions with base address register in position 2.
177 bool baseRegNeedsLoadStoreMask(unsigned Reg) {
178 // The contents of SP and thread pointer register do not require masking.
179 return Reg != Mips::SP && Reg != Mips::T8;
182 MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
184 MCCodeEmitter *Emitter, bool RelaxAll,
186 MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter);
188 S->getAssembler().setRelaxAll(true);
190 S->getAssembler().setNoExecStack(true);
192 // Set bundle-alignment as required by the NaCl ABI for the target.
193 S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN);