llvm/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

//===- AddressSanitizer.cpp - memory error detector -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address basic correctness
// checker.
// Details of the algorithm:
//  https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm
//
// FIXME: This sanitizer does not yet handle scalable vectors
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/StackSafetyAnalysis.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
#include "llvm/Transforms/Utils/ASanStackFrameLayout.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Instrumentation.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>
#include <tuple>

usingnamespacellvm;

#define DEBUG_TYPE

static const uint64_t kDefaultShadowScale =;
static const uint64_t kDefaultShadowOffset32 =;
static const uint64_t kDefaultShadowOffset64 =;
static const uint64_t kDynamicShadowSentinel =;
static const uint64_t kSmallX86_64ShadowOffsetBase =;  // < 2G.
static const uint64_t kSmallX86_64ShadowOffsetAlignMask =;
static const uint64_t kLinuxKasan_ShadowOffset64 =;
static const uint64_t kPPC64_ShadowOffset64 =;
static const uint64_t kSystemZ_ShadowOffset64 =;
static const uint64_t kMIPS_ShadowOffsetN32 =;
static const uint64_t kMIPS32_ShadowOffset32 =;
static const uint64_t kMIPS64_ShadowOffset64 =;
static const uint64_t kAArch64_ShadowOffset64 =;
static const uint64_t kLoongArch64_ShadowOffset64 =;
static const uint64_t kRISCV64_ShadowOffset64 =;
static const uint64_t kFreeBSD_ShadowOffset32 =;
static const uint64_t kFreeBSD_ShadowOffset64 =;
static const uint64_t kFreeBSDAArch64_ShadowOffset64 =;
static const uint64_t kFreeBSDKasan_ShadowOffset64 =;
static const uint64_t kNetBSD_ShadowOffset32 =;
static const uint64_t kNetBSD_ShadowOffset64 =;
static const uint64_t kNetBSDKasan_ShadowOffset64 =;
static const uint64_t kPS_ShadowOffset64 =;
static const uint64_t kWindowsShadowOffset32 =;
static const uint64_t kEmscriptenShadowOffset =;

// The shadow memory space is dynamically allocated.
static const uint64_t kWindowsShadowOffset64 =;

static const size_t kMinStackMallocSize =;   // 64B
static const size_t kMaxStackMallocSize =;  // 64K
static const uintptr_t kCurrentStackFrameMagic =;
static const uintptr_t kRetiredStackFrameMagic =;

const char kAsanModuleCtorName[] =;
const char kAsanModuleDtorName[] =;
static const uint64_t kAsanCtorAndDtorPriority =;
// On Emscripten, the system needs more than one priorities for constructors.
static const uint64_t kAsanEmscriptenCtorAndDtorPriority =;
const char kAsanReportErrorTemplate[] =;
const char kAsanRegisterGlobalsName[] =;
const char kAsanUnregisterGlobalsName[] =;
const char kAsanRegisterImageGlobalsName[] =;
const char kAsanUnregisterImageGlobalsName[] =;
const char kAsanRegisterElfGlobalsName[] =;
const char kAsanUnregisterElfGlobalsName[] =;
const char kAsanPoisonGlobalsName[] =;
const char kAsanUnpoisonGlobalsName[] =;
const char kAsanInitName[] =;
const char kAsanVersionCheckNamePrefix[] =;
const char kAsanPtrCmp[] =;
const char kAsanPtrSub[] =;
const char kAsanHandleNoReturnName[] =;
static const int kMaxAsanStackMallocSizeClass =;
const char kAsanStackMallocNameTemplate[] =;
const char kAsanStackMallocAlwaysNameTemplate[] =;
const char kAsanStackFreeNameTemplate[] =;
const char kAsanGenPrefix[] =;
const char kODRGenPrefix[] =;
const char kSanCovGenPrefix[] =;
const char kAsanSetShadowPrefix[] =;
const char kAsanPoisonStackMemoryName[] =;
const char kAsanUnpoisonStackMemoryName[] =;

// ASan version script has __asan_* wildcard. Triple underscore prevents a
// linker (gold) warning about attempting to export a local symbol.
const char kAsanGlobalsRegisteredFlagName[] =;

