Chromium Code Reviews| Index: src/IceASanInstrumentation.cpp |
| diff --git a/src/IceASanInstrumentation.cpp b/src/IceASanInstrumentation.cpp |
| index f4b47e15f0f42b56d7b47af892026db3519129e1..ed445558d1ae2efa105037b4b46859a49c5faeed 100644 |
| --- a/src/IceASanInstrumentation.cpp |
| +++ b/src/IceASanInstrumentation.cpp |
| @@ -24,10 +24,12 @@ |
| #include <sstream> |
| #include <unordered_map> |
| +#include <vector> |
| namespace Ice { |
| namespace { |
| + |
| constexpr SizeT RzSize = 32; |
| const std::string RzPrefix = "__$rz"; |
| const llvm::NaClBitcodeRecord::RecordVector RzContents = |
| @@ -42,6 +44,9 @@ const string_map FuncSubstitutions = {{"malloc", "__asan_malloc"}, |
| } // end of anonymous namespace |
| +ICE_TLS_DEFINE_FIELD(std::vector<InstCall *> *, ASanInstrumentation, |
| + LocalDtors); |
| + |
| // Create redzones around all global variables, ensuring that the initializer |
| // types of the redzones and their associated globals match so that they are |
| // laid out together in memory. |
| @@ -126,38 +131,95 @@ ASanInstrumentation::createRz(VariableDeclarationList *List, |
| // Check for an alloca signaling the presence of local variables and add a |
| // redzone if it is found |
| void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) { |
| - auto *FirstAlloca = llvm::dyn_cast<InstAlloca>(Context.getCur()); |
| - if (FirstAlloca == nullptr) |
| - return; |
| + if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) |
| + ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>()); |
| - constexpr SizeT Alignment = 4; |
| - InstAlloca *RzAlloca = createLocalRz(Context, RzSize, Alignment); |
| + 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")); |
| - // insert before the current instruction |
| - InstList::iterator Next = Context.getNext(); |
| - Context.setInsertPoint(Context.getCur()); |
| - Context.insert(RzAlloca); |
| - Context.setNext(Next); |
| -} |
| + InstAlloca *Cur; |
| + ConstantInteger32 *VarSizeOp; |
| + while ( |
| + (Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(C.getCur()))) && |
| + (VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()))) { |
| + HasLocals = true; |
| -void ASanInstrumentation::instrumentAlloca(LoweringContext &Context, |
| - InstAlloca *Instr) { |
| - auto *VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Instr->getSizeInBytes()); |
| - SizeT VarSize = (VarSizeOp == nullptr) ? RzSize : VarSizeOp->getValue(); |
| - SizeT Padding = Utils::OffsetToAlignment(VarSize, RzSize); |
| - constexpr SizeT Alignment = 1; |
| - InstAlloca *Rz = createLocalRz(Context, RzSize + Padding, Alignment); |
| - Context.insert(Rz); |
| -} |
| + // create the new alloca that includes a redzone |
| + SizeT VarSize = VarSizeOp->getValue(); |
| + Variable *Dest = Cur->getDest(); |
| + SizeT RzPadding = RzSize + Utils::OffsetToAlignment(VarSize, RzSize); |
| + auto *ByteCount = |
| + ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding); |
| + constexpr SizeT Alignment = 8; |
| + auto *NewVar = InstAlloca::create(Func, Dest, ByteCount, Alignment); |
| -InstAlloca *ASanInstrumentation::createLocalRz(LoweringContext &Context, |
| - SizeT Size, SizeT Alignment) { |
| - Cfg *Func = Context.getNode()->getCfg(); |
| - Variable *Rz = Func->makeVariable(IceType_i32); |
| - Rz->setName(Func, nextRzName()); |
| - auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, Size); |
| - auto *RzAlloca = InstAlloca::create(Func, Rz, ByteCount, Alignment); |
| - return RzAlloca; |
| + // 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 *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall); |
| + auto *Destroy = |
| + InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall); |
| + Init->addArg(RzLocVar); |
| + Destroy->addArg(RzLocVar); |
| + auto *RzSizeConst = ConstantInteger32::create(Ctx, IceType_i32, RzPadding); |
| + Init->addArg(RzSizeConst); |
| + 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(); |
| + } |
| + |
| + 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 *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall); |
| + auto *Destroy = |
| + InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall); |
| + Init->addArg(LastRz); |
| + Destroy->addArg(LastRz); |
| + Init->addArg(RzAlloca->getSizeInBytes()); |
| + Destroy->addArg(RzAlloca->getSizeInBytes()); |
| + |
| + ICE_TLS_GET_FIELD(LocalDtors)->emplace_back(Destroy); |
| + C.insert(RzAlloca); |
| + C.insert(Init); |
| + } |
| + |
| + // insert initializers for the redzones |
| + for (Inst *Init : Initializations) { |
| + C.insert(Init); |
| + } |
| } |
| void ASanInstrumentation::instrumentCall(LoweringContext &Context, |
| @@ -214,6 +276,17 @@ void ASanInstrumentation::instrumentAccess(LoweringContext &Context, |
| Context.setNext(Next); |
| } |
| +void ASanInstrumentation::instrumentRet(LoweringContext &Context, |
| + InstRet *Instr) { |
|
Jim Stichnoth
2016/06/25 17:14:13
You can just use "InstRet *) {" and avoid the void
tlively
2016/06/27 17:03:57
Done.
|
| + (void)Instr; |
| + InstList::iterator Next = Context.getNext(); |
| + Context.setInsertPoint(Context.getCur()); |
| + for (InstCall *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) { |
| + Context.insert(RzUnpoison); |
| + } |
| + Context.setNext(Next); |
| +} |
| + |
| void ASanInstrumentation::instrumentStart(Cfg *Func) { |
| Constant *ShadowMemInit = |
| Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_init")); |
| @@ -224,4 +297,10 @@ void ASanInstrumentation::instrumentStart(Cfg *Func) { |
| Func->getEntryNode()->getInsts().push_front(Call); |
| } |
| +// TODO(tlively): make this more efficient with swap idiom |
| +void ASanInstrumentation::finishFunc(Cfg *Func) { |
| + (void)Func; |
| + ICE_TLS_GET_FIELD(LocalDtors)->clear(); |
| +} |
| + |
| } // end of namespace Ice |