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