const char kAsanOptionDetectUseAfterReturn[] =;

const char kAsanShadowMemoryDynamicAddress[] =;

const char kAsanAllocaPoison[] =;
const char kAsanAllocasUnpoison[] =;

const char kAMDGPUAddressSharedName[] =;
const char kAMDGPUAddressPrivateName[] =;
const char kAMDGPUBallotName[] =;
const char kAMDGPUUnreachableName[] =;

// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
static const size_t kNumberOfAccessSizes =;

static const uint64_t kAllocaRzSize =;

// ASanAccessInfo implementation constants.
constexpr size_t kCompileKernelShift =;
constexpr size_t kCompileKernelMask =;
constexpr size_t kAccessSizeIndexShift =;
constexpr size_t kAccessSizeIndexMask =;
constexpr size_t kIsWriteShift =;
constexpr size_t kIsWriteMask =;

// Command-line flags.

static cl::opt<bool> ClEnableKasan(
    "asan-kernel", cl::desc("Enable KernelAddressSanitizer instrumentation"),
    cl::Hidden, cl::init(false));

static cl::opt<bool> ClRecover(
    "asan-recover",
    cl::desc("Enable recovery mode (continue-after-error)."),
    cl::Hidden, cl::init(false));

static cl::opt<bool> ClInsertVersionCheck(
    "asan-guard-against-version-mismatch",
    cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden,
    cl::init(true));

// This flag may need to be replaced with -f[no-]asan-reads.
static cl::opt<bool> ClInstrumentReads("asan-instrument-reads",
                                       cl::desc("instrument read instructions"),
                                       cl::Hidden, cl::init(true));

static cl::opt<bool> ClInstrumentWrites(
    "asan-instrument-writes", cl::desc("instrument write instructions"),
    cl::Hidden, cl::init(true));

static cl::opt<bool>
    ClUseStackSafety("asan-use-stack-safety", cl::Hidden, cl::init(true),
                     cl::Hidden, cl::desc("Use Stack Safety analysis results"),
                     cl::Optional);

static cl::opt<bool> ClInstrumentAtomics(
    "asan-instrument-atomics",
    cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
    cl::init(true));

static cl::opt<bool>
    ClInstrumentByval("asan-instrument-byval",
                      cl::desc("instrument byval call arguments"), cl::Hidden,
                      cl::init(true));

static cl::opt<bool> ClAlwaysSlowPath(
    "asan-always-slow-path",
    cl::desc("use instrumentation with slow path for all accesses"), cl::Hidden,
    cl::init(false));

static cl::opt<bool> ClForceDynamicShadow(
    "asan-force-dynamic-shadow",
    cl::desc("Load shadow address into a local variable for each function"),
    cl::Hidden, cl::init(false));

static cl::opt<bool>
    ClWithIfunc("asan-with-ifunc",
                cl::desc("Access dynamic shadow through an ifunc global on "
                         "platforms that support this"),
                cl::Hidden, cl::init(true));

static cl::opt<bool> ClWithIfuncSuppressRemat(
    "asan-with-ifunc-suppress-remat",
    cl::desc("Suppress rematerialization of dynamic shadow address by passing "
             "it through inline asm in prologue."),
    cl::Hidden, cl::init(true));

// This flag limits the number of instructions to be instrumented
// in any given BB. Normally, this should be set to unlimited (INT_MAX),
// but due to http://llvm.org/bugs/show_bug.cgi?id=12652 we temporary
// set it to 10000.
static cl::opt<int> ClMaxInsnsToInstrumentPerBB(
    "asan-max-ins-per-bb", cl::init(10000),
    cl::desc("maximal number of instructions to instrument in any given BB"),
    cl::Hidden);

// This flag may need to be replaced with -f[no]asan-stack.
static cl::opt<bool> ClStack("asan-stack", cl::desc("Handle stack memory"),
                             cl::Hidden, cl::init(true));
static cl::opt<uint32_t> ClMaxInlinePoisoningSize(
    "asan-max-inline-poisoning-size",
    cl::desc(
        "Inline shadow poisoning for blocks up to the given size in bytes."),
    cl::Hidden, cl::init(64));

