1234285Sdim//===-- AddressSanitizer.cpp - memory error detector ------------*- C++ -*-===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This file is a part of AddressSanitizer, an address sanity checker. 11234285Sdim// Details of the algorithm: 12234285Sdim// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm 13234285Sdim// 14234285Sdim//===----------------------------------------------------------------------===// 15234285Sdim 16234285Sdim#define DEBUG_TYPE "asan" 17234285Sdim 18252723Sdim#include "llvm/Transforms/Instrumentation.h" 19234285Sdim#include "llvm/ADT/ArrayRef.h" 20252723Sdim#include "llvm/ADT/DenseMap.h" 21252723Sdim#include "llvm/ADT/DepthFirstIterator.h" 22234285Sdim#include "llvm/ADT/OwningPtr.h" 23234285Sdim#include "llvm/ADT/SmallSet.h" 24234285Sdim#include "llvm/ADT/SmallString.h" 25234285Sdim#include "llvm/ADT/SmallVector.h" 26263509Sdim#include "llvm/ADT/Statistic.h" 27234285Sdim#include "llvm/ADT/StringExtras.h" 28245431Sdim#include "llvm/ADT/Triple.h" 29252723Sdim#include "llvm/DIBuilder.h" 30252723Sdim#include "llvm/IR/DataLayout.h" 31252723Sdim#include "llvm/IR/Function.h" 32252723Sdim#include "llvm/IR/IRBuilder.h" 33252723Sdim#include "llvm/IR/InlineAsm.h" 34252723Sdim#include "llvm/IR/IntrinsicInst.h" 35252723Sdim#include "llvm/IR/LLVMContext.h" 36252723Sdim#include "llvm/IR/Module.h" 37252723Sdim#include "llvm/IR/Type.h" 38252723Sdim#include "llvm/InstVisitor.h" 39252723Sdim#include "llvm/Support/CallSite.h" 40234285Sdim#include "llvm/Support/CommandLine.h" 41234285Sdim#include "llvm/Support/DataTypes.h" 42234285Sdim#include "llvm/Support/Debug.h" 43263509Sdim#include "llvm/Support/Endian.h" 44234285Sdim#include "llvm/Support/raw_ostream.h" 45234285Sdim#include "llvm/Support/system_error.h" 46234285Sdim#include "llvm/Transforms/Utils/BasicBlockUtils.h" 47263509Sdim#include "llvm/Transforms/Utils/Cloning.h" 48252723Sdim#include "llvm/Transforms/Utils/Local.h" 49234285Sdim#include "llvm/Transforms/Utils/ModuleUtils.h" 50263509Sdim#include "llvm/Transforms/Utils/SpecialCaseList.h" 51252723Sdim#include <algorithm> 52234285Sdim#include <string> 53234285Sdim 54234285Sdimusing namespace llvm; 55234285Sdim 56234285Sdimstatic const uint64_t kDefaultShadowScale = 3; 57234285Sdimstatic const uint64_t kDefaultShadowOffset32 = 1ULL << 29; 58234285Sdimstatic const uint64_t kDefaultShadowOffset64 = 1ULL << 44; 59252723Sdimstatic const uint64_t kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G. 60252723Sdimstatic const uint64_t kPPC64_ShadowOffset64 = 1ULL << 41; 61263509Sdimstatic const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa8000; 62234285Sdim 63263509Sdimstatic const size_t kMinStackMallocSize = 1 << 6; // 64B 64234285Sdimstatic const size_t kMaxStackMallocSize = 1 << 16; // 64K 65234285Sdimstatic const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3; 66234285Sdimstatic const uintptr_t kRetiredStackFrameMagic = 0x45E0360E; 67234285Sdim 68263509Sdimstatic const char *const kAsanModuleCtorName = "asan.module_ctor"; 69263509Sdimstatic const char *const kAsanModuleDtorName = "asan.module_dtor"; 70263509Sdimstatic const int kAsanCtorAndCtorPriority = 1; 71263509Sdimstatic const char *const kAsanReportErrorTemplate = "__asan_report_"; 72263509Sdimstatic const char *const kAsanReportLoadN = "__asan_report_load_n"; 73263509Sdimstatic const char *const kAsanReportStoreN = "__asan_report_store_n"; 74263509Sdimstatic const char *const kAsanRegisterGlobalsName = "__asan_register_globals"; 75263509Sdimstatic const char *const kAsanUnregisterGlobalsName = 76263509Sdim "__asan_unregister_globals"; 77263509Sdimstatic const char *const kAsanPoisonGlobalsName = "__asan_before_dynamic_init"; 78263509Sdimstatic const char *const kAsanUnpoisonGlobalsName = "__asan_after_dynamic_init"; 79263509Sdimstatic const char *const kAsanInitName = "__asan_init_v3"; 80263509Sdimstatic const char *const kAsanCovName = "__sanitizer_cov"; 81263509Sdimstatic const char *const kAsanHandleNoReturnName = "__asan_handle_no_return"; 82263509Sdimstatic const char *const kAsanMappingOffsetName = "__asan_mapping_offset"; 83263509Sdimstatic const char *const kAsanMappingScaleName = "__asan_mapping_scale"; 84263509Sdimstatic const int kMaxAsanStackMallocSizeClass = 10; 85263509Sdimstatic const char *const kAsanStackMallocNameTemplate = "__asan_stack_malloc_"; 86263509Sdimstatic const char *const kAsanStackFreeNameTemplate = "__asan_stack_free_"; 87263509Sdimstatic const char *const kAsanGenPrefix = "__asan_gen_"; 88263509Sdimstatic const char *const kAsanPoisonStackMemoryName = 89263509Sdim "__asan_poison_stack_memory"; 90263509Sdimstatic const char *const kAsanUnpoisonStackMemoryName = 91252723Sdim "__asan_unpoison_stack_memory"; 92234285Sdim 93263509Sdimstatic const char *const kAsanOptionDetectUAR = 94263509Sdim "__asan_option_detect_stack_use_after_return"; 95263509Sdim 96263509Sdim// These constants must match the definitions in the run-time library. 97234285Sdimstatic const int kAsanStackLeftRedzoneMagic = 0xf1; 98234285Sdimstatic const int kAsanStackMidRedzoneMagic = 0xf2; 99234285Sdimstatic const int kAsanStackRightRedzoneMagic = 0xf3; 100234285Sdimstatic const int kAsanStackPartialRedzoneMagic = 0xf4; 101263509Sdim#ifndef NDEBUG 102263509Sdimstatic const int kAsanStackAfterReturnMagic = 0xf5; 103263509Sdim#endif 104234285Sdim 105245431Sdim// Accesses sizes are powers of two: 1, 2, 4, 8, 16. 106245431Sdimstatic const size_t kNumberOfAccessSizes = 5; 107245431Sdim 108234285Sdim// Command-line flags. 109234285Sdim 110234285Sdim// This flag may need to be replaced with -f[no-]asan-reads. 111234285Sdimstatic cl::opt<bool> ClInstrumentReads("asan-instrument-reads", 112234285Sdim cl::desc("instrument read instructions"), cl::Hidden, cl::init(true)); 113234285Sdimstatic cl::opt<bool> ClInstrumentWrites("asan-instrument-writes", 114234285Sdim cl::desc("instrument write instructions"), cl::Hidden, cl::init(true)); 115245431Sdimstatic cl::opt<bool> ClInstrumentAtomics("asan-instrument-atomics", 116245431Sdim cl::desc("instrument atomic instructions (rmw, cmpxchg)"), 117245431Sdim cl::Hidden, cl::init(true)); 118245431Sdimstatic cl::opt<bool> ClAlwaysSlowPath("asan-always-slow-path", 119245431Sdim cl::desc("use instrumentation with slow path for all accesses"), 120245431Sdim cl::Hidden, cl::init(false)); 121245431Sdim// This flag limits the number of instructions to be instrumented 122245431Sdim// in any given BB. Normally, this should be set to unlimited (INT_MAX), 123245431Sdim// but due to http://llvm.org/bugs/show_bug.cgi?id=12652 we temporary 124245431Sdim// set it to 10000. 125245431Sdimstatic cl::opt<int> ClMaxInsnsToInstrumentPerBB("asan-max-ins-per-bb", 126245431Sdim cl::init(10000), 127245431Sdim cl::desc("maximal number of instructions to instrument in any given BB"), 128245431Sdim cl::Hidden); 129234285Sdim// This flag may need to be replaced with -f[no]asan-stack. 130234285Sdimstatic cl::opt<bool> ClStack("asan-stack", 131234285Sdim cl::desc("Handle stack memory"), cl::Hidden, cl::init(true)); 132234285Sdim// This flag may need to be replaced with -f[no]asan-use-after-return. 133234285Sdimstatic cl::opt<bool> ClUseAfterReturn("asan-use-after-return", 134234285Sdim cl::desc("Check return-after-free"), cl::Hidden, cl::init(false)); 135234285Sdim// This flag may need to be replaced with -f[no]asan-globals. 136234285Sdimstatic cl::opt<bool> ClGlobals("asan-globals", 137234285Sdim cl::desc("Handle global objects"), cl::Hidden, cl::init(true)); 138263509Sdimstatic cl::opt<bool> ClCoverage("asan-coverage", 139263509Sdim cl::desc("ASan coverage"), cl::Hidden, cl::init(false)); 140245431Sdimstatic cl::opt<bool> ClInitializers("asan-initialization-order", 141245431Sdim cl::desc("Handle C++ initializer order"), cl::Hidden, cl::init(false)); 142234285Sdimstatic cl::opt<bool> ClMemIntrin("asan-memintrin", 143234285Sdim cl::desc("Handle memset/memcpy/memmove"), cl::Hidden, cl::init(true)); 144252723Sdimstatic cl::opt<bool> ClRealignStack("asan-realign-stack", 145252723Sdim cl::desc("Realign stack to 32"), cl::Hidden, cl::init(true)); 146252723Sdimstatic cl::opt<std::string> ClBlacklistFile("asan-blacklist", 147252723Sdim cl::desc("File containing the list of objects to ignore " 148234285Sdim "during instrumentation"), cl::Hidden); 149234285Sdim 150263509Sdim// This is an experimental feature that will allow to choose between 151263509Sdim// instrumented and non-instrumented code at link-time. 152263509Sdim// If this option is on, just before instrumenting a function we create its 153263509Sdim// clone; if the function is not changed by asan the clone is deleted. 154263509Sdim// If we end up with a clone, we put the instrumented function into a section 155263509Sdim// called "ASAN" and the uninstrumented function into a section called "NOASAN". 156263509Sdim// 157263509Sdim// This is still a prototype, we need to figure out a way to keep two copies of 158263509Sdim// a function so that the linker can easily choose one of them. 159263509Sdimstatic cl::opt<bool> ClKeepUninstrumented("asan-keep-uninstrumented-functions", 160263509Sdim cl::desc("Keep uninstrumented copies of functions"), 161263509Sdim cl::Hidden, cl::init(false)); 162263509Sdim 163234285Sdim// These flags allow to change the shadow mapping. 164234285Sdim// The shadow mapping looks like 165234285Sdim// Shadow = (Mem >> scale) + (1 << offset_log) 166234285Sdimstatic cl::opt<int> ClMappingScale("asan-mapping-scale", 167234285Sdim cl::desc("scale of asan shadow mapping"), cl::Hidden, cl::init(0)); 168234285Sdimstatic cl::opt<int> ClMappingOffsetLog("asan-mapping-offset-log", 169234285Sdim cl::desc("offset of asan shadow mapping"), cl::Hidden, cl::init(-1)); 170252723Sdimstatic cl::opt<bool> ClShort64BitOffset("asan-short-64bit-mapping-offset", 171252723Sdim cl::desc("Use short immediate constant as the mapping offset for 64bit"), 172252723Sdim cl::Hidden, cl::init(true)); 173234285Sdim 174234285Sdim// Optimization flags. Not user visible, used mostly for testing 175234285Sdim// and benchmarking the tool. 176234285Sdimstatic cl::opt<bool> ClOpt("asan-opt", 177234285Sdim cl::desc("Optimize instrumentation"), cl::Hidden, cl::init(true)); 178234285Sdimstatic cl::opt<bool> ClOptSameTemp("asan-opt-same-temp", 179234285Sdim cl::desc("Instrument the same temp just once"), cl::Hidden, 180234285Sdim cl::init(true)); 181234285Sdimstatic cl::opt<bool> ClOptGlobals("asan-opt-globals", 182234285Sdim cl::desc("Don't instrument scalar globals"), cl::Hidden, cl::init(true)); 183234285Sdim 184252723Sdimstatic cl::opt<bool> ClCheckLifetime("asan-check-lifetime", 185252723Sdim cl::desc("Use llvm.lifetime intrinsics to insert extra checks"), 186252723Sdim cl::Hidden, cl::init(false)); 187252723Sdim 188234285Sdim// Debug flags. 189234285Sdimstatic cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden, 190234285Sdim cl::init(0)); 191234285Sdimstatic cl::opt<int> ClDebugStack("asan-debug-stack", cl::desc("debug stack"), 192234285Sdim cl::Hidden, cl::init(0)); 193234285Sdimstatic cl::opt<std::string> ClDebugFunc("asan-debug-func", 194234285Sdim cl::Hidden, cl::desc("Debug func")); 195234285Sdimstatic cl::opt<int> ClDebugMin("asan-debug-min", cl::desc("Debug min inst"), 196234285Sdim cl::Hidden, cl::init(-1)); 197234285Sdimstatic cl::opt<int> ClDebugMax("asan-debug-max", cl::desc("Debug man inst"), 198234285Sdim cl::Hidden, cl::init(-1)); 199234285Sdim 200263509SdimSTATISTIC(NumInstrumentedReads, "Number of instrumented reads"); 201263509SdimSTATISTIC(NumInstrumentedWrites, "Number of instrumented writes"); 202263509SdimSTATISTIC(NumOptimizedAccessesToGlobalArray, 203263509Sdim "Number of optimized accesses to global arrays"); 204263509SdimSTATISTIC(NumOptimizedAccessesToGlobalVar, 205263509Sdim "Number of optimized accesses to global vars"); 206263509Sdim 207234285Sdimnamespace { 208252723Sdim/// A set of dynamically initialized globals extracted from metadata. 209252723Sdimclass SetOfDynamicallyInitializedGlobals { 210252723Sdim public: 211252723Sdim void Init(Module& M) { 212252723Sdim // Clang generates metadata identifying all dynamically initialized globals. 213252723Sdim NamedMDNode *DynamicGlobals = 214252723Sdim M.getNamedMetadata("llvm.asan.dynamically_initialized_globals"); 215252723Sdim if (!DynamicGlobals) 216252723Sdim return; 217252723Sdim for (int i = 0, n = DynamicGlobals->getNumOperands(); i < n; ++i) { 218252723Sdim MDNode *MDN = DynamicGlobals->getOperand(i); 219252723Sdim assert(MDN->getNumOperands() == 1); 220252723Sdim Value *VG = MDN->getOperand(0); 221252723Sdim // The optimizer may optimize away a global entirely, in which case we 222252723Sdim // cannot instrument access to it. 223252723Sdim if (!VG) 224252723Sdim continue; 225252723Sdim DynInitGlobals.insert(cast<GlobalVariable>(VG)); 226252723Sdim } 227252723Sdim } 228252723Sdim bool Contains(GlobalVariable *G) { return DynInitGlobals.count(G) != 0; } 229252723Sdim private: 230252723Sdim SmallSet<GlobalValue*, 32> DynInitGlobals; 231252723Sdim}; 232252723Sdim 233252723Sdim/// This struct defines the shadow mapping using the rule: 234252723Sdim/// shadow = (mem >> Scale) ADD-or-OR Offset. 235252723Sdimstruct ShadowMapping { 236252723Sdim int Scale; 237252723Sdim uint64_t Offset; 238252723Sdim bool OrShadowOffset; 239252723Sdim}; 240252723Sdim 241252723Sdimstatic ShadowMapping getShadowMapping(const Module &M, int LongSize, 242252723Sdim bool ZeroBaseShadow) { 243252723Sdim llvm::Triple TargetTriple(M.getTargetTriple()); 244252723Sdim bool IsAndroid = TargetTriple.getEnvironment() == llvm::Triple::Android; 245252723Sdim bool IsMacOSX = TargetTriple.getOS() == llvm::Triple::MacOSX; 246263509Sdim bool IsPPC64 = TargetTriple.getArch() == llvm::Triple::ppc64 || 247263509Sdim TargetTriple.getArch() == llvm::Triple::ppc64le; 248252723Sdim bool IsX86_64 = TargetTriple.getArch() == llvm::Triple::x86_64; 249263509Sdim bool IsMIPS32 = TargetTriple.getArch() == llvm::Triple::mips || 250263509Sdim TargetTriple.getArch() == llvm::Triple::mipsel; 251252723Sdim 252252723Sdim ShadowMapping Mapping; 253252723Sdim 254252723Sdim // OR-ing shadow offset if more efficient (at least on x86), 255252723Sdim // but on ppc64 we have to use add since the shadow offset is not neccesary 256252723Sdim // 1/8-th of the address space. 257252723Sdim Mapping.OrShadowOffset = !IsPPC64 && !ClShort64BitOffset; 258252723Sdim 259252723Sdim Mapping.Offset = (IsAndroid || ZeroBaseShadow) ? 0 : 260263509Sdim (LongSize == 32 ? 261263509Sdim (IsMIPS32 ? kMIPS32_ShadowOffset32 : kDefaultShadowOffset32) : 262252723Sdim IsPPC64 ? kPPC64_ShadowOffset64 : kDefaultShadowOffset64); 263252723Sdim if (!ZeroBaseShadow && ClShort64BitOffset && IsX86_64 && !IsMacOSX) { 264252723Sdim assert(LongSize == 64); 265252723Sdim Mapping.Offset = kDefaultShort64bitShadowOffset; 266252723Sdim } 267252723Sdim if (!ZeroBaseShadow && ClMappingOffsetLog >= 0) { 268252723Sdim // Zero offset log is the special case. 269252723Sdim Mapping.Offset = (ClMappingOffsetLog == 0) ? 0 : 1ULL << ClMappingOffsetLog; 270252723Sdim } 271252723Sdim 272252723Sdim Mapping.Scale = kDefaultShadowScale; 273252723Sdim if (ClMappingScale) { 274252723Sdim Mapping.Scale = ClMappingScale; 275252723Sdim } 276252723Sdim 277252723Sdim return Mapping; 278252723Sdim} 279252723Sdim 280252723Sdimstatic size_t RedzoneSizeForScale(int MappingScale) { 281252723Sdim // Redzone used for stack and globals is at least 32 bytes. 282252723Sdim // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively. 283252723Sdim return std::max(32U, 1U << MappingScale); 284252723Sdim} 285252723Sdim 286234285Sdim/// AddressSanitizer: instrument the code in module to find memory bugs. 287245431Sdimstruct AddressSanitizer : public FunctionPass { 288252723Sdim AddressSanitizer(bool CheckInitOrder = true, 289252723Sdim bool CheckUseAfterReturn = false, 290252723Sdim bool CheckLifetime = false, 291252723Sdim StringRef BlacklistFile = StringRef(), 292252723Sdim bool ZeroBaseShadow = false) 293252723Sdim : FunctionPass(ID), 294252723Sdim CheckInitOrder(CheckInitOrder || ClInitializers), 295252723Sdim CheckUseAfterReturn(CheckUseAfterReturn || ClUseAfterReturn), 296252723Sdim CheckLifetime(CheckLifetime || ClCheckLifetime), 297252723Sdim BlacklistFile(BlacklistFile.empty() ? ClBlacklistFile 298252723Sdim : BlacklistFile), 299252723Sdim ZeroBaseShadow(ZeroBaseShadow) {} 300252723Sdim virtual const char *getPassName() const { 301252723Sdim return "AddressSanitizerFunctionPass"; 302252723Sdim } 303234285Sdim void instrumentMop(Instruction *I); 304252723Sdim void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore, 305252723Sdim Value *Addr, uint32_t TypeSize, bool IsWrite, 306252723Sdim Value *SizeArgument); 307245431Sdim Value *createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, 308245431Sdim Value *ShadowValue, uint32_t TypeSize); 309245431Sdim Instruction *generateCrashCode(Instruction *InsertBefore, Value *Addr, 310252723Sdim bool IsWrite, size_t AccessSizeIndex, 311252723Sdim Value *SizeArgument); 312234285Sdim bool instrumentMemIntrinsic(MemIntrinsic *MI); 313234285Sdim void instrumentMemIntrinsicParam(Instruction *OrigIns, Value *Addr, 314245431Sdim Value *Size, 315234285Sdim Instruction *InsertBefore, bool IsWrite); 316234285Sdim Value *memToShadow(Value *Shadow, IRBuilder<> &IRB); 317245431Sdim bool runOnFunction(Function &F); 318234285Sdim bool maybeInsertAsanInitAtFunctionEntry(Function &F); 319252723Sdim void emitShadowMapping(Module &M, IRBuilder<> &IRB) const; 320245431Sdim virtual bool doInitialization(Module &M); 321234285Sdim static char ID; // Pass identification, replacement for typeid 322234285Sdim 323234285Sdim private: 324252723Sdim void initializeCallbacks(Module &M); 325234285Sdim 326245431Sdim bool ShouldInstrumentGlobal(GlobalVariable *G); 327234285Sdim bool LooksLikeCodeInBug11395(Instruction *I); 328245431Sdim void FindDynamicInitializers(Module &M); 329263509Sdim bool GlobalIsLinkerInitialized(GlobalVariable *G); 330263509Sdim bool InjectCoverage(Function &F); 331234285Sdim 332252723Sdim bool CheckInitOrder; 333252723Sdim bool CheckUseAfterReturn; 334252723Sdim bool CheckLifetime; 335252723Sdim SmallString<64> BlacklistFile; 336252723Sdim bool ZeroBaseShadow; 337252723Sdim 338234285Sdim LLVMContext *C; 339245431Sdim DataLayout *TD; 340234285Sdim int LongSize; 341234285Sdim Type *IntptrTy; 342252723Sdim ShadowMapping Mapping; 343234285Sdim Function *AsanCtorFunction; 344234285Sdim Function *AsanInitFunction; 345245431Sdim Function *AsanHandleNoReturnFunc; 346263509Sdim Function *AsanCovFunction; 347263509Sdim OwningPtr<SpecialCaseList> BL; 348245431Sdim // This array is indexed by AccessIsWrite and log2(AccessSize). 349245431Sdim Function *AsanErrorCallback[2][kNumberOfAccessSizes]; 350252723Sdim // This array is indexed by AccessIsWrite. 351252723Sdim Function *AsanErrorCallbackSized[2]; 352245431Sdim InlineAsm *EmptyAsm; 353252723Sdim SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals; 354252723Sdim 355252723Sdim friend struct FunctionStackPoisoner; 356234285Sdim}; 357245431Sdim 358252723Sdimclass AddressSanitizerModule : public ModulePass { 359252723Sdim public: 360252723Sdim AddressSanitizerModule(bool CheckInitOrder = true, 361252723Sdim StringRef BlacklistFile = StringRef(), 362252723Sdim bool ZeroBaseShadow = false) 363252723Sdim : ModulePass(ID), 364252723Sdim CheckInitOrder(CheckInitOrder || ClInitializers), 365252723Sdim BlacklistFile(BlacklistFile.empty() ? ClBlacklistFile 366252723Sdim : BlacklistFile), 367252723Sdim ZeroBaseShadow(ZeroBaseShadow) {} 368252723Sdim bool runOnModule(Module &M); 369252723Sdim static char ID; // Pass identification, replacement for typeid 370252723Sdim virtual const char *getPassName() const { 371252723Sdim return "AddressSanitizerModule"; 372252723Sdim } 373252723Sdim 374252723Sdim private: 375252723Sdim void initializeCallbacks(Module &M); 376252723Sdim 377252723Sdim bool ShouldInstrumentGlobal(GlobalVariable *G); 378252723Sdim void createInitializerPoisonCalls(Module &M, GlobalValue *ModuleName); 379252723Sdim size_t RedzoneSize() const { 380252723Sdim return RedzoneSizeForScale(Mapping.Scale); 381252723Sdim } 382252723Sdim 383252723Sdim bool CheckInitOrder; 384252723Sdim SmallString<64> BlacklistFile; 385252723Sdim bool ZeroBaseShadow; 386252723Sdim 387263509Sdim OwningPtr<SpecialCaseList> BL; 388252723Sdim SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals; 389252723Sdim Type *IntptrTy; 390252723Sdim LLVMContext *C; 391252723Sdim DataLayout *TD; 392252723Sdim ShadowMapping Mapping; 393252723Sdim Function *AsanPoisonGlobals; 394252723Sdim Function *AsanUnpoisonGlobals; 395252723Sdim Function *AsanRegisterGlobals; 396252723Sdim Function *AsanUnregisterGlobals; 397252723Sdim}; 398252723Sdim 399252723Sdim// Stack poisoning does not play well with exception handling. 400252723Sdim// When an exception is thrown, we essentially bypass the code 401252723Sdim// that unpoisones the stack. This is why the run-time library has 402252723Sdim// to intercept __cxa_throw (as well as longjmp, etc) and unpoison the entire 403252723Sdim// stack in the interceptor. This however does not work inside the 404252723Sdim// actual function which catches the exception. Most likely because the 405252723Sdim// compiler hoists the load of the shadow value somewhere too high. 406252723Sdim// This causes asan to report a non-existing bug on 453.povray. 407252723Sdim// It sounds like an LLVM bug. 408252723Sdimstruct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> { 409252723Sdim Function &F; 410252723Sdim AddressSanitizer &ASan; 411252723Sdim DIBuilder DIB; 412252723Sdim LLVMContext *C; 413252723Sdim Type *IntptrTy; 414252723Sdim Type *IntptrPtrTy; 415252723Sdim ShadowMapping Mapping; 416252723Sdim 417252723Sdim SmallVector<AllocaInst*, 16> AllocaVec; 418252723Sdim SmallVector<Instruction*, 8> RetVec; 419252723Sdim uint64_t TotalStackSize; 420252723Sdim unsigned StackAlignment; 421252723Sdim 422263509Sdim Function *AsanStackMallocFunc[kMaxAsanStackMallocSizeClass + 1], 423263509Sdim *AsanStackFreeFunc[kMaxAsanStackMallocSizeClass + 1]; 424252723Sdim Function *AsanPoisonStackMemoryFunc, *AsanUnpoisonStackMemoryFunc; 425252723Sdim 426252723Sdim // Stores a place and arguments of poisoning/unpoisoning call for alloca. 427252723Sdim struct AllocaPoisonCall { 428252723Sdim IntrinsicInst *InsBefore; 429263509Sdim AllocaInst *AI; 430252723Sdim uint64_t Size; 431252723Sdim bool DoPoison; 432252723Sdim }; 433252723Sdim SmallVector<AllocaPoisonCall, 8> AllocaPoisonCallVec; 434252723Sdim 435252723Sdim // Maps Value to an AllocaInst from which the Value is originated. 436252723Sdim typedef DenseMap<Value*, AllocaInst*> AllocaForValueMapTy; 437252723Sdim AllocaForValueMapTy AllocaForValue; 438252723Sdim 439252723Sdim FunctionStackPoisoner(Function &F, AddressSanitizer &ASan) 440252723Sdim : F(F), ASan(ASan), DIB(*F.getParent()), C(ASan.C), 441252723Sdim IntptrTy(ASan.IntptrTy), IntptrPtrTy(PointerType::get(IntptrTy, 0)), 442252723Sdim Mapping(ASan.Mapping), 443252723Sdim TotalStackSize(0), StackAlignment(1 << Mapping.Scale) {} 444252723Sdim 445252723Sdim bool runOnFunction() { 446252723Sdim if (!ClStack) return false; 447252723Sdim // Collect alloca, ret, lifetime instructions etc. 448252723Sdim for (df_iterator<BasicBlock*> DI = df_begin(&F.getEntryBlock()), 449252723Sdim DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) { 450252723Sdim BasicBlock *BB = *DI; 451252723Sdim visit(*BB); 452252723Sdim } 453252723Sdim if (AllocaVec.empty()) return false; 454252723Sdim 455252723Sdim initializeCallbacks(*F.getParent()); 456252723Sdim 457252723Sdim poisonStack(); 458252723Sdim 459252723Sdim if (ClDebugStack) { 460252723Sdim DEBUG(dbgs() << F); 461252723Sdim } 462252723Sdim return true; 463252723Sdim } 464252723Sdim 465252723Sdim // Finds all static Alloca instructions and puts 466252723Sdim // poisoned red zones around all of them. 467252723Sdim // Then unpoison everything back before the function returns. 468252723Sdim void poisonStack(); 469252723Sdim 470252723Sdim // ----------------------- Visitors. 471252723Sdim /// \brief Collect all Ret instructions. 472252723Sdim void visitReturnInst(ReturnInst &RI) { 473252723Sdim RetVec.push_back(&RI); 474252723Sdim } 475252723Sdim 476252723Sdim /// \brief Collect Alloca instructions we want (and can) handle. 477252723Sdim void visitAllocaInst(AllocaInst &AI) { 478252723Sdim if (!isInterestingAlloca(AI)) return; 479252723Sdim 480252723Sdim StackAlignment = std::max(StackAlignment, AI.getAlignment()); 481252723Sdim AllocaVec.push_back(&AI); 482263509Sdim uint64_t AlignedSize = getAlignedAllocaSize(&AI); 483252723Sdim TotalStackSize += AlignedSize; 484252723Sdim } 485252723Sdim 486252723Sdim /// \brief Collect lifetime intrinsic calls to check for use-after-scope 487252723Sdim /// errors. 488252723Sdim void visitIntrinsicInst(IntrinsicInst &II) { 489252723Sdim if (!ASan.CheckLifetime) return; 490252723Sdim Intrinsic::ID ID = II.getIntrinsicID(); 491252723Sdim if (ID != Intrinsic::lifetime_start && 492252723Sdim ID != Intrinsic::lifetime_end) 493252723Sdim return; 494252723Sdim // Found lifetime intrinsic, add ASan instrumentation if necessary. 495252723Sdim ConstantInt *Size = dyn_cast<ConstantInt>(II.getArgOperand(0)); 496252723Sdim // If size argument is undefined, don't do anything. 497252723Sdim if (Size->isMinusOne()) return; 498252723Sdim // Check that size doesn't saturate uint64_t and can 499252723Sdim // be stored in IntptrTy. 500252723Sdim const uint64_t SizeValue = Size->getValue().getLimitedValue(); 501252723Sdim if (SizeValue == ~0ULL || 502252723Sdim !ConstantInt::isValueValidForType(IntptrTy, SizeValue)) 503252723Sdim return; 504252723Sdim // Find alloca instruction that corresponds to llvm.lifetime argument. 505252723Sdim AllocaInst *AI = findAllocaForValue(II.getArgOperand(1)); 506252723Sdim if (!AI) return; 507252723Sdim bool DoPoison = (ID == Intrinsic::lifetime_end); 508263509Sdim AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison}; 509252723Sdim AllocaPoisonCallVec.push_back(APC); 510252723Sdim } 511252723Sdim 512252723Sdim // ---------------------- Helpers. 513252723Sdim void initializeCallbacks(Module &M); 514252723Sdim 515252723Sdim // Check if we want (and can) handle this alloca. 516263509Sdim bool isInterestingAlloca(AllocaInst &AI) const { 517252723Sdim return (!AI.isArrayAllocation() && 518252723Sdim AI.isStaticAlloca() && 519263509Sdim AI.getAlignment() <= RedzoneSize() && 520252723Sdim AI.getAllocatedType()->isSized()); 521252723Sdim } 522252723Sdim 523252723Sdim size_t RedzoneSize() const { 524252723Sdim return RedzoneSizeForScale(Mapping.Scale); 525252723Sdim } 526263509Sdim uint64_t getAllocaSizeInBytes(AllocaInst *AI) const { 527252723Sdim Type *Ty = AI->getAllocatedType(); 528252723Sdim uint64_t SizeInBytes = ASan.TD->getTypeAllocSize(Ty); 529252723Sdim return SizeInBytes; 530252723Sdim } 531263509Sdim uint64_t getAlignedSize(uint64_t SizeInBytes) const { 532252723Sdim size_t RZ = RedzoneSize(); 533252723Sdim return ((SizeInBytes + RZ - 1) / RZ) * RZ; 534252723Sdim } 535263509Sdim uint64_t getAlignedAllocaSize(AllocaInst *AI) const { 536252723Sdim uint64_t SizeInBytes = getAllocaSizeInBytes(AI); 537252723Sdim return getAlignedSize(SizeInBytes); 538252723Sdim } 539252723Sdim /// Finds alloca where the value comes from. 540252723Sdim AllocaInst *findAllocaForValue(Value *V); 541263509Sdim void poisonRedZones(const ArrayRef<AllocaInst*> &AllocaVec, IRBuilder<> &IRB, 542252723Sdim Value *ShadowBase, bool DoPoison); 543263509Sdim void poisonAlloca(Value *V, uint64_t Size, IRBuilder<> &IRB, bool DoPoison); 544263509Sdim 545263509Sdim void SetShadowToStackAfterReturnInlined(IRBuilder<> &IRB, Value *ShadowBase, 546263509Sdim int Size); 547252723Sdim}; 548252723Sdim 549234285Sdim} // namespace 550234285Sdim 551234285Sdimchar AddressSanitizer::ID = 0; 552234285SdimINITIALIZE_PASS(AddressSanitizer, "asan", 553234285Sdim "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", 554234285Sdim false, false) 555252723SdimFunctionPass *llvm::createAddressSanitizerFunctionPass( 556252723Sdim bool CheckInitOrder, bool CheckUseAfterReturn, bool CheckLifetime, 557252723Sdim StringRef BlacklistFile, bool ZeroBaseShadow) { 558252723Sdim return new AddressSanitizer(CheckInitOrder, CheckUseAfterReturn, 559252723Sdim CheckLifetime, BlacklistFile, ZeroBaseShadow); 560234285Sdim} 561234285Sdim 562252723Sdimchar AddressSanitizerModule::ID = 0; 563252723SdimINITIALIZE_PASS(AddressSanitizerModule, "asan-module", 564252723Sdim "AddressSanitizer: detects use-after-free and out-of-bounds bugs." 565252723Sdim "ModulePass", false, false) 566252723SdimModulePass *llvm::createAddressSanitizerModulePass( 567252723Sdim bool CheckInitOrder, StringRef BlacklistFile, bool ZeroBaseShadow) { 568252723Sdim return new AddressSanitizerModule(CheckInitOrder, BlacklistFile, 569252723Sdim ZeroBaseShadow); 570234285Sdim} 571234285Sdim 572245431Sdimstatic size_t TypeSizeToSizeIndex(uint32_t TypeSize) { 573263509Sdim size_t Res = countTrailingZeros(TypeSize / 8); 574245431Sdim assert(Res < kNumberOfAccessSizes); 575245431Sdim return Res; 576245431Sdim} 577245431Sdim 578263509Sdim// \brief Create a constant for Str so that we can pass it to the run-time lib. 579234285Sdimstatic GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { 580234285Sdim Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); 581252723Sdim GlobalVariable *GV = new GlobalVariable(M, StrConst->getType(), true, 582263509Sdim GlobalValue::InternalLinkage, StrConst, 583252723Sdim kAsanGenPrefix); 584252723Sdim GV->setUnnamedAddr(true); // Ok to merge these. 585252723Sdim GV->setAlignment(1); // Strings may not be merged w/o setting align 1. 586252723Sdim return GV; 587234285Sdim} 588234285Sdim 589252723Sdimstatic bool GlobalWasGeneratedByAsan(GlobalVariable *G) { 590252723Sdim return G->getName().find(kAsanGenPrefix) == 0; 591252723Sdim} 592252723Sdim 593234285SdimValue *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) { 594234285Sdim // Shadow >> scale 595252723Sdim Shadow = IRB.CreateLShr(Shadow, Mapping.Scale); 596252723Sdim if (Mapping.Offset == 0) 597234285Sdim return Shadow; 598234285Sdim // (Shadow >> scale) | offset 599252723Sdim if (Mapping.OrShadowOffset) 600252723Sdim return IRB.CreateOr(Shadow, ConstantInt::get(IntptrTy, Mapping.Offset)); 601252723Sdim else 602252723Sdim return IRB.CreateAdd(Shadow, ConstantInt::get(IntptrTy, Mapping.Offset)); 603234285Sdim} 604234285Sdim 605245431Sdimvoid AddressSanitizer::instrumentMemIntrinsicParam( 606245431Sdim Instruction *OrigIns, 607234285Sdim Value *Addr, Value *Size, Instruction *InsertBefore, bool IsWrite) { 608252723Sdim IRBuilder<> IRB(InsertBefore); 609252723Sdim if (Size->getType() != IntptrTy) 610252723Sdim Size = IRB.CreateIntCast(Size, IntptrTy, false); 611234285Sdim // Check the first byte. 612252723Sdim instrumentAddress(OrigIns, InsertBefore, Addr, 8, IsWrite, Size); 613234285Sdim // Check the last byte. 614252723Sdim IRB.SetInsertPoint(InsertBefore); 615252723Sdim Value *SizeMinusOne = IRB.CreateSub(Size, ConstantInt::get(IntptrTy, 1)); 616252723Sdim Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 617252723Sdim Value *AddrLast = IRB.CreateAdd(AddrLong, SizeMinusOne); 618252723Sdim instrumentAddress(OrigIns, InsertBefore, AddrLast, 8, IsWrite, Size); 619234285Sdim} 620234285Sdim 621234285Sdim// Instrument memset/memmove/memcpy 622234285Sdimbool AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) { 623234285Sdim Value *Dst = MI->getDest(); 624234285Sdim MemTransferInst *MemTran = dyn_cast<MemTransferInst>(MI); 625245431Sdim Value *Src = MemTran ? MemTran->getSource() : 0; 626234285Sdim Value *Length = MI->getLength(); 627234285Sdim 628234285Sdim Constant *ConstLength = dyn_cast<Constant>(Length); 629234285Sdim Instruction *InsertBefore = MI; 630234285Sdim if (ConstLength) { 631234285Sdim if (ConstLength->isNullValue()) return false; 632234285Sdim } else { 633234285Sdim // The size is not a constant so it could be zero -- check at run-time. 634234285Sdim IRBuilder<> IRB(InsertBefore); 635234285Sdim 636234285Sdim Value *Cmp = IRB.CreateICmpNE(Length, 637245431Sdim Constant::getNullValue(Length->getType())); 638245431Sdim InsertBefore = SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); 639234285Sdim } 640234285Sdim 641234285Sdim instrumentMemIntrinsicParam(MI, Dst, Length, InsertBefore, true); 642234285Sdim if (Src) 643234285Sdim instrumentMemIntrinsicParam(MI, Src, Length, InsertBefore, false); 644234285Sdim return true; 645234285Sdim} 646234285Sdim 647245431Sdim// If I is an interesting memory access, return the PointerOperand 648245431Sdim// and set IsWrite. Otherwise return NULL. 649245431Sdimstatic Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite) { 650234285Sdim if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 651245431Sdim if (!ClInstrumentReads) return NULL; 652245431Sdim *IsWrite = false; 653234285Sdim return LI->getPointerOperand(); 654234285Sdim } 655245431Sdim if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 656245431Sdim if (!ClInstrumentWrites) return NULL; 657245431Sdim *IsWrite = true; 658245431Sdim return SI->getPointerOperand(); 659245431Sdim } 660245431Sdim if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { 661245431Sdim if (!ClInstrumentAtomics) return NULL; 662245431Sdim *IsWrite = true; 663245431Sdim return RMW->getPointerOperand(); 664245431Sdim } 665245431Sdim if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { 666245431Sdim if (!ClInstrumentAtomics) return NULL; 667245431Sdim *IsWrite = true; 668245431Sdim return XCHG->getPointerOperand(); 669245431Sdim } 670245431Sdim return NULL; 671234285Sdim} 672234285Sdim 673263509Sdimbool AddressSanitizer::GlobalIsLinkerInitialized(GlobalVariable *G) { 674263509Sdim // If a global variable does not have dynamic initialization we don't 675263509Sdim // have to instrument it. However, if a global does not have initializer 676263509Sdim // at all, we assume it has dynamic initializer (in other TU). 677263509Sdim return G->hasInitializer() && !DynamicallyInitializedGlobals.Contains(G); 678263509Sdim} 679263509Sdim 680245431Sdimvoid AddressSanitizer::instrumentMop(Instruction *I) { 681245431Sdim bool IsWrite = false; 682245431Sdim Value *Addr = isInterestingMemoryAccess(I, &IsWrite); 683245431Sdim assert(Addr); 684245431Sdim if (ClOpt && ClOptGlobals) { 685245431Sdim if (GlobalVariable *G = dyn_cast<GlobalVariable>(Addr)) { 686245431Sdim // If initialization order checking is disabled, a simple access to a 687245431Sdim // dynamically initialized global is always valid. 688263509Sdim if (!CheckInitOrder || GlobalIsLinkerInitialized(G)) { 689263509Sdim NumOptimizedAccessesToGlobalVar++; 690245431Sdim return; 691263509Sdim } 692245431Sdim } 693263509Sdim ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr); 694263509Sdim if (CE && CE->isGEPWithNoNotionalOverIndexing()) { 695263509Sdim if (GlobalVariable *G = dyn_cast<GlobalVariable>(CE->getOperand(0))) { 696263509Sdim if (CE->getOperand(1)->isNullValue() && GlobalIsLinkerInitialized(G)) { 697263509Sdim NumOptimizedAccessesToGlobalArray++; 698263509Sdim return; 699263509Sdim } 700263509Sdim } 701263509Sdim } 702245431Sdim } 703245431Sdim 704234285Sdim Type *OrigPtrTy = Addr->getType(); 705234285Sdim Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType(); 706234285Sdim 707234285Sdim assert(OrigTy->isSized()); 708234285Sdim uint32_t TypeSize = TD->getTypeStoreSizeInBits(OrigTy); 709234285Sdim 710252723Sdim assert((TypeSize % 8) == 0); 711234285Sdim 712263509Sdim if (IsWrite) 713263509Sdim NumInstrumentedWrites++; 714263509Sdim else 715263509Sdim NumInstrumentedReads++; 716263509Sdim 717252723Sdim // Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check. 718252723Sdim if (TypeSize == 8 || TypeSize == 16 || 719252723Sdim TypeSize == 32 || TypeSize == 64 || TypeSize == 128) 720252723Sdim return instrumentAddress(I, I, Addr, TypeSize, IsWrite, 0); 721252723Sdim // Instrument unusual size (but still multiple of 8). 722252723Sdim // We can not do it with a single check, so we do 1-byte check for the first 723252723Sdim // and the last bytes. We call __asan_report_*_n(addr, real_size) to be able 724252723Sdim // to report the actual access size. 725234285Sdim IRBuilder<> IRB(I); 726252723Sdim Value *LastByte = IRB.CreateIntToPtr( 727252723Sdim IRB.CreateAdd(IRB.CreatePointerCast(Addr, IntptrTy), 728252723Sdim ConstantInt::get(IntptrTy, TypeSize / 8 - 1)), 729252723Sdim OrigPtrTy); 730252723Sdim Value *Size = ConstantInt::get(IntptrTy, TypeSize / 8); 731252723Sdim instrumentAddress(I, I, Addr, 8, IsWrite, Size); 732252723Sdim instrumentAddress(I, I, LastByte, 8, IsWrite, Size); 733234285Sdim} 734234285Sdim 735245431Sdim// Validate the result of Module::getOrInsertFunction called for an interface 736245431Sdim// function of AddressSanitizer. If the instrumented module defines a function 737245431Sdim// with the same name, their prototypes must match, otherwise 738245431Sdim// getOrInsertFunction returns a bitcast. 739252723Sdimstatic Function *checkInterfaceFunction(Constant *FuncOrBitcast) { 740245431Sdim if (isa<Function>(FuncOrBitcast)) return cast<Function>(FuncOrBitcast); 741245431Sdim FuncOrBitcast->dump(); 742245431Sdim report_fatal_error("trying to redefine an AddressSanitizer " 743245431Sdim "interface function"); 744245431Sdim} 745245431Sdim 746234285SdimInstruction *AddressSanitizer::generateCrashCode( 747245431Sdim Instruction *InsertBefore, Value *Addr, 748252723Sdim bool IsWrite, size_t AccessSizeIndex, Value *SizeArgument) { 749245431Sdim IRBuilder<> IRB(InsertBefore); 750252723Sdim CallInst *Call = SizeArgument 751252723Sdim ? IRB.CreateCall2(AsanErrorCallbackSized[IsWrite], Addr, SizeArgument) 752252723Sdim : IRB.CreateCall(AsanErrorCallback[IsWrite][AccessSizeIndex], Addr); 753252723Sdim 754245431Sdim // We don't do Call->setDoesNotReturn() because the BB already has 755245431Sdim // UnreachableInst at the end. 756245431Sdim // This EmptyAsm is required to avoid callback merge. 757245431Sdim IRB.CreateCall(EmptyAsm); 758234285Sdim return Call; 759234285Sdim} 760234285Sdim 761245431SdimValue *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, 762245431Sdim Value *ShadowValue, 763245431Sdim uint32_t TypeSize) { 764252723Sdim size_t Granularity = 1 << Mapping.Scale; 765245431Sdim // Addr & (Granularity - 1) 766245431Sdim Value *LastAccessedByte = IRB.CreateAnd( 767245431Sdim AddrLong, ConstantInt::get(IntptrTy, Granularity - 1)); 768245431Sdim // (Addr & (Granularity - 1)) + size - 1 769245431Sdim if (TypeSize / 8 > 1) 770245431Sdim LastAccessedByte = IRB.CreateAdd( 771245431Sdim LastAccessedByte, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)); 772245431Sdim // (uint8_t) ((Addr & (Granularity-1)) + size - 1) 773245431Sdim LastAccessedByte = IRB.CreateIntCast( 774245431Sdim LastAccessedByte, ShadowValue->getType(), false); 775245431Sdim // ((uint8_t) ((Addr & (Granularity-1)) + size - 1)) >= ShadowValue 776245431Sdim return IRB.CreateICmpSGE(LastAccessedByte, ShadowValue); 777245431Sdim} 778245431Sdim 779234285Sdimvoid AddressSanitizer::instrumentAddress(Instruction *OrigIns, 780252723Sdim Instruction *InsertBefore, 781252723Sdim Value *Addr, uint32_t TypeSize, 782252723Sdim bool IsWrite, Value *SizeArgument) { 783252723Sdim IRBuilder<> IRB(InsertBefore); 784234285Sdim Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 785234285Sdim 786234285Sdim Type *ShadowTy = IntegerType::get( 787252723Sdim *C, std::max(8U, TypeSize >> Mapping.Scale)); 788234285Sdim Type *ShadowPtrTy = PointerType::get(ShadowTy, 0); 789234285Sdim Value *ShadowPtr = memToShadow(AddrLong, IRB); 790234285Sdim Value *CmpVal = Constant::getNullValue(ShadowTy); 791234285Sdim Value *ShadowValue = IRB.CreateLoad( 792234285Sdim IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy)); 793234285Sdim 794234285Sdim Value *Cmp = IRB.CreateICmpNE(ShadowValue, CmpVal); 795245431Sdim size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); 796252723Sdim size_t Granularity = 1 << Mapping.Scale; 797245431Sdim TerminatorInst *CrashTerm = 0; 798234285Sdim 799245431Sdim if (ClAlwaysSlowPath || (TypeSize < 8 * Granularity)) { 800245431Sdim TerminatorInst *CheckTerm = 801245431Sdim SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); 802245431Sdim assert(dyn_cast<BranchInst>(CheckTerm)->isUnconditional()); 803245431Sdim BasicBlock *NextBB = CheckTerm->getSuccessor(0); 804245431Sdim IRB.SetInsertPoint(CheckTerm); 805245431Sdim Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeSize); 806245431Sdim BasicBlock *CrashBlock = 807245431Sdim BasicBlock::Create(*C, "", NextBB->getParent(), NextBB); 808245431Sdim CrashTerm = new UnreachableInst(*C, CrashBlock); 809245431Sdim BranchInst *NewTerm = BranchInst::Create(CrashBlock, NextBB, Cmp2); 810245431Sdim ReplaceInstWithInst(CheckTerm, NewTerm); 811245431Sdim } else { 812245431Sdim CrashTerm = SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), true); 813234285Sdim } 814234285Sdim 815252723Sdim Instruction *Crash = generateCrashCode( 816252723Sdim CrashTerm, AddrLong, IsWrite, AccessSizeIndex, SizeArgument); 817234285Sdim Crash->setDebugLoc(OrigIns->getDebugLoc()); 818234285Sdim} 819234285Sdim 820252723Sdimvoid AddressSanitizerModule::createInitializerPoisonCalls( 821252723Sdim Module &M, GlobalValue *ModuleName) { 822245431Sdim // We do all of our poisoning and unpoisoning within _GLOBAL__I_a. 823245431Sdim Function *GlobalInit = M.getFunction("_GLOBAL__I_a"); 824245431Sdim // If that function is not present, this TU contains no globals, or they have 825245431Sdim // all been optimized away 826245431Sdim if (!GlobalInit) 827245431Sdim return; 828234285Sdim 829245431Sdim // Set up the arguments to our poison/unpoison functions. 830245431Sdim IRBuilder<> IRB(GlobalInit->begin()->getFirstInsertionPt()); 831234285Sdim 832245431Sdim // Add a call to poison all external globals before the given function starts. 833252723Sdim Value *ModuleNameAddr = ConstantExpr::getPointerCast(ModuleName, IntptrTy); 834252723Sdim IRB.CreateCall(AsanPoisonGlobals, ModuleNameAddr); 835245431Sdim 836245431Sdim // Add calls to unpoison all globals before each return instruction. 837245431Sdim for (Function::iterator I = GlobalInit->begin(), E = GlobalInit->end(); 838245431Sdim I != E; ++I) { 839245431Sdim if (ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator())) { 840245431Sdim CallInst::Create(AsanUnpoisonGlobals, "", RI); 841234285Sdim } 842245431Sdim } 843245431Sdim} 844234285Sdim 845252723Sdimbool AddressSanitizerModule::ShouldInstrumentGlobal(GlobalVariable *G) { 846245431Sdim Type *Ty = cast<PointerType>(G->getType())->getElementType(); 847245431Sdim DEBUG(dbgs() << "GLOBAL: " << *G << "\n"); 848245431Sdim 849245431Sdim if (BL->isIn(*G)) return false; 850245431Sdim if (!Ty->isSized()) return false; 851245431Sdim if (!G->hasInitializer()) return false; 852252723Sdim if (GlobalWasGeneratedByAsan(G)) return false; // Our own global. 853245431Sdim // Touch only those globals that will not be defined in other modules. 854245431Sdim // Don't handle ODR type linkages since other modules may be built w/o asan. 855245431Sdim if (G->getLinkage() != GlobalVariable::ExternalLinkage && 856245431Sdim G->getLinkage() != GlobalVariable::PrivateLinkage && 857245431Sdim G->getLinkage() != GlobalVariable::InternalLinkage) 858245431Sdim return false; 859245431Sdim // Two problems with thread-locals: 860245431Sdim // - The address of the main thread's copy can't be computed at link-time. 861245431Sdim // - Need to poison all copies, not just the main thread's one. 862245431Sdim if (G->isThreadLocal()) 863245431Sdim return false; 864245431Sdim // For now, just ignore this Alloca if the alignment is large. 865252723Sdim if (G->getAlignment() > RedzoneSize()) return false; 866245431Sdim 867245431Sdim // Ignore all the globals with the names starting with "\01L_OBJC_". 868245431Sdim // Many of those are put into the .cstring section. The linker compresses 869245431Sdim // that section by removing the spare \0s after the string terminator, so 870245431Sdim // our redzones get broken. 871245431Sdim if ((G->getName().find("\01L_OBJC_") == 0) || 872245431Sdim (G->getName().find("\01l_OBJC_") == 0)) { 873245431Sdim DEBUG(dbgs() << "Ignoring \\01L_OBJC_* global: " << *G); 874245431Sdim return false; 875245431Sdim } 876245431Sdim 877245431Sdim if (G->hasSection()) { 878245431Sdim StringRef Section(G->getSection()); 879245431Sdim // Ignore the globals from the __OBJC section. The ObjC runtime assumes 880245431Sdim // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to 881245431Sdim // them. 882245431Sdim if ((Section.find("__OBJC,") == 0) || 883245431Sdim (Section.find("__DATA, __objc_") == 0)) { 884245431Sdim DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G); 885245431Sdim return false; 886234285Sdim } 887245431Sdim // See http://code.google.com/p/address-sanitizer/issues/detail?id=32 888245431Sdim // Constant CFString instances are compiled in the following way: 889245431Sdim // -- the string buffer is emitted into 890245431Sdim // __TEXT,__cstring,cstring_literals 891245431Sdim // -- the constant NSConstantString structure referencing that buffer 892245431Sdim // is placed into __DATA,__cfstring 893245431Sdim // Therefore there's no point in placing redzones into __DATA,__cfstring. 894245431Sdim // Moreover, it causes the linker to crash on OS X 10.7 895245431Sdim if (Section.find("__DATA,__cfstring") == 0) { 896245431Sdim DEBUG(dbgs() << "Ignoring CFString: " << *G); 897245431Sdim return false; 898245431Sdim } 899245431Sdim } 900234285Sdim 901245431Sdim return true; 902245431Sdim} 903245431Sdim 904252723Sdimvoid AddressSanitizerModule::initializeCallbacks(Module &M) { 905252723Sdim IRBuilder<> IRB(*C); 906252723Sdim // Declare our poisoning and unpoisoning functions. 907252723Sdim AsanPoisonGlobals = checkInterfaceFunction(M.getOrInsertFunction( 908252723Sdim kAsanPoisonGlobalsName, IRB.getVoidTy(), IntptrTy, NULL)); 909252723Sdim AsanPoisonGlobals->setLinkage(Function::ExternalLinkage); 910252723Sdim AsanUnpoisonGlobals = checkInterfaceFunction(M.getOrInsertFunction( 911252723Sdim kAsanUnpoisonGlobalsName, IRB.getVoidTy(), NULL)); 912252723Sdim AsanUnpoisonGlobals->setLinkage(Function::ExternalLinkage); 913252723Sdim // Declare functions that register/unregister globals. 914252723Sdim AsanRegisterGlobals = checkInterfaceFunction(M.getOrInsertFunction( 915252723Sdim kAsanRegisterGlobalsName, IRB.getVoidTy(), 916252723Sdim IntptrTy, IntptrTy, NULL)); 917252723Sdim AsanRegisterGlobals->setLinkage(Function::ExternalLinkage); 918252723Sdim AsanUnregisterGlobals = checkInterfaceFunction(M.getOrInsertFunction( 919252723Sdim kAsanUnregisterGlobalsName, 920252723Sdim IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); 921252723Sdim AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage); 922252723Sdim} 923252723Sdim 924245431Sdim// This function replaces all global variables with new variables that have 925245431Sdim// trailing redzones. It also creates a function that poisons 926245431Sdim// redzones and inserts this function into llvm.global_ctors. 927252723Sdimbool AddressSanitizerModule::runOnModule(Module &M) { 928252723Sdim if (!ClGlobals) return false; 929252723Sdim TD = getAnalysisIfAvailable<DataLayout>(); 930252723Sdim if (!TD) 931252723Sdim return false; 932263509Sdim BL.reset(SpecialCaseList::createOrDie(BlacklistFile)); 933252723Sdim if (BL->isIn(M)) return false; 934252723Sdim C = &(M.getContext()); 935252723Sdim int LongSize = TD->getPointerSizeInBits(); 936252723Sdim IntptrTy = Type::getIntNTy(*C, LongSize); 937252723Sdim Mapping = getShadowMapping(M, LongSize, ZeroBaseShadow); 938252723Sdim initializeCallbacks(M); 939252723Sdim DynamicallyInitializedGlobals.Init(M); 940252723Sdim 941245431Sdim SmallVector<GlobalVariable *, 16> GlobalsToChange; 942245431Sdim 943245431Sdim for (Module::GlobalListType::iterator G = M.global_begin(), 944245431Sdim E = M.global_end(); G != E; ++G) { 945245431Sdim if (ShouldInstrumentGlobal(G)) 946245431Sdim GlobalsToChange.push_back(G); 947234285Sdim } 948234285Sdim 949234285Sdim size_t n = GlobalsToChange.size(); 950234285Sdim if (n == 0) return false; 951234285Sdim 952234285Sdim // A global is described by a structure 953234285Sdim // size_t beg; 954234285Sdim // size_t size; 955234285Sdim // size_t size_with_redzone; 956234285Sdim // const char *name; 957252723Sdim // const char *module_name; 958245431Sdim // size_t has_dynamic_init; 959234285Sdim // We initialize an array of such structures and pass it to a run-time call. 960234285Sdim StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy, 961245431Sdim IntptrTy, IntptrTy, 962252723Sdim IntptrTy, IntptrTy, NULL); 963263509Sdim SmallVector<Constant *, 16> Initializers(n); 964234285Sdim 965252723Sdim Function *CtorFunc = M.getFunction(kAsanModuleCtorName); 966252723Sdim assert(CtorFunc); 967252723Sdim IRBuilder<> IRB(CtorFunc->getEntryBlock().getTerminator()); 968245431Sdim 969252723Sdim bool HasDynamicallyInitializedGlobals = false; 970245431Sdim 971252723Sdim GlobalVariable *ModuleName = createPrivateGlobalForString( 972252723Sdim M, M.getModuleIdentifier()); 973252723Sdim // We shouldn't merge same module names, as this string serves as unique 974252723Sdim // module ID in runtime. 975252723Sdim ModuleName->setUnnamedAddr(false); 976252723Sdim 977234285Sdim for (size_t i = 0; i < n; i++) { 978252723Sdim static const uint64_t kMaxGlobalRedzone = 1 << 18; 979234285Sdim GlobalVariable *G = GlobalsToChange[i]; 980234285Sdim PointerType *PtrTy = cast<PointerType>(G->getType()); 981234285Sdim Type *Ty = PtrTy->getElementType(); 982234285Sdim uint64_t SizeInBytes = TD->getTypeAllocSize(Ty); 983252723Sdim uint64_t MinRZ = RedzoneSize(); 984252723Sdim // MinRZ <= RZ <= kMaxGlobalRedzone 985252723Sdim // and trying to make RZ to be ~ 1/4 of SizeInBytes. 986252723Sdim uint64_t RZ = std::max(MinRZ, 987252723Sdim std::min(kMaxGlobalRedzone, 988252723Sdim (SizeInBytes / MinRZ / 4) * MinRZ)); 989252723Sdim uint64_t RightRedzoneSize = RZ; 990252723Sdim // Round up to MinRZ 991252723Sdim if (SizeInBytes % MinRZ) 992252723Sdim RightRedzoneSize += MinRZ - (SizeInBytes % MinRZ); 993252723Sdim assert(((RightRedzoneSize + SizeInBytes) % MinRZ) == 0); 994234285Sdim Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); 995245431Sdim // Determine whether this global should be poisoned in initialization. 996252723Sdim bool GlobalHasDynamicInitializer = 997252723Sdim DynamicallyInitializedGlobals.Contains(G); 998245431Sdim // Don't check initialization order if this global is blacklisted. 999263509Sdim GlobalHasDynamicInitializer &= !BL->isIn(*G, "init"); 1000234285Sdim 1001234285Sdim StructType *NewTy = StructType::get(Ty, RightRedZoneTy, NULL); 1002234285Sdim Constant *NewInitializer = ConstantStruct::get( 1003234285Sdim NewTy, G->getInitializer(), 1004234285Sdim Constant::getNullValue(RightRedZoneTy), NULL); 1005234285Sdim 1006252723Sdim GlobalVariable *Name = createPrivateGlobalForString(M, G->getName()); 1007234285Sdim 1008234285Sdim // Create a new global variable with enough space for a redzone. 1009263509Sdim GlobalValue::LinkageTypes Linkage = G->getLinkage(); 1010263509Sdim if (G->isConstant() && Linkage == GlobalValue::PrivateLinkage) 1011263509Sdim Linkage = GlobalValue::InternalLinkage; 1012234285Sdim GlobalVariable *NewGlobal = new GlobalVariable( 1013263509Sdim M, NewTy, G->isConstant(), Linkage, 1014245431Sdim NewInitializer, "", G, G->getThreadLocalMode()); 1015234285Sdim NewGlobal->copyAttributesFrom(G); 1016252723Sdim NewGlobal->setAlignment(MinRZ); 1017234285Sdim 1018234285Sdim Value *Indices2[2]; 1019234285Sdim Indices2[0] = IRB.getInt32(0); 1020234285Sdim Indices2[1] = IRB.getInt32(0); 1021234285Sdim 1022234285Sdim G->replaceAllUsesWith( 1023234285Sdim ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true)); 1024234285Sdim NewGlobal->takeName(G); 1025234285Sdim G->eraseFromParent(); 1026234285Sdim 1027234285Sdim Initializers[i] = ConstantStruct::get( 1028234285Sdim GlobalStructTy, 1029234285Sdim ConstantExpr::getPointerCast(NewGlobal, IntptrTy), 1030234285Sdim ConstantInt::get(IntptrTy, SizeInBytes), 1031234285Sdim ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), 1032234285Sdim ConstantExpr::getPointerCast(Name, IntptrTy), 1033252723Sdim ConstantExpr::getPointerCast(ModuleName, IntptrTy), 1034245431Sdim ConstantInt::get(IntptrTy, GlobalHasDynamicInitializer), 1035234285Sdim NULL); 1036245431Sdim 1037245431Sdim // Populate the first and last globals declared in this TU. 1038252723Sdim if (CheckInitOrder && GlobalHasDynamicInitializer) 1039252723Sdim HasDynamicallyInitializedGlobals = true; 1040245431Sdim 1041245431Sdim DEBUG(dbgs() << "NEW GLOBAL: " << *NewGlobal << "\n"); 1042234285Sdim } 1043234285Sdim 1044234285Sdim ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n); 1045234285Sdim GlobalVariable *AllGlobals = new GlobalVariable( 1046263509Sdim M, ArrayOfGlobalStructTy, false, GlobalVariable::InternalLinkage, 1047234285Sdim ConstantArray::get(ArrayOfGlobalStructTy, Initializers), ""); 1048234285Sdim 1049245431Sdim // Create calls for poisoning before initializers run and unpoisoning after. 1050252723Sdim if (CheckInitOrder && HasDynamicallyInitializedGlobals) 1051252723Sdim createInitializerPoisonCalls(M, ModuleName); 1052234285Sdim IRB.CreateCall2(AsanRegisterGlobals, 1053234285Sdim IRB.CreatePointerCast(AllGlobals, IntptrTy), 1054234285Sdim ConstantInt::get(IntptrTy, n)); 1055234285Sdim 1056234285Sdim // We also need to unregister globals at the end, e.g. when a shared library 1057234285Sdim // gets closed. 1058234285Sdim Function *AsanDtorFunction = Function::Create( 1059234285Sdim FunctionType::get(Type::getVoidTy(*C), false), 1060234285Sdim GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); 1061234285Sdim BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); 1062234285Sdim IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB)); 1063234285Sdim IRB_Dtor.CreateCall2(AsanUnregisterGlobals, 1064234285Sdim IRB.CreatePointerCast(AllGlobals, IntptrTy), 1065234285Sdim ConstantInt::get(IntptrTy, n)); 1066234285Sdim appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndCtorPriority); 1067234285Sdim 1068234285Sdim DEBUG(dbgs() << M); 1069234285Sdim return true; 1070234285Sdim} 1071234285Sdim 1072252723Sdimvoid AddressSanitizer::initializeCallbacks(Module &M) { 1073252723Sdim IRBuilder<> IRB(*C); 1074245431Sdim // Create __asan_report* callbacks. 1075245431Sdim for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) { 1076245431Sdim for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; 1077245431Sdim AccessSizeIndex++) { 1078245431Sdim // IsWrite and TypeSize are encoded in the function name. 1079245431Sdim std::string FunctionName = std::string(kAsanReportErrorTemplate) + 1080245431Sdim (AccessIsWrite ? "store" : "load") + itostr(1 << AccessSizeIndex); 1081245431Sdim // If we are merging crash callbacks, they have two parameters. 1082245431Sdim AsanErrorCallback[AccessIsWrite][AccessSizeIndex] = 1083245431Sdim checkInterfaceFunction(M.getOrInsertFunction( 1084245431Sdim FunctionName, IRB.getVoidTy(), IntptrTy, NULL)); 1085245431Sdim } 1086245431Sdim } 1087252723Sdim AsanErrorCallbackSized[0] = checkInterfaceFunction(M.getOrInsertFunction( 1088252723Sdim kAsanReportLoadN, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); 1089252723Sdim AsanErrorCallbackSized[1] = checkInterfaceFunction(M.getOrInsertFunction( 1090252723Sdim kAsanReportStoreN, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); 1091245431Sdim 1092245431Sdim AsanHandleNoReturnFunc = checkInterfaceFunction(M.getOrInsertFunction( 1093245431Sdim kAsanHandleNoReturnName, IRB.getVoidTy(), NULL)); 1094263509Sdim AsanCovFunction = checkInterfaceFunction(M.getOrInsertFunction( 1095263509Sdim kAsanCovName, IRB.getVoidTy(), IntptrTy, NULL)); 1096245431Sdim // We insert an empty inline asm after __asan_report* to avoid callback merge. 1097245431Sdim EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), 1098245431Sdim StringRef(""), StringRef(""), 1099245431Sdim /*hasSideEffects=*/true); 1100252723Sdim} 1101245431Sdim 1102252723Sdimvoid AddressSanitizer::emitShadowMapping(Module &M, IRBuilder<> &IRB) const { 1103252723Sdim // Tell the values of mapping offset and scale to the run-time. 1104252723Sdim GlobalValue *asan_mapping_offset = 1105252723Sdim new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage, 1106252723Sdim ConstantInt::get(IntptrTy, Mapping.Offset), 1107252723Sdim kAsanMappingOffsetName); 1108252723Sdim // Read the global, otherwise it may be optimized away. 1109252723Sdim IRB.CreateLoad(asan_mapping_offset, true); 1110245431Sdim 1111252723Sdim GlobalValue *asan_mapping_scale = 1112252723Sdim new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage, 1113252723Sdim ConstantInt::get(IntptrTy, Mapping.Scale), 1114252723Sdim kAsanMappingScaleName); 1115252723Sdim // Read the global, otherwise it may be optimized away. 1116252723Sdim IRB.CreateLoad(asan_mapping_scale, true); 1117252723Sdim} 1118234285Sdim 1119252723Sdim// virtual 1120252723Sdimbool AddressSanitizer::doInitialization(Module &M) { 1121252723Sdim // Initialize the private fields. No one has accessed them before. 1122252723Sdim TD = getAnalysisIfAvailable<DataLayout>(); 1123234285Sdim 1124252723Sdim if (!TD) 1125252723Sdim return false; 1126263509Sdim BL.reset(SpecialCaseList::createOrDie(BlacklistFile)); 1127252723Sdim DynamicallyInitializedGlobals.Init(M); 1128234285Sdim 1129252723Sdim C = &(M.getContext()); 1130252723Sdim LongSize = TD->getPointerSizeInBits(); 1131252723Sdim IntptrTy = Type::getIntNTy(*C, LongSize); 1132252723Sdim 1133252723Sdim AsanCtorFunction = Function::Create( 1134252723Sdim FunctionType::get(Type::getVoidTy(*C), false), 1135252723Sdim GlobalValue::InternalLinkage, kAsanModuleCtorName, &M); 1136252723Sdim BasicBlock *AsanCtorBB = BasicBlock::Create(*C, "", AsanCtorFunction); 1137252723Sdim // call __asan_init in the module ctor. 1138252723Sdim IRBuilder<> IRB(ReturnInst::Create(*C, AsanCtorBB)); 1139252723Sdim AsanInitFunction = checkInterfaceFunction( 1140252723Sdim M.getOrInsertFunction(kAsanInitName, IRB.getVoidTy(), NULL)); 1141252723Sdim AsanInitFunction->setLinkage(Function::ExternalLinkage); 1142252723Sdim IRB.CreateCall(AsanInitFunction); 1143252723Sdim 1144252723Sdim Mapping = getShadowMapping(M, LongSize, ZeroBaseShadow); 1145252723Sdim emitShadowMapping(M, IRB); 1146252723Sdim 1147234285Sdim appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndCtorPriority); 1148245431Sdim return true; 1149234285Sdim} 1150234285Sdim 1151234285Sdimbool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) { 1152234285Sdim // For each NSObject descendant having a +load method, this method is invoked 1153234285Sdim // by the ObjC runtime before any of the static constructors is called. 1154234285Sdim // Therefore we need to instrument such methods with a call to __asan_init 1155234285Sdim // at the beginning in order to initialize our runtime before any access to 1156234285Sdim // the shadow memory. 1157234285Sdim // We cannot just ignore these methods, because they may call other 1158234285Sdim // instrumented functions. 1159234285Sdim if (F.getName().find(" load]") != std::string::npos) { 1160234285Sdim IRBuilder<> IRB(F.begin()->begin()); 1161234285Sdim IRB.CreateCall(AsanInitFunction); 1162234285Sdim return true; 1163234285Sdim } 1164234285Sdim return false; 1165234285Sdim} 1166234285Sdim 1167263509Sdim// Poor man's coverage that works with ASan. 1168263509Sdim// We create a Guard boolean variable with the same linkage 1169263509Sdim// as the function and inject this code into the entry block: 1170263509Sdim// if (*Guard) { 1171263509Sdim// __sanitizer_cov(&F); 1172263509Sdim// *Guard = 1; 1173263509Sdim// } 1174263509Sdim// The accesses to Guard are atomic. The rest of the logic is 1175263509Sdim// in __sanitizer_cov (it's fine to call it more than once). 1176263509Sdim// 1177263509Sdim// This coverage implementation provides very limited data: 1178263509Sdim// it only tells if a given function was ever executed. 1179263509Sdim// No counters, no per-basic-block or per-edge data. 1180263509Sdim// But for many use cases this is what we need and the added slowdown 1181263509Sdim// is negligible. This simple implementation will probably be obsoleted 1182263509Sdim// by the upcoming Clang-based coverage implementation. 1183263509Sdim// By having it here and now we hope to 1184263509Sdim// a) get the functionality to users earlier and 1185263509Sdim// b) collect usage statistics to help improve Clang coverage design. 1186263509Sdimbool AddressSanitizer::InjectCoverage(Function &F) { 1187263509Sdim if (!ClCoverage) return false; 1188263509Sdim IRBuilder<> IRB(F.getEntryBlock().getFirstInsertionPt()); 1189263509Sdim Type *Int8Ty = IRB.getInt8Ty(); 1190263509Sdim GlobalVariable *Guard = new GlobalVariable( 1191263509Sdim *F.getParent(), Int8Ty, false, GlobalValue::PrivateLinkage, 1192263509Sdim Constant::getNullValue(Int8Ty), "__asan_gen_cov_" + F.getName()); 1193263509Sdim LoadInst *Load = IRB.CreateLoad(Guard); 1194263509Sdim Load->setAtomic(Monotonic); 1195263509Sdim Load->setAlignment(1); 1196263509Sdim Value *Cmp = IRB.CreateICmpEQ(Constant::getNullValue(Int8Ty), Load); 1197263509Sdim Instruction *Ins = SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); 1198263509Sdim IRB.SetInsertPoint(Ins); 1199263509Sdim // We pass &F to __sanitizer_cov. We could avoid this and rely on 1200263509Sdim // GET_CALLER_PC, but having the PC of the first instruction is just nice. 1201263509Sdim IRB.CreateCall(AsanCovFunction, IRB.CreatePointerCast(&F, IntptrTy)); 1202263509Sdim StoreInst *Store = IRB.CreateStore(ConstantInt::get(Int8Ty, 1), Guard); 1203263509Sdim Store->setAtomic(Monotonic); 1204263509Sdim Store->setAlignment(1); 1205263509Sdim return true; 1206263509Sdim} 1207263509Sdim 1208245431Sdimbool AddressSanitizer::runOnFunction(Function &F) { 1209234285Sdim if (BL->isIn(F)) return false; 1210234285Sdim if (&F == AsanCtorFunction) return false; 1211252723Sdim if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return false; 1212245431Sdim DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n"); 1213252723Sdim initializeCallbacks(*F.getParent()); 1214234285Sdim 1215252723Sdim // If needed, insert __asan_init before checking for SanitizeAddress attr. 1216234285Sdim maybeInsertAsanInitAtFunctionEntry(F); 1217234285Sdim 1218263509Sdim if (!F.hasFnAttribute(Attribute::SanitizeAddress)) 1219245431Sdim return false; 1220234285Sdim 1221234285Sdim if (!ClDebugFunc.empty() && ClDebugFunc != F.getName()) 1222234285Sdim return false; 1223245431Sdim 1224245431Sdim // We want to instrument every address only once per basic block (unless there 1225245431Sdim // are calls between uses). 1226234285Sdim SmallSet<Value*, 16> TempsToInstrument; 1227234285Sdim SmallVector<Instruction*, 16> ToInstrument; 1228234285Sdim SmallVector<Instruction*, 8> NoReturnCalls; 1229263509Sdim int NumAllocas = 0; 1230245431Sdim bool IsWrite; 1231234285Sdim 1232234285Sdim // Fill the set of memory operations to instrument. 1233234285Sdim for (Function::iterator FI = F.begin(), FE = F.end(); 1234234285Sdim FI != FE; ++FI) { 1235234285Sdim TempsToInstrument.clear(); 1236245431Sdim int NumInsnsPerBB = 0; 1237234285Sdim for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); 1238234285Sdim BI != BE; ++BI) { 1239234285Sdim if (LooksLikeCodeInBug11395(BI)) return false; 1240245431Sdim if (Value *Addr = isInterestingMemoryAccess(BI, &IsWrite)) { 1241234285Sdim if (ClOpt && ClOptSameTemp) { 1242234285Sdim if (!TempsToInstrument.insert(Addr)) 1243234285Sdim continue; // We've seen this temp in the current BB. 1244234285Sdim } 1245234285Sdim } else if (isa<MemIntrinsic>(BI) && ClMemIntrin) { 1246234285Sdim // ok, take it. 1247234285Sdim } else { 1248263509Sdim if (isa<AllocaInst>(BI)) 1249263509Sdim NumAllocas++; 1250252723Sdim CallSite CS(BI); 1251252723Sdim if (CS) { 1252234285Sdim // A call inside BB. 1253234285Sdim TempsToInstrument.clear(); 1254252723Sdim if (CS.doesNotReturn()) 1255252723Sdim NoReturnCalls.push_back(CS.getInstruction()); 1256234285Sdim } 1257234285Sdim continue; 1258234285Sdim } 1259234285Sdim ToInstrument.push_back(BI); 1260245431Sdim NumInsnsPerBB++; 1261245431Sdim if (NumInsnsPerBB >= ClMaxInsnsToInstrumentPerBB) 1262245431Sdim break; 1263234285Sdim } 1264234285Sdim } 1265234285Sdim 1266263509Sdim Function *UninstrumentedDuplicate = 0; 1267263509Sdim bool LikelyToInstrument = 1268263509Sdim !NoReturnCalls.empty() || !ToInstrument.empty() || (NumAllocas > 0); 1269263509Sdim if (ClKeepUninstrumented && LikelyToInstrument) { 1270263509Sdim ValueToValueMapTy VMap; 1271263509Sdim UninstrumentedDuplicate = CloneFunction(&F, VMap, false); 1272263509Sdim UninstrumentedDuplicate->removeFnAttr(Attribute::SanitizeAddress); 1273263509Sdim UninstrumentedDuplicate->setName("NOASAN_" + F.getName()); 1274263509Sdim F.getParent()->getFunctionList().push_back(UninstrumentedDuplicate); 1275263509Sdim } 1276263509Sdim 1277234285Sdim // Instrument. 1278234285Sdim int NumInstrumented = 0; 1279234285Sdim for (size_t i = 0, n = ToInstrument.size(); i != n; i++) { 1280234285Sdim Instruction *Inst = ToInstrument[i]; 1281234285Sdim if (ClDebugMin < 0 || ClDebugMax < 0 || 1282234285Sdim (NumInstrumented >= ClDebugMin && NumInstrumented <= ClDebugMax)) { 1283245431Sdim if (isInterestingMemoryAccess(Inst, &IsWrite)) 1284234285Sdim instrumentMop(Inst); 1285234285Sdim else 1286234285Sdim instrumentMemIntrinsic(cast<MemIntrinsic>(Inst)); 1287234285Sdim } 1288234285Sdim NumInstrumented++; 1289234285Sdim } 1290234285Sdim 1291252723Sdim FunctionStackPoisoner FSP(F, *this); 1292252723Sdim bool ChangedStack = FSP.runOnFunction(); 1293234285Sdim 1294234285Sdim // We must unpoison the stack before every NoReturn call (throw, _exit, etc). 1295234285Sdim // See e.g. http://code.google.com/p/address-sanitizer/issues/detail?id=37 1296234285Sdim for (size_t i = 0, n = NoReturnCalls.size(); i != n; i++) { 1297234285Sdim Instruction *CI = NoReturnCalls[i]; 1298234285Sdim IRBuilder<> IRB(CI); 1299245431Sdim IRB.CreateCall(AsanHandleNoReturnFunc); 1300234285Sdim } 1301234285Sdim 1302263509Sdim bool res = NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty(); 1303263509Sdim 1304263509Sdim if (InjectCoverage(F)) 1305263509Sdim res = true; 1306263509Sdim 1307263509Sdim DEBUG(dbgs() << "ASAN done instrumenting: " << res << " " << F << "\n"); 1308263509Sdim 1309263509Sdim if (ClKeepUninstrumented) { 1310263509Sdim if (!res) { 1311263509Sdim // No instrumentation is done, no need for the duplicate. 1312263509Sdim if (UninstrumentedDuplicate) 1313263509Sdim UninstrumentedDuplicate->eraseFromParent(); 1314263509Sdim } else { 1315263509Sdim // The function was instrumented. We must have the duplicate. 1316263509Sdim assert(UninstrumentedDuplicate); 1317263509Sdim UninstrumentedDuplicate->setSection("NOASAN"); 1318263509Sdim assert(!F.hasSection()); 1319263509Sdim F.setSection("ASAN"); 1320263509Sdim } 1321263509Sdim } 1322263509Sdim 1323263509Sdim return res; 1324234285Sdim} 1325234285Sdim 1326234285Sdimstatic uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize) { 1327234285Sdim if (ShadowRedzoneSize == 1) return PoisonByte; 1328234285Sdim if (ShadowRedzoneSize == 2) return (PoisonByte << 8) + PoisonByte; 1329234285Sdim if (ShadowRedzoneSize == 4) 1330234285Sdim return (PoisonByte << 24) + (PoisonByte << 16) + 1331234285Sdim (PoisonByte << 8) + (PoisonByte); 1332234285Sdim llvm_unreachable("ShadowRedzoneSize is either 1, 2 or 4"); 1333234285Sdim} 1334234285Sdim 1335234285Sdimstatic void PoisonShadowPartialRightRedzone(uint8_t *Shadow, 1336234285Sdim size_t Size, 1337252723Sdim size_t RZSize, 1338234285Sdim size_t ShadowGranularity, 1339234285Sdim uint8_t Magic) { 1340252723Sdim for (size_t i = 0; i < RZSize; 1341234285Sdim i+= ShadowGranularity, Shadow++) { 1342234285Sdim if (i + ShadowGranularity <= Size) { 1343234285Sdim *Shadow = 0; // fully addressable 1344234285Sdim } else if (i >= Size) { 1345234285Sdim *Shadow = Magic; // unaddressable 1346234285Sdim } else { 1347234285Sdim *Shadow = Size - i; // first Size-i bytes are addressable 1348234285Sdim } 1349234285Sdim } 1350234285Sdim} 1351234285Sdim 1352252723Sdim// Workaround for bug 11395: we don't want to instrument stack in functions 1353252723Sdim// with large assembly blobs (32-bit only), otherwise reg alloc may crash. 1354252723Sdim// FIXME: remove once the bug 11395 is fixed. 1355252723Sdimbool AddressSanitizer::LooksLikeCodeInBug11395(Instruction *I) { 1356252723Sdim if (LongSize != 32) return false; 1357252723Sdim CallInst *CI = dyn_cast<CallInst>(I); 1358252723Sdim if (!CI || !CI->isInlineAsm()) return false; 1359252723Sdim if (CI->getNumArgOperands() <= 5) return false; 1360252723Sdim // We have inline assembly with quite a few arguments. 1361252723Sdim return true; 1362252723Sdim} 1363252723Sdim 1364252723Sdimvoid FunctionStackPoisoner::initializeCallbacks(Module &M) { 1365252723Sdim IRBuilder<> IRB(*C); 1366263509Sdim for (int i = 0; i <= kMaxAsanStackMallocSizeClass; i++) { 1367263509Sdim std::string Suffix = itostr(i); 1368263509Sdim AsanStackMallocFunc[i] = checkInterfaceFunction( 1369263509Sdim M.getOrInsertFunction(kAsanStackMallocNameTemplate + Suffix, IntptrTy, 1370263509Sdim IntptrTy, IntptrTy, NULL)); 1371263509Sdim AsanStackFreeFunc[i] = checkInterfaceFunction(M.getOrInsertFunction( 1372263509Sdim kAsanStackFreeNameTemplate + Suffix, IRB.getVoidTy(), IntptrTy, 1373263509Sdim IntptrTy, IntptrTy, NULL)); 1374263509Sdim } 1375252723Sdim AsanPoisonStackMemoryFunc = checkInterfaceFunction(M.getOrInsertFunction( 1376252723Sdim kAsanPoisonStackMemoryName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); 1377252723Sdim AsanUnpoisonStackMemoryFunc = checkInterfaceFunction(M.getOrInsertFunction( 1378252723Sdim kAsanUnpoisonStackMemoryName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); 1379252723Sdim} 1380252723Sdim 1381252723Sdimvoid FunctionStackPoisoner::poisonRedZones( 1382263509Sdim const ArrayRef<AllocaInst*> &AllocaVec, IRBuilder<> &IRB, Value *ShadowBase, 1383252723Sdim bool DoPoison) { 1384252723Sdim size_t ShadowRZSize = RedzoneSize() >> Mapping.Scale; 1385234285Sdim assert(ShadowRZSize >= 1 && ShadowRZSize <= 4); 1386234285Sdim Type *RZTy = Type::getIntNTy(*C, ShadowRZSize * 8); 1387234285Sdim Type *RZPtrTy = PointerType::get(RZTy, 0); 1388234285Sdim 1389234285Sdim Value *PoisonLeft = ConstantInt::get(RZTy, 1390234285Sdim ValueForPoison(DoPoison ? kAsanStackLeftRedzoneMagic : 0LL, ShadowRZSize)); 1391234285Sdim Value *PoisonMid = ConstantInt::get(RZTy, 1392234285Sdim ValueForPoison(DoPoison ? kAsanStackMidRedzoneMagic : 0LL, ShadowRZSize)); 1393234285Sdim Value *PoisonRight = ConstantInt::get(RZTy, 1394234285Sdim ValueForPoison(DoPoison ? kAsanStackRightRedzoneMagic : 0LL, ShadowRZSize)); 1395234285Sdim 1396234285Sdim // poison the first red zone. 1397234285Sdim IRB.CreateStore(PoisonLeft, IRB.CreateIntToPtr(ShadowBase, RZPtrTy)); 1398234285Sdim 1399234285Sdim // poison all other red zones. 1400252723Sdim uint64_t Pos = RedzoneSize(); 1401234285Sdim for (size_t i = 0, n = AllocaVec.size(); i < n; i++) { 1402234285Sdim AllocaInst *AI = AllocaVec[i]; 1403234285Sdim uint64_t SizeInBytes = getAllocaSizeInBytes(AI); 1404234285Sdim uint64_t AlignedSize = getAlignedAllocaSize(AI); 1405252723Sdim assert(AlignedSize - SizeInBytes < RedzoneSize()); 1406234285Sdim Value *Ptr = NULL; 1407234285Sdim 1408234285Sdim Pos += AlignedSize; 1409234285Sdim 1410234285Sdim assert(ShadowBase->getType() == IntptrTy); 1411234285Sdim if (SizeInBytes < AlignedSize) { 1412234285Sdim // Poison the partial redzone at right 1413234285Sdim Ptr = IRB.CreateAdd( 1414234285Sdim ShadowBase, ConstantInt::get(IntptrTy, 1415252723Sdim (Pos >> Mapping.Scale) - ShadowRZSize)); 1416252723Sdim size_t AddressableBytes = RedzoneSize() - (AlignedSize - SizeInBytes); 1417234285Sdim uint32_t Poison = 0; 1418234285Sdim if (DoPoison) { 1419234285Sdim PoisonShadowPartialRightRedzone((uint8_t*)&Poison, AddressableBytes, 1420252723Sdim RedzoneSize(), 1421252723Sdim 1ULL << Mapping.Scale, 1422234285Sdim kAsanStackPartialRedzoneMagic); 1423263509Sdim Poison = 1424263509Sdim ASan.TD->isLittleEndian() 1425263509Sdim ? support::endian::byte_swap<uint32_t, support::little>(Poison) 1426263509Sdim : support::endian::byte_swap<uint32_t, support::big>(Poison); 1427234285Sdim } 1428234285Sdim Value *PartialPoison = ConstantInt::get(RZTy, Poison); 1429234285Sdim IRB.CreateStore(PartialPoison, IRB.CreateIntToPtr(Ptr, RZPtrTy)); 1430234285Sdim } 1431234285Sdim 1432234285Sdim // Poison the full redzone at right. 1433234285Sdim Ptr = IRB.CreateAdd(ShadowBase, 1434252723Sdim ConstantInt::get(IntptrTy, Pos >> Mapping.Scale)); 1435252723Sdim bool LastAlloca = (i == AllocaVec.size() - 1); 1436252723Sdim Value *Poison = LastAlloca ? PoisonRight : PoisonMid; 1437234285Sdim IRB.CreateStore(Poison, IRB.CreateIntToPtr(Ptr, RZPtrTy)); 1438234285Sdim 1439252723Sdim Pos += RedzoneSize(); 1440234285Sdim } 1441234285Sdim} 1442234285Sdim 1443263509Sdim// Fake stack allocator (asan_fake_stack.h) has 11 size classes 1444263509Sdim// for every power of 2 from kMinStackMallocSize to kMaxAsanStackMallocSizeClass 1445263509Sdimstatic int StackMallocSizeClass(uint64_t LocalStackSize) { 1446263509Sdim assert(LocalStackSize <= kMaxStackMallocSize); 1447263509Sdim uint64_t MaxSize = kMinStackMallocSize; 1448263509Sdim for (int i = 0; ; i++, MaxSize *= 2) 1449263509Sdim if (LocalStackSize <= MaxSize) 1450263509Sdim return i; 1451263509Sdim llvm_unreachable("impossible LocalStackSize"); 1452263509Sdim} 1453263509Sdim 1454263509Sdim// Set Size bytes starting from ShadowBase to kAsanStackAfterReturnMagic. 1455263509Sdim// We can not use MemSet intrinsic because it may end up calling the actual 1456263509Sdim// memset. Size is a multiple of 8. 1457263509Sdim// Currently this generates 8-byte stores on x86_64; it may be better to 1458263509Sdim// generate wider stores. 1459263509Sdimvoid FunctionStackPoisoner::SetShadowToStackAfterReturnInlined( 1460263509Sdim IRBuilder<> &IRB, Value *ShadowBase, int Size) { 1461263509Sdim assert(!(Size % 8)); 1462263509Sdim assert(kAsanStackAfterReturnMagic == 0xf5); 1463263509Sdim for (int i = 0; i < Size; i += 8) { 1464263509Sdim Value *p = IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)); 1465263509Sdim IRB.CreateStore(ConstantInt::get(IRB.getInt64Ty(), 0xf5f5f5f5f5f5f5f5ULL), 1466263509Sdim IRB.CreateIntToPtr(p, IRB.getInt64Ty()->getPointerTo())); 1467263509Sdim } 1468263509Sdim} 1469263509Sdim 1470252723Sdimvoid FunctionStackPoisoner::poisonStack() { 1471252723Sdim uint64_t LocalStackSize = TotalStackSize + 1472252723Sdim (AllocaVec.size() + 1) * RedzoneSize(); 1473234285Sdim 1474252723Sdim bool DoStackMalloc = ASan.CheckUseAfterReturn 1475234285Sdim && LocalStackSize <= kMaxStackMallocSize; 1476263509Sdim int StackMallocIdx = -1; 1477234285Sdim 1478252723Sdim assert(AllocaVec.size() > 0); 1479234285Sdim Instruction *InsBefore = AllocaVec[0]; 1480234285Sdim IRBuilder<> IRB(InsBefore); 1481234285Sdim 1482234285Sdim 1483234285Sdim Type *ByteArrayTy = ArrayType::get(IRB.getInt8Ty(), LocalStackSize); 1484234285Sdim AllocaInst *MyAlloca = 1485234285Sdim new AllocaInst(ByteArrayTy, "MyAlloca", InsBefore); 1486252723Sdim if (ClRealignStack && StackAlignment < RedzoneSize()) 1487252723Sdim StackAlignment = RedzoneSize(); 1488252723Sdim MyAlloca->setAlignment(StackAlignment); 1489234285Sdim assert(MyAlloca->isStaticAlloca()); 1490234285Sdim Value *OrigStackBase = IRB.CreatePointerCast(MyAlloca, IntptrTy); 1491234285Sdim Value *LocalStackBase = OrigStackBase; 1492234285Sdim 1493234285Sdim if (DoStackMalloc) { 1494263509Sdim // LocalStackBase = OrigStackBase 1495263509Sdim // if (__asan_option_detect_stack_use_after_return) 1496263509Sdim // LocalStackBase = __asan_stack_malloc_N(LocalStackBase, OrigStackBase); 1497263509Sdim StackMallocIdx = StackMallocSizeClass(LocalStackSize); 1498263509Sdim assert(StackMallocIdx <= kMaxAsanStackMallocSizeClass); 1499263509Sdim Constant *OptionDetectUAR = F.getParent()->getOrInsertGlobal( 1500263509Sdim kAsanOptionDetectUAR, IRB.getInt32Ty()); 1501263509Sdim Value *Cmp = IRB.CreateICmpNE(IRB.CreateLoad(OptionDetectUAR), 1502263509Sdim Constant::getNullValue(IRB.getInt32Ty())); 1503263509Sdim Instruction *Term = 1504263509Sdim SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); 1505263509Sdim BasicBlock *CmpBlock = cast<Instruction>(Cmp)->getParent(); 1506263509Sdim IRBuilder<> IRBIf(Term); 1507263509Sdim LocalStackBase = IRBIf.CreateCall2( 1508263509Sdim AsanStackMallocFunc[StackMallocIdx], 1509234285Sdim ConstantInt::get(IntptrTy, LocalStackSize), OrigStackBase); 1510263509Sdim BasicBlock *SetBlock = cast<Instruction>(LocalStackBase)->getParent(); 1511263509Sdim IRB.SetInsertPoint(InsBefore); 1512263509Sdim PHINode *Phi = IRB.CreatePHI(IntptrTy, 2); 1513263509Sdim Phi->addIncoming(OrigStackBase, CmpBlock); 1514263509Sdim Phi->addIncoming(LocalStackBase, SetBlock); 1515263509Sdim LocalStackBase = Phi; 1516234285Sdim } 1517234285Sdim 1518252723Sdim // This string will be parsed by the run-time (DescribeAddressIfStack). 1519234285Sdim SmallString<2048> StackDescriptionStorage; 1520234285Sdim raw_svector_ostream StackDescription(StackDescriptionStorage); 1521252723Sdim StackDescription << AllocaVec.size() << " "; 1522234285Sdim 1523252723Sdim // Insert poison calls for lifetime intrinsics for alloca. 1524252723Sdim bool HavePoisonedAllocas = false; 1525252723Sdim for (size_t i = 0, n = AllocaPoisonCallVec.size(); i < n; i++) { 1526252723Sdim const AllocaPoisonCall &APC = AllocaPoisonCallVec[i]; 1527263509Sdim assert(APC.InsBefore); 1528263509Sdim assert(APC.AI); 1529263509Sdim IRBuilder<> IRB(APC.InsBefore); 1530263509Sdim poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison); 1531252723Sdim HavePoisonedAllocas |= APC.DoPoison; 1532252723Sdim } 1533252723Sdim 1534252723Sdim uint64_t Pos = RedzoneSize(); 1535234285Sdim // Replace Alloca instructions with base+offset. 1536234285Sdim for (size_t i = 0, n = AllocaVec.size(); i < n; i++) { 1537234285Sdim AllocaInst *AI = AllocaVec[i]; 1538234285Sdim uint64_t SizeInBytes = getAllocaSizeInBytes(AI); 1539234285Sdim StringRef Name = AI->getName(); 1540234285Sdim StackDescription << Pos << " " << SizeInBytes << " " 1541234285Sdim << Name.size() << " " << Name << " "; 1542234285Sdim uint64_t AlignedSize = getAlignedAllocaSize(AI); 1543252723Sdim assert((AlignedSize % RedzoneSize()) == 0); 1544252723Sdim Value *NewAllocaPtr = IRB.CreateIntToPtr( 1545234285Sdim IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Pos)), 1546252723Sdim AI->getType()); 1547252723Sdim replaceDbgDeclareForAlloca(AI, NewAllocaPtr, DIB); 1548252723Sdim AI->replaceAllUsesWith(NewAllocaPtr); 1549252723Sdim Pos += AlignedSize + RedzoneSize(); 1550234285Sdim } 1551234285Sdim assert(Pos == LocalStackSize); 1552234285Sdim 1553252723Sdim // The left-most redzone has enough space for at least 4 pointers. 1554252723Sdim // Write the Magic value to redzone[0]. 1555234285Sdim Value *BasePlus0 = IRB.CreateIntToPtr(LocalStackBase, IntptrPtrTy); 1556234285Sdim IRB.CreateStore(ConstantInt::get(IntptrTy, kCurrentStackFrameMagic), 1557234285Sdim BasePlus0); 1558252723Sdim // Write the frame description constant to redzone[1]. 1559252723Sdim Value *BasePlus1 = IRB.CreateIntToPtr( 1560252723Sdim IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, ASan.LongSize/8)), 1561252723Sdim IntptrPtrTy); 1562245431Sdim GlobalVariable *StackDescriptionGlobal = 1563245431Sdim createPrivateGlobalForString(*F.getParent(), StackDescription.str()); 1564252723Sdim Value *Description = IRB.CreatePointerCast(StackDescriptionGlobal, 1565252723Sdim IntptrTy); 1566234285Sdim IRB.CreateStore(Description, BasePlus1); 1567252723Sdim // Write the PC to redzone[2]. 1568252723Sdim Value *BasePlus2 = IRB.CreateIntToPtr( 1569252723Sdim IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, 1570252723Sdim 2 * ASan.LongSize/8)), 1571252723Sdim IntptrPtrTy); 1572252723Sdim IRB.CreateStore(IRB.CreatePointerCast(&F, IntptrTy), BasePlus2); 1573234285Sdim 1574234285Sdim // Poison the stack redzones at the entry. 1575252723Sdim Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB); 1576252723Sdim poisonRedZones(AllocaVec, IRB, ShadowBase, true); 1577234285Sdim 1578234285Sdim // Unpoison the stack before all ret instructions. 1579234285Sdim for (size_t i = 0, n = RetVec.size(); i < n; i++) { 1580234285Sdim Instruction *Ret = RetVec[i]; 1581234285Sdim IRBuilder<> IRBRet(Ret); 1582234285Sdim // Mark the current frame as retired. 1583234285Sdim IRBRet.CreateStore(ConstantInt::get(IntptrTy, kRetiredStackFrameMagic), 1584234285Sdim BasePlus0); 1585234285Sdim // Unpoison the stack. 1586252723Sdim poisonRedZones(AllocaVec, IRBRet, ShadowBase, false); 1587234285Sdim if (DoStackMalloc) { 1588263509Sdim assert(StackMallocIdx >= 0); 1589252723Sdim // In use-after-return mode, mark the whole stack frame unaddressable. 1590263509Sdim if (StackMallocIdx <= 4) { 1591263509Sdim // For small sizes inline the whole thing: 1592263509Sdim // if LocalStackBase != OrigStackBase: 1593263509Sdim // memset(ShadowBase, kAsanStackAfterReturnMagic, ShadowSize); 1594263509Sdim // **SavedFlagPtr(LocalStackBase) = 0 1595263509Sdim // FIXME: if LocalStackBase != OrigStackBase don't call poisonRedZones. 1596263509Sdim Value *Cmp = IRBRet.CreateICmpNE(LocalStackBase, OrigStackBase); 1597263509Sdim TerminatorInst *PoisonTerm = 1598263509Sdim SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); 1599263509Sdim IRBuilder<> IRBPoison(PoisonTerm); 1600263509Sdim int ClassSize = kMinStackMallocSize << StackMallocIdx; 1601263509Sdim SetShadowToStackAfterReturnInlined(IRBPoison, ShadowBase, 1602263509Sdim ClassSize >> Mapping.Scale); 1603263509Sdim Value *SavedFlagPtrPtr = IRBPoison.CreateAdd( 1604263509Sdim LocalStackBase, 1605263509Sdim ConstantInt::get(IntptrTy, ClassSize - ASan.LongSize / 8)); 1606263509Sdim Value *SavedFlagPtr = IRBPoison.CreateLoad( 1607263509Sdim IRBPoison.CreateIntToPtr(SavedFlagPtrPtr, IntptrPtrTy)); 1608263509Sdim IRBPoison.CreateStore( 1609263509Sdim Constant::getNullValue(IRBPoison.getInt8Ty()), 1610263509Sdim IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getInt8PtrTy())); 1611263509Sdim } else { 1612263509Sdim // For larger frames call __asan_stack_free_*. 1613263509Sdim IRBRet.CreateCall3(AsanStackFreeFunc[StackMallocIdx], LocalStackBase, 1614263509Sdim ConstantInt::get(IntptrTy, LocalStackSize), 1615263509Sdim OrigStackBase); 1616263509Sdim } 1617252723Sdim } else if (HavePoisonedAllocas) { 1618252723Sdim // If we poisoned some allocas in llvm.lifetime analysis, 1619252723Sdim // unpoison whole stack frame now. 1620252723Sdim assert(LocalStackBase == OrigStackBase); 1621252723Sdim poisonAlloca(LocalStackBase, LocalStackSize, IRBRet, false); 1622234285Sdim } 1623234285Sdim } 1624234285Sdim 1625245431Sdim // We are done. Remove the old unused alloca instructions. 1626245431Sdim for (size_t i = 0, n = AllocaVec.size(); i < n; i++) 1627245431Sdim AllocaVec[i]->eraseFromParent(); 1628252723Sdim} 1629245431Sdim 1630252723Sdimvoid FunctionStackPoisoner::poisonAlloca(Value *V, uint64_t Size, 1631263509Sdim IRBuilder<> &IRB, bool DoPoison) { 1632252723Sdim // For now just insert the call to ASan runtime. 1633252723Sdim Value *AddrArg = IRB.CreatePointerCast(V, IntptrTy); 1634252723Sdim Value *SizeArg = ConstantInt::get(IntptrTy, Size); 1635252723Sdim IRB.CreateCall2(DoPoison ? AsanPoisonStackMemoryFunc 1636252723Sdim : AsanUnpoisonStackMemoryFunc, 1637252723Sdim AddrArg, SizeArg); 1638252723Sdim} 1639252723Sdim 1640252723Sdim// Handling llvm.lifetime intrinsics for a given %alloca: 1641252723Sdim// (1) collect all llvm.lifetime.xxx(%size, %value) describing the alloca. 1642252723Sdim// (2) if %size is constant, poison memory for llvm.lifetime.end (to detect 1643252723Sdim// invalid accesses) and unpoison it for llvm.lifetime.start (the memory 1644252723Sdim// could be poisoned by previous llvm.lifetime.end instruction, as the 1645252723Sdim// variable may go in and out of scope several times, e.g. in loops). 1646252723Sdim// (3) if we poisoned at least one %alloca in a function, 1647252723Sdim// unpoison the whole stack frame at function exit. 1648252723Sdim 1649252723SdimAllocaInst *FunctionStackPoisoner::findAllocaForValue(Value *V) { 1650252723Sdim if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) 1651252723Sdim // We're intested only in allocas we can handle. 1652252723Sdim return isInterestingAlloca(*AI) ? AI : 0; 1653252723Sdim // See if we've already calculated (or started to calculate) alloca for a 1654252723Sdim // given value. 1655252723Sdim AllocaForValueMapTy::iterator I = AllocaForValue.find(V); 1656252723Sdim if (I != AllocaForValue.end()) 1657252723Sdim return I->second; 1658252723Sdim // Store 0 while we're calculating alloca for value V to avoid 1659252723Sdim // infinite recursion if the value references itself. 1660252723Sdim AllocaForValue[V] = 0; 1661252723Sdim AllocaInst *Res = 0; 1662252723Sdim if (CastInst *CI = dyn_cast<CastInst>(V)) 1663252723Sdim Res = findAllocaForValue(CI->getOperand(0)); 1664252723Sdim else if (PHINode *PN = dyn_cast<PHINode>(V)) { 1665252723Sdim for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { 1666252723Sdim Value *IncValue = PN->getIncomingValue(i); 1667252723Sdim // Allow self-referencing phi-nodes. 1668252723Sdim if (IncValue == PN) continue; 1669252723Sdim AllocaInst *IncValueAI = findAllocaForValue(IncValue); 1670252723Sdim // AI for incoming values should exist and should all be equal. 1671252723Sdim if (IncValueAI == 0 || (Res != 0 && IncValueAI != Res)) 1672252723Sdim return 0; 1673252723Sdim Res = IncValueAI; 1674252723Sdim } 1675234285Sdim } 1676252723Sdim if (Res != 0) 1677252723Sdim AllocaForValue[V] = Res; 1678252723Sdim return Res; 1679234285Sdim} 1680