13f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively//===- subzero/src/IceASanInstrumentation.cpp - ASan ------------*- C++ -*-===// 23f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// 33f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// The Subzero Code Generator 43f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// 53f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// This file is distributed under the University of Illinois Open Source 63f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// License. See LICENSE.TXT for details. 73f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// 83f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively//===----------------------------------------------------------------------===// 93f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively/// 103f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively/// \file 113f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively/// \brief Implements the AddressSanitizer instrumentation class. 123f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively/// 133f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively//===----------------------------------------------------------------------===// 143f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 153f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively#include "IceASanInstrumentation.h" 163f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 173f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively#include "IceBuildDefs.h" 18227c9f39303e6357adcfeb4b94a905681f3616f0Thomas Lively#include "IceCfg.h" 194e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively#include "IceCfgNode.h" 203f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively#include "IceGlobalInits.h" 214e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively#include "IceInst.h" 22bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively#include "IceTargetLowering.h" 23bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively#include "IceTypes.h" 243f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 253f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively#include <sstream> 2626c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively#include <unordered_map> 273f97afb1675218f1a4cd7f30fc4faa86fcbeea03Thomas Lively#include <unordered_set> 281fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively#include <vector> 293f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 303f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Livelynamespace Ice { 313f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 323f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Livelynamespace { 331fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively 34cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Livelyconstexpr SizeT BytesPerWord = sizeof(uint32_t); 353f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Livelyconstexpr SizeT RzSize = 32; 36cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Livelyconstexpr SizeT ShadowScaleLog2 = 3; 37cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Livelyconstexpr SizeT ShadowScale = 1 << ShadowScaleLog2; 38cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Livelyconstexpr SizeT ShadowLength32 = 1 << (32 - ShadowScaleLog2); 39cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Livelyconstexpr int32_t StackPoisonVal = -1; 40cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Livelyconstexpr const char *ASanPrefix = "__asan"; 41aedc5e49ded4595d723b09ee31a16884ced06680Thomas Livelyconstexpr const char *RzPrefix = "__$rz"; 42aedc5e49ded4595d723b09ee31a16884ced06680Thomas Livelyconstexpr const char *RzArrayName = "__$rz_array"; 43aedc5e49ded4595d723b09ee31a16884ced06680Thomas Livelyconstexpr const char *RzSizesName = "__$rz_sizes"; 443f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Livelyconst llvm::NaClBitcodeRecord::RecordVector RzContents = 453f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively llvm::NaClBitcodeRecord::RecordVector(RzSize, 'R'); 4626c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively 4726c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively// In order to instrument the code correctly, the .pexe must not have had its 4826c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively// symbols stripped. 49ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Livelyusing StringMap = std::unordered_map<std::string, std::string>; 50ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Livelyusing StringSet = std::unordered_set<std::string>; 513f97afb1675218f1a4cd7f30fc4faa86fcbeea03Thomas Lively// TODO(tlively): Handle all allocation functions 52ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Livelyconst StringMap FuncSubstitutions = {{"malloc", "__asan_malloc"}, 53ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively {"free", "__asan_free"}, 54ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively {"calloc", "__asan_calloc"}, 55ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively {"__asan_dummy_calloc", "__asan_calloc"}, 56ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively {"realloc", "__asan_realloc"}}; 57ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Livelyconst StringSet FuncBlackList = {"_Balloc"}; 5826c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively 59aedc5e49ded4595d723b09ee31a16884ced06680Thomas Livelyllvm::NaClBitcodeRecord::RecordVector sizeToByteVec(SizeT Size) { 60aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively llvm::NaClBitcodeRecord::RecordVector SizeContents; 61aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively for (unsigned i = 0; i < sizeof(Size); ++i) { 62aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively SizeContents.emplace_back(Size % (1 << CHAR_BIT)); 63aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively Size >>= CHAR_BIT; 64aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively } 65aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively return SizeContents; 66aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively} 67aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively 683f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively} // end of anonymous namespace 693f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 70ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas LivelyICE_TLS_DEFINE_FIELD(VarSizeMap *, ASanInstrumentation, LocalVars); 71cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas LivelyICE_TLS_DEFINE_FIELD(std::vector<InstStore *> *, ASanInstrumentation, 721fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively LocalDtors); 739b384977448d4396028b342ed96c490c1a69c391Thomas LivelyICE_TLS_DEFINE_FIELD(CfgNode *, ASanInstrumentation, CurNode); 749b384977448d4396028b342ed96c490c1a69c391Thomas LivelyICE_TLS_DEFINE_FIELD(VarSizeMap *, ASanInstrumentation, CheckedVars); 751fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively 763f97afb1675218f1a4cd7f30fc4faa86fcbeea03Thomas Livelybool ASanInstrumentation::isInstrumentable(Cfg *Func) { 773f97afb1675218f1a4cd7f30fc4faa86fcbeea03Thomas Lively std::string FuncName = Func->getFunctionName().toStringOrEmpty(); 78f6c41e46ac899f3bf606dd824890eeedefa81750Thomas Lively return FuncName == "" || 79f6c41e46ac899f3bf606dd824890eeedefa81750Thomas Lively (FuncBlackList.count(FuncName) == 0 && FuncName.find(ASanPrefix) != 0); 803f97afb1675218f1a4cd7f30fc4faa86fcbeea03Thomas Lively} 813f97afb1675218f1a4cd7f30fc4faa86fcbeea03Thomas Lively 827f0ab86035da401f95a9a255b95d6e5a59bbcbe3Thomas Lively// Create redzones around all global variables, ensuring that the initializer 833f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// types of the redzones and their associated globals match so that they are 843f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively// laid out together in memory. 853f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Livelyvoid ASanInstrumentation::instrumentGlobals(VariableDeclarationList &Globals) { 862c9992a596475c09234ee69e66b5ae715ca33124Thomas Lively std::unique_lock<std::mutex> _(GlobalsMutex); 87aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively if (DidProcessGlobals) 883f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively return; 893f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively VariableDeclarationList NewGlobals; 903f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively // Global holding pointers to all redzones 913f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively auto *RzArray = VariableDeclaration::create(&NewGlobals); 92aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively // Global holding sizes of all redzones 93aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively auto *RzSizes = VariableDeclaration::create(&NewGlobals); 943f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 95aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzArray->setName(Ctx, RzArrayName); 96aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzSizes->setName(Ctx, RzSizesName); 973f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively RzArray->setIsConstant(true); 98aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzSizes->setIsConstant(true); 993f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively NewGlobals.push_back(RzArray); 100aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively NewGlobals.push_back(RzSizes); 1013f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 1029a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively using PrototypeMap = std::unordered_map<std::string, FunctionDeclaration *>; 1039a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively PrototypeMap ProtoSubstitutions; 1043f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively for (VariableDeclaration *Global : Globals) { 105aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively assert(Global->getAlignment() <= RzSize); 106aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively VariableDeclaration *RzLeft = VariableDeclaration::create(&NewGlobals); 1079a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively VariableDeclaration *NewGlobal = Global; 108aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively VariableDeclaration *RzRight = VariableDeclaration::create(&NewGlobals); 109aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzLeft->setName(Ctx, nextRzName()); 110aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzRight->setName(Ctx, nextRzName()); 111aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively SizeT Alignment = std::max(RzSize, Global->getAlignment()); 112aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively SizeT RzLeftSize = Alignment; 113aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively SizeT RzRightSize = 114aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzSize + Utils::OffsetToAlignment(Global->getNumBytes(), Alignment); 1159a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively if (!Global->hasNonzeroInitializer()) { 1169a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively RzLeft->addInitializer(VariableDeclaration::ZeroInitializer::create( 1179a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively &NewGlobals, RzLeftSize)); 1189a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively RzRight->addInitializer(VariableDeclaration::ZeroInitializer::create( 1199a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively &NewGlobals, RzRightSize)); 1209a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively } else { 121aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzLeft->addInitializer(VariableDeclaration::DataInitializer::create( 122aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively &NewGlobals, llvm::NaClBitcodeRecord::RecordVector(RzLeftSize, 'R'))); 123aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzRight->addInitializer(VariableDeclaration::DataInitializer::create( 124aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively &NewGlobals, 125aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively llvm::NaClBitcodeRecord::RecordVector(RzRightSize, 'R'))); 1269a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively 1279a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively // replace any pointers to allocator functions 1289a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal = VariableDeclaration::create(&NewGlobals); 1299a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal->setName(Global->getName()); 1309a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively std::vector<VariableDeclaration::Initializer *> GlobalInits = 1319a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively Global->getInitializers(); 1329a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively for (VariableDeclaration::Initializer *Init : GlobalInits) { 1339a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively auto *RelocInit = 1349a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively llvm::dyn_cast<VariableDeclaration::RelocInitializer>(Init); 1359a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively if (RelocInit == nullptr) { 1369a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal->addInitializer(Init); 1379a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively continue; 1389a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively } 1399a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively const GlobalDeclaration *TargetDecl = RelocInit->getDeclaration(); 1409a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively const auto *TargetFunc = 1419a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively llvm::dyn_cast<FunctionDeclaration>(TargetDecl); 1429a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively if (TargetFunc == nullptr) { 1439a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal->addInitializer(Init); 1449a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively continue; 1459a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively } 1469a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively std::string TargetName = TargetDecl->getName().toStringOrEmpty(); 1479a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively StringMap::const_iterator Subst = FuncSubstitutions.find(TargetName); 1489a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively if (Subst == FuncSubstitutions.end()) { 1499a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal->addInitializer(Init); 1509a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively continue; 1519a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively } 1529a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively std::string SubstName = Subst->second; 1539a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively PrototypeMap::iterator SubstProtoEntry = 1549a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively ProtoSubstitutions.find(SubstName); 1559a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively FunctionDeclaration *SubstProto; 1569a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively if (SubstProtoEntry != ProtoSubstitutions.end()) 1579a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively SubstProto = SubstProtoEntry->second; 1589a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively else { 1599a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively constexpr bool IsProto = true; 1609a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively SubstProto = FunctionDeclaration::create( 1619a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively Ctx, TargetFunc->getSignature(), TargetFunc->getCallingConv(), 1629a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively llvm::GlobalValue::ExternalLinkage, IsProto); 1639a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively SubstProto->setName(Ctx, SubstName); 1649a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively ProtoSubstitutions.insert({SubstName, SubstProto}); 1659a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively } 1669a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively 1679a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal->addInitializer(VariableDeclaration::RelocInitializer::create( 1689a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively &NewGlobals, SubstProto, RelocOffsetArray(0))); 1699a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively } 170aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively } 1719a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively 172aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzLeft->setIsConstant(Global->getIsConstant()); 1739a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal->setIsConstant(Global->getIsConstant()); 174aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzRight->setIsConstant(Global->getIsConstant()); 175aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzLeft->setAlignment(Alignment); 1769a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobal->setAlignment(Alignment); 177aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzRight->setAlignment(1); 178aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzArray->addInitializer(VariableDeclaration::RelocInitializer::create( 179aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively &NewGlobals, RzLeft, RelocOffsetArray(0))); 180aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzArray->addInitializer(VariableDeclaration::RelocInitializer::create( 181aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively &NewGlobals, RzRight, RelocOffsetArray(0))); 182aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzSizes->addInitializer(VariableDeclaration::DataInitializer::create( 183aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively &NewGlobals, sizeToByteVec(RzLeftSize))); 184aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzSizes->addInitializer(VariableDeclaration::DataInitializer::create( 185aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively &NewGlobals, sizeToByteVec(RzRightSize))); 186aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively 1873f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively NewGlobals.push_back(RzLeft); 1889a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively NewGlobals.push_back(NewGlobal); 1893f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively NewGlobals.push_back(RzRight); 190aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively RzGlobalsNum += 2; 191181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively 1929a313a8d09d1c7fa4c499fdc14fa3ef1332896d6Thomas Lively GlobalSizes.insert({NewGlobal->getName(), NewGlobal->getNumBytes()}); 1933f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively } 1943f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 1953f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively // Replace old list of globals, without messing up arena allocators 1963f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively Globals.clear(); 1973f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively Globals.merge(&NewGlobals); 198aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively DidProcessGlobals = true; 1993f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 2003f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively // Log the new set of globals 2013f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_GlobalInit)) { 2023f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively OstreamLocker _(Ctx); 2033f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively Ctx->getStrDump() << "========= Instrumented Globals =========\n"; 2043f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively for (VariableDeclaration *Global : Globals) { 2053f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively Global->dump(Ctx->getStrDump()); 2063f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively } 2073f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively } 2083f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively} 2093f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 2103f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Livelystd::string ASanInstrumentation::nextRzName() { 2113f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively std::stringstream Name; 2123f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively Name << RzPrefix << RzNum++; 2133f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively return Name.str(); 2143f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively} 2153f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively 216227c9f39303e6357adcfeb4b94a905681f3616f0Thomas Lively// Check for an alloca signaling the presence of local variables and add a 217227c9f39303e6357adcfeb4b94a905681f3616f0Thomas Lively// redzone if it is found 218227c9f39303e6357adcfeb4b94a905681f3616f0Thomas Livelyvoid ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) { 219ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) { 220cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstStore *>()); 221ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively ICE_TLS_SET_FIELD(LocalVars, new VarSizeMap()); 222ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively } 2231fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively Cfg *Func = Context.getNode()->getCfg(); 224cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively using Entry = std::pair<SizeT, int32_t>; 225cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively std::vector<InstAlloca *> NewAllocas; 226cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively std::vector<Entry> PoisonVals; 227cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Variable *FirstShadowLocVar; 228cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively InstArithmetic *ShadowIndexCalc; 229cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively InstArithmetic *ShadowLocCalc; 2301fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively InstAlloca *Cur; 2311fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively ConstantInteger32 *VarSizeOp; 232cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively while (!Context.atEnd()) { 233cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(Context.getCur())); 234cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively VarSizeOp = (Cur == nullptr) 235cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ? nullptr 236cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively : llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()); 237cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively if (Cur == nullptr || VarSizeOp == nullptr) { 238cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceCur(); 239cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceNext(); 240cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively continue; 241cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively } 242cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively 243cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Cur->setDeleted(); 244cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively 245cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively if (PoisonVals.empty()) { 246cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively // insert leftmost redzone 247cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *LastRzVar = Func->makeVariable(IceType_i32); 248cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively LastRzVar->setName(Func, nextRzName()); 249cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, RzSize); 250cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively constexpr SizeT Alignment = 8; 251cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively NewAllocas.emplace_back( 252cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively InstAlloca::create(Func, LastRzVar, ByteCount, Alignment)); 253cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively PoisonVals.emplace_back(Entry{RzSize >> ShadowScaleLog2, StackPoisonVal}); 254cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively 255cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively // Calculate starting address for poisoning 256cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively FirstShadowLocVar = Func->makeVariable(IceType_i32); 257cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively FirstShadowLocVar->setName(Func, "firstShadowLoc"); 258cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *ShadowIndexVar = Func->makeVariable(IceType_i32); 259cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ShadowIndexVar->setName(Func, "shadowIndex"); 260cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively 261cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *ShadowScaleLog2Const = 262cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ConstantInteger32::create(Ctx, IceType_i32, ShadowScaleLog2); 263cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *ShadowMemLocConst = 264cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ConstantInteger32::create(Ctx, IceType_i32, ShadowLength32); 265cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively 266cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ShadowIndexCalc = 267cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively InstArithmetic::create(Func, InstArithmetic::Lshr, ShadowIndexVar, 268cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively LastRzVar, ShadowScaleLog2Const); 269cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ShadowLocCalc = 270cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively InstArithmetic::create(Func, InstArithmetic::Add, FirstShadowLocVar, 271cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ShadowIndexVar, ShadowMemLocConst); 272cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively } 273227c9f39303e6357adcfeb4b94a905681f3616f0Thomas Lively 2741fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively // create the new alloca that includes a redzone 2751fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively SizeT VarSize = VarSizeOp->getValue(); 2761fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively Variable *Dest = Cur->getDest(); 277ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively ICE_TLS_GET_FIELD(LocalVars)->insert({Dest, VarSize}); 2781fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively SizeT RzPadding = RzSize + Utils::OffsetToAlignment(VarSize, RzSize); 2791fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively auto *ByteCount = 2801fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding); 2811fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively constexpr SizeT Alignment = 8; 282cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively NewAllocas.emplace_back( 283cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively InstAlloca::create(Func, Dest, ByteCount, Alignment)); 284cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively 285cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively const SizeT Zeros = VarSize >> ShadowScaleLog2; 286cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively const SizeT Offset = VarSize % ShadowScale; 287cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively const SizeT PoisonBytes = 288cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ((VarSize + RzPadding) >> ShadowScaleLog2) - Zeros - 1; 289cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively if (Zeros > 0) 290cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively PoisonVals.emplace_back(Entry{Zeros, 0}); 291cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively PoisonVals.emplace_back(Entry{1, (Offset == 0) ? StackPoisonVal : Offset}); 292cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively PoisonVals.emplace_back(Entry{PoisonBytes, StackPoisonVal}); 293cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceCur(); 294cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceNext(); 2951fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively } 2961fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively 297cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.rewind(); 298cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively if (PoisonVals.empty()) { 299cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceNext(); 300cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively return; 3011fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively } 302cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively for (InstAlloca *RzAlloca : NewAllocas) { 303cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.insert(RzAlloca); 3041fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively } 305cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.insert(ShadowIndexCalc); 306cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.insert(ShadowLocCalc); 307cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively 308cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively // Poison redzones 309cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively std::vector<Entry>::iterator Iter = PoisonVals.begin(); 310cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively for (SizeT Offset = 0; Iter != PoisonVals.end(); Offset += BytesPerWord) { 311cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively int32_t CurVals[BytesPerWord] = {0}; 312cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively for (uint32_t i = 0; i < BytesPerWord; ++i) { 313cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively if (Iter == PoisonVals.end()) 314cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively break; 315cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Entry Val = *Iter; 316cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively CurVals[i] = Val.second; 317cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively --Val.first; 318cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively if (Val.first > 0) 319cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively *Iter = Val; 320cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively else 321cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ++Iter; 322cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively } 323cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively int32_t Poison = ((CurVals[3] & 0xff) << 24) | ((CurVals[2] & 0xff) << 16) | 324cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ((CurVals[1] & 0xff) << 8) | (CurVals[0] & 0xff); 325cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively if (Poison == 0) 326cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively continue; 327cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *PoisonConst = ConstantInteger32::create(Ctx, IceType_i32, Poison); 328cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *ZeroConst = ConstantInteger32::create(Ctx, IceType_i32, 0); 329cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *OffsetConst = ConstantInteger32::create(Ctx, IceType_i32, Offset); 330cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively auto *PoisonAddrVar = Func->makeVariable(IceType_i32); 331cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.insert(InstArithmetic::create(Func, InstArithmetic::Add, 332cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively PoisonAddrVar, FirstShadowLocVar, 333cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively OffsetConst)); 334cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.insert(InstStore::create(Func, PoisonConst, PoisonAddrVar)); 335cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ICE_TLS_GET_FIELD(LocalDtors) 336cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively ->emplace_back(InstStore::create(Func, ZeroConst, PoisonAddrVar)); 337cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively } 338cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceNext(); 339227c9f39303e6357adcfeb4b94a905681f3616f0Thomas Lively} 340227c9f39303e6357adcfeb4b94a905681f3616f0Thomas Lively 34126c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Livelyvoid ASanInstrumentation::instrumentCall(LoweringContext &Context, 34226c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively InstCall *Instr) { 34326c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively auto *CallTarget = 34426c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively llvm::dyn_cast<ConstantRelocatable>(Instr->getCallTarget()); 34526c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively if (CallTarget == nullptr) 34626c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively return; 34726c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively 34826c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively std::string TargetName = CallTarget->getName().toStringOrEmpty(); 34926c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively auto Subst = FuncSubstitutions.find(TargetName); 35026c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively if (Subst == FuncSubstitutions.end()) 35126c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively return; 35226c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively 35326c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively std::string SubName = Subst->second; 35426c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively Constant *NewFunc = Ctx->getConstantExternSym(Ctx->getGlobalString(SubName)); 35526c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively auto *NewCall = 35626c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively InstCall::create(Context.getNode()->getCfg(), Instr->getNumArgs(), 35726c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively Instr->getDest(), NewFunc, Instr->isTailcall()); 35826c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively for (SizeT I = 0, Args = Instr->getNumArgs(); I < Args; ++I) 35926c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively NewCall->addArg(Instr->getArg(I)); 36026c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively Context.insert(NewCall); 36126c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively Instr->setDeleted(); 36226c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively} 36326c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively 364bdb912f4fccc8f8710d219277fee342a897427c8Thomas Livelyvoid ASanInstrumentation::instrumentLoad(LoweringContext &Context, 36526c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively InstLoad *Instr) { 36648a568dbe65cd74ba688e7398f6f1f50450abfbeThomas Lively Operand *Src = Instr->getSourceAddress(); 36748a568dbe65cd74ba688e7398f6f1f50450abfbeThomas Lively if (auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { 36875f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively auto *NewLoad = InstLoad::create(Context.getNode()->getCfg(), 36975f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Instr->getDest(), instrumentReloc(Reloc)); 37075f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Instr->setDeleted(); 37175f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Context.insert(NewLoad); 37275f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Instr = NewLoad; 37348a568dbe65cd74ba688e7398f6f1f50450abfbeThomas Lively } 374cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively Constant *Func = 375cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_check_load")); 37626c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively instrumentAccess(Context, Instr->getSourceAddress(), 377cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively typeWidthInBytes(Instr->getDest()->getType()), Func); 378bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively} 379bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively 380bdb912f4fccc8f8710d219277fee342a897427c8Thomas Livelyvoid ASanInstrumentation::instrumentStore(LoweringContext &Context, 38126c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively InstStore *Instr) { 38275f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Operand *Data = Instr->getData(); 38375f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively if (auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Data)) { 38475f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively auto *NewStore = InstStore::create( 38575f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Context.getNode()->getCfg(), instrumentReloc(Reloc), Instr->getAddr()); 38675f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Instr->setDeleted(); 38775f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Context.insert(NewStore); 38875f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Instr = NewStore; 38975f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively } 390cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively Constant *Func = 391cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_check_store")); 39226c43064eccd7b238a97adf8c1e824cc4f2db4eaThomas Lively instrumentAccess(Context, Instr->getAddr(), 393cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively typeWidthInBytes(Instr->getData()->getType()), Func); 394bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively} 395bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively 39675f5229f8b4ac3985f4e31d0402e01510b065720Thomas LivelyConstantRelocatable * 39775f5229f8b4ac3985f4e31d0402e01510b065720Thomas LivelyASanInstrumentation::instrumentReloc(ConstantRelocatable *Reloc) { 39875f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively std::string DataName = Reloc->getName().toString(); 39975f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively StringMap::const_iterator DataSub = FuncSubstitutions.find(DataName); 40075f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively if (DataSub != FuncSubstitutions.end()) { 40175f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively return ConstantRelocatable::create( 40275f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Ctx, Reloc->getType(), 40375f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively RelocatableTuple(Reloc->getOffset(), RelocOffsetArray(0), 40475f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Ctx->getGlobalString(DataSub->second), 40575f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively Reloc->getEmitString())); 40675f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively } 40775f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively return Reloc; 40875f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively} 40975f5229f8b4ac3985f4e31d0402e01510b065720Thomas Lively 410bdb912f4fccc8f8710d219277fee342a897427c8Thomas Livelyvoid ASanInstrumentation::instrumentAccess(LoweringContext &Context, 411cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively Operand *Op, SizeT Size, 412cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively Constant *CheckFunc) { 4139b384977448d4396028b342ed96c490c1a69c391Thomas Lively // Skip redundant checks within basic blocks 4149b384977448d4396028b342ed96c490c1a69c391Thomas Lively VarSizeMap *Checked = ICE_TLS_GET_FIELD(CheckedVars); 4159b384977448d4396028b342ed96c490c1a69c391Thomas Lively if (ICE_TLS_GET_FIELD(CurNode) != Context.getNode()) { 4169b384977448d4396028b342ed96c490c1a69c391Thomas Lively ICE_TLS_SET_FIELD(CurNode, Context.getNode()); 4179b384977448d4396028b342ed96c490c1a69c391Thomas Lively if (Checked == NULL) { 4189b384977448d4396028b342ed96c490c1a69c391Thomas Lively Checked = new VarSizeMap(); 4199b384977448d4396028b342ed96c490c1a69c391Thomas Lively ICE_TLS_SET_FIELD(CheckedVars, Checked); 4209b384977448d4396028b342ed96c490c1a69c391Thomas Lively } 4219b384977448d4396028b342ed96c490c1a69c391Thomas Lively Checked->clear(); 4229b384977448d4396028b342ed96c490c1a69c391Thomas Lively } 4239b384977448d4396028b342ed96c490c1a69c391Thomas Lively VarSizeMap::iterator PrevCheck = Checked->find(Op); 4249b384977448d4396028b342ed96c490c1a69c391Thomas Lively if (PrevCheck != Checked->end() && PrevCheck->second >= Size) 4259b384977448d4396028b342ed96c490c1a69c391Thomas Lively return; 4269b384977448d4396028b342ed96c490c1a69c391Thomas Lively else 4279b384977448d4396028b342ed96c490c1a69c391Thomas Lively Checked->insert({Op, Size}); 4289b384977448d4396028b342ed96c490c1a69c391Thomas Lively 4299b384977448d4396028b342ed96c490c1a69c391Thomas Lively // check for known good local access 430ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively VarSizeMap::iterator LocalSize = ICE_TLS_GET_FIELD(LocalVars)->find(Op); 431ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively if (LocalSize != ICE_TLS_GET_FIELD(LocalVars)->end() && 432ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively LocalSize->second >= Size) 433ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively return; 434181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively if (isOkGlobalAccess(Op, Size)) 435181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively return; 436bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively constexpr SizeT NumArgs = 2; 437bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively constexpr Variable *Void = nullptr; 438bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively constexpr bool NoTailCall = false; 439bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively auto *Call = InstCall::create(Context.getNode()->getCfg(), NumArgs, Void, 440cf06279931ba91b98fbbd7689353cb6068817497Thomas Lively CheckFunc, NoTailCall); 441bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively Call->addArg(Op); 442bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, Size)); 443bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively // play games to insert the call before the access instruction 444bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively InstList::iterator Next = Context.getNext(); 445bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively Context.setInsertPoint(Context.getCur()); 446bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively Context.insert(Call); 447bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively Context.setNext(Next); 448bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively} 449bdb912f4fccc8f8710d219277fee342a897427c8Thomas Lively 450181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively// TODO(tlively): Trace back load and store addresses to find their real offsets 451181a9bcb55b8d1e22210479e5210852d703855f5Thomas Livelybool ASanInstrumentation::isOkGlobalAccess(Operand *Op, SizeT Size) { 452181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Op); 453181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively if (Reloc == nullptr) 454181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively return false; 455181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively RelocOffsetT Offset = Reloc->getOffset(); 456181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively GlobalSizeMap::iterator GlobalSize = GlobalSizes.find(Reloc->getName()); 457181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively return GlobalSize != GlobalSizes.end() && GlobalSize->second - Offset >= Size; 458181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively} 459181a9bcb55b8d1e22210479e5210852d703855f5Thomas Lively 4601fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Livelyvoid ASanInstrumentation::instrumentRet(LoweringContext &Context, InstRet *) { 461a7e5a951381aeb5390c460b810cd2b01e888ee4aThomas Lively Cfg *Func = Context.getNode()->getCfg(); 4621fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively Context.setInsertPoint(Context.getCur()); 463cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively for (InstStore *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) { 464cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.insert( 465cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively InstStore::create(Func, RzUnpoison->getData(), RzUnpoison->getAddr())); 4661fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively } 467cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceCur(); 468cbd3dbc6f00a7784f523132910cc9adbdfa09bf2Thomas Lively Context.advanceNext(); 4691fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively} 4701fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively 4714e81fe0a5429c103509c8380de8dc7d779f67134Thomas Livelyvoid ASanInstrumentation::instrumentStart(Cfg *Func) { 4724e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively Constant *ShadowMemInit = 4734e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_init")); 474aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively constexpr SizeT NumArgs = 3; 4754e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively constexpr Variable *Void = nullptr; 4764e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively constexpr bool NoTailCall = false; 4774e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively auto *Call = InstCall::create(Func, NumArgs, Void, ShadowMemInit, NoTailCall); 4784e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively Func->getEntryNode()->getInsts().push_front(Call); 479aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively 4802c9992a596475c09234ee69e66b5ae715ca33124Thomas Lively instrumentGlobals(*getGlobals()); 4812c9992a596475c09234ee69e66b5ae715ca33124Thomas Lively 482aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively Call->addArg(ConstantInteger32::create(Ctx, IceType_i32, RzGlobalsNum)); 483aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzArrayName))); 484aedc5e49ded4595d723b09ee31a16884ced06680Thomas Lively Call->addArg(Ctx->getConstantSym(0, Ctx->getGlobalString(RzSizesName))); 4854e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively} 4864e81fe0a5429c103509c8380de8dc7d779f67134Thomas Lively 4871fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively// TODO(tlively): make this more efficient with swap idiom 4883f97afb1675218f1a4cd7f30fc4faa86fcbeea03Thomas Livelyvoid ASanInstrumentation::finishFunc(Cfg *) { 489ac27c516cf0b490a7e06f66acff023cb6ecd3718Thomas Lively ICE_TLS_GET_FIELD(LocalVars)->clear(); 4901fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively ICE_TLS_GET_FIELD(LocalDtors)->clear(); 4911fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively} 4921fd80c722c1a2d4c31d43a0df35ccbd49d9c2b5aThomas Lively 4933f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively} // end of namespace Ice 494