static cl::opt<AsanDetectStackUseAfterReturnMode> ClUseAfterReturn(
    "asan-use-after-return",
    cl::desc("Sets the mode of detection for stack-use-after-return."),
    cl::values(
        clEnumValN(AsanDetectStackUseAfterReturnMode::Never, "never",
                   "Never detect stack use after return."),
        clEnumValN(
            AsanDetectStackUseAfterReturnMode::Runtime, "runtime",
            "Detect stack use after return if "
            "binary flag 'ASAN_OPTIONS=detect_stack_use_after_return' is set."),
        clEnumValN(AsanDetectStackUseAfterReturnMode::Always, "always",
                   "Always detect stack use after return.")),
    cl::Hidden, cl::init(AsanDetectStackUseAfterReturnMode::Runtime));

static cl::opt<bool> ClRedzoneByvalArgs("asan-redzone-byval-args",
                                        cl::desc("Create redzones for byval "
                                                 "arguments (extra copy "
                                                 "required)"), cl::Hidden,
                                        cl::init(true));

static cl::opt<bool> ClUseAfterScope("asan-use-after-scope",
                                     cl::desc("Check stack-use-after-scope"),
                                     cl::Hidden, cl::init(false));

// This flag may need to be replaced with -f[no]asan-globals.
static cl::opt<bool> ClGlobals("asan-globals",
                               cl::desc("Handle global objects"), cl::Hidden,
                               cl::init(true));

static cl::opt<bool> ClInitializers("asan-initialization-order",
                                    cl::desc("Handle C++ initializer order"),
                                    cl::Hidden, cl::init(true));

static cl::opt<bool> ClInvalidPointerPairs(
    "asan-detect-invalid-pointer-pair",
    cl::desc("Instrument <, <=, >, >=, - with pointer operands"), cl::Hidden,
    cl::init(false));

static cl::opt<bool> ClInvalidPointerCmp(
    "asan-detect-invalid-pointer-cmp",
    cl::desc("Instrument <, <=, >, >= with pointer operands"), cl::Hidden,
    cl::init(false));

static cl::opt<bool> ClInvalidPointerSub(
    "asan-detect-invalid-pointer-sub",
    cl::desc("Instrument - operations with pointer operands"), cl::Hidden,
    cl::init(false));

static cl::opt<unsigned> ClRealignStack(
    "asan-realign-stack",
    cl::desc("Realign stack to the value of this flag (power of two)"),
    cl::Hidden, cl::init(32));

static cl::opt<int> ClInstrumentationWithCallsThreshold(
    "asan-instrumentation-with-call-threshold",
    cl::desc("If the function being instrumented contains more than "
             "this number of memory accesses, use callbacks instead of "
             "inline checks (-1 means never use callbacks)."),
    cl::Hidden, cl::init(7000));

static cl::opt<std::string> ClMemoryAccessCallbackPrefix(
    "asan-memory-access-callback-prefix",
    cl::desc("Prefix for memory access callbacks"), cl::Hidden,
    cl::init("__asan_"));

static cl::opt<bool> ClKasanMemIntrinCallbackPrefix(
    "asan-kernel-mem-intrinsic-prefix",
    cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden,
    cl::init(false));

static cl::opt<bool>
    ClInstrumentDynamicAllocas("asan-instrument-dynamic-allocas",
                               cl::desc("instrument dynamic allocas"),
                               cl::Hidden, cl::init(true));

static cl::opt<bool> ClSkipPromotableAllocas(
    "asan-skip-promotable-allocas",
    cl::desc("Do not instrument promotable allocas"), cl::Hidden,
    cl::init(true));

static cl::opt<AsanCtorKind> ClConstructorKind(
    "asan-constructor-kind",
    cl::desc("Sets the ASan constructor kind"),
    cl::values(clEnumValN(AsanCtorKind::None, "none", "No constructors"),
               clEnumValN(AsanCtorKind::Global, "global",
                          "Use global constructors")),
    cl::init(AsanCtorKind::Global), cl::Hidden);
// These flags allow to change the shadow mapping.
// The shadow mapping looks like
//    Shadow = (Mem >> scale) + offset

