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

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: Comments round 1 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
« no previous file with comments | « src/IceTargetLoweringX8632.h ('k') | tests_lit/llvm2ice_tests/randomize-immediates.ll » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceTargetLoweringX8632.cpp
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index d36ad1695191b49e77d7ad516c33d80eacfbf890..eb6afca1ecc552807b41855d43a902b92cdde4e6 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -136,6 +136,8 @@ const uint32_t X86_LOG2_OF_MIN_STACK_SLOT_SIZE = 2;
const uint32_t X86_LOG2_OF_MAX_STACK_SLOT_SIZE = 4;
// The number of different NOP instructions
const uint32_t X86_NUM_NOP_VARIANTS = 5;
+// Randomize integer immediates at least 2 bytes in size.
+const uint64_t X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD = 0xffff;
// Value and Alignment are in bytes. Return Value adjusted to the next
// highest multiple of Alignment.
@@ -151,6 +153,17 @@ uint32_t applyStackAlignment(uint32_t Value) {
return applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
}
+// 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(
@@ -162,6 +175,51 @@ 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));
+
+bool immediateShouldBeRandomized(Operand *Immediate) {
+ if (!CLRandomizeImmediates)
+ return false;
+ if (ConstantInteger *ConstInt =
+ llvm::dyn_cast_or_null<ConstantInteger>(Immediate)) {
+ // i64 should have been split at this point.
+ assert(ConstInt->getType() != IceType_i64);
+ return ConstInt->getType() == IceType_i32 &&
+ (ConstInt->getValue() +
+ X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD / 2) >=
+ X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD;
+ }
+ return false;
+}
+
+// Return a string representation of the type that is suitable for use
+// in an identifier.
+IceString typeIdentString(const Type Ty) {
+ IceString Str;
+ llvm::raw_string_ostream BaseOS(Str);
+ if (isVectorType(Ty)) {
+ BaseOS << "v" << typeNumElements(Ty) << typeElementType(Ty);
+ } else {
+ BaseOS << Ty;
+ }
+ return BaseOS.str();
+}
+
// In some cases, there are x-macros tables for both high-level and
// low-level instructions/operands that use the same enum key value.
// The tables are kept separate to maintain a proper separation
@@ -263,7 +321,8 @@ TargetX8632::TargetX8632(Cfg *Func)
: TargetLowering(Func), InstructionSet(CLInstructionSet),
IsEbpBasedFrame(false), NeedsStackAlignment(false), FrameSizeLocals(0),
SpillAreaSizeBytes(0), NextLabelNumber(0), ComputedLiveRanges(false),
- PhysicalRegisters(VarList(Reg_NUM)) {
+ PhysicalRegisters(VarList(Reg_NUM)),
+ ConstantBlindingCookieInitialized(false), ConstantBlindingCookie(0) {
// TODO: Don't initialize IntegerRegisters and friends every time.
// Instead, initialize in some sort of static initializer for the
// class.
@@ -983,9 +1042,41 @@ template <typename T> void TargetX8632::emitConstantPool() const {
}
}
+void TargetX8632::emitPooledImmediates() const {
+ 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.
@@ -3808,8 +3899,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));
@@ -4027,6 +4119,49 @@ 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.
+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) {
+ 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();
+ if (!ConstantBlindingCookieInitialized) {
+ RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
+ ConstantBlindingCookie =
+ RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1);
+ ConstantBlindingCookieInitialized = true;
+ }
+ uint32_t Mask1 = ConstantBlindingCookie;
+ 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
@@ -4044,6 +4179,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) {
@@ -4052,10 +4188,22 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
if (Index) {
RegIndex = legalizeToVar(Index, true);
}
+
+ if (immediateShouldBeRandomized(Offset)) {
+ // 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)) {
@@ -4082,6 +4230,11 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
}
// There should be no constants of vector type (other than undef).
assert(!isVectorType(From->getType()));
+
+ if (immediateShouldBeRandomized(From)) {
+ return randomizeImmediate(llvm::cast<Constant>(From));
+ }
+
bool NeedsReg = false;
if (!(Allowed & Legal_Imm))
// Immediate specifically not allowed
« no previous file with comments | « src/IceTargetLoweringX8632.h ('k') | tests_lit/llvm2ice_tests/randomize-immediates.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698