Chromium Code Reviews| Index: src/IceTargetLoweringX8632.cpp |
| diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp |
| index ebc0bae319fc44d9d509e67999f088e905586076..3d533d21eae9a90c8458e26596e59d964136dcd9 100644 |
| --- a/src/IceTargetLoweringX8632.cpp |
| +++ b/src/IceTargetLoweringX8632.cpp |
| @@ -128,6 +128,8 @@ const uint32_t X86_CHAR_BIT = 8; |
| const uint32_t X86_STACK_ALIGNMENT_BYTES = 16; |
| // Size of the return address on the stack |
| const uint32_t X86_RET_IP_SIZE_BYTES = 4; |
| +// Randomize integer immediates at least 2 bytes in size. |
| +const uint64_t X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD = 65536; |
|
JF
2014/08/12 05:37:47
I find 0xFFFF more readable.
wala
2014/08/16 00:07:13
Done.
|
| // Value is a size in bytes. Return Value adjusted to the next highest |
| // multiple of the stack alignment. |
| @@ -137,6 +139,31 @@ uint32_t applyStackAlignment(uint32_t Value) { |
| return (Value + X86_STACK_ALIGNMENT_BYTES - 1) & -X86_STACK_ALIGNMENT_BYTES; |
| } |
| +bool immediateShouldBeRandomized(Operand *Immediate) { |
| + if (!Immediate) { |
| + return false; |
| + } else if (llvm::isa<ConstantRelocatable>(Immediate)) { |
|
Jim Stichnoth
2014/08/13 23:30:25
Remove "else" after "return".
wala
2014/08/16 00:07:12
Done.
|
| + return true; |
| + } else if (ConstantInteger *ConstInt = |
| + llvm::dyn_cast<ConstantInteger>(Immediate)) { |
| + return ConstInt->getType() != IceType_i64 && |
|
JF
2014/08/12 05:37:47
Why not i64?
Jim Stichnoth
2014/08/13 23:30:25
i64 constants are split into i32 operations at thi
wala
2014/08/16 00:07:13
Done.
wala
2014/08/16 00:16:15
Hmm, it looks like some i64 "immediates" are reach
|
| + ConstInt->getValue() >= X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD; |
|
Jim Stichnoth
2014/08/13 23:30:25
As we discussed offline, you probably want to add
|
| + } else { |
| + return false; |
|
JF
2014/08/12 05:37:47
What about FP and vectors?
Jim Stichnoth
2014/08/13 23:30:26
FP and vector constants are always pooled, due to
|
| + } |
| +} |
| + |
| +// This gives a name to the immediate so it can be identified as a |
| +// constant pool entry. |
| +IceString nameImmediate(Constant *Immediate) { |
| + bool IsRelocatable = llvm::isa<ConstantRelocatable>(Immediate); |
| + IceString Name; |
| + llvm::raw_string_ostream NameBuf(Name); |
| + NameBuf << (IsRelocatable ? "L$__reloc" : "L$") << Immediate->getType() |
| + << "$" << Immediate->getPoolEntryID(); |
| + return NameBuf.str(); |
| +} |
| + |
| // Instruction set options |
| namespace cl = ::llvm::cl; |
| cl::opt<TargetX8632::X86InstructionSet> CLInstructionSet( |
| @@ -148,6 +175,23 @@ cl::opt<TargetX8632::X86InstructionSet> CLInstructionSet( |
| clEnumValN(TargetX8632::SSE4_1, "sse4.1", |
| "Enable SSE 4.1 instructions"), clEnumValEnd)); |
| +enum RandomizeImmediates { |
| + Randomize_None, |
| + Randomize_ConstantBlinding, |
| + Randomize_ConstantPooling |
| +}; |
| + |
| +cl::opt<RandomizeImmediates> CLRandomizeImmediates( |
| + "randomize-immediates", |
| + cl::desc("Randomize the representation of immediates"), |
| + cl::init(Randomize_None), |
| + cl::values(clEnumValN(Randomize_None, "none", "Don't randomize (default)"), |
| + clEnumValN(Randomize_ConstantBlinding, "constant-blinding", |
| + "Use constant blinding"), |
| + clEnumValN(Randomize_ConstantPooling, "constant-pooling", |
| + "Use constant pooling"), |
| + clEnumValEnd)); |
|
JF
2014/08/12 05:37:47
Those should probably be composable.
Jim Stichnoth
2014/08/13 23:30:26
I didn't think it would add any more security to b
|
| + |
| // Return a string representation of the type that is suitable for use |
| // in an identifier. |
| IceString typeIdentString(const Type Ty) { |
| @@ -859,9 +903,41 @@ template <typename T> void TargetX8632::emitConstantPool() const { |
| } |
| } |
| +void TargetX8632::emitPooledImmediates() const { |
|
JF
2014/08/12 05:37:47
Are redundant pooled immediates pooled at the same
wala
2014/08/16 00:07:12
Right now, the implementation uses the Subzero con
|
| + Ostream &Str = Ctx->getStrEmit(); |
| + SizeT Align = typeWidthInBytesOnStack(IceType_i32); |
| + // TODO: Determine the right directives to place here. |
| + Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align |
| + << "\n"; |
| + Str << "\t.align\t" << Align << "\n"; |
| + ConstantList PooledImmediates = Ctx->getImmediatePool(); |
| + for (ConstantList::const_iterator I = PooledImmediates.begin(), |
| + E = PooledImmediates.end(); I != E; ++I) { |
| + Constant *Value = *I; |
| + IceString Name = nameImmediate(Value); |
| + Str << Name << ":\n"; |
| + if (ConstantInteger *Int = llvm::dyn_cast<ConstantInteger>(Value)) { |
| + assert(Int->getType() == IceType_i32); |
| + char buf[30]; |
| + int CharsPrinted = |
| + snprintf(buf, llvm::array_lengthof(buf), "0x%x", |
| + (uint32_t) Int->getValue()); |
| + assert(CharsPrinted >= 0 && |
| + (size_t)CharsPrinted < llvm::array_lengthof(buf)); |
| + Str << "\t.long\t" << buf << "\n"; |
| + } else if (ConstantRelocatable *Reloc = |
| + llvm::dyn_cast<ConstantRelocatable>(Value)) { |
| + Str << "\t.long\t"; |
| + Reloc->emit(Ctx); |
| + Str << "\n"; |
| + } |
| + } |
| +} |
| + |
| void TargetX8632::emitConstants() const { |
| emitConstantPool<PoolTypeConverter<float> >(); |
| emitConstantPool<PoolTypeConverter<double> >(); |
| + emitPooledImmediates(); |
| // No need to emit constants from the int pool since (for x86) they |
| // are embedded as immediates in the instructions. |
| @@ -3721,8 +3797,9 @@ void TargetX8632::lowerSelect(const InstSelect *Inst) { |
| _mov(DestLo, SrcLoRI); |
| _mov(DestHi, SrcHiRI); |
| } else { |
| - _cmp(ConditionRMI, Zero); |
| + // Call legalize() before _cmp, since legalize() may modify flags. |
| SrcT = legalize(SrcT, Legal_Reg | Legal_Imm, true); |
| + _cmp(ConditionRMI, Zero); |
| _mov(Dest, SrcT); |
| _br(InstX8632Br::Br_ne, Label); |
| Context.insert(InstFakeUse::create(Func, Dest)); |
| @@ -3940,6 +4017,45 @@ Variable *TargetX8632::copyToReg(Operand *Src, int32_t RegNum) { |
| return Reg; |
| } |
| +// Insert code to randomize the representation of the immediate. Return |
| +// a register that holds the (derandomized) value of the immediate. |
| +// WARNING: Constant blinding overwrites the flags register. |
|
JF
2014/08/12 05:37:47
Is that one random cookie per immediate, or one pe
wala
2014/08/16 00:07:13
One per immediate.
|
| +Variable *TargetX8632::randomizeImmediate(Constant *Immediate) { |
| + assert(llvm::isa<ConstantInteger>(Immediate) || |
| + llvm::isa<ConstantRelocatable>(Immediate)); |
| + |
| + if (CLRandomizeImmediates == Randomize_None) |
| + return legalizeToVar(Immediate); |
| + |
| + Variable *Dest = makeReg(Immediate->getType()); |
| + |
| + if (CLRandomizeImmediates == Randomize_ConstantPooling || |
| + llvm::isa<ConstantRelocatable>(Immediate)) { |
| + const Type Ty = Immediate->getType(); |
| + const int64_t Offset = 0; |
| + const IceString Name = nameImmediate(Immediate); |
| + const bool SuppressMangling = true; |
| + Ctx->addConstantPooledImmediate(Name, Immediate); |
| + Constant *Sym = Ctx->getConstantSym(Ty, Offset, Name, SuppressMangling); |
| + // LEAHACK: Once a proper assembler is used, change this to be |
| + // mov Dest, [Sym]. |
| + _mov(Dest, OperandX8632Mem::create(Func, Ty, NULL, Sym)); |
| + } else { |
| + assert(CLRandomizeImmediates == Randomize_ConstantBlinding); |
| + // Mask integer immediates with a random XOR key. |
| + ConstantInteger *IntegerImmediate = llvm::cast<ConstantInteger>(Immediate); |
| + assert(IntegerImmediate->getType() != IceType_i64); |
| + uint64_t Value = IntegerImmediate->getValue(); |
| + RandomNumberGenerator &RNG = Ctx->getRNG(); |
|
Jim Stichnoth
2014/08/13 23:30:25
I think it should be one random cookie per functio
wala
2014/08/16 00:07:12
Done, no CSE yet.
|
| + uint32_t Mask1 = RNG.next((uint64_t)UINT32_MAX + 1); |
|
JF
2014/08/12 05:37:47
Use std::numeric_limits.
wala
2014/08/16 00:07:12
Done.
|
| + uint32_t Mask2 = Mask1 ^ Value; |
| + _mov(Dest, Ctx->getConstantInt(IceType_i32, Mask1)); |
| + _xor(Dest, Ctx->getConstantInt(IceType_i32, Mask2)); |
| + } |
| + |
| + return Dest; |
| +} |
| + |
| Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, |
| bool AllowOverlap, int32_t RegNum) { |
| // Assert that a physical register is allowed. To date, all calls |
| @@ -3957,6 +4073,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, |
| // that the Base and Index components are in physical registers. |
| Variable *Base = Mem->getBase(); |
| Variable *Index = Mem->getIndex(); |
| + Constant *Offset = Mem->getOffset(); |
| Variable *RegBase = NULL; |
| Variable *RegIndex = NULL; |
| if (Base) { |
| @@ -3965,10 +4082,22 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, |
| if (Index) { |
| RegIndex = legalizeToVar(Index, true); |
| } |
| + |
| + if (CLRandomizeImmediates && immediateShouldBeRandomized(Offset)) { |
|
Jim Stichnoth
2014/08/13 23:30:25
Can you just add the CLRandomizeImmediates test in
wala
2014/08/16 00:07:12
Done.
|
| + // lea new_base [base + randomize(offset)] |
| + Variable *RegOffset = randomizeImmediate(Offset); |
| + OperandX8632Mem *NewBaseAddr = OperandX8632Mem::create( |
| + Func, Mem->getType(), RegBase, NULL, RegOffset, 0); |
| + Variable *NewBase = makeReg(IceType_i32); |
| + _lea(NewBase, NewBaseAddr); |
| + RegBase = NewBase; |
| + Offset = NULL; |
| + } |
| + |
| if (Base != RegBase || Index != RegIndex) { |
| - From = OperandX8632Mem::create( |
| - Func, Mem->getType(), RegBase, Mem->getOffset(), RegIndex, |
| - Mem->getShift(), Mem->getSegmentRegister()); |
| + From = OperandX8632Mem::create(Func, Mem->getType(), RegBase, Offset, |
| + RegIndex, Mem->getShift(), |
| + Mem->getSegmentRegister()); |
| } |
| if (!(Allowed & Legal_Mem)) { |
| @@ -3995,6 +4124,11 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, |
| } |
| // There should be no constants of vector type (other than undef). |
| assert(!isVectorType(From->getType())); |
| + |
| + if (CLRandomizeImmediates && immediateShouldBeRandomized(From)) { |
| + return randomizeImmediate(llvm::cast<Constant>(From)); |
| + } |
| + |
| bool NeedsReg = false; |
| if (!(Allowed & Legal_Imm)) |
| // Immediate specifically not allowed |