static cl::opt<int> ClMappingScale("asan-mapping-scale",
                                   cl::desc("scale of asan shadow mapping"),
                                   cl::Hidden, cl::init(0));

static cl::opt<uint64_t>
    ClMappingOffset("asan-mapping-offset",
                    cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"),
                    cl::Hidden, cl::init(0));

// Optimization flags. Not user visible, used mostly for testing
// and benchmarking the tool.

static cl::opt<bool> ClOpt("asan-opt", cl::desc("Optimize instrumentation"),
                           cl::Hidden, cl::init(true));

static cl::opt<bool> ClOptimizeCallbacks("asan-optimize-callbacks",
                                         cl::desc("Optimize callbacks"),
                                         cl::Hidden, cl::init(false));

static cl::opt<bool> ClOptSameTemp(
    "asan-opt-same-temp", cl::desc("Instrument the same temp just once"),
    cl::Hidden, cl::init(true));

static cl::opt<bool> ClOptGlobals("asan-opt-globals",
                                  cl::desc("Don't instrument scalar globals"),
                                  cl::Hidden, cl::init(true));

static cl::opt<bool> ClOptStack(
    "asan-opt-stack", cl::desc("Don't instrument scalar stack variables"),
    cl::Hidden, cl::init(false));

static cl::opt<bool> ClDynamicAllocaStack(
    "asan-stack-dynamic-alloca",
    cl::desc("Use dynamic alloca to represent stack variables"), cl::Hidden,
    cl::init(true));

static cl::opt<uint32_t> ClForceExperiment(
    "asan-force-experiment",
    cl::desc("Force optimization experiment (for testing)"), cl::Hidden,
    cl::init(0));

static cl::opt<bool>
    ClUsePrivateAlias("asan-use-private-alias",
                      cl::desc("Use private aliases for global variables"),
                      cl::Hidden, cl::init(true));

static cl::opt<bool>
    ClUseOdrIndicator("asan-use-odr-indicator",
                      cl::desc("Use odr indicators to improve ODR reporting"),
                      cl::Hidden, cl::init(true));

static cl::opt<bool>
    ClUseGlobalsGC("asan-globals-live-support",
                   cl::desc("Use linker features to support dead "
                            "code stripping of globals"),
                   cl::Hidden, cl::init(true));

// This is on by default even though there is a bug in gold:
// https://sourceware.org/bugzilla/show_bug.cgi?id=19002
static cl::opt<bool>
    ClWithComdat("asan-with-comdat",
                 cl::desc("Place ASan constructors in comdat sections"),
                 cl::Hidden, cl::init(true));

static cl::opt<AsanDtorKind> ClOverrideDestructorKind(
    "asan-destructor-kind",
    cl::desc("Sets the ASan destructor kind. The default is to use the value "
             "provided to the pass constructor"),
    cl::values(clEnumValN(AsanDtorKind::None, "none", "No destructors"),
               clEnumValN(AsanDtorKind::Global, "global",
                          "Use global destructors")),
    cl::init(AsanDtorKind::Invalid), cl::Hidden);

// Debug flags.

static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
                            cl::init(0));

static cl::opt<int> ClDebugStack("asan-debug-stack", cl::desc("debug stack"),
                                 cl::Hidden, cl::init(0));

static cl::opt<std::string> ClDebugFunc("asan-debug-func", cl::Hidden,
                                        cl::desc("Debug func"));

static cl::opt<int> ClDebugMin("asan-debug-min", cl::desc("Debug min inst"),
                               cl::Hidden, cl::init(-1));

static cl::opt<int> ClDebugMax("asan-debug-max", cl::desc("Debug max inst"),
                               cl::Hidden, cl::init(-1));

STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
STATISTIC(NumOptimizedAccessesToGlobalVar,
          "Number of optimized accesses to global vars");
STATISTIC(NumOptimizedAccessesToStackVar,
          "Number of optimized accesses to stack vars");

namespace {

/// This struct defines the shadow mapping using the rule:
///   shadow = (mem >> Scale) ADD-or-OR Offset.
/// If InGlobal is true, then
///   extern char __asan_shadow[];
///   shadow = (mem >> Scale) + &__asan_shadow
struct ShadowMapping {};

} // end anonymous namespace

