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