Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Unified Diff: src/IceTargetLoweringX8632.cpp

Issue 460233002: Subzero: Randomize immediates by constant blinding or pooling. (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Formatting Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698