Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
35266 views
//===- MemorySanitizer.cpp - detector of uninitialized reads --------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8/// \file9/// This file is a part of MemorySanitizer, a detector of uninitialized10/// reads.11///12/// The algorithm of the tool is similar to Memcheck13/// (https://static.usenix.org/event/usenix05/tech/general/full_papers/seward/seward_html/usenix2005.html)14/// We associate a few shadow bits with every byte of the application memory,15/// poison the shadow of the malloc-ed or alloca-ed memory, load the shadow,16/// bits on every memory read, propagate the shadow bits through some of the17/// arithmetic instruction (including MOV), store the shadow bits on every memory18/// write, report a bug on some other instructions (e.g. JMP) if the19/// associated shadow is poisoned.20///21/// But there are differences too. The first and the major one:22/// compiler instrumentation instead of binary instrumentation. This23/// gives us much better register allocation, possible compiler24/// optimizations and a fast start-up. But this brings the major issue25/// as well: msan needs to see all program events, including system26/// calls and reads/writes in system libraries, so we either need to27/// compile *everything* with msan or use a binary translation28/// component (e.g. DynamoRIO) to instrument pre-built libraries.29/// Another difference from Memcheck is that we use 8 shadow bits per30/// byte of application memory and use a direct shadow mapping. This31/// greatly simplifies the instrumentation code and avoids races on32/// shadow updates (Memcheck is single-threaded so races are not a33/// concern there. Memcheck uses 2 shadow bits per byte with a slow34/// path storage that uses 8 bits per byte).35///36/// The default value of shadow is 0, which means "clean" (not poisoned).37///38/// Every module initializer should call __msan_init to ensure that the39/// shadow memory is ready. On error, __msan_warning is called. Since40/// parameters and return values may be passed via registers, we have a41/// specialized thread-local shadow for return values42/// (__msan_retval_tls) and parameters (__msan_param_tls).43///44/// Origin tracking.45///46/// MemorySanitizer can track origins (allocation points) of all uninitialized47/// values. This behavior is controlled with a flag (msan-track-origins) and is48/// disabled by default.49///50/// Origins are 4-byte values created and interpreted by the runtime library.51/// They are stored in a second shadow mapping, one 4-byte value for 4 bytes52/// of application memory. Propagation of origins is basically a bunch of53/// "select" instructions that pick the origin of a dirty argument, if an54/// instruction has one.55///56/// Every 4 aligned, consecutive bytes of application memory have one origin57/// value associated with them. If these bytes contain uninitialized data58/// coming from 2 different allocations, the last store wins. Because of this,59/// MemorySanitizer reports can show unrelated origins, but this is unlikely in60/// practice.61///62/// Origins are meaningless for fully initialized values, so MemorySanitizer63/// avoids storing origin to memory when a fully initialized value is stored.64/// This way it avoids needless overwriting origin of the 4-byte region on65/// a short (i.e. 1 byte) clean store, and it is also good for performance.66///67/// Atomic handling.68///69/// Ideally, every atomic store of application value should update the70/// corresponding shadow location in an atomic way. Unfortunately, atomic store71/// of two disjoint locations can not be done without severe slowdown.72///73/// Therefore, we implement an approximation that may err on the safe side.74/// In this implementation, every atomically accessed location in the program75/// may only change from (partially) uninitialized to fully initialized, but76/// not the other way around. We load the shadow _after_ the application load,77/// and we store the shadow _before_ the app store. Also, we always store clean78/// shadow (if the application store is atomic). This way, if the store-load79/// pair constitutes a happens-before arc, shadow store and load are correctly80/// ordered such that the load will get either the value that was stored, or81/// some later value (which is always clean).82///83/// This does not work very well with Compare-And-Swap (CAS) and84/// Read-Modify-Write (RMW) operations. To follow the above logic, CAS and RMW85/// must store the new shadow before the app operation, and load the shadow86/// after the app operation. Computers don't work this way. Current87/// implementation ignores the load aspect of CAS/RMW, always returning a clean88/// value. It implements the store part as a simple atomic store by storing a89/// clean shadow.90///91/// Instrumenting inline assembly.92///93/// For inline assembly code LLVM has little idea about which memory locations94/// become initialized depending on the arguments. It can be possible to figure95/// out which arguments are meant to point to inputs and outputs, but the96/// actual semantics can be only visible at runtime. In the Linux kernel it's97/// also possible that the arguments only indicate the offset for a base taken98/// from a segment register, so it's dangerous to treat any asm() arguments as99/// pointers. We take a conservative approach generating calls to100/// __msan_instrument_asm_store(ptr, size)101/// , which defer the memory unpoisoning to the runtime library.102/// The latter can perform more complex address checks to figure out whether103/// it's safe to touch the shadow memory.104/// Like with atomic operations, we call __msan_instrument_asm_store() before105/// the assembly call, so that changes to the shadow memory will be seen by106/// other threads together with main memory initialization.107///108/// KernelMemorySanitizer (KMSAN) implementation.109///110/// The major differences between KMSAN and MSan instrumentation are:111/// - KMSAN always tracks the origins and implies msan-keep-going=true;112/// - KMSAN allocates shadow and origin memory for each page separately, so113/// there are no explicit accesses to shadow and origin in the114/// instrumentation.115/// Shadow and origin values for a particular X-byte memory location116/// (X=1,2,4,8) are accessed through pointers obtained via the117/// __msan_metadata_ptr_for_load_X(ptr)118/// __msan_metadata_ptr_for_store_X(ptr)119/// functions. The corresponding functions check that the X-byte accesses120/// are possible and returns the pointers to shadow and origin memory.121/// Arbitrary sized accesses are handled with:122/// __msan_metadata_ptr_for_load_n(ptr, size)123/// __msan_metadata_ptr_for_store_n(ptr, size);124/// Note that the sanitizer code has to deal with how shadow/origin pairs125/// returned by the these functions are represented in different ABIs. In126/// the X86_64 ABI they are returned in RDX:RAX, in PowerPC64 they are127/// returned in r3 and r4, and in the SystemZ ABI they are written to memory128/// pointed to by a hidden parameter.129/// - TLS variables are stored in a single per-task struct. A call to a130/// function __msan_get_context_state() returning a pointer to that struct131/// is inserted into every instrumented function before the entry block;132/// - __msan_warning() takes a 32-bit origin parameter;133/// - local variables are poisoned with __msan_poison_alloca() upon function134/// entry and unpoisoned with __msan_unpoison_alloca() before leaving the135/// function;136/// - the pass doesn't declare any global variables or add global constructors137/// to the translation unit.138///139/// Also, KMSAN currently ignores uninitialized memory passed into inline asm140/// calls, making sure we're on the safe side wrt. possible false positives.141///142/// KernelMemorySanitizer only supports X86_64, SystemZ and PowerPC64 at the143/// moment.144///145//146// FIXME: This sanitizer does not yet handle scalable vectors147//148//===----------------------------------------------------------------------===//149150#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"151#include "llvm/ADT/APInt.h"152#include "llvm/ADT/ArrayRef.h"153#include "llvm/ADT/DenseMap.h"154#include "llvm/ADT/DepthFirstIterator.h"155#include "llvm/ADT/SetVector.h"156#include "llvm/ADT/SmallPtrSet.h"157#include "llvm/ADT/SmallVector.h"158#include "llvm/ADT/StringExtras.h"159#include "llvm/ADT/StringRef.h"160#include "llvm/Analysis/GlobalsModRef.h"161#include "llvm/Analysis/TargetLibraryInfo.h"162#include "llvm/Analysis/ValueTracking.h"163#include "llvm/IR/Argument.h"164#include "llvm/IR/AttributeMask.h"165#include "llvm/IR/Attributes.h"166#include "llvm/IR/BasicBlock.h"167#include "llvm/IR/CallingConv.h"168#include "llvm/IR/Constant.h"169#include "llvm/IR/Constants.h"170#include "llvm/IR/DataLayout.h"171#include "llvm/IR/DerivedTypes.h"172#include "llvm/IR/Function.h"173#include "llvm/IR/GlobalValue.h"174#include "llvm/IR/GlobalVariable.h"175#include "llvm/IR/IRBuilder.h"176#include "llvm/IR/InlineAsm.h"177#include "llvm/IR/InstVisitor.h"178#include "llvm/IR/InstrTypes.h"179#include "llvm/IR/Instruction.h"180#include "llvm/IR/Instructions.h"181#include "llvm/IR/IntrinsicInst.h"182#include "llvm/IR/Intrinsics.h"183#include "llvm/IR/IntrinsicsAArch64.h"184#include "llvm/IR/IntrinsicsX86.h"185#include "llvm/IR/MDBuilder.h"186#include "llvm/IR/Module.h"187#include "llvm/IR/Type.h"188#include "llvm/IR/Value.h"189#include "llvm/IR/ValueMap.h"190#include "llvm/Support/Alignment.h"191#include "llvm/Support/AtomicOrdering.h"192#include "llvm/Support/Casting.h"193#include "llvm/Support/CommandLine.h"194#include "llvm/Support/Debug.h"195#include "llvm/Support/DebugCounter.h"196#include "llvm/Support/ErrorHandling.h"197#include "llvm/Support/MathExtras.h"198#include "llvm/Support/raw_ostream.h"199#include "llvm/TargetParser/Triple.h"200#include "llvm/Transforms/Utils/BasicBlockUtils.h"201#include "llvm/Transforms/Utils/Local.h"202#include "llvm/Transforms/Utils/ModuleUtils.h"203#include <algorithm>204#include <cassert>205#include <cstddef>206#include <cstdint>207#include <memory>208#include <string>209#include <tuple>210211using namespace llvm;212213#define DEBUG_TYPE "msan"214215DEBUG_COUNTER(DebugInsertCheck, "msan-insert-check",216"Controls which checks to insert");217218DEBUG_COUNTER(DebugInstrumentInstruction, "msan-instrument-instruction",219"Controls which instruction to instrument");220221static const unsigned kOriginSize = 4;222static const Align kMinOriginAlignment = Align(4);223static const Align kShadowTLSAlignment = Align(8);224225// These constants must be kept in sync with the ones in msan.h.226static const unsigned kParamTLSSize = 800;227static const unsigned kRetvalTLSSize = 800;228229// Accesses sizes are powers of two: 1, 2, 4, 8.230static const size_t kNumberOfAccessSizes = 4;231232/// Track origins of uninitialized values.233///234/// Adds a section to MemorySanitizer report that points to the allocation235/// (stack or heap) the uninitialized bits came from originally.236static cl::opt<int> ClTrackOrigins(237"msan-track-origins",238cl::desc("Track origins (allocation sites) of poisoned memory"), cl::Hidden,239cl::init(0));240241static cl::opt<bool> ClKeepGoing("msan-keep-going",242cl::desc("keep going after reporting a UMR"),243cl::Hidden, cl::init(false));244245static cl::opt<bool>246ClPoisonStack("msan-poison-stack",247cl::desc("poison uninitialized stack variables"), cl::Hidden,248cl::init(true));249250static cl::opt<bool> ClPoisonStackWithCall(251"msan-poison-stack-with-call",252cl::desc("poison uninitialized stack variables with a call"), cl::Hidden,253cl::init(false));254255static cl::opt<int> ClPoisonStackPattern(256"msan-poison-stack-pattern",257cl::desc("poison uninitialized stack variables with the given pattern"),258cl::Hidden, cl::init(0xff));259260static cl::opt<bool>261ClPrintStackNames("msan-print-stack-names",262cl::desc("Print name of local stack variable"),263cl::Hidden, cl::init(true));264265static cl::opt<bool> ClPoisonUndef("msan-poison-undef",266cl::desc("poison undef temps"), cl::Hidden,267cl::init(true));268269static cl::opt<bool>270ClHandleICmp("msan-handle-icmp",271cl::desc("propagate shadow through ICmpEQ and ICmpNE"),272cl::Hidden, cl::init(true));273274static cl::opt<bool>275ClHandleICmpExact("msan-handle-icmp-exact",276cl::desc("exact handling of relational integer ICmp"),277cl::Hidden, cl::init(false));278279static cl::opt<bool> ClHandleLifetimeIntrinsics(280"msan-handle-lifetime-intrinsics",281cl::desc(282"when possible, poison scoped variables at the beginning of the scope "283"(slower, but more precise)"),284cl::Hidden, cl::init(true));285286// When compiling the Linux kernel, we sometimes see false positives related to287// MSan being unable to understand that inline assembly calls may initialize288// local variables.289// This flag makes the compiler conservatively unpoison every memory location290// passed into an assembly call. Note that this may cause false positives.291// Because it's impossible to figure out the array sizes, we can only unpoison292// the first sizeof(type) bytes for each type* pointer.293static cl::opt<bool> ClHandleAsmConservative(294"msan-handle-asm-conservative",295cl::desc("conservative handling of inline assembly"), cl::Hidden,296cl::init(true));297298// This flag controls whether we check the shadow of the address299// operand of load or store. Such bugs are very rare, since load from300// a garbage address typically results in SEGV, but still happen301// (e.g. only lower bits of address are garbage, or the access happens302// early at program startup where malloc-ed memory is more likely to303// be zeroed. As of 2012-08-28 this flag adds 20% slowdown.304static cl::opt<bool> ClCheckAccessAddress(305"msan-check-access-address",306cl::desc("report accesses through a pointer which has poisoned shadow"),307cl::Hidden, cl::init(true));308309static cl::opt<bool> ClEagerChecks(310"msan-eager-checks",311cl::desc("check arguments and return values at function call boundaries"),312cl::Hidden, cl::init(false));313314static cl::opt<bool> ClDumpStrictInstructions(315"msan-dump-strict-instructions",316cl::desc("print out instructions with default strict semantics"),317cl::Hidden, cl::init(false));318319static cl::opt<int> ClInstrumentationWithCallThreshold(320"msan-instrumentation-with-call-threshold",321cl::desc(322"If the function being instrumented requires more than "323"this number of checks and origin stores, use callbacks instead of "324"inline checks (-1 means never use callbacks)."),325cl::Hidden, cl::init(3500));326327static cl::opt<bool>328ClEnableKmsan("msan-kernel",329cl::desc("Enable KernelMemorySanitizer instrumentation"),330cl::Hidden, cl::init(false));331332static cl::opt<bool>333ClDisableChecks("msan-disable-checks",334cl::desc("Apply no_sanitize to the whole file"), cl::Hidden,335cl::init(false));336337static cl::opt<bool>338ClCheckConstantShadow("msan-check-constant-shadow",339cl::desc("Insert checks for constant shadow values"),340cl::Hidden, cl::init(true));341342// This is off by default because of a bug in gold:343// https://sourceware.org/bugzilla/show_bug.cgi?id=19002344static cl::opt<bool>345ClWithComdat("msan-with-comdat",346cl::desc("Place MSan constructors in comdat sections"),347cl::Hidden, cl::init(false));348349// These options allow to specify custom memory map parameters350// See MemoryMapParams for details.351static cl::opt<uint64_t> ClAndMask("msan-and-mask",352cl::desc("Define custom MSan AndMask"),353cl::Hidden, cl::init(0));354355static cl::opt<uint64_t> ClXorMask("msan-xor-mask",356cl::desc("Define custom MSan XorMask"),357cl::Hidden, cl::init(0));358359static cl::opt<uint64_t> ClShadowBase("msan-shadow-base",360cl::desc("Define custom MSan ShadowBase"),361cl::Hidden, cl::init(0));362363static cl::opt<uint64_t> ClOriginBase("msan-origin-base",364cl::desc("Define custom MSan OriginBase"),365cl::Hidden, cl::init(0));366367static cl::opt<int>368ClDisambiguateWarning("msan-disambiguate-warning-threshold",369cl::desc("Define threshold for number of checks per "370"debug location to force origin update."),371cl::Hidden, cl::init(3));372373const char kMsanModuleCtorName[] = "msan.module_ctor";374const char kMsanInitName[] = "__msan_init";375376namespace {377378// Memory map parameters used in application-to-shadow address calculation.379// Offset = (Addr & ~AndMask) ^ XorMask380// Shadow = ShadowBase + Offset381// Origin = OriginBase + Offset382struct MemoryMapParams {383uint64_t AndMask;384uint64_t XorMask;385uint64_t ShadowBase;386uint64_t OriginBase;387};388389struct PlatformMemoryMapParams {390const MemoryMapParams *bits32;391const MemoryMapParams *bits64;392};393394} // end anonymous namespace395396// i386 Linux397static const MemoryMapParams Linux_I386_MemoryMapParams = {3980x000080000000, // AndMask3990, // XorMask (not used)4000, // ShadowBase (not used)4010x000040000000, // OriginBase402};403404// x86_64 Linux405static const MemoryMapParams Linux_X86_64_MemoryMapParams = {4060, // AndMask (not used)4070x500000000000, // XorMask4080, // ShadowBase (not used)4090x100000000000, // OriginBase410};411412// mips64 Linux413static const MemoryMapParams Linux_MIPS64_MemoryMapParams = {4140, // AndMask (not used)4150x008000000000, // XorMask4160, // ShadowBase (not used)4170x002000000000, // OriginBase418};419420// ppc64 Linux421static const MemoryMapParams Linux_PowerPC64_MemoryMapParams = {4220xE00000000000, // AndMask4230x100000000000, // XorMask4240x080000000000, // ShadowBase4250x1C0000000000, // OriginBase426};427428// s390x Linux429static const MemoryMapParams Linux_S390X_MemoryMapParams = {4300xC00000000000, // AndMask4310, // XorMask (not used)4320x080000000000, // ShadowBase4330x1C0000000000, // OriginBase434};435436// aarch64 Linux437static const MemoryMapParams Linux_AArch64_MemoryMapParams = {4380, // AndMask (not used)4390x0B00000000000, // XorMask4400, // ShadowBase (not used)4410x0200000000000, // OriginBase442};443444// loongarch64 Linux445static const MemoryMapParams Linux_LoongArch64_MemoryMapParams = {4460, // AndMask (not used)4470x500000000000, // XorMask4480, // ShadowBase (not used)4490x100000000000, // OriginBase450};451452// aarch64 FreeBSD453static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams = {4540x1800000000000, // AndMask4550x0400000000000, // XorMask4560x0200000000000, // ShadowBase4570x0700000000000, // OriginBase458};459460// i386 FreeBSD461static const MemoryMapParams FreeBSD_I386_MemoryMapParams = {4620x000180000000, // AndMask4630x000040000000, // XorMask4640x000020000000, // ShadowBase4650x000700000000, // OriginBase466};467468// x86_64 FreeBSD469static const MemoryMapParams FreeBSD_X86_64_MemoryMapParams = {4700xc00000000000, // AndMask4710x200000000000, // XorMask4720x100000000000, // ShadowBase4730x380000000000, // OriginBase474};475476// x86_64 NetBSD477static const MemoryMapParams NetBSD_X86_64_MemoryMapParams = {4780, // AndMask4790x500000000000, // XorMask4800, // ShadowBase4810x100000000000, // OriginBase482};483484static const PlatformMemoryMapParams Linux_X86_MemoryMapParams = {485&Linux_I386_MemoryMapParams,486&Linux_X86_64_MemoryMapParams,487};488489static const PlatformMemoryMapParams Linux_MIPS_MemoryMapParams = {490nullptr,491&Linux_MIPS64_MemoryMapParams,492};493494static const PlatformMemoryMapParams Linux_PowerPC_MemoryMapParams = {495nullptr,496&Linux_PowerPC64_MemoryMapParams,497};498499static const PlatformMemoryMapParams Linux_S390_MemoryMapParams = {500nullptr,501&Linux_S390X_MemoryMapParams,502};503504static const PlatformMemoryMapParams Linux_ARM_MemoryMapParams = {505nullptr,506&Linux_AArch64_MemoryMapParams,507};508509static const PlatformMemoryMapParams Linux_LoongArch_MemoryMapParams = {510nullptr,511&Linux_LoongArch64_MemoryMapParams,512};513514static const PlatformMemoryMapParams FreeBSD_ARM_MemoryMapParams = {515nullptr,516&FreeBSD_AArch64_MemoryMapParams,517};518519static const PlatformMemoryMapParams FreeBSD_X86_MemoryMapParams = {520&FreeBSD_I386_MemoryMapParams,521&FreeBSD_X86_64_MemoryMapParams,522};523524static const PlatformMemoryMapParams NetBSD_X86_MemoryMapParams = {525nullptr,526&NetBSD_X86_64_MemoryMapParams,527};528529namespace {530531/// Instrument functions of a module to detect uninitialized reads.532///533/// Instantiating MemorySanitizer inserts the msan runtime library API function534/// declarations into the module if they don't exist already. Instantiating535/// ensures the __msan_init function is in the list of global constructors for536/// the module.537class MemorySanitizer {538public:539MemorySanitizer(Module &M, MemorySanitizerOptions Options)540: CompileKernel(Options.Kernel), TrackOrigins(Options.TrackOrigins),541Recover(Options.Recover), EagerChecks(Options.EagerChecks) {542initializeModule(M);543}544545// MSan cannot be moved or copied because of MapParams.546MemorySanitizer(MemorySanitizer &&) = delete;547MemorySanitizer &operator=(MemorySanitizer &&) = delete;548MemorySanitizer(const MemorySanitizer &) = delete;549MemorySanitizer &operator=(const MemorySanitizer &) = delete;550551bool sanitizeFunction(Function &F, TargetLibraryInfo &TLI);552553private:554friend struct MemorySanitizerVisitor;555friend struct VarArgHelperBase;556friend struct VarArgAMD64Helper;557friend struct VarArgMIPS64Helper;558friend struct VarArgAArch64Helper;559friend struct VarArgPowerPC64Helper;560friend struct VarArgSystemZHelper;561562void initializeModule(Module &M);563void initializeCallbacks(Module &M, const TargetLibraryInfo &TLI);564void createKernelApi(Module &M, const TargetLibraryInfo &TLI);565void createUserspaceApi(Module &M, const TargetLibraryInfo &TLI);566567template <typename... ArgsTy>568FunctionCallee getOrInsertMsanMetadataFunction(Module &M, StringRef Name,569ArgsTy... Args);570571/// True if we're compiling the Linux kernel.572bool CompileKernel;573/// Track origins (allocation points) of uninitialized values.574int TrackOrigins;575bool Recover;576bool EagerChecks;577578Triple TargetTriple;579LLVMContext *C;580Type *IntptrTy; ///< Integer type with the size of a ptr in default AS.581Type *OriginTy;582PointerType *PtrTy; ///< Integer type with the size of a ptr in default AS.583584// XxxTLS variables represent the per-thread state in MSan and per-task state585// in KMSAN.586// For the userspace these point to thread-local globals. In the kernel land587// they point to the members of a per-task struct obtained via a call to588// __msan_get_context_state().589590/// Thread-local shadow storage for function parameters.591Value *ParamTLS;592593/// Thread-local origin storage for function parameters.594Value *ParamOriginTLS;595596/// Thread-local shadow storage for function return value.597Value *RetvalTLS;598599/// Thread-local origin storage for function return value.600Value *RetvalOriginTLS;601602/// Thread-local shadow storage for in-register va_arg function.603Value *VAArgTLS;604605/// Thread-local shadow storage for in-register va_arg function.606Value *VAArgOriginTLS;607608/// Thread-local shadow storage for va_arg overflow area.609Value *VAArgOverflowSizeTLS;610611/// Are the instrumentation callbacks set up?612bool CallbacksInitialized = false;613614/// The run-time callback to print a warning.615FunctionCallee WarningFn;616617// These arrays are indexed by log2(AccessSize).618FunctionCallee MaybeWarningFn[kNumberOfAccessSizes];619FunctionCallee MaybeStoreOriginFn[kNumberOfAccessSizes];620621/// Run-time helper that generates a new origin value for a stack622/// allocation.623FunctionCallee MsanSetAllocaOriginWithDescriptionFn;624// No description version625FunctionCallee MsanSetAllocaOriginNoDescriptionFn;626627/// Run-time helper that poisons stack on function entry.628FunctionCallee MsanPoisonStackFn;629630/// Run-time helper that records a store (or any event) of an631/// uninitialized value and returns an updated origin id encoding this info.632FunctionCallee MsanChainOriginFn;633634/// Run-time helper that paints an origin over a region.635FunctionCallee MsanSetOriginFn;636637/// MSan runtime replacements for memmove, memcpy and memset.638FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;639640/// KMSAN callback for task-local function argument shadow.641StructType *MsanContextStateTy;642FunctionCallee MsanGetContextStateFn;643644/// Functions for poisoning/unpoisoning local variables645FunctionCallee MsanPoisonAllocaFn, MsanUnpoisonAllocaFn;646647/// Pair of shadow/origin pointers.648Type *MsanMetadata;649650/// Each of the MsanMetadataPtrXxx functions returns a MsanMetadata.651FunctionCallee MsanMetadataPtrForLoadN, MsanMetadataPtrForStoreN;652FunctionCallee MsanMetadataPtrForLoad_1_8[4];653FunctionCallee MsanMetadataPtrForStore_1_8[4];654FunctionCallee MsanInstrumentAsmStoreFn;655656/// Storage for return values of the MsanMetadataPtrXxx functions.657Value *MsanMetadataAlloca;658659/// Helper to choose between different MsanMetadataPtrXxx().660FunctionCallee getKmsanShadowOriginAccessFn(bool isStore, int size);661662/// Memory map parameters used in application-to-shadow calculation.663const MemoryMapParams *MapParams;664665/// Custom memory map parameters used when -msan-shadow-base or666// -msan-origin-base is provided.667MemoryMapParams CustomMapParams;668669MDNode *ColdCallWeights;670671/// Branch weights for origin store.672MDNode *OriginStoreWeights;673};674675void insertModuleCtor(Module &M) {676getOrCreateSanitizerCtorAndInitFunctions(677M, kMsanModuleCtorName, kMsanInitName,678/*InitArgTypes=*/{},679/*InitArgs=*/{},680// This callback is invoked when the functions are created the first681// time. Hook them into the global ctors list in that case:682[&](Function *Ctor, FunctionCallee) {683if (!ClWithComdat) {684appendToGlobalCtors(M, Ctor, 0);685return;686}687Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);688Ctor->setComdat(MsanCtorComdat);689appendToGlobalCtors(M, Ctor, 0, Ctor);690});691}692693template <class T> T getOptOrDefault(const cl::opt<T> &Opt, T Default) {694return (Opt.getNumOccurrences() > 0) ? Opt : Default;695}696697} // end anonymous namespace698699MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,700bool EagerChecks)701: Kernel(getOptOrDefault(ClEnableKmsan, K)),702TrackOrigins(getOptOrDefault(ClTrackOrigins, Kernel ? 2 : TO)),703Recover(getOptOrDefault(ClKeepGoing, Kernel || R)),704EagerChecks(getOptOrDefault(ClEagerChecks, EagerChecks)) {}705706PreservedAnalyses MemorySanitizerPass::run(Module &M,707ModuleAnalysisManager &AM) {708bool Modified = false;709if (!Options.Kernel) {710insertModuleCtor(M);711Modified = true;712}713714auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();715for (Function &F : M) {716if (F.empty())717continue;718MemorySanitizer Msan(*F.getParent(), Options);719Modified |=720Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));721}722723if (!Modified)724return PreservedAnalyses::all();725726PreservedAnalyses PA = PreservedAnalyses::none();727// GlobalsAA is considered stateless and does not get invalidated unless728// explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers729// make changes that require GlobalsAA to be invalidated.730PA.abandon<GlobalsAA>();731return PA;732}733734void MemorySanitizerPass::printPipeline(735raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {736static_cast<PassInfoMixin<MemorySanitizerPass> *>(this)->printPipeline(737OS, MapClassName2PassName);738OS << '<';739if (Options.Recover)740OS << "recover;";741if (Options.Kernel)742OS << "kernel;";743if (Options.EagerChecks)744OS << "eager-checks;";745OS << "track-origins=" << Options.TrackOrigins;746OS << '>';747}748749/// Create a non-const global initialized with the given string.750///751/// Creates a writable global for Str so that we can pass it to the752/// run-time lib. Runtime uses first 4 bytes of the string to store the753/// frame ID, so the string needs to be mutable.754static GlobalVariable *createPrivateConstGlobalForString(Module &M,755StringRef Str) {756Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str);757return new GlobalVariable(M, StrConst->getType(), /*isConstant=*/true,758GlobalValue::PrivateLinkage, StrConst, "");759}760761template <typename... ArgsTy>762FunctionCallee763MemorySanitizer::getOrInsertMsanMetadataFunction(Module &M, StringRef Name,764ArgsTy... Args) {765if (TargetTriple.getArch() == Triple::systemz) {766// SystemZ ABI: shadow/origin pair is returned via a hidden parameter.767return M.getOrInsertFunction(Name, Type::getVoidTy(*C),768PointerType::get(MsanMetadata, 0),769std::forward<ArgsTy>(Args)...);770}771772return M.getOrInsertFunction(Name, MsanMetadata,773std::forward<ArgsTy>(Args)...);774}775776/// Create KMSAN API callbacks.777void MemorySanitizer::createKernelApi(Module &M, const TargetLibraryInfo &TLI) {778IRBuilder<> IRB(*C);779780// These will be initialized in insertKmsanPrologue().781RetvalTLS = nullptr;782RetvalOriginTLS = nullptr;783ParamTLS = nullptr;784ParamOriginTLS = nullptr;785VAArgTLS = nullptr;786VAArgOriginTLS = nullptr;787VAArgOverflowSizeTLS = nullptr;788789WarningFn = M.getOrInsertFunction("__msan_warning",790TLI.getAttrList(C, {0}, /*Signed=*/false),791IRB.getVoidTy(), IRB.getInt32Ty());792793// Requests the per-task context state (kmsan_context_state*) from the794// runtime library.795MsanContextStateTy = StructType::get(796ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8),797ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8),798ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8),799ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), /* va_arg_origin */800IRB.getInt64Ty(), ArrayType::get(OriginTy, kParamTLSSize / 4), OriginTy,801OriginTy);802MsanGetContextStateFn = M.getOrInsertFunction(803"__msan_get_context_state", PointerType::get(MsanContextStateTy, 0));804805MsanMetadata = StructType::get(PointerType::get(IRB.getInt8Ty(), 0),806PointerType::get(IRB.getInt32Ty(), 0));807808for (int ind = 0, size = 1; ind < 4; ind++, size <<= 1) {809std::string name_load =810"__msan_metadata_ptr_for_load_" + std::to_string(size);811std::string name_store =812"__msan_metadata_ptr_for_store_" + std::to_string(size);813MsanMetadataPtrForLoad_1_8[ind] = getOrInsertMsanMetadataFunction(814M, name_load, PointerType::get(IRB.getInt8Ty(), 0));815MsanMetadataPtrForStore_1_8[ind] = getOrInsertMsanMetadataFunction(816M, name_store, PointerType::get(IRB.getInt8Ty(), 0));817}818819MsanMetadataPtrForLoadN = getOrInsertMsanMetadataFunction(820M, "__msan_metadata_ptr_for_load_n", PointerType::get(IRB.getInt8Ty(), 0),821IRB.getInt64Ty());822MsanMetadataPtrForStoreN = getOrInsertMsanMetadataFunction(823M, "__msan_metadata_ptr_for_store_n",824PointerType::get(IRB.getInt8Ty(), 0), IRB.getInt64Ty());825826// Functions for poisoning and unpoisoning memory.827MsanPoisonAllocaFn = M.getOrInsertFunction(828"__msan_poison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);829MsanUnpoisonAllocaFn = M.getOrInsertFunction(830"__msan_unpoison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy);831}832833static Constant *getOrInsertGlobal(Module &M, StringRef Name, Type *Ty) {834return M.getOrInsertGlobal(Name, Ty, [&] {835return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,836nullptr, Name, nullptr,837GlobalVariable::InitialExecTLSModel);838});839}840841/// Insert declarations for userspace-specific functions and globals.842void MemorySanitizer::createUserspaceApi(Module &M, const TargetLibraryInfo &TLI) {843IRBuilder<> IRB(*C);844845// Create the callback.846// FIXME: this function should have "Cold" calling conv,847// which is not yet implemented.848if (TrackOrigins) {849StringRef WarningFnName = Recover ? "__msan_warning_with_origin"850: "__msan_warning_with_origin_noreturn";851WarningFn = M.getOrInsertFunction(WarningFnName,852TLI.getAttrList(C, {0}, /*Signed=*/false),853IRB.getVoidTy(), IRB.getInt32Ty());854} else {855StringRef WarningFnName =856Recover ? "__msan_warning" : "__msan_warning_noreturn";857WarningFn = M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());858}859860// Create the global TLS variables.861RetvalTLS =862getOrInsertGlobal(M, "__msan_retval_tls",863ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8));864865RetvalOriginTLS = getOrInsertGlobal(M, "__msan_retval_origin_tls", OriginTy);866867ParamTLS =868getOrInsertGlobal(M, "__msan_param_tls",869ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8));870871ParamOriginTLS =872getOrInsertGlobal(M, "__msan_param_origin_tls",873ArrayType::get(OriginTy, kParamTLSSize / 4));874875VAArgTLS =876getOrInsertGlobal(M, "__msan_va_arg_tls",877ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8));878879VAArgOriginTLS =880getOrInsertGlobal(M, "__msan_va_arg_origin_tls",881ArrayType::get(OriginTy, kParamTLSSize / 4));882883VAArgOverflowSizeTLS =884getOrInsertGlobal(M, "__msan_va_arg_overflow_size_tls", IRB.getInt64Ty());885886for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;887AccessSizeIndex++) {888unsigned AccessSize = 1 << AccessSizeIndex;889std::string FunctionName = "__msan_maybe_warning_" + itostr(AccessSize);890MaybeWarningFn[AccessSizeIndex] = M.getOrInsertFunction(891FunctionName, TLI.getAttrList(C, {0, 1}, /*Signed=*/false),892IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), IRB.getInt32Ty());893894FunctionName = "__msan_maybe_store_origin_" + itostr(AccessSize);895MaybeStoreOriginFn[AccessSizeIndex] = M.getOrInsertFunction(896FunctionName, TLI.getAttrList(C, {0, 2}, /*Signed=*/false),897IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), PtrTy,898IRB.getInt32Ty());899}900901MsanSetAllocaOriginWithDescriptionFn =902M.getOrInsertFunction("__msan_set_alloca_origin_with_descr",903IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy, PtrTy);904MsanSetAllocaOriginNoDescriptionFn =905M.getOrInsertFunction("__msan_set_alloca_origin_no_descr",906IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);907MsanPoisonStackFn = M.getOrInsertFunction("__msan_poison_stack",908IRB.getVoidTy(), PtrTy, IntptrTy);909}910911/// Insert extern declaration of runtime-provided functions and globals.912void MemorySanitizer::initializeCallbacks(Module &M, const TargetLibraryInfo &TLI) {913// Only do this once.914if (CallbacksInitialized)915return;916917IRBuilder<> IRB(*C);918// Initialize callbacks that are common for kernel and userspace919// instrumentation.920MsanChainOriginFn = M.getOrInsertFunction(921"__msan_chain_origin",922TLI.getAttrList(C, {0}, /*Signed=*/false, /*Ret=*/true), IRB.getInt32Ty(),923IRB.getInt32Ty());924MsanSetOriginFn = M.getOrInsertFunction(925"__msan_set_origin", TLI.getAttrList(C, {2}, /*Signed=*/false),926IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());927MemmoveFn =928M.getOrInsertFunction("__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);929MemcpyFn =930M.getOrInsertFunction("__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);931MemsetFn = M.getOrInsertFunction("__msan_memset",932TLI.getAttrList(C, {1}, /*Signed=*/true),933PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);934935MsanInstrumentAsmStoreFn =936M.getOrInsertFunction("__msan_instrument_asm_store", IRB.getVoidTy(),937PointerType::get(IRB.getInt8Ty(), 0), IntptrTy);938939if (CompileKernel) {940createKernelApi(M, TLI);941} else {942createUserspaceApi(M, TLI);943}944CallbacksInitialized = true;945}946947FunctionCallee MemorySanitizer::getKmsanShadowOriginAccessFn(bool isStore,948int size) {949FunctionCallee *Fns =950isStore ? MsanMetadataPtrForStore_1_8 : MsanMetadataPtrForLoad_1_8;951switch (size) {952case 1:953return Fns[0];954case 2:955return Fns[1];956case 4:957return Fns[2];958case 8:959return Fns[3];960default:961return nullptr;962}963}964965/// Module-level initialization.966///967/// inserts a call to __msan_init to the module's constructor list.968void MemorySanitizer::initializeModule(Module &M) {969auto &DL = M.getDataLayout();970971TargetTriple = Triple(M.getTargetTriple());972973bool ShadowPassed = ClShadowBase.getNumOccurrences() > 0;974bool OriginPassed = ClOriginBase.getNumOccurrences() > 0;975// Check the overrides first976if (ShadowPassed || OriginPassed) {977CustomMapParams.AndMask = ClAndMask;978CustomMapParams.XorMask = ClXorMask;979CustomMapParams.ShadowBase = ClShadowBase;980CustomMapParams.OriginBase = ClOriginBase;981MapParams = &CustomMapParams;982} else {983switch (TargetTriple.getOS()) {984case Triple::FreeBSD:985switch (TargetTriple.getArch()) {986case Triple::aarch64:987MapParams = FreeBSD_ARM_MemoryMapParams.bits64;988break;989case Triple::x86_64:990MapParams = FreeBSD_X86_MemoryMapParams.bits64;991break;992case Triple::x86:993MapParams = FreeBSD_X86_MemoryMapParams.bits32;994break;995default:996report_fatal_error("unsupported architecture");997}998break;999case Triple::NetBSD:1000switch (TargetTriple.getArch()) {1001case Triple::x86_64:1002MapParams = NetBSD_X86_MemoryMapParams.bits64;1003break;1004default:1005report_fatal_error("unsupported architecture");1006}1007break;1008case Triple::Linux:1009switch (TargetTriple.getArch()) {1010case Triple::x86_64:1011MapParams = Linux_X86_MemoryMapParams.bits64;1012break;1013case Triple::x86:1014MapParams = Linux_X86_MemoryMapParams.bits32;1015break;1016case Triple::mips64:1017case Triple::mips64el:1018MapParams = Linux_MIPS_MemoryMapParams.bits64;1019break;1020case Triple::ppc64:1021case Triple::ppc64le:1022MapParams = Linux_PowerPC_MemoryMapParams.bits64;1023break;1024case Triple::systemz:1025MapParams = Linux_S390_MemoryMapParams.bits64;1026break;1027case Triple::aarch64:1028case Triple::aarch64_be:1029MapParams = Linux_ARM_MemoryMapParams.bits64;1030break;1031case Triple::loongarch64:1032MapParams = Linux_LoongArch_MemoryMapParams.bits64;1033break;1034default:1035report_fatal_error("unsupported architecture");1036}1037break;1038default:1039report_fatal_error("unsupported operating system");1040}1041}10421043C = &(M.getContext());1044IRBuilder<> IRB(*C);1045IntptrTy = IRB.getIntPtrTy(DL);1046OriginTy = IRB.getInt32Ty();1047PtrTy = IRB.getPtrTy();10481049ColdCallWeights = MDBuilder(*C).createUnlikelyBranchWeights();1050OriginStoreWeights = MDBuilder(*C).createUnlikelyBranchWeights();10511052if (!CompileKernel) {1053if (TrackOrigins)1054M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] {1055return new GlobalVariable(1056M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,1057IRB.getInt32(TrackOrigins), "__msan_track_origins");1058});10591060if (Recover)1061M.getOrInsertGlobal("__msan_keep_going", IRB.getInt32Ty(), [&] {1062return new GlobalVariable(M, IRB.getInt32Ty(), true,1063GlobalValue::WeakODRLinkage,1064IRB.getInt32(Recover), "__msan_keep_going");1065});1066}1067}10681069namespace {10701071/// A helper class that handles instrumentation of VarArg1072/// functions on a particular platform.1073///1074/// Implementations are expected to insert the instrumentation1075/// necessary to propagate argument shadow through VarArg function1076/// calls. Visit* methods are called during an InstVisitor pass over1077/// the function, and should avoid creating new basic blocks. A new1078/// instance of this class is created for each instrumented function.1079struct VarArgHelper {1080virtual ~VarArgHelper() = default;10811082/// Visit a CallBase.1083virtual void visitCallBase(CallBase &CB, IRBuilder<> &IRB) = 0;10841085/// Visit a va_start call.1086virtual void visitVAStartInst(VAStartInst &I) = 0;10871088/// Visit a va_copy call.1089virtual void visitVACopyInst(VACopyInst &I) = 0;10901091/// Finalize function instrumentation.1092///1093/// This method is called after visiting all interesting (see above)1094/// instructions in a function.1095virtual void finalizeInstrumentation() = 0;1096};10971098struct MemorySanitizerVisitor;10991100} // end anonymous namespace11011102static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,1103MemorySanitizerVisitor &Visitor);11041105static unsigned TypeSizeToSizeIndex(TypeSize TS) {1106if (TS.isScalable())1107// Scalable types unconditionally take slowpaths.1108return kNumberOfAccessSizes;1109unsigned TypeSizeFixed = TS.getFixedValue();1110if (TypeSizeFixed <= 8)1111return 0;1112return Log2_32_Ceil((TypeSizeFixed + 7) / 8);1113}11141115namespace {11161117/// Helper class to attach debug information of the given instruction onto new1118/// instructions inserted after.1119class NextNodeIRBuilder : public IRBuilder<> {1120public:1121explicit NextNodeIRBuilder(Instruction *IP) : IRBuilder<>(IP->getNextNode()) {1122SetCurrentDebugLocation(IP->getDebugLoc());1123}1124};11251126/// This class does all the work for a given function. Store and Load1127/// instructions store and load corresponding shadow and origin1128/// values. Most instructions propagate shadow from arguments to their1129/// return values. Certain instructions (most importantly, BranchInst)1130/// test their argument shadow and print reports (with a runtime call) if it's1131/// non-zero.1132struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {1133Function &F;1134MemorySanitizer &MS;1135SmallVector<PHINode *, 16> ShadowPHINodes, OriginPHINodes;1136ValueMap<Value *, Value *> ShadowMap, OriginMap;1137std::unique_ptr<VarArgHelper> VAHelper;1138const TargetLibraryInfo *TLI;1139Instruction *FnPrologueEnd;1140SmallVector<Instruction *, 16> Instructions;11411142// The following flags disable parts of MSan instrumentation based on1143// exclusion list contents and command-line options.1144bool InsertChecks;1145bool PropagateShadow;1146bool PoisonStack;1147bool PoisonUndef;11481149struct ShadowOriginAndInsertPoint {1150Value *Shadow;1151Value *Origin;1152Instruction *OrigIns;11531154ShadowOriginAndInsertPoint(Value *S, Value *O, Instruction *I)1155: Shadow(S), Origin(O), OrigIns(I) {}1156};1157SmallVector<ShadowOriginAndInsertPoint, 16> InstrumentationList;1158DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;1159bool InstrumentLifetimeStart = ClHandleLifetimeIntrinsics;1160SmallSetVector<AllocaInst *, 16> AllocaSet;1161SmallVector<std::pair<IntrinsicInst *, AllocaInst *>, 16> LifetimeStartList;1162SmallVector<StoreInst *, 16> StoreList;1163int64_t SplittableBlocksCount = 0;11641165MemorySanitizerVisitor(Function &F, MemorySanitizer &MS,1166const TargetLibraryInfo &TLI)1167: F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)), TLI(&TLI) {1168bool SanitizeFunction =1169F.hasFnAttribute(Attribute::SanitizeMemory) && !ClDisableChecks;1170InsertChecks = SanitizeFunction;1171PropagateShadow = SanitizeFunction;1172PoisonStack = SanitizeFunction && ClPoisonStack;1173PoisonUndef = SanitizeFunction && ClPoisonUndef;11741175// In the presence of unreachable blocks, we may see Phi nodes with1176// incoming nodes from such blocks. Since InstVisitor skips unreachable1177// blocks, such nodes will not have any shadow value associated with them.1178// It's easier to remove unreachable blocks than deal with missing shadow.1179removeUnreachableBlocks(F);11801181MS.initializeCallbacks(*F.getParent(), TLI);1182FnPrologueEnd = IRBuilder<>(F.getEntryBlock().getFirstNonPHI())1183.CreateIntrinsic(Intrinsic::donothing, {}, {});11841185if (MS.CompileKernel) {1186IRBuilder<> IRB(FnPrologueEnd);1187insertKmsanPrologue(IRB);1188}11891190LLVM_DEBUG(if (!InsertChecks) dbgs()1191<< "MemorySanitizer is not inserting checks into '"1192<< F.getName() << "'\n");1193}11941195bool instrumentWithCalls(Value *V) {1196// Constants likely will be eliminated by follow-up passes.1197if (isa<Constant>(V))1198return false;11991200++SplittableBlocksCount;1201return ClInstrumentationWithCallThreshold >= 0 &&1202SplittableBlocksCount > ClInstrumentationWithCallThreshold;1203}12041205bool isInPrologue(Instruction &I) {1206return I.getParent() == FnPrologueEnd->getParent() &&1207(&I == FnPrologueEnd || I.comesBefore(FnPrologueEnd));1208}12091210// Creates a new origin and records the stack trace. In general we can call1211// this function for any origin manipulation we like. However it will cost1212// runtime resources. So use this wisely only if it can provide additional1213// information helpful to a user.1214Value *updateOrigin(Value *V, IRBuilder<> &IRB) {1215if (MS.TrackOrigins <= 1)1216return V;1217return IRB.CreateCall(MS.MsanChainOriginFn, V);1218}12191220Value *originToIntptr(IRBuilder<> &IRB, Value *Origin) {1221const DataLayout &DL = F.getDataLayout();1222unsigned IntptrSize = DL.getTypeStoreSize(MS.IntptrTy);1223if (IntptrSize == kOriginSize)1224return Origin;1225assert(IntptrSize == kOriginSize * 2);1226Origin = IRB.CreateIntCast(Origin, MS.IntptrTy, /* isSigned */ false);1227return IRB.CreateOr(Origin, IRB.CreateShl(Origin, kOriginSize * 8));1228}12291230/// Fill memory range with the given origin value.1231void paintOrigin(IRBuilder<> &IRB, Value *Origin, Value *OriginPtr,1232TypeSize TS, Align Alignment) {1233const DataLayout &DL = F.getDataLayout();1234const Align IntptrAlignment = DL.getABITypeAlign(MS.IntptrTy);1235unsigned IntptrSize = DL.getTypeStoreSize(MS.IntptrTy);1236assert(IntptrAlignment >= kMinOriginAlignment);1237assert(IntptrSize >= kOriginSize);12381239// Note: The loop based formation works for fixed length vectors too,1240// however we prefer to unroll and specialize alignment below.1241if (TS.isScalable()) {1242Value *Size = IRB.CreateTypeSize(MS.IntptrTy, TS);1243Value *RoundUp =1244IRB.CreateAdd(Size, ConstantInt::get(MS.IntptrTy, kOriginSize - 1));1245Value *End =1246IRB.CreateUDiv(RoundUp, ConstantInt::get(MS.IntptrTy, kOriginSize));1247auto [InsertPt, Index] =1248SplitBlockAndInsertSimpleForLoop(End, &*IRB.GetInsertPoint());1249IRB.SetInsertPoint(InsertPt);12501251Value *GEP = IRB.CreateGEP(MS.OriginTy, OriginPtr, Index);1252IRB.CreateAlignedStore(Origin, GEP, kMinOriginAlignment);1253return;1254}12551256unsigned Size = TS.getFixedValue();12571258unsigned Ofs = 0;1259Align CurrentAlignment = Alignment;1260if (Alignment >= IntptrAlignment && IntptrSize > kOriginSize) {1261Value *IntptrOrigin = originToIntptr(IRB, Origin);1262Value *IntptrOriginPtr =1263IRB.CreatePointerCast(OriginPtr, PointerType::get(MS.IntptrTy, 0));1264for (unsigned i = 0; i < Size / IntptrSize; ++i) {1265Value *Ptr = i ? IRB.CreateConstGEP1_32(MS.IntptrTy, IntptrOriginPtr, i)1266: IntptrOriginPtr;1267IRB.CreateAlignedStore(IntptrOrigin, Ptr, CurrentAlignment);1268Ofs += IntptrSize / kOriginSize;1269CurrentAlignment = IntptrAlignment;1270}1271}12721273for (unsigned i = Ofs; i < (Size + kOriginSize - 1) / kOriginSize; ++i) {1274Value *GEP =1275i ? IRB.CreateConstGEP1_32(MS.OriginTy, OriginPtr, i) : OriginPtr;1276IRB.CreateAlignedStore(Origin, GEP, CurrentAlignment);1277CurrentAlignment = kMinOriginAlignment;1278}1279}12801281void storeOrigin(IRBuilder<> &IRB, Value *Addr, Value *Shadow, Value *Origin,1282Value *OriginPtr, Align Alignment) {1283const DataLayout &DL = F.getDataLayout();1284const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);1285TypeSize StoreSize = DL.getTypeStoreSize(Shadow->getType());1286// ZExt cannot convert between vector and scalar1287Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);1288if (auto *ConstantShadow = dyn_cast<Constant>(ConvertedShadow)) {1289if (!ClCheckConstantShadow || ConstantShadow->isZeroValue()) {1290// Origin is not needed: value is initialized or const shadow is1291// ignored.1292return;1293}1294if (llvm::isKnownNonZero(ConvertedShadow, DL)) {1295// Copy origin as the value is definitely uninitialized.1296paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize,1297OriginAlignment);1298return;1299}1300// Fallback to runtime check, which still can be optimized out later.1301}13021303TypeSize TypeSizeInBits = DL.getTypeSizeInBits(ConvertedShadow->getType());1304unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits);1305if (instrumentWithCalls(ConvertedShadow) &&1306SizeIndex < kNumberOfAccessSizes && !MS.CompileKernel) {1307FunctionCallee Fn = MS.MaybeStoreOriginFn[SizeIndex];1308Value *ConvertedShadow2 =1309IRB.CreateZExt(ConvertedShadow, IRB.getIntNTy(8 * (1 << SizeIndex)));1310CallBase *CB = IRB.CreateCall(Fn, {ConvertedShadow2, Addr, Origin});1311CB->addParamAttr(0, Attribute::ZExt);1312CB->addParamAttr(2, Attribute::ZExt);1313} else {1314Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp");1315Instruction *CheckTerm = SplitBlockAndInsertIfThen(1316Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights);1317IRBuilder<> IRBNew(CheckTerm);1318paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), OriginPtr, StoreSize,1319OriginAlignment);1320}1321}13221323void materializeStores() {1324for (StoreInst *SI : StoreList) {1325IRBuilder<> IRB(SI);1326Value *Val = SI->getValueOperand();1327Value *Addr = SI->getPointerOperand();1328Value *Shadow = SI->isAtomic() ? getCleanShadow(Val) : getShadow(Val);1329Value *ShadowPtr, *OriginPtr;1330Type *ShadowTy = Shadow->getType();1331const Align Alignment = SI->getAlign();1332const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);1333std::tie(ShadowPtr, OriginPtr) =1334getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment, /*isStore*/ true);13351336StoreInst *NewSI = IRB.CreateAlignedStore(Shadow, ShadowPtr, Alignment);1337LLVM_DEBUG(dbgs() << " STORE: " << *NewSI << "\n");1338(void)NewSI;13391340if (SI->isAtomic())1341SI->setOrdering(addReleaseOrdering(SI->getOrdering()));13421343if (MS.TrackOrigins && !SI->isAtomic())1344storeOrigin(IRB, Addr, Shadow, getOrigin(Val), OriginPtr,1345OriginAlignment);1346}1347}13481349// Returns true if Debug Location corresponds to multiple warnings.1350bool shouldDisambiguateWarningLocation(const DebugLoc &DebugLoc) {1351if (MS.TrackOrigins < 2)1352return false;13531354if (LazyWarningDebugLocationCount.empty())1355for (const auto &I : InstrumentationList)1356++LazyWarningDebugLocationCount[I.OrigIns->getDebugLoc()];13571358return LazyWarningDebugLocationCount[DebugLoc] >= ClDisambiguateWarning;1359}13601361/// Helper function to insert a warning at IRB's current insert point.1362void insertWarningFn(IRBuilder<> &IRB, Value *Origin) {1363if (!Origin)1364Origin = (Value *)IRB.getInt32(0);1365assert(Origin->getType()->isIntegerTy());13661367if (shouldDisambiguateWarningLocation(IRB.getCurrentDebugLocation())) {1368// Try to create additional origin with debug info of the last origin1369// instruction. It may provide additional information to the user.1370if (Instruction *OI = dyn_cast_or_null<Instruction>(Origin)) {1371assert(MS.TrackOrigins);1372auto NewDebugLoc = OI->getDebugLoc();1373// Origin update with missing or the same debug location provides no1374// additional value.1375if (NewDebugLoc && NewDebugLoc != IRB.getCurrentDebugLocation()) {1376// Insert update just before the check, so we call runtime only just1377// before the report.1378IRBuilder<> IRBOrigin(&*IRB.GetInsertPoint());1379IRBOrigin.SetCurrentDebugLocation(NewDebugLoc);1380Origin = updateOrigin(Origin, IRBOrigin);1381}1382}1383}13841385if (MS.CompileKernel || MS.TrackOrigins)1386IRB.CreateCall(MS.WarningFn, Origin)->setCannotMerge();1387else1388IRB.CreateCall(MS.WarningFn)->setCannotMerge();1389// FIXME: Insert UnreachableInst if !MS.Recover?1390// This may invalidate some of the following checks and needs to be done1391// at the very end.1392}13931394void materializeOneCheck(IRBuilder<> &IRB, Value *ConvertedShadow,1395Value *Origin) {1396const DataLayout &DL = F.getDataLayout();1397TypeSize TypeSizeInBits = DL.getTypeSizeInBits(ConvertedShadow->getType());1398unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits);1399if (instrumentWithCalls(ConvertedShadow) &&1400SizeIndex < kNumberOfAccessSizes && !MS.CompileKernel) {1401FunctionCallee Fn = MS.MaybeWarningFn[SizeIndex];1402// ZExt cannot convert between vector and scalar1403ConvertedShadow = convertShadowToScalar(ConvertedShadow, IRB);1404Value *ConvertedShadow2 =1405IRB.CreateZExt(ConvertedShadow, IRB.getIntNTy(8 * (1 << SizeIndex)));1406CallBase *CB = IRB.CreateCall(1407Fn, {ConvertedShadow2,1408MS.TrackOrigins && Origin ? Origin : (Value *)IRB.getInt32(0)});1409CB->addParamAttr(0, Attribute::ZExt);1410CB->addParamAttr(1, Attribute::ZExt);1411} else {1412Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp");1413Instruction *CheckTerm = SplitBlockAndInsertIfThen(1414Cmp, &*IRB.GetInsertPoint(),1415/* Unreachable */ !MS.Recover, MS.ColdCallWeights);14161417IRB.SetInsertPoint(CheckTerm);1418insertWarningFn(IRB, Origin);1419LLVM_DEBUG(dbgs() << " CHECK: " << *Cmp << "\n");1420}1421}14221423void materializeInstructionChecks(1424ArrayRef<ShadowOriginAndInsertPoint> InstructionChecks) {1425const DataLayout &DL = F.getDataLayout();1426// Disable combining in some cases. TrackOrigins checks each shadow to pick1427// correct origin.1428bool Combine = !MS.TrackOrigins;1429Instruction *Instruction = InstructionChecks.front().OrigIns;1430Value *Shadow = nullptr;1431for (const auto &ShadowData : InstructionChecks) {1432assert(ShadowData.OrigIns == Instruction);1433IRBuilder<> IRB(Instruction);14341435Value *ConvertedShadow = ShadowData.Shadow;14361437if (auto *ConstantShadow = dyn_cast<Constant>(ConvertedShadow)) {1438if (!ClCheckConstantShadow || ConstantShadow->isZeroValue()) {1439// Skip, value is initialized or const shadow is ignored.1440continue;1441}1442if (llvm::isKnownNonZero(ConvertedShadow, DL)) {1443// Report as the value is definitely uninitialized.1444insertWarningFn(IRB, ShadowData.Origin);1445if (!MS.Recover)1446return; // Always fail and stop here, not need to check the rest.1447// Skip entire instruction,1448continue;1449}1450// Fallback to runtime check, which still can be optimized out later.1451}14521453if (!Combine) {1454materializeOneCheck(IRB, ConvertedShadow, ShadowData.Origin);1455continue;1456}14571458if (!Shadow) {1459Shadow = ConvertedShadow;1460continue;1461}14621463Shadow = convertToBool(Shadow, IRB, "_mscmp");1464ConvertedShadow = convertToBool(ConvertedShadow, IRB, "_mscmp");1465Shadow = IRB.CreateOr(Shadow, ConvertedShadow, "_msor");1466}14671468if (Shadow) {1469assert(Combine);1470IRBuilder<> IRB(Instruction);1471materializeOneCheck(IRB, Shadow, nullptr);1472}1473}14741475void materializeChecks() {1476#ifndef NDEBUG1477// For assert below.1478SmallPtrSet<Instruction *, 16> Done;1479#endif14801481for (auto I = InstrumentationList.begin();1482I != InstrumentationList.end();) {1483auto OrigIns = I->OrigIns;1484// Checks are grouped by the original instruction. We call all1485// `insertShadowCheck` for an instruction at once.1486assert(Done.insert(OrigIns).second);1487auto J = std::find_if(I + 1, InstrumentationList.end(),1488[OrigIns](const ShadowOriginAndInsertPoint &R) {1489return OrigIns != R.OrigIns;1490});1491// Process all checks of instruction at once.1492materializeInstructionChecks(ArrayRef<ShadowOriginAndInsertPoint>(I, J));1493I = J;1494}14951496LLVM_DEBUG(dbgs() << "DONE:\n" << F);1497}14981499// Returns the last instruction in the new prologue1500void insertKmsanPrologue(IRBuilder<> &IRB) {1501Value *ContextState = IRB.CreateCall(MS.MsanGetContextStateFn, {});1502Constant *Zero = IRB.getInt32(0);1503MS.ParamTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,1504{Zero, IRB.getInt32(0)}, "param_shadow");1505MS.RetvalTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,1506{Zero, IRB.getInt32(1)}, "retval_shadow");1507MS.VAArgTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,1508{Zero, IRB.getInt32(2)}, "va_arg_shadow");1509MS.VAArgOriginTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,1510{Zero, IRB.getInt32(3)}, "va_arg_origin");1511MS.VAArgOverflowSizeTLS =1512IRB.CreateGEP(MS.MsanContextStateTy, ContextState,1513{Zero, IRB.getInt32(4)}, "va_arg_overflow_size");1514MS.ParamOriginTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,1515{Zero, IRB.getInt32(5)}, "param_origin");1516MS.RetvalOriginTLS =1517IRB.CreateGEP(MS.MsanContextStateTy, ContextState,1518{Zero, IRB.getInt32(6)}, "retval_origin");1519if (MS.TargetTriple.getArch() == Triple::systemz)1520MS.MsanMetadataAlloca = IRB.CreateAlloca(MS.MsanMetadata, 0u);1521}15221523/// Add MemorySanitizer instrumentation to a function.1524bool runOnFunction() {1525// Iterate all BBs in depth-first order and create shadow instructions1526// for all instructions (where applicable).1527// For PHI nodes we create dummy shadow PHIs which will be finalized later.1528for (BasicBlock *BB : depth_first(FnPrologueEnd->getParent()))1529visit(*BB);15301531// `visit` above only collects instructions. Process them after iterating1532// CFG to avoid requirement on CFG transformations.1533for (Instruction *I : Instructions)1534InstVisitor<MemorySanitizerVisitor>::visit(*I);15351536// Finalize PHI nodes.1537for (PHINode *PN : ShadowPHINodes) {1538PHINode *PNS = cast<PHINode>(getShadow(PN));1539PHINode *PNO = MS.TrackOrigins ? cast<PHINode>(getOrigin(PN)) : nullptr;1540size_t NumValues = PN->getNumIncomingValues();1541for (size_t v = 0; v < NumValues; v++) {1542PNS->addIncoming(getShadow(PN, v), PN->getIncomingBlock(v));1543if (PNO)1544PNO->addIncoming(getOrigin(PN, v), PN->getIncomingBlock(v));1545}1546}15471548VAHelper->finalizeInstrumentation();15491550// Poison llvm.lifetime.start intrinsics, if we haven't fallen back to1551// instrumenting only allocas.1552if (InstrumentLifetimeStart) {1553for (auto Item : LifetimeStartList) {1554instrumentAlloca(*Item.second, Item.first);1555AllocaSet.remove(Item.second);1556}1557}1558// Poison the allocas for which we didn't instrument the corresponding1559// lifetime intrinsics.1560for (AllocaInst *AI : AllocaSet)1561instrumentAlloca(*AI);15621563// Insert shadow value checks.1564materializeChecks();15651566// Delayed instrumentation of StoreInst.1567// This may not add new address checks.1568materializeStores();15691570return true;1571}15721573/// Compute the shadow type that corresponds to a given Value.1574Type *getShadowTy(Value *V) { return getShadowTy(V->getType()); }15751576/// Compute the shadow type that corresponds to a given Type.1577Type *getShadowTy(Type *OrigTy) {1578if (!OrigTy->isSized()) {1579return nullptr;1580}1581// For integer type, shadow is the same as the original type.1582// This may return weird-sized types like i1.1583if (IntegerType *IT = dyn_cast<IntegerType>(OrigTy))1584return IT;1585const DataLayout &DL = F.getDataLayout();1586if (VectorType *VT = dyn_cast<VectorType>(OrigTy)) {1587uint32_t EltSize = DL.getTypeSizeInBits(VT->getElementType());1588return VectorType::get(IntegerType::get(*MS.C, EltSize),1589VT->getElementCount());1590}1591if (ArrayType *AT = dyn_cast<ArrayType>(OrigTy)) {1592return ArrayType::get(getShadowTy(AT->getElementType()),1593AT->getNumElements());1594}1595if (StructType *ST = dyn_cast<StructType>(OrigTy)) {1596SmallVector<Type *, 4> Elements;1597for (unsigned i = 0, n = ST->getNumElements(); i < n; i++)1598Elements.push_back(getShadowTy(ST->getElementType(i)));1599StructType *Res = StructType::get(*MS.C, Elements, ST->isPacked());1600LLVM_DEBUG(dbgs() << "getShadowTy: " << *ST << " ===> " << *Res << "\n");1601return Res;1602}1603uint32_t TypeSize = DL.getTypeSizeInBits(OrigTy);1604return IntegerType::get(*MS.C, TypeSize);1605}16061607/// Extract combined shadow of struct elements as a bool1608Value *collapseStructShadow(StructType *Struct, Value *Shadow,1609IRBuilder<> &IRB) {1610Value *FalseVal = IRB.getIntN(/* width */ 1, /* value */ 0);1611Value *Aggregator = FalseVal;16121613for (unsigned Idx = 0; Idx < Struct->getNumElements(); Idx++) {1614// Combine by ORing together each element's bool shadow1615Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx);1616Value *ShadowBool = convertToBool(ShadowItem, IRB);16171618if (Aggregator != FalseVal)1619Aggregator = IRB.CreateOr(Aggregator, ShadowBool);1620else1621Aggregator = ShadowBool;1622}16231624return Aggregator;1625}16261627// Extract combined shadow of array elements1628Value *collapseArrayShadow(ArrayType *Array, Value *Shadow,1629IRBuilder<> &IRB) {1630if (!Array->getNumElements())1631return IRB.getIntN(/* width */ 1, /* value */ 0);16321633Value *FirstItem = IRB.CreateExtractValue(Shadow, 0);1634Value *Aggregator = convertShadowToScalar(FirstItem, IRB);16351636for (unsigned Idx = 1; Idx < Array->getNumElements(); Idx++) {1637Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx);1638Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB);1639Aggregator = IRB.CreateOr(Aggregator, ShadowInner);1640}1641return Aggregator;1642}16431644/// Convert a shadow value to it's flattened variant. The resulting1645/// shadow may not necessarily have the same bit width as the input1646/// value, but it will always be comparable to zero.1647Value *convertShadowToScalar(Value *V, IRBuilder<> &IRB) {1648if (StructType *Struct = dyn_cast<StructType>(V->getType()))1649return collapseStructShadow(Struct, V, IRB);1650if (ArrayType *Array = dyn_cast<ArrayType>(V->getType()))1651return collapseArrayShadow(Array, V, IRB);1652if (isa<VectorType>(V->getType())) {1653if (isa<ScalableVectorType>(V->getType()))1654return convertShadowToScalar(IRB.CreateOrReduce(V), IRB);1655unsigned BitWidth =1656V->getType()->getPrimitiveSizeInBits().getFixedValue();1657return IRB.CreateBitCast(V, IntegerType::get(*MS.C, BitWidth));1658}1659return V;1660}16611662// Convert a scalar value to an i1 by comparing with 01663Value *convertToBool(Value *V, IRBuilder<> &IRB, const Twine &name = "") {1664Type *VTy = V->getType();1665if (!VTy->isIntegerTy())1666return convertToBool(convertShadowToScalar(V, IRB), IRB, name);1667if (VTy->getIntegerBitWidth() == 1)1668// Just converting a bool to a bool, so do nothing.1669return V;1670return IRB.CreateICmpNE(V, ConstantInt::get(VTy, 0), name);1671}16721673Type *ptrToIntPtrType(Type *PtrTy) const {1674if (VectorType *VectTy = dyn_cast<VectorType>(PtrTy)) {1675return VectorType::get(ptrToIntPtrType(VectTy->getElementType()),1676VectTy->getElementCount());1677}1678assert(PtrTy->isIntOrPtrTy());1679return MS.IntptrTy;1680}16811682Type *getPtrToShadowPtrType(Type *IntPtrTy, Type *ShadowTy) const {1683if (VectorType *VectTy = dyn_cast<VectorType>(IntPtrTy)) {1684return VectorType::get(1685getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),1686VectTy->getElementCount());1687}1688assert(IntPtrTy == MS.IntptrTy);1689return PointerType::get(*MS.C, 0);1690}16911692Constant *constToIntPtr(Type *IntPtrTy, uint64_t C) const {1693if (VectorType *VectTy = dyn_cast<VectorType>(IntPtrTy)) {1694return ConstantVector::getSplat(1695VectTy->getElementCount(), constToIntPtr(VectTy->getElementType(), C));1696}1697assert(IntPtrTy == MS.IntptrTy);1698return ConstantInt::get(MS.IntptrTy, C);1699}17001701/// Compute the integer shadow offset that corresponds to a given1702/// application address.1703///1704/// Offset = (Addr & ~AndMask) ^ XorMask1705/// Addr can be a ptr or <N x ptr>. In both cases ShadowTy the shadow type of1706/// a single pointee.1707/// Returns <shadow_ptr, origin_ptr> or <<N x shadow_ptr>, <N x origin_ptr>>.1708Value *getShadowPtrOffset(Value *Addr, IRBuilder<> &IRB) {1709Type *IntptrTy = ptrToIntPtrType(Addr->getType());1710Value *OffsetLong = IRB.CreatePointerCast(Addr, IntptrTy);17111712if (uint64_t AndMask = MS.MapParams->AndMask)1713OffsetLong = IRB.CreateAnd(OffsetLong, constToIntPtr(IntptrTy, ~AndMask));17141715if (uint64_t XorMask = MS.MapParams->XorMask)1716OffsetLong = IRB.CreateXor(OffsetLong, constToIntPtr(IntptrTy, XorMask));1717return OffsetLong;1718}17191720/// Compute the shadow and origin addresses corresponding to a given1721/// application address.1722///1723/// Shadow = ShadowBase + Offset1724/// Origin = (OriginBase + Offset) & ~3ULL1725/// Addr can be a ptr or <N x ptr>. In both cases ShadowTy the shadow type of1726/// a single pointee.1727/// Returns <shadow_ptr, origin_ptr> or <<N x shadow_ptr>, <N x origin_ptr>>.1728std::pair<Value *, Value *>1729getShadowOriginPtrUserspace(Value *Addr, IRBuilder<> &IRB, Type *ShadowTy,1730MaybeAlign Alignment) {1731VectorType *VectTy = dyn_cast<VectorType>(Addr->getType());1732if (!VectTy) {1733assert(Addr->getType()->isPointerTy());1734} else {1735assert(VectTy->getElementType()->isPointerTy());1736}1737Type *IntptrTy = ptrToIntPtrType(Addr->getType());1738Value *ShadowOffset = getShadowPtrOffset(Addr, IRB);1739Value *ShadowLong = ShadowOffset;1740if (uint64_t ShadowBase = MS.MapParams->ShadowBase) {1741ShadowLong =1742IRB.CreateAdd(ShadowLong, constToIntPtr(IntptrTy, ShadowBase));1743}1744Value *ShadowPtr = IRB.CreateIntToPtr(1745ShadowLong, getPtrToShadowPtrType(IntptrTy, ShadowTy));17461747Value *OriginPtr = nullptr;1748if (MS.TrackOrigins) {1749Value *OriginLong = ShadowOffset;1750uint64_t OriginBase = MS.MapParams->OriginBase;1751if (OriginBase != 0)1752OriginLong =1753IRB.CreateAdd(OriginLong, constToIntPtr(IntptrTy, OriginBase));1754if (!Alignment || *Alignment < kMinOriginAlignment) {1755uint64_t Mask = kMinOriginAlignment.value() - 1;1756OriginLong = IRB.CreateAnd(OriginLong, constToIntPtr(IntptrTy, ~Mask));1757}1758OriginPtr = IRB.CreateIntToPtr(1759OriginLong, getPtrToShadowPtrType(IntptrTy, MS.OriginTy));1760}1761return std::make_pair(ShadowPtr, OriginPtr);1762}17631764template <typename... ArgsTy>1765Value *createMetadataCall(IRBuilder<> &IRB, FunctionCallee Callee,1766ArgsTy... Args) {1767if (MS.TargetTriple.getArch() == Triple::systemz) {1768IRB.CreateCall(Callee,1769{MS.MsanMetadataAlloca, std::forward<ArgsTy>(Args)...});1770return IRB.CreateLoad(MS.MsanMetadata, MS.MsanMetadataAlloca);1771}17721773return IRB.CreateCall(Callee, {std::forward<ArgsTy>(Args)...});1774}17751776std::pair<Value *, Value *> getShadowOriginPtrKernelNoVec(Value *Addr,1777IRBuilder<> &IRB,1778Type *ShadowTy,1779bool isStore) {1780Value *ShadowOriginPtrs;1781const DataLayout &DL = F.getDataLayout();1782TypeSize Size = DL.getTypeStoreSize(ShadowTy);17831784FunctionCallee Getter = MS.getKmsanShadowOriginAccessFn(isStore, Size);1785Value *AddrCast =1786IRB.CreatePointerCast(Addr, PointerType::get(IRB.getInt8Ty(), 0));1787if (Getter) {1788ShadowOriginPtrs = createMetadataCall(IRB, Getter, AddrCast);1789} else {1790Value *SizeVal = ConstantInt::get(MS.IntptrTy, Size);1791ShadowOriginPtrs = createMetadataCall(1792IRB,1793isStore ? MS.MsanMetadataPtrForStoreN : MS.MsanMetadataPtrForLoadN,1794AddrCast, SizeVal);1795}1796Value *ShadowPtr = IRB.CreateExtractValue(ShadowOriginPtrs, 0);1797ShadowPtr = IRB.CreatePointerCast(ShadowPtr, PointerType::get(ShadowTy, 0));1798Value *OriginPtr = IRB.CreateExtractValue(ShadowOriginPtrs, 1);17991800return std::make_pair(ShadowPtr, OriginPtr);1801}18021803/// Addr can be a ptr or <N x ptr>. In both cases ShadowTy the shadow type of1804/// a single pointee.1805/// Returns <shadow_ptr, origin_ptr> or <<N x shadow_ptr>, <N x origin_ptr>>.1806std::pair<Value *, Value *> getShadowOriginPtrKernel(Value *Addr,1807IRBuilder<> &IRB,1808Type *ShadowTy,1809bool isStore) {1810VectorType *VectTy = dyn_cast<VectorType>(Addr->getType());1811if (!VectTy) {1812assert(Addr->getType()->isPointerTy());1813return getShadowOriginPtrKernelNoVec(Addr, IRB, ShadowTy, isStore);1814}18151816// TODO: Support callbacs with vectors of addresses.1817unsigned NumElements = cast<FixedVectorType>(VectTy)->getNumElements();1818Value *ShadowPtrs = ConstantInt::getNullValue(1819FixedVectorType::get(IRB.getPtrTy(), NumElements));1820Value *OriginPtrs = nullptr;1821if (MS.TrackOrigins)1822OriginPtrs = ConstantInt::getNullValue(1823FixedVectorType::get(IRB.getPtrTy(), NumElements));1824for (unsigned i = 0; i < NumElements; ++i) {1825Value *OneAddr =1826IRB.CreateExtractElement(Addr, ConstantInt::get(IRB.getInt32Ty(), i));1827auto [ShadowPtr, OriginPtr] =1828getShadowOriginPtrKernelNoVec(OneAddr, IRB, ShadowTy, isStore);18291830ShadowPtrs = IRB.CreateInsertElement(1831ShadowPtrs, ShadowPtr, ConstantInt::get(IRB.getInt32Ty(), i));1832if (MS.TrackOrigins)1833OriginPtrs = IRB.CreateInsertElement(1834OriginPtrs, OriginPtr, ConstantInt::get(IRB.getInt32Ty(), i));1835}1836return {ShadowPtrs, OriginPtrs};1837}18381839std::pair<Value *, Value *> getShadowOriginPtr(Value *Addr, IRBuilder<> &IRB,1840Type *ShadowTy,1841MaybeAlign Alignment,1842bool isStore) {1843if (MS.CompileKernel)1844return getShadowOriginPtrKernel(Addr, IRB, ShadowTy, isStore);1845return getShadowOriginPtrUserspace(Addr, IRB, ShadowTy, Alignment);1846}18471848/// Compute the shadow address for a given function argument.1849///1850/// Shadow = ParamTLS+ArgOffset.1851Value *getShadowPtrForArgument(IRBuilder<> &IRB, int ArgOffset) {1852Value *Base = IRB.CreatePointerCast(MS.ParamTLS, MS.IntptrTy);1853if (ArgOffset)1854Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));1855return IRB.CreateIntToPtr(Base, IRB.getPtrTy(0), "_msarg");1856}18571858/// Compute the origin address for a given function argument.1859Value *getOriginPtrForArgument(IRBuilder<> &IRB, int ArgOffset) {1860if (!MS.TrackOrigins)1861return nullptr;1862Value *Base = IRB.CreatePointerCast(MS.ParamOriginTLS, MS.IntptrTy);1863if (ArgOffset)1864Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));1865return IRB.CreateIntToPtr(Base, IRB.getPtrTy(0), "_msarg_o");1866}18671868/// Compute the shadow address for a retval.1869Value *getShadowPtrForRetval(IRBuilder<> &IRB) {1870return IRB.CreatePointerCast(MS.RetvalTLS, IRB.getPtrTy(0), "_msret");1871}18721873/// Compute the origin address for a retval.1874Value *getOriginPtrForRetval() {1875// We keep a single origin for the entire retval. Might be too optimistic.1876return MS.RetvalOriginTLS;1877}18781879/// Set SV to be the shadow value for V.1880void setShadow(Value *V, Value *SV) {1881assert(!ShadowMap.count(V) && "Values may only have one shadow");1882ShadowMap[V] = PropagateShadow ? SV : getCleanShadow(V);1883}18841885/// Set Origin to be the origin value for V.1886void setOrigin(Value *V, Value *Origin) {1887if (!MS.TrackOrigins)1888return;1889assert(!OriginMap.count(V) && "Values may only have one origin");1890LLVM_DEBUG(dbgs() << "ORIGIN: " << *V << " ==> " << *Origin << "\n");1891OriginMap[V] = Origin;1892}18931894Constant *getCleanShadow(Type *OrigTy) {1895Type *ShadowTy = getShadowTy(OrigTy);1896if (!ShadowTy)1897return nullptr;1898return Constant::getNullValue(ShadowTy);1899}19001901/// Create a clean shadow value for a given value.1902///1903/// Clean shadow (all zeroes) means all bits of the value are defined1904/// (initialized).1905Constant *getCleanShadow(Value *V) { return getCleanShadow(V->getType()); }19061907/// Create a dirty shadow of a given shadow type.1908Constant *getPoisonedShadow(Type *ShadowTy) {1909assert(ShadowTy);1910if (isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy))1911return Constant::getAllOnesValue(ShadowTy);1912if (ArrayType *AT = dyn_cast<ArrayType>(ShadowTy)) {1913SmallVector<Constant *, 4> Vals(AT->getNumElements(),1914getPoisonedShadow(AT->getElementType()));1915return ConstantArray::get(AT, Vals);1916}1917if (StructType *ST = dyn_cast<StructType>(ShadowTy)) {1918SmallVector<Constant *, 4> Vals;1919for (unsigned i = 0, n = ST->getNumElements(); i < n; i++)1920Vals.push_back(getPoisonedShadow(ST->getElementType(i)));1921return ConstantStruct::get(ST, Vals);1922}1923llvm_unreachable("Unexpected shadow type");1924}19251926/// Create a dirty shadow for a given value.1927Constant *getPoisonedShadow(Value *V) {1928Type *ShadowTy = getShadowTy(V);1929if (!ShadowTy)1930return nullptr;1931return getPoisonedShadow(ShadowTy);1932}19331934/// Create a clean (zero) origin.1935Value *getCleanOrigin() { return Constant::getNullValue(MS.OriginTy); }19361937/// Get the shadow value for a given Value.1938///1939/// This function either returns the value set earlier with setShadow,1940/// or extracts if from ParamTLS (for function arguments).1941Value *getShadow(Value *V) {1942if (Instruction *I = dyn_cast<Instruction>(V)) {1943if (!PropagateShadow || I->getMetadata(LLVMContext::MD_nosanitize))1944return getCleanShadow(V);1945// For instructions the shadow is already stored in the map.1946Value *Shadow = ShadowMap[V];1947if (!Shadow) {1948LLVM_DEBUG(dbgs() << "No shadow: " << *V << "\n" << *(I->getParent()));1949(void)I;1950assert(Shadow && "No shadow for a value");1951}1952return Shadow;1953}1954if (UndefValue *U = dyn_cast<UndefValue>(V)) {1955Value *AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)1956: getCleanShadow(V);1957LLVM_DEBUG(dbgs() << "Undef: " << *U << " ==> " << *AllOnes << "\n");1958(void)U;1959return AllOnes;1960}1961if (Argument *A = dyn_cast<Argument>(V)) {1962// For arguments we compute the shadow on demand and store it in the map.1963Value *&ShadowPtr = ShadowMap[V];1964if (ShadowPtr)1965return ShadowPtr;1966Function *F = A->getParent();1967IRBuilder<> EntryIRB(FnPrologueEnd);1968unsigned ArgOffset = 0;1969const DataLayout &DL = F->getDataLayout();1970for (auto &FArg : F->args()) {1971if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {1972LLVM_DEBUG(dbgs() << (FArg.getType()->isScalableTy()1973? "vscale not fully supported\n"1974: "Arg is not sized\n"));1975if (A == &FArg) {1976ShadowPtr = getCleanShadow(V);1977setOrigin(A, getCleanOrigin());1978break;1979}1980continue;1981}19821983unsigned Size = FArg.hasByValAttr()1984? DL.getTypeAllocSize(FArg.getParamByValType())1985: DL.getTypeAllocSize(FArg.getType());19861987if (A == &FArg) {1988bool Overflow = ArgOffset + Size > kParamTLSSize;1989if (FArg.hasByValAttr()) {1990// ByVal pointer itself has clean shadow. We copy the actual1991// argument shadow to the underlying memory.1992// Figure out maximal valid memcpy alignment.1993const Align ArgAlign = DL.getValueOrABITypeAlignment(1994FArg.getParamAlign(), FArg.getParamByValType());1995Value *CpShadowPtr, *CpOriginPtr;1996std::tie(CpShadowPtr, CpOriginPtr) =1997getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign,1998/*isStore*/ true);1999if (!PropagateShadow || Overflow) {2000// ParamTLS overflow.2001EntryIRB.CreateMemSet(2002CpShadowPtr, Constant::getNullValue(EntryIRB.getInt8Ty()),2003Size, ArgAlign);2004} else {2005Value *Base = getShadowPtrForArgument(EntryIRB, ArgOffset);2006const Align CopyAlign = std::min(ArgAlign, kShadowTLSAlignment);2007Value *Cpy = EntryIRB.CreateMemCpy(CpShadowPtr, CopyAlign, Base,2008CopyAlign, Size);2009LLVM_DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n");2010(void)Cpy;20112012if (MS.TrackOrigins) {2013Value *OriginPtr =2014getOriginPtrForArgument(EntryIRB, ArgOffset);2015// FIXME: OriginSize should be:2016// alignTo(V % kMinOriginAlignment + Size, kMinOriginAlignment)2017unsigned OriginSize = alignTo(Size, kMinOriginAlignment);2018EntryIRB.CreateMemCpy(2019CpOriginPtr,2020/* by getShadowOriginPtr */ kMinOriginAlignment, OriginPtr,2021/* by origin_tls[ArgOffset] */ kMinOriginAlignment,2022OriginSize);2023}2024}2025}20262027if (!PropagateShadow || Overflow || FArg.hasByValAttr() ||2028(MS.EagerChecks && FArg.hasAttribute(Attribute::NoUndef))) {2029ShadowPtr = getCleanShadow(V);2030setOrigin(A, getCleanOrigin());2031} else {2032// Shadow over TLS2033Value *Base = getShadowPtrForArgument(EntryIRB, ArgOffset);2034ShadowPtr = EntryIRB.CreateAlignedLoad(getShadowTy(&FArg), Base,2035kShadowTLSAlignment);2036if (MS.TrackOrigins) {2037Value *OriginPtr =2038getOriginPtrForArgument(EntryIRB, ArgOffset);2039setOrigin(A, EntryIRB.CreateLoad(MS.OriginTy, OriginPtr));2040}2041}2042LLVM_DEBUG(dbgs()2043<< " ARG: " << FArg << " ==> " << *ShadowPtr << "\n");2044break;2045}20462047ArgOffset += alignTo(Size, kShadowTLSAlignment);2048}2049assert(ShadowPtr && "Could not find shadow for an argument");2050return ShadowPtr;2051}2052// For everything else the shadow is zero.2053return getCleanShadow(V);2054}20552056/// Get the shadow for i-th argument of the instruction I.2057Value *getShadow(Instruction *I, int i) {2058return getShadow(I->getOperand(i));2059}20602061/// Get the origin for a value.2062Value *getOrigin(Value *V) {2063if (!MS.TrackOrigins)2064return nullptr;2065if (!PropagateShadow || isa<Constant>(V) || isa<InlineAsm>(V))2066return getCleanOrigin();2067assert((isa<Instruction>(V) || isa<Argument>(V)) &&2068"Unexpected value type in getOrigin()");2069if (Instruction *I = dyn_cast<Instruction>(V)) {2070if (I->getMetadata(LLVMContext::MD_nosanitize))2071return getCleanOrigin();2072}2073Value *Origin = OriginMap[V];2074assert(Origin && "Missing origin");2075return Origin;2076}20772078/// Get the origin for i-th argument of the instruction I.2079Value *getOrigin(Instruction *I, int i) {2080return getOrigin(I->getOperand(i));2081}20822083/// Remember the place where a shadow check should be inserted.2084///2085/// This location will be later instrumented with a check that will print a2086/// UMR warning in runtime if the shadow value is not 0.2087void insertShadowCheck(Value *Shadow, Value *Origin, Instruction *OrigIns) {2088assert(Shadow);2089if (!InsertChecks)2090return;20912092if (!DebugCounter::shouldExecute(DebugInsertCheck)) {2093LLVM_DEBUG(dbgs() << "Skipping check of " << *Shadow << " before "2094<< *OrigIns << "\n");2095return;2096}2097#ifndef NDEBUG2098Type *ShadowTy = Shadow->getType();2099assert((isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy) ||2100isa<StructType>(ShadowTy) || isa<ArrayType>(ShadowTy)) &&2101"Can only insert checks for integer, vector, and aggregate shadow "2102"types");2103#endif2104InstrumentationList.push_back(2105ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));2106}21072108/// Remember the place where a shadow check should be inserted.2109///2110/// This location will be later instrumented with a check that will print a2111/// UMR warning in runtime if the value is not fully defined.2112void insertShadowCheck(Value *Val, Instruction *OrigIns) {2113assert(Val);2114Value *Shadow, *Origin;2115if (ClCheckConstantShadow) {2116Shadow = getShadow(Val);2117if (!Shadow)2118return;2119Origin = getOrigin(Val);2120} else {2121Shadow = dyn_cast_or_null<Instruction>(getShadow(Val));2122if (!Shadow)2123return;2124Origin = dyn_cast_or_null<Instruction>(getOrigin(Val));2125}2126insertShadowCheck(Shadow, Origin, OrigIns);2127}21282129AtomicOrdering addReleaseOrdering(AtomicOrdering a) {2130switch (a) {2131case AtomicOrdering::NotAtomic:2132return AtomicOrdering::NotAtomic;2133case AtomicOrdering::Unordered:2134case AtomicOrdering::Monotonic:2135case AtomicOrdering::Release:2136return AtomicOrdering::Release;2137case AtomicOrdering::Acquire:2138case AtomicOrdering::AcquireRelease:2139return AtomicOrdering::AcquireRelease;2140case AtomicOrdering::SequentiallyConsistent:2141return AtomicOrdering::SequentiallyConsistent;2142}2143llvm_unreachable("Unknown ordering");2144}21452146Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB) {2147constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;2148uint32_t OrderingTable[NumOrderings] = {};21492150OrderingTable[(int)AtomicOrderingCABI::relaxed] =2151OrderingTable[(int)AtomicOrderingCABI::release] =2152(int)AtomicOrderingCABI::release;2153OrderingTable[(int)AtomicOrderingCABI::consume] =2154OrderingTable[(int)AtomicOrderingCABI::acquire] =2155OrderingTable[(int)AtomicOrderingCABI::acq_rel] =2156(int)AtomicOrderingCABI::acq_rel;2157OrderingTable[(int)AtomicOrderingCABI::seq_cst] =2158(int)AtomicOrderingCABI::seq_cst;21592160return ConstantDataVector::get(IRB.getContext(), OrderingTable);2161}21622163AtomicOrdering addAcquireOrdering(AtomicOrdering a) {2164switch (a) {2165case AtomicOrdering::NotAtomic:2166return AtomicOrdering::NotAtomic;2167case AtomicOrdering::Unordered:2168case AtomicOrdering::Monotonic:2169case AtomicOrdering::Acquire:2170return AtomicOrdering::Acquire;2171case AtomicOrdering::Release:2172case AtomicOrdering::AcquireRelease:2173return AtomicOrdering::AcquireRelease;2174case AtomicOrdering::SequentiallyConsistent:2175return AtomicOrdering::SequentiallyConsistent;2176}2177llvm_unreachable("Unknown ordering");2178}21792180Value *makeAddAcquireOrderingTable(IRBuilder<> &IRB) {2181constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;2182uint32_t OrderingTable[NumOrderings] = {};21832184OrderingTable[(int)AtomicOrderingCABI::relaxed] =2185OrderingTable[(int)AtomicOrderingCABI::acquire] =2186OrderingTable[(int)AtomicOrderingCABI::consume] =2187(int)AtomicOrderingCABI::acquire;2188OrderingTable[(int)AtomicOrderingCABI::release] =2189OrderingTable[(int)AtomicOrderingCABI::acq_rel] =2190(int)AtomicOrderingCABI::acq_rel;2191OrderingTable[(int)AtomicOrderingCABI::seq_cst] =2192(int)AtomicOrderingCABI::seq_cst;21932194return ConstantDataVector::get(IRB.getContext(), OrderingTable);2195}21962197// ------------------- Visitors.2198using InstVisitor<MemorySanitizerVisitor>::visit;2199void visit(Instruction &I) {2200if (I.getMetadata(LLVMContext::MD_nosanitize))2201return;2202// Don't want to visit if we're in the prologue2203if (isInPrologue(I))2204return;2205if (!DebugCounter::shouldExecute(DebugInstrumentInstruction)) {2206LLVM_DEBUG(dbgs() << "Skipping instruction: " << I << "\n");2207// We still need to set the shadow and origin to clean values.2208setShadow(&I, getCleanShadow(&I));2209setOrigin(&I, getCleanOrigin());2210return;2211}22122213Instructions.push_back(&I);2214}22152216/// Instrument LoadInst2217///2218/// Loads the corresponding shadow and (optionally) origin.2219/// Optionally, checks that the load address is fully defined.2220void visitLoadInst(LoadInst &I) {2221assert(I.getType()->isSized() && "Load type must have size");2222assert(!I.getMetadata(LLVMContext::MD_nosanitize));2223NextNodeIRBuilder IRB(&I);2224Type *ShadowTy = getShadowTy(&I);2225Value *Addr = I.getPointerOperand();2226Value *ShadowPtr = nullptr, *OriginPtr = nullptr;2227const Align Alignment = I.getAlign();2228if (PropagateShadow) {2229std::tie(ShadowPtr, OriginPtr) =2230getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment, /*isStore*/ false);2231setShadow(&I,2232IRB.CreateAlignedLoad(ShadowTy, ShadowPtr, Alignment, "_msld"));2233} else {2234setShadow(&I, getCleanShadow(&I));2235}22362237if (ClCheckAccessAddress)2238insertShadowCheck(I.getPointerOperand(), &I);22392240if (I.isAtomic())2241I.setOrdering(addAcquireOrdering(I.getOrdering()));22422243if (MS.TrackOrigins) {2244if (PropagateShadow) {2245const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);2246setOrigin(2247&I, IRB.CreateAlignedLoad(MS.OriginTy, OriginPtr, OriginAlignment));2248} else {2249setOrigin(&I, getCleanOrigin());2250}2251}2252}22532254/// Instrument StoreInst2255///2256/// Stores the corresponding shadow and (optionally) origin.2257/// Optionally, checks that the store address is fully defined.2258void visitStoreInst(StoreInst &I) {2259StoreList.push_back(&I);2260if (ClCheckAccessAddress)2261insertShadowCheck(I.getPointerOperand(), &I);2262}22632264void handleCASOrRMW(Instruction &I) {2265assert(isa<AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I));22662267IRBuilder<> IRB(&I);2268Value *Addr = I.getOperand(0);2269Value *Val = I.getOperand(1);2270Value *ShadowPtr = getShadowOriginPtr(Addr, IRB, getShadowTy(Val), Align(1),2271/*isStore*/ true)2272.first;22732274if (ClCheckAccessAddress)2275insertShadowCheck(Addr, &I);22762277// Only test the conditional argument of cmpxchg instruction.2278// The other argument can potentially be uninitialized, but we can not2279// detect this situation reliably without possible false positives.2280if (isa<AtomicCmpXchgInst>(I))2281insertShadowCheck(Val, &I);22822283IRB.CreateStore(getCleanShadow(Val), ShadowPtr);22842285setShadow(&I, getCleanShadow(&I));2286setOrigin(&I, getCleanOrigin());2287}22882289void visitAtomicRMWInst(AtomicRMWInst &I) {2290handleCASOrRMW(I);2291I.setOrdering(addReleaseOrdering(I.getOrdering()));2292}22932294void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {2295handleCASOrRMW(I);2296I.setSuccessOrdering(addReleaseOrdering(I.getSuccessOrdering()));2297}22982299// Vector manipulation.2300void visitExtractElementInst(ExtractElementInst &I) {2301insertShadowCheck(I.getOperand(1), &I);2302IRBuilder<> IRB(&I);2303setShadow(&I, IRB.CreateExtractElement(getShadow(&I, 0), I.getOperand(1),2304"_msprop"));2305setOrigin(&I, getOrigin(&I, 0));2306}23072308void visitInsertElementInst(InsertElementInst &I) {2309insertShadowCheck(I.getOperand(2), &I);2310IRBuilder<> IRB(&I);2311auto *Shadow0 = getShadow(&I, 0);2312auto *Shadow1 = getShadow(&I, 1);2313setShadow(&I, IRB.CreateInsertElement(Shadow0, Shadow1, I.getOperand(2),2314"_msprop"));2315setOriginForNaryOp(I);2316}23172318void visitShuffleVectorInst(ShuffleVectorInst &I) {2319IRBuilder<> IRB(&I);2320auto *Shadow0 = getShadow(&I, 0);2321auto *Shadow1 = getShadow(&I, 1);2322setShadow(&I, IRB.CreateShuffleVector(Shadow0, Shadow1, I.getShuffleMask(),2323"_msprop"));2324setOriginForNaryOp(I);2325}23262327// Casts.2328void visitSExtInst(SExtInst &I) {2329IRBuilder<> IRB(&I);2330setShadow(&I, IRB.CreateSExt(getShadow(&I, 0), I.getType(), "_msprop"));2331setOrigin(&I, getOrigin(&I, 0));2332}23332334void visitZExtInst(ZExtInst &I) {2335IRBuilder<> IRB(&I);2336setShadow(&I, IRB.CreateZExt(getShadow(&I, 0), I.getType(), "_msprop"));2337setOrigin(&I, getOrigin(&I, 0));2338}23392340void visitTruncInst(TruncInst &I) {2341IRBuilder<> IRB(&I);2342setShadow(&I, IRB.CreateTrunc(getShadow(&I, 0), I.getType(), "_msprop"));2343setOrigin(&I, getOrigin(&I, 0));2344}23452346void visitBitCastInst(BitCastInst &I) {2347// Special case: if this is the bitcast (there is exactly 1 allowed) between2348// a musttail call and a ret, don't instrument. New instructions are not2349// allowed after a musttail call.2350if (auto *CI = dyn_cast<CallInst>(I.getOperand(0)))2351if (CI->isMustTailCall())2352return;2353IRBuilder<> IRB(&I);2354setShadow(&I, IRB.CreateBitCast(getShadow(&I, 0), getShadowTy(&I)));2355setOrigin(&I, getOrigin(&I, 0));2356}23572358void visitPtrToIntInst(PtrToIntInst &I) {2359IRBuilder<> IRB(&I);2360setShadow(&I, IRB.CreateIntCast(getShadow(&I, 0), getShadowTy(&I), false,2361"_msprop_ptrtoint"));2362setOrigin(&I, getOrigin(&I, 0));2363}23642365void visitIntToPtrInst(IntToPtrInst &I) {2366IRBuilder<> IRB(&I);2367setShadow(&I, IRB.CreateIntCast(getShadow(&I, 0), getShadowTy(&I), false,2368"_msprop_inttoptr"));2369setOrigin(&I, getOrigin(&I, 0));2370}23712372void visitFPToSIInst(CastInst &I) { handleShadowOr(I); }2373void visitFPToUIInst(CastInst &I) { handleShadowOr(I); }2374void visitSIToFPInst(CastInst &I) { handleShadowOr(I); }2375void visitUIToFPInst(CastInst &I) { handleShadowOr(I); }2376void visitFPExtInst(CastInst &I) { handleShadowOr(I); }2377void visitFPTruncInst(CastInst &I) { handleShadowOr(I); }23782379/// Propagate shadow for bitwise AND.2380///2381/// This code is exact, i.e. if, for example, a bit in the left argument2382/// is defined and 0, then neither the value not definedness of the2383/// corresponding bit in B don't affect the resulting shadow.2384void visitAnd(BinaryOperator &I) {2385IRBuilder<> IRB(&I);2386// "And" of 0 and a poisoned value results in unpoisoned value.2387// 1&1 => 1; 0&1 => 0; p&1 => p;2388// 1&0 => 0; 0&0 => 0; p&0 => 0;2389// 1&p => p; 0&p => 0; p&p => p;2390// S = (S1 & S2) | (V1 & S2) | (S1 & V2)2391Value *S1 = getShadow(&I, 0);2392Value *S2 = getShadow(&I, 1);2393Value *V1 = I.getOperand(0);2394Value *V2 = I.getOperand(1);2395if (V1->getType() != S1->getType()) {2396V1 = IRB.CreateIntCast(V1, S1->getType(), false);2397V2 = IRB.CreateIntCast(V2, S2->getType(), false);2398}2399Value *S1S2 = IRB.CreateAnd(S1, S2);2400Value *V1S2 = IRB.CreateAnd(V1, S2);2401Value *S1V2 = IRB.CreateAnd(S1, V2);2402setShadow(&I, IRB.CreateOr({S1S2, V1S2, S1V2}));2403setOriginForNaryOp(I);2404}24052406void visitOr(BinaryOperator &I) {2407IRBuilder<> IRB(&I);2408// "Or" of 1 and a poisoned value results in unpoisoned value.2409// 1|1 => 1; 0|1 => 1; p|1 => 1;2410// 1|0 => 1; 0|0 => 0; p|0 => p;2411// 1|p => 1; 0|p => p; p|p => p;2412// S = (S1 & S2) | (~V1 & S2) | (S1 & ~V2)2413Value *S1 = getShadow(&I, 0);2414Value *S2 = getShadow(&I, 1);2415Value *V1 = IRB.CreateNot(I.getOperand(0));2416Value *V2 = IRB.CreateNot(I.getOperand(1));2417if (V1->getType() != S1->getType()) {2418V1 = IRB.CreateIntCast(V1, S1->getType(), false);2419V2 = IRB.CreateIntCast(V2, S2->getType(), false);2420}2421Value *S1S2 = IRB.CreateAnd(S1, S2);2422Value *V1S2 = IRB.CreateAnd(V1, S2);2423Value *S1V2 = IRB.CreateAnd(S1, V2);2424setShadow(&I, IRB.CreateOr({S1S2, V1S2, S1V2}));2425setOriginForNaryOp(I);2426}24272428/// Default propagation of shadow and/or origin.2429///2430/// This class implements the general case of shadow propagation, used in all2431/// cases where we don't know and/or don't care about what the operation2432/// actually does. It converts all input shadow values to a common type2433/// (extending or truncating as necessary), and bitwise OR's them.2434///2435/// This is much cheaper than inserting checks (i.e. requiring inputs to be2436/// fully initialized), and less prone to false positives.2437///2438/// This class also implements the general case of origin propagation. For a2439/// Nary operation, result origin is set to the origin of an argument that is2440/// not entirely initialized. If there is more than one such arguments, the2441/// rightmost of them is picked. It does not matter which one is picked if all2442/// arguments are initialized.2443template <bool CombineShadow> class Combiner {2444Value *Shadow = nullptr;2445Value *Origin = nullptr;2446IRBuilder<> &IRB;2447MemorySanitizerVisitor *MSV;24482449public:2450Combiner(MemorySanitizerVisitor *MSV, IRBuilder<> &IRB)2451: IRB(IRB), MSV(MSV) {}24522453/// Add a pair of shadow and origin values to the mix.2454Combiner &Add(Value *OpShadow, Value *OpOrigin) {2455if (CombineShadow) {2456assert(OpShadow);2457if (!Shadow)2458Shadow = OpShadow;2459else {2460OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());2461Shadow = IRB.CreateOr(Shadow, OpShadow, "_msprop");2462}2463}24642465if (MSV->MS.TrackOrigins) {2466assert(OpOrigin);2467if (!Origin) {2468Origin = OpOrigin;2469} else {2470Constant *ConstOrigin = dyn_cast<Constant>(OpOrigin);2471// No point in adding something that might result in 0 origin value.2472if (!ConstOrigin || !ConstOrigin->isNullValue()) {2473Value *Cond = MSV->convertToBool(OpShadow, IRB);2474Origin = IRB.CreateSelect(Cond, OpOrigin, Origin);2475}2476}2477}2478return *this;2479}24802481/// Add an application value to the mix.2482Combiner &Add(Value *V) {2483Value *OpShadow = MSV->getShadow(V);2484Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) : nullptr;2485return Add(OpShadow, OpOrigin);2486}24872488/// Set the current combined values as the given instruction's shadow2489/// and origin.2490void Done(Instruction *I) {2491if (CombineShadow) {2492assert(Shadow);2493Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(I));2494MSV->setShadow(I, Shadow);2495}2496if (MSV->MS.TrackOrigins) {2497assert(Origin);2498MSV->setOrigin(I, Origin);2499}2500}25012502/// Store the current combined value at the specified origin2503/// location.2504void DoneAndStoreOrigin(TypeSize TS, Value *OriginPtr) {2505if (MSV->MS.TrackOrigins) {2506assert(Origin);2507MSV->paintOrigin(IRB, Origin, OriginPtr, TS, kMinOriginAlignment);2508}2509}2510};25112512using ShadowAndOriginCombiner = Combiner<true>;2513using OriginCombiner = Combiner<false>;25142515/// Propagate origin for arbitrary operation.2516void setOriginForNaryOp(Instruction &I) {2517if (!MS.TrackOrigins)2518return;2519IRBuilder<> IRB(&I);2520OriginCombiner OC(this, IRB);2521for (Use &Op : I.operands())2522OC.Add(Op.get());2523OC.Done(&I);2524}25252526size_t VectorOrPrimitiveTypeSizeInBits(Type *Ty) {2527assert(!(Ty->isVectorTy() && Ty->getScalarType()->isPointerTy()) &&2528"Vector of pointers is not a valid shadow type");2529return Ty->isVectorTy() ? cast<FixedVectorType>(Ty)->getNumElements() *2530Ty->getScalarSizeInBits()2531: Ty->getPrimitiveSizeInBits();2532}25332534/// Cast between two shadow types, extending or truncating as2535/// necessary.2536Value *CreateShadowCast(IRBuilder<> &IRB, Value *V, Type *dstTy,2537bool Signed = false) {2538Type *srcTy = V->getType();2539if (srcTy == dstTy)2540return V;2541size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);2542size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);2543if (srcSizeInBits > 1 && dstSizeInBits == 1)2544return IRB.CreateICmpNE(V, getCleanShadow(V));25452546if (dstTy->isIntegerTy() && srcTy->isIntegerTy())2547return IRB.CreateIntCast(V, dstTy, Signed);2548if (dstTy->isVectorTy() && srcTy->isVectorTy() &&2549cast<VectorType>(dstTy)->getElementCount() ==2550cast<VectorType>(srcTy)->getElementCount())2551return IRB.CreateIntCast(V, dstTy, Signed);2552Value *V1 = IRB.CreateBitCast(V, Type::getIntNTy(*MS.C, srcSizeInBits));2553Value *V2 =2554IRB.CreateIntCast(V1, Type::getIntNTy(*MS.C, dstSizeInBits), Signed);2555return IRB.CreateBitCast(V2, dstTy);2556// TODO: handle struct types.2557}25582559/// Cast an application value to the type of its own shadow.2560Value *CreateAppToShadowCast(IRBuilder<> &IRB, Value *V) {2561Type *ShadowTy = getShadowTy(V);2562if (V->getType() == ShadowTy)2563return V;2564if (V->getType()->isPtrOrPtrVectorTy())2565return IRB.CreatePtrToInt(V, ShadowTy);2566else2567return IRB.CreateBitCast(V, ShadowTy);2568}25692570/// Propagate shadow for arbitrary operation.2571void handleShadowOr(Instruction &I) {2572IRBuilder<> IRB(&I);2573ShadowAndOriginCombiner SC(this, IRB);2574for (Use &Op : I.operands())2575SC.Add(Op.get());2576SC.Done(&I);2577}25782579void visitFNeg(UnaryOperator &I) { handleShadowOr(I); }25802581// Handle multiplication by constant.2582//2583// Handle a special case of multiplication by constant that may have one or2584// more zeros in the lower bits. This makes corresponding number of lower bits2585// of the result zero as well. We model it by shifting the other operand2586// shadow left by the required number of bits. Effectively, we transform2587// (X * (A * 2**B)) to ((X << B) * A) and instrument (X << B) as (Sx << B).2588// We use multiplication by 2**N instead of shift to cover the case of2589// multiplication by 0, which may occur in some elements of a vector operand.2590void handleMulByConstant(BinaryOperator &I, Constant *ConstArg,2591Value *OtherArg) {2592Constant *ShadowMul;2593Type *Ty = ConstArg->getType();2594if (auto *VTy = dyn_cast<VectorType>(Ty)) {2595unsigned NumElements = cast<FixedVectorType>(VTy)->getNumElements();2596Type *EltTy = VTy->getElementType();2597SmallVector<Constant *, 16> Elements;2598for (unsigned Idx = 0; Idx < NumElements; ++Idx) {2599if (ConstantInt *Elt =2600dyn_cast<ConstantInt>(ConstArg->getAggregateElement(Idx))) {2601const APInt &V = Elt->getValue();2602APInt V2 = APInt(V.getBitWidth(), 1) << V.countr_zero();2603Elements.push_back(ConstantInt::get(EltTy, V2));2604} else {2605Elements.push_back(ConstantInt::get(EltTy, 1));2606}2607}2608ShadowMul = ConstantVector::get(Elements);2609} else {2610if (ConstantInt *Elt = dyn_cast<ConstantInt>(ConstArg)) {2611const APInt &V = Elt->getValue();2612APInt V2 = APInt(V.getBitWidth(), 1) << V.countr_zero();2613ShadowMul = ConstantInt::get(Ty, V2);2614} else {2615ShadowMul = ConstantInt::get(Ty, 1);2616}2617}26182619IRBuilder<> IRB(&I);2620setShadow(&I,2621IRB.CreateMul(getShadow(OtherArg), ShadowMul, "msprop_mul_cst"));2622setOrigin(&I, getOrigin(OtherArg));2623}26242625void visitMul(BinaryOperator &I) {2626Constant *constOp0 = dyn_cast<Constant>(I.getOperand(0));2627Constant *constOp1 = dyn_cast<Constant>(I.getOperand(1));2628if (constOp0 && !constOp1)2629handleMulByConstant(I, constOp0, I.getOperand(1));2630else if (constOp1 && !constOp0)2631handleMulByConstant(I, constOp1, I.getOperand(0));2632else2633handleShadowOr(I);2634}26352636void visitFAdd(BinaryOperator &I) { handleShadowOr(I); }2637void visitFSub(BinaryOperator &I) { handleShadowOr(I); }2638void visitFMul(BinaryOperator &I) { handleShadowOr(I); }2639void visitAdd(BinaryOperator &I) { handleShadowOr(I); }2640void visitSub(BinaryOperator &I) { handleShadowOr(I); }2641void visitXor(BinaryOperator &I) { handleShadowOr(I); }26422643void handleIntegerDiv(Instruction &I) {2644IRBuilder<> IRB(&I);2645// Strict on the second argument.2646insertShadowCheck(I.getOperand(1), &I);2647setShadow(&I, getShadow(&I, 0));2648setOrigin(&I, getOrigin(&I, 0));2649}26502651void visitUDiv(BinaryOperator &I) { handleIntegerDiv(I); }2652void visitSDiv(BinaryOperator &I) { handleIntegerDiv(I); }2653void visitURem(BinaryOperator &I) { handleIntegerDiv(I); }2654void visitSRem(BinaryOperator &I) { handleIntegerDiv(I); }26552656// Floating point division is side-effect free. We can not require that the2657// divisor is fully initialized and must propagate shadow. See PR37523.2658void visitFDiv(BinaryOperator &I) { handleShadowOr(I); }2659void visitFRem(BinaryOperator &I) { handleShadowOr(I); }26602661/// Instrument == and != comparisons.2662///2663/// Sometimes the comparison result is known even if some of the bits of the2664/// arguments are not.2665void handleEqualityComparison(ICmpInst &I) {2666IRBuilder<> IRB(&I);2667Value *A = I.getOperand(0);2668Value *B = I.getOperand(1);2669Value *Sa = getShadow(A);2670Value *Sb = getShadow(B);26712672// Get rid of pointers and vectors of pointers.2673// For ints (and vectors of ints), types of A and Sa match,2674// and this is a no-op.2675A = IRB.CreatePointerCast(A, Sa->getType());2676B = IRB.CreatePointerCast(B, Sb->getType());26772678// A == B <==> (C = A^B) == 02679// A != B <==> (C = A^B) != 02680// Sc = Sa | Sb2681Value *C = IRB.CreateXor(A, B);2682Value *Sc = IRB.CreateOr(Sa, Sb);2683// Now dealing with i = (C == 0) comparison (or C != 0, does not matter now)2684// Result is defined if one of the following is true2685// * there is a defined 1 bit in C2686// * C is fully defined2687// Si = !(C & ~Sc) && Sc2688Value *Zero = Constant::getNullValue(Sc->getType());2689Value *MinusOne = Constant::getAllOnesValue(Sc->getType());2690Value *LHS = IRB.CreateICmpNE(Sc, Zero);2691Value *RHS =2692IRB.CreateICmpEQ(IRB.CreateAnd(IRB.CreateXor(Sc, MinusOne), C), Zero);2693Value *Si = IRB.CreateAnd(LHS, RHS);2694Si->setName("_msprop_icmp");2695setShadow(&I, Si);2696setOriginForNaryOp(I);2697}26982699/// Build the lowest possible value of V, taking into account V's2700/// uninitialized bits.2701Value *getLowestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,2702bool isSigned) {2703if (isSigned) {2704// Split shadow into sign bit and other bits.2705Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);2706Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);2707// Maximise the undefined shadow bit, minimize other undefined bits.2708return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaOtherBits)),2709SaSignBit);2710} else {2711// Minimize undefined bits.2712return IRB.CreateAnd(A, IRB.CreateNot(Sa));2713}2714}27152716/// Build the highest possible value of V, taking into account V's2717/// uninitialized bits.2718Value *getHighestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,2719bool isSigned) {2720if (isSigned) {2721// Split shadow into sign bit and other bits.2722Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);2723Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);2724// Minimise the undefined shadow bit, maximise other undefined bits.2725return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaSignBit)),2726SaOtherBits);2727} else {2728// Maximize undefined bits.2729return IRB.CreateOr(A, Sa);2730}2731}27322733/// Instrument relational comparisons.2734///2735/// This function does exact shadow propagation for all relational2736/// comparisons of integers, pointers and vectors of those.2737/// FIXME: output seems suboptimal when one of the operands is a constant2738void handleRelationalComparisonExact(ICmpInst &I) {2739IRBuilder<> IRB(&I);2740Value *A = I.getOperand(0);2741Value *B = I.getOperand(1);2742Value *Sa = getShadow(A);2743Value *Sb = getShadow(B);27442745// Get rid of pointers and vectors of pointers.2746// For ints (and vectors of ints), types of A and Sa match,2747// and this is a no-op.2748A = IRB.CreatePointerCast(A, Sa->getType());2749B = IRB.CreatePointerCast(B, Sb->getType());27502751// Let [a0, a1] be the interval of possible values of A, taking into account2752// its undefined bits. Let [b0, b1] be the interval of possible values of B.2753// Then (A cmp B) is defined iff (a0 cmp b1) == (a1 cmp b0).2754bool IsSigned = I.isSigned();2755Value *S1 = IRB.CreateICmp(I.getPredicate(),2756getLowestPossibleValue(IRB, A, Sa, IsSigned),2757getHighestPossibleValue(IRB, B, Sb, IsSigned));2758Value *S2 = IRB.CreateICmp(I.getPredicate(),2759getHighestPossibleValue(IRB, A, Sa, IsSigned),2760getLowestPossibleValue(IRB, B, Sb, IsSigned));2761Value *Si = IRB.CreateXor(S1, S2);2762setShadow(&I, Si);2763setOriginForNaryOp(I);2764}27652766/// Instrument signed relational comparisons.2767///2768/// Handle sign bit tests: x<0, x>=0, x<=-1, x>-1 by propagating the highest2769/// bit of the shadow. Everything else is delegated to handleShadowOr().2770void handleSignedRelationalComparison(ICmpInst &I) {2771Constant *constOp;2772Value *op = nullptr;2773CmpInst::Predicate pre;2774if ((constOp = dyn_cast<Constant>(I.getOperand(1)))) {2775op = I.getOperand(0);2776pre = I.getPredicate();2777} else if ((constOp = dyn_cast<Constant>(I.getOperand(0)))) {2778op = I.getOperand(1);2779pre = I.getSwappedPredicate();2780} else {2781handleShadowOr(I);2782return;2783}27842785if ((constOp->isNullValue() &&2786(pre == CmpInst::ICMP_SLT || pre == CmpInst::ICMP_SGE)) ||2787(constOp->isAllOnesValue() &&2788(pre == CmpInst::ICMP_SGT || pre == CmpInst::ICMP_SLE))) {2789IRBuilder<> IRB(&I);2790Value *Shadow = IRB.CreateICmpSLT(getShadow(op), getCleanShadow(op),2791"_msprop_icmp_s");2792setShadow(&I, Shadow);2793setOrigin(&I, getOrigin(op));2794} else {2795handleShadowOr(I);2796}2797}27982799void visitICmpInst(ICmpInst &I) {2800if (!ClHandleICmp) {2801handleShadowOr(I);2802return;2803}2804if (I.isEquality()) {2805handleEqualityComparison(I);2806return;2807}28082809assert(I.isRelational());2810if (ClHandleICmpExact) {2811handleRelationalComparisonExact(I);2812return;2813}2814if (I.isSigned()) {2815handleSignedRelationalComparison(I);2816return;2817}28182819assert(I.isUnsigned());2820if ((isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {2821handleRelationalComparisonExact(I);2822return;2823}28242825handleShadowOr(I);2826}28272828void visitFCmpInst(FCmpInst &I) { handleShadowOr(I); }28292830void handleShift(BinaryOperator &I) {2831IRBuilder<> IRB(&I);2832// If any of the S2 bits are poisoned, the whole thing is poisoned.2833// Otherwise perform the same shift on S1.2834Value *S1 = getShadow(&I, 0);2835Value *S2 = getShadow(&I, 1);2836Value *S2Conv =2837IRB.CreateSExt(IRB.CreateICmpNE(S2, getCleanShadow(S2)), S2->getType());2838Value *V2 = I.getOperand(1);2839Value *Shift = IRB.CreateBinOp(I.getOpcode(), S1, V2);2840setShadow(&I, IRB.CreateOr(Shift, S2Conv));2841setOriginForNaryOp(I);2842}28432844void visitShl(BinaryOperator &I) { handleShift(I); }2845void visitAShr(BinaryOperator &I) { handleShift(I); }2846void visitLShr(BinaryOperator &I) { handleShift(I); }28472848void handleFunnelShift(IntrinsicInst &I) {2849IRBuilder<> IRB(&I);2850// If any of the S2 bits are poisoned, the whole thing is poisoned.2851// Otherwise perform the same shift on S0 and S1.2852Value *S0 = getShadow(&I, 0);2853Value *S1 = getShadow(&I, 1);2854Value *S2 = getShadow(&I, 2);2855Value *S2Conv =2856IRB.CreateSExt(IRB.CreateICmpNE(S2, getCleanShadow(S2)), S2->getType());2857Value *V2 = I.getOperand(2);2858Function *Intrin = Intrinsic::getDeclaration(2859I.getModule(), I.getIntrinsicID(), S2Conv->getType());2860Value *Shift = IRB.CreateCall(Intrin, {S0, S1, V2});2861setShadow(&I, IRB.CreateOr(Shift, S2Conv));2862setOriginForNaryOp(I);2863}28642865/// Instrument llvm.memmove2866///2867/// At this point we don't know if llvm.memmove will be inlined or not.2868/// If we don't instrument it and it gets inlined,2869/// our interceptor will not kick in and we will lose the memmove.2870/// If we instrument the call here, but it does not get inlined,2871/// we will memove the shadow twice: which is bad in case2872/// of overlapping regions. So, we simply lower the intrinsic to a call.2873///2874/// Similar situation exists for memcpy and memset.2875void visitMemMoveInst(MemMoveInst &I) {2876getShadow(I.getArgOperand(1)); // Ensure shadow initialized2877IRBuilder<> IRB(&I);2878IRB.CreateCall(MS.MemmoveFn,2879{I.getArgOperand(0), I.getArgOperand(1),2880IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});2881I.eraseFromParent();2882}28832884/// Instrument memcpy2885///2886/// Similar to memmove: avoid copying shadow twice. This is somewhat2887/// unfortunate as it may slowdown small constant memcpys.2888/// FIXME: consider doing manual inline for small constant sizes and proper2889/// alignment.2890///2891/// Note: This also handles memcpy.inline, which promises no calls to external2892/// functions as an optimization. However, with instrumentation enabled this2893/// is difficult to promise; additionally, we know that the MSan runtime2894/// exists and provides __msan_memcpy(). Therefore, we assume that with2895/// instrumentation it's safe to turn memcpy.inline into a call to2896/// __msan_memcpy(). Should this be wrong, such as when implementing memcpy()2897/// itself, instrumentation should be disabled with the no_sanitize attribute.2898void visitMemCpyInst(MemCpyInst &I) {2899getShadow(I.getArgOperand(1)); // Ensure shadow initialized2900IRBuilder<> IRB(&I);2901IRB.CreateCall(MS.MemcpyFn,2902{I.getArgOperand(0), I.getArgOperand(1),2903IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});2904I.eraseFromParent();2905}29062907// Same as memcpy.2908void visitMemSetInst(MemSetInst &I) {2909IRBuilder<> IRB(&I);2910IRB.CreateCall(2911MS.MemsetFn,2912{I.getArgOperand(0),2913IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),2914IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});2915I.eraseFromParent();2916}29172918void visitVAStartInst(VAStartInst &I) { VAHelper->visitVAStartInst(I); }29192920void visitVACopyInst(VACopyInst &I) { VAHelper->visitVACopyInst(I); }29212922/// Handle vector store-like intrinsics.2923///2924/// Instrument intrinsics that look like a simple SIMD store: writes memory,2925/// has 1 pointer argument and 1 vector argument, returns void.2926bool handleVectorStoreIntrinsic(IntrinsicInst &I) {2927IRBuilder<> IRB(&I);2928Value *Addr = I.getArgOperand(0);2929Value *Shadow = getShadow(&I, 1);2930Value *ShadowPtr, *OriginPtr;29312932// We don't know the pointer alignment (could be unaligned SSE store!).2933// Have to assume to worst case.2934std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(2935Addr, IRB, Shadow->getType(), Align(1), /*isStore*/ true);2936IRB.CreateAlignedStore(Shadow, ShadowPtr, Align(1));29372938if (ClCheckAccessAddress)2939insertShadowCheck(Addr, &I);29402941// FIXME: factor out common code from materializeStores2942if (MS.TrackOrigins)2943IRB.CreateStore(getOrigin(&I, 1), OriginPtr);2944return true;2945}29462947/// Handle vector load-like intrinsics.2948///2949/// Instrument intrinsics that look like a simple SIMD load: reads memory,2950/// has 1 pointer argument, returns a vector.2951bool handleVectorLoadIntrinsic(IntrinsicInst &I) {2952IRBuilder<> IRB(&I);2953Value *Addr = I.getArgOperand(0);29542955Type *ShadowTy = getShadowTy(&I);2956Value *ShadowPtr = nullptr, *OriginPtr = nullptr;2957if (PropagateShadow) {2958// We don't know the pointer alignment (could be unaligned SSE load!).2959// Have to assume to worst case.2960const Align Alignment = Align(1);2961std::tie(ShadowPtr, OriginPtr) =2962getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment, /*isStore*/ false);2963setShadow(&I,2964IRB.CreateAlignedLoad(ShadowTy, ShadowPtr, Alignment, "_msld"));2965} else {2966setShadow(&I, getCleanShadow(&I));2967}29682969if (ClCheckAccessAddress)2970insertShadowCheck(Addr, &I);29712972if (MS.TrackOrigins) {2973if (PropagateShadow)2974setOrigin(&I, IRB.CreateLoad(MS.OriginTy, OriginPtr));2975else2976setOrigin(&I, getCleanOrigin());2977}2978return true;2979}29802981/// Handle (SIMD arithmetic)-like intrinsics.2982///2983/// Instrument intrinsics with any number of arguments of the same type,2984/// equal to the return type. The type should be simple (no aggregates or2985/// pointers; vectors are fine).2986/// Caller guarantees that this intrinsic does not access memory.2987bool maybeHandleSimpleNomemIntrinsic(IntrinsicInst &I) {2988Type *RetTy = I.getType();2989if (!(RetTy->isIntOrIntVectorTy() || RetTy->isFPOrFPVectorTy() ||2990RetTy->isX86_MMXTy()))2991return false;29922993unsigned NumArgOperands = I.arg_size();2994for (unsigned i = 0; i < NumArgOperands; ++i) {2995Type *Ty = I.getArgOperand(i)->getType();2996if (Ty != RetTy)2997return false;2998}29993000IRBuilder<> IRB(&I);3001ShadowAndOriginCombiner SC(this, IRB);3002for (unsigned i = 0; i < NumArgOperands; ++i)3003SC.Add(I.getArgOperand(i));3004SC.Done(&I);30053006return true;3007}30083009/// Heuristically instrument unknown intrinsics.3010///3011/// The main purpose of this code is to do something reasonable with all3012/// random intrinsics we might encounter, most importantly - SIMD intrinsics.3013/// We recognize several classes of intrinsics by their argument types and3014/// ModRefBehaviour and apply special instrumentation when we are reasonably3015/// sure that we know what the intrinsic does.3016///3017/// We special-case intrinsics where this approach fails. See llvm.bswap3018/// handling as an example of that.3019bool handleUnknownIntrinsic(IntrinsicInst &I) {3020unsigned NumArgOperands = I.arg_size();3021if (NumArgOperands == 0)3022return false;30233024if (NumArgOperands == 2 && I.getArgOperand(0)->getType()->isPointerTy() &&3025I.getArgOperand(1)->getType()->isVectorTy() &&3026I.getType()->isVoidTy() && !I.onlyReadsMemory()) {3027// This looks like a vector store.3028return handleVectorStoreIntrinsic(I);3029}30303031if (NumArgOperands == 1 && I.getArgOperand(0)->getType()->isPointerTy() &&3032I.getType()->isVectorTy() && I.onlyReadsMemory()) {3033// This looks like a vector load.3034return handleVectorLoadIntrinsic(I);3035}30363037if (I.doesNotAccessMemory())3038if (maybeHandleSimpleNomemIntrinsic(I))3039return true;30403041// FIXME: detect and handle SSE maskstore/maskload3042return false;3043}30443045void handleInvariantGroup(IntrinsicInst &I) {3046setShadow(&I, getShadow(&I, 0));3047setOrigin(&I, getOrigin(&I, 0));3048}30493050void handleLifetimeStart(IntrinsicInst &I) {3051if (!PoisonStack)3052return;3053AllocaInst *AI = llvm::findAllocaForValue(I.getArgOperand(1));3054if (!AI)3055InstrumentLifetimeStart = false;3056LifetimeStartList.push_back(std::make_pair(&I, AI));3057}30583059void handleBswap(IntrinsicInst &I) {3060IRBuilder<> IRB(&I);3061Value *Op = I.getArgOperand(0);3062Type *OpType = Op->getType();3063Function *BswapFunc = Intrinsic::getDeclaration(3064F.getParent(), Intrinsic::bswap, ArrayRef(&OpType, 1));3065setShadow(&I, IRB.CreateCall(BswapFunc, getShadow(Op)));3066setOrigin(&I, getOrigin(Op));3067}30683069void handleCountZeroes(IntrinsicInst &I) {3070IRBuilder<> IRB(&I);3071Value *Src = I.getArgOperand(0);30723073// Set the Output shadow based on input Shadow3074Value *BoolShadow = IRB.CreateIsNotNull(getShadow(Src), "_mscz_bs");30753076// If zero poison is requested, mix in with the shadow3077Constant *IsZeroPoison = cast<Constant>(I.getOperand(1));3078if (!IsZeroPoison->isZeroValue()) {3079Value *BoolZeroPoison = IRB.CreateIsNull(Src, "_mscz_bzp");3080BoolShadow = IRB.CreateOr(BoolShadow, BoolZeroPoison, "_mscz_bs");3081}30823083Value *OutputShadow =3084IRB.CreateSExt(BoolShadow, getShadowTy(Src), "_mscz_os");30853086setShadow(&I, OutputShadow);3087setOriginForNaryOp(I);3088}30893090// Instrument vector convert intrinsic.3091//3092// This function instruments intrinsics like cvtsi2ss:3093// %Out = int_xxx_cvtyyy(%ConvertOp)3094// or3095// %Out = int_xxx_cvtyyy(%CopyOp, %ConvertOp)3096// Intrinsic converts \p NumUsedElements elements of \p ConvertOp to the same3097// number \p Out elements, and (if has 2 arguments) copies the rest of the3098// elements from \p CopyOp.3099// In most cases conversion involves floating-point value which may trigger a3100// hardware exception when not fully initialized. For this reason we require3101// \p ConvertOp[0:NumUsedElements] to be fully initialized and trap otherwise.3102// We copy the shadow of \p CopyOp[NumUsedElements:] to \p3103// Out[NumUsedElements:]. This means that intrinsics without \p CopyOp always3104// return a fully initialized value.3105void handleVectorConvertIntrinsic(IntrinsicInst &I, int NumUsedElements,3106bool HasRoundingMode = false) {3107IRBuilder<> IRB(&I);3108Value *CopyOp, *ConvertOp;31093110assert((!HasRoundingMode ||3111isa<ConstantInt>(I.getArgOperand(I.arg_size() - 1))) &&3112"Invalid rounding mode");31133114switch (I.arg_size() - HasRoundingMode) {3115case 2:3116CopyOp = I.getArgOperand(0);3117ConvertOp = I.getArgOperand(1);3118break;3119case 1:3120ConvertOp = I.getArgOperand(0);3121CopyOp = nullptr;3122break;3123default:3124llvm_unreachable("Cvt intrinsic with unsupported number of arguments.");3125}31263127// The first *NumUsedElements* elements of ConvertOp are converted to the3128// same number of output elements. The rest of the output is copied from3129// CopyOp, or (if not available) filled with zeroes.3130// Combine shadow for elements of ConvertOp that are used in this operation,3131// and insert a check.3132// FIXME: consider propagating shadow of ConvertOp, at least in the case of3133// int->any conversion.3134Value *ConvertShadow = getShadow(ConvertOp);3135Value *AggShadow = nullptr;3136if (ConvertOp->getType()->isVectorTy()) {3137AggShadow = IRB.CreateExtractElement(3138ConvertShadow, ConstantInt::get(IRB.getInt32Ty(), 0));3139for (int i = 1; i < NumUsedElements; ++i) {3140Value *MoreShadow = IRB.CreateExtractElement(3141ConvertShadow, ConstantInt::get(IRB.getInt32Ty(), i));3142AggShadow = IRB.CreateOr(AggShadow, MoreShadow);3143}3144} else {3145AggShadow = ConvertShadow;3146}3147assert(AggShadow->getType()->isIntegerTy());3148insertShadowCheck(AggShadow, getOrigin(ConvertOp), &I);31493150// Build result shadow by zero-filling parts of CopyOp shadow that come from3151// ConvertOp.3152if (CopyOp) {3153assert(CopyOp->getType() == I.getType());3154assert(CopyOp->getType()->isVectorTy());3155Value *ResultShadow = getShadow(CopyOp);3156Type *EltTy = cast<VectorType>(ResultShadow->getType())->getElementType();3157for (int i = 0; i < NumUsedElements; ++i) {3158ResultShadow = IRB.CreateInsertElement(3159ResultShadow, ConstantInt::getNullValue(EltTy),3160ConstantInt::get(IRB.getInt32Ty(), i));3161}3162setShadow(&I, ResultShadow);3163setOrigin(&I, getOrigin(CopyOp));3164} else {3165setShadow(&I, getCleanShadow(&I));3166setOrigin(&I, getCleanOrigin());3167}3168}31693170// Given a scalar or vector, extract lower 64 bits (or less), and return all3171// zeroes if it is zero, and all ones otherwise.3172Value *Lower64ShadowExtend(IRBuilder<> &IRB, Value *S, Type *T) {3173if (S->getType()->isVectorTy())3174S = CreateShadowCast(IRB, S, IRB.getInt64Ty(), /* Signed */ true);3175assert(S->getType()->getPrimitiveSizeInBits() <= 64);3176Value *S2 = IRB.CreateICmpNE(S, getCleanShadow(S));3177return CreateShadowCast(IRB, S2, T, /* Signed */ true);3178}31793180// Given a vector, extract its first element, and return all3181// zeroes if it is zero, and all ones otherwise.3182Value *LowerElementShadowExtend(IRBuilder<> &IRB, Value *S, Type *T) {3183Value *S1 = IRB.CreateExtractElement(S, (uint64_t)0);3184Value *S2 = IRB.CreateICmpNE(S1, getCleanShadow(S1));3185return CreateShadowCast(IRB, S2, T, /* Signed */ true);3186}31873188Value *VariableShadowExtend(IRBuilder<> &IRB, Value *S) {3189Type *T = S->getType();3190assert(T->isVectorTy());3191Value *S2 = IRB.CreateICmpNE(S, getCleanShadow(S));3192return IRB.CreateSExt(S2, T);3193}31943195// Instrument vector shift intrinsic.3196//3197// This function instruments intrinsics like int_x86_avx2_psll_w.3198// Intrinsic shifts %In by %ShiftSize bits.3199// %ShiftSize may be a vector. In that case the lower 64 bits determine shift3200// size, and the rest is ignored. Behavior is defined even if shift size is3201// greater than register (or field) width.3202void handleVectorShiftIntrinsic(IntrinsicInst &I, bool Variable) {3203assert(I.arg_size() == 2);3204IRBuilder<> IRB(&I);3205// If any of the S2 bits are poisoned, the whole thing is poisoned.3206// Otherwise perform the same shift on S1.3207Value *S1 = getShadow(&I, 0);3208Value *S2 = getShadow(&I, 1);3209Value *S2Conv = Variable ? VariableShadowExtend(IRB, S2)3210: Lower64ShadowExtend(IRB, S2, getShadowTy(&I));3211Value *V1 = I.getOperand(0);3212Value *V2 = I.getOperand(1);3213Value *Shift = IRB.CreateCall(I.getFunctionType(), I.getCalledOperand(),3214{IRB.CreateBitCast(S1, V1->getType()), V2});3215Shift = IRB.CreateBitCast(Shift, getShadowTy(&I));3216setShadow(&I, IRB.CreateOr(Shift, S2Conv));3217setOriginForNaryOp(I);3218}32193220// Get an X86_MMX-sized vector type.3221Type *getMMXVectorTy(unsigned EltSizeInBits) {3222const unsigned X86_MMXSizeInBits = 64;3223assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&3224"Illegal MMX vector element size");3225return FixedVectorType::get(IntegerType::get(*MS.C, EltSizeInBits),3226X86_MMXSizeInBits / EltSizeInBits);3227}32283229// Returns a signed counterpart for an (un)signed-saturate-and-pack3230// intrinsic.3231Intrinsic::ID getSignedPackIntrinsic(Intrinsic::ID id) {3232switch (id) {3233case Intrinsic::x86_sse2_packsswb_128:3234case Intrinsic::x86_sse2_packuswb_128:3235return Intrinsic::x86_sse2_packsswb_128;32363237case Intrinsic::x86_sse2_packssdw_128:3238case Intrinsic::x86_sse41_packusdw:3239return Intrinsic::x86_sse2_packssdw_128;32403241case Intrinsic::x86_avx2_packsswb:3242case Intrinsic::x86_avx2_packuswb:3243return Intrinsic::x86_avx2_packsswb;32443245case Intrinsic::x86_avx2_packssdw:3246case Intrinsic::x86_avx2_packusdw:3247return Intrinsic::x86_avx2_packssdw;32483249case Intrinsic::x86_mmx_packsswb:3250case Intrinsic::x86_mmx_packuswb:3251return Intrinsic::x86_mmx_packsswb;32523253case Intrinsic::x86_mmx_packssdw:3254return Intrinsic::x86_mmx_packssdw;3255default:3256llvm_unreachable("unexpected intrinsic id");3257}3258}32593260// Instrument vector pack intrinsic.3261//3262// This function instruments intrinsics like x86_mmx_packsswb, that3263// packs elements of 2 input vectors into half as many bits with saturation.3264// Shadow is propagated with the signed variant of the same intrinsic applied3265// to sext(Sa != zeroinitializer), sext(Sb != zeroinitializer).3266// EltSizeInBits is used only for x86mmx arguments.3267void handleVectorPackIntrinsic(IntrinsicInst &I, unsigned EltSizeInBits = 0) {3268assert(I.arg_size() == 2);3269bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy();3270IRBuilder<> IRB(&I);3271Value *S1 = getShadow(&I, 0);3272Value *S2 = getShadow(&I, 1);3273assert(isX86_MMX || S1->getType()->isVectorTy());32743275// SExt and ICmpNE below must apply to individual elements of input vectors.3276// In case of x86mmx arguments, cast them to appropriate vector types and3277// back.3278Type *T = isX86_MMX ? getMMXVectorTy(EltSizeInBits) : S1->getType();3279if (isX86_MMX) {3280S1 = IRB.CreateBitCast(S1, T);3281S2 = IRB.CreateBitCast(S2, T);3282}3283Value *S1_ext =3284IRB.CreateSExt(IRB.CreateICmpNE(S1, Constant::getNullValue(T)), T);3285Value *S2_ext =3286IRB.CreateSExt(IRB.CreateICmpNE(S2, Constant::getNullValue(T)), T);3287if (isX86_MMX) {3288Type *X86_MMXTy = Type::getX86_MMXTy(*MS.C);3289S1_ext = IRB.CreateBitCast(S1_ext, X86_MMXTy);3290S2_ext = IRB.CreateBitCast(S2_ext, X86_MMXTy);3291}32923293Function *ShadowFn = Intrinsic::getDeclaration(3294F.getParent(), getSignedPackIntrinsic(I.getIntrinsicID()));32953296Value *S =3297IRB.CreateCall(ShadowFn, {S1_ext, S2_ext}, "_msprop_vector_pack");3298if (isX86_MMX)3299S = IRB.CreateBitCast(S, getShadowTy(&I));3300setShadow(&I, S);3301setOriginForNaryOp(I);3302}33033304// Convert `Mask` into `<n x i1>`.3305Constant *createDppMask(unsigned Width, unsigned Mask) {3306SmallVector<Constant *, 4> R(Width);3307for (auto &M : R) {3308M = ConstantInt::getBool(F.getContext(), Mask & 1);3309Mask >>= 1;3310}3311return ConstantVector::get(R);3312}33133314// Calculate output shadow as array of booleans `<n x i1>`, assuming if any3315// arg is poisoned, entire dot product is poisoned.3316Value *findDppPoisonedOutput(IRBuilder<> &IRB, Value *S, unsigned SrcMask,3317unsigned DstMask) {3318const unsigned Width =3319cast<FixedVectorType>(S->getType())->getNumElements();33203321S = IRB.CreateSelect(createDppMask(Width, SrcMask), S,3322Constant::getNullValue(S->getType()));3323Value *SElem = IRB.CreateOrReduce(S);3324Value *IsClean = IRB.CreateIsNull(SElem, "_msdpp");3325Value *DstMaskV = createDppMask(Width, DstMask);33263327return IRB.CreateSelect(3328IsClean, Constant::getNullValue(DstMaskV->getType()), DstMaskV);3329}33303331// See `Intel Intrinsics Guide` for `_dp_p*` instructions.3332//3333// 2 and 4 element versions produce single scalar of dot product, and then3334// puts it into elements of output vector, selected by 4 lowest bits of the3335// mask. Top 4 bits of the mask control which elements of input to use for dot3336// product.3337//3338// 8 element version mask still has only 4 bit for input, and 4 bit for output3339// mask. According to the spec it just operates as 4 element version on first3340// 4 elements of inputs and output, and then on last 4 elements of inputs and3341// output.3342void handleDppIntrinsic(IntrinsicInst &I) {3343IRBuilder<> IRB(&I);33443345Value *S0 = getShadow(&I, 0);3346Value *S1 = getShadow(&I, 1);3347Value *S = IRB.CreateOr(S0, S1);33483349const unsigned Width =3350cast<FixedVectorType>(S->getType())->getNumElements();3351assert(Width == 2 || Width == 4 || Width == 8);33523353const unsigned Mask = cast<ConstantInt>(I.getArgOperand(2))->getZExtValue();3354const unsigned SrcMask = Mask >> 4;3355const unsigned DstMask = Mask & 0xf;33563357// Calculate shadow as `<n x i1>`.3358Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);3359if (Width == 8) {3360// First 4 elements of shadow are already calculated. `makeDppShadow`3361// operats on 32 bit masks, so we can just shift masks, and repeat.3362SI1 = IRB.CreateOr(3363SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));3364}3365// Extend to real size of shadow, poisoning either all or none bits of an3366// element.3367S = IRB.CreateSExt(SI1, S->getType(), "_msdpp");33683369setShadow(&I, S);3370setOriginForNaryOp(I);3371}33723373Value *convertBlendvToSelectMask(IRBuilder<> &IRB, Value *C) {3374C = CreateAppToShadowCast(IRB, C);3375FixedVectorType *FVT = cast<FixedVectorType>(C->getType());3376unsigned ElSize = FVT->getElementType()->getPrimitiveSizeInBits();3377C = IRB.CreateAShr(C, ElSize - 1);3378FVT = FixedVectorType::get(IRB.getInt1Ty(), FVT->getNumElements());3379return IRB.CreateTrunc(C, FVT);3380}33813382// `blendv(f, t, c)` is effectively `select(c[top_bit], t, f)`.3383void handleBlendvIntrinsic(IntrinsicInst &I) {3384Value *C = I.getOperand(2);3385Value *T = I.getOperand(1);3386Value *F = I.getOperand(0);33873388Value *Sc = getShadow(&I, 2);3389Value *Oc = MS.TrackOrigins ? getOrigin(C) : nullptr;33903391{3392IRBuilder<> IRB(&I);3393// Extract top bit from condition and its shadow.3394C = convertBlendvToSelectMask(IRB, C);3395Sc = convertBlendvToSelectMask(IRB, Sc);33963397setShadow(C, Sc);3398setOrigin(C, Oc);3399}34003401handleSelectLikeInst(I, C, T, F);3402}34033404// Instrument sum-of-absolute-differences intrinsic.3405void handleVectorSadIntrinsic(IntrinsicInst &I) {3406const unsigned SignificantBitsPerResultElement = 16;3407bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy();3408Type *ResTy = isX86_MMX ? IntegerType::get(*MS.C, 64) : I.getType();3409unsigned ZeroBitsPerResultElement =3410ResTy->getScalarSizeInBits() - SignificantBitsPerResultElement;34113412IRBuilder<> IRB(&I);3413auto *Shadow0 = getShadow(&I, 0);3414auto *Shadow1 = getShadow(&I, 1);3415Value *S = IRB.CreateOr(Shadow0, Shadow1);3416S = IRB.CreateBitCast(S, ResTy);3417S = IRB.CreateSExt(IRB.CreateICmpNE(S, Constant::getNullValue(ResTy)),3418ResTy);3419S = IRB.CreateLShr(S, ZeroBitsPerResultElement);3420S = IRB.CreateBitCast(S, getShadowTy(&I));3421setShadow(&I, S);3422setOriginForNaryOp(I);3423}34243425// Instrument multiply-add intrinsic.3426void handleVectorPmaddIntrinsic(IntrinsicInst &I,3427unsigned EltSizeInBits = 0) {3428bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy();3429Type *ResTy = isX86_MMX ? getMMXVectorTy(EltSizeInBits * 2) : I.getType();3430IRBuilder<> IRB(&I);3431auto *Shadow0 = getShadow(&I, 0);3432auto *Shadow1 = getShadow(&I, 1);3433Value *S = IRB.CreateOr(Shadow0, Shadow1);3434S = IRB.CreateBitCast(S, ResTy);3435S = IRB.CreateSExt(IRB.CreateICmpNE(S, Constant::getNullValue(ResTy)),3436ResTy);3437S = IRB.CreateBitCast(S, getShadowTy(&I));3438setShadow(&I, S);3439setOriginForNaryOp(I);3440}34413442// Instrument compare-packed intrinsic.3443// Basically, an or followed by sext(icmp ne 0) to end up with all-zeros or3444// all-ones shadow.3445void handleVectorComparePackedIntrinsic(IntrinsicInst &I) {3446IRBuilder<> IRB(&I);3447Type *ResTy = getShadowTy(&I);3448auto *Shadow0 = getShadow(&I, 0);3449auto *Shadow1 = getShadow(&I, 1);3450Value *S0 = IRB.CreateOr(Shadow0, Shadow1);3451Value *S = IRB.CreateSExt(3452IRB.CreateICmpNE(S0, Constant::getNullValue(ResTy)), ResTy);3453setShadow(&I, S);3454setOriginForNaryOp(I);3455}34563457// Instrument compare-scalar intrinsic.3458// This handles both cmp* intrinsics which return the result in the first3459// element of a vector, and comi* which return the result as i32.3460void handleVectorCompareScalarIntrinsic(IntrinsicInst &I) {3461IRBuilder<> IRB(&I);3462auto *Shadow0 = getShadow(&I, 0);3463auto *Shadow1 = getShadow(&I, 1);3464Value *S0 = IRB.CreateOr(Shadow0, Shadow1);3465Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&I));3466setShadow(&I, S);3467setOriginForNaryOp(I);3468}34693470// Instrument generic vector reduction intrinsics3471// by ORing together all their fields.3472void handleVectorReduceIntrinsic(IntrinsicInst &I) {3473IRBuilder<> IRB(&I);3474Value *S = IRB.CreateOrReduce(getShadow(&I, 0));3475setShadow(&I, S);3476setOrigin(&I, getOrigin(&I, 0));3477}34783479// Instrument vector.reduce.or intrinsic.3480// Valid (non-poisoned) set bits in the operand pull low the3481// corresponding shadow bits.3482void handleVectorReduceOrIntrinsic(IntrinsicInst &I) {3483IRBuilder<> IRB(&I);3484Value *OperandShadow = getShadow(&I, 0);3485Value *OperandUnsetBits = IRB.CreateNot(I.getOperand(0));3486Value *OperandUnsetOrPoison = IRB.CreateOr(OperandUnsetBits, OperandShadow);3487// Bit N is clean if any field's bit N is 1 and unpoison3488Value *OutShadowMask = IRB.CreateAndReduce(OperandUnsetOrPoison);3489// Otherwise, it is clean if every field's bit N is unpoison3490Value *OrShadow = IRB.CreateOrReduce(OperandShadow);3491Value *S = IRB.CreateAnd(OutShadowMask, OrShadow);34923493setShadow(&I, S);3494setOrigin(&I, getOrigin(&I, 0));3495}34963497// Instrument vector.reduce.and intrinsic.3498// Valid (non-poisoned) unset bits in the operand pull down the3499// corresponding shadow bits.3500void handleVectorReduceAndIntrinsic(IntrinsicInst &I) {3501IRBuilder<> IRB(&I);3502Value *OperandShadow = getShadow(&I, 0);3503Value *OperandSetOrPoison = IRB.CreateOr(I.getOperand(0), OperandShadow);3504// Bit N is clean if any field's bit N is 0 and unpoison3505Value *OutShadowMask = IRB.CreateAndReduce(OperandSetOrPoison);3506// Otherwise, it is clean if every field's bit N is unpoison3507Value *OrShadow = IRB.CreateOrReduce(OperandShadow);3508Value *S = IRB.CreateAnd(OutShadowMask, OrShadow);35093510setShadow(&I, S);3511setOrigin(&I, getOrigin(&I, 0));3512}35133514void handleStmxcsr(IntrinsicInst &I) {3515IRBuilder<> IRB(&I);3516Value *Addr = I.getArgOperand(0);3517Type *Ty = IRB.getInt32Ty();3518Value *ShadowPtr =3519getShadowOriginPtr(Addr, IRB, Ty, Align(1), /*isStore*/ true).first;35203521IRB.CreateStore(getCleanShadow(Ty), ShadowPtr);35223523if (ClCheckAccessAddress)3524insertShadowCheck(Addr, &I);3525}35263527void handleLdmxcsr(IntrinsicInst &I) {3528if (!InsertChecks)3529return;35303531IRBuilder<> IRB(&I);3532Value *Addr = I.getArgOperand(0);3533Type *Ty = IRB.getInt32Ty();3534const Align Alignment = Align(1);3535Value *ShadowPtr, *OriginPtr;3536std::tie(ShadowPtr, OriginPtr) =3537getShadowOriginPtr(Addr, IRB, Ty, Alignment, /*isStore*/ false);35383539if (ClCheckAccessAddress)3540insertShadowCheck(Addr, &I);35413542Value *Shadow = IRB.CreateAlignedLoad(Ty, ShadowPtr, Alignment, "_ldmxcsr");3543Value *Origin = MS.TrackOrigins ? IRB.CreateLoad(MS.OriginTy, OriginPtr)3544: getCleanOrigin();3545insertShadowCheck(Shadow, Origin, &I);3546}35473548void handleMaskedExpandLoad(IntrinsicInst &I) {3549IRBuilder<> IRB(&I);3550Value *Ptr = I.getArgOperand(0);3551Value *Mask = I.getArgOperand(1);3552Value *PassThru = I.getArgOperand(2);35533554if (ClCheckAccessAddress) {3555insertShadowCheck(Ptr, &I);3556insertShadowCheck(Mask, &I);3557}35583559if (!PropagateShadow) {3560setShadow(&I, getCleanShadow(&I));3561setOrigin(&I, getCleanOrigin());3562return;3563}35643565Type *ShadowTy = getShadowTy(&I);3566Type *ElementShadowTy = cast<VectorType>(ShadowTy)->getElementType();3567auto [ShadowPtr, OriginPtr] =3568getShadowOriginPtr(Ptr, IRB, ElementShadowTy, {}, /*isStore*/ false);35693570Value *Shadow = IRB.CreateMaskedExpandLoad(3571ShadowTy, ShadowPtr, Mask, getShadow(PassThru), "_msmaskedexpload");35723573setShadow(&I, Shadow);35743575// TODO: Store origins.3576setOrigin(&I, getCleanOrigin());3577}35783579void handleMaskedCompressStore(IntrinsicInst &I) {3580IRBuilder<> IRB(&I);3581Value *Values = I.getArgOperand(0);3582Value *Ptr = I.getArgOperand(1);3583Value *Mask = I.getArgOperand(2);35843585if (ClCheckAccessAddress) {3586insertShadowCheck(Ptr, &I);3587insertShadowCheck(Mask, &I);3588}35893590Value *Shadow = getShadow(Values);3591Type *ElementShadowTy =3592getShadowTy(cast<VectorType>(Values->getType())->getElementType());3593auto [ShadowPtr, OriginPtrs] =3594getShadowOriginPtr(Ptr, IRB, ElementShadowTy, {}, /*isStore*/ true);35953596IRB.CreateMaskedCompressStore(Shadow, ShadowPtr, Mask);35973598// TODO: Store origins.3599}36003601void handleMaskedGather(IntrinsicInst &I) {3602IRBuilder<> IRB(&I);3603Value *Ptrs = I.getArgOperand(0);3604const Align Alignment(3605cast<ConstantInt>(I.getArgOperand(1))->getZExtValue());3606Value *Mask = I.getArgOperand(2);3607Value *PassThru = I.getArgOperand(3);36083609Type *PtrsShadowTy = getShadowTy(Ptrs);3610if (ClCheckAccessAddress) {3611insertShadowCheck(Mask, &I);3612Value *MaskedPtrShadow = IRB.CreateSelect(3613Mask, getShadow(Ptrs), Constant::getNullValue((PtrsShadowTy)),3614"_msmaskedptrs");3615insertShadowCheck(MaskedPtrShadow, getOrigin(Ptrs), &I);3616}36173618if (!PropagateShadow) {3619setShadow(&I, getCleanShadow(&I));3620setOrigin(&I, getCleanOrigin());3621return;3622}36233624Type *ShadowTy = getShadowTy(&I);3625Type *ElementShadowTy = cast<VectorType>(ShadowTy)->getElementType();3626auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(3627Ptrs, IRB, ElementShadowTy, Alignment, /*isStore*/ false);36283629Value *Shadow =3630IRB.CreateMaskedGather(ShadowTy, ShadowPtrs, Alignment, Mask,3631getShadow(PassThru), "_msmaskedgather");36323633setShadow(&I, Shadow);36343635// TODO: Store origins.3636setOrigin(&I, getCleanOrigin());3637}36383639void handleMaskedScatter(IntrinsicInst &I) {3640IRBuilder<> IRB(&I);3641Value *Values = I.getArgOperand(0);3642Value *Ptrs = I.getArgOperand(1);3643const Align Alignment(3644cast<ConstantInt>(I.getArgOperand(2))->getZExtValue());3645Value *Mask = I.getArgOperand(3);36463647Type *PtrsShadowTy = getShadowTy(Ptrs);3648if (ClCheckAccessAddress) {3649insertShadowCheck(Mask, &I);3650Value *MaskedPtrShadow = IRB.CreateSelect(3651Mask, getShadow(Ptrs), Constant::getNullValue((PtrsShadowTy)),3652"_msmaskedptrs");3653insertShadowCheck(MaskedPtrShadow, getOrigin(Ptrs), &I);3654}36553656Value *Shadow = getShadow(Values);3657Type *ElementShadowTy =3658getShadowTy(cast<VectorType>(Values->getType())->getElementType());3659auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(3660Ptrs, IRB, ElementShadowTy, Alignment, /*isStore*/ true);36613662IRB.CreateMaskedScatter(Shadow, ShadowPtrs, Alignment, Mask);36633664// TODO: Store origin.3665}36663667void handleMaskedStore(IntrinsicInst &I) {3668IRBuilder<> IRB(&I);3669Value *V = I.getArgOperand(0);3670Value *Ptr = I.getArgOperand(1);3671const Align Alignment(3672cast<ConstantInt>(I.getArgOperand(2))->getZExtValue());3673Value *Mask = I.getArgOperand(3);3674Value *Shadow = getShadow(V);36753676if (ClCheckAccessAddress) {3677insertShadowCheck(Ptr, &I);3678insertShadowCheck(Mask, &I);3679}36803681Value *ShadowPtr;3682Value *OriginPtr;3683std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(3684Ptr, IRB, Shadow->getType(), Alignment, /*isStore*/ true);36853686IRB.CreateMaskedStore(Shadow, ShadowPtr, Alignment, Mask);36873688if (!MS.TrackOrigins)3689return;36903691auto &DL = F.getDataLayout();3692paintOrigin(IRB, getOrigin(V), OriginPtr,3693DL.getTypeStoreSize(Shadow->getType()),3694std::max(Alignment, kMinOriginAlignment));3695}36963697void handleMaskedLoad(IntrinsicInst &I) {3698IRBuilder<> IRB(&I);3699Value *Ptr = I.getArgOperand(0);3700const Align Alignment(3701cast<ConstantInt>(I.getArgOperand(1))->getZExtValue());3702Value *Mask = I.getArgOperand(2);3703Value *PassThru = I.getArgOperand(3);37043705if (ClCheckAccessAddress) {3706insertShadowCheck(Ptr, &I);3707insertShadowCheck(Mask, &I);3708}37093710if (!PropagateShadow) {3711setShadow(&I, getCleanShadow(&I));3712setOrigin(&I, getCleanOrigin());3713return;3714}37153716Type *ShadowTy = getShadowTy(&I);3717Value *ShadowPtr, *OriginPtr;3718std::tie(ShadowPtr, OriginPtr) =3719getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment, /*isStore*/ false);3720setShadow(&I, IRB.CreateMaskedLoad(ShadowTy, ShadowPtr, Alignment, Mask,3721getShadow(PassThru), "_msmaskedld"));37223723if (!MS.TrackOrigins)3724return;37253726// Choose between PassThru's and the loaded value's origins.3727Value *MaskedPassThruShadow = IRB.CreateAnd(3728getShadow(PassThru), IRB.CreateSExt(IRB.CreateNeg(Mask), ShadowTy));37293730Value *NotNull = convertToBool(MaskedPassThruShadow, IRB, "_mscmp");37313732Value *PtrOrigin = IRB.CreateLoad(MS.OriginTy, OriginPtr);3733Value *Origin = IRB.CreateSelect(NotNull, getOrigin(PassThru), PtrOrigin);37343735setOrigin(&I, Origin);3736}37373738// Instrument BMI / BMI2 intrinsics.3739// All of these intrinsics are Z = I(X, Y)3740// where the types of all operands and the result match, and are either i32 or3741// i64. The following instrumentation happens to work for all of them:3742// Sz = I(Sx, Y) | (sext (Sy != 0))3743void handleBmiIntrinsic(IntrinsicInst &I) {3744IRBuilder<> IRB(&I);3745Type *ShadowTy = getShadowTy(&I);37463747// If any bit of the mask operand is poisoned, then the whole thing is.3748Value *SMask = getShadow(&I, 1);3749SMask = IRB.CreateSExt(IRB.CreateICmpNE(SMask, getCleanShadow(ShadowTy)),3750ShadowTy);3751// Apply the same intrinsic to the shadow of the first operand.3752Value *S = IRB.CreateCall(I.getCalledFunction(),3753{getShadow(&I, 0), I.getOperand(1)});3754S = IRB.CreateOr(SMask, S);3755setShadow(&I, S);3756setOriginForNaryOp(I);3757}37583759static SmallVector<int, 8> getPclmulMask(unsigned Width, bool OddElements) {3760SmallVector<int, 8> Mask;3761for (unsigned X = OddElements ? 1 : 0; X < Width; X += 2) {3762Mask.append(2, X);3763}3764return Mask;3765}37663767// Instrument pclmul intrinsics.3768// These intrinsics operate either on odd or on even elements of the input3769// vectors, depending on the constant in the 3rd argument, ignoring the rest.3770// Replace the unused elements with copies of the used ones, ex:3771// (0, 1, 2, 3) -> (0, 0, 2, 2) (even case)3772// or3773// (0, 1, 2, 3) -> (1, 1, 3, 3) (odd case)3774// and then apply the usual shadow combining logic.3775void handlePclmulIntrinsic(IntrinsicInst &I) {3776IRBuilder<> IRB(&I);3777unsigned Width =3778cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements();3779assert(isa<ConstantInt>(I.getArgOperand(2)) &&3780"pclmul 3rd operand must be a constant");3781unsigned Imm = cast<ConstantInt>(I.getArgOperand(2))->getZExtValue();3782Value *Shuf0 = IRB.CreateShuffleVector(getShadow(&I, 0),3783getPclmulMask(Width, Imm & 0x01));3784Value *Shuf1 = IRB.CreateShuffleVector(getShadow(&I, 1),3785getPclmulMask(Width, Imm & 0x10));3786ShadowAndOriginCombiner SOC(this, IRB);3787SOC.Add(Shuf0, getOrigin(&I, 0));3788SOC.Add(Shuf1, getOrigin(&I, 1));3789SOC.Done(&I);3790}37913792// Instrument _mm_*_sd|ss intrinsics3793void handleUnarySdSsIntrinsic(IntrinsicInst &I) {3794IRBuilder<> IRB(&I);3795unsigned Width =3796cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements();3797Value *First = getShadow(&I, 0);3798Value *Second = getShadow(&I, 1);3799// First element of second operand, remaining elements of first operand3800SmallVector<int, 16> Mask;3801Mask.push_back(Width);3802for (unsigned i = 1; i < Width; i++)3803Mask.push_back(i);3804Value *Shadow = IRB.CreateShuffleVector(First, Second, Mask);38053806setShadow(&I, Shadow);3807setOriginForNaryOp(I);3808}38093810void handleVtestIntrinsic(IntrinsicInst &I) {3811IRBuilder<> IRB(&I);3812Value *Shadow0 = getShadow(&I, 0);3813Value *Shadow1 = getShadow(&I, 1);3814Value *Or = IRB.CreateOr(Shadow0, Shadow1);3815Value *NZ = IRB.CreateICmpNE(Or, Constant::getNullValue(Or->getType()));3816Value *Scalar = convertShadowToScalar(NZ, IRB);3817Value *Shadow = IRB.CreateZExt(Scalar, getShadowTy(&I));38183819setShadow(&I, Shadow);3820setOriginForNaryOp(I);3821}38223823void handleBinarySdSsIntrinsic(IntrinsicInst &I) {3824IRBuilder<> IRB(&I);3825unsigned Width =3826cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements();3827Value *First = getShadow(&I, 0);3828Value *Second = getShadow(&I, 1);3829Value *OrShadow = IRB.CreateOr(First, Second);3830// First element of both OR'd together, remaining elements of first operand3831SmallVector<int, 16> Mask;3832Mask.push_back(Width);3833for (unsigned i = 1; i < Width; i++)3834Mask.push_back(i);3835Value *Shadow = IRB.CreateShuffleVector(First, OrShadow, Mask);38363837setShadow(&I, Shadow);3838setOriginForNaryOp(I);3839}38403841// Instrument abs intrinsic.3842// handleUnknownIntrinsic can't handle it because of the last3843// is_int_min_poison argument which does not match the result type.3844void handleAbsIntrinsic(IntrinsicInst &I) {3845assert(I.getType()->isIntOrIntVectorTy());3846assert(I.getArgOperand(0)->getType() == I.getType());38473848// FIXME: Handle is_int_min_poison.3849IRBuilder<> IRB(&I);3850setShadow(&I, getShadow(&I, 0));3851setOrigin(&I, getOrigin(&I, 0));3852}38533854void handleIsFpClass(IntrinsicInst &I) {3855IRBuilder<> IRB(&I);3856Value *Shadow = getShadow(&I, 0);3857setShadow(&I, IRB.CreateICmpNE(Shadow, getCleanShadow(Shadow)));3858setOrigin(&I, getOrigin(&I, 0));3859}38603861void handleArithmeticWithOverflow(IntrinsicInst &I) {3862IRBuilder<> IRB(&I);3863Value *Shadow0 = getShadow(&I, 0);3864Value *Shadow1 = getShadow(&I, 1);3865Value *ShadowElt0 = IRB.CreateOr(Shadow0, Shadow1);3866Value *ShadowElt1 =3867IRB.CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));38683869Value *Shadow = PoisonValue::get(getShadowTy(&I));3870Shadow = IRB.CreateInsertValue(Shadow, ShadowElt0, 0);3871Shadow = IRB.CreateInsertValue(Shadow, ShadowElt1, 1);38723873setShadow(&I, Shadow);3874setOriginForNaryOp(I);3875}38763877/// Handle Arm NEON vector store intrinsics (vst{2,3,4}).3878///3879/// Arm NEON vector store intrinsics have the output address (pointer) as the3880/// last argument, with the initial arguments being the inputs. They return3881/// void.3882void handleNEONVectorStoreIntrinsic(IntrinsicInst &I) {3883IRBuilder<> IRB(&I);38843885// Don't use getNumOperands() because it includes the callee3886int numArgOperands = I.arg_size();3887assert(numArgOperands >= 1);38883889// The last arg operand is the output3890Value *Addr = I.getArgOperand(numArgOperands - 1);3891assert(Addr->getType()->isPointerTy());38923893if (ClCheckAccessAddress)3894insertShadowCheck(Addr, &I);38953896// Every arg operand, other than the last one, is an input vector3897IntrinsicInst *ShadowI = cast<IntrinsicInst>(I.clone());3898for (int i = 0; i < numArgOperands - 1; i++) {3899assert(isa<FixedVectorType>(I.getArgOperand(i)->getType()));3900ShadowI->setArgOperand(i, getShadow(&I, i));3901}39023903// MSan's GetShadowTy assumes the LHS is the type we want the shadow for3904// e.g., for:3905// [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to i1283906// we know the type of the output (and its shadow) is <16 x i8>.3907//3908// Arm NEON VST is unusual because the last argument is the output address:3909// define void @st2_16b(<16 x i8> %A, <16 x i8> %B, ptr %P) {3910// call void @llvm.aarch64.neon.st2.v16i8.p03911// (<16 x i8> [[A]], <16 x i8> [[B]], ptr [[P]])3912// and we have no type information about P's operand. We must manually3913// compute the type (<16 x i8> x 2).3914FixedVectorType *OutputVectorTy = FixedVectorType::get(3915cast<FixedVectorType>(I.getArgOperand(0)->getType())->getElementType(),3916cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements() *3917(numArgOperands - 1));3918Type *ShadowTy = getShadowTy(OutputVectorTy);3919Value *ShadowPtr, *OriginPtr;3920// AArch64 NEON does not need alignment (unless OS requires it)3921std::tie(ShadowPtr, OriginPtr) =3922getShadowOriginPtr(Addr, IRB, ShadowTy, Align(1), /*isStore*/ true);3923ShadowI->setArgOperand(numArgOperands - 1, ShadowPtr);3924ShadowI->insertAfter(&I);39253926if (MS.TrackOrigins) {3927// TODO: if we modelled the vst* instruction more precisely, we could3928// more accurately track the origins (e.g., if both inputs are3929// uninitialized for vst2, we currently blame the second input, even3930// though part of the output depends only on the first input).3931OriginCombiner OC(this, IRB);3932for (int i = 0; i < numArgOperands - 1; i++)3933OC.Add(I.getArgOperand(i));39343935const DataLayout &DL = F.getDataLayout();3936OC.DoneAndStoreOrigin(DL.getTypeStoreSize(OutputVectorTy), OriginPtr);3937}3938}39393940void visitIntrinsicInst(IntrinsicInst &I) {3941switch (I.getIntrinsicID()) {3942case Intrinsic::uadd_with_overflow:3943case Intrinsic::sadd_with_overflow:3944case Intrinsic::usub_with_overflow:3945case Intrinsic::ssub_with_overflow:3946case Intrinsic::umul_with_overflow:3947case Intrinsic::smul_with_overflow:3948handleArithmeticWithOverflow(I);3949break;3950case Intrinsic::abs:3951handleAbsIntrinsic(I);3952break;3953case Intrinsic::is_fpclass:3954handleIsFpClass(I);3955break;3956case Intrinsic::lifetime_start:3957handleLifetimeStart(I);3958break;3959case Intrinsic::launder_invariant_group:3960case Intrinsic::strip_invariant_group:3961handleInvariantGroup(I);3962break;3963case Intrinsic::bswap:3964handleBswap(I);3965break;3966case Intrinsic::ctlz:3967case Intrinsic::cttz:3968handleCountZeroes(I);3969break;3970case Intrinsic::masked_compressstore:3971handleMaskedCompressStore(I);3972break;3973case Intrinsic::masked_expandload:3974handleMaskedExpandLoad(I);3975break;3976case Intrinsic::masked_gather:3977handleMaskedGather(I);3978break;3979case Intrinsic::masked_scatter:3980handleMaskedScatter(I);3981break;3982case Intrinsic::masked_store:3983handleMaskedStore(I);3984break;3985case Intrinsic::masked_load:3986handleMaskedLoad(I);3987break;3988case Intrinsic::vector_reduce_and:3989handleVectorReduceAndIntrinsic(I);3990break;3991case Intrinsic::vector_reduce_or:3992handleVectorReduceOrIntrinsic(I);3993break;3994case Intrinsic::vector_reduce_add:3995case Intrinsic::vector_reduce_xor:3996case Intrinsic::vector_reduce_mul:3997handleVectorReduceIntrinsic(I);3998break;3999case Intrinsic::x86_sse_stmxcsr:4000handleStmxcsr(I);4001break;4002case Intrinsic::x86_sse_ldmxcsr:4003handleLdmxcsr(I);4004break;4005case Intrinsic::x86_avx512_vcvtsd2usi64:4006case Intrinsic::x86_avx512_vcvtsd2usi32:4007case Intrinsic::x86_avx512_vcvtss2usi64:4008case Intrinsic::x86_avx512_vcvtss2usi32:4009case Intrinsic::x86_avx512_cvttss2usi64:4010case Intrinsic::x86_avx512_cvttss2usi:4011case Intrinsic::x86_avx512_cvttsd2usi64:4012case Intrinsic::x86_avx512_cvttsd2usi:4013case Intrinsic::x86_avx512_cvtusi2ss:4014case Intrinsic::x86_avx512_cvtusi642sd:4015case Intrinsic::x86_avx512_cvtusi642ss:4016handleVectorConvertIntrinsic(I, 1, true);4017break;4018case Intrinsic::x86_sse2_cvtsd2si64:4019case Intrinsic::x86_sse2_cvtsd2si:4020case Intrinsic::x86_sse2_cvtsd2ss:4021case Intrinsic::x86_sse2_cvttsd2si64:4022case Intrinsic::x86_sse2_cvttsd2si:4023case Intrinsic::x86_sse_cvtss2si64:4024case Intrinsic::x86_sse_cvtss2si:4025case Intrinsic::x86_sse_cvttss2si64:4026case Intrinsic::x86_sse_cvttss2si:4027handleVectorConvertIntrinsic(I, 1);4028break;4029case Intrinsic::x86_sse_cvtps2pi:4030case Intrinsic::x86_sse_cvttps2pi:4031handleVectorConvertIntrinsic(I, 2);4032break;40334034case Intrinsic::x86_avx512_psll_w_512:4035case Intrinsic::x86_avx512_psll_d_512:4036case Intrinsic::x86_avx512_psll_q_512:4037case Intrinsic::x86_avx512_pslli_w_512:4038case Intrinsic::x86_avx512_pslli_d_512:4039case Intrinsic::x86_avx512_pslli_q_512:4040case Intrinsic::x86_avx512_psrl_w_512:4041case Intrinsic::x86_avx512_psrl_d_512:4042case Intrinsic::x86_avx512_psrl_q_512:4043case Intrinsic::x86_avx512_psra_w_512:4044case Intrinsic::x86_avx512_psra_d_512:4045case Intrinsic::x86_avx512_psra_q_512:4046case Intrinsic::x86_avx512_psrli_w_512:4047case Intrinsic::x86_avx512_psrli_d_512:4048case Intrinsic::x86_avx512_psrli_q_512:4049case Intrinsic::x86_avx512_psrai_w_512:4050case Intrinsic::x86_avx512_psrai_d_512:4051case Intrinsic::x86_avx512_psrai_q_512:4052case Intrinsic::x86_avx512_psra_q_256:4053case Intrinsic::x86_avx512_psra_q_128:4054case Intrinsic::x86_avx512_psrai_q_256:4055case Intrinsic::x86_avx512_psrai_q_128:4056case Intrinsic::x86_avx2_psll_w:4057case Intrinsic::x86_avx2_psll_d:4058case Intrinsic::x86_avx2_psll_q:4059case Intrinsic::x86_avx2_pslli_w:4060case Intrinsic::x86_avx2_pslli_d:4061case Intrinsic::x86_avx2_pslli_q:4062case Intrinsic::x86_avx2_psrl_w:4063case Intrinsic::x86_avx2_psrl_d:4064case Intrinsic::x86_avx2_psrl_q:4065case Intrinsic::x86_avx2_psra_w:4066case Intrinsic::x86_avx2_psra_d:4067case Intrinsic::x86_avx2_psrli_w:4068case Intrinsic::x86_avx2_psrli_d:4069case Intrinsic::x86_avx2_psrli_q:4070case Intrinsic::x86_avx2_psrai_w:4071case Intrinsic::x86_avx2_psrai_d:4072case Intrinsic::x86_sse2_psll_w:4073case Intrinsic::x86_sse2_psll_d:4074case Intrinsic::x86_sse2_psll_q:4075case Intrinsic::x86_sse2_pslli_w:4076case Intrinsic::x86_sse2_pslli_d:4077case Intrinsic::x86_sse2_pslli_q:4078case Intrinsic::x86_sse2_psrl_w:4079case Intrinsic::x86_sse2_psrl_d:4080case Intrinsic::x86_sse2_psrl_q:4081case Intrinsic::x86_sse2_psra_w:4082case Intrinsic::x86_sse2_psra_d:4083case Intrinsic::x86_sse2_psrli_w:4084case Intrinsic::x86_sse2_psrli_d:4085case Intrinsic::x86_sse2_psrli_q:4086case Intrinsic::x86_sse2_psrai_w:4087case Intrinsic::x86_sse2_psrai_d:4088case Intrinsic::x86_mmx_psll_w:4089case Intrinsic::x86_mmx_psll_d:4090case Intrinsic::x86_mmx_psll_q:4091case Intrinsic::x86_mmx_pslli_w:4092case Intrinsic::x86_mmx_pslli_d:4093case Intrinsic::x86_mmx_pslli_q:4094case Intrinsic::x86_mmx_psrl_w:4095case Intrinsic::x86_mmx_psrl_d:4096case Intrinsic::x86_mmx_psrl_q:4097case Intrinsic::x86_mmx_psra_w:4098case Intrinsic::x86_mmx_psra_d:4099case Intrinsic::x86_mmx_psrli_w:4100case Intrinsic::x86_mmx_psrli_d:4101case Intrinsic::x86_mmx_psrli_q:4102case Intrinsic::x86_mmx_psrai_w:4103case Intrinsic::x86_mmx_psrai_d:4104handleVectorShiftIntrinsic(I, /* Variable */ false);4105break;4106case Intrinsic::x86_avx2_psllv_d:4107case Intrinsic::x86_avx2_psllv_d_256:4108case Intrinsic::x86_avx512_psllv_d_512:4109case Intrinsic::x86_avx2_psllv_q:4110case Intrinsic::x86_avx2_psllv_q_256:4111case Intrinsic::x86_avx512_psllv_q_512:4112case Intrinsic::x86_avx2_psrlv_d:4113case Intrinsic::x86_avx2_psrlv_d_256:4114case Intrinsic::x86_avx512_psrlv_d_512:4115case Intrinsic::x86_avx2_psrlv_q:4116case Intrinsic::x86_avx2_psrlv_q_256:4117case Intrinsic::x86_avx512_psrlv_q_512:4118case Intrinsic::x86_avx2_psrav_d:4119case Intrinsic::x86_avx2_psrav_d_256:4120case Intrinsic::x86_avx512_psrav_d_512:4121case Intrinsic::x86_avx512_psrav_q_128:4122case Intrinsic::x86_avx512_psrav_q_256:4123case Intrinsic::x86_avx512_psrav_q_512:4124handleVectorShiftIntrinsic(I, /* Variable */ true);4125break;41264127case Intrinsic::x86_sse2_packsswb_128:4128case Intrinsic::x86_sse2_packssdw_128:4129case Intrinsic::x86_sse2_packuswb_128:4130case Intrinsic::x86_sse41_packusdw:4131case Intrinsic::x86_avx2_packsswb:4132case Intrinsic::x86_avx2_packssdw:4133case Intrinsic::x86_avx2_packuswb:4134case Intrinsic::x86_avx2_packusdw:4135handleVectorPackIntrinsic(I);4136break;41374138case Intrinsic::x86_sse41_pblendvb:4139case Intrinsic::x86_sse41_blendvpd:4140case Intrinsic::x86_sse41_blendvps:4141case Intrinsic::x86_avx_blendv_pd_256:4142case Intrinsic::x86_avx_blendv_ps_256:4143case Intrinsic::x86_avx2_pblendvb:4144handleBlendvIntrinsic(I);4145break;41464147case Intrinsic::x86_avx_dp_ps_256:4148case Intrinsic::x86_sse41_dppd:4149case Intrinsic::x86_sse41_dpps:4150handleDppIntrinsic(I);4151break;41524153case Intrinsic::x86_mmx_packsswb:4154case Intrinsic::x86_mmx_packuswb:4155handleVectorPackIntrinsic(I, 16);4156break;41574158case Intrinsic::x86_mmx_packssdw:4159handleVectorPackIntrinsic(I, 32);4160break;41614162case Intrinsic::x86_mmx_psad_bw:4163case Intrinsic::x86_sse2_psad_bw:4164case Intrinsic::x86_avx2_psad_bw:4165handleVectorSadIntrinsic(I);4166break;41674168case Intrinsic::x86_sse2_pmadd_wd:4169case Intrinsic::x86_avx2_pmadd_wd:4170case Intrinsic::x86_ssse3_pmadd_ub_sw_128:4171case Intrinsic::x86_avx2_pmadd_ub_sw:4172handleVectorPmaddIntrinsic(I);4173break;41744175case Intrinsic::x86_ssse3_pmadd_ub_sw:4176handleVectorPmaddIntrinsic(I, 8);4177break;41784179case Intrinsic::x86_mmx_pmadd_wd:4180handleVectorPmaddIntrinsic(I, 16);4181break;41824183case Intrinsic::x86_sse_cmp_ss:4184case Intrinsic::x86_sse2_cmp_sd:4185case Intrinsic::x86_sse_comieq_ss:4186case Intrinsic::x86_sse_comilt_ss:4187case Intrinsic::x86_sse_comile_ss:4188case Intrinsic::x86_sse_comigt_ss:4189case Intrinsic::x86_sse_comige_ss:4190case Intrinsic::x86_sse_comineq_ss:4191case Intrinsic::x86_sse_ucomieq_ss:4192case Intrinsic::x86_sse_ucomilt_ss:4193case Intrinsic::x86_sse_ucomile_ss:4194case Intrinsic::x86_sse_ucomigt_ss:4195case Intrinsic::x86_sse_ucomige_ss:4196case Intrinsic::x86_sse_ucomineq_ss:4197case Intrinsic::x86_sse2_comieq_sd:4198case Intrinsic::x86_sse2_comilt_sd:4199case Intrinsic::x86_sse2_comile_sd:4200case Intrinsic::x86_sse2_comigt_sd:4201case Intrinsic::x86_sse2_comige_sd:4202case Intrinsic::x86_sse2_comineq_sd:4203case Intrinsic::x86_sse2_ucomieq_sd:4204case Intrinsic::x86_sse2_ucomilt_sd:4205case Intrinsic::x86_sse2_ucomile_sd:4206case Intrinsic::x86_sse2_ucomigt_sd:4207case Intrinsic::x86_sse2_ucomige_sd:4208case Intrinsic::x86_sse2_ucomineq_sd:4209handleVectorCompareScalarIntrinsic(I);4210break;42114212case Intrinsic::x86_avx_cmp_pd_256:4213case Intrinsic::x86_avx_cmp_ps_256:4214case Intrinsic::x86_sse2_cmp_pd:4215case Intrinsic::x86_sse_cmp_ps:4216handleVectorComparePackedIntrinsic(I);4217break;42184219case Intrinsic::x86_bmi_bextr_32:4220case Intrinsic::x86_bmi_bextr_64:4221case Intrinsic::x86_bmi_bzhi_32:4222case Intrinsic::x86_bmi_bzhi_64:4223case Intrinsic::x86_bmi_pdep_32:4224case Intrinsic::x86_bmi_pdep_64:4225case Intrinsic::x86_bmi_pext_32:4226case Intrinsic::x86_bmi_pext_64:4227handleBmiIntrinsic(I);4228break;42294230case Intrinsic::x86_pclmulqdq:4231case Intrinsic::x86_pclmulqdq_256:4232case Intrinsic::x86_pclmulqdq_512:4233handlePclmulIntrinsic(I);4234break;42354236case Intrinsic::x86_sse41_round_sd:4237case Intrinsic::x86_sse41_round_ss:4238handleUnarySdSsIntrinsic(I);4239break;4240case Intrinsic::x86_sse2_max_sd:4241case Intrinsic::x86_sse_max_ss:4242case Intrinsic::x86_sse2_min_sd:4243case Intrinsic::x86_sse_min_ss:4244handleBinarySdSsIntrinsic(I);4245break;42464247case Intrinsic::x86_avx_vtestc_pd:4248case Intrinsic::x86_avx_vtestc_pd_256:4249case Intrinsic::x86_avx_vtestc_ps:4250case Intrinsic::x86_avx_vtestc_ps_256:4251case Intrinsic::x86_avx_vtestnzc_pd:4252case Intrinsic::x86_avx_vtestnzc_pd_256:4253case Intrinsic::x86_avx_vtestnzc_ps:4254case Intrinsic::x86_avx_vtestnzc_ps_256:4255case Intrinsic::x86_avx_vtestz_pd:4256case Intrinsic::x86_avx_vtestz_pd_256:4257case Intrinsic::x86_avx_vtestz_ps:4258case Intrinsic::x86_avx_vtestz_ps_256:4259case Intrinsic::x86_avx_ptestc_256:4260case Intrinsic::x86_avx_ptestnzc_256:4261case Intrinsic::x86_avx_ptestz_256:4262case Intrinsic::x86_sse41_ptestc:4263case Intrinsic::x86_sse41_ptestnzc:4264case Intrinsic::x86_sse41_ptestz:4265handleVtestIntrinsic(I);4266break;42674268case Intrinsic::fshl:4269case Intrinsic::fshr:4270handleFunnelShift(I);4271break;42724273case Intrinsic::is_constant:4274// The result of llvm.is.constant() is always defined.4275setShadow(&I, getCleanShadow(&I));4276setOrigin(&I, getCleanOrigin());4277break;42784279case Intrinsic::aarch64_neon_st2:4280case Intrinsic::aarch64_neon_st3:4281case Intrinsic::aarch64_neon_st4: {4282handleNEONVectorStoreIntrinsic(I);4283break;4284}42854286default:4287if (!handleUnknownIntrinsic(I))4288visitInstruction(I);4289break;4290}4291}42924293void visitLibAtomicLoad(CallBase &CB) {4294// Since we use getNextNode here, we can't have CB terminate the BB.4295assert(isa<CallInst>(CB));42964297IRBuilder<> IRB(&CB);4298Value *Size = CB.getArgOperand(0);4299Value *SrcPtr = CB.getArgOperand(1);4300Value *DstPtr = CB.getArgOperand(2);4301Value *Ordering = CB.getArgOperand(3);4302// Convert the call to have at least Acquire ordering to make sure4303// the shadow operations aren't reordered before it.4304Value *NewOrdering =4305IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);4306CB.setArgOperand(3, NewOrdering);43074308NextNodeIRBuilder NextIRB(&CB);4309Value *SrcShadowPtr, *SrcOriginPtr;4310std::tie(SrcShadowPtr, SrcOriginPtr) =4311getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(), Align(1),4312/*isStore*/ false);4313Value *DstShadowPtr =4314getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(), Align(1),4315/*isStore*/ true)4316.first;43174318NextIRB.CreateMemCpy(DstShadowPtr, Align(1), SrcShadowPtr, Align(1), Size);4319if (MS.TrackOrigins) {4320Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,4321kMinOriginAlignment);4322Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);4323NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});4324}4325}43264327void visitLibAtomicStore(CallBase &CB) {4328IRBuilder<> IRB(&CB);4329Value *Size = CB.getArgOperand(0);4330Value *DstPtr = CB.getArgOperand(2);4331Value *Ordering = CB.getArgOperand(3);4332// Convert the call to have at least Release ordering to make sure4333// the shadow operations aren't reordered after it.4334Value *NewOrdering =4335IRB.CreateExtractElement(makeAddReleaseOrderingTable(IRB), Ordering);4336CB.setArgOperand(3, NewOrdering);43374338Value *DstShadowPtr =4339getShadowOriginPtr(DstPtr, IRB, IRB.getInt8Ty(), Align(1),4340/*isStore*/ true)4341.first;43424343// Atomic store always paints clean shadow/origin. See file header.4344IRB.CreateMemSet(DstShadowPtr, getCleanShadow(IRB.getInt8Ty()), Size,4345Align(1));4346}43474348void visitCallBase(CallBase &CB) {4349assert(!CB.getMetadata(LLVMContext::MD_nosanitize));4350if (CB.isInlineAsm()) {4351// For inline asm (either a call to asm function, or callbr instruction),4352// do the usual thing: check argument shadow and mark all outputs as4353// clean. Note that any side effects of the inline asm that are not4354// immediately visible in its constraints are not handled.4355if (ClHandleAsmConservative)4356visitAsmInstruction(CB);4357else4358visitInstruction(CB);4359return;4360}4361LibFunc LF;4362if (TLI->getLibFunc(CB, LF)) {4363// libatomic.a functions need to have special handling because there isn't4364// a good way to intercept them or compile the library with4365// instrumentation.4366switch (LF) {4367case LibFunc_atomic_load:4368if (!isa<CallInst>(CB)) {4369llvm::errs() << "MSAN -- cannot instrument invoke of libatomic load."4370"Ignoring!\n";4371break;4372}4373visitLibAtomicLoad(CB);4374return;4375case LibFunc_atomic_store:4376visitLibAtomicStore(CB);4377return;4378default:4379break;4380}4381}43824383if (auto *Call = dyn_cast<CallInst>(&CB)) {4384assert(!isa<IntrinsicInst>(Call) && "intrinsics are handled elsewhere");43854386// We are going to insert code that relies on the fact that the callee4387// will become a non-readonly function after it is instrumented by us. To4388// prevent this code from being optimized out, mark that function4389// non-readonly in advance.4390// TODO: We can likely do better than dropping memory() completely here.4391AttributeMask B;4392B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);43934394Call->removeFnAttrs(B);4395if (Function *Func = Call->getCalledFunction()) {4396Func->removeFnAttrs(B);4397}43984399maybeMarkSanitizerLibraryCallNoBuiltin(Call, TLI);4400}4401IRBuilder<> IRB(&CB);4402bool MayCheckCall = MS.EagerChecks;4403if (Function *Func = CB.getCalledFunction()) {4404// __sanitizer_unaligned_{load,store} functions may be called by users4405// and always expects shadows in the TLS. So don't check them.4406MayCheckCall &= !Func->getName().starts_with("__sanitizer_unaligned_");4407}44084409unsigned ArgOffset = 0;4410LLVM_DEBUG(dbgs() << " CallSite: " << CB << "\n");4411for (const auto &[i, A] : llvm::enumerate(CB.args())) {4412if (!A->getType()->isSized()) {4413LLVM_DEBUG(dbgs() << "Arg " << i << " is not sized: " << CB << "\n");4414continue;4415}44164417if (A->getType()->isScalableTy()) {4418LLVM_DEBUG(dbgs() << "Arg " << i << " is vscale: " << CB << "\n");4419// Handle as noundef, but don't reserve tls slots.4420insertShadowCheck(A, &CB);4421continue;4422}44234424unsigned Size = 0;4425const DataLayout &DL = F.getDataLayout();44264427bool ByVal = CB.paramHasAttr(i, Attribute::ByVal);4428bool NoUndef = CB.paramHasAttr(i, Attribute::NoUndef);4429bool EagerCheck = MayCheckCall && !ByVal && NoUndef;44304431if (EagerCheck) {4432insertShadowCheck(A, &CB);4433Size = DL.getTypeAllocSize(A->getType());4434} else {4435Value *Store = nullptr;4436// Compute the Shadow for arg even if it is ByVal, because4437// in that case getShadow() will copy the actual arg shadow to4438// __msan_param_tls.4439Value *ArgShadow = getShadow(A);4440Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);4441LLVM_DEBUG(dbgs() << " Arg#" << i << ": " << *A4442<< " Shadow: " << *ArgShadow << "\n");4443if (ByVal) {4444// ByVal requires some special handling as it's too big for a single4445// load4446assert(A->getType()->isPointerTy() &&4447"ByVal argument is not a pointer!");4448Size = DL.getTypeAllocSize(CB.getParamByValType(i));4449if (ArgOffset + Size > kParamTLSSize)4450break;4451const MaybeAlign ParamAlignment(CB.getParamAlign(i));4452MaybeAlign Alignment = std::nullopt;4453if (ParamAlignment)4454Alignment = std::min(*ParamAlignment, kShadowTLSAlignment);4455Value *AShadowPtr, *AOriginPtr;4456std::tie(AShadowPtr, AOriginPtr) =4457getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), Alignment,4458/*isStore*/ false);4459if (!PropagateShadow) {4460Store = IRB.CreateMemSet(ArgShadowBase,4461Constant::getNullValue(IRB.getInt8Ty()),4462Size, Alignment);4463} else {4464Store = IRB.CreateMemCpy(ArgShadowBase, Alignment, AShadowPtr,4465Alignment, Size);4466if (MS.TrackOrigins) {4467Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);4468// FIXME: OriginSize should be:4469// alignTo(A % kMinOriginAlignment + Size, kMinOriginAlignment)4470unsigned OriginSize = alignTo(Size, kMinOriginAlignment);4471IRB.CreateMemCpy(4472ArgOriginBase,4473/* by origin_tls[ArgOffset] */ kMinOriginAlignment,4474AOriginPtr,4475/* by getShadowOriginPtr */ kMinOriginAlignment, OriginSize);4476}4477}4478} else {4479// Any other parameters mean we need bit-grained tracking of uninit4480// data4481Size = DL.getTypeAllocSize(A->getType());4482if (ArgOffset + Size > kParamTLSSize)4483break;4484Store = IRB.CreateAlignedStore(ArgShadow, ArgShadowBase,4485kShadowTLSAlignment);4486Constant *Cst = dyn_cast<Constant>(ArgShadow);4487if (MS.TrackOrigins && !(Cst && Cst->isNullValue())) {4488IRB.CreateStore(getOrigin(A),4489getOriginPtrForArgument(IRB, ArgOffset));4490}4491}4492(void)Store;4493assert(Store != nullptr);4494LLVM_DEBUG(dbgs() << " Param:" << *Store << "\n");4495}4496assert(Size != 0);4497ArgOffset += alignTo(Size, kShadowTLSAlignment);4498}4499LLVM_DEBUG(dbgs() << " done with call args\n");45004501FunctionType *FT = CB.getFunctionType();4502if (FT->isVarArg()) {4503VAHelper->visitCallBase(CB, IRB);4504}45054506// Now, get the shadow for the RetVal.4507if (!CB.getType()->isSized())4508return;4509// Don't emit the epilogue for musttail call returns.4510if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())4511return;45124513if (MayCheckCall && CB.hasRetAttr(Attribute::NoUndef)) {4514setShadow(&CB, getCleanShadow(&CB));4515setOrigin(&CB, getCleanOrigin());4516return;4517}45184519IRBuilder<> IRBBefore(&CB);4520// Until we have full dynamic coverage, make sure the retval shadow is 0.4521Value *Base = getShadowPtrForRetval(IRBBefore);4522IRBBefore.CreateAlignedStore(getCleanShadow(&CB), Base,4523kShadowTLSAlignment);4524BasicBlock::iterator NextInsn;4525if (isa<CallInst>(CB)) {4526NextInsn = ++CB.getIterator();4527assert(NextInsn != CB.getParent()->end());4528} else {4529BasicBlock *NormalDest = cast<InvokeInst>(CB).getNormalDest();4530if (!NormalDest->getSinglePredecessor()) {4531// FIXME: this case is tricky, so we are just conservative here.4532// Perhaps we need to split the edge between this BB and NormalDest,4533// but a naive attempt to use SplitEdge leads to a crash.4534setShadow(&CB, getCleanShadow(&CB));4535setOrigin(&CB, getCleanOrigin());4536return;4537}4538// FIXME: NextInsn is likely in a basic block that has not been visited4539// yet. Anything inserted there will be instrumented by MSan later!4540NextInsn = NormalDest->getFirstInsertionPt();4541assert(NextInsn != NormalDest->end() &&4542"Could not find insertion point for retval shadow load");4543}4544IRBuilder<> IRBAfter(&*NextInsn);4545Value *RetvalShadow = IRBAfter.CreateAlignedLoad(4546getShadowTy(&CB), getShadowPtrForRetval(IRBAfter),4547kShadowTLSAlignment, "_msret");4548setShadow(&CB, RetvalShadow);4549if (MS.TrackOrigins)4550setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy,4551getOriginPtrForRetval()));4552}45534554bool isAMustTailRetVal(Value *RetVal) {4555if (auto *I = dyn_cast<BitCastInst>(RetVal)) {4556RetVal = I->getOperand(0);4557}4558if (auto *I = dyn_cast<CallInst>(RetVal)) {4559return I->isMustTailCall();4560}4561return false;4562}45634564void visitReturnInst(ReturnInst &I) {4565IRBuilder<> IRB(&I);4566Value *RetVal = I.getReturnValue();4567if (!RetVal)4568return;4569// Don't emit the epilogue for musttail call returns.4570if (isAMustTailRetVal(RetVal))4571return;4572Value *ShadowPtr = getShadowPtrForRetval(IRB);4573bool HasNoUndef = F.hasRetAttribute(Attribute::NoUndef);4574bool StoreShadow = !(MS.EagerChecks && HasNoUndef);4575// FIXME: Consider using SpecialCaseList to specify a list of functions that4576// must always return fully initialized values. For now, we hardcode "main".4577bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (F.getName() == "main");45784579Value *Shadow = getShadow(RetVal);4580bool StoreOrigin = true;4581if (EagerCheck) {4582insertShadowCheck(RetVal, &I);4583Shadow = getCleanShadow(RetVal);4584StoreOrigin = false;4585}45864587// The caller may still expect information passed over TLS if we pass our4588// check4589if (StoreShadow) {4590IRB.CreateAlignedStore(Shadow, ShadowPtr, kShadowTLSAlignment);4591if (MS.TrackOrigins && StoreOrigin)4592IRB.CreateStore(getOrigin(RetVal), getOriginPtrForRetval());4593}4594}45954596void visitPHINode(PHINode &I) {4597IRBuilder<> IRB(&I);4598if (!PropagateShadow) {4599setShadow(&I, getCleanShadow(&I));4600setOrigin(&I, getCleanOrigin());4601return;4602}46034604ShadowPHINodes.push_back(&I);4605setShadow(&I, IRB.CreatePHI(getShadowTy(&I), I.getNumIncomingValues(),4606"_msphi_s"));4607if (MS.TrackOrigins)4608setOrigin(4609&I, IRB.CreatePHI(MS.OriginTy, I.getNumIncomingValues(), "_msphi_o"));4610}46114612Value *getLocalVarIdptr(AllocaInst &I) {4613ConstantInt *IntConst =4614ConstantInt::get(Type::getInt32Ty((*F.getParent()).getContext()), 0);4615return new GlobalVariable(*F.getParent(), IntConst->getType(),4616/*isConstant=*/false, GlobalValue::PrivateLinkage,4617IntConst);4618}46194620Value *getLocalVarDescription(AllocaInst &I) {4621return createPrivateConstGlobalForString(*F.getParent(), I.getName());4622}46234624void poisonAllocaUserspace(AllocaInst &I, IRBuilder<> &IRB, Value *Len) {4625if (PoisonStack && ClPoisonStackWithCall) {4626IRB.CreateCall(MS.MsanPoisonStackFn, {&I, Len});4627} else {4628Value *ShadowBase, *OriginBase;4629std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(4630&I, IRB, IRB.getInt8Ty(), Align(1), /*isStore*/ true);46314632Value *PoisonValue = IRB.getInt8(PoisonStack ? ClPoisonStackPattern : 0);4633IRB.CreateMemSet(ShadowBase, PoisonValue, Len, I.getAlign());4634}46354636if (PoisonStack && MS.TrackOrigins) {4637Value *Idptr = getLocalVarIdptr(I);4638if (ClPrintStackNames) {4639Value *Descr = getLocalVarDescription(I);4640IRB.CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,4641{&I, Len, Idptr, Descr});4642} else {4643IRB.CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});4644}4645}4646}46474648void poisonAllocaKmsan(AllocaInst &I, IRBuilder<> &IRB, Value *Len) {4649Value *Descr = getLocalVarDescription(I);4650if (PoisonStack) {4651IRB.CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});4652} else {4653IRB.CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});4654}4655}46564657void instrumentAlloca(AllocaInst &I, Instruction *InsPoint = nullptr) {4658if (!InsPoint)4659InsPoint = &I;4660NextNodeIRBuilder IRB(InsPoint);4661const DataLayout &DL = F.getDataLayout();4662TypeSize TS = DL.getTypeAllocSize(I.getAllocatedType());4663Value *Len = IRB.CreateTypeSize(MS.IntptrTy, TS);4664if (I.isArrayAllocation())4665Len = IRB.CreateMul(Len,4666IRB.CreateZExtOrTrunc(I.getArraySize(), MS.IntptrTy));46674668if (MS.CompileKernel)4669poisonAllocaKmsan(I, IRB, Len);4670else4671poisonAllocaUserspace(I, IRB, Len);4672}46734674void visitAllocaInst(AllocaInst &I) {4675setShadow(&I, getCleanShadow(&I));4676setOrigin(&I, getCleanOrigin());4677// We'll get to this alloca later unless it's poisoned at the corresponding4678// llvm.lifetime.start.4679AllocaSet.insert(&I);4680}46814682void visitSelectInst(SelectInst &I) {4683// a = select b, c, d4684Value *B = I.getCondition();4685Value *C = I.getTrueValue();4686Value *D = I.getFalseValue();46874688handleSelectLikeInst(I, B, C, D);4689}46904691void handleSelectLikeInst(Instruction &I, Value *B, Value *C, Value *D) {4692IRBuilder<> IRB(&I);46934694Value *Sb = getShadow(B);4695Value *Sc = getShadow(C);4696Value *Sd = getShadow(D);46974698Value *Ob = MS.TrackOrigins ? getOrigin(B) : nullptr;4699Value *Oc = MS.TrackOrigins ? getOrigin(C) : nullptr;4700Value *Od = MS.TrackOrigins ? getOrigin(D) : nullptr;47014702// Result shadow if condition shadow is 0.4703Value *Sa0 = IRB.CreateSelect(B, Sc, Sd);4704Value *Sa1;4705if (I.getType()->isAggregateType()) {4706// To avoid "sign extending" i1 to an arbitrary aggregate type, we just do4707// an extra "select". This results in much more compact IR.4708// Sa = select Sb, poisoned, (select b, Sc, Sd)4709Sa1 = getPoisonedShadow(getShadowTy(I.getType()));4710} else {4711// Sa = select Sb, [ (c^d) | Sc | Sd ], [ b ? Sc : Sd ]4712// If Sb (condition is poisoned), look for bits in c and d that are equal4713// and both unpoisoned.4714// If !Sb (condition is unpoisoned), simply pick one of Sc and Sd.47154716// Cast arguments to shadow-compatible type.4717C = CreateAppToShadowCast(IRB, C);4718D = CreateAppToShadowCast(IRB, D);47194720// Result shadow if condition shadow is 1.4721Sa1 = IRB.CreateOr({IRB.CreateXor(C, D), Sc, Sd});4722}4723Value *Sa = IRB.CreateSelect(Sb, Sa1, Sa0, "_msprop_select");4724setShadow(&I, Sa);4725if (MS.TrackOrigins) {4726// Origins are always i32, so any vector conditions must be flattened.4727// FIXME: consider tracking vector origins for app vectors?4728if (B->getType()->isVectorTy()) {4729B = convertToBool(B, IRB);4730Sb = convertToBool(Sb, IRB);4731}4732// a = select b, c, d4733// Oa = Sb ? Ob : (b ? Oc : Od)4734setOrigin(&I, IRB.CreateSelect(Sb, Ob, IRB.CreateSelect(B, Oc, Od)));4735}4736}47374738void visitLandingPadInst(LandingPadInst &I) {4739// Do nothing.4740// See https://github.com/google/sanitizers/issues/5044741setShadow(&I, getCleanShadow(&I));4742setOrigin(&I, getCleanOrigin());4743}47444745void visitCatchSwitchInst(CatchSwitchInst &I) {4746setShadow(&I, getCleanShadow(&I));4747setOrigin(&I, getCleanOrigin());4748}47494750void visitFuncletPadInst(FuncletPadInst &I) {4751setShadow(&I, getCleanShadow(&I));4752setOrigin(&I, getCleanOrigin());4753}47544755void visitGetElementPtrInst(GetElementPtrInst &I) { handleShadowOr(I); }47564757void visitExtractValueInst(ExtractValueInst &I) {4758IRBuilder<> IRB(&I);4759Value *Agg = I.getAggregateOperand();4760LLVM_DEBUG(dbgs() << "ExtractValue: " << I << "\n");4761Value *AggShadow = getShadow(Agg);4762LLVM_DEBUG(dbgs() << " AggShadow: " << *AggShadow << "\n");4763Value *ResShadow = IRB.CreateExtractValue(AggShadow, I.getIndices());4764LLVM_DEBUG(dbgs() << " ResShadow: " << *ResShadow << "\n");4765setShadow(&I, ResShadow);4766setOriginForNaryOp(I);4767}47684769void visitInsertValueInst(InsertValueInst &I) {4770IRBuilder<> IRB(&I);4771LLVM_DEBUG(dbgs() << "InsertValue: " << I << "\n");4772Value *AggShadow = getShadow(I.getAggregateOperand());4773Value *InsShadow = getShadow(I.getInsertedValueOperand());4774LLVM_DEBUG(dbgs() << " AggShadow: " << *AggShadow << "\n");4775LLVM_DEBUG(dbgs() << " InsShadow: " << *InsShadow << "\n");4776Value *Res = IRB.CreateInsertValue(AggShadow, InsShadow, I.getIndices());4777LLVM_DEBUG(dbgs() << " Res: " << *Res << "\n");4778setShadow(&I, Res);4779setOriginForNaryOp(I);4780}47814782void dumpInst(Instruction &I) {4783if (CallInst *CI = dyn_cast<CallInst>(&I)) {4784errs() << "ZZZ call " << CI->getCalledFunction()->getName() << "\n";4785} else {4786errs() << "ZZZ " << I.getOpcodeName() << "\n";4787}4788errs() << "QQQ " << I << "\n";4789}47904791void visitResumeInst(ResumeInst &I) {4792LLVM_DEBUG(dbgs() << "Resume: " << I << "\n");4793// Nothing to do here.4794}47954796void visitCleanupReturnInst(CleanupReturnInst &CRI) {4797LLVM_DEBUG(dbgs() << "CleanupReturn: " << CRI << "\n");4798// Nothing to do here.4799}48004801void visitCatchReturnInst(CatchReturnInst &CRI) {4802LLVM_DEBUG(dbgs() << "CatchReturn: " << CRI << "\n");4803// Nothing to do here.4804}48054806void instrumentAsmArgument(Value *Operand, Type *ElemTy, Instruction &I,4807IRBuilder<> &IRB, const DataLayout &DL,4808bool isOutput) {4809// For each assembly argument, we check its value for being initialized.4810// If the argument is a pointer, we assume it points to a single element4811// of the corresponding type (or to a 8-byte word, if the type is unsized).4812// Each such pointer is instrumented with a call to the runtime library.4813Type *OpType = Operand->getType();4814// Check the operand value itself.4815insertShadowCheck(Operand, &I);4816if (!OpType->isPointerTy() || !isOutput) {4817assert(!isOutput);4818return;4819}4820if (!ElemTy->isSized())4821return;4822auto Size = DL.getTypeStoreSize(ElemTy);4823Value *SizeVal = IRB.CreateTypeSize(MS.IntptrTy, Size);4824if (MS.CompileKernel) {4825IRB.CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});4826} else {4827// ElemTy, derived from elementtype(), does not encode the alignment of4828// the pointer. Conservatively assume that the shadow memory is unaligned.4829// When Size is large, avoid StoreInst as it would expand to many4830// instructions.4831auto [ShadowPtr, _] =4832getShadowOriginPtrUserspace(Operand, IRB, IRB.getInt8Ty(), Align(1));4833if (Size <= 32)4834IRB.CreateAlignedStore(getCleanShadow(ElemTy), ShadowPtr, Align(1));4835else4836IRB.CreateMemSet(ShadowPtr, ConstantInt::getNullValue(IRB.getInt8Ty()),4837SizeVal, Align(1));4838}4839}48404841/// Get the number of output arguments returned by pointers.4842int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {4843int NumRetOutputs = 0;4844int NumOutputs = 0;4845Type *RetTy = cast<Value>(CB)->getType();4846if (!RetTy->isVoidTy()) {4847// Register outputs are returned via the CallInst return value.4848auto *ST = dyn_cast<StructType>(RetTy);4849if (ST)4850NumRetOutputs = ST->getNumElements();4851else4852NumRetOutputs = 1;4853}4854InlineAsm::ConstraintInfoVector Constraints = IA->ParseConstraints();4855for (const InlineAsm::ConstraintInfo &Info : Constraints) {4856switch (Info.Type) {4857case InlineAsm::isOutput:4858NumOutputs++;4859break;4860default:4861break;4862}4863}4864return NumOutputs - NumRetOutputs;4865}48664867void visitAsmInstruction(Instruction &I) {4868// Conservative inline assembly handling: check for poisoned shadow of4869// asm() arguments, then unpoison the result and all the memory locations4870// pointed to by those arguments.4871// An inline asm() statement in C++ contains lists of input and output4872// arguments used by the assembly code. These are mapped to operands of the4873// CallInst as follows:4874// - nR register outputs ("=r) are returned by value in a single structure4875// (SSA value of the CallInst);4876// - nO other outputs ("=m" and others) are returned by pointer as first4877// nO operands of the CallInst;4878// - nI inputs ("r", "m" and others) are passed to CallInst as the4879// remaining nI operands.4880// The total number of asm() arguments in the source is nR+nO+nI, and the4881// corresponding CallInst has nO+nI+1 operands (the last operand is the4882// function to be called).4883const DataLayout &DL = F.getDataLayout();4884CallBase *CB = cast<CallBase>(&I);4885IRBuilder<> IRB(&I);4886InlineAsm *IA = cast<InlineAsm>(CB->getCalledOperand());4887int OutputArgs = getNumOutputArgs(IA, CB);4888// The last operand of a CallInst is the function itself.4889int NumOperands = CB->getNumOperands() - 1;48904891// Check input arguments. Doing so before unpoisoning output arguments, so4892// that we won't overwrite uninit values before checking them.4893for (int i = OutputArgs; i < NumOperands; i++) {4894Value *Operand = CB->getOperand(i);4895instrumentAsmArgument(Operand, CB->getParamElementType(i), I, IRB, DL,4896/*isOutput*/ false);4897}4898// Unpoison output arguments. This must happen before the actual InlineAsm4899// call, so that the shadow for memory published in the asm() statement4900// remains valid.4901for (int i = 0; i < OutputArgs; i++) {4902Value *Operand = CB->getOperand(i);4903instrumentAsmArgument(Operand, CB->getParamElementType(i), I, IRB, DL,4904/*isOutput*/ true);4905}49064907setShadow(&I, getCleanShadow(&I));4908setOrigin(&I, getCleanOrigin());4909}49104911void visitFreezeInst(FreezeInst &I) {4912// Freeze always returns a fully defined value.4913setShadow(&I, getCleanShadow(&I));4914setOrigin(&I, getCleanOrigin());4915}49164917void visitInstruction(Instruction &I) {4918// Everything else: stop propagating and check for poisoned shadow.4919if (ClDumpStrictInstructions)4920dumpInst(I);4921LLVM_DEBUG(dbgs() << "DEFAULT: " << I << "\n");4922for (size_t i = 0, n = I.getNumOperands(); i < n; i++) {4923Value *Operand = I.getOperand(i);4924if (Operand->getType()->isSized())4925insertShadowCheck(Operand, &I);4926}4927setShadow(&I, getCleanShadow(&I));4928setOrigin(&I, getCleanOrigin());4929}4930};49314932struct VarArgHelperBase : public VarArgHelper {4933Function &F;4934MemorySanitizer &MS;4935MemorySanitizerVisitor &MSV;4936SmallVector<CallInst *, 16> VAStartInstrumentationList;4937const unsigned VAListTagSize;49384939VarArgHelperBase(Function &F, MemorySanitizer &MS,4940MemorySanitizerVisitor &MSV, unsigned VAListTagSize)4941: F(F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}49424943Value *getShadowAddrForVAArgument(IRBuilder<> &IRB, unsigned ArgOffset) {4944Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);4945return IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));4946}49474948/// Compute the shadow address for a given va_arg.4949Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,4950unsigned ArgOffset) {4951Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);4952Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));4953return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),4954"_msarg_va_s");4955}49564957/// Compute the shadow address for a given va_arg.4958Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,4959unsigned ArgOffset, unsigned ArgSize) {4960// Make sure we don't overflow __msan_va_arg_tls.4961if (ArgOffset + ArgSize > kParamTLSSize)4962return nullptr;4963return getShadowPtrForVAArgument(Ty, IRB, ArgOffset);4964}49654966/// Compute the origin address for a given va_arg.4967Value *getOriginPtrForVAArgument(IRBuilder<> &IRB, int ArgOffset) {4968Value *Base = IRB.CreatePointerCast(MS.VAArgOriginTLS, MS.IntptrTy);4969// getOriginPtrForVAArgument() is always called after4970// getShadowPtrForVAArgument(), so __msan_va_arg_origin_tls can never4971// overflow.4972Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));4973return IRB.CreateIntToPtr(Base, PointerType::get(MS.OriginTy, 0),4974"_msarg_va_o");4975}49764977void CleanUnusedTLS(IRBuilder<> &IRB, Value *ShadowBase,4978unsigned BaseOffset) {4979// The tails of __msan_va_arg_tls is not large enough to fit full4980// value shadow, but it will be copied to backup anyway. Make it4981// clean.4982if (BaseOffset >= kParamTLSSize)4983return;4984Value *TailSize =4985ConstantInt::getSigned(IRB.getInt32Ty(), kParamTLSSize - BaseOffset);4986IRB.CreateMemSet(ShadowBase, ConstantInt::getNullValue(IRB.getInt8Ty()),4987TailSize, Align(8));4988}49894990void unpoisonVAListTagForInst(IntrinsicInst &I) {4991IRBuilder<> IRB(&I);4992Value *VAListTag = I.getArgOperand(0);4993const Align Alignment = Align(8);4994auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(4995VAListTag, IRB, IRB.getInt8Ty(), Alignment, /*isStore*/ true);4996// Unpoison the whole __va_list_tag.4997IRB.CreateMemSet(ShadowPtr, Constant::getNullValue(IRB.getInt8Ty()),4998VAListTagSize, Alignment, false);4999}50005001void visitVAStartInst(VAStartInst &I) override {5002if (F.getCallingConv() == CallingConv::Win64)5003return;5004VAStartInstrumentationList.push_back(&I);5005unpoisonVAListTagForInst(I);5006}50075008void visitVACopyInst(VACopyInst &I) override {5009if (F.getCallingConv() == CallingConv::Win64)5010return;5011unpoisonVAListTagForInst(I);5012}5013};50145015/// AMD64-specific implementation of VarArgHelper.5016struct VarArgAMD64Helper : public VarArgHelperBase {5017// An unfortunate workaround for asymmetric lowering of va_arg stuff.5018// See a comment in visitCallBase for more details.5019static const unsigned AMD64GpEndOffset = 48; // AMD64 ABI Draft 0.99.6 p3.5.75020static const unsigned AMD64FpEndOffsetSSE = 176;5021// If SSE is disabled, fp_offset in va_list is zero.5022static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;50235024unsigned AMD64FpEndOffset;5025AllocaInst *VAArgTLSCopy = nullptr;5026AllocaInst *VAArgTLSOriginCopy = nullptr;5027Value *VAArgOverflowSize = nullptr;50285029enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };50305031VarArgAMD64Helper(Function &F, MemorySanitizer &MS,5032MemorySanitizerVisitor &MSV)5033: VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/24) {5034AMD64FpEndOffset = AMD64FpEndOffsetSSE;5035for (const auto &Attr : F.getAttributes().getFnAttrs()) {5036if (Attr.isStringAttribute() &&5037(Attr.getKindAsString() == "target-features")) {5038if (Attr.getValueAsString().contains("-sse"))5039AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;5040break;5041}5042}5043}50445045ArgKind classifyArgument(Value *arg) {5046// A very rough approximation of X86_64 argument classification rules.5047Type *T = arg->getType();5048if (T->isX86_FP80Ty())5049return AK_Memory;5050if (T->isFPOrFPVectorTy() || T->isX86_MMXTy())5051return AK_FloatingPoint;5052if (T->isIntegerTy() && T->getPrimitiveSizeInBits() <= 64)5053return AK_GeneralPurpose;5054if (T->isPointerTy())5055return AK_GeneralPurpose;5056return AK_Memory;5057}50585059// For VarArg functions, store the argument shadow in an ABI-specific format5060// that corresponds to va_list layout.5061// We do this because Clang lowers va_arg in the frontend, and this pass5062// only sees the low level code that deals with va_list internals.5063// A much easier alternative (provided that Clang emits va_arg instructions)5064// would have been to associate each live instance of va_list with a copy of5065// MSanParamTLS, and extract shadow on va_arg() call in the argument list5066// order.5067void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {5068unsigned GpOffset = 0;5069unsigned FpOffset = AMD64GpEndOffset;5070unsigned OverflowOffset = AMD64FpEndOffset;5071const DataLayout &DL = F.getDataLayout();50725073for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {5074bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();5075bool IsByVal = CB.paramHasAttr(ArgNo, Attribute::ByVal);5076if (IsByVal) {5077// ByVal arguments always go to the overflow area.5078// Fixed arguments passed through the overflow area will be stepped5079// over by va_start, so don't count them towards the offset.5080if (IsFixed)5081continue;5082assert(A->getType()->isPointerTy());5083Type *RealTy = CB.getParamByValType(ArgNo);5084uint64_t ArgSize = DL.getTypeAllocSize(RealTy);5085uint64_t AlignedSize = alignTo(ArgSize, 8);5086unsigned BaseOffset = OverflowOffset;5087Value *ShadowBase =5088getShadowPtrForVAArgument(RealTy, IRB, OverflowOffset);5089Value *OriginBase = nullptr;5090if (MS.TrackOrigins)5091OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);5092OverflowOffset += AlignedSize;50935094if (OverflowOffset > kParamTLSSize) {5095CleanUnusedTLS(IRB, ShadowBase, BaseOffset);5096continue; // We have no space to copy shadow there.5097}50985099Value *ShadowPtr, *OriginPtr;5100std::tie(ShadowPtr, OriginPtr) =5101MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), kShadowTLSAlignment,5102/*isStore*/ false);5103IRB.CreateMemCpy(ShadowBase, kShadowTLSAlignment, ShadowPtr,5104kShadowTLSAlignment, ArgSize);5105if (MS.TrackOrigins)5106IRB.CreateMemCpy(OriginBase, kShadowTLSAlignment, OriginPtr,5107kShadowTLSAlignment, ArgSize);5108} else {5109ArgKind AK = classifyArgument(A);5110if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)5111AK = AK_Memory;5112if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)5113AK = AK_Memory;5114Value *ShadowBase, *OriginBase = nullptr;5115switch (AK) {5116case AK_GeneralPurpose:5117ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, GpOffset);5118if (MS.TrackOrigins)5119OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);5120GpOffset += 8;5121assert(GpOffset <= kParamTLSSize);5122break;5123case AK_FloatingPoint:5124ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, FpOffset);5125if (MS.TrackOrigins)5126OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);5127FpOffset += 16;5128assert(FpOffset <= kParamTLSSize);5129break;5130case AK_Memory:5131if (IsFixed)5132continue;5133uint64_t ArgSize = DL.getTypeAllocSize(A->getType());5134uint64_t AlignedSize = alignTo(ArgSize, 8);5135unsigned BaseOffset = OverflowOffset;5136ShadowBase =5137getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset);5138if (MS.TrackOrigins) {5139OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);5140}5141OverflowOffset += AlignedSize;5142if (OverflowOffset > kParamTLSSize) {5143// We have no space to copy shadow there.5144CleanUnusedTLS(IRB, ShadowBase, BaseOffset);5145continue;5146}5147}5148// Take fixed arguments into account for GpOffset and FpOffset,5149// but don't actually store shadows for them.5150// TODO(glider): don't call get*PtrForVAArgument() for them.5151if (IsFixed)5152continue;5153Value *Shadow = MSV.getShadow(A);5154IRB.CreateAlignedStore(Shadow, ShadowBase, kShadowTLSAlignment);5155if (MS.TrackOrigins) {5156Value *Origin = MSV.getOrigin(A);5157TypeSize StoreSize = DL.getTypeStoreSize(Shadow->getType());5158MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,5159std::max(kShadowTLSAlignment, kMinOriginAlignment));5160}5161}5162}5163Constant *OverflowSize =5164ConstantInt::get(IRB.getInt64Ty(), OverflowOffset - AMD64FpEndOffset);5165IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);5166}51675168void finalizeInstrumentation() override {5169assert(!VAArgOverflowSize && !VAArgTLSCopy &&5170"finalizeInstrumentation called twice");5171if (!VAStartInstrumentationList.empty()) {5172// If there is a va_start in this function, make a backup copy of5173// va_arg_tls somewhere in the function entry block.5174IRBuilder<> IRB(MSV.FnPrologueEnd);5175VAArgOverflowSize =5176IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);5177Value *CopySize = IRB.CreateAdd(5178ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);5179VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);5180VAArgTLSCopy->setAlignment(kShadowTLSAlignment);5181IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),5182CopySize, kShadowTLSAlignment, false);51835184Value *SrcSize = IRB.CreateBinaryIntrinsic(5185Intrinsic::umin, CopySize,5186ConstantInt::get(MS.IntptrTy, kParamTLSSize));5187IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,5188kShadowTLSAlignment, SrcSize);5189if (MS.TrackOrigins) {5190VAArgTLSOriginCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);5191VAArgTLSOriginCopy->setAlignment(kShadowTLSAlignment);5192IRB.CreateMemCpy(VAArgTLSOriginCopy, kShadowTLSAlignment,5193MS.VAArgOriginTLS, kShadowTLSAlignment, SrcSize);5194}5195}51965197// Instrument va_start.5198// Copy va_list shadow from the backup copy of the TLS contents.5199for (CallInst *OrigInst : VAStartInstrumentationList) {5200NextNodeIRBuilder IRB(OrigInst);5201Value *VAListTag = OrigInst->getArgOperand(0);52025203Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*5204Value *RegSaveAreaPtrPtr = IRB.CreateIntToPtr(5205IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5206ConstantInt::get(MS.IntptrTy, 16)),5207PointerType::get(RegSaveAreaPtrTy, 0));5208Value *RegSaveAreaPtr =5209IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);5210Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;5211const Align Alignment = Align(16);5212std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =5213MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(),5214Alignment, /*isStore*/ true);5215IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,5216AMD64FpEndOffset);5217if (MS.TrackOrigins)5218IRB.CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,5219Alignment, AMD64FpEndOffset);5220Type *OverflowArgAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*5221Value *OverflowArgAreaPtrPtr = IRB.CreateIntToPtr(5222IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5223ConstantInt::get(MS.IntptrTy, 8)),5224PointerType::get(OverflowArgAreaPtrTy, 0));5225Value *OverflowArgAreaPtr =5226IRB.CreateLoad(OverflowArgAreaPtrTy, OverflowArgAreaPtrPtr);5227Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;5228std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =5229MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.getInt8Ty(),5230Alignment, /*isStore*/ true);5231Value *SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSCopy,5232AMD64FpEndOffset);5233IRB.CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,5234VAArgOverflowSize);5235if (MS.TrackOrigins) {5236SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSOriginCopy,5237AMD64FpEndOffset);5238IRB.CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,5239VAArgOverflowSize);5240}5241}5242}5243};52445245/// MIPS64-specific implementation of VarArgHelper.5246/// NOTE: This is also used for LoongArch64.5247struct VarArgMIPS64Helper : public VarArgHelperBase {5248AllocaInst *VAArgTLSCopy = nullptr;5249Value *VAArgSize = nullptr;52505251VarArgMIPS64Helper(Function &F, MemorySanitizer &MS,5252MemorySanitizerVisitor &MSV)5253: VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/8) {}52545255void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {5256unsigned VAArgOffset = 0;5257const DataLayout &DL = F.getDataLayout();5258for (Value *A :5259llvm::drop_begin(CB.args(), CB.getFunctionType()->getNumParams())) {5260Triple TargetTriple(F.getParent()->getTargetTriple());5261Value *Base;5262uint64_t ArgSize = DL.getTypeAllocSize(A->getType());5263if (TargetTriple.getArch() == Triple::mips64) {5264// Adjusting the shadow for argument with size < 8 to match the5265// placement of bits in big endian system5266if (ArgSize < 8)5267VAArgOffset += (8 - ArgSize);5268}5269Base = getShadowPtrForVAArgument(A->getType(), IRB, VAArgOffset, ArgSize);5270VAArgOffset += ArgSize;5271VAArgOffset = alignTo(VAArgOffset, 8);5272if (!Base)5273continue;5274IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);5275}52765277Constant *TotalVAArgSize = ConstantInt::get(IRB.getInt64Ty(), VAArgOffset);5278// Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of5279// a new class member i.e. it is the total size of all VarArgs.5280IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);5281}52825283void finalizeInstrumentation() override {5284assert(!VAArgSize && !VAArgTLSCopy &&5285"finalizeInstrumentation called twice");5286IRBuilder<> IRB(MSV.FnPrologueEnd);5287VAArgSize = IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);5288Value *CopySize =5289IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, 0), VAArgSize);52905291if (!VAStartInstrumentationList.empty()) {5292// If there is a va_start in this function, make a backup copy of5293// va_arg_tls somewhere in the function entry block.5294VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);5295VAArgTLSCopy->setAlignment(kShadowTLSAlignment);5296IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),5297CopySize, kShadowTLSAlignment, false);52985299Value *SrcSize = IRB.CreateBinaryIntrinsic(5300Intrinsic::umin, CopySize,5301ConstantInt::get(MS.IntptrTy, kParamTLSSize));5302IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,5303kShadowTLSAlignment, SrcSize);5304}53055306// Instrument va_start.5307// Copy va_list shadow from the backup copy of the TLS contents.5308for (CallInst *OrigInst : VAStartInstrumentationList) {5309NextNodeIRBuilder IRB(OrigInst);5310Value *VAListTag = OrigInst->getArgOperand(0);5311Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*5312Value *RegSaveAreaPtrPtr =5313IRB.CreateIntToPtr(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5314PointerType::get(RegSaveAreaPtrTy, 0));5315Value *RegSaveAreaPtr =5316IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);5317Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;5318const Align Alignment = Align(8);5319std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =5320MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(),5321Alignment, /*isStore*/ true);5322IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,5323CopySize);5324}5325}5326};53275328/// AArch64-specific implementation of VarArgHelper.5329struct VarArgAArch64Helper : public VarArgHelperBase {5330static const unsigned kAArch64GrArgSize = 64;5331static const unsigned kAArch64VrArgSize = 128;53325333static const unsigned AArch64GrBegOffset = 0;5334static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;5335// Make VR space aligned to 16 bytes.5336static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;5337static const unsigned AArch64VrEndOffset =5338AArch64VrBegOffset + kAArch64VrArgSize;5339static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;53405341AllocaInst *VAArgTLSCopy = nullptr;5342Value *VAArgOverflowSize = nullptr;53435344enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };53455346VarArgAArch64Helper(Function &F, MemorySanitizer &MS,5347MemorySanitizerVisitor &MSV)5348: VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/32) {}53495350// A very rough approximation of aarch64 argument classification rules.5351std::pair<ArgKind, uint64_t> classifyArgument(Type *T) {5352if (T->isIntOrPtrTy() && T->getPrimitiveSizeInBits() <= 64)5353return {AK_GeneralPurpose, 1};5354if (T->isFloatingPointTy() && T->getPrimitiveSizeInBits() <= 128)5355return {AK_FloatingPoint, 1};53565357if (T->isArrayTy()) {5358auto R = classifyArgument(T->getArrayElementType());5359R.second *= T->getScalarType()->getArrayNumElements();5360return R;5361}53625363if (const FixedVectorType *FV = dyn_cast<FixedVectorType>(T)) {5364auto R = classifyArgument(FV->getScalarType());5365R.second *= FV->getNumElements();5366return R;5367}53685369LLVM_DEBUG(errs() << "Unknown vararg type: " << *T << "\n");5370return {AK_Memory, 0};5371}53725373// The instrumentation stores the argument shadow in a non ABI-specific5374// format because it does not know which argument is named (since Clang,5375// like x86_64 case, lowers the va_args in the frontend and this pass only5376// sees the low level code that deals with va_list internals).5377// The first seven GR registers are saved in the first 56 bytes of the5378// va_arg tls arra, followed by the first 8 FP/SIMD registers, and then5379// the remaining arguments.5380// Using constant offset within the va_arg TLS array allows fast copy5381// in the finalize instrumentation.5382void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {5383unsigned GrOffset = AArch64GrBegOffset;5384unsigned VrOffset = AArch64VrBegOffset;5385unsigned OverflowOffset = AArch64VAEndOffset;53865387const DataLayout &DL = F.getDataLayout();5388for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {5389bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();5390auto [AK, RegNum] = classifyArgument(A->getType());5391if (AK == AK_GeneralPurpose &&5392(GrOffset + RegNum * 8) > AArch64GrEndOffset)5393AK = AK_Memory;5394if (AK == AK_FloatingPoint &&5395(VrOffset + RegNum * 16) > AArch64VrEndOffset)5396AK = AK_Memory;5397Value *Base;5398switch (AK) {5399case AK_GeneralPurpose:5400Base = getShadowPtrForVAArgument(A->getType(), IRB, GrOffset);5401GrOffset += 8 * RegNum;5402break;5403case AK_FloatingPoint:5404Base = getShadowPtrForVAArgument(A->getType(), IRB, VrOffset);5405VrOffset += 16 * RegNum;5406break;5407case AK_Memory:5408// Don't count fixed arguments in the overflow area - va_start will5409// skip right over them.5410if (IsFixed)5411continue;5412uint64_t ArgSize = DL.getTypeAllocSize(A->getType());5413uint64_t AlignedSize = alignTo(ArgSize, 8);5414unsigned BaseOffset = OverflowOffset;5415Base = getShadowPtrForVAArgument(A->getType(), IRB, BaseOffset);5416OverflowOffset += AlignedSize;5417if (OverflowOffset > kParamTLSSize) {5418// We have no space to copy shadow there.5419CleanUnusedTLS(IRB, Base, BaseOffset);5420continue;5421}5422break;5423}5424// Count Gp/Vr fixed arguments to their respective offsets, but don't5425// bother to actually store a shadow.5426if (IsFixed)5427continue;5428IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);5429}5430Constant *OverflowSize =5431ConstantInt::get(IRB.getInt64Ty(), OverflowOffset - AArch64VAEndOffset);5432IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);5433}54345435// Retrieve a va_list field of 'void*' size.5436Value *getVAField64(IRBuilder<> &IRB, Value *VAListTag, int offset) {5437Value *SaveAreaPtrPtr = IRB.CreateIntToPtr(5438IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5439ConstantInt::get(MS.IntptrTy, offset)),5440PointerType::get(*MS.C, 0));5441return IRB.CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);5442}54435444// Retrieve a va_list field of 'int' size.5445Value *getVAField32(IRBuilder<> &IRB, Value *VAListTag, int offset) {5446Value *SaveAreaPtr = IRB.CreateIntToPtr(5447IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5448ConstantInt::get(MS.IntptrTy, offset)),5449PointerType::get(*MS.C, 0));5450Value *SaveArea32 = IRB.CreateLoad(IRB.getInt32Ty(), SaveAreaPtr);5451return IRB.CreateSExt(SaveArea32, MS.IntptrTy);5452}54535454void finalizeInstrumentation() override {5455assert(!VAArgOverflowSize && !VAArgTLSCopy &&5456"finalizeInstrumentation called twice");5457if (!VAStartInstrumentationList.empty()) {5458// If there is a va_start in this function, make a backup copy of5459// va_arg_tls somewhere in the function entry block.5460IRBuilder<> IRB(MSV.FnPrologueEnd);5461VAArgOverflowSize =5462IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);5463Value *CopySize = IRB.CreateAdd(5464ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);5465VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);5466VAArgTLSCopy->setAlignment(kShadowTLSAlignment);5467IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),5468CopySize, kShadowTLSAlignment, false);54695470Value *SrcSize = IRB.CreateBinaryIntrinsic(5471Intrinsic::umin, CopySize,5472ConstantInt::get(MS.IntptrTy, kParamTLSSize));5473IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,5474kShadowTLSAlignment, SrcSize);5475}54765477Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);5478Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);54795480// Instrument va_start, copy va_list shadow from the backup copy of5481// the TLS contents.5482for (CallInst *OrigInst : VAStartInstrumentationList) {5483NextNodeIRBuilder IRB(OrigInst);54845485Value *VAListTag = OrigInst->getArgOperand(0);54865487// The variadic ABI for AArch64 creates two areas to save the incoming5488// argument registers (one for 64-bit general register xn-x7 and another5489// for 128-bit FP/SIMD vn-v7).5490// We need then to propagate the shadow arguments on both regions5491// 'va::__gr_top + va::__gr_offs' and 'va::__vr_top + va::__vr_offs'.5492// The remaining arguments are saved on shadow for 'va::stack'.5493// One caveat is it requires only to propagate the non-named arguments,5494// however on the call site instrumentation 'all' the arguments are5495// saved. So to copy the shadow values from the va_arg TLS array5496// we need to adjust the offset for both GR and VR fields based on5497// the __{gr,vr}_offs value (since they are stores based on incoming5498// named arguments).5499Type *RegSaveAreaPtrTy = IRB.getPtrTy();55005501// Read the stack pointer from the va_list.5502Value *StackSaveAreaPtr =5503IRB.CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);55045505// Read both the __gr_top and __gr_off and add them up.5506Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);5507Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);55085509Value *GrRegSaveAreaPtr = IRB.CreateIntToPtr(5510IRB.CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);55115512// Read both the __vr_top and __vr_off and add them up.5513Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);5514Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);55155516Value *VrRegSaveAreaPtr = IRB.CreateIntToPtr(5517IRB.CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);55185519// It does not know how many named arguments is being used and, on the5520// callsite all the arguments were saved. Since __gr_off is defined as5521// '0 - ((8 - named_gr) * 8)', the idea is to just propagate the variadic5522// argument by ignoring the bytes of shadow from named arguments.5523Value *GrRegSaveAreaShadowPtrOff =5524IRB.CreateAdd(GrArgSize, GrOffSaveArea);55255526Value *GrRegSaveAreaShadowPtr =5527MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.getInt8Ty(),5528Align(8), /*isStore*/ true)5529.first;55305531Value *GrSrcPtr =5532IRB.CreateInBoundsPtrAdd(VAArgTLSCopy, GrRegSaveAreaShadowPtrOff);5533Value *GrCopySize = IRB.CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);55345535IRB.CreateMemCpy(GrRegSaveAreaShadowPtr, Align(8), GrSrcPtr, Align(8),5536GrCopySize);55375538// Again, but for FP/SIMD values.5539Value *VrRegSaveAreaShadowPtrOff =5540IRB.CreateAdd(VrArgSize, VrOffSaveArea);55415542Value *VrRegSaveAreaShadowPtr =5543MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.getInt8Ty(),5544Align(8), /*isStore*/ true)5545.first;55465547Value *VrSrcPtr = IRB.CreateInBoundsPtrAdd(5548IRB.CreateInBoundsPtrAdd(VAArgTLSCopy,5549IRB.getInt32(AArch64VrBegOffset)),5550VrRegSaveAreaShadowPtrOff);5551Value *VrCopySize = IRB.CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);55525553IRB.CreateMemCpy(VrRegSaveAreaShadowPtr, Align(8), VrSrcPtr, Align(8),5554VrCopySize);55555556// And finally for remaining arguments.5557Value *StackSaveAreaShadowPtr =5558MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.getInt8Ty(),5559Align(16), /*isStore*/ true)5560.first;55615562Value *StackSrcPtr = IRB.CreateInBoundsPtrAdd(5563VAArgTLSCopy, IRB.getInt32(AArch64VAEndOffset));55645565IRB.CreateMemCpy(StackSaveAreaShadowPtr, Align(16), StackSrcPtr,5566Align(16), VAArgOverflowSize);5567}5568}5569};55705571/// PowerPC64-specific implementation of VarArgHelper.5572struct VarArgPowerPC64Helper : public VarArgHelperBase {5573AllocaInst *VAArgTLSCopy = nullptr;5574Value *VAArgSize = nullptr;55755576VarArgPowerPC64Helper(Function &F, MemorySanitizer &MS,5577MemorySanitizerVisitor &MSV)5578: VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/8) {}55795580void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {5581// For PowerPC, we need to deal with alignment of stack arguments -5582// they are mostly aligned to 8 bytes, but vectors and i128 arrays5583// are aligned to 16 bytes, byvals can be aligned to 8 or 16 bytes,5584// For that reason, we compute current offset from stack pointer (which is5585// always properly aligned), and offset for the first vararg, then subtract5586// them.5587unsigned VAArgBase;5588Triple TargetTriple(F.getParent()->getTargetTriple());5589// Parameter save area starts at 48 bytes from frame pointer for ABIv1,5590// and 32 bytes for ABIv2. This is usually determined by target5591// endianness, but in theory could be overridden by function attribute.5592if (TargetTriple.getArch() == Triple::ppc64)5593VAArgBase = 48;5594else5595VAArgBase = 32;5596unsigned VAArgOffset = VAArgBase;5597const DataLayout &DL = F.getDataLayout();5598for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {5599bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();5600bool IsByVal = CB.paramHasAttr(ArgNo, Attribute::ByVal);5601if (IsByVal) {5602assert(A->getType()->isPointerTy());5603Type *RealTy = CB.getParamByValType(ArgNo);5604uint64_t ArgSize = DL.getTypeAllocSize(RealTy);5605Align ArgAlign = CB.getParamAlign(ArgNo).value_or(Align(8));5606if (ArgAlign < 8)5607ArgAlign = Align(8);5608VAArgOffset = alignTo(VAArgOffset, ArgAlign);5609if (!IsFixed) {5610Value *Base = getShadowPtrForVAArgument(5611RealTy, IRB, VAArgOffset - VAArgBase, ArgSize);5612if (Base) {5613Value *AShadowPtr, *AOriginPtr;5614std::tie(AShadowPtr, AOriginPtr) =5615MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(),5616kShadowTLSAlignment, /*isStore*/ false);56175618IRB.CreateMemCpy(Base, kShadowTLSAlignment, AShadowPtr,5619kShadowTLSAlignment, ArgSize);5620}5621}5622VAArgOffset += alignTo(ArgSize, Align(8));5623} else {5624Value *Base;5625uint64_t ArgSize = DL.getTypeAllocSize(A->getType());5626Align ArgAlign = Align(8);5627if (A->getType()->isArrayTy()) {5628// Arrays are aligned to element size, except for long double5629// arrays, which are aligned to 8 bytes.5630Type *ElementTy = A->getType()->getArrayElementType();5631if (!ElementTy->isPPC_FP128Ty())5632ArgAlign = Align(DL.getTypeAllocSize(ElementTy));5633} else if (A->getType()->isVectorTy()) {5634// Vectors are naturally aligned.5635ArgAlign = Align(ArgSize);5636}5637if (ArgAlign < 8)5638ArgAlign = Align(8);5639VAArgOffset = alignTo(VAArgOffset, ArgAlign);5640if (DL.isBigEndian()) {5641// Adjusting the shadow for argument with size < 8 to match the5642// placement of bits in big endian system5643if (ArgSize < 8)5644VAArgOffset += (8 - ArgSize);5645}5646if (!IsFixed) {5647Base = getShadowPtrForVAArgument(A->getType(), IRB,5648VAArgOffset - VAArgBase, ArgSize);5649if (Base)5650IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);5651}5652VAArgOffset += ArgSize;5653VAArgOffset = alignTo(VAArgOffset, Align(8));5654}5655if (IsFixed)5656VAArgBase = VAArgOffset;5657}56585659Constant *TotalVAArgSize =5660ConstantInt::get(IRB.getInt64Ty(), VAArgOffset - VAArgBase);5661// Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of5662// a new class member i.e. it is the total size of all VarArgs.5663IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);5664}56655666void finalizeInstrumentation() override {5667assert(!VAArgSize && !VAArgTLSCopy &&5668"finalizeInstrumentation called twice");5669IRBuilder<> IRB(MSV.FnPrologueEnd);5670VAArgSize = IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);5671Value *CopySize =5672IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, 0), VAArgSize);56735674if (!VAStartInstrumentationList.empty()) {5675// If there is a va_start in this function, make a backup copy of5676// va_arg_tls somewhere in the function entry block.56775678VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);5679VAArgTLSCopy->setAlignment(kShadowTLSAlignment);5680IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),5681CopySize, kShadowTLSAlignment, false);56825683Value *SrcSize = IRB.CreateBinaryIntrinsic(5684Intrinsic::umin, CopySize,5685ConstantInt::get(MS.IntptrTy, kParamTLSSize));5686IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,5687kShadowTLSAlignment, SrcSize);5688}56895690// Instrument va_start.5691// Copy va_list shadow from the backup copy of the TLS contents.5692for (CallInst *OrigInst : VAStartInstrumentationList) {5693NextNodeIRBuilder IRB(OrigInst);5694Value *VAListTag = OrigInst->getArgOperand(0);5695Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*5696Value *RegSaveAreaPtrPtr =5697IRB.CreateIntToPtr(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5698PointerType::get(RegSaveAreaPtrTy, 0));5699Value *RegSaveAreaPtr =5700IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);5701Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;5702const Align Alignment = Align(8);5703std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =5704MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(),5705Alignment, /*isStore*/ true);5706IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,5707CopySize);5708}5709}5710};57115712/// SystemZ-specific implementation of VarArgHelper.5713struct VarArgSystemZHelper : public VarArgHelperBase {5714static const unsigned SystemZGpOffset = 16;5715static const unsigned SystemZGpEndOffset = 56;5716static const unsigned SystemZFpOffset = 128;5717static const unsigned SystemZFpEndOffset = 160;5718static const unsigned SystemZMaxVrArgs = 8;5719static const unsigned SystemZRegSaveAreaSize = 160;5720static const unsigned SystemZOverflowOffset = 160;5721static const unsigned SystemZVAListTagSize = 32;5722static const unsigned SystemZOverflowArgAreaPtrOffset = 16;5723static const unsigned SystemZRegSaveAreaPtrOffset = 24;57245725bool IsSoftFloatABI;5726AllocaInst *VAArgTLSCopy = nullptr;5727AllocaInst *VAArgTLSOriginCopy = nullptr;5728Value *VAArgOverflowSize = nullptr;57295730enum class ArgKind {5731GeneralPurpose,5732FloatingPoint,5733Vector,5734Memory,5735Indirect,5736};57375738enum class ShadowExtension { None, Zero, Sign };57395740VarArgSystemZHelper(Function &F, MemorySanitizer &MS,5741MemorySanitizerVisitor &MSV)5742: VarArgHelperBase(F, MS, MSV, SystemZVAListTagSize),5743IsSoftFloatABI(F.getFnAttribute("use-soft-float").getValueAsBool()) {}57445745ArgKind classifyArgument(Type *T) {5746// T is a SystemZABIInfo::classifyArgumentType() output, and there are5747// only a few possibilities of what it can be. In particular, enums, single5748// element structs and large types have already been taken care of.57495750// Some i128 and fp128 arguments are converted to pointers only in the5751// back end.5752if (T->isIntegerTy(128) || T->isFP128Ty())5753return ArgKind::Indirect;5754if (T->isFloatingPointTy())5755return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;5756if (T->isIntegerTy() || T->isPointerTy())5757return ArgKind::GeneralPurpose;5758if (T->isVectorTy())5759return ArgKind::Vector;5760return ArgKind::Memory;5761}57625763ShadowExtension getShadowExtension(const CallBase &CB, unsigned ArgNo) {5764// ABI says: "One of the simple integer types no more than 64 bits wide.5765// ... If such an argument is shorter than 64 bits, replace it by a full5766// 64-bit integer representing the same number, using sign or zero5767// extension". Shadow for an integer argument has the same type as the5768// argument itself, so it can be sign or zero extended as well.5769bool ZExt = CB.paramHasAttr(ArgNo, Attribute::ZExt);5770bool SExt = CB.paramHasAttr(ArgNo, Attribute::SExt);5771if (ZExt) {5772assert(!SExt);5773return ShadowExtension::Zero;5774}5775if (SExt) {5776assert(!ZExt);5777return ShadowExtension::Sign;5778}5779return ShadowExtension::None;5780}57815782void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {5783unsigned GpOffset = SystemZGpOffset;5784unsigned FpOffset = SystemZFpOffset;5785unsigned VrIndex = 0;5786unsigned OverflowOffset = SystemZOverflowOffset;5787const DataLayout &DL = F.getDataLayout();5788for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {5789bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();5790// SystemZABIInfo does not produce ByVal parameters.5791assert(!CB.paramHasAttr(ArgNo, Attribute::ByVal));5792Type *T = A->getType();5793ArgKind AK = classifyArgument(T);5794if (AK == ArgKind::Indirect) {5795T = PointerType::get(T, 0);5796AK = ArgKind::GeneralPurpose;5797}5798if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)5799AK = ArgKind::Memory;5800if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)5801AK = ArgKind::Memory;5802if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))5803AK = ArgKind::Memory;5804Value *ShadowBase = nullptr;5805Value *OriginBase = nullptr;5806ShadowExtension SE = ShadowExtension::None;5807switch (AK) {5808case ArgKind::GeneralPurpose: {5809// Always keep track of GpOffset, but store shadow only for varargs.5810uint64_t ArgSize = 8;5811if (GpOffset + ArgSize <= kParamTLSSize) {5812if (!IsFixed) {5813SE = getShadowExtension(CB, ArgNo);5814uint64_t GapSize = 0;5815if (SE == ShadowExtension::None) {5816uint64_t ArgAllocSize = DL.getTypeAllocSize(T);5817assert(ArgAllocSize <= ArgSize);5818GapSize = ArgSize - ArgAllocSize;5819}5820ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);5821if (MS.TrackOrigins)5822OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);5823}5824GpOffset += ArgSize;5825} else {5826GpOffset = kParamTLSSize;5827}5828break;5829}5830case ArgKind::FloatingPoint: {5831// Always keep track of FpOffset, but store shadow only for varargs.5832uint64_t ArgSize = 8;5833if (FpOffset + ArgSize <= kParamTLSSize) {5834if (!IsFixed) {5835// PoP says: "A short floating-point datum requires only the5836// left-most 32 bit positions of a floating-point register".5837// Therefore, in contrast to AK_GeneralPurpose and AK_Memory,5838// don't extend shadow and don't mind the gap.5839ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);5840if (MS.TrackOrigins)5841OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);5842}5843FpOffset += ArgSize;5844} else {5845FpOffset = kParamTLSSize;5846}5847break;5848}5849case ArgKind::Vector: {5850// Keep track of VrIndex. No need to store shadow, since vector varargs5851// go through AK_Memory.5852assert(IsFixed);5853VrIndex++;5854break;5855}5856case ArgKind::Memory: {5857// Keep track of OverflowOffset and store shadow only for varargs.5858// Ignore fixed args, since we need to copy only the vararg portion of5859// the overflow area shadow.5860if (!IsFixed) {5861uint64_t ArgAllocSize = DL.getTypeAllocSize(T);5862uint64_t ArgSize = alignTo(ArgAllocSize, 8);5863if (OverflowOffset + ArgSize <= kParamTLSSize) {5864SE = getShadowExtension(CB, ArgNo);5865uint64_t GapSize =5866SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;5867ShadowBase =5868getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);5869if (MS.TrackOrigins)5870OriginBase =5871getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);5872OverflowOffset += ArgSize;5873} else {5874OverflowOffset = kParamTLSSize;5875}5876}5877break;5878}5879case ArgKind::Indirect:5880llvm_unreachable("Indirect must be converted to GeneralPurpose");5881}5882if (ShadowBase == nullptr)5883continue;5884Value *Shadow = MSV.getShadow(A);5885if (SE != ShadowExtension::None)5886Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.getInt64Ty(),5887/*Signed*/ SE == ShadowExtension::Sign);5888ShadowBase = IRB.CreateIntToPtr(5889ShadowBase, PointerType::get(Shadow->getType(), 0), "_msarg_va_s");5890IRB.CreateStore(Shadow, ShadowBase);5891if (MS.TrackOrigins) {5892Value *Origin = MSV.getOrigin(A);5893TypeSize StoreSize = DL.getTypeStoreSize(Shadow->getType());5894MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,5895kMinOriginAlignment);5896}5897}5898Constant *OverflowSize = ConstantInt::get(5899IRB.getInt64Ty(), OverflowOffset - SystemZOverflowOffset);5900IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);5901}59025903void copyRegSaveArea(IRBuilder<> &IRB, Value *VAListTag) {5904Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*5905Value *RegSaveAreaPtrPtr = IRB.CreateIntToPtr(5906IRB.CreateAdd(5907IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5908ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),5909PointerType::get(RegSaveAreaPtrTy, 0));5910Value *RegSaveAreaPtr = IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);5911Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;5912const Align Alignment = Align(8);5913std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =5914MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(), Alignment,5915/*isStore*/ true);5916// TODO(iii): copy only fragments filled by visitCallBase()5917// TODO(iii): support packed-stack && !use-soft-float5918// For use-soft-float functions, it is enough to copy just the GPRs.5919unsigned RegSaveAreaSize =5920IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;5921IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,5922RegSaveAreaSize);5923if (MS.TrackOrigins)5924IRB.CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,5925Alignment, RegSaveAreaSize);5926}59275928// FIXME: This implementation limits OverflowOffset to kParamTLSSize, so we5929// don't know real overflow size and can't clear shadow beyond kParamTLSSize.5930void copyOverflowArea(IRBuilder<> &IRB, Value *VAListTag) {5931Type *OverflowArgAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*5932Value *OverflowArgAreaPtrPtr = IRB.CreateIntToPtr(5933IRB.CreateAdd(5934IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),5935ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),5936PointerType::get(OverflowArgAreaPtrTy, 0));5937Value *OverflowArgAreaPtr =5938IRB.CreateLoad(OverflowArgAreaPtrTy, OverflowArgAreaPtrPtr);5939Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;5940const Align Alignment = Align(8);5941std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =5942MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.getInt8Ty(),5943Alignment, /*isStore*/ true);5944Value *SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSCopy,5945SystemZOverflowOffset);5946IRB.CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,5947VAArgOverflowSize);5948if (MS.TrackOrigins) {5949SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSOriginCopy,5950SystemZOverflowOffset);5951IRB.CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,5952VAArgOverflowSize);5953}5954}59555956void finalizeInstrumentation() override {5957assert(!VAArgOverflowSize && !VAArgTLSCopy &&5958"finalizeInstrumentation called twice");5959if (!VAStartInstrumentationList.empty()) {5960// If there is a va_start in this function, make a backup copy of5961// va_arg_tls somewhere in the function entry block.5962IRBuilder<> IRB(MSV.FnPrologueEnd);5963VAArgOverflowSize =5964IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);5965Value *CopySize =5966IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),5967VAArgOverflowSize);5968VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);5969VAArgTLSCopy->setAlignment(kShadowTLSAlignment);5970IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),5971CopySize, kShadowTLSAlignment, false);59725973Value *SrcSize = IRB.CreateBinaryIntrinsic(5974Intrinsic::umin, CopySize,5975ConstantInt::get(MS.IntptrTy, kParamTLSSize));5976IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,5977kShadowTLSAlignment, SrcSize);5978if (MS.TrackOrigins) {5979VAArgTLSOriginCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);5980VAArgTLSOriginCopy->setAlignment(kShadowTLSAlignment);5981IRB.CreateMemCpy(VAArgTLSOriginCopy, kShadowTLSAlignment,5982MS.VAArgOriginTLS, kShadowTLSAlignment, SrcSize);5983}5984}59855986// Instrument va_start.5987// Copy va_list shadow from the backup copy of the TLS contents.5988for (CallInst *OrigInst : VAStartInstrumentationList) {5989NextNodeIRBuilder IRB(OrigInst);5990Value *VAListTag = OrigInst->getArgOperand(0);5991copyRegSaveArea(IRB, VAListTag);5992copyOverflowArea(IRB, VAListTag);5993}5994}5995};59965997// Loongarch64 is not a MIPS, but the current vargs calling convention matches5998// the MIPS.5999using VarArgLoongArch64Helper = VarArgMIPS64Helper;60006001/// A no-op implementation of VarArgHelper.6002struct VarArgNoOpHelper : public VarArgHelper {6003VarArgNoOpHelper(Function &F, MemorySanitizer &MS,6004MemorySanitizerVisitor &MSV) {}60056006void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {}60076008void visitVAStartInst(VAStartInst &I) override {}60096010void visitVACopyInst(VACopyInst &I) override {}60116012void finalizeInstrumentation() override {}6013};60146015} // end anonymous namespace60166017static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,6018MemorySanitizerVisitor &Visitor) {6019// VarArg handling is only implemented on AMD64. False positives are possible6020// on other platforms.6021Triple TargetTriple(Func.getParent()->getTargetTriple());6022if (TargetTriple.getArch() == Triple::x86_64)6023return new VarArgAMD64Helper(Func, Msan, Visitor);6024else if (TargetTriple.isMIPS64())6025return new VarArgMIPS64Helper(Func, Msan, Visitor);6026else if (TargetTriple.getArch() == Triple::aarch64)6027return new VarArgAArch64Helper(Func, Msan, Visitor);6028else if (TargetTriple.getArch() == Triple::ppc64 ||6029TargetTriple.getArch() == Triple::ppc64le)6030return new VarArgPowerPC64Helper(Func, Msan, Visitor);6031else if (TargetTriple.getArch() == Triple::systemz)6032return new VarArgSystemZHelper(Func, Msan, Visitor);6033else if (TargetTriple.isLoongArch64())6034return new VarArgLoongArch64Helper(Func, Msan, Visitor);6035else6036return new VarArgNoOpHelper(Func, Msan, Visitor);6037}60386039bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) {6040if (!CompileKernel && F.getName() == kMsanModuleCtorName)6041return false;60426043if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))6044return false;60456046MemorySanitizerVisitor Visitor(F, *this, TLI);60476048// Clear out memory attributes.6049AttributeMask B;6050B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);6051F.removeFnAttrs(B);60526053return Visitor.runOnFunction();6054}605560566057