| 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 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 #include <sstream> | 25 #include <sstream> |
| 26 #include <unordered_map> | 26 #include <unordered_map> |
| 27 #include <unordered_set> | 27 #include <unordered_set> |
| 28 #include <vector> | 28 #include <vector> |
| 29 | 29 |
| 30 namespace Ice { | 30 namespace Ice { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 constexpr SizeT BytesPerWord = sizeof(uint32_t); |
| 35 constexpr SizeT RzSize = 32; |
| 36 constexpr SizeT ShadowScaleLog2 = 3; |
| 37 constexpr SizeT ShadowScale = 1 << ShadowScaleLog2; |
| 38 constexpr SizeT ShadowLength32 = 1 << (32 - ShadowScaleLog2); |
| 39 constexpr int32_t StackPoisonVal = -1; |
| 34 constexpr const char *ASanPrefix = "__asan"; | 40 constexpr const char *ASanPrefix = "__asan"; |
| 35 constexpr SizeT RzSize = 32; | |
| 36 constexpr const char *RzPrefix = "__$rz"; | 41 constexpr const char *RzPrefix = "__$rz"; |
| 37 constexpr const char *RzArrayName = "__$rz_array"; | 42 constexpr const char *RzArrayName = "__$rz_array"; |
| 38 constexpr const char *RzSizesName = "__$rz_sizes"; | 43 constexpr const char *RzSizesName = "__$rz_sizes"; |
| 39 constexpr char RzStackPoison = -1; | |
| 40 const llvm::NaClBitcodeRecord::RecordVector RzContents = | 44 const llvm::NaClBitcodeRecord::RecordVector RzContents = |
| 41 llvm::NaClBitcodeRecord::RecordVector(RzSize, 'R'); | 45 llvm::NaClBitcodeRecord::RecordVector(RzSize, 'R'); |
| 42 | 46 |
| 43 // In order to instrument the code correctly, the .pexe must not have had its | 47 // In order to instrument the code correctly, the .pexe must not have had its |
| 44 // symbols stripped. | 48 // symbols stripped. |
| 45 using StringMap = std::unordered_map<std::string, std::string>; | 49 using StringMap = std::unordered_map<std::string, std::string>; |
| 46 using StringSet = std::unordered_set<std::string>; | 50 using StringSet = std::unordered_set<std::string>; |
| 47 // TODO(tlively): Handle all allocation functions | 51 // TODO(tlively): Handle all allocation functions |
| 48 const StringMap FuncSubstitutions = {{"malloc", "__asan_malloc"}, | 52 const StringMap FuncSubstitutions = {{"malloc", "__asan_malloc"}, |
| 49 {"free", "__asan_free"}, | 53 {"free", "__asan_free"}, |
| 50 {"calloc", "__asan_calloc"}, | 54 {"calloc", "__asan_calloc"}, |
| 51 {"__asan_dummy_calloc", "__asan_calloc"}, | 55 {"__asan_dummy_calloc", "__asan_calloc"}, |
| 52 {"realloc", "__asan_realloc"}}; | 56 {"realloc", "__asan_realloc"}}; |
| 53 const StringSet FuncBlackList = {"_Balloc"}; | 57 const StringSet FuncBlackList = {"_Balloc"}; |
| 54 | 58 |
| 55 llvm::NaClBitcodeRecord::RecordVector sizeToByteVec(SizeT Size) { | 59 llvm::NaClBitcodeRecord::RecordVector sizeToByteVec(SizeT Size) { |
| 56 llvm::NaClBitcodeRecord::RecordVector SizeContents; | 60 llvm::NaClBitcodeRecord::RecordVector SizeContents; |
| 57 for (unsigned i = 0; i < sizeof(Size); ++i) { | 61 for (unsigned i = 0; i < sizeof(Size); ++i) { |
| 58 SizeContents.emplace_back(Size % (1 << CHAR_BIT)); | 62 SizeContents.emplace_back(Size % (1 << CHAR_BIT)); |
| 59 Size >>= CHAR_BIT; | 63 Size >>= CHAR_BIT; |
| 60 } | 64 } |
| 61 return SizeContents; | 65 return SizeContents; |
| 62 } | 66 } |
| 63 | 67 |
| 64 } // end of anonymous namespace | 68 } // end of anonymous namespace |
| 65 | 69 |
| 66 ICE_TLS_DEFINE_FIELD(VarSizeMap *, ASanInstrumentation, LocalVars); | 70 ICE_TLS_DEFINE_FIELD(VarSizeMap *, ASanInstrumentation, LocalVars); |
| 67 ICE_TLS_DEFINE_FIELD(std::vector<InstCall *> *, ASanInstrumentation, | 71 ICE_TLS_DEFINE_FIELD(std::vector<InstStore *> *, ASanInstrumentation, |
| 68 LocalDtors); | 72 LocalDtors); |
| 69 | 73 |
| 70 bool ASanInstrumentation::isInstrumentable(Cfg *Func) { | 74 bool ASanInstrumentation::isInstrumentable(Cfg *Func) { |
| 71 std::string FuncName = Func->getFunctionName().toStringOrEmpty(); | 75 std::string FuncName = Func->getFunctionName().toStringOrEmpty(); |
| 72 return FuncName == "" || | 76 return FuncName == "" || |
| 73 (FuncBlackList.count(FuncName) == 0 && FuncName.find(ASanPrefix) != 0); | 77 (FuncBlackList.count(FuncName) == 0 && FuncName.find(ASanPrefix) != 0); |
| 74 } | 78 } |
| 75 | 79 |
| 76 // Create redzones around all global variables, ensuring that the initializer | 80 // Create redzones around all global variables, ensuring that the initializer |
| 77 // types of the redzones and their associated globals match so that they are | 81 // types of the redzones and their associated globals match so that they are |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 std::string ASanInstrumentation::nextRzName() { | 159 std::string ASanInstrumentation::nextRzName() { |
| 156 std::stringstream Name; | 160 std::stringstream Name; |
| 157 Name << RzPrefix << RzNum++; | 161 Name << RzPrefix << RzNum++; |
| 158 return Name.str(); | 162 return Name.str(); |
| 159 } | 163 } |
| 160 | 164 |
| 161 // Check for an alloca signaling the presence of local variables and add a | 165 // Check for an alloca signaling the presence of local variables and add a |
| 162 // redzone if it is found | 166 // redzone if it is found |
| 163 void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) { | 167 void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) { |
| 164 if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) { | 168 if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) { |
| 165 ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>()); | 169 ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstStore *>()); |
| 166 ICE_TLS_SET_FIELD(LocalVars, new VarSizeMap()); | 170 ICE_TLS_SET_FIELD(LocalVars, new VarSizeMap()); |
| 167 } | 171 } |
| 168 Cfg *Func = Context.getNode()->getCfg(); | 172 Cfg *Func = Context.getNode()->getCfg(); |
| 169 bool HasLocals = false; | 173 using Entry = std::pair<SizeT, int32_t>; |
| 170 LoweringContext C; | 174 std::vector<InstAlloca *> NewAllocas; |
| 171 C.init(Context.getNode()); | 175 std::vector<Entry> PoisonVals; |
| 172 std::vector<Inst *> Initializations; | 176 Variable *FirstShadowLocVar; |
| 173 Constant *InitFunc = | 177 InstArithmetic *ShadowIndexCalc; |
| 174 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_poison")); | 178 InstArithmetic *ShadowLocCalc; |
| 175 Constant *DestroyFunc = | |
| 176 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_unpoison")); | |
| 177 | |
| 178 InstAlloca *Cur; | 179 InstAlloca *Cur; |
| 179 ConstantInteger32 *VarSizeOp; | 180 ConstantInteger32 *VarSizeOp; |
| 180 while ( | 181 while (!Context.atEnd()) { |
| 181 (Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(C.getCur()))) && | 182 Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(Context.getCur())); |
| 182 (VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()))) { | 183 VarSizeOp = (Cur == nullptr) |
| 183 HasLocals = true; | 184 ? nullptr |
| 185 : llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()); |
| 186 if (Cur == nullptr || VarSizeOp == nullptr) { |
| 187 Context.advanceCur(); |
| 188 Context.advanceNext(); |
| 189 continue; |
| 190 } |
| 191 |
| 192 Cur->setDeleted(); |
| 193 |
| 194 if (PoisonVals.empty()) { |
| 195 // insert leftmost redzone |
| 196 auto *LastRzVar = Func->makeVariable(IceType_i32); |
| 197 LastRzVar->setName(Func, nextRzName()); |
| 198 auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, RzSize); |
| 199 constexpr SizeT Alignment = 8; |
| 200 NewAllocas.emplace_back( |
| 201 InstAlloca::create(Func, LastRzVar, ByteCount, Alignment)); |
| 202 PoisonVals.emplace_back(Entry{RzSize >> ShadowScaleLog2, StackPoisonVal}); |
| 203 |
| 204 // Calculate starting address for poisoning |
| 205 FirstShadowLocVar = Func->makeVariable(IceType_i32); |
| 206 FirstShadowLocVar->setName(Func, "firstShadowLoc"); |
| 207 auto *ShadowIndexVar = Func->makeVariable(IceType_i32); |
| 208 ShadowIndexVar->setName(Func, "shadowIndex"); |
| 209 |
| 210 auto *ShadowScaleLog2Const = |
| 211 ConstantInteger32::create(Ctx, IceType_i32, ShadowScaleLog2); |
| 212 auto *ShadowMemLocConst = |
| 213 ConstantInteger32::create(Ctx, IceType_i32, ShadowLength32); |
| 214 |
| 215 ShadowIndexCalc = |
| 216 InstArithmetic::create(Func, InstArithmetic::Lshr, ShadowIndexVar, |
| 217 LastRzVar, ShadowScaleLog2Const); |
| 218 ShadowLocCalc = |
| 219 InstArithmetic::create(Func, InstArithmetic::Add, FirstShadowLocVar, |
| 220 ShadowIndexVar, ShadowMemLocConst); |
| 221 } |
| 184 | 222 |
| 185 // create the new alloca that includes a redzone | 223 // create the new alloca that includes a redzone |
| 186 SizeT VarSize = VarSizeOp->getValue(); | 224 SizeT VarSize = VarSizeOp->getValue(); |
| 187 Variable *Dest = Cur->getDest(); | 225 Variable *Dest = Cur->getDest(); |
| 188 ICE_TLS_GET_FIELD(LocalVars)->insert({Dest, VarSize}); | 226 ICE_TLS_GET_FIELD(LocalVars)->insert({Dest, VarSize}); |
| 189 SizeT RzPadding = RzSize + Utils::OffsetToAlignment(VarSize, RzSize); | 227 SizeT RzPadding = RzSize + Utils::OffsetToAlignment(VarSize, RzSize); |
| 190 auto *ByteCount = | 228 auto *ByteCount = |
| 191 ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding); | 229 ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding); |
| 192 constexpr SizeT Alignment = 8; | 230 constexpr SizeT Alignment = 8; |
| 193 auto *NewVar = InstAlloca::create(Func, Dest, ByteCount, Alignment); | 231 NewAllocas.emplace_back( |
| 232 InstAlloca::create(Func, Dest, ByteCount, Alignment)); |
| 194 | 233 |
| 195 // calculate the redzone offset | 234 const SizeT Zeros = VarSize >> ShadowScaleLog2; |
| 196 Variable *RzLocVar = Func->makeVariable(IceType_i32); | 235 const SizeT Offset = VarSize % ShadowScale; |
| 197 RzLocVar->setName(Func, nextRzName()); | 236 const SizeT PoisonBytes = |
| 198 auto *Offset = ConstantInteger32::create(Ctx, IceType_i32, VarSize); | 237 ((VarSize + RzPadding) >> ShadowScaleLog2) - Zeros - 1; |
| 199 auto *RzLoc = InstArithmetic::create(Func, InstArithmetic::Add, RzLocVar, | 238 if (Zeros > 0) |
| 200 Dest, Offset); | 239 PoisonVals.emplace_back(Entry{Zeros, 0}); |
| 201 | 240 PoisonVals.emplace_back(Entry{1, (Offset == 0) ? StackPoisonVal : Offset}); |
| 202 // instructions to poison and unpoison the redzone | 241 PoisonVals.emplace_back(Entry{PoisonBytes, StackPoisonVal}); |
| 203 constexpr SizeT NumArgs = 2; | 242 Context.advanceCur(); |
| 204 constexpr Variable *Void = nullptr; | 243 Context.advanceNext(); |
| 205 constexpr bool NoTailcall = false; | |
| 206 auto *RzSizeConst = ConstantInteger32::create(Ctx, IceType_i32, RzPadding); | |
| 207 auto *RzPoisonConst = | |
| 208 ConstantInteger32::create(Ctx, IceType_i32, RzStackPoison); | |
| 209 auto *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall); | |
| 210 Init->addArg(RzLocVar); | |
| 211 Init->addArg(RzSizeConst); | |
| 212 Init->addArg(RzPoisonConst); | |
| 213 auto *Destroy = | |
| 214 InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall); | |
| 215 Destroy->addArg(RzLocVar); | |
| 216 Destroy->addArg(RzSizeConst); | |
| 217 Cur->setDeleted(); | |
| 218 C.insert(NewVar); | |
| 219 ICE_TLS_GET_FIELD(LocalDtors)->emplace_back(Destroy); | |
| 220 Initializations.emplace_back(RzLoc); | |
| 221 Initializations.emplace_back(Init); | |
| 222 | |
| 223 C.advanceCur(); | |
| 224 C.advanceNext(); | |
| 225 } | 244 } |
| 226 | 245 |
| 227 C.setInsertPoint(C.getCur()); | 246 Context.rewind(); |
| 247 if (PoisonVals.empty()) { |
| 248 Context.advanceNext(); |
| 249 return; |
| 250 } |
| 251 for (InstAlloca *RzAlloca : NewAllocas) { |
| 252 Context.insert(RzAlloca); |
| 253 } |
| 254 Context.insert(ShadowIndexCalc); |
| 255 Context.insert(ShadowLocCalc); |
| 228 | 256 |
| 229 // add the leftmost redzone | 257 // Poison redzones |
| 230 if (HasLocals) { | 258 std::vector<Entry>::iterator Iter = PoisonVals.begin(); |
| 231 Variable *LastRz = Func->makeVariable(IceType_i32); | 259 for (SizeT Offset = 0; Iter != PoisonVals.end(); Offset += BytesPerWord) { |
| 232 LastRz->setName(Func, nextRzName()); | 260 int32_t CurVals[BytesPerWord] = {0}; |
| 233 auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, RzSize); | 261 for (uint32_t i = 0; i < BytesPerWord; ++i) { |
| 234 constexpr SizeT Alignment = 8; | 262 if (Iter == PoisonVals.end()) |
| 235 auto *RzAlloca = InstAlloca::create(Func, LastRz, ByteCount, Alignment); | 263 break; |
| 236 | 264 Entry Val = *Iter; |
| 237 constexpr SizeT NumArgs = 2; | 265 CurVals[i] = Val.second; |
| 238 constexpr Variable *Void = nullptr; | 266 --Val.first; |
| 239 constexpr bool NoTailcall = false; | 267 if (Val.first > 0) |
| 240 auto *RzPoisonConst = | 268 *Iter = Val; |
| 241 ConstantInteger32::create(Ctx, IceType_i32, RzStackPoison); | 269 else |
| 242 auto *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall); | 270 ++Iter; |
| 243 Init->addArg(LastRz); | 271 } |
| 244 Init->addArg(RzAlloca->getSizeInBytes()); | 272 int32_t Poison = ((CurVals[3] & 0xff) << 24) | ((CurVals[2] & 0xff) << 16) | |
| 245 Init->addArg(RzPoisonConst); | 273 ((CurVals[1] & 0xff) << 8) | (CurVals[0] & 0xff); |
| 246 auto *Destroy = | 274 if (Poison == 0) |
| 247 InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall); | 275 continue; |
| 248 Destroy->addArg(LastRz); | 276 auto *PoisonConst = ConstantInteger32::create(Ctx, IceType_i32, Poison); |
| 249 Destroy->addArg(RzAlloca->getSizeInBytes()); | 277 auto *ZeroConst = ConstantInteger32::create(Ctx, IceType_i32, 0); |
| 250 ICE_TLS_GET_FIELD(LocalDtors)->emplace_back(Destroy); | 278 auto *OffsetConst = ConstantInteger32::create(Ctx, IceType_i32, Offset); |
| 251 C.insert(RzAlloca); | 279 auto *PoisonAddrVar = Func->makeVariable(IceType_i32); |
| 252 C.insert(Init); | 280 Context.insert(InstArithmetic::create(Func, InstArithmetic::Add, |
| 281 PoisonAddrVar, FirstShadowLocVar, |
| 282 OffsetConst)); |
| 283 Context.insert(InstStore::create(Func, PoisonConst, PoisonAddrVar)); |
| 284 ICE_TLS_GET_FIELD(LocalDtors) |
| 285 ->emplace_back(InstStore::create(Func, ZeroConst, PoisonAddrVar)); |
| 253 } | 286 } |
| 254 | 287 Context.advanceNext(); |
| 255 // insert initializers for the redzones | |
| 256 for (Inst *Init : Initializations) { | |
| 257 C.insert(Init); | |
| 258 } | |
| 259 } | 288 } |
| 260 | 289 |
| 261 void ASanInstrumentation::instrumentCall(LoweringContext &Context, | 290 void ASanInstrumentation::instrumentCall(LoweringContext &Context, |
| 262 InstCall *Instr) { | 291 InstCall *Instr) { |
| 263 auto *CallTarget = | 292 auto *CallTarget = |
| 264 llvm::dyn_cast<ConstantRelocatable>(Instr->getCallTarget()); | 293 llvm::dyn_cast<ConstantRelocatable>(Instr->getCallTarget()); |
| 265 if (CallTarget == nullptr) | 294 if (CallTarget == nullptr) |
| 266 return; | 295 return; |
| 267 | 296 |
| 268 std::string TargetName = CallTarget->getName().toStringOrEmpty(); | 297 std::string TargetName = CallTarget->getName().toStringOrEmpty(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Op); | 354 auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Op); |
| 326 if (Reloc == nullptr) | 355 if (Reloc == nullptr) |
| 327 return false; | 356 return false; |
| 328 RelocOffsetT Offset = Reloc->getOffset(); | 357 RelocOffsetT Offset = Reloc->getOffset(); |
| 329 GlobalSizeMap::iterator GlobalSize = GlobalSizes.find(Reloc->getName()); | 358 GlobalSizeMap::iterator GlobalSize = GlobalSizes.find(Reloc->getName()); |
| 330 return GlobalSize != GlobalSizes.end() && GlobalSize->second - Offset >= Size; | 359 return GlobalSize != GlobalSizes.end() && GlobalSize->second - Offset >= Size; |
| 331 } | 360 } |
| 332 | 361 |
| 333 void ASanInstrumentation::instrumentRet(LoweringContext &Context, InstRet *) { | 362 void ASanInstrumentation::instrumentRet(LoweringContext &Context, InstRet *) { |
| 334 Cfg *Func = Context.getNode()->getCfg(); | 363 Cfg *Func = Context.getNode()->getCfg(); |
| 335 InstList::iterator Next = Context.getNext(); | |
| 336 Context.setInsertPoint(Context.getCur()); | 364 Context.setInsertPoint(Context.getCur()); |
| 337 for (InstCall *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) { | 365 for (InstStore *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) { |
| 338 SizeT NumArgs = RzUnpoison->getNumArgs(); | 366 Context.insert( |
| 339 Variable *Dest = RzUnpoison->getDest(); | 367 InstStore::create(Func, RzUnpoison->getData(), RzUnpoison->getAddr())); |
| 340 Operand *CallTarget = RzUnpoison->getCallTarget(); | |
| 341 bool HasTailCall = RzUnpoison->isTailcall(); | |
| 342 bool IsTargetHelperCall = RzUnpoison->isTargetHelperCall(); | |
| 343 auto *RzUnpoisonCpy = InstCall::create(Func, NumArgs, Dest, CallTarget, | |
| 344 HasTailCall, IsTargetHelperCall); | |
| 345 for (int I = 0, Args = RzUnpoison->getNumArgs(); I < Args; ++I) { | |
| 346 RzUnpoisonCpy->addArg(RzUnpoison->getArg(I)); | |
| 347 } | |
| 348 Context.insert(RzUnpoisonCpy); | |
| 349 } | 368 } |
| 350 Context.setNext(Next); | 369 Context.advanceCur(); |
| 370 Context.advanceNext(); |
| 351 } | 371 } |
| 352 | 372 |
| 353 void ASanInstrumentation::instrumentStart(Cfg *Func) { | 373 void ASanInstrumentation::instrumentStart(Cfg *Func) { |
| 354 Constant *ShadowMemInit = | 374 Constant *ShadowMemInit = |
| 355 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_init")); | 375 Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_init")); |
| 356 constexpr SizeT NumArgs = 3; | 376 constexpr SizeT NumArgs = 3; |
| 357 constexpr Variable *Void = nullptr; | 377 constexpr Variable *Void = nullptr; |
| 358 constexpr bool NoTailCall = false; | 378 constexpr bool NoTailCall = false; |
| 359 auto *Call = InstCall::create(Func, NumArgs, Void, ShadowMemInit, NoTailCall); | 379 auto *Call = InstCall::create(Func, NumArgs, Void, ShadowMemInit, NoTailCall); |
| 360 Func->getEntryNode()->getInsts().push_front(Call); | 380 Func->getEntryNode()->getInsts().push_front(Call); |
| 361 | 381 |
| 362 instrumentGlobals(*getGlobals()); | 382 instrumentGlobals(*getGlobals()); |
| 363 | 383 |
| 364 Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, RzGlobalsNum)); | 384 Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, RzGlobalsNum)); |
| 365 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzArrayName))); | 385 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzArrayName))); |
| 366 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzSizesName))); | 386 Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzSizesName))); |
| 367 } | 387 } |
| 368 | 388 |
| 369 // TODO(tlively): make this more efficient with swap idiom | 389 // TODO(tlively): make this more efficient with swap idiom |
| 370 void ASanInstrumentation::finishFunc(Cfg *) { | 390 void ASanInstrumentation::finishFunc(Cfg *) { |
| 371 ICE_TLS_GET_FIELD(LocalVars)->clear(); | 391 ICE_TLS_GET_FIELD(LocalVars)->clear(); |
| 372 ICE_TLS_GET_FIELD(LocalDtors)->clear(); | 392 ICE_TLS_GET_FIELD(LocalDtors)->clear(); |
| 373 } | 393 } |
| 374 | 394 |
| 375 } // end of namespace Ice | 395 } // end of namespace Ice |
| OLD | NEW |