1 //===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===//
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 // 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.  It aligns call + branch delay to the bundle end,
16 // so that return address is always aligned to the start of next bundle.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "Mips.h"
21 #include "MipsELFStreamer.h"
22 #include "MipsMCNaCl.h"
23 #include "llvm/MC/MCAssembler.h"
24 #include "llvm/MC/MCELFStreamer.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include <cassert>
28 
29 using namespace llvm;
30 
31 #define DEBUG_TYPE "mips-mc-nacl"
32 
33 namespace {
34 
35 const unsigned IndirectBranchMaskReg = Mips::T6;
36 const unsigned LoadStoreStackMaskReg = Mips::T7;
37 
38 /// Extend the generic MCELFStreamer class so that it can mask dangerous
39 /// instructions.
40 
41 class MipsNaClELFStreamer : public MipsELFStreamer {
42 public:
43   MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
44                       raw_pwrite_stream &OS, MCCodeEmitter *Emitter)
45       : MipsELFStreamer(Context, TAB, OS, Emitter) {}
46 
47   ~MipsNaClELFStreamer() override = default;
48 
49 private:
50   // Whether we started the sandboxing sequence for calls.  Calls are bundled
51   // with branch delays and aligned to the bundle end.
52   bool PendingCall = false;
53 
54   bool isIndirectJump(const MCInst &MI) {
55     if (MI.getOpcode() == Mips::JALR) {
56       // MIPS32r6/MIPS64r6 doesn't have a JR instruction and uses JALR instead.
57       // JALR is an indirect branch if the link register is $0.
58       assert(MI.getOperand(0).isReg());
59       return MI.getOperand(0).getReg() == Mips::ZERO;
60     }
61     return MI.getOpcode() == Mips::JR;
62   }
63 
64   bool isStackPointerFirstOperand(const MCInst &MI) {
65     return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg()
66             && MI.getOperand(0).getReg() == Mips::SP);
67   }
68 
69   bool isCall(const MCInst &MI, bool *IsIndirectCall) {
70     unsigned Opcode = MI.getOpcode();
71 
72     *IsIndirectCall = false;
73 
74     switch (Opcode) {
75     default:
76       return false;
77 
78     case Mips::JAL:
79     case Mips::BAL:
80     case Mips::BAL_BR:
81     case Mips::BLTZAL:
82     case Mips::BGEZAL:
83       return true;
84 
85     case Mips::JALR:
86       // JALR is only a call if the link register is not $0. Otherwise it's an
87       // indirect branch.
88       assert(MI.getOperand(0).isReg());
89       if (MI.getOperand(0).getReg() == Mips::ZERO)
90         return false;
91 
92       *IsIndirectCall = true;
93       return true;
94     }
95   }
96 
97   void emitMask(unsigned AddrReg, unsigned MaskReg,
98                 const MCSubtargetInfo &STI) {
99     MCInst MaskInst;
100     MaskInst.setOpcode(Mips::AND);
101     MaskInst.addOperand(MCOperand::createReg(AddrReg));
102     MaskInst.addOperand(MCOperand::createReg(AddrReg));
103     MaskInst.addOperand(MCOperand::createReg(MaskReg));
104     MipsELFStreamer::EmitInstruction(MaskInst, STI);
105   }
106 
107   // Sandbox indirect branch or return instruction by inserting mask operation
108   // before it.
109   void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) {
110     unsigned AddrReg = MI.getOperand(0).getReg();
111 
112     EmitBundleLock(false);
113     emitMask(AddrReg, IndirectBranchMaskReg, STI);
114     MipsELFStreamer::EmitInstruction(MI, STI);
115     EmitBundleUnlock();
116   }
117 
118   // Sandbox memory access or SP change.  Insert mask operation before and/or
119   // after the instruction.
120   void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx,
121                                    const MCSubtargetInfo &STI, bool MaskBefore,
122                                    bool MaskAfter) {
123     EmitBundleLock(false);
124     if (MaskBefore) {
125       // Sandbox memory access.
126       unsigned BaseReg = MI.getOperand(AddrIdx).getReg();
127       emitMask(BaseReg, LoadStoreStackMaskReg, STI);
128     }
129     MipsELFStreamer::EmitInstruction(MI, STI);
130     if (MaskAfter) {
131       // Sandbox SP change.
132       unsigned SPReg = MI.getOperand(0).getReg();
133       assert((Mips::SP == SPReg) && "Unexpected stack-pointer register.");
134       emitMask(SPReg, LoadStoreStackMaskReg, STI);
135     }
136     EmitBundleUnlock();
137   }
138 
139 public:
140   /// This function is the one used to emit instruction data into the ELF
141   /// streamer.  We override it to mask dangerous instructions.
142   void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
143                        bool) override {
144     // Sandbox indirect jumps.
145     if (isIndirectJump(Inst)) {
146       if (PendingCall)
147         report_fatal_error("Dangerous instruction in branch delay slot!");
148       sandboxIndirectJump(Inst, STI);
149       return;
150     }
151 
152     // Sandbox loads, stores and SP changes.
153     unsigned AddrIdx;
154     bool IsStore;
155     bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx,
156                                                     &IsStore);
157     bool IsSPFirstOperand = isStackPointerFirstOperand(Inst);
158     if (IsMemAccess || IsSPFirstOperand) {
159       bool MaskBefore = (IsMemAccess
160                          && baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx)
161                                                           .getReg()));
162       bool MaskAfter = IsSPFirstOperand && !IsStore;
163       if (MaskBefore || MaskAfter) {
164         if (PendingCall)
165           report_fatal_error("Dangerous instruction in branch delay slot!");
166         sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter);
167         return;
168       }
169       // fallthrough
170     }
171 
172     // Sandbox calls by aligning call and branch delay to the bundle end.
173     // For indirect calls, emit the mask before the call.
174     bool IsIndirectCall;
175     if (isCall(Inst, &IsIndirectCall)) {
176       if (PendingCall)
177         report_fatal_error("Dangerous instruction in branch delay slot!");
178 
179       // Start the sandboxing sequence by emitting call.
180       EmitBundleLock(true);
181       if (IsIndirectCall) {
182         unsigned TargetReg = Inst.getOperand(1).getReg();
183         emitMask(TargetReg, IndirectBranchMaskReg, STI);
184       }
185       MipsELFStreamer::EmitInstruction(Inst, STI);
186       PendingCall = true;
187       return;
188     }
189     if (PendingCall) {
190       // Finish the sandboxing sequence by emitting branch delay.
191       MipsELFStreamer::EmitInstruction(Inst, STI);
192       EmitBundleUnlock();
193       PendingCall = false;
194       return;
195     }
196 
197     // None of the sandboxing applies, just emit the instruction.
198     MipsELFStreamer::EmitInstruction(Inst, STI);
199   }
200 };
201 
202 } // end anonymous namespace
203 
204 namespace llvm {
205 
206 bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
207                                   bool *IsStore) {
208   if (IsStore)
209     *IsStore = false;
210 
211   switch (Opcode) {
212   default:
213     return false;
214 
215   // Load instructions with base address register in position 1.
216   case Mips::LB:
217   case Mips::LBu:
218   case Mips::LH:
219   case Mips::LHu:
220   case Mips::LW:
221   case Mips::LWC1:
222   case Mips::LDC1:
223   case Mips::LL:
224   case Mips::LL_R6:
225   case Mips::LWL:
226   case Mips::LWR:
227     *AddrIdx = 1;
228     return true;
229 
230   // Store instructions with base address register in position 1.
231   case Mips::SB:
232   case Mips::SH:
233   case Mips::SW:
234   case Mips::SWC1:
235   case Mips::SDC1:
236   case Mips::SWL:
237   case Mips::SWR:
238     *AddrIdx = 1;
239     if (IsStore)
240       *IsStore = true;
241     return true;
242 
243   // Store instructions with base address register in position 2.
244   case Mips::SC:
245   case Mips::SC_R6:
246     *AddrIdx = 2;
247     if (IsStore)
248       *IsStore = true;
249     return true;
250   }
251 }
252 
253 bool baseRegNeedsLoadStoreMask(unsigned Reg) {
254   // The contents of SP and thread pointer register do not require masking.
255   return Reg != Mips::SP && Reg != Mips::T8;
256 }
257 
258 MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
259                                          raw_pwrite_stream &OS,
260                                          MCCodeEmitter *Emitter,
261                                          bool RelaxAll) {
262   MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter);
263   if (RelaxAll)
264     S->getAssembler().setRelaxAll(true);
265 
266   // Set bundle-alignment as required by the NaCl ABI for the target.
267   S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN);
268 
269   return S;
270 }
271 
272 } // end namespace llvm
273