| OLD | NEW |
| 1 //===- subzero/src/IceASanInstrumentation.cpp - ASan ------------*- C++ -*-===// | 1 //===- subzero/src/IceASanInstrumentation.cpp - ASan ------------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 constexpr const char *ASanPrefix = "__asan"; | 34 constexpr const char *ASanPrefix = "__asan"; |
| 35 constexpr SizeT RzSize = 32; | 35 constexpr SizeT RzSize = 32; |
| 36 constexpr const char *RzPrefix = "__$rz"; | 36 constexpr const char *RzPrefix = "__$rz"; |
| 37 constexpr const char *RzArrayName = "__$rz_array"; | 37 constexpr const char *RzArrayName = "__$rz_array"; |
| 38 constexpr const char *RzSizesName = "__$rz_sizes"; | 38 constexpr const char *RzSizesName = "__$rz_sizes"; |
| 39 const llvm::NaClBitcodeRecord::RecordVector RzContents = | 39 const llvm::NaClBitcodeRecord::RecordVector RzContents = |
| 40 llvm::NaClBitcodeRecord::RecordVector(RzSize, 'R'); | 40 llvm::NaClBitcodeRecord::RecordVector(RzSize, 'R'); |
| 41 | 41 |
| 42 // In order to instrument the code correctly, the .pexe must not have had its | 42 // In order to instrument the code correctly, the .pexe must not have had its |
| 43 // symbols stripped. | 43 // symbols stripped. |
| 44 using string_map = std::unordered_map<std::string, std::string>; | 44 using StringMap = std::unordered_map<std::string, std::string>; |
| 45 using string_set = std::unordered_set<std::string>; | 45 using StringSet = std::unordered_set<std::string>; |
| 46 // TODO(tlively): Handle all allocation functions | 46 // TODO(tlively): Handle all allocation functions |
| 47 const string_map FuncSubstitutions = {{"malloc", "__asan_malloc"}, | 47 const StringMap FuncSubstitutions = {{"malloc", "__asan_malloc"}, |
| 48 {"free", "__asan_free"}, | 48 {"free", "__asan_free"}, |
| 49 {"calloc", "__asan_calloc"}, | 49 {"calloc", "__asan_calloc"}, |
| 50 {"__asan_dummy_calloc", "__asan_calloc"}, | 50 {"__asan_dummy_calloc", "__asan_calloc"}, |
| 51 {"realloc", "__asan_realloc"}}; | 51 {"realloc", "__asan_realloc"}}; |
| 52 const string_set FuncBlackList = {"_Balloc"}; | 52 const StringSet FuncBlackList = {"_Balloc"}; |
| 53 | 53 |
| 54 llvm::NaClBitcodeRecord::RecordVector sizeToByteVec(SizeT Size) { | 54 llvm::NaClBitcodeRecord::RecordVector sizeToByteVec(SizeT Size) { |
| 55 llvm::NaClBitcodeRecord::RecordVector SizeContents; | 55 llvm::NaClBitcodeRecord::RecordVector SizeContents; |
| 56 for (unsigned i = 0; i < sizeof(Size); ++i) { | 56 for (unsigned i = 0; i < sizeof(Size); ++i) { |
| 57 SizeContents.emplace_back(Size % (1 << CHAR_BIT)); | 57 SizeContents.emplace_back(Size % (1 << CHAR_BIT)); |
| 58 Size >>= CHAR_BIT; | 58 Size >>= CHAR_BIT; |
| 59 } | 59 } |
| 60 return SizeContents; | 60 return SizeContents; |
| 61 } | 61 } |
| 62 | 62 |
| 63 } // end of anonymous namespace | 63 } // end of anonymous namespace |
| 64 | 64 |
| 65 ICE_TLS_DEFINE_FIELD(VarSizeMap *, ASanInstrumentation, LocalVars); |
| 65 ICE_TLS_DEFINE_FIELD(std::vector<InstCall *> *, ASanInstrumentation, | 66 ICE_TLS_DEFINE_FIELD(std::vector<InstCall *> *, ASanInstrumentation, |
| 66 LocalDtors); | 67 LocalDtors); |
| 67 | 68 |
| 68 bool ASanInstrumentation::isInstrumentable(Cfg *Func) { | 69 bool ASanInstrumentation::isInstrumentable(Cfg *Func) { |
| 69 std::string FuncName = Func->getFunctionName().toStringOrEmpty(); | 70 std::string FuncName = Func->getFunctionName().toStringOrEmpty(); |
| 70 return FuncName == "" || | 71 return FuncName == "" || |
| 71 (FuncBlackList.count(FuncName) == 0 && FuncName.find(ASanPrefix) != 0); | 72 (FuncBlackList.count(FuncName) == 0 && FuncName.find(ASanPrefix) != 0); |
| 72 } | 73 } |
| 73 | 74 |
| 74 // Create redzones around all global variables, ensuring that the initializer | 75 // Create redzones around all global variables, ensuring that the initializer |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 | 151 |
| 151 std::string ASanInstrumentation::nextRzName() { | 152 std::string ASanInstrumentation::nextRzName() { |
| 152 std::stringstream Name; | 153 std::stringstream Name; |
| 153 Name << RzPrefix << RzNum++; | 154 Name << RzPrefix << RzNum++; |
| 154 return Name.str(); | 155 return Name.str(); |
| 155 } | 156 } |
| 156 | 157 |
| 157 // Check for an alloca signaling the presence of local variables and add a | 158 // Check for an alloca signaling the presence of local variables and add a |
| 158 // redzone if it is found | 159 // redzone if it is found |
| 159 void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) { | 160 void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) { |
| 160 if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) | 161 if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) { |
| 161 ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>()); | 162 ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>()); |
| 163 ICE_TLS_SET_FIELD(LocalVars, new VarSizeMap()); |
| 164 } |
| 162 Cfg *Func = Context.getNode()->getCfg(); | 165 Cfg *Func = Context.getNode()->getCfg(); |
| 163 bool HasLocals = false; | 166 bool HasLocals = false; |
| 164 LoweringContext C; | 167 LoweringContext C; |
| 165 C.init(Context.getNode()); | 168 C.init(Context.getNode()); |
| 166 std::vector<Inst *> Initializations; | 169 std::vector<Inst *> Initializations; |
| 167 Constant *InitFunc = | 170 Constant *InitFunc = |
| 168 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_poison")); | 171 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_poison")); |
| 169 Constant *DestroyFunc = | 172 Constant *DestroyFunc = |
| 170 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_unpoison")); | 173 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_unpoison")); |
| 171 | 174 |
| 172 InstAlloca *Cur; | 175 InstAlloca *Cur; |
| 173 ConstantInteger32 *VarSizeOp; | 176 ConstantInteger32 *VarSizeOp; |
| 174 while ( | 177 while ( |
| 175 (Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(C.getCur()))) && | 178 (Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(C.getCur()))) && |
| 176 (VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()))) { | 179 (VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()))) { |
| 177 HasLocals = true; | 180 HasLocals = true; |
| 178 | 181 |
| 179 // create the new alloca that includes a redzone | 182 // create the new alloca that includes a redzone |
| 180 SizeT VarSize = VarSizeOp->getValue(); | 183 SizeT VarSize = VarSizeOp->getValue(); |
| 181 Variable *Dest = Cur->getDest(); | 184 Variable *Dest = Cur->getDest(); |
| 185 ICE_TLS_GET_FIELD(LocalVars)->insert({Dest, VarSize}); |
| 182 SizeT RzPadding = RzSize + Utils::OffsetToAlignment(VarSize, RzSize); | 186 SizeT RzPadding = RzSize + Utils::OffsetToAlignment(VarSize, RzSize); |
| 183 auto *ByteCount = | 187 auto *ByteCount = |
| 184 ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding); | 188 ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding); |
| 185 constexpr SizeT Alignment = 8; | 189 constexpr SizeT Alignment = 8; |
| 186 auto *NewVar = InstAlloca::create(Func, Dest, ByteCount, Alignment); | 190 auto *NewVar = InstAlloca::create(Func, Dest, ByteCount, Alignment); |
| 187 | 191 |
| 188 // calculate the redzone offset | 192 // calculate the redzone offset |
| 189 Variable *RzLocVar = Func->makeVariable(IceType_i32); | 193 Variable *RzLocVar = Func->makeVariable(IceType_i32); |
| 190 RzLocVar->setName(Func, nextRzName()); | 194 RzLocVar->setName(Func, nextRzName()); |
| 191 auto *Offset = ConstantInteger32::create(Ctx, IceType_i32, VarSize); | 195 auto *Offset = ConstantInteger32::create(Ctx, IceType_i32, VarSize); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 } | 283 } |
| 280 | 284 |
| 281 void ASanInstrumentation::instrumentStore(LoweringContext &Context, | 285 void ASanInstrumentation::instrumentStore(LoweringContext &Context, |
| 282 InstStore *Instr) { | 286 InstStore *Instr) { |
| 283 Constant *Func = | 287 Constant *Func = |
| 284 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_check_store")); | 288 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_check_store")); |
| 285 instrumentAccess(Context, Instr->getAddr(), | 289 instrumentAccess(Context, Instr->getAddr(), |
| 286 typeWidthInBytes(Instr->getData()->getType()), Func); | 290 typeWidthInBytes(Instr->getData()->getType()), Func); |
| 287 } | 291 } |
| 288 | 292 |
| 289 // TODO(tlively): Take size of access into account as well | |
| 290 void ASanInstrumentation::instrumentAccess(LoweringContext &Context, | 293 void ASanInstrumentation::instrumentAccess(LoweringContext &Context, |
| 291 Operand *Op, SizeT Size, | 294 Operand *Op, SizeT Size, |
| 292 Constant *CheckFunc) { | 295 Constant *CheckFunc) { |
| 296 VarSizeMap::iterator LocalSize = ICE_TLS_GET_FIELD(LocalVars)->find(Op); |
| 297 if (LocalSize != ICE_TLS_GET_FIELD(LocalVars)->end() && |
| 298 LocalSize->second >= Size) |
| 299 return; |
| 293 constexpr SizeT NumArgs = 2; | 300 constexpr SizeT NumArgs = 2; |
| 294 constexpr Variable *Void = nullptr; | 301 constexpr Variable *Void = nullptr; |
| 295 constexpr bool NoTailCall = false; | 302 constexpr bool NoTailCall = false; |
| 296 auto *Call = InstCall::create(Context.getNode()->getCfg(), NumArgs, Void, | 303 auto *Call = InstCall::create(Context.getNode()->getCfg(), NumArgs, Void, |
| 297 CheckFunc, NoTailCall); | 304 CheckFunc, NoTailCall); |
| 298 Call->addArg(Op); | 305 Call->addArg(Op); |
| 299 Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, Size)); | 306 Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, Size)); |
| 300 // play games to insert the call before the access instruction | 307 // play games to insert the call before the access instruction |
| 301 InstList::iterator Next = Context.getNext(); | 308 InstList::iterator Next = Context.getNext(); |
| 302 Context.setInsertPoint(Context.getCur()); | 309 Context.setInsertPoint(Context.getCur()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 | 342 |
| 336 instrumentGlobals(*getGlobals()); | 343 instrumentGlobals(*getGlobals()); |
| 337 | 344 |
| 338 Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, RzGlobalsNum)); | 345 Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, RzGlobalsNum)); |
| 339 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzArrayName))); | 346 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzArrayName))); |
| 340 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzSizesName))); | 347 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzSizesName))); |
| 341 } | 348 } |
| 342 | 349 |
| 343 // TODO(tlively): make this more efficient with swap idiom | 350 // TODO(tlively): make this more efficient with swap idiom |
| 344 void ASanInstrumentation::finishFunc(Cfg *) { | 351 void ASanInstrumentation::finishFunc(Cfg *) { |
| 352 ICE_TLS_GET_FIELD(LocalVars)->clear(); |
| 345 ICE_TLS_GET_FIELD(LocalDtors)->clear(); | 353 ICE_TLS_GET_FIELD(LocalDtors)->clear(); |
| 346 } | 354 } |
| 347 | 355 |
| 348 } // end of namespace Ice | 356 } // end of namespace Ice |
| OLD | NEW |