AddressSanitizer.cpp revision 6948897e478cbd66626159776a8017b3c18579b9
1800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany//===-- AddressSanitizer.cpp - memory error detector ------------*- C++ -*-===// 2800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// 3800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// The LLVM Compiler Infrastructure 4800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// 5800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// This file is distributed under the University of Illinois Open Source 6800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// License. See LICENSE.TXT for details. 7800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// 8800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany//===----------------------------------------------------------------------===// 9800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// 10800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 11800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// Details of the algorithm: 12800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm 13800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// 14800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany//===----------------------------------------------------------------------===// 15800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Transforms/Instrumentation.h" 17800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/ADT/ArrayRef.h" 181c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov#include "llvm/ADT/DenseMap.h" 19c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include "llvm/ADT/DenseSet.h" 2059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov#include "llvm/ADT/DepthFirstIterator.h" 21800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/ADT/SmallSet.h" 22800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/ADT/SmallString.h" 23800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/ADT/SmallVector.h" 243386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany#include "llvm/ADT/Statistic.h" 25800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/ADT/StringExtras.h" 2606fdbaa9145f01a291d4981ca5120b7bdcad44c6Evgeniy Stepanov#include "llvm/ADT/Triple.h" 274c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/Analysis/MemoryBuiltins.h" 284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/Analysis/TargetLibraryInfo.h" 294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/Analysis/ValueTracking.h" 3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/CallSite.h" 3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DIBuilder.h" 320b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DataLayout.h" 33ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/IR/Dominators.h" 340b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h" 350b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IRBuilder.h" 360b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/InlineAsm.h" 3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/InstVisitor.h" 380b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IntrinsicInst.h" 390b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h" 4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/MDBuilder.h" 410b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h" 420b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Type.h" 43ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/MC/MCSectionMachO.h" 44800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/Support/CommandLine.h" 45800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/Support/DataTypes.h" 46800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/Support/Debug.h" 473e1d45bf44f882f3ee139d452dd50305d831a341Kostya Serebryany#include "llvm/Support/Endian.h" 48ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Support/SwapByteOrder.h" 494c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/Support/raw_ostream.h" 5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/Transforms/Scalar.h" 5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Transforms/Utils/ASanStackFrameLayout.h" 52800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/Transforms/Utils/BasicBlockUtils.h" 5320985711c76b8799d689a9c0e416b68896333c23Kostya Serebryany#include "llvm/Transforms/Utils/Cloning.h" 541afbb517965e29b07cb42e2335d5eadd87de6535Alexey Samsonov#include "llvm/Transforms/Utils/Local.h" 55800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "llvm/Transforms/Utils/ModuleUtils.h" 564c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/Transforms/Utils/PromoteMemToReg.h" 57800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include <algorithm> 58d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <string> 59c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include <system_error> 60800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 61800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanyusing namespace llvm; 62800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 63dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "asan" 64dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 65800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic const uint64_t kDefaultShadowScale = 3; 66800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic const uint64_t kDefaultShadowOffset32 = 1ULL << 29; 67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic const uint64_t kIOSShadowOffset32 = 1ULL << 30; 68800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic const uint64_t kDefaultShadowOffset64 = 1ULL << 44; 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic const uint64_t kSmallX86_64ShadowOffset = 0x7FFF8000; // < 2G. 7048a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryanystatic const uint64_t kPPC64_ShadowOffset64 = 1ULL << 41; 7137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa0000; 72ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic const uint64_t kMIPS64_ShadowOffset64 = 1ULL << 37; 73ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic const uint64_t kAArch64_ShadowOffset64 = 1ULL << 36; 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic const uint64_t kFreeBSD_ShadowOffset32 = 1ULL << 30; 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic const uint64_t kFreeBSD_ShadowOffset64 = 1ULL << 46; 76ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic const uint64_t kWindowsShadowOffset32 = 3ULL << 28; 77800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic const size_t kMinStackMallocSize = 1 << 6; // 64B 79800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic const size_t kMaxStackMallocSize = 1 << 16; // 64K 80800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3; 81800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic const uintptr_t kRetiredStackFrameMagic = 0x45E0360E; 82800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 834172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanModuleCtorName = "asan.module_ctor"; 844172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanModuleDtorName = "asan.module_dtor"; 854c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic const uint64_t kAsanCtorAndDtorPriority = 1; 864172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanReportErrorTemplate = "__asan_report_"; 874172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanRegisterGlobalsName = "__asan_register_globals"; 8848d7d1d231cde758599fa0a010c29a174907c12fAlexey Samsonovstatic const char *const kAsanUnregisterGlobalsName = 8948d7d1d231cde758599fa0a010c29a174907c12fAlexey Samsonov "__asan_unregister_globals"; 904172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanPoisonGlobalsName = "__asan_before_dynamic_init"; 914172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanUnpoisonGlobalsName = "__asan_after_dynamic_init"; 92ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic const char *const kAsanInitName = "__asan_init_v5"; 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic const char *const kAsanPtrCmp = "__sanitizer_ptr_cmp"; 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic const char *const kAsanPtrSub = "__sanitizer_ptr_sub"; 954172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanHandleNoReturnName = "__asan_handle_no_return"; 964c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic const int kMaxAsanStackMallocSizeClass = 10; 97f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryanystatic const char *const kAsanStackMallocNameTemplate = "__asan_stack_malloc_"; 98f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryanystatic const char *const kAsanStackFreeNameTemplate = "__asan_stack_free_"; 994172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanGenPrefix = "__asan_gen_"; 10037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic const char *const kSanCovGenPrefix = "__sancov_gen_"; 1014172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanPoisonStackMemoryName = 1024172a8abbabea2359d91bb07101166565127d798Craig Topper "__asan_poison_stack_memory"; 1034172a8abbabea2359d91bb07101166565127d798Craig Topperstatic const char *const kAsanUnpoisonStackMemoryName = 104f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov "__asan_unpoison_stack_memory"; 105800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 106ac04abaf5a1df4c4bf48367cfbb41600289c4d78Kostya Serebryanystatic const char *const kAsanOptionDetectUAR = 107ac04abaf5a1df4c4bf48367cfbb41600289c4d78Kostya Serebryany "__asan_option_detect_stack_use_after_return"; 108ac04abaf5a1df4c4bf48367cfbb41600289c4d78Kostya Serebryany 1096948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic const char *const kAsanAllocaPoison = "__asan_alloca_poison"; 1106948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic const char *const kAsanAllocasUnpoison = "__asan_allocas_unpoison"; 1116948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 112c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany// Accesses sizes are powers of two: 1, 2, 4, 8, 16. 113c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryanystatic const size_t kNumberOfAccessSizes = 5; 114c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany 115ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic const unsigned kAllocaRzSize = 32; 116ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 117800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// Command-line flags. 118800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 119800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// This flag may need to be replaced with -f[no-]asan-reads. 120800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<bool> ClInstrumentReads("asan-instrument-reads", 1214c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("instrument read instructions"), 1224c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 1234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClInstrumentWrites( 1244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-instrument-writes", cl::desc("instrument write instructions"), 1254c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 1264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClInstrumentAtomics( 1274c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-instrument-atomics", 1284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, 1294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(true)); 1304c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClAlwaysSlowPath( 1314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-always-slow-path", 1324c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("use instrumentation with slow path for all accesses"), cl::Hidden, 1334c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(false)); 134c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany// This flag limits the number of instructions to be instrumented 135324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany// in any given BB. Normally, this should be set to unlimited (INT_MAX), 136324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany// but due to http://llvm.org/bugs/show_bug.cgi?id=12652 we temporary 137324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany// set it to 10000. 1384c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<int> ClMaxInsnsToInstrumentPerBB( 1394c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-max-ins-per-bb", cl::init(10000), 1404c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("maximal number of instructions to instrument in any given BB"), 1414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden); 142800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// This flag may need to be replaced with -f[no]asan-stack. 1434c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClStack("asan-stack", cl::desc("Handle stack memory"), 1444c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 145800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<bool> ClUseAfterReturn("asan-use-after-return", 1464c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Check return-after-free"), 1474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 148800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// This flag may need to be replaced with -f[no]asan-globals. 149800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<bool> ClGlobals("asan-globals", 1504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Handle global objects"), cl::Hidden, 1514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(true)); 1529b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryanystatic cl::opt<bool> ClInitializers("asan-initialization-order", 1534c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Handle C++ initializer order"), 1544c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 1554c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClInvalidPointerPairs( 1564c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-detect-invalid-pointer-pair", 1574c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Instrument <, <=, >, >=, - with pointer operands"), cl::Hidden, 1584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(false)); 1594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<unsigned> ClRealignStack( 1604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-realign-stack", 1614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Realign stack to the value of this flag (power of two)"), 1624c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(32)); 163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic cl::opt<int> ClInstrumentationWithCallsThreshold( 164dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines "asan-instrumentation-with-call-threshold", 1654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc( 1664c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "If the function being instrumented contains more than " 1674c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "this number of memory accesses, use callbacks instead of " 1684c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "inline checks (-1 means never use callbacks)."), 1694c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(7000)); 170dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic cl::opt<std::string> ClMemoryAccessCallbackPrefix( 1714c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-memory-access-callback-prefix", 1724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Prefix for memory access callbacks"), cl::Hidden, 1734c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init("__asan_")); 174ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic cl::opt<bool> ClInstrumentAllocas("asan-instrument-allocas", 1754c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("instrument dynamic allocas"), 1764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(false)); 1774c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClSkipPromotableAllocas( 1784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-skip-promotable-allocas", 1794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Do not instrument promotable allocas"), cl::Hidden, 1804c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(true)); 18120985711c76b8799d689a9c0e416b68896333c23Kostya Serebryany 182800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// These flags allow to change the shadow mapping. 183800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// The shadow mapping looks like 184800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// Shadow = (Mem >> scale) + (1 << offset_log) 185800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<int> ClMappingScale("asan-mapping-scale", 1864c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("scale of asan shadow mapping"), 1874c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(0)); 188800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 189800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// Optimization flags. Not user visible, used mostly for testing 190800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// and benchmarking the tool. 1914c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClOpt("asan-opt", cl::desc("Optimize instrumentation"), 1924c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 1934c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClOptSameTemp( 1944c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-opt-same-temp", cl::desc("Instrument the same temp just once"), 1954c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 196800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<bool> ClOptGlobals("asan-opt-globals", 1974c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Don't instrument scalar globals"), 1984c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(true)); 1994c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClOptStack( 2004c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-opt-stack", cl::desc("Don't instrument scalar stack variables"), 2014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::Hidden, cl::init(false)); 202800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 2034c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> ClCheckLifetime( 2044c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-check-lifetime", 2054c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Use llvm.lifetime intrinsics to insert extra checks"), cl::Hidden, 2064c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(false)); 207ee548275c63a1eeffda9d3edd2bea04e1dadcc67Alexey Samsonov 208ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic cl::opt<bool> ClDynamicAllocaStack( 209ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines "asan-stack-dynamic-alloca", 210ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines cl::desc("Use dynamic alloca to represent stack variables"), cl::Hidden, 211ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines cl::init(true)); 212ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 2134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<uint32_t> ClForceExperiment( 2144c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "asan-force-experiment", 2154c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Force optimization experiment (for testing)"), cl::Hidden, 2164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(0)); 2174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 218800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// Debug flags. 219800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden, 220800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany cl::init(0)); 221800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<int> ClDebugStack("asan-debug-stack", cl::desc("debug stack"), 222800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany cl::Hidden, cl::init(0)); 2234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<std::string> ClDebugFunc("asan-debug-func", cl::Hidden, 2244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::desc("Debug func")); 225800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<int> ClDebugMin("asan-debug-min", cl::desc("Debug min inst"), 226800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany cl::Hidden, cl::init(-1)); 227800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanystatic cl::opt<int> ClDebugMax("asan-debug-max", cl::desc("Debug man inst"), 228800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany cl::Hidden, cl::init(-1)); 229800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 2303386d252579ea00d0fc26a3ba7874bec25ce4516Kostya SerebryanySTATISTIC(NumInstrumentedReads, "Number of instrumented reads"); 2313386d252579ea00d0fc26a3ba7874bec25ce4516Kostya SerebryanySTATISTIC(NumInstrumentedWrites, "Number of instrumented writes"); 2323386d252579ea00d0fc26a3ba7874bec25ce4516Kostya SerebryanySTATISTIC(NumOptimizedAccessesToGlobalVar, 2333386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany "Number of optimized accesses to global vars"); 2344c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga NainarSTATISTIC(NumOptimizedAccessesToStackVar, 2354c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "Number of optimized accesses to stack vars"); 2363386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany 237800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanynamespace { 23837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// Frontend-provided metadata for source location. 23937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstruct LocationMetadata { 24037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines StringRef Filename; 24137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int LineNo; 24237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int ColumnNo; 24337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 24437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines LocationMetadata() : Filename(), LineNo(0), ColumnNo(0) {} 24537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 24637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bool empty() const { return Filename.empty(); } 24737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 24837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines void parse(MDNode *MDN) { 24937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines assert(MDN->getNumOperands() == 3); 2506948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar MDString *DIFilename = cast<MDString>(MDN->getOperand(0)); 2516948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Filename = DIFilename->getString(); 252ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines LineNo = 253ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines mdconst::extract<ConstantInt>(MDN->getOperand(1))->getLimitedValue(); 254ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ColumnNo = 255ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines mdconst::extract<ConstantInt>(MDN->getOperand(2))->getLimitedValue(); 25637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 25737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}; 25837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 259c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// Frontend-provided metadata for global variables. 260c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesclass GlobalsMetadata { 261ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany public: 26237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines struct Entry { 2634c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Entry() : SourceLoc(), Name(), IsDynInit(false), IsBlacklisted(false) {} 26437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines LocationMetadata SourceLoc; 26537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines StringRef Name; 26637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bool IsDynInit; 26737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bool IsBlacklisted; 26837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines }; 26937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 270c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalsMetadata() : inited_(false) {} 27137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 2724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar void init(Module &M) { 273c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines assert(!inited_); 274c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines inited_ = true; 275c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines NamedMDNode *Globals = M.getNamedMetadata("llvm.asan.globals"); 2764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!Globals) return; 277c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto MDN : Globals->operands()) { 27837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Metadata node contains the global and the fields of "Entry". 27937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines assert(MDN->getNumOperands() == 5); 280ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines auto *GV = mdconst::extract_or_null<GlobalVariable>(MDN->getOperand(0)); 281c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // The optimizer may optimize away a global entirely. 2824c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!GV) continue; 28337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // We can already have an entry for GV if it was merged with another 28437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // global. 28537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Entry &E = Entries[GV]; 286ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (auto *Loc = cast_or_null<MDNode>(MDN->getOperand(1))) 287ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines E.SourceLoc.parse(Loc); 288ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (auto *Name = cast_or_null<MDString>(MDN->getOperand(2))) 289ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines E.Name = Name->getString(); 290ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ConstantInt *IsDynInit = 291ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines mdconst::extract<ConstantInt>(MDN->getOperand(3)); 29237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines E.IsDynInit |= IsDynInit->isOne(); 293ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ConstantInt *IsBlacklisted = 294ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines mdconst::extract<ConstantInt>(MDN->getOperand(4)); 29537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines E.IsBlacklisted |= IsBlacklisted->isOne(); 296ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany } 297ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany } 298c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 29937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines /// Returns metadata entry for a given global. 30037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Entry get(GlobalVariable *G) const { 30137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto Pos = Entries.find(G); 30237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return (Pos != Entries.end()) ? Pos->second : Entry(); 303c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines } 304c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 305ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany private: 306c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines bool inited_; 3074c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar DenseMap<GlobalVariable *, Entry> Entries; 308ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany}; 309ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany 31019cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov/// This struct defines the shadow mapping using the rule: 31148a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryany/// shadow = (mem >> Scale) ADD-or-OR Offset. 31219cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonovstruct ShadowMapping { 31319cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov int Scale; 31419cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov uint64_t Offset; 31548a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryany bool OrShadowOffset; 31619cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov}; 31719cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov 318ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize) { 31911af9a873f9e1409a422ab31e22729368805afafAlexey Samsonov bool IsAndroid = TargetTriple.getEnvironment() == llvm::Triple::Android; 32037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bool IsIOS = TargetTriple.isiOS(); 321ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool IsFreeBSD = TargetTriple.isOSFreeBSD(); 322ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool IsLinux = TargetTriple.isOSLinux(); 323f38cc38fa647d4e72c053c39bbe0cdec1342535fBill Schmidt bool IsPPC64 = TargetTriple.getArch() == llvm::Triple::ppc64 || 324f38cc38fa647d4e72c053c39bbe0cdec1342535fBill Schmidt TargetTriple.getArch() == llvm::Triple::ppc64le; 3250bc55d517e8e64f0f441736fba2447781c405ef4Kostya Serebryany bool IsX86_64 = TargetTriple.getArch() == llvm::Triple::x86_64; 3263e1d45bf44f882f3ee139d452dd50305d831a341Kostya Serebryany bool IsMIPS32 = TargetTriple.getArch() == llvm::Triple::mips || 3273e1d45bf44f882f3ee139d452dd50305d831a341Kostya Serebryany TargetTriple.getArch() == llvm::Triple::mipsel; 32837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bool IsMIPS64 = TargetTriple.getArch() == llvm::Triple::mips64 || 32937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines TargetTriple.getArch() == llvm::Triple::mips64el; 330ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool IsAArch64 = TargetTriple.getArch() == llvm::Triple::aarch64; 331ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool IsWindows = TargetTriple.isOSWindows(); 33219cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov 33319cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov ShadowMapping Mapping; 33419cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov 33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (LongSize == 32) { 33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (IsAndroid) 33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = 0; 33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (IsMIPS32) 33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = kMIPS32_ShadowOffset32; 34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (IsFreeBSD) 34136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = kFreeBSD_ShadowOffset32; 342dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (IsIOS) 343dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Mapping.Offset = kIOSShadowOffset32; 344ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines else if (IsWindows) 345ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Mapping.Offset = kWindowsShadowOffset32; 34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = kDefaultShadowOffset32; 34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { // LongSize == 64 34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (IsPPC64) 35036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = kPPC64_ShadowOffset64; 35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (IsFreeBSD) 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = kFreeBSD_ShadowOffset64; 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (IsLinux && IsX86_64) 35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = kSmallX86_64ShadowOffset; 35537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines else if (IsMIPS64) 35637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Mapping.Offset = kMIPS64_ShadowOffset64; 357ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines else if (IsAArch64) 358ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Mapping.Offset = kAArch64_ShadowOffset64; 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.Offset = kDefaultShadowOffset64; 36119cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov } 36219cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov 36319cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov Mapping.Scale = kDefaultShadowScale; 36419cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov if (ClMappingScale) { 36519cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov Mapping.Scale = ClMappingScale; 36619cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov } 36719cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov 36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // OR-ing shadow offset if more efficient (at least on x86) if the offset 36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // is a power of two, but on ppc64 we have to use add since the shadow 37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // offset is not necessary 1/8-th of the address space. 37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Mapping.OrShadowOffset = !IsPPC64 && !(Mapping.Offset & (Mapping.Offset - 1)); 37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 37319cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov return Mapping; 374b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany} 375b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany 37619cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonovstatic size_t RedzoneSizeForScale(int MappingScale) { 377b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany // Redzone used for stack and globals is at least 32 bytes. 378b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively. 37919cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov return std::max(32U, 1U << MappingScale); 380b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany} 381ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany 382800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany/// AddressSanitizer: instrument the code in module to find memory bugs. 383ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryanystruct AddressSanitizer : public FunctionPass { 384ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AddressSanitizer() : FunctionPass(ID) { 385ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines initializeAddressSanitizerPass(*PassRegistry::getPassRegistry()); 386ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 38736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const char *getPassName() const override { 3881416edc30adbd53b2be863f7f3de56de4a4c9d0aKostya Serebryany return "AddressSanitizerFunctionPass"; 3891416edc30adbd53b2be863f7f3de56de4a4c9d0aKostya Serebryany } 390ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void getAnalysisUsage(AnalysisUsage &AU) const override { 391ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AU.addRequired<DominatorTreeWrapperPass>(); 3924c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AU.addRequired<TargetLibraryInfoWrapperPass>(); 393ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 3944c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t getAllocaSizeInBytes(AllocaInst *AI) const { 3954c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Type *Ty = AI->getAllocatedType(); 3964c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t SizeInBytes = 3974c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AI->getModule()->getDataLayout().getTypeAllocSize(Ty); 3984c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return SizeInBytes; 3994c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 4004c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar /// Check if we want (and can) handle this alloca. 4010c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar bool isInterestingAlloca(AllocaInst &AI); 4026948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 4036948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Check if we have dynamic alloca. 4046948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar bool isDynamicAlloca(AllocaInst &AI) const { 4056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return AI.isArrayAllocation() || !AI.isStaticAlloca(); 4066948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar } 4076948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 4084c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar /// If it is an interesting memory access, return the PointerOperand 4094c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar /// and set IsWrite/Alignment. Otherwise return nullptr. 4104c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite, 4116948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar uint64_t *TypeSize, unsigned *Alignment); 4124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar void instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis, Instruction *I, 4134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar bool UseCalls, const DataLayout &DL); 41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void instrumentPointerComparisonOrSubtraction(Instruction *I); 4156ecccdbb2bf24a011b9c8ecbdd39be5a02269670Kostya Serebryany void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore, 4166ecccdbb2bf24a011b9c8ecbdd39be5a02269670Kostya Serebryany Value *Addr, uint32_t TypeSize, bool IsWrite, 4174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *SizeArgument, bool UseCalls, uint32_t Exp); 4184c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar void instrumentUnusualSizeOrAlignment(Instruction *I, Value *Addr, 4194c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint32_t TypeSize, bool IsWrite, 4204c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *SizeArgument, bool UseCalls, 4214c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint32_t Exp); 422c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany Value *createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, 423c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany Value *ShadowValue, uint32_t TypeSize); 424ebd6454929f2ba3b92f61c151eccde0b8b0a8dedKostya Serebryany Instruction *generateCrashCode(Instruction *InsertBefore, Value *Addr, 4256ecccdbb2bf24a011b9c8ecbdd39be5a02269670Kostya Serebryany bool IsWrite, size_t AccessSizeIndex, 4264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *SizeArgument, uint32_t Exp); 427dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines void instrumentMemIntrinsic(MemIntrinsic *MI); 428800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Value *memToShadow(Value *Shadow, IRBuilder<> &IRB); 42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool runOnFunction(Function &F) override; 430a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany bool maybeInsertAsanInitAtFunctionEntry(Function &F); 43136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool doInitialization(Module &M) override; 432800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany static char ID; // Pass identification, replacement for typeid 433800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 434ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DominatorTree &getDominatorTree() const { return *DT; } 435ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 436800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany private: 4378b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany void initializeCallbacks(Module &M); 438800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 4395a3a9c937198084498a196dae856ac5a5a005bccKostya Serebryany bool LooksLikeCodeInBug11395(Instruction *I); 4403386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany bool GlobalIsLinkerInitialized(GlobalVariable *G); 4414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar bool isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis, Value *Addr, 4424c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t TypeSize) const; 443800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 444800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany LLVMContext *C; 445ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Triple TargetTriple; 446800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany int LongSize; 447800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Type *IntptrTy; 44819cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov ShadowMapping Mapping; 449ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DominatorTree *DT; 450800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Function *AsanCtorFunction; 451800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Function *AsanInitFunction; 452ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryany Function *AsanHandleNoReturnFunc; 45336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Function *AsanPtrCmpFunction, *AsanPtrSubFunction; 4544c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // This array is indexed by AccessIsWrite, Experiment and log2(AccessSize). 4554c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Function *AsanErrorCallback[2][2][kNumberOfAccessSizes]; 4564c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Function *AsanMemoryAccessCallback[2][2][kNumberOfAccessSizes]; 4574c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // This array is indexed by AccessIsWrite and Experiment. 4584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Function *AsanErrorCallbackSized[2][2]; 4594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Function *AsanMemoryAccessCallbackSized[2][2]; 460dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Function *AsanMemmove, *AsanMemcpy, *AsanMemset; 461f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany InlineAsm *EmptyAsm; 462c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalsMetadata GlobalsMD; 4630c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar DenseMap<AllocaInst *, bool> ProcessedAllocas; 46459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 46559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov friend struct FunctionStackPoisoner; 466800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany}; 467c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany 4681416edc30adbd53b2be863f7f3de56de4a4c9d0aKostya Serebryanyclass AddressSanitizerModule : public ModulePass { 469b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany public: 470c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines AddressSanitizerModule() : ModulePass(ID) {} 47136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool runOnModule(Module &M) override; 4721416edc30adbd53b2be863f7f3de56de4a4c9d0aKostya Serebryany static char ID; // Pass identification, replacement for typeid 4734c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const char *getPassName() const override { return "AddressSanitizerModule"; } 474f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov 475b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany private: 4764684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov void initializeCallbacks(Module &M); 4774684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov 478c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines bool InstrumentGlobals(IRBuilder<> &IRB, Module &M); 479b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany bool ShouldInstrumentGlobal(GlobalVariable *G); 480c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines void poisonOneInitializer(Function &GlobalInit, GlobalValue *ModuleName); 481ca825ea24de2f3d819845ee01796dc6c7a45170dAlexey Samsonov void createInitializerPoisonCalls(Module &M, GlobalValue *ModuleName); 48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t MinRedzoneSizeForGlobal() const { 48319cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov return RedzoneSizeForScale(Mapping.Scale); 48419cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov } 485b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany 486c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalsMetadata GlobalsMD; 487b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany Type *IntptrTy; 488b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany LLVMContext *C; 489ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Triple TargetTriple; 49019cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov ShadowMapping Mapping; 4914684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov Function *AsanPoisonGlobals; 4924684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov Function *AsanUnpoisonGlobals; 4934684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov Function *AsanRegisterGlobals; 4944684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov Function *AsanUnregisterGlobals; 495b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany}; 496b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany 49759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// Stack poisoning does not play well with exception handling. 49859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// When an exception is thrown, we essentially bypass the code 49959cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// that unpoisones the stack. This is why the run-time library has 50059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// to intercept __cxa_throw (as well as longjmp, etc) and unpoison the entire 50159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// stack in the interceptor. This however does not work inside the 50259cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// actual function which catches the exception. Most likely because the 50359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// compiler hoists the load of the shadow value somewhere too high. 50459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// This causes asan to report a non-existing bug on 453.povray. 50559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// It sounds like an LLVM bug. 50659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonovstruct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> { 50759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov Function &F; 50859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov AddressSanitizer &ASan; 50959cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov DIBuilder DIB; 51059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov LLVMContext *C; 51159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov Type *IntptrTy; 51259cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov Type *IntptrPtrTy; 51319cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov ShadowMapping Mapping; 51459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 5154c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SmallVector<AllocaInst *, 16> AllocaVec; 5164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SmallVector<Instruction *, 8> RetVec; 51759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov unsigned StackAlignment; 51859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 519f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany Function *AsanStackMallocFunc[kMaxAsanStackMallocSizeClass + 1], 5204c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar *AsanStackFreeFunc[kMaxAsanStackMallocSizeClass + 1]; 52159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov Function *AsanPoisonStackMemoryFunc, *AsanUnpoisonStackMemoryFunc; 5226948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Function *AsanAllocaPoisonFunc, *AsanAllocasUnpoisonFunc; 52359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 5241c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Stores a place and arguments of poisoning/unpoisoning call for alloca. 5251c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov struct AllocaPoisonCall { 5261c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov IntrinsicInst *InsBefore; 52764409ad8e3b360b84349042f14b57f87a5c0ca18Alexey Samsonov AllocaInst *AI; 5281c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov uint64_t Size; 5291c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov bool DoPoison; 5301c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov }; 5311c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov SmallVector<AllocaPoisonCall, 8> AllocaPoisonCallVec; 5321c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov 5336948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar SmallVector<AllocaInst *, 1> DynamicAllocaVec; 5346948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar SmallVector<IntrinsicInst *, 1> StackRestoreVec; 5356948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar AllocaInst *DynamicAllocaLayout = nullptr; 536ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 5371c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Maps Value to an AllocaInst from which the Value is originated. 5384c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar typedef DenseMap<Value *, AllocaInst *> AllocaForValueMapTy; 5391c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov AllocaForValueMapTy AllocaForValue; 5401c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov 541ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool HasNonEmptyInlineAsm; 542ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines std::unique_ptr<CallInst> EmptyInlineAsm; 543ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 54459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov FunctionStackPoisoner(Function &F, AddressSanitizer &ASan) 5454c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar : F(F), 5464c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ASan(ASan), 5474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar DIB(*F.getParent(), /*AllowUnresolved*/ false), 5484c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar C(ASan.C), 5494c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntptrTy(ASan.IntptrTy), 5504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntptrPtrTy(PointerType::get(IntptrTy, 0)), 5514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Mapping(ASan.Mapping), 5524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar StackAlignment(1 << Mapping.Scale), 5534c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar HasNonEmptyInlineAsm(false), 554ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines EmptyInlineAsm(CallInst::Create(ASan.EmptyAsm)) {} 55559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 55659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov bool runOnFunction() { 55759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov if (!ClStack) return false; 55859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov // Collect alloca, ret, lifetime instructions etc. 5594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (BasicBlock *BB : depth_first(&F.getEntryBlock())) visit(*BB); 560dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 561ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (AllocaVec.empty() && DynamicAllocaVec.empty()) return false; 56259cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 56359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov initializeCallbacks(*F.getParent()); 56459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 56559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov poisonStack(); 56659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 56759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov if (ClDebugStack) { 56859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov DEBUG(dbgs() << F); 56959cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov } 57059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov return true; 57159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov } 57259cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 573ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Finds all Alloca instructions and puts 57459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov // poisoned red zones around all of them. 57559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov // Then unpoison everything back before the function returns. 57659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov void poisonStack(); 57759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 5786948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar void createDynamicAllocasInitStorage(); 5796948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 58059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov // ----------------------- Visitors. 58159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov /// \brief Collect all Ret instructions. 5824c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar void visitReturnInst(ReturnInst &RI) { RetVec.push_back(&RI); } 58359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 5846948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar void unpoisonDynamicAllocasBeforeInst(Instruction *InstBefore, 5856948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Value *SavedStack) { 5866948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRBuilder<> IRB(InstBefore); 5876948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanAllocasUnpoisonFunc, 5886948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {IRB.CreateLoad(DynamicAllocaLayout), 5896948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreatePtrToInt(SavedStack, IntptrTy)}); 590ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 591ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 5926948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Unpoison dynamic allocas redzones. 5936948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar void unpoisonDynamicAllocas() { 5946948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar for (auto &Ret : RetVec) 5956948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar unpoisonDynamicAllocasBeforeInst(Ret, DynamicAllocaLayout); 596ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 5976948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar for (auto &StackRestoreInst : StackRestoreVec) 5986948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar unpoisonDynamicAllocasBeforeInst(StackRestoreInst, 5996948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar StackRestoreInst->getOperand(0)); 6006948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar } 601ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 602ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Deploy and poison redzones around dynamic alloca call. To do this, we 603ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // should replace this call with another one with changed parameters and 604ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // replace all its uses with new address, so 605ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // addr = alloca type, old_size, align 606ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // is replaced by 607ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // new_size = (old_size + additional_size) * sizeof(type) 608ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // tmp = alloca i8, new_size, max(align, 32) 609ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // addr = tmp + 32 (first 32 bytes are for the left redzone). 610ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Additional_size is added to make new memory allocation contain not only 611ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // requested memory, but also left, partial and right redzones. 6126948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar void handleDynamicAllocaCall(AllocaInst *AI); 613ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 61459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov /// \brief Collect Alloca instructions we want (and can) handle. 61559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov void visitAllocaInst(AllocaInst &AI) { 6164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!ASan.isInterestingAlloca(AI)) return; 61759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 61859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov StackAlignment = std::max(StackAlignment, AI.getAlignment()); 6196948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar if (ASan.isDynamicAlloca(AI)) 6206948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar DynamicAllocaVec.push_back(&AI); 621ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines else 622ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AllocaVec.push_back(&AI); 62359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov } 62459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 6251c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov /// \brief Collect lifetime intrinsic calls to check for use-after-scope 6261c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov /// errors. 6271c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov void visitIntrinsicInst(IntrinsicInst &II) { 6281c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov Intrinsic::ID ID = II.getIntrinsicID(); 6296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar if (ID == Intrinsic::stackrestore) StackRestoreVec.push_back(&II); 6306948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar if (!ClCheckLifetime) return; 6314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (ID != Intrinsic::lifetime_start && ID != Intrinsic::lifetime_end) 6321c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov return; 6331c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Found lifetime intrinsic, add ASan instrumentation if necessary. 6341c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov ConstantInt *Size = dyn_cast<ConstantInt>(II.getArgOperand(0)); 6351c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // If size argument is undefined, don't do anything. 6361c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov if (Size->isMinusOne()) return; 6371c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Check that size doesn't saturate uint64_t and can 6381c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // be stored in IntptrTy. 6391c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov const uint64_t SizeValue = Size->getValue().getLimitedValue(); 6401c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov if (SizeValue == ~0ULL || 6411c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov !ConstantInt::isValueValidForType(IntptrTy, SizeValue)) 6421c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov return; 6431c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Find alloca instruction that corresponds to llvm.lifetime argument. 6441c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov AllocaInst *AI = findAllocaForValue(II.getArgOperand(1)); 6451c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov if (!AI) return; 6461c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov bool DoPoison = (ID == Intrinsic::lifetime_end); 64764409ad8e3b360b84349042f14b57f87a5c0ca18Alexey Samsonov AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison}; 6481c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov AllocaPoisonCallVec.push_back(APC); 6491c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov } 6501c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov 651ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void visitCallInst(CallInst &CI) { 652ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines HasNonEmptyInlineAsm |= 653ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines CI.isInlineAsm() && !CI.isIdenticalTo(EmptyInlineAsm.get()); 654ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 655ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 65659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov // ---------------------- Helpers. 65759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov void initializeCallbacks(Module &M); 65859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 659ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool doesDominateAllExits(const Instruction *I) const { 660ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (auto Ret : RetVec) { 6614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!ASan.getDominatorTree().dominates(I, Ret)) return false; 662ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 663ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return true; 664ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 665ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 6661c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov /// Finds alloca where the value comes from. 6671c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov AllocaInst *findAllocaForValue(Value *V); 66837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines void poisonRedZones(ArrayRef<uint8_t> ShadowBytes, IRBuilder<> &IRB, 66959cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov Value *ShadowBase, bool DoPoison); 6704c71064129d1e5def34d74ee47c4f3beaa0a66dfJakub Staszak void poisonAlloca(Value *V, uint64_t Size, IRBuilder<> &IRB, bool DoPoison); 671671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany 672671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany void SetShadowToStackAfterReturnInlined(IRBuilder<> &IRB, Value *ShadowBase, 673671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany int Size); 674ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *createAllocaForLayout(IRBuilder<> &IRB, const ASanStackFrameLayout &L, 675ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool Dynamic); 676ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines PHINode *createPHI(IRBuilder<> &IRB, Value *Cond, Value *ValueIfTrue, 677ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Instruction *ThenTerm, Value *ValueIfFalse); 67859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov}; 67959cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 680800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} // namespace 681800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 682800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanychar AddressSanitizer::ID = 0; 6834c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga NainarINITIALIZE_PASS_BEGIN( 6844c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AddressSanitizer, "asan", 6854c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, 6864c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar false) 687ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesINITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 6884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga NainarINITIALIZE_PASS_END( 6894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AddressSanitizer, "asan", 6904c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, 6914c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar false) 692c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesFunctionPass *llvm::createAddressSanitizerFunctionPass() { 693c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return new AddressSanitizer(); 694800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 695800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 6961416edc30adbd53b2be863f7f3de56de4a4c9d0aKostya Serebryanychar AddressSanitizerModule::ID = 0; 6974c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga NainarINITIALIZE_PASS( 6984c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AddressSanitizerModule, "asan-module", 6991416edc30adbd53b2be863f7f3de56de4a4c9d0aKostya Serebryany "AddressSanitizer: detects use-after-free and out-of-bounds bugs." 7004c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "ModulePass", 7014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar false, false) 702c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesModulePass *llvm::createAddressSanitizerModulePass() { 703c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return new AddressSanitizerModule(); 70425878042030e85c244b41bfcdfad27c32360e2ecAlexander Potapenko} 70525878042030e85c244b41bfcdfad27c32360e2ecAlexander Potapenko 7062735cf4aa52e31b8d2de90f836c3ad991215e04eKostya Serebryanystatic size_t TypeSizeToSizeIndex(uint32_t TypeSize) { 707c6af2432c802d241c8fffbe0371c023e6c58844eMichael J. Spencer size_t Res = countTrailingZeros(TypeSize / 8); 7082735cf4aa52e31b8d2de90f836c3ad991215e04eKostya Serebryany assert(Res < kNumberOfAccessSizes); 7092735cf4aa52e31b8d2de90f836c3ad991215e04eKostya Serebryany return Res; 7102735cf4aa52e31b8d2de90f836c3ad991215e04eKostya Serebryany} 7112735cf4aa52e31b8d2de90f836c3ad991215e04eKostya Serebryany 71255a1a590bf0cadf88dfbef2aab6948ffec35c1c3Bill Wendling// \brief Create a constant for Str so that we can pass it to the run-time lib. 7134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str, 7144c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar bool AllowMerging) { 71518c7f80b3e83ab584bd8572695a3cde8bafd9d3cChris Lattner Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); 71636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // We use private linkage for module-local strings. If they can be merged 71736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // with another one, we set the unnamed_addr attribute. 71836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines GlobalVariable *GV = 71936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines new GlobalVariable(M, StrConst->getType(), true, 72036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines GlobalValue::PrivateLinkage, StrConst, kAsanGenPrefix); 7214c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (AllowMerging) GV->setUnnamedAddr(true); 7225111627ac1b0ae8a5a9d4dc1be8b22939ba850d0Kostya Serebryany GV->setAlignment(1); // Strings may not be merged w/o setting align 1. 7235111627ac1b0ae8a5a9d4dc1be8b22939ba850d0Kostya Serebryany return GV; 72451c7c65e32f76ec5a50cdecfe2b4c287c57da127Kostya Serebryany} 72551c7c65e32f76ec5a50cdecfe2b4c287c57da127Kostya Serebryany 72637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// \brief Create a global describing a source location. 72737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic GlobalVariable *createPrivateGlobalForSourceLoc(Module &M, 72837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines LocationMetadata MD) { 72937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Constant *LocData[] = { 73037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines createPrivateGlobalForString(M, MD.Filename, true), 73137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ConstantInt::get(Type::getInt32Ty(M.getContext()), MD.LineNo), 73237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ConstantInt::get(Type::getInt32Ty(M.getContext()), MD.ColumnNo), 73337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines }; 73437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto LocStruct = ConstantStruct::getAnon(LocData); 73537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto GV = new GlobalVariable(M, LocStruct->getType(), true, 73637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines GlobalValue::PrivateLinkage, LocStruct, 73737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines kAsanGenPrefix); 73837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines GV->setUnnamedAddr(true); 73937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return GV; 74037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 74137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 74251c7c65e32f76ec5a50cdecfe2b4c287c57da127Kostya Serebryanystatic bool GlobalWasGeneratedByAsan(GlobalVariable *G) { 74337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return G->getName().find(kAsanGenPrefix) == 0 || 74437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines G->getName().find(kSanCovGenPrefix) == 0; 745800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 746800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 747800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya SerebryanyValue *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) { 748800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // Shadow >> scale 74919cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov Shadow = IRB.CreateLShr(Shadow, Mapping.Scale); 7504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Mapping.Offset == 0) return Shadow; 751800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // (Shadow >> scale) | offset 75248a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryany if (Mapping.OrShadowOffset) 75348a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryany return IRB.CreateOr(Shadow, ConstantInt::get(IntptrTy, Mapping.Offset)); 75448a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryany else 75548a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryany return IRB.CreateAdd(Shadow, ConstantInt::get(IntptrTy, Mapping.Offset)); 756800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 757800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 758800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// Instrument memset/memmove/memcpy 759dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) { 760dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines IRBuilder<> IRB(MI); 761dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (isa<MemTransferInst>(MI)) { 7626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall( 763dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines isa<MemMoveInst>(MI) ? AsanMemmove : AsanMemcpy, 7646948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()), 7656948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()), 7666948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); 767dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else if (isa<MemSetInst>(MI)) { 7686948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall( 769dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines AsanMemset, 7706948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()), 7716948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false), 7726948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); 773800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 774dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MI->eraseFromParent(); 775800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 776800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 7774c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar/// Check if we want (and can) handle this alloca. 7780c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainarbool AddressSanitizer::isInterestingAlloca(AllocaInst &AI) { 7790c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar auto PreviouslySeenAllocaInfo = ProcessedAllocas.find(&AI); 7800c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 7810c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (PreviouslySeenAllocaInfo != ProcessedAllocas.end()) 7820c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar return PreviouslySeenAllocaInfo->getSecond(); 7830c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 7846948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar bool IsInteresting = 7856948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar (AI.getAllocatedType()->isSized() && 7866948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // alloca() may be called with 0 size, ignore it. 7876948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar getAllocaSizeInBytes(&AI) > 0 && 7886948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // We are only interested in allocas not promotable to registers. 7896948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Promotable allocas are common under -O0. 7906948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar (!ClSkipPromotableAllocas || !isAllocaPromotable(&AI) || 7916948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar isDynamicAlloca(AI))); 7920c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 7930c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar ProcessedAllocas[&AI] = IsInteresting; 7940c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar return IsInteresting; 7954c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} 7964c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 7974c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar/// If I is an interesting memory access, return the PointerOperand 7984c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar/// and set IsWrite/Alignment. Otherwise return nullptr. 7994c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga NainarValue *AddressSanitizer::isInterestingMemoryAccess(Instruction *I, 8004c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar bool *IsWrite, 8014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t *TypeSize, 8020c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar unsigned *Alignment) { 80337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Skip memory accesses inserted by another instrumentation. 8044c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (I->getMetadata("nosanitize")) return nullptr; 8054c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 8064c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *PtrOperand = nullptr; 8074c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const DataLayout &DL = I->getModule()->getDataLayout(); 808800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 809dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!ClInstrumentReads) return nullptr; 810e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany *IsWrite = false; 8114c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar *TypeSize = DL.getTypeStoreSizeInBits(LI->getType()); 812dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines *Alignment = LI->getAlignment(); 8134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar PtrOperand = LI->getPointerOperand(); 8144c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 815dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!ClInstrumentWrites) return nullptr; 816e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany *IsWrite = true; 8174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType()); 818dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines *Alignment = SI->getAlignment(); 8194c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar PtrOperand = SI->getPointerOperand(); 8204c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { 821dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!ClInstrumentAtomics) return nullptr; 822e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany *IsWrite = true; 8234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType()); 824dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines *Alignment = 0; 8254c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar PtrOperand = RMW->getPointerOperand(); 8264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { 827dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!ClInstrumentAtomics) return nullptr; 828e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany *IsWrite = true; 8294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType()); 830dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines *Alignment = 0; 8314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar PtrOperand = XCHG->getPointerOperand(); 832e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany } 8334c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 8344c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // Treat memory accesses to promotable allocas as non-interesting since they 8354c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // will not cause memory violations. This greatly speeds up the instrumented 8364c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // executable at -O0. 8374c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (ClSkipPromotableAllocas) 8384c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (auto AI = dyn_cast_or_null<AllocaInst>(PtrOperand)) 8394c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return isInterestingAlloca(*AI) ? AI : nullptr; 8404c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 8414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return PtrOperand; 842800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 843800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 84436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool isPointerOperand(Value *V) { 84536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return V->getType()->isPointerTy() || isa<PtrToIntInst>(V); 84636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 84736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 84836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This is a rough heuristic; it may cause both false positives and 84936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// false negatives. The proper implementation requires cooperation with 85036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// the frontend. 85136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool isInterestingPointerComparisonOrSubtraction(Instruction *I) { 85236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ICmpInst *Cmp = dyn_cast<ICmpInst>(I)) { 8534c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!Cmp->isRelational()) return false; 85436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I)) { 8554c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (BO->getOpcode() != Instruction::Sub) return false; 85636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 85736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 85836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 85936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!isPointerOperand(I->getOperand(0)) || 86036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines !isPointerOperand(I->getOperand(1))) 8614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return false; 86236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 86336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 86436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8653386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryanybool AddressSanitizer::GlobalIsLinkerInitialized(GlobalVariable *G) { 8663386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany // If a global variable does not have dynamic initialization we don't 8673386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany // have to instrument it. However, if a global does not have initializer 8683386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany // at all, we assume it has dynamic initializer (in other TU). 86937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return G->hasInitializer() && !GlobalsMD.get(G).IsDynInit; 8703386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany} 8713386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany 8724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarvoid AddressSanitizer::instrumentPointerComparisonOrSubtraction( 8734c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Instruction *I) { 87436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines IRBuilder<> IRB(I); 87536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Function *F = isa<ICmpInst>(I) ? AsanPtrCmpFunction : AsanPtrSubFunction; 87636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value *Param[2] = {I->getOperand(0), I->getOperand(1)}; 87736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (int i = 0; i < 2; i++) { 87836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Param[i]->getType()->isPointerTy()) 87936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Param[i] = IRB.CreatePointerCast(Param[i], IntptrTy); 88036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 8816948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(F, Param); 88236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 88336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8844c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarvoid AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis, 8854c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Instruction *I, bool UseCalls, 8864c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const DataLayout &DL) { 8873780ad8b998d93d7db406919c06137cdb786ef05Axel Naumann bool IsWrite = false; 888dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines unsigned Alignment = 0; 8894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t TypeSize = 0; 8904c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *Addr = isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment); 891e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany assert(Addr); 8924c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 8934c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // Optimization experiments. 8944c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // The experiments can be used to evaluate potential optimizations that remove 8954c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // instrumentation (assess false negatives). Instead of completely removing 8964c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // some instrumentation, you set Exp to a non-zero value (mask of optimization 8974c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // experiments that want to remove instrumentation of this instruction). 8984c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // If Exp is non-zero, this pass will emit special calls into runtime 8994c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // (e.g. __asan_report_exp_load1 instead of __asan_report_load1). These calls 9004c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // make runtime terminate the program in a special way (with a different 9014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // exit status). Then you run the new compiler on a buggy corpus, collect 9024c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // the special terminations (ideally, you don't see them at all -- no false 9034c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // negatives) and make the decision on the optimization. 9044c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint32_t Exp = ClForceExperiment; 9054c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 9069b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany if (ClOpt && ClOptGlobals) { 9074c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // If initialization order checking is disabled, a simple access to a 9084c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // dynamically initialized global is always valid. 9094c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar GlobalVariable *G = dyn_cast<GlobalVariable>(GetUnderlyingObject(Addr, DL)); 9104c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (G != NULL && (!ClInitializers || GlobalIsLinkerInitialized(G)) && 9114c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar isSafeAccess(ObjSizeVis, Addr, TypeSize)) { 9124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar NumOptimizedAccessesToGlobalVar++; 9134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return; 9149b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany } 915800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 9169b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 9174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (ClOpt && ClOptStack) { 9184c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // A direct inbounds access to a stack variable is always valid. 9194c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (isa<AllocaInst>(GetUnderlyingObject(Addr, DL)) && 9204c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar isSafeAccess(ObjSizeVis, Addr, TypeSize)) { 9214c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar NumOptimizedAccessesToStackVar++; 9224c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return; 9234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 9244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 925800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 9263386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany if (IsWrite) 9273386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany NumInstrumentedWrites++; 9283386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany else 9293386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany NumInstrumentedReads++; 9303386d252579ea00d0fc26a3ba7874bec25ce4516Kostya Serebryany 931dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines unsigned Granularity = 1 << Mapping.Scale; 932dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check 933dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // if the data is properly aligned. 934dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if ((TypeSize == 8 || TypeSize == 16 || TypeSize == 32 || TypeSize == 64 || 935dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines TypeSize == 128) && 936dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines (Alignment >= Granularity || Alignment == 0 || Alignment >= TypeSize / 8)) 9374c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return instrumentAddress(I, I, Addr, TypeSize, IsWrite, nullptr, UseCalls, 9384c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Exp); 9394c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar instrumentUnusualSizeOrAlignment(I, Addr, TypeSize, IsWrite, nullptr, 9404c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar UseCalls, Exp); 941800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 942800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 9434c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga NainarInstruction *AddressSanitizer::generateCrashCode(Instruction *InsertBefore, 9444c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *Addr, bool IsWrite, 9454c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar size_t AccessSizeIndex, 9464c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *SizeArgument, 9474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint32_t Exp) { 948ebd6454929f2ba3b92f61c151eccde0b8b0a8dedKostya Serebryany IRBuilder<> IRB(InsertBefore); 9494c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *ExpVal = Exp == 0 ? nullptr : ConstantInt::get(IRB.getInt32Ty(), Exp); 9504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar CallInst *Call = nullptr; 9514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (SizeArgument) { 9524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Exp == 0) 9536948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Call = IRB.CreateCall(AsanErrorCallbackSized[IsWrite][0], 9546948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {Addr, SizeArgument}); 9554c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar else 9566948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Call = IRB.CreateCall(AsanErrorCallbackSized[IsWrite][1], 9576948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {Addr, SizeArgument, ExpVal}); 9584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } else { 9594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Exp == 0) 9604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Call = 9614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateCall(AsanErrorCallback[IsWrite][0][AccessSizeIndex], Addr); 9624c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar else 9636948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Call = IRB.CreateCall(AsanErrorCallback[IsWrite][1][AccessSizeIndex], 9646948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {Addr, ExpVal}); 9654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 9666ecccdbb2bf24a011b9c8ecbdd39be5a02269670Kostya Serebryany 967f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany // We don't do Call->setDoesNotReturn() because the BB already has 968f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany // UnreachableInst at the end. 969f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany // This EmptyAsm is required to avoid callback merge. 9706948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(EmptyAsm, {}); 9713c7faae346f548c55cad86d82a2e242443001f23Kostya Serebryany return Call; 972800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 973800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 9742735cf4aa52e31b8d2de90f836c3ad991215e04eKostya SerebryanyValue *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, 9754c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *ShadowValue, 9764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint32_t TypeSize) { 97719cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov size_t Granularity = 1 << Mapping.Scale; 978c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany // Addr & (Granularity - 1) 9794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *LastAccessedByte = 9804c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateAnd(AddrLong, ConstantInt::get(IntptrTy, Granularity - 1)); 981c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany // (Addr & (Granularity - 1)) + size - 1 982c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany if (TypeSize / 8 > 1) 983c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany LastAccessedByte = IRB.CreateAdd( 984c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany LastAccessedByte, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)); 985c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany // (uint8_t) ((Addr & (Granularity-1)) + size - 1) 9864c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar LastAccessedByte = 9874c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateIntCast(LastAccessedByte, ShadowValue->getType(), false); 988c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany // ((uint8_t) ((Addr & (Granularity-1)) + size - 1)) >= ShadowValue 989c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany return IRB.CreateICmpSGE(LastAccessedByte, ShadowValue); 990c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany} 991c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany 992ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryanyvoid AddressSanitizer::instrumentAddress(Instruction *OrigIns, 993dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Instruction *InsertBefore, Value *Addr, 994dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t TypeSize, bool IsWrite, 9954c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *SizeArgument, bool UseCalls, 9964c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint32_t Exp) { 9976ecccdbb2bf24a011b9c8ecbdd39be5a02269670Kostya Serebryany IRBuilder<> IRB(InsertBefore); 998800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 999dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); 1000dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 1001dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (UseCalls) { 10024c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Exp == 0) 10034c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], 10044c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AddrLong); 10054c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar else 10066948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex], 10076948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {AddrLong, ConstantInt::get(IRB.getInt32Ty(), Exp)}); 1008dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return; 1009dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 1010800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 10114c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Type *ShadowTy = 10124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntegerType::get(*C, std::max(8U, TypeSize >> Mapping.Scale)); 1013800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Type *ShadowPtrTy = PointerType::get(ShadowTy, 0); 1014800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Value *ShadowPtr = memToShadow(AddrLong, IRB); 1015800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Value *CmpVal = Constant::getNullValue(ShadowTy); 10164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *ShadowValue = 10174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateLoad(IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy)); 1018800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1019800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Value *Cmp = IRB.CreateICmpNE(ShadowValue, CmpVal); 102019cd7e9ce28ed7f3326ebcd386eec215ab3763f9Alexey Samsonov size_t Granularity = 1 << Mapping.Scale; 1021dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines TerminatorInst *CrashTerm = nullptr; 1022ebd6454929f2ba3b92f61c151eccde0b8b0a8dedKostya Serebryany 10236e2d506dc962873a0e05092bbb034f9a615d1084Kostya Serebryany if (ClAlwaysSlowPath || (TypeSize < 8 * Granularity)) { 102437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // We use branch weights for the slow path check, to indicate that the slow 102537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // path is rarely taken. This seems to be the case for SPEC benchmarks. 10264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar TerminatorInst *CheckTerm = SplitBlockAndInsertIfThen( 10274c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Cmp, InsertBefore, false, MDBuilder(*C).createBranchWeights(1, 100000)); 10280c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar assert(cast<BranchInst>(CheckTerm)->isUnconditional()); 1029f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany BasicBlock *NextBB = CheckTerm->getSuccessor(0); 1030c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany IRB.SetInsertPoint(CheckTerm); 1031c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeSize); 1032ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryany BasicBlock *CrashBlock = 1033ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryany BasicBlock::Create(*C, "", NextBB->getParent(), NextBB); 1034ebd6454929f2ba3b92f61c151eccde0b8b0a8dedKostya Serebryany CrashTerm = new UnreachableInst(*C, CrashBlock); 1035f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany BranchInst *NewTerm = BranchInst::Create(CrashBlock, NextBB, Cmp2); 1036f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany ReplaceInstWithInst(CheckTerm, NewTerm); 1037c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany } else { 103836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CrashTerm = SplitBlockAndInsertIfThen(Cmp, InsertBefore, true); 1039800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1040ebd6454929f2ba3b92f61c151eccde0b8b0a8dedKostya Serebryany 10414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Instruction *Crash = generateCrashCode(CrashTerm, AddrLong, IsWrite, 10424c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AccessSizeIndex, SizeArgument, Exp); 1043ebd6454929f2ba3b92f61c151eccde0b8b0a8dedKostya Serebryany Crash->setDebugLoc(OrigIns->getDebugLoc()); 1044800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 1045800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 10464c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// Instrument unusual size or unusual alignment. 10474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// We can not do it with a single check, so we do 1-byte check for the first 10484c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// and the last bytes. We call __asan_report_*_n(addr, real_size) to be able 10494c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// to report the actual access size. 10504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarvoid AddressSanitizer::instrumentUnusualSizeOrAlignment( 10514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Instruction *I, Value *Addr, uint32_t TypeSize, bool IsWrite, 10524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *SizeArgument, bool UseCalls, uint32_t Exp) { 10534c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRBuilder<> IRB(I); 10544c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *Size = ConstantInt::get(IntptrTy, TypeSize / 8); 10554c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 10564c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (UseCalls) { 10574c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Exp == 0) 10586948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanMemoryAccessCallbackSized[IsWrite][0], 10596948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {AddrLong, Size}); 10604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar else 10616948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanMemoryAccessCallbackSized[IsWrite][1], 10626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {AddrLong, Size, ConstantInt::get(IRB.getInt32Ty(), Exp)}); 10634c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } else { 10644c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *LastByte = IRB.CreateIntToPtr( 10654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateAdd(AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)), 10664c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Addr->getType()); 10674c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar instrumentAddress(I, I, Addr, 8, IsWrite, Size, false, Exp); 10684c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar instrumentAddress(I, I, LastByte, 8, IsWrite, Size, false, Exp); 10694c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 10704c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} 10714c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 1072c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesvoid AddressSanitizerModule::poisonOneInitializer(Function &GlobalInit, 1073c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalValue *ModuleName) { 10749b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // Set up the arguments to our poison/unpoison functions. 1075c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines IRBuilder<> IRB(GlobalInit.begin()->getFirstInsertionPt()); 10769b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 10779b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // Add a call to poison all external globals before the given function starts. 1078ca825ea24de2f3d819845ee01796dc6c7a45170dAlexey Samsonov Value *ModuleNameAddr = ConstantExpr::getPointerCast(ModuleName, IntptrTy); 1079ca825ea24de2f3d819845ee01796dc6c7a45170dAlexey Samsonov IRB.CreateCall(AsanPoisonGlobals, ModuleNameAddr); 10809b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 10819b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // Add calls to unpoison all globals before each return instruction. 1082c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto &BB : GlobalInit.getBasicBlockList()) 1083c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) 10849b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany CallInst::Create(AsanUnpoisonGlobals, "", RI); 1085c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines} 1086c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 1087c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesvoid AddressSanitizerModule::createInitializerPoisonCalls( 1088c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines Module &M, GlobalValue *ModuleName) { 1089c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); 1090c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 1091c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ConstantArray *CA = cast<ConstantArray>(GV->getInitializer()); 1092c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (Use &OP : CA->operands()) { 10934c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (isa<ConstantAggregateZero>(OP)) continue; 1094c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ConstantStruct *CS = cast<ConstantStruct>(OP); 1095c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 1096c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Must have a function or null ptr. 10974c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Function *F = dyn_cast<Function>(CS->getOperand(1))) { 109837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (F->getName() == kAsanModuleCtorName) continue; 109937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); 110037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Don't instrument CTORs that will run before asan.module_ctor. 110137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Priority->getLimitedValue() <= kAsanCtorAndDtorPriority) continue; 110237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines poisonOneInitializer(*F, ModuleName); 11039b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany } 11049b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany } 11059b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany} 11069b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 11071416edc30adbd53b2be863f7f3de56de4a4c9d0aKostya Serebryanybool AddressSanitizerModule::ShouldInstrumentGlobal(GlobalVariable *G) { 11089b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany Type *Ty = cast<PointerType>(G->getType())->getElementType(); 1109324d96b9e265b0fd8bf63a28340910def64e2164Kostya Serebryany DEBUG(dbgs() << "GLOBAL: " << *G << "\n"); 11109b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 111137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (GlobalsMD.get(G).IsBlacklisted) return false; 11129b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany if (!Ty->isSized()) return false; 11139b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany if (!G->hasInitializer()) return false; 111451c7c65e32f76ec5a50cdecfe2b4c287c57da127Kostya Serebryany if (GlobalWasGeneratedByAsan(G)) return false; // Our own global. 11159b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // Touch only those globals that will not be defined in other modules. 1116c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Don't handle ODR linkage types and COMDATs since other modules may be built 1117c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // without ASan. 11189b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany if (G->getLinkage() != GlobalVariable::ExternalLinkage && 11199b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany G->getLinkage() != GlobalVariable::PrivateLinkage && 11209b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany G->getLinkage() != GlobalVariable::InternalLinkage) 11219b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany return false; 11224c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (G->hasComdat()) return false; 11239b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // Two problems with thread-locals: 11249b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // - The address of the main thread's copy can't be computed at link-time. 11259b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // - Need to poison all copies, not just the main thread's one. 11264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (G->isThreadLocal()) return false; 112736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // For now, just ignore this Global if the alignment is large. 112836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (G->getAlignment() > MinRedzoneSizeForGlobal()) return false; 11299b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 11309b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany if (G->hasSection()) { 11319b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany StringRef Section(G->getSection()); 113237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 11336948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Globals from llvm.metadata aren't emitted, do not instrument them. 11346948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar if (Section == "llvm.metadata") return false; 11356948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 11366948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Callbacks put into the CRT initializer/terminator sections 11376948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // should not be instrumented. 11386948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // See https://code.google.com/p/address-sanitizer/issues/detail?id=305 11396948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // and http://msdn.microsoft.com/en-US/en-en/library/bb918180(v=vs.120).aspx 11406948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar if (Section.startswith(".CRT")) { 11416948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar DEBUG(dbgs() << "Ignoring a global initializer callback: " << *G << "\n"); 11426948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return false; 11436948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar } 11446948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 1145ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (TargetTriple.isOSBinFormatMachO()) { 1146ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines StringRef ParsedSegment, ParsedSection; 1147ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines unsigned TAA = 0, StubSize = 0; 1148ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool TAAParsed; 11494c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar std::string ErrorCode = MCSectionMachO::ParseSectionSpecifier( 11504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize); 1151ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (!ErrorCode.empty()) { 11526948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar assert(false && "Invalid section specifier."); 11536948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return false; 1154ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 1155ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1156ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Ignore the globals from the __OBJC section. The ObjC runtime assumes 1157ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to 1158ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // them. 1159ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (ParsedSegment == "__OBJC" || 1160ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines (ParsedSegment == "__DATA" && ParsedSection.startswith("__objc_"))) { 1161ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G << "\n"); 1162ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 1163ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 1164ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // See http://code.google.com/p/address-sanitizer/issues/detail?id=32 1165ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Constant CFString instances are compiled in the following way: 1166ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // -- the string buffer is emitted into 1167ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // __TEXT,__cstring,cstring_literals 1168ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // -- the constant NSConstantString structure referencing that buffer 1169ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // is placed into __DATA,__cfstring 1170ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Therefore there's no point in placing redzones into __DATA,__cfstring. 1171ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Moreover, it causes the linker to crash on OS X 10.7 1172ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (ParsedSegment == "__DATA" && ParsedSection == "__cfstring") { 1173ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DEBUG(dbgs() << "Ignoring CFString: " << *G << "\n"); 1174ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 1175ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 1176ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // The linker merges the contents of cstring_literals and removes the 1177ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // trailing zeroes. 1178ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (ParsedSegment == "__TEXT" && (TAA & MachO::S_CSTRING_LITERALS)) { 1179ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DEBUG(dbgs() << "Ignoring a cstring literal: " << *G << "\n"); 1180ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 1181ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 1182ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 11839b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany } 11849b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 11859b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany return true; 11869b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany} 11879b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 11884684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonovvoid AddressSanitizerModule::initializeCallbacks(Module &M) { 11894684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov IRBuilder<> IRB(*C); 11904684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov // Declare our poisoning and unpoisoning functions. 11910c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanPoisonGlobals = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 119237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines kAsanPoisonGlobalsName, IRB.getVoidTy(), IntptrTy, nullptr)); 11934684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov AsanPoisonGlobals->setLinkage(Function::ExternalLinkage); 11940c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanUnpoisonGlobals = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 119537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines kAsanUnpoisonGlobalsName, IRB.getVoidTy(), nullptr)); 11964684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov AsanUnpoisonGlobals->setLinkage(Function::ExternalLinkage); 11974684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov // Declare functions that register/unregister globals. 11980c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanRegisterGlobals = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 11994c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); 12004684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov AsanRegisterGlobals->setLinkage(Function::ExternalLinkage); 12010c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanUnregisterGlobals = checkSanitizerInterfaceFunction( 12024c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar M.getOrInsertFunction(kAsanUnregisterGlobalsName, IRB.getVoidTy(), 12034c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntptrTy, IntptrTy, nullptr)); 12044684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage); 12054684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov} 12064684858624d7ffe82379783e9b678227d5e0b515Alexey Samsonov 1207800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// This function replaces all global variables with new variables that have 1208800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// trailing redzones. It also creates a function that poisons 1209800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany// redzones and inserts this function into llvm.global_ctors. 1210c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesbool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { 1211c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalsMD.init(M); 1212b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany 1213800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany SmallVector<GlobalVariable *, 16> GlobalsToChange; 1214800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1215c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto &G : M.globals()) { 12164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (ShouldInstrumentGlobal(&G)) GlobalsToChange.push_back(&G); 1217800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1218800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1219800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany size_t n = GlobalsToChange.size(); 1220800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany if (n == 0) return false; 1221800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1222800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // A global is described by a structure 1223800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // size_t beg; 1224800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // size_t size; 1225800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // size_t size_with_redzone; 1226800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // const char *name; 1227086a472dbed9911f83add781e020cb49c89829d0Kostya Serebryany // const char *module_name; 12289b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // size_t has_dynamic_init; 1229c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // void *source_location; 1230800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // We initialize an array of such structures and pass it to a run-time call. 1231c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StructType *GlobalStructTy = 1232c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, 123337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IntptrTy, IntptrTy, nullptr); 12348819c84aed10777ba91d4e862229882b8da0b272Rafael Espindola SmallVector<Constant *, 16> Initializers(n); 1235b9a12ea0fd92bfdb4c6eb5af333648a618f68686Kostya Serebryany 1236ca825ea24de2f3d819845ee01796dc6c7a45170dAlexey Samsonov bool HasDynamicallyInitializedGlobals = false; 12379b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 1238ca825ea24de2f3d819845ee01796dc6c7a45170dAlexey Samsonov // We shouldn't merge same module names, as this string serves as unique 1239ca825ea24de2f3d819845ee01796dc6c7a45170dAlexey Samsonov // module ID in runtime. 124036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines GlobalVariable *ModuleName = createPrivateGlobalForString( 12414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar M, M.getModuleIdentifier(), /*AllowMerging*/ false); 1242086a472dbed9911f83add781e020cb49c89829d0Kostya Serebryany 12434c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar auto &DL = M.getDataLayout(); 1244800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany for (size_t i = 0; i < n; i++) { 124529f975f8ffda1f5d78cbf2530c2316abef11aa70Kostya Serebryany static const uint64_t kMaxGlobalRedzone = 1 << 18; 1246800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany GlobalVariable *G = GlobalsToChange[i]; 124737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 124837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto MD = GlobalsMD.get(G); 124937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Create string holding the global name (use global name from metadata 125037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // if it's available, otherwise just write the name of global variable). 125137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines GlobalVariable *Name = createPrivateGlobalForString( 125237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines M, MD.Name.empty() ? G->getName() : MD.Name, 125337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines /*AllowMerging*/ true); 125437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 1255800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany PointerType *PtrTy = cast<PointerType>(G->getType()); 1256800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Type *Ty = PtrTy->getElementType(); 12574c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t SizeInBytes = DL.getTypeAllocSize(Ty); 125836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t MinRZ = MinRedzoneSizeForGlobal(); 125963f0846f1eb43332a08811d332b813276b727eb6Kostya Serebryany // MinRZ <= RZ <= kMaxGlobalRedzone 126063f0846f1eb43332a08811d332b813276b727eb6Kostya Serebryany // and trying to make RZ to be ~ 1/4 of SizeInBytes. 12614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t RZ = std::max( 12624c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar MinRZ, std::min(kMaxGlobalRedzone, (SizeInBytes / MinRZ / 4) * MinRZ)); 126363f0846f1eb43332a08811d332b813276b727eb6Kostya Serebryany uint64_t RightRedzoneSize = RZ; 126463f0846f1eb43332a08811d332b813276b727eb6Kostya Serebryany // Round up to MinRZ 12654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (SizeInBytes % MinRZ) RightRedzoneSize += MinRZ - (SizeInBytes % MinRZ); 126663f0846f1eb43332a08811d332b813276b727eb6Kostya Serebryany assert(((RightRedzoneSize + SizeInBytes) % MinRZ) == 0); 1267800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); 1268800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 126937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines StructType *NewTy = StructType::get(Ty, RightRedZoneTy, nullptr); 12704c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Constant *NewInitializer = 12714c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ConstantStruct::get(NewTy, G->getInitializer(), 12724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Constant::getNullValue(RightRedZoneTy), nullptr); 1273800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1274800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // Create a new global variable with enough space for a redzone. 127555a1a590bf0cadf88dfbef2aab6948ffec35c1c3Bill Wendling GlobalValue::LinkageTypes Linkage = G->getLinkage(); 127655a1a590bf0cadf88dfbef2aab6948ffec35c1c3Bill Wendling if (G->isConstant() && Linkage == GlobalValue::PrivateLinkage) 127755a1a590bf0cadf88dfbef2aab6948ffec35c1c3Bill Wendling Linkage = GlobalValue::InternalLinkage; 12784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar GlobalVariable *NewGlobal = 12794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar new GlobalVariable(M, NewTy, G->isConstant(), Linkage, NewInitializer, 12804c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar "", G, G->getThreadLocalMode()); 1281800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany NewGlobal->copyAttributesFrom(G); 128263f0846f1eb43332a08811d332b813276b727eb6Kostya Serebryany NewGlobal->setAlignment(MinRZ); 1283800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1284800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Value *Indices2[2]; 1285800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Indices2[0] = IRB.getInt32(0); 1286800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Indices2[1] = IRB.getInt32(0); 1287800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1288800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany G->replaceAllUsesWith( 12890c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar ConstantExpr::getGetElementPtr(NewTy, NewGlobal, Indices2, true)); 1290800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany NewGlobal->takeName(G); 1291800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany G->eraseFromParent(); 1292800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 129337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Constant *SourceLoc; 129437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!MD.SourceLoc.empty()) { 129537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto SourceLocGlobal = createPrivateGlobalForSourceLoc(M, MD.SourceLoc); 129637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SourceLoc = ConstantExpr::getPointerCast(SourceLocGlobal, IntptrTy); 129737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 129837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SourceLoc = ConstantInt::get(IntptrTy, 0); 129937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 1300c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 1301800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Initializers[i] = ConstantStruct::get( 1302c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy), 1303800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany ConstantInt::get(IntptrTy, SizeInBytes), 1304800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), 1305800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany ConstantExpr::getPointerCast(Name, IntptrTy), 1306086a472dbed9911f83add781e020cb49c89829d0Kostya Serebryany ConstantExpr::getPointerCast(ModuleName, IntptrTy), 130737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc, nullptr); 13089b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 13094c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (ClInitializers && MD.IsDynInit) HasDynamicallyInitializedGlobals = true; 13109b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany 1311324d96b9e265b0fd8bf63a28340910def64e2164Kostya Serebryany DEBUG(dbgs() << "NEW GLOBAL: " << *NewGlobal << "\n"); 1312800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1313800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1314800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n); 1315800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany GlobalVariable *AllGlobals = new GlobalVariable( 131655a1a590bf0cadf88dfbef2aab6948ffec35c1c3Bill Wendling M, ArrayOfGlobalStructTy, false, GlobalVariable::InternalLinkage, 1317800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany ConstantArray::get(ArrayOfGlobalStructTy, Initializers), ""); 1318800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 13199b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany // Create calls for poisoning before initializers run and unpoisoning after. 1320c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (HasDynamicallyInitializedGlobals) 1321ca825ea24de2f3d819845ee01796dc6c7a45170dAlexey Samsonov createInitializerPoisonCalls(M, ModuleName); 13226948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanRegisterGlobals, 13236948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {IRB.CreatePointerCast(AllGlobals, IntptrTy), 13246948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ConstantInt::get(IntptrTy, n)}); 1325800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 13267bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany // We also need to unregister globals at the end, e.g. when a shared library 13277bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany // gets closed. 13284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Function *AsanDtorFunction = 13294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Function::Create(FunctionType::get(Type::getVoidTy(*C), false), 13304c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); 13317bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); 13327bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB)); 13336948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB_Dtor.CreateCall(AsanUnregisterGlobals, 13346948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {IRB.CreatePointerCast(AllGlobals, IntptrTy), 13356948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ConstantInt::get(IntptrTy, n)}); 1336c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority); 13377bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany 1338800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany DEBUG(dbgs() << M); 1339800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany return true; 1340800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 1341800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1342c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesbool AddressSanitizerModule::runOnModule(Module &M) { 1343c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines C = &(M.getContext()); 13444c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar int LongSize = M.getDataLayout().getPointerSizeInBits(); 1345c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines IntptrTy = Type::getIntNTy(*C, LongSize); 1346ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines TargetTriple = Triple(M.getTargetTriple()); 1347ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Mapping = getShadowMapping(TargetTriple, LongSize); 1348c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines initializeCallbacks(M); 1349c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 1350c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines bool Changed = false; 1351c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 1352c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines Function *CtorFunc = M.getFunction(kAsanModuleCtorName); 1353c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines assert(CtorFunc); 1354c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines IRBuilder<> IRB(CtorFunc->getEntryBlock().getTerminator()); 1355c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 13564c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (ClGlobals) Changed |= InstrumentGlobals(IRB, M); 1357c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 1358c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return Changed; 1359c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines} 1360c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 13618b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryanyvoid AddressSanitizer::initializeCallbacks(Module &M) { 13628b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany IRBuilder<> IRB(*C); 13639db5b5ffa9fccd5c7f1f39a3e9aa66cc4a5eedc1Kostya Serebryany // Create __asan_report* callbacks. 13644c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // IsWrite, TypeSize and Exp are encoded in the function name. 13654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (int Exp = 0; Exp < 2; Exp++) { 13664c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) { 13674c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const std::string TypeStr = AccessIsWrite ? "store" : "load"; 13684c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const std::string ExpStr = Exp ? "exp_" : ""; 13694c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const Type *ExpType = Exp ? Type::getInt32Ty(*C) : nullptr; 13704c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AsanErrorCallbackSized[AccessIsWrite][Exp] = 13710c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar checkSanitizerInterfaceFunction(M.getOrInsertFunction( 13724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar kAsanReportErrorTemplate + ExpStr + TypeStr + "_n", 13734c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr)); 13744c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AsanMemoryAccessCallbackSized[AccessIsWrite][Exp] = 13750c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar checkSanitizerInterfaceFunction(M.getOrInsertFunction( 13764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ClMemoryAccessCallbackPrefix + ExpStr + TypeStr + "N", 13774c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr)); 13784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; 13794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AccessSizeIndex++) { 13804c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const std::string Suffix = TypeStr + itostr(1 << AccessSizeIndex); 13814c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AsanErrorCallback[AccessIsWrite][Exp][AccessSizeIndex] = 13820c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar checkSanitizerInterfaceFunction(M.getOrInsertFunction( 13834c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar kAsanReportErrorTemplate + ExpStr + Suffix, IRB.getVoidTy(), 13844c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntptrTy, ExpType, nullptr)); 13854c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AsanMemoryAccessCallback[AccessIsWrite][Exp][AccessSizeIndex] = 13860c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar checkSanitizerInterfaceFunction(M.getOrInsertFunction( 13874c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ClMemoryAccessCallbackPrefix + ExpStr + Suffix, IRB.getVoidTy(), 13884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntptrTy, ExpType, nullptr)); 13894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 13909db5b5ffa9fccd5c7f1f39a3e9aa66cc4a5eedc1Kostya Serebryany } 13919db5b5ffa9fccd5c7f1f39a3e9aa66cc4a5eedc1Kostya Serebryany } 1392dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 13930c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanMemmove = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 1394dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(), 139537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy, nullptr)); 13960c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanMemcpy = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 1397dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ClMemoryAccessCallbackPrefix + "memcpy", IRB.getInt8PtrTy(), 139837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy, nullptr)); 13990c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanMemset = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 1400dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ClMemoryAccessCallbackPrefix + "memset", IRB.getInt8PtrTy(), 140137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy, nullptr)); 1402dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 14030c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanHandleNoReturnFunc = checkSanitizerInterfaceFunction( 140437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines M.getOrInsertFunction(kAsanHandleNoReturnName, IRB.getVoidTy(), nullptr)); 140537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 14060c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanPtrCmpFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 140737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines kAsanPtrCmp, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); 14080c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanPtrSubFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 140937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines kAsanPtrSub, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); 1410f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany // We insert an empty inline asm after __asan_report* to avoid callback merge. 1411f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), 1412f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany StringRef(""), StringRef(""), 1413f7b08226eb44458f6f38cbeaca527028803c725aKostya Serebryany /*hasSideEffects=*/true); 14148b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany} 14158b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany 14168b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany// virtual 14178b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryanybool AddressSanitizer::doInitialization(Module &M) { 14188b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany // Initialize the private fields. No one has accessed them before. 141936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1420c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines GlobalsMD.init(M); 14218b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany 14228b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany C = &(M.getContext()); 14234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar LongSize = M.getDataLayout().getPointerSizeInBits(); 14248b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany IntptrTy = Type::getIntNTy(*C, LongSize); 1425ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines TargetTriple = Triple(M.getTargetTriple()); 14268b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany 14276948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar std::tie(AsanCtorFunction, AsanInitFunction) = 14286948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName, kAsanInitName, 14296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar /*InitArgTypes=*/{}, 14306948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar /*InitArgs=*/{}); 14319db5b5ffa9fccd5c7f1f39a3e9aa66cc4a5eedc1Kostya Serebryany 1432ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Mapping = getShadowMapping(TargetTriple, LongSize); 1433800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1434c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority); 1435ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryany return true; 1436ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryany} 1437ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryany 1438a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryanybool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) { 1439a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany // For each NSObject descendant having a +load method, this method is invoked 1440a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany // by the ObjC runtime before any of the static constructors is called. 1441a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany // Therefore we need to instrument such methods with a call to __asan_init 1442a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany // at the beginning in order to initialize our runtime before any access to 1443a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany // the shadow memory. 1444a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany // We cannot just ignore these methods, because they may call other 1445a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany // instrumented functions. 1446a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany if (F.getName().find(" load]") != std::string::npos) { 1447a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany IRBuilder<> IRB(F.begin()->begin()); 14486948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanInitFunction, {}); 1449a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany return true; 1450a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany } 1451a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany return false; 1452a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany} 1453a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany 1454ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryanybool AddressSanitizer::runOnFunction(Function &F) { 1455800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany if (&F == AsanCtorFunction) return false; 14563797adb94fdc6b747cb0e97a64b15b931f2533b8Kostya Serebryany if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return false; 1457324d96b9e265b0fd8bf63a28340910def64e2164Kostya Serebryany DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n"); 14588b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany initializeCallbacks(*F.getParent()); 1459a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany 1460ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 1461ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 14628eec41fc778e99d42172a7f6de76faa43a6d8847Kostya Serebryany // If needed, insert __asan_init before checking for SanitizeAddress attr. 1463a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany maybeInsertAsanInitAtFunctionEntry(F); 1464a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590Kostya Serebryany 14654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!F.hasFnAttribute(Attribute::SanitizeAddress)) return false; 1466800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 14674c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!ClDebugFunc.empty() && ClDebugFunc != F.getName()) return false; 14686765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling 14696765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling // We want to instrument every address only once per basic block (unless there 14706765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling // are calls between uses). 14714c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SmallSet<Value *, 16> TempsToInstrument; 14724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SmallVector<Instruction *, 16> ToInstrument; 14734c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SmallVector<Instruction *, 8> NoReturnCalls; 14744c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SmallVector<BasicBlock *, 16> AllBlocks; 14754c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SmallVector<Instruction *, 16> PointerComparisonsOrSubtracts; 147620985711c76b8799d689a9c0e416b68896333c23Kostya Serebryany int NumAllocas = 0; 1477e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany bool IsWrite; 1478dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines unsigned Alignment; 14794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t TypeSize; 1480800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1481800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // Fill the set of memory operations to instrument. 1482c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto &BB : F) { 1483c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines AllBlocks.push_back(&BB); 1484800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany TempsToInstrument.clear(); 1485324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany int NumInsnsPerBB = 0; 1486c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto &Inst : BB) { 1487c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (LooksLikeCodeInBug11395(&Inst)) return false; 14884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize, 14894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar &Alignment)) { 1490800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany if (ClOpt && ClOptSameTemp) { 149137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!TempsToInstrument.insert(Addr).second) 1492800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany continue; // We've seen this temp in the current BB. 1493800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 149436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else if (ClInvalidPointerPairs && 1495c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines isInterestingPointerComparisonOrSubtraction(&Inst)) { 1496c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines PointerComparisonsOrSubtracts.push_back(&Inst); 149736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 1498c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines } else if (isa<MemIntrinsic>(Inst)) { 1499800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // ok, take it. 1500800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } else { 15014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (isa<AllocaInst>(Inst)) NumAllocas++; 1502c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines CallSite CS(&Inst); 15031479c9bb392325688b72e5829bbb7939c4a079a4Kostya Serebryany if (CS) { 1504800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // A call inside BB. 1505800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany TempsToInstrument.clear(); 15064c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (CS.doesNotReturn()) NoReturnCalls.push_back(CS.getInstruction()); 1507800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1508800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany continue; 1509800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1510c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ToInstrument.push_back(&Inst); 1511324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany NumInsnsPerBB++; 15124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (NumInsnsPerBB >= ClMaxInsnsToInstrumentPerBB) break; 1513800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1514800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1515800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1516dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool UseCalls = false; 1517dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (ClInstrumentationWithCallsThreshold >= 0 && 1518dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ToInstrument.size() > (unsigned)ClInstrumentationWithCallsThreshold) 1519dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines UseCalls = true; 1520dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 15214c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const TargetLibraryInfo *TLI = 15224c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); 15234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const DataLayout &DL = F.getParent()->getDataLayout(); 15244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ObjectSizeOffsetVisitor ObjSizeVis(DL, TLI, F.getContext(), 15254c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar /*RoundToAlign=*/true); 15264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 1527800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // Instrument. 1528800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany int NumInstrumented = 0; 1529c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto Inst : ToInstrument) { 1530800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany if (ClDebugMin < 0 || ClDebugMax < 0 || 1531800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany (NumInstrumented >= ClDebugMin && NumInstrumented <= ClDebugMax)) { 15324c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (isInterestingMemoryAccess(Inst, &IsWrite, &TypeSize, &Alignment)) 15334c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar instrumentMop(ObjSizeVis, Inst, UseCalls, 15344c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar F.getParent()->getDataLayout()); 1535800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany else 1536ee4edeccabe1854ee895f52d4ac5588bd5f40c80Kostya Serebryany instrumentMemIntrinsic(cast<MemIntrinsic>(Inst)); 1537800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1538800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany NumInstrumented++; 1539800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1540800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 154159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov FunctionStackPoisoner FSP(F, *this); 154259cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov bool ChangedStack = FSP.runOnFunction(); 154395e3cf44a9d4672655dee3bd558bfeefa631dd55Kostya Serebryany 154495e3cf44a9d4672655dee3bd558bfeefa631dd55Kostya Serebryany // We must unpoison the stack before every NoReturn call (throw, _exit, etc). 154595e3cf44a9d4672655dee3bd558bfeefa631dd55Kostya Serebryany // See e.g. http://code.google.com/p/address-sanitizer/issues/detail?id=37 1546c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto CI : NoReturnCalls) { 154795e3cf44a9d4672655dee3bd558bfeefa631dd55Kostya Serebryany IRBuilder<> IRB(CI); 15486948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanHandleNoReturnFunc, {}); 154995e3cf44a9d4672655dee3bd558bfeefa631dd55Kostya Serebryany } 155095e3cf44a9d4672655dee3bd558bfeefa631dd55Kostya Serebryany 1551c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto Inst : PointerComparisonsOrSubtracts) { 1552c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines instrumentPointerComparisonOrSubtraction(Inst); 155336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines NumInstrumented++; 155436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 155536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 155620985711c76b8799d689a9c0e416b68896333c23Kostya Serebryany bool res = NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty(); 15574b8991424a8967dfdafc1768a9748f67e6c8b36fBob Wilson 155820985711c76b8799d689a9c0e416b68896333c23Kostya Serebryany DEBUG(dbgs() << "ASAN done instrumenting: " << res << " " << F << "\n"); 155920985711c76b8799d689a9c0e416b68896333c23Kostya Serebryany 156020985711c76b8799d689a9c0e416b68896333c23Kostya Serebryany return res; 1561800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 1562800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 156359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// Workaround for bug 11395: we don't want to instrument stack in functions 156459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// with large assembly blobs (32-bit only), otherwise reg alloc may crash. 156559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// FIXME: remove once the bug 11395 is fixed. 156659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonovbool AddressSanitizer::LooksLikeCodeInBug11395(Instruction *I) { 156759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov if (LongSize != 32) return false; 156859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov CallInst *CI = dyn_cast<CallInst>(I); 156959cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov if (!CI || !CI->isInlineAsm()) return false; 157059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov if (CI->getNumArgOperands() <= 5) return false; 157159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov // We have inline assembly with quite a few arguments. 157259cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov return true; 157359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov} 157459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 157559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonovvoid FunctionStackPoisoner::initializeCallbacks(Module &M) { 157659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov IRBuilder<> IRB(*C); 1577f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany for (int i = 0; i <= kMaxAsanStackMallocSizeClass; i++) { 1578f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany std::string Suffix = itostr(i); 15790c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanStackMallocFunc[i] = checkSanitizerInterfaceFunction( 15800c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar M.getOrInsertFunction(kAsanStackMallocNameTemplate + Suffix, IntptrTy, 15810c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar IntptrTy, nullptr)); 15820c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanStackFreeFunc[i] = checkSanitizerInterfaceFunction( 1583ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines M.getOrInsertFunction(kAsanStackFreeNameTemplate + Suffix, 1584ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); 1585f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany } 15860c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanPoisonStackMemoryFunc = checkSanitizerInterfaceFunction( 158737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines M.getOrInsertFunction(kAsanPoisonStackMemoryName, IRB.getVoidTy(), 158837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IntptrTy, IntptrTy, nullptr)); 15890c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar AsanUnpoisonStackMemoryFunc = checkSanitizerInterfaceFunction( 159037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines M.getOrInsertFunction(kAsanUnpoisonStackMemoryName, IRB.getVoidTy(), 159137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IntptrTy, IntptrTy, nullptr)); 15926948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar AsanAllocaPoisonFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 15936948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar kAsanAllocaPoison, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); 15946948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar AsanAllocasUnpoisonFunc = 15956948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar checkSanitizerInterfaceFunction(M.getOrInsertFunction( 15966948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar kAsanAllocasUnpoison, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr)); 159759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov} 159859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 15994c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarvoid FunctionStackPoisoner::poisonRedZones(ArrayRef<uint8_t> ShadowBytes, 16004c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRBuilder<> &IRB, Value *ShadowBase, 16014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar bool DoPoison) { 160236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t n = ShadowBytes.size(); 160336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t i = 0; 160436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // We need to (un)poison n bytes of stack shadow. Poison as many as we can 160536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // using 64-bit stores (if we are on 64-bit arch), then poison the rest 160636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // with 32-bit stores, then with 16-byte stores, then with 8-byte stores. 160736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (size_t LargeStoreSizeInBytes = ASan.LongSize / 8; 160836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines LargeStoreSizeInBytes != 0; LargeStoreSizeInBytes /= 2) { 160936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (; i + LargeStoreSizeInBytes - 1 < n; i += LargeStoreSizeInBytes) { 161036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Val = 0; 161136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (size_t j = 0; j < LargeStoreSizeInBytes; j++) { 16124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (F.getParent()->getDataLayout().isLittleEndian()) 161336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Val |= (uint64_t)ShadowBytes[i + j] << (8 * j); 161436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 161536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Val = (Val << 8) | ShadowBytes[i + j]; 1616800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 161736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!Val) continue; 161836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value *Ptr = IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)); 161936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type *StoreTy = Type::getIntNTy(*C, LargeStoreSizeInBytes * 8); 162036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value *Poison = ConstantInt::get(StoreTy, DoPoison ? Val : 0); 162136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines IRB.CreateStore(Poison, IRB.CreateIntToPtr(Ptr, StoreTy->getPointerTo())); 1622800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1623800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1624800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 1625800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1626f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany// Fake stack allocator (asan_fake_stack.h) has 11 size classes 1627f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany// for every power of 2 from kMinStackMallocSize to kMaxAsanStackMallocSizeClass 1628f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryanystatic int StackMallocSizeClass(uint64_t LocalStackSize) { 1629f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany assert(LocalStackSize <= kMaxStackMallocSize); 1630f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany uint64_t MaxSize = kMinStackMallocSize; 16314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (int i = 0;; i++, MaxSize *= 2) 16324c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (LocalStackSize <= MaxSize) return i; 1633f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany llvm_unreachable("impossible LocalStackSize"); 1634f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany} 1635f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany 1636671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany// Set Size bytes starting from ShadowBase to kAsanStackAfterReturnMagic. 1637671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany// We can not use MemSet intrinsic because it may end up calling the actual 1638671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany// memset. Size is a multiple of 8. 1639671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany// Currently this generates 8-byte stores on x86_64; it may be better to 1640671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany// generate wider stores. 1641671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryanyvoid FunctionStackPoisoner::SetShadowToStackAfterReturnInlined( 1642671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany IRBuilder<> &IRB, Value *ShadowBase, int Size) { 1643671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany assert(!(Size % 8)); 16444c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 16454c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // kAsanStackAfterReturnMagic is 0xf5. 16464c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const uint64_t kAsanStackAfterReturnMagic64 = 0xf5f5f5f5f5f5f5f5ULL; 16474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 1648671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany for (int i = 0; i < Size; i += 8) { 1649671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany Value *p = IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)); 16504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateStore( 16514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ConstantInt::get(IRB.getInt64Ty(), kAsanStackAfterReturnMagic64), 16524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateIntToPtr(p, IRB.getInt64Ty()->getPointerTo())); 1653671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany } 1654671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany} 1655671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany 1656dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic DebugLoc getFunctionEntryDebugLocation(Function &F) { 1657c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (const auto &Inst : F.getEntryBlock()) 16584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!isa<AllocaInst>(Inst)) return Inst.getDebugLoc(); 1659c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return DebugLoc(); 1660dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 1661dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 1662ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesPHINode *FunctionStackPoisoner::createPHI(IRBuilder<> &IRB, Value *Cond, 1663ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *ValueIfTrue, 1664ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Instruction *ThenTerm, 1665ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *ValueIfFalse) { 1666ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines PHINode *PHI = IRB.CreatePHI(IntptrTy, 2); 1667ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines BasicBlock *CondBlock = cast<Instruction>(Cond)->getParent(); 1668ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines PHI->addIncoming(ValueIfFalse, CondBlock); 1669ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines BasicBlock *ThenBlock = ThenTerm->getParent(); 1670ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines PHI->addIncoming(ValueIfTrue, ThenBlock); 1671ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return PHI; 1672ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 1673ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1674ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesValue *FunctionStackPoisoner::createAllocaForLayout( 1675ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRBuilder<> &IRB, const ASanStackFrameLayout &L, bool Dynamic) { 1676ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AllocaInst *Alloca; 1677ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (Dynamic) { 1678ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Alloca = IRB.CreateAlloca(IRB.getInt8Ty(), 1679ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ConstantInt::get(IRB.getInt64Ty(), L.FrameSize), 1680ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines "MyAlloca"); 1681ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } else { 1682ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Alloca = IRB.CreateAlloca(ArrayType::get(IRB.getInt8Ty(), L.FrameSize), 1683ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines nullptr, "MyAlloca"); 1684ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(Alloca->isStaticAlloca()); 1685ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 1686ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert((ClRealignStack & (ClRealignStack - 1)) == 0); 1687ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines size_t FrameAlignment = std::max(L.FrameAlignment, (size_t)ClRealignStack); 1688ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Alloca->setAlignment(FrameAlignment); 1689ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return IRB.CreatePointerCast(Alloca, IntptrTy); 1690ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 1691ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 16926948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarvoid FunctionStackPoisoner::createDynamicAllocasInitStorage() { 16936948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar BasicBlock &FirstBB = *F.begin(); 16946948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRBuilder<> IRB(dyn_cast<Instruction>(FirstBB.begin())); 16956948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar DynamicAllocaLayout = IRB.CreateAlloca(IntptrTy, nullptr); 16966948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateStore(Constant::getNullValue(IntptrTy), DynamicAllocaLayout); 16976948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar DynamicAllocaLayout->setAlignment(32); 16986948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar} 16996948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 170059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonovvoid FunctionStackPoisoner::poisonStack() { 1701ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(AllocaVec.size() > 0 || DynamicAllocaVec.size() > 0); 1702ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 17036948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar if (ClInstrumentAllocas && DynamicAllocaVec.size() > 0) { 1704ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Handle dynamic allocas. 17056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar createDynamicAllocasInitStorage(); 17066948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar for (auto &AI : DynamicAllocaVec) handleDynamicAllocaCall(AI); 17076948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 17086948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar unpoisonDynamicAllocas(); 1709ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 1710ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1711ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (AllocaVec.size() == 0) return; 1712ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1713f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany int StackMallocIdx = -1; 1714dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines DebugLoc EntryDebugLocation = getFunctionEntryDebugLocation(F); 1715800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1716800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Instruction *InsBefore = AllocaVec[0]; 1717800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany IRBuilder<> IRB(InsBefore); 1718dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines IRB.SetCurrentDebugLocation(EntryDebugLocation); 1719800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 172036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SmallVector<ASanStackVariableDescription, 16> SVD; 172136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SVD.reserve(AllocaVec.size()); 1722c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (AllocaInst *AI : AllocaVec) { 17234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ASanStackVariableDescription D = {AI->getName().data(), 17244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ASan.getAllocaSizeInBytes(AI), 17254c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar AI->getAlignment(), AI, 0}; 172636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SVD.push_back(D); 172736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 172836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Minimal header size (left redzone) is 4 pointers, 172936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // i.e. 32 bytes on 64-bit platforms and 16 bytes in 32-bit platforms. 173036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t MinHeaderSize = ASan.LongSize / 2; 173136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ASanStackFrameLayout L; 173236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ComputeASanStackFrameLayout(SVD, 1UL << Mapping.Scale, MinHeaderSize, &L); 173336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DEBUG(dbgs() << L.DescriptionString << " --- " << L.FrameSize << "\n"); 173436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t LocalStackSize = L.FrameSize; 173536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool DoStackMalloc = 1736c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ClUseAfterReturn && LocalStackSize <= kMaxStackMallocSize; 17370c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar // Don't do dynamic alloca in presence of inline asm: too often it makes 17380c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar // assumptions on which registers are available. Don't do stack malloc in the 17390c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar // presence of inline asm on 32-bit platforms for the same reason. 1740ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool DoDynamicAlloca = ClDynamicAllocaStack && !HasNonEmptyInlineAsm; 17410c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar DoStackMalloc &= !HasNonEmptyInlineAsm || ASan.LongSize != 32; 1742800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1743ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *StaticAlloca = 1744ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DoDynamicAlloca ? nullptr : createAllocaForLayout(IRB, L, false); 1745ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1746ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *FakeStack; 1747ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *LocalStackBase; 1748800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1749800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany if (DoStackMalloc) { 1750ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // void *FakeStack = __asan_option_detect_stack_use_after_return 1751ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // ? __asan_stack_malloc_N(LocalStackSize) 1752ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // : nullptr; 1753ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // void *LocalStackBase = (FakeStack) ? FakeStack : alloca(LocalStackSize); 1754ac04abaf5a1df4c4bf48367cfbb41600289c4d78Kostya Serebryany Constant *OptionDetectUAR = F.getParent()->getOrInsertGlobal( 1755ac04abaf5a1df4c4bf48367cfbb41600289c4d78Kostya Serebryany kAsanOptionDetectUAR, IRB.getInt32Ty()); 1756ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *UARIsEnabled = 1757ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRB.CreateICmpNE(IRB.CreateLoad(OptionDetectUAR), 1758ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Constant::getNullValue(IRB.getInt32Ty())); 1759ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Instruction *Term = 1760ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines SplitBlockAndInsertIfThen(UARIsEnabled, InsBefore, false); 1761ac04abaf5a1df4c4bf48367cfbb41600289c4d78Kostya Serebryany IRBuilder<> IRBIf(Term); 1762dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines IRBIf.SetCurrentDebugLocation(EntryDebugLocation); 1763ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines StackMallocIdx = StackMallocSizeClass(LocalStackSize); 1764ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(StackMallocIdx <= kMaxAsanStackMallocSizeClass); 1765ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *FakeStackValue = 1766ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRBIf.CreateCall(AsanStackMallocFunc[StackMallocIdx], 1767ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ConstantInt::get(IntptrTy, LocalStackSize)); 1768ac04abaf5a1df4c4bf48367cfbb41600289c4d78Kostya Serebryany IRB.SetInsertPoint(InsBefore); 1769dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines IRB.SetCurrentDebugLocation(EntryDebugLocation); 1770ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FakeStack = createPHI(IRB, UARIsEnabled, FakeStackValue, Term, 1771ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ConstantInt::get(IntptrTy, 0)); 1772ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1773ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *NoFakeStack = 1774ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRB.CreateICmpEQ(FakeStack, Constant::getNullValue(IntptrTy)); 1775ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Term = SplitBlockAndInsertIfThen(NoFakeStack, InsBefore, false); 1776ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRBIf.SetInsertPoint(Term); 1777ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRBIf.SetCurrentDebugLocation(EntryDebugLocation); 1778ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *AllocaValue = 1779ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DoDynamicAlloca ? createAllocaForLayout(IRBIf, L, true) : StaticAlloca; 1780ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRB.SetInsertPoint(InsBefore); 1781ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRB.SetCurrentDebugLocation(EntryDebugLocation); 1782ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines LocalStackBase = createPHI(IRB, NoFakeStack, AllocaValue, Term, FakeStack); 1783ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } else { 1784ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // void *FakeStack = nullptr; 1785ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // void *LocalStackBase = alloca(LocalStackSize); 1786ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FakeStack = ConstantInt::get(IntptrTy, 0); 1787ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines LocalStackBase = 1788ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DoDynamicAlloca ? createAllocaForLayout(IRB, L, true) : StaticAlloca; 1789800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1790800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 17911c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Insert poison calls for lifetime intrinsics for alloca. 17921c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov bool HavePoisonedAllocas = false; 1793c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (const auto &APC : AllocaPoisonCallVec) { 179464409ad8e3b360b84349042f14b57f87a5c0ca18Alexey Samsonov assert(APC.InsBefore); 179564409ad8e3b360b84349042f14b57f87a5c0ca18Alexey Samsonov assert(APC.AI); 179664409ad8e3b360b84349042f14b57f87a5c0ca18Alexey Samsonov IRBuilder<> IRB(APC.InsBefore); 179764409ad8e3b360b84349042f14b57f87a5c0ca18Alexey Samsonov poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison); 17981c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov HavePoisonedAllocas |= APC.DoPoison; 17991c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov } 18001c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov 1801800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // Replace Alloca instructions with base+offset. 1802c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (const auto &Desc : SVD) { 1803c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines AllocaInst *AI = Desc.AI; 1804f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov Value *NewAllocaPtr = IRB.CreateIntToPtr( 1805c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Desc.Offset)), 180636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines AI->getType()); 1807ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines replaceDbgDeclareForAlloca(AI, NewAllocaPtr, DIB, /*Deref=*/true); 1808f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov AI->replaceAllUsesWith(NewAllocaPtr); 1809800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1810800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 18113016056769639878b4f152838f0cf16d2e482339Kostya Serebryany // The left-most redzone has enough space for at least 4 pointers. 18123016056769639878b4f152838f0cf16d2e482339Kostya Serebryany // Write the Magic value to redzone[0]. 1813800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany Value *BasePlus0 = IRB.CreateIntToPtr(LocalStackBase, IntptrPtrTy); 1814800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany IRB.CreateStore(ConstantInt::get(IntptrTy, kCurrentStackFrameMagic), 1815800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany BasePlus0); 18163016056769639878b4f152838f0cf16d2e482339Kostya Serebryany // Write the frame description constant to redzone[1]. 18173016056769639878b4f152838f0cf16d2e482339Kostya Serebryany Value *BasePlus1 = IRB.CreateIntToPtr( 18184c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateAdd(LocalStackBase, 18194c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ConstantInt::get(IntptrTy, ASan.LongSize / 8)), 18204c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntptrPtrTy); 18219ce84c1c95c0153a2f33e188ce0db00770425f9eAlexey Samsonov GlobalVariable *StackDescriptionGlobal = 182236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines createPrivateGlobalForString(*F.getParent(), L.DescriptionString, 18234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar /*AllowMerging*/ true); 18244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *Description = IRB.CreatePointerCast(StackDescriptionGlobal, IntptrTy); 1825800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany IRB.CreateStore(Description, BasePlus1); 18263016056769639878b4f152838f0cf16d2e482339Kostya Serebryany // Write the PC to redzone[2]. 18273016056769639878b4f152838f0cf16d2e482339Kostya Serebryany Value *BasePlus2 = IRB.CreateIntToPtr( 18284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IRB.CreateAdd(LocalStackBase, 18294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ConstantInt::get(IntptrTy, 2 * ASan.LongSize / 8)), 18304c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar IntptrPtrTy); 18313016056769639878b4f152838f0cf16d2e482339Kostya Serebryany IRB.CreateStore(IRB.CreatePointerCast(&F, IntptrTy), BasePlus2); 1832800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1833800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // Poison the stack redzones at the entry. 183459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB); 183536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines poisonRedZones(L.ShadowBytes, IRB, ShadowBase, true); 1836800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 183736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // (Un)poison the stack before all ret instructions. 1838c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines for (auto Ret : RetVec) { 1839800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany IRBuilder<> IRBRet(Ret); 1840800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany // Mark the current frame as retired. 1841800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany IRBRet.CreateStore(ConstantInt::get(IntptrTy, kRetiredStackFrameMagic), 1842800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany BasePlus0); 1843800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany if (DoStackMalloc) { 1844f3d4b35f24f4e54b2cb99e06f47a958e5557d01eKostya Serebryany assert(StackMallocIdx >= 0); 1845ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // if FakeStack != 0 // LocalStackBase == FakeStack 184636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // // In use-after-return mode, poison the whole stack frame. 184736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // if StackMallocIdx <= 4 184836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // // For small sizes inline the whole thing: 184936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // memset(ShadowBase, kAsanStackAfterReturnMagic, ShadowSize); 1850ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // **SavedFlagPtr(FakeStack) = 0 185136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // else 1852ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // __asan_stack_free_N(FakeStack, LocalStackSize) 185336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // else 185436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // <This is not a fake stack; unpoison the redzones> 1855ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *Cmp = 1856ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRBRet.CreateICmpNE(FakeStack, Constant::getNullValue(IntptrTy)); 185736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TerminatorInst *ThenTerm, *ElseTerm; 185836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SplitBlockAndInsertIfThenElse(Cmp, Ret, &ThenTerm, &ElseTerm); 185936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 186036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines IRBuilder<> IRBPoison(ThenTerm); 1861671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany if (StackMallocIdx <= 4) { 1862671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany int ClassSize = kMinStackMallocSize << StackMallocIdx; 1863671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany SetShadowToStackAfterReturnInlined(IRBPoison, ShadowBase, 1864671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany ClassSize >> Mapping.Scale); 1865671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany Value *SavedFlagPtrPtr = IRBPoison.CreateAdd( 1866ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FakeStack, 1867671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany ConstantInt::get(IntptrTy, ClassSize - ASan.LongSize / 8)); 1868671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany Value *SavedFlagPtr = IRBPoison.CreateLoad( 1869671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany IRBPoison.CreateIntToPtr(SavedFlagPtrPtr, IntptrPtrTy)); 1870671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany IRBPoison.CreateStore( 1871671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany Constant::getNullValue(IRBPoison.getInt8Ty()), 1872671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getInt8PtrTy())); 1873671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany } else { 1874671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany // For larger frames call __asan_stack_free_*. 18756948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRBPoison.CreateCall( 18766948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar AsanStackFreeFunc[StackMallocIdx], 18776948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {FakeStack, ConstantInt::get(IntptrTy, LocalStackSize)}); 1878671c3ba921d5b8271307a8caa5e29f512d2e8e82Kostya Serebryany } 187936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 188036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines IRBuilder<> IRBElse(ElseTerm); 188136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines poisonRedZones(L.ShadowBytes, IRBElse, ShadowBase, false); 1882f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov } else if (HavePoisonedAllocas) { 1883f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov // If we poisoned some allocas in llvm.lifetime analysis, 1884f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov // unpoison whole stack frame now. 1885f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov poisonAlloca(LocalStackBase, LocalStackSize, IRBRet, false); 188636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 188736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines poisonRedZones(L.ShadowBytes, IRBRet, ShadowBase, false); 1888800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1889800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany } 1890800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany 1891bd0052a0f26f04b8fcf59e8f645e5e33751e1f6eKostya Serebryany // We are done. Remove the old unused alloca instructions. 18924c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (auto AI : AllocaVec) AI->eraseFromParent(); 1893800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany} 1894f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov 189559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonovvoid FunctionStackPoisoner::poisonAlloca(Value *V, uint64_t Size, 18964c71064129d1e5def34d74ee47c4f3beaa0a66dfJakub Staszak IRBuilder<> &IRB, bool DoPoison) { 1897f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov // For now just insert the call to ASan runtime. 1898f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov Value *AddrArg = IRB.CreatePointerCast(V, IntptrTy); 1899f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov Value *SizeArg = ConstantInt::get(IntptrTy, Size); 19006948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall( 19014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc, 19026948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {AddrArg, SizeArg}); 1903f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov} 190459cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 190559cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// Handling llvm.lifetime intrinsics for a given %alloca: 190659cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// (1) collect all llvm.lifetime.xxx(%size, %value) describing the alloca. 190759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// (2) if %size is constant, poison memory for llvm.lifetime.end (to detect 190859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// invalid accesses) and unpoison it for llvm.lifetime.start (the memory 190959cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// could be poisoned by previous llvm.lifetime.end instruction, as the 191059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// variable may go in and out of scope several times, e.g. in loops). 191159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// (3) if we poisoned at least one %alloca in a function, 191259cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov// unpoison the whole stack frame at function exit. 191359cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov 19141c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey SamsonovAllocaInst *FunctionStackPoisoner::findAllocaForValue(Value *V) { 19151c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) 19161c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // We're intested only in allocas we can handle. 19174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return ASan.isInterestingAlloca(*AI) ? AI : nullptr; 19181c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // See if we've already calculated (or started to calculate) alloca for a 19191c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // given value. 19201c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov AllocaForValueMapTy::iterator I = AllocaForValue.find(V); 19214c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (I != AllocaForValue.end()) return I->second; 19221c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Store 0 while we're calculating alloca for value V to avoid 19231c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // infinite recursion if the value references itself. 1924dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines AllocaForValue[V] = nullptr; 1925dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines AllocaInst *Res = nullptr; 19261c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov if (CastInst *CI = dyn_cast<CastInst>(V)) 19271c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov Res = findAllocaForValue(CI->getOperand(0)); 19281c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov else if (PHINode *PN = dyn_cast<PHINode>(V)) { 19296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar for (Value *IncValue : PN->incoming_values()) { 19301c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // Allow self-referencing phi-nodes. 19311c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov if (IncValue == PN) continue; 19321c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov AllocaInst *IncValueAI = findAllocaForValue(IncValue); 19331c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov // AI for incoming values should exist and should all be equal. 1934dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (IncValueAI == nullptr || (Res != nullptr && IncValueAI != Res)) 1935dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 19361c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonov Res = IncValueAI; 193759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov } 193859cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov } 19394c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Res) AllocaForValue[V] = Res; 194059cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov return Res; 194159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov} 1942ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 19436948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarvoid FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) { 1944ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines IRBuilder<> IRB(AI); 1945ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1946ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const unsigned Align = std::max(kAllocaRzSize, AI->getAlignment()); 1947ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const uint64_t AllocaRedzoneMask = kAllocaRzSize - 1; 1948ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1949ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *Zero = Constant::getNullValue(IntptrTy); 1950ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *AllocaRzSize = ConstantInt::get(IntptrTy, kAllocaRzSize); 1951ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *AllocaRzMask = ConstantInt::get(IntptrTy, AllocaRedzoneMask); 1952ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1953ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Since we need to extend alloca with additional memory to locate 1954ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // redzones, and OldSize is number of allocated blocks with 1955ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // ElementSize size, get allocated memory size in bytes by 1956ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // OldSize * ElementSize. 19576948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar const unsigned ElementSize = 19584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar F.getParent()->getDataLayout().getTypeAllocSize(AI->getAllocatedType()); 19596948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Value *OldSize = 19606948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateMul(IRB.CreateIntCast(AI->getArraySize(), IntptrTy, false), 19616948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ConstantInt::get(IntptrTy, ElementSize)); 1962ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1963ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // PartialSize = OldSize % 32 1964ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *PartialSize = IRB.CreateAnd(OldSize, AllocaRzMask); 1965ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1966ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Misalign = kAllocaRzSize - PartialSize; 1967ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *Misalign = IRB.CreateSub(AllocaRzSize, PartialSize); 1968ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1969ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // PartialPadding = Misalign != kAllocaRzSize ? Misalign : 0; 1970ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *Cond = IRB.CreateICmpNE(Misalign, AllocaRzSize); 1971ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *PartialPadding = IRB.CreateSelect(Cond, Misalign, Zero); 1972ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1973ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // AdditionalChunkSize = Align + PartialPadding + kAllocaRzSize 1974ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Align is added to locate left redzone, PartialPadding for possible 1975ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // partial redzone and kAllocaRzSize for right redzone respectively. 1976ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *AdditionalChunkSize = IRB.CreateAdd( 1977ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ConstantInt::get(IntptrTy, Align + kAllocaRzSize), PartialPadding); 1978ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1979ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *NewSize = IRB.CreateAdd(OldSize, AdditionalChunkSize); 1980ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1981ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Insert new alloca with new NewSize and Align params. 1982ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AllocaInst *NewAlloca = IRB.CreateAlloca(IRB.getInt8Ty(), NewSize); 1983ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines NewAlloca->setAlignment(Align); 1984ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 1985ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // NewAddress = Address + Align 1986ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *NewAddress = IRB.CreateAdd(IRB.CreatePtrToInt(NewAlloca, IntptrTy), 1987ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ConstantInt::get(IntptrTy, Align)); 1988ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 19896948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Insert __asan_alloca_poison call for new created alloca. 19906948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateCall(AsanAllocaPoisonFunc, {NewAddress, OldSize}); 1991ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 19926948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Store the last alloca's address to DynamicAllocaLayout. We'll need this 19936948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // for unpoisoning stuff. 19946948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar IRB.CreateStore(IRB.CreatePtrToInt(NewAlloca, IntptrTy), DynamicAllocaLayout); 1995ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 19966948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Value *NewAddressPtr = IRB.CreateIntToPtr(NewAddress, AI->getType()); 1997ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 19986948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // Replace all uses of AddessReturnedByAlloca with NewAddressPtr. 1999ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AI->replaceAllUsesWith(NewAddressPtr); 2000ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 20016948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar // We are done. Erase old alloca from parent. 2002ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AI->eraseFromParent(); 2003ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 20044c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 20054c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// isSafeAccess returns true if Addr is always inbounds with respect to its 20064c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// base object. For example, it is a field access or an array access with 20074c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// constant inbounds index. 20084c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarbool AddressSanitizer::isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis, 20094c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Value *Addr, uint64_t TypeSize) const { 20104c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar SizeOffsetType SizeOffset = ObjSizeVis.compute(Addr); 20114c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!ObjSizeVis.bothKnown(SizeOffset)) return false; 20124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar uint64_t Size = SizeOffset.first.getZExtValue(); 20134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar int64_t Offset = SizeOffset.second.getSExtValue(); 20144c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // Three checks are required to ensure safety: 20154c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // . Offset >= 0 (since the offset is given from the base ptr) 20164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // . Size >= Offset (unsigned) 20174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // . Size - Offset >= NeededSize (unsigned) 20184c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return Offset >= 0 && Size >= uint64_t(Offset) && 20194c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Size - uint64_t(Offset) >= TypeSize / 8; 20204c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} 2021