static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize,
                                      bool IsKasan) {}

namespace llvm {
void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize,
                               bool IsKasan, uint64_t *ShadowBase,
                               int *MappingScale, bool *OrShadowOffset) {}

ASanAccessInfo::ASanAccessInfo(int32_t Packed)
    :{}

ASanAccessInfo::ASanAccessInfo(bool IsWrite, bool CompileKernel,
                               uint8_t AccessSizeIndex)
    :{}

} // namespace llvm

static uint64_t getRedzoneSizeForScale(int MappingScale) {}

static uint64_t GetCtorAndDtorPriority(Triple &TargetTriple) {}

static Twine genName(StringRef suffix) {}

namespace {
/// Helper RAII class to post-process inserted asan runtime calls during a
/// pass on a single Function. Upon end of scope, detects and applies the
/// required funclet OpBundle.
class RuntimeCallInserter {};

/// AddressSanitizer: instrument the code in module to find memory bugs.
struct AddressSanitizer {};

class ModuleAddressSanitizer {};

// Stack poisoning does not play well with exception handling.
// When an exception is thrown, we essentially bypass the code
// that unpoisones the stack. This is why the run-time library has
// to intercept __cxa_throw (as well as longjmp, etc) and unpoison the entire
// stack in the interceptor. This however does not work inside the
// actual function which catches the exception. Most likely because the
// compiler hoists the load of the shadow value somewhere too high.
// This causes asan to report a non-existing bug on 453.povray.
// It sounds like an LLVM bug.
struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {};

} // end anonymous namespace

void AddressSanitizerPass::printPipeline(
    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {}

AddressSanitizerPass::AddressSanitizerPass(
    const AddressSanitizerOptions &Options, bool UseGlobalGC,
    bool UseOdrIndicator, AsanDtorKind DestructorKind,
    AsanCtorKind ConstructorKind)
    :{}

PreservedAnalyses AddressSanitizerPass::run(Module &M,
                                            ModuleAnalysisManager &MAM) {}

static size_t TypeStoreSizeToSizeIndex(uint32_t TypeSize) {}

/// Check if \p G has been created by a trusted compiler pass.
static bool GlobalWasGeneratedByCompiler(GlobalVariable *G) {}

static bool isUnsupportedAMDGPUAddrspace(Value *Addr) {}

Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {}

// Instrument memset/memmove/memcpy
void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI,
                                              RuntimeCallInserter &RTCI) {}

/// Check if we want (and can) handle this alloca.
bool AddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {}

bool AddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) {}

void AddressSanitizer::getInterestingMemoryOperands(
    Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting) {}

static bool isPointerOperand(Value *V) {}

// This is a rough heuristic; it may cause both false positives and
// false negatives. The proper implementation requires cooperation with
// the frontend.
static bool isInterestingPointerComparison(Instruction *I) {}

// This is a rough heuristic; it may cause both false positives and
// false negatives. The proper implementation requires cooperation with
// the frontend.
static bool isInterestingPointerSubtraction(Instruction *I) {}

bool AddressSanitizer::GlobalIsLinkerInitialized(GlobalVariable *G) {}

void AddressSanitizer::instrumentPointerComparisonOrSubtraction(
    Instruction *I, RuntimeCallInserter &RTCI) {}

static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
                                Instruction *InsertBefore, Value *Addr,
                                MaybeAlign Alignment, unsigned Granularity,
                                TypeSize TypeStoreSize, bool IsWrite,
                                Value *SizeArgument, bool UseCalls,
                                uint32_t Exp, RuntimeCallInserter &RTCI) {}

void AddressSanitizer::instrumentMaskedLoadOrStore(
    AddressSanitizer *Pass, const DataLayout &DL, Type *IntptrTy, Value *Mask,
    Value *EVL, Value *Stride, Instruction *I, Value *Addr,
    MaybeAlign Alignment, unsigned Granularity, Type *OpType, bool IsWrite,
    Value *SizeArgument, bool UseCalls, uint32_t Exp,
    RuntimeCallInserter &RTCI) {}

