summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
diff options
context:
space:
mode:
authorSasa Stankovic <Sasa.Stankovic@imgtec.com>2014-03-10 20:34:23 +0000
committerSasa Stankovic <Sasa.Stankovic@imgtec.com>2014-03-10 20:34:23 +0000
commit5fddf61089761b984b0a2591281a2217a686c4d3 (patch)
treef364f1fb81913ff9111309da56e61543a6694e61 /llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
parente78ae059b54cb514a48db05c16af75d97794e4e5 (diff)
downloadbcm5719-llvm-5fddf61089761b984b0a2591281a2217a686c4d3.tar.gz
bcm5719-llvm-5fddf61089761b984b0a2591281a2217a686c4d3.zip
[mips] Implement NaCl sandboxing of loads, stores and SP changes:
* Add masking instructions before loads and stores (in MC layer). * Add masking instructions after SP changes (in MC layer). * Forbid loads, stores and SP changes in delay slots (in MI layer). Differential Revision: http://llvm-reviews.chandlerc.com/D2904 llvm-svn: 203484
Diffstat (limited to 'llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp')
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp111
1 files changed, 106 insertions, 5 deletions
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
index a442e5b31bb..3353cfef33c 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
@@ -9,8 +9,10 @@
//
// This file implements MCELFStreamer for Mips NaCl. It emits .o object files
// as required by NaCl's SFI sandbox. It inserts address-masking instructions
-// before dangerous control-flow instructions. It aligns on bundle size all
-// functions and all targets of indirect branches.
+// before dangerous control-flow and memory access instructions. It inserts
+// address-masking instructions after instructions that change the stack
+// pointer. It ensures that the mask and the dangerous instruction are always
+// emitted in the same bundle.
//
//===----------------------------------------------------------------------===//
@@ -25,6 +27,7 @@ using namespace llvm;
namespace {
const unsigned IndirectBranchMaskReg = Mips::T6;
+const unsigned LoadStoreStackMaskReg = Mips::T7;
/// Extend the generic MCELFStreamer class so that it can mask dangerous
/// instructions.
@@ -42,6 +45,11 @@ private:
return MI.getOpcode() == Mips::JR || MI.getOpcode() == Mips::RET;
}
+ bool isStackPointerFirstOperand(const MCInst &MI) {
+ return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg()
+ && MI.getOperand(0).getReg() == Mips::SP);
+ }
+
void emitMask(unsigned AddrReg, unsigned MaskReg,
const MCSubtargetInfo &STI) {
MCInst MaskInst;
@@ -63,14 +71,57 @@ private:
EmitBundleUnlock();
}
+ // Sandbox memory access or SP change. Insert mask operation before and/or
+ // after the instruction.
+ void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx,
+ const MCSubtargetInfo &STI, bool MaskBefore,
+ bool MaskAfter) {
+ EmitBundleLock(false);
+ if (MaskBefore) {
+ // Sandbox memory access.
+ unsigned BaseReg = MI.getOperand(AddrIdx).getReg();
+ emitMask(BaseReg, LoadStoreStackMaskReg, STI);
+ }
+ MCELFStreamer::EmitInstruction(MI, STI);
+ if (MaskAfter) {
+ // Sandbox SP change.
+ unsigned SPReg = MI.getOperand(0).getReg();
+ assert((Mips::SP == SPReg) && "Unexpected stack-pointer register.");
+ emitMask(SPReg, LoadStoreStackMaskReg, STI);
+ }
+ EmitBundleUnlock();
+ }
+
public:
/// This function is the one used to emit instruction data into the ELF
/// streamer. We override it to mask dangerous instructions.
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) {
- if (isIndirectJump(Inst))
+ // Sandbox indirect jumps.
+ if (isIndirectJump(Inst)) {
sandboxIndirectJump(Inst, STI);
- else
- MCELFStreamer::EmitInstruction(Inst, STI);
+ return;
+ }
+
+ // Sandbox loads, stores and SP changes.
+ unsigned AddrIdx;
+ bool IsStore;
+ bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx,
+ &IsStore);
+ bool IsSPFirstOperand = isStackPointerFirstOperand(Inst);
+ if (IsMemAccess || IsSPFirstOperand) {
+ bool MaskBefore = (IsMemAccess
+ && baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx)
+ .getReg()));
+ bool MaskAfter = IsSPFirstOperand && !IsStore;
+ if (MaskBefore || MaskAfter)
+ sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter);
+ else
+ MCELFStreamer::EmitInstruction(Inst, STI);
+ return;
+ }
+
+ // None of the sandboxing applies, just emit the instruction.
+ MCELFStreamer::EmitInstruction(Inst, STI);
}
};
@@ -78,6 +129,56 @@ public:
namespace llvm {
+bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
+ bool *IsStore) {
+ if (IsStore)
+ *IsStore = false;
+
+ switch (Opcode) {
+ default:
+ return false;
+
+ // Load instructions with base address register in position 1.
+ case Mips::LB:
+ case Mips::LBu:
+ case Mips::LH:
+ case Mips::LHu:
+ case Mips::LW:
+ case Mips::LWC1:
+ case Mips::LDC1:
+ case Mips::LL:
+ case Mips::LWL:
+ case Mips::LWR:
+ *AddrIdx = 1;
+ return true;
+
+ // Store instructions with base address register in position 1.
+ case Mips::SB:
+ case Mips::SH:
+ case Mips::SW:
+ case Mips::SWC1:
+ case Mips::SDC1:
+ case Mips::SWL:
+ case Mips::SWR:
+ *AddrIdx = 1;
+ if (IsStore)
+ *IsStore = true;
+ return true;
+
+ // Store instructions with base address register in position 2.
+ case Mips::SC:
+ *AddrIdx = 2;
+ if (IsStore)
+ *IsStore = true;
+ return true;
+ }
+}
+
+bool baseRegNeedsLoadStoreMask(unsigned Reg) {
+ // The contents of SP and thread pointer register do not require masking.
+ return Reg != Mips::SP && Reg != Mips::T8;
+}
+
MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_ostream &OS,
MCCodeEmitter *Emitter, bool RelaxAll,
OpenPOWER on IntegriCloud