9
9
//
10
10
// This file implements MCELFStreamer for Mips NaCl. It emits .o object files
11
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.
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.
14
16
//
15
17
// ===----------------------------------------------------------------------===//
16
18
@@ -25,6 +27,7 @@ using namespace llvm;
25
27
namespace {
26
28
27
29
const unsigned IndirectBranchMaskReg = Mips::T6;
30
+ const unsigned LoadStoreStackMaskReg = Mips::T7;
28
31
29
32
// / Extend the generic MCELFStreamer class so that it can mask dangerous
30
33
// / instructions.
@@ -42,6 +45,11 @@ class MipsNaClELFStreamer : public MCELFStreamer {
42
45
return MI.getOpcode () == Mips::JR || MI.getOpcode () == Mips::RET;
43
46
}
44
47
48
+ bool isStackPointerFirstOperand (const MCInst &MI) {
49
+ return (MI.getNumOperands () > 0 && MI.getOperand (0 ).isReg ()
50
+ && MI.getOperand (0 ).getReg () == Mips::SP);
51
+ }
52
+
45
53
void emitMask (unsigned AddrReg, unsigned MaskReg,
46
54
const MCSubtargetInfo &STI) {
47
55
MCInst MaskInst;
@@ -63,21 +71,114 @@ class MipsNaClELFStreamer : public MCELFStreamer {
63
71
EmitBundleUnlock ();
64
72
}
65
73
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,
78
+ bool MaskAfter) {
79
+ EmitBundleLock (false );
80
+ if (MaskBefore) {
81
+ // Sandbox memory access.
82
+ unsigned BaseReg = MI.getOperand (AddrIdx).getReg ();
83
+ emitMask (BaseReg, LoadStoreStackMaskReg, STI);
84
+ }
85
+ MCELFStreamer::EmitInstruction (MI, STI);
86
+ if (MaskAfter) {
87
+ // Sandbox SP change.
88
+ unsigned SPReg = MI.getOperand (0 ).getReg ();
89
+ assert ((Mips::SP == SPReg) && " Unexpected stack-pointer register." );
90
+ emitMask (SPReg, LoadStoreStackMaskReg, STI);
91
+ }
92
+ EmitBundleUnlock ();
93
+ }
94
+
66
95
public:
67
96
// / This function is the one used to emit instruction data into the ELF
68
97
// / streamer. We override it to mask dangerous instructions.
69
98
virtual void EmitInstruction (const MCInst &Inst, const MCSubtargetInfo &STI) {
70
- if (isIndirectJump (Inst))
99
+ // Sandbox indirect jumps.
100
+ if (isIndirectJump (Inst)) {
71
101
sandboxIndirectJump (Inst, STI);
72
- else
73
- MCELFStreamer::EmitInstruction (Inst, STI);
102
+ return ;
103
+ }
104
+
105
+ // Sandbox loads, stores and SP changes.
106
+ unsigned AddrIdx;
107
+ bool IsStore;
108
+ bool IsMemAccess = isBasePlusOffsetMemoryAccess (Inst.getOpcode (), &AddrIdx,
109
+ &IsStore);
110
+ bool IsSPFirstOperand = isStackPointerFirstOperand (Inst);
111
+ if (IsMemAccess || IsSPFirstOperand) {
112
+ bool MaskBefore = (IsMemAccess
113
+ && baseRegNeedsLoadStoreMask (Inst.getOperand (AddrIdx)
114
+ .getReg ()));
115
+ bool MaskAfter = IsSPFirstOperand && !IsStore;
116
+ if (MaskBefore || MaskAfter)
117
+ sandboxLoadStoreStackChange (Inst, AddrIdx, STI, MaskBefore, MaskAfter);
118
+ else
119
+ MCELFStreamer::EmitInstruction (Inst, STI);
120
+ return ;
121
+ }
122
+
123
+ // None of the sandboxing applies, just emit the instruction.
124
+ MCELFStreamer::EmitInstruction (Inst, STI);
74
125
}
75
126
};
76
127
77
128
} // end anonymous namespace
78
129
79
130
namespace llvm {
80
131
132
+ bool isBasePlusOffsetMemoryAccess (unsigned Opcode, unsigned *AddrIdx,
133
+ bool *IsStore) {
134
+ if (IsStore)
135
+ *IsStore = false ;
136
+
137
+ switch (Opcode) {
138
+ default :
139
+ return false ;
140
+
141
+ // Load instructions with base address register in position 1.
142
+ case Mips::LB:
143
+ case Mips::LBu:
144
+ case Mips::LH:
145
+ case Mips::LHu:
146
+ case Mips::LW:
147
+ case Mips::LWC1:
148
+ case Mips::LDC1:
149
+ case Mips::LL:
150
+ case Mips::LWL:
151
+ case Mips::LWR:
152
+ *AddrIdx = 1 ;
153
+ return true ;
154
+
155
+ // Store instructions with base address register in position 1.
156
+ case Mips::SB:
157
+ case Mips::SH:
158
+ case Mips::SW:
159
+ case Mips::SWC1:
160
+ case Mips::SDC1:
161
+ case Mips::SWL:
162
+ case Mips::SWR:
163
+ *AddrIdx = 1 ;
164
+ if (IsStore)
165
+ *IsStore = true ;
166
+ return true ;
167
+
168
+ // Store instructions with base address register in position 2.
169
+ case Mips::SC:
170
+ *AddrIdx = 2 ;
171
+ if (IsStore)
172
+ *IsStore = true ;
173
+ return true ;
174
+ }
175
+ }
176
+
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;
180
+ }
181
+
81
182
MCELFStreamer *createMipsNaClELFStreamer (MCContext &Context, MCAsmBackend &TAB,
82
183
raw_ostream &OS,
83
184
MCCodeEmitter *Emitter, bool RelaxAll,
0 commit comments