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 instructions. It aligns on bundle size all
13 // functions and all targets of indirect branches.
15 //===----------------------------------------------------------------------===//
17 #define DEBUG_TYPE "mips-mc-nacl"
20 #include "MipsMCNaCl.h"
21 #include "llvm/MC/MCELFStreamer.h"
27 const unsigned IndirectBranchMaskReg = Mips::T6;
29 /// Extend the generic MCELFStreamer class so that it can mask dangerous
32 class MipsNaClELFStreamer : public MCELFStreamer {
34 MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
35 MCCodeEmitter *Emitter)
36 : MCELFStreamer(Context, TAB, OS, Emitter) {}
38 ~MipsNaClELFStreamer() {}
41 bool isIndirectJump(const MCInst &MI) {
42 return MI.getOpcode() == Mips::JR || MI.getOpcode() == Mips::RET;
45 void emitMask(unsigned AddrReg, unsigned MaskReg,
46 const MCSubtargetInfo &STI) {
48 MaskInst.setOpcode(Mips::AND);
49 MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
50 MaskInst.addOperand(MCOperand::CreateReg(AddrReg));
51 MaskInst.addOperand(MCOperand::CreateReg(MaskReg));
52 MCELFStreamer::EmitInstruction(MaskInst, STI);
55 // Sandbox indirect branch or return instruction by inserting mask operation
57 void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) {
58 unsigned AddrReg = MI.getOperand(0).getReg();
60 EmitBundleLock(false);
61 emitMask(AddrReg, IndirectBranchMaskReg, STI);
62 MCELFStreamer::EmitInstruction(MI, STI);
67 /// This function is the one used to emit instruction data into the ELF
68 /// streamer. We override it to mask dangerous instructions.
69 virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) {
70 if (isIndirectJump(Inst))
71 sandboxIndirectJump(Inst, STI);
73 MCELFStreamer::EmitInstruction(Inst, STI);
77 } // end anonymous namespace
81 MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
83 MCCodeEmitter *Emitter, bool RelaxAll,
85 MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter);
87 S->getAssembler().setRelaxAll(true);
89 S->getAssembler().setNoExecStack(true);
91 // Set bundle-alignment as required by the NaCl ABI for the target.
92 S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN);