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

Unified Diff: src/IceASanInstrumentation.cpp

Issue 2194853003: Subzero: Implemented codegen for poisoning and unpoisoning stack redzones (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Added missing REQUIRES directive Created 4 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/IceASanInstrumentation.h ('k') | src/IceCfg.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceASanInstrumentation.cpp
diff --git a/src/IceASanInstrumentation.cpp b/src/IceASanInstrumentation.cpp
index 1aa1730699fa6cb2024526383276a43e400d355e..62862990b7c67cdbdc36799b61b3290efb4cf2d0 100644
--- a/src/IceASanInstrumentation.cpp
+++ b/src/IceASanInstrumentation.cpp
@@ -31,12 +31,16 @@ namespace Ice {
namespace {
-constexpr const char *ASanPrefix = "__asan";
+constexpr SizeT BytesPerWord = sizeof(uint32_t);
constexpr SizeT RzSize = 32;
+constexpr SizeT ShadowScaleLog2 = 3;
+constexpr SizeT ShadowScale = 1 << ShadowScaleLog2;
+constexpr SizeT ShadowLength32 = 1 << (32 - ShadowScaleLog2);
+constexpr int32_t StackPoisonVal = -1;
+constexpr const char *ASanPrefix = "__asan";
constexpr const char *RzPrefix = "__$rz";
constexpr const char *RzArrayName = "__$rz_array";
constexpr const char *RzSizesName = "__$rz_sizes";
-constexpr char RzStackPoison = -1;
const llvm::NaClBitcodeRecord::RecordVector RzContents =
llvm::NaClBitcodeRecord::RecordVector(RzSize, 'R');
@@ -64,7 +68,7 @@ llvm::NaClBitcodeRecord::RecordVector sizeToByteVec(SizeT Size) {
} // end of anonymous namespace
ICE_TLS_DEFINE_FIELD(VarSizeMap *, ASanInstrumentation, LocalVars);
-ICE_TLS_DEFINE_FIELD(std::vector<InstCall *> *, ASanInstrumentation,
+ICE_TLS_DEFINE_FIELD(std::vector<InstStore *> *, ASanInstrumentation,
LocalDtors);
bool ASanInstrumentation::isInstrumentable(Cfg *Func) {
@@ -162,25 +166,59 @@ std::string ASanInstrumentation::nextRzName() {
// redzone if it is found
void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) {
if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) {
- ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>());
+ ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstStore *>());
ICE_TLS_SET_FIELD(LocalVars, new VarSizeMap());
}
Cfg *Func = Context.getNode()->getCfg();
- bool HasLocals = false;
- LoweringContext C;
- C.init(Context.getNode());
- std::vector<Inst *> Initializations;
- Constant *InitFunc =
- Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_poison"));
- Constant *DestroyFunc =
- Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_unpoison"));
-
+ using Entry = std::pair<SizeT, int32_t>;
+ std::vector<InstAlloca *> NewAllocas;
+ std::vector<Entry> PoisonVals;
+ Variable *FirstShadowLocVar;
+ InstArithmetic *ShadowIndexCalc;
+ InstArithmetic *ShadowLocCalc;
InstAlloca *Cur;
ConstantInteger32 *VarSizeOp;
- while (
- (Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(C.getCur()))) &&
- (VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()))) {
- HasLocals = true;
+ while (!Context.atEnd()) {
+ Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(Context.getCur()));
+ VarSizeOp = (Cur == nullptr)
+ ? nullptr
+ : llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes());
+ if (Cur == nullptr || VarSizeOp == nullptr) {
+ Context.advanceCur();
+ Context.advanceNext();
+ continue;
+ }
+
+ Cur->setDeleted();
+
+ if (PoisonVals.empty()) {
+ // insert leftmost redzone
+ auto *LastRzVar = Func->makeVariable(IceType_i32);
+ LastRzVar->setName(Func, nextRzName());
+ auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, RzSize);
+ constexpr SizeT Alignment = 8;
+ NewAllocas.emplace_back(
+ InstAlloca::create(Func, LastRzVar, ByteCount, Alignment));
+ PoisonVals.emplace_back(Entry{RzSize >> ShadowScaleLog2, StackPoisonVal});
+
+ // Calculate starting address for poisoning
+ FirstShadowLocVar = Func->makeVariable(IceType_i32);
+ FirstShadowLocVar->setName(Func, "firstShadowLoc");
+ auto *ShadowIndexVar = Func->makeVariable(IceType_i32);
+ ShadowIndexVar->setName(Func, "shadowIndex");
+
+ auto *ShadowScaleLog2Const =
+ ConstantInteger32::create(Ctx, IceType_i32, ShadowScaleLog2);
+ auto *ShadowMemLocConst =
+ ConstantInteger32::create(Ctx, IceType_i32, ShadowLength32);
+
+ ShadowIndexCalc =
+ InstArithmetic::create(Func, InstArithmetic::Lshr, ShadowIndexVar,
+ LastRzVar, ShadowScaleLog2Const);
+ ShadowLocCalc =
+ InstArithmetic::create(Func, InstArithmetic::Add, FirstShadowLocVar,
+ ShadowIndexVar, ShadowMemLocConst);
+ }
// create the new alloca that includes a redzone
SizeT VarSize = VarSizeOp->getValue();
@@ -190,72 +228,63 @@ void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) {
auto *ByteCount =
ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding);
constexpr SizeT Alignment = 8;
- auto *NewVar = InstAlloca::create(Func, Dest, ByteCount, Alignment);
-
- // calculate the redzone offset
- Variable *RzLocVar = Func->makeVariable(IceType_i32);
- RzLocVar->setName(Func, nextRzName());
- auto *Offset = ConstantInteger32::create(Ctx, IceType_i32, VarSize);
- auto *RzLoc = InstArithmetic::create(Func, InstArithmetic::Add, RzLocVar,
- Dest, Offset);
-
- // instructions to poison and unpoison the redzone
- constexpr SizeT NumArgs = 2;
- constexpr Variable *Void = nullptr;
- constexpr bool NoTailcall = false;
- auto *RzSizeConst = ConstantInteger32::create(Ctx, IceType_i32, RzPadding);
- auto *RzPoisonConst =
- ConstantInteger32::create(Ctx, IceType_i32, RzStackPoison);
- auto *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall);
- Init->addArg(RzLocVar);
- Init->addArg(RzSizeConst);
- Init->addArg(RzPoisonConst);
- auto *Destroy =
- InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall);
- Destroy->addArg(RzLocVar);
- Destroy->addArg(RzSizeConst);
- Cur->setDeleted();
- C.insert(NewVar);
- ICE_TLS_GET_FIELD(LocalDtors)->emplace_back(Destroy);
- Initializations.emplace_back(RzLoc);
- Initializations.emplace_back(Init);
-
- C.advanceCur();
- C.advanceNext();
+ NewAllocas.emplace_back(
+ InstAlloca::create(Func, Dest, ByteCount, Alignment));
+
+ const SizeT Zeros = VarSize >> ShadowScaleLog2;
+ const SizeT Offset = VarSize % ShadowScale;
+ const SizeT PoisonBytes =
+ ((VarSize + RzPadding) >> ShadowScaleLog2) - Zeros - 1;
+ if (Zeros > 0)
+ PoisonVals.emplace_back(Entry{Zeros, 0});
+ PoisonVals.emplace_back(Entry{1, (Offset == 0) ? StackPoisonVal : Offset});
+ PoisonVals.emplace_back(Entry{PoisonBytes, StackPoisonVal});
+ Context.advanceCur();
+ Context.advanceNext();
}
- C.setInsertPoint(C.getCur());
-
- // add the leftmost redzone
- if (HasLocals) {
- Variable *LastRz = Func->makeVariable(IceType_i32);
- LastRz->setName(Func, nextRzName());
- auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, RzSize);
- constexpr SizeT Alignment = 8;
- auto *RzAlloca = InstAlloca::create(Func, LastRz, ByteCount, Alignment);
-
- constexpr SizeT NumArgs = 2;
- constexpr Variable *Void = nullptr;
- constexpr bool NoTailcall = false;
- auto *RzPoisonConst =
- ConstantInteger32::create(Ctx, IceType_i32, RzStackPoison);
- auto *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall);
- Init->addArg(LastRz);
- Init->addArg(RzAlloca->getSizeInBytes());
- Init->addArg(RzPoisonConst);
- auto *Destroy =
- InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall);
- Destroy->addArg(LastRz);
- Destroy->addArg(RzAlloca->getSizeInBytes());
- ICE_TLS_GET_FIELD(LocalDtors)->emplace_back(Destroy);
- C.insert(RzAlloca);
- C.insert(Init);
+ Context.rewind();
+ if (PoisonVals.empty()) {
+ Context.advanceNext();
+ return;
}
-
- // insert initializers for the redzones
- for (Inst *Init : Initializations) {
- C.insert(Init);
+ for (InstAlloca *RzAlloca : NewAllocas) {
+ Context.insert(RzAlloca);
}
+ Context.insert(ShadowIndexCalc);
+ Context.insert(ShadowLocCalc);
+
+ // Poison redzones
+ std::vector<Entry>::iterator Iter = PoisonVals.begin();
+ for (SizeT Offset = 0; Iter != PoisonVals.end(); Offset += BytesPerWord) {
+ int32_t CurVals[BytesPerWord] = {0};
+ for (uint32_t i = 0; i < BytesPerWord; ++i) {
+ if (Iter == PoisonVals.end())
+ break;
+ Entry Val = *Iter;
+ CurVals[i] = Val.second;
+ --Val.first;
+ if (Val.first > 0)
+ *Iter = Val;
+ else
+ ++Iter;
+ }
+ int32_t Poison = ((CurVals[3] & 0xff) << 24) | ((CurVals[2] & 0xff) << 16) |
+ ((CurVals[1] & 0xff) << 8) | (CurVals[0] & 0xff);
+ if (Poison == 0)
+ continue;
+ auto *PoisonConst = ConstantInteger32::create(Ctx, IceType_i32, Poison);
+ auto *ZeroConst = ConstantInteger32::create(Ctx, IceType_i32, 0);
+ auto *OffsetConst = ConstantInteger32::create(Ctx, IceType_i32, Offset);
+ auto *PoisonAddrVar = Func->makeVariable(IceType_i32);
+ Context.insert(InstArithmetic::create(Func, InstArithmetic::Add,
+ PoisonAddrVar, FirstShadowLocVar,
+ OffsetConst));
+ Context.insert(InstStore::create(Func, PoisonConst, PoisonAddrVar));
+ ICE_TLS_GET_FIELD(LocalDtors)
+ ->emplace_back(InstStore::create(Func, ZeroConst, PoisonAddrVar));
+ }
+ Context.advanceNext();
}
void ASanInstrumentation::instrumentCall(LoweringContext &Context,
@@ -332,22 +361,13 @@ bool ASanInstrumentation::isOkGlobalAccess(Operand *Op, SizeT Size) {
void ASanInstrumentation::instrumentRet(LoweringContext &Context, InstRet *) {
Cfg *Func = Context.getNode()->getCfg();
- InstList::iterator Next = Context.getNext();
Context.setInsertPoint(Context.getCur());
- for (InstCall *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) {
- SizeT NumArgs = RzUnpoison->getNumArgs();
- Variable *Dest = RzUnpoison->getDest();
- Operand *CallTarget = RzUnpoison->getCallTarget();
- bool HasTailCall = RzUnpoison->isTailcall();
- bool IsTargetHelperCall = RzUnpoison->isTargetHelperCall();
- auto *RzUnpoisonCpy = InstCall::create(Func, NumArgs, Dest, CallTarget,
- HasTailCall, IsTargetHelperCall);
- for (int I = 0, Args = RzUnpoison->getNumArgs(); I < Args; ++I) {
- RzUnpoisonCpy->addArg(RzUnpoison->getArg(I));
- }
- Context.insert(RzUnpoisonCpy);
+ for (InstStore *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) {
+ Context.insert(
+ InstStore::create(Func, RzUnpoison->getData(), RzUnpoison->getAddr()));
}
- Context.setNext(Next);
+ Context.advanceCur();
+ Context.advanceNext();
}
void ASanInstrumentation::instrumentStart(Cfg *Func) {
« no previous file with comments | « src/IceASanInstrumentation.h ('k') | src/IceCfg.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698