void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
                                     InterestingMemoryOperand &O, bool UseCalls,
                                     const DataLayout &DL,
                                     RuntimeCallInserter &RTCI) {}

Instruction *AddressSanitizer::generateCrashCode(Instruction *InsertBefore,
                                                 Value *Addr, bool IsWrite,
                                                 size_t AccessSizeIndex,
                                                 Value *SizeArgument,
                                                 uint32_t Exp,
                                                 RuntimeCallInserter &RTCI) {}

Value *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong,
                                           Value *ShadowValue,
                                           uint32_t TypeStoreSize) {}

Instruction *AddressSanitizer::instrumentAMDGPUAddress(
    Instruction *OrigIns, Instruction *InsertBefore, Value *Addr,
    uint32_t TypeStoreSize, bool IsWrite, Value *SizeArgument) {}

Instruction *AddressSanitizer::genAMDGPUReportBlock(IRBuilder<> &IRB,
                                                    Value *Cond, bool Recover) {}

void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
                                         Instruction *InsertBefore, Value *Addr,
                                         MaybeAlign Alignment,
                                         uint32_t TypeStoreSize, bool IsWrite,
                                         Value *SizeArgument, bool UseCalls,
                                         uint32_t Exp,
                                         RuntimeCallInserter &RTCI) {}

// Instrument unusual size or unusual alignment.
// We can not do it with a single check, so we do 1-byte check for the first
// and the last bytes. We call __asan_report_*_n(addr, real_size) to be able
// to report the actual access size.
void AddressSanitizer::instrumentUnusualSizeOrAlignment(
    Instruction *I, Instruction *InsertBefore, Value *Addr,
    TypeSize TypeStoreSize, bool IsWrite, Value *SizeArgument, bool UseCalls,
    uint32_t Exp, RuntimeCallInserter &RTCI) {}

void ModuleAddressSanitizer::poisonOneInitializer(Function &GlobalInit) {}

void ModuleAddressSanitizer::createInitializerPoisonCalls() {}

const GlobalVariable *
ModuleAddressSanitizer::getExcludedAliasedGlobal(const GlobalAlias &GA) const {}

bool ModuleAddressSanitizer::shouldInstrumentGlobal(GlobalVariable *G) const {}

// On Mach-O platforms, we emit global metadata in a separate section of the
// binary in order to allow the linker to properly dead strip. This is only
// supported on recent versions of ld64.
bool ModuleAddressSanitizer::ShouldUseMachOGlobalsSection() const {}

StringRef ModuleAddressSanitizer::getGlobalMetadataSection() const {}

void ModuleAddressSanitizer::initializeCallbacks() {}

// Put the metadata and the instrumented global in the same group. This ensures
// that the metadata is discarded if the instrumented global is discarded.
void ModuleAddressSanitizer::SetComdatForGlobalMetadata(
    GlobalVariable *G, GlobalVariable *Metadata, StringRef InternalSuffix) {}

// Create a separate metadata global and put it in the appropriate ASan
// global registration section.
GlobalVariable *
ModuleAddressSanitizer::CreateMetadataGlobal(Constant *Initializer,
                                             StringRef OriginalName) {}

Instruction *ModuleAddressSanitizer::CreateAsanModuleDtor() {}

void ModuleAddressSanitizer::InstrumentGlobalsCOFF(
    IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
    ArrayRef<Constant *> MetadataInitializers) {}

void ModuleAddressSanitizer::instrumentGlobalsELF(
    IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
    ArrayRef<Constant *> MetadataInitializers,
    const std::string &UniqueModuleId) {}

void ModuleAddressSanitizer::InstrumentGlobalsMachO(
    IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
    ArrayRef<Constant *> MetadataInitializers) {}

void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
    IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
    ArrayRef<Constant *> MetadataInitializers) {}

// This function replaces all global variables with new variables that have
// trailing redzones. It also creates a function that poisons
// redzones and inserts this function into llvm.global_ctors.
// Sets *CtorComdat to true if the global registration code emitted into the
// asan constructor is comdat-compatible.
void ModuleAddressSanitizer::instrumentGlobals(IRBuilder<> &IRB,
                                               bool *CtorComdat) {}

uint64_t
ModuleAddressSanitizer::getRedzoneSizeForGlobal(uint64_t SizeInBytes) const {}

int ModuleAddressSanitizer::GetAsanVersion() const {}

GlobalVariable *ModuleAddressSanitizer::getOrCreateModuleName() {}

bool ModuleAddressSanitizer::instrumentModule() {}

void AddressSanitizer::initializeCallbacks(const TargetLibraryInfo *TLI) {}

bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {}

bool AddressSanitizer::maybeInsertDynamicShadowAtFunctionEntry(Function &F) {}

void AddressSanitizer::markEscapedLocalAllocas(Function &F) {}

bool AddressSanitizer::suppressInstrumentationSiteForDebug(int &Instrumented) {}

bool AddressSanitizer::instrumentFunction(Function &F,
                                          const TargetLibraryInfo *TLI) {}

// Workaround for bug 11395: we don't want to instrument stack in functions
// with large assembly blobs (32-bit only), otherwise reg alloc may crash.
// FIXME: remove once the bug 11395 is fixed.
bool AddressSanitizer::LooksLikeCodeInBug11395(Instruction *I) {}

void FunctionStackPoisoner::initializeCallbacks(Module &M) {}

void FunctionStackPoisoner::copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
                                               ArrayRef<uint8_t> ShadowBytes,
                                               size_t Begin, size_t End,
                                               IRBuilder<> &IRB,
                                               Value *ShadowBase) {}

void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
                                         ArrayRef<uint8_t> ShadowBytes,
                                         IRBuilder<> &IRB, Value *ShadowBase) {}

void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
                                         ArrayRef<uint8_t> ShadowBytes,
                                         size_t Begin, size_t End,
                                         IRBuilder<> &IRB, Value *ShadowBase) {}

// Fake stack allocator (asan_fake_stack.h) has 11 size classes
// for every power of 2 from kMinStackMallocSize to kMaxAsanStackMallocSizeClass
static int StackMallocSizeClass(uint64_t LocalStackSize) {}

void FunctionStackPoisoner::copyArgsPassedByValToAllocas() {}

PHINode *FunctionStackPoisoner::createPHI(IRBuilder<> &IRB, Value *Cond,
                                          Value *ValueIfTrue,
                                          Instruction *ThenTerm,
                                          Value *ValueIfFalse) {}

Value *FunctionStackPoisoner::createAllocaForLayout(
    IRBuilder<> &IRB, const ASanStackFrameLayout &L, bool Dynamic) {}

void FunctionStackPoisoner::createDynamicAllocasInitStorage() {}

void FunctionStackPoisoner::processDynamicAllocas() {}

/// Collect instructions in the entry block after \p InsBefore which initialize
/// permanent storage for a function argument. These instructions must remain in
/// the entry block so that uninitialized values do not appear in backtraces. An
/// added benefit is that this conserves spill slots. This does not move stores
/// before instrumented / "interesting" allocas.
static void findStoresToUninstrumentedArgAllocas(
    AddressSanitizer &ASan, Instruction &InsBefore,
    SmallVectorImpl<Instruction *> &InitInsts) {}

void FunctionStackPoisoner::processStaticAllocas() {}

void FunctionStackPoisoner::poisonAlloca(Value *V, uint64_t Size,
                                         IRBuilder<> &IRB, bool DoPoison) {}

// Handling llvm.lifetime intrinsics for a given %alloca:
// (1) collect all llvm.lifetime.xxx(%size, %value) describing the alloca.
// (2) if %size is constant, poison memory for llvm.lifetime.end (to detect
//     invalid accesses) and unpoison it for llvm.lifetime.start (the memory
//     could be poisoned by previous llvm.lifetime.end instruction, as the
//     variable may go in and out of scope several times, e.g. in loops).
// (3) if we poisoned at least one %alloca in a function,
//     unpoison the whole stack frame at function exit.
void FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) {}

// isSafeAccess returns true if Addr is always inbounds with respect to its
// base object. For example, it is a field access or an array access with
// constant inbounds index.
bool AddressSanitizer::isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis,
                                    Value *Addr, TypeSize TypeStoreSize) const {}