1bdd1243dSDimitry Andric //===- SanitizerBinaryMetadata.cpp - binary analysis sanitizers metadata --===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric // This file is a part of SanitizerBinaryMetadata. 10bdd1243dSDimitry Andric // 11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h" 14bdd1243dSDimitry Andric #include "llvm/ADT/SetVector.h" 15bdd1243dSDimitry Andric #include "llvm/ADT/SmallVector.h" 16bdd1243dSDimitry Andric #include "llvm/ADT/Statistic.h" 17bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h" 18bdd1243dSDimitry Andric #include "llvm/ADT/Twine.h" 1906c3fb27SDimitry Andric #include "llvm/Analysis/CaptureTracking.h" 2006c3fb27SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 21bdd1243dSDimitry Andric #include "llvm/IR/Constant.h" 22bdd1243dSDimitry Andric #include "llvm/IR/DerivedTypes.h" 23bdd1243dSDimitry Andric #include "llvm/IR/Function.h" 24bdd1243dSDimitry Andric #include "llvm/IR/GlobalValue.h" 25bdd1243dSDimitry Andric #include "llvm/IR/GlobalVariable.h" 26bdd1243dSDimitry Andric #include "llvm/IR/IRBuilder.h" 27bdd1243dSDimitry Andric #include "llvm/IR/Instruction.h" 28bdd1243dSDimitry Andric #include "llvm/IR/Instructions.h" 29bdd1243dSDimitry Andric #include "llvm/IR/LLVMContext.h" 30bdd1243dSDimitry Andric #include "llvm/IR/MDBuilder.h" 31bdd1243dSDimitry Andric #include "llvm/IR/Metadata.h" 32bdd1243dSDimitry Andric #include "llvm/IR/Module.h" 33bdd1243dSDimitry Andric #include "llvm/IR/Type.h" 34bdd1243dSDimitry Andric #include "llvm/IR/Value.h" 3506c3fb27SDimitry Andric #include "llvm/ProfileData/InstrProf.h" 3606c3fb27SDimitry Andric #include "llvm/Support/Allocator.h" 37bdd1243dSDimitry Andric #include "llvm/Support/CommandLine.h" 38bdd1243dSDimitry Andric #include "llvm/Support/Debug.h" 3906c3fb27SDimitry Andric #include "llvm/Support/SpecialCaseList.h" 4006c3fb27SDimitry Andric #include "llvm/Support/StringSaver.h" 4106c3fb27SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 4206c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 43bdd1243dSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 44bdd1243dSDimitry Andric 45bdd1243dSDimitry Andric #include <array> 46bdd1243dSDimitry Andric #include <cstdint> 4706c3fb27SDimitry Andric #include <memory> 48bdd1243dSDimitry Andric 49bdd1243dSDimitry Andric using namespace llvm; 50bdd1243dSDimitry Andric 51bdd1243dSDimitry Andric #define DEBUG_TYPE "sanmd" 52bdd1243dSDimitry Andric 53bdd1243dSDimitry Andric namespace { 54bdd1243dSDimitry Andric 55bdd1243dSDimitry Andric //===--- Constants --------------------------------------------------------===// 56bdd1243dSDimitry Andric 5706c3fb27SDimitry Andric constexpr uint32_t kVersionBase = 2; // occupies lower 16 bits 58bdd1243dSDimitry Andric constexpr uint32_t kVersionPtrSizeRel = (1u << 16); // offsets are pointer-sized 59bdd1243dSDimitry Andric constexpr int kCtorDtorPriority = 2; 60bdd1243dSDimitry Andric 61bdd1243dSDimitry Andric // Pairs of names of initialization callback functions and which section 62bdd1243dSDimitry Andric // contains the relevant metadata. 63bdd1243dSDimitry Andric class MetadataInfo { 64bdd1243dSDimitry Andric public: 65bdd1243dSDimitry Andric const StringRef FunctionPrefix; 66bdd1243dSDimitry Andric const StringRef SectionSuffix; 67bdd1243dSDimitry Andric 68bdd1243dSDimitry Andric static const MetadataInfo Covered; 69bdd1243dSDimitry Andric static const MetadataInfo Atomics; 70bdd1243dSDimitry Andric 71bdd1243dSDimitry Andric private: 72bdd1243dSDimitry Andric // Forbid construction elsewhere. 73bdd1243dSDimitry Andric explicit constexpr MetadataInfo(StringRef FunctionPrefix, 7406c3fb27SDimitry Andric StringRef SectionSuffix) 7506c3fb27SDimitry Andric : FunctionPrefix(FunctionPrefix), SectionSuffix(SectionSuffix) {} 76bdd1243dSDimitry Andric }; 7706c3fb27SDimitry Andric const MetadataInfo MetadataInfo::Covered{ 7806c3fb27SDimitry Andric "__sanitizer_metadata_covered", kSanitizerBinaryMetadataCoveredSection}; 7906c3fb27SDimitry Andric const MetadataInfo MetadataInfo::Atomics{ 8006c3fb27SDimitry Andric "__sanitizer_metadata_atomics", kSanitizerBinaryMetadataAtomicsSection}; 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric // The only instances of MetadataInfo are the constants above, so a set of 83bdd1243dSDimitry Andric // them may simply store pointers to them. To deterministically generate code, 84bdd1243dSDimitry Andric // we need to use a set with stable iteration order, such as SetVector. 85bdd1243dSDimitry Andric using MetadataInfoSet = SetVector<const MetadataInfo *>; 86bdd1243dSDimitry Andric 87bdd1243dSDimitry Andric //===--- Command-line options ---------------------------------------------===// 88bdd1243dSDimitry Andric 89bdd1243dSDimitry Andric cl::opt<bool> ClWeakCallbacks( 90bdd1243dSDimitry Andric "sanitizer-metadata-weak-callbacks", 91bdd1243dSDimitry Andric cl::desc("Declare callbacks extern weak, and only call if non-null."), 92bdd1243dSDimitry Andric cl::Hidden, cl::init(true)); 9306c3fb27SDimitry Andric cl::opt<bool> 9406c3fb27SDimitry Andric ClNoSanitize("sanitizer-metadata-nosanitize-attr", 9506c3fb27SDimitry Andric cl::desc("Mark some metadata features uncovered in functions " 9606c3fb27SDimitry Andric "with associated no_sanitize attributes."), 9706c3fb27SDimitry Andric cl::Hidden, cl::init(true)); 98bdd1243dSDimitry Andric 99bdd1243dSDimitry Andric cl::opt<bool> ClEmitCovered("sanitizer-metadata-covered", 100bdd1243dSDimitry Andric cl::desc("Emit PCs for covered functions."), 101bdd1243dSDimitry Andric cl::Hidden, cl::init(false)); 102bdd1243dSDimitry Andric cl::opt<bool> ClEmitAtomics("sanitizer-metadata-atomics", 103bdd1243dSDimitry Andric cl::desc("Emit PCs for atomic operations."), 104bdd1243dSDimitry Andric cl::Hidden, cl::init(false)); 105bdd1243dSDimitry Andric cl::opt<bool> ClEmitUAR("sanitizer-metadata-uar", 106bdd1243dSDimitry Andric cl::desc("Emit PCs for start of functions that are " 107bdd1243dSDimitry Andric "subject for use-after-return checking"), 108bdd1243dSDimitry Andric cl::Hidden, cl::init(false)); 109bdd1243dSDimitry Andric 110bdd1243dSDimitry Andric //===--- Statistics -------------------------------------------------------===// 111bdd1243dSDimitry Andric 112bdd1243dSDimitry Andric STATISTIC(NumMetadataCovered, "Metadata attached to covered functions"); 113bdd1243dSDimitry Andric STATISTIC(NumMetadataAtomics, "Metadata attached to atomics"); 114bdd1243dSDimitry Andric STATISTIC(NumMetadataUAR, "Metadata attached to UAR functions"); 115bdd1243dSDimitry Andric 116bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric // Apply opt overrides. 119bdd1243dSDimitry Andric SanitizerBinaryMetadataOptions && 120bdd1243dSDimitry Andric transformOptionsFromCl(SanitizerBinaryMetadataOptions &&Opts) { 121bdd1243dSDimitry Andric Opts.Covered |= ClEmitCovered; 122bdd1243dSDimitry Andric Opts.Atomics |= ClEmitAtomics; 123bdd1243dSDimitry Andric Opts.UAR |= ClEmitUAR; 124bdd1243dSDimitry Andric return std::move(Opts); 125bdd1243dSDimitry Andric } 126bdd1243dSDimitry Andric 127bdd1243dSDimitry Andric class SanitizerBinaryMetadata { 128bdd1243dSDimitry Andric public: 12906c3fb27SDimitry Andric SanitizerBinaryMetadata(Module &M, SanitizerBinaryMetadataOptions Opts, 13006c3fb27SDimitry Andric std::unique_ptr<SpecialCaseList> Ignorelist) 131bdd1243dSDimitry Andric : Mod(M), Options(transformOptionsFromCl(std::move(Opts))), 13206c3fb27SDimitry Andric Ignorelist(std::move(Ignorelist)), TargetTriple(M.getTargetTriple()), 13306c3fb27SDimitry Andric IRB(M.getContext()) { 134bdd1243dSDimitry Andric // FIXME: Make it work with other formats. 135bdd1243dSDimitry Andric assert(TargetTriple.isOSBinFormatELF() && "ELF only"); 13606c3fb27SDimitry Andric assert(!(TargetTriple.isNVPTX() || TargetTriple.isAMDGPU()) && 13706c3fb27SDimitry Andric "Device targets are not supported"); 138bdd1243dSDimitry Andric } 139bdd1243dSDimitry Andric 140bdd1243dSDimitry Andric bool run(); 141bdd1243dSDimitry Andric 142bdd1243dSDimitry Andric private: 143bdd1243dSDimitry Andric uint32_t getVersion() const { 144bdd1243dSDimitry Andric uint32_t Version = kVersionBase; 145bdd1243dSDimitry Andric const auto CM = Mod.getCodeModel(); 146bdd1243dSDimitry Andric if (CM.has_value() && (*CM == CodeModel::Medium || *CM == CodeModel::Large)) 147bdd1243dSDimitry Andric Version |= kVersionPtrSizeRel; 148bdd1243dSDimitry Andric return Version; 149bdd1243dSDimitry Andric } 150bdd1243dSDimitry Andric 151bdd1243dSDimitry Andric void runOn(Function &F, MetadataInfoSet &MIS); 152bdd1243dSDimitry Andric 153bdd1243dSDimitry Andric // Determines which set of metadata to collect for this instruction. 154bdd1243dSDimitry Andric // 155bdd1243dSDimitry Andric // Returns true if covered metadata is required to unambiguously interpret 156bdd1243dSDimitry Andric // other metadata. For example, if we are interested in atomics metadata, any 157bdd1243dSDimitry Andric // function with memory operations (atomic or not) requires covered metadata 158bdd1243dSDimitry Andric // to determine if a memory operation is atomic or not in modules compiled 159bdd1243dSDimitry Andric // with SanitizerBinaryMetadata. 160bdd1243dSDimitry Andric bool runOn(Instruction &I, MetadataInfoSet &MIS, MDBuilder &MDB, 16106c3fb27SDimitry Andric uint64_t &FeatureMask); 162bdd1243dSDimitry Andric 163bdd1243dSDimitry Andric // Get start/end section marker pointer. 164bdd1243dSDimitry Andric GlobalVariable *getSectionMarker(const Twine &MarkerName, Type *Ty); 165bdd1243dSDimitry Andric 166bdd1243dSDimitry Andric // Returns the target-dependent section name. 167bdd1243dSDimitry Andric StringRef getSectionName(StringRef SectionSuffix); 168bdd1243dSDimitry Andric 169bdd1243dSDimitry Andric // Returns the section start marker name. 170bdd1243dSDimitry Andric Twine getSectionStart(StringRef SectionSuffix); 171bdd1243dSDimitry Andric 172bdd1243dSDimitry Andric // Returns the section end marker name. 173bdd1243dSDimitry Andric Twine getSectionEnd(StringRef SectionSuffix); 174bdd1243dSDimitry Andric 17506c3fb27SDimitry Andric // Returns true if the access to the address should be considered "atomic". 17606c3fb27SDimitry Andric bool pretendAtomicAccess(const Value *Addr); 17706c3fb27SDimitry Andric 178bdd1243dSDimitry Andric Module &Mod; 179bdd1243dSDimitry Andric const SanitizerBinaryMetadataOptions Options; 18006c3fb27SDimitry Andric std::unique_ptr<SpecialCaseList> Ignorelist; 181bdd1243dSDimitry Andric const Triple TargetTriple; 182bdd1243dSDimitry Andric IRBuilder<> IRB; 18306c3fb27SDimitry Andric BumpPtrAllocator Alloc; 18406c3fb27SDimitry Andric UniqueStringSaver StringPool{Alloc}; 185bdd1243dSDimitry Andric }; 186bdd1243dSDimitry Andric 187bdd1243dSDimitry Andric bool SanitizerBinaryMetadata::run() { 188bdd1243dSDimitry Andric MetadataInfoSet MIS; 189bdd1243dSDimitry Andric 190bdd1243dSDimitry Andric for (Function &F : Mod) 191bdd1243dSDimitry Andric runOn(F, MIS); 192bdd1243dSDimitry Andric 193bdd1243dSDimitry Andric if (MIS.empty()) 194bdd1243dSDimitry Andric return false; 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric // 197bdd1243dSDimitry Andric // Setup constructors and call all initialization functions for requested 198bdd1243dSDimitry Andric // metadata features. 199bdd1243dSDimitry Andric // 200bdd1243dSDimitry Andric 201*5f757f3fSDimitry Andric auto *PtrTy = IRB.getPtrTy(); 202bdd1243dSDimitry Andric auto *Int32Ty = IRB.getInt32Ty(); 203*5f757f3fSDimitry Andric const std::array<Type *, 3> InitTypes = {Int32Ty, PtrTy, PtrTy}; 204bdd1243dSDimitry Andric auto *Version = ConstantInt::get(Int32Ty, getVersion()); 205bdd1243dSDimitry Andric 206bdd1243dSDimitry Andric for (const MetadataInfo *MI : MIS) { 207bdd1243dSDimitry Andric const std::array<Value *, InitTypes.size()> InitArgs = { 208bdd1243dSDimitry Andric Version, 209*5f757f3fSDimitry Andric getSectionMarker(getSectionStart(MI->SectionSuffix), PtrTy), 210*5f757f3fSDimitry Andric getSectionMarker(getSectionEnd(MI->SectionSuffix), PtrTy), 211bdd1243dSDimitry Andric }; 212bdd1243dSDimitry Andric // We declare the _add and _del functions as weak, and only call them if 213bdd1243dSDimitry Andric // there is a valid symbol linked. This allows building binaries with 214bdd1243dSDimitry Andric // semantic metadata, but without having callbacks. When a tool that wants 215bdd1243dSDimitry Andric // the metadata is linked which provides the callbacks, they will be called. 216bdd1243dSDimitry Andric Function *Ctor = 217bdd1243dSDimitry Andric createSanitizerCtorAndInitFunctions( 218bdd1243dSDimitry Andric Mod, (MI->FunctionPrefix + ".module_ctor").str(), 219bdd1243dSDimitry Andric (MI->FunctionPrefix + "_add").str(), InitTypes, InitArgs, 220bdd1243dSDimitry Andric /*VersionCheckName=*/StringRef(), /*Weak=*/ClWeakCallbacks) 221bdd1243dSDimitry Andric .first; 222bdd1243dSDimitry Andric Function *Dtor = 223bdd1243dSDimitry Andric createSanitizerCtorAndInitFunctions( 224bdd1243dSDimitry Andric Mod, (MI->FunctionPrefix + ".module_dtor").str(), 225bdd1243dSDimitry Andric (MI->FunctionPrefix + "_del").str(), InitTypes, InitArgs, 226bdd1243dSDimitry Andric /*VersionCheckName=*/StringRef(), /*Weak=*/ClWeakCallbacks) 227bdd1243dSDimitry Andric .first; 22806c3fb27SDimitry Andric Constant *CtorComdatKey = nullptr; 22906c3fb27SDimitry Andric Constant *DtorComdatKey = nullptr; 230bdd1243dSDimitry Andric if (TargetTriple.supportsCOMDAT()) { 23106c3fb27SDimitry Andric // Use COMDAT to deduplicate constructor/destructor function. The COMDAT 23206c3fb27SDimitry Andric // key needs to be a non-local linkage. 233bdd1243dSDimitry Andric Ctor->setComdat(Mod.getOrInsertComdat(Ctor->getName())); 234bdd1243dSDimitry Andric Dtor->setComdat(Mod.getOrInsertComdat(Dtor->getName())); 23506c3fb27SDimitry Andric Ctor->setLinkage(GlobalValue::ExternalLinkage); 23606c3fb27SDimitry Andric Dtor->setLinkage(GlobalValue::ExternalLinkage); 23706c3fb27SDimitry Andric // DSOs should _not_ call another constructor/destructor! 23806c3fb27SDimitry Andric Ctor->setVisibility(GlobalValue::HiddenVisibility); 23906c3fb27SDimitry Andric Dtor->setVisibility(GlobalValue::HiddenVisibility); 24006c3fb27SDimitry Andric CtorComdatKey = Ctor; 24106c3fb27SDimitry Andric DtorComdatKey = Dtor; 242bdd1243dSDimitry Andric } 24306c3fb27SDimitry Andric appendToGlobalCtors(Mod, Ctor, kCtorDtorPriority, CtorComdatKey); 24406c3fb27SDimitry Andric appendToGlobalDtors(Mod, Dtor, kCtorDtorPriority, DtorComdatKey); 245bdd1243dSDimitry Andric } 246bdd1243dSDimitry Andric 247bdd1243dSDimitry Andric return true; 248bdd1243dSDimitry Andric } 249bdd1243dSDimitry Andric 250bdd1243dSDimitry Andric void SanitizerBinaryMetadata::runOn(Function &F, MetadataInfoSet &MIS) { 251bdd1243dSDimitry Andric if (F.empty()) 252bdd1243dSDimitry Andric return; 253bdd1243dSDimitry Andric if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) 254bdd1243dSDimitry Andric return; 25506c3fb27SDimitry Andric if (Ignorelist && Ignorelist->inSection("metadata", "fun", F.getName())) 25606c3fb27SDimitry Andric return; 257bdd1243dSDimitry Andric // Don't touch available_externally functions, their actual body is elsewhere. 258bdd1243dSDimitry Andric if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) 259bdd1243dSDimitry Andric return; 260bdd1243dSDimitry Andric 261bdd1243dSDimitry Andric MDBuilder MDB(F.getContext()); 262bdd1243dSDimitry Andric 263bdd1243dSDimitry Andric // The metadata features enabled for this function, stored along covered 264bdd1243dSDimitry Andric // metadata (if enabled). 26506c3fb27SDimitry Andric uint64_t FeatureMask = 0; 266bdd1243dSDimitry Andric // Don't emit unnecessary covered metadata for all functions to save space. 267bdd1243dSDimitry Andric bool RequiresCovered = false; 26806c3fb27SDimitry Andric 26906c3fb27SDimitry Andric if (Options.Atomics || Options.UAR) { 270bdd1243dSDimitry Andric for (BasicBlock &BB : F) 271bdd1243dSDimitry Andric for (Instruction &I : BB) 272bdd1243dSDimitry Andric RequiresCovered |= runOn(I, MIS, MDB, FeatureMask); 273bdd1243dSDimitry Andric } 274bdd1243dSDimitry Andric 27506c3fb27SDimitry Andric if (ClNoSanitize && F.hasFnAttribute("no_sanitize_thread")) 27606c3fb27SDimitry Andric FeatureMask &= ~kSanitizerBinaryMetadataAtomics; 277bdd1243dSDimitry Andric if (F.isVarArg()) 278bdd1243dSDimitry Andric FeatureMask &= ~kSanitizerBinaryMetadataUAR; 279bdd1243dSDimitry Andric if (FeatureMask & kSanitizerBinaryMetadataUAR) { 280bdd1243dSDimitry Andric RequiresCovered = true; 281bdd1243dSDimitry Andric NumMetadataUAR++; 282bdd1243dSDimitry Andric } 283bdd1243dSDimitry Andric 284bdd1243dSDimitry Andric // Covered metadata is always emitted if explicitly requested, otherwise only 285bdd1243dSDimitry Andric // if some other metadata requires it to unambiguously interpret it for 286bdd1243dSDimitry Andric // modules compiled with SanitizerBinaryMetadata. 287bdd1243dSDimitry Andric if (Options.Covered || (FeatureMask && RequiresCovered)) { 288bdd1243dSDimitry Andric NumMetadataCovered++; 289bdd1243dSDimitry Andric const auto *MI = &MetadataInfo::Covered; 290bdd1243dSDimitry Andric MIS.insert(MI); 291bdd1243dSDimitry Andric const StringRef Section = getSectionName(MI->SectionSuffix); 29206c3fb27SDimitry Andric // The feature mask will be placed after the function size. 29306c3fb27SDimitry Andric Constant *CFM = IRB.getInt64(FeatureMask); 294bdd1243dSDimitry Andric F.setMetadata(LLVMContext::MD_pcsections, 295bdd1243dSDimitry Andric MDB.createPCSections({{Section, {CFM}}})); 296bdd1243dSDimitry Andric } 297bdd1243dSDimitry Andric } 298bdd1243dSDimitry Andric 299bdd1243dSDimitry Andric bool isUARSafeCall(CallInst *CI) { 300bdd1243dSDimitry Andric auto *F = CI->getCalledFunction(); 301bdd1243dSDimitry Andric // There are no intrinsic functions that leak arguments. 302bdd1243dSDimitry Andric // If the called function does not return, the current function 303bdd1243dSDimitry Andric // does not return as well, so no possibility of use-after-return. 304bdd1243dSDimitry Andric // Sanitizer function also don't leak or don't return. 305bdd1243dSDimitry Andric // It's safe to both pass pointers to local variables to them 306bdd1243dSDimitry Andric // and to tail-call them. 307bdd1243dSDimitry Andric return F && (F->isIntrinsic() || F->doesNotReturn() || 308*5f757f3fSDimitry Andric F->getName().starts_with("__asan_") || 309*5f757f3fSDimitry Andric F->getName().starts_with("__hwsan_") || 310*5f757f3fSDimitry Andric F->getName().starts_with("__ubsan_") || 311*5f757f3fSDimitry Andric F->getName().starts_with("__msan_") || 312*5f757f3fSDimitry Andric F->getName().starts_with("__tsan_")); 313bdd1243dSDimitry Andric } 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric bool hasUseAfterReturnUnsafeUses(Value &V) { 316bdd1243dSDimitry Andric for (User *U : V.users()) { 317bdd1243dSDimitry Andric if (auto *I = dyn_cast<Instruction>(U)) { 318bdd1243dSDimitry Andric if (I->isLifetimeStartOrEnd() || I->isDroppable()) 319bdd1243dSDimitry Andric continue; 320bdd1243dSDimitry Andric if (auto *CI = dyn_cast<CallInst>(U)) { 321bdd1243dSDimitry Andric if (isUARSafeCall(CI)) 322bdd1243dSDimitry Andric continue; 323bdd1243dSDimitry Andric } 324bdd1243dSDimitry Andric if (isa<LoadInst>(U)) 325bdd1243dSDimitry Andric continue; 326bdd1243dSDimitry Andric if (auto *SI = dyn_cast<StoreInst>(U)) { 327bdd1243dSDimitry Andric // If storing TO the alloca, then the address isn't taken. 328bdd1243dSDimitry Andric if (SI->getOperand(1) == &V) 329bdd1243dSDimitry Andric continue; 330bdd1243dSDimitry Andric } 331bdd1243dSDimitry Andric if (auto *GEPI = dyn_cast<GetElementPtrInst>(U)) { 332bdd1243dSDimitry Andric if (!hasUseAfterReturnUnsafeUses(*GEPI)) 333bdd1243dSDimitry Andric continue; 334bdd1243dSDimitry Andric } else if (auto *BCI = dyn_cast<BitCastInst>(U)) { 335bdd1243dSDimitry Andric if (!hasUseAfterReturnUnsafeUses(*BCI)) 336bdd1243dSDimitry Andric continue; 337bdd1243dSDimitry Andric } 338bdd1243dSDimitry Andric } 339bdd1243dSDimitry Andric return true; 340bdd1243dSDimitry Andric } 341bdd1243dSDimitry Andric return false; 342bdd1243dSDimitry Andric } 343bdd1243dSDimitry Andric 344bdd1243dSDimitry Andric bool useAfterReturnUnsafe(Instruction &I) { 345bdd1243dSDimitry Andric if (isa<AllocaInst>(I)) 346bdd1243dSDimitry Andric return hasUseAfterReturnUnsafeUses(I); 347bdd1243dSDimitry Andric // Tail-called functions are not necessary intercepted 348bdd1243dSDimitry Andric // at runtime because there is no call instruction. 349bdd1243dSDimitry Andric // So conservatively mark the caller as requiring checking. 350bdd1243dSDimitry Andric else if (auto *CI = dyn_cast<CallInst>(&I)) 351bdd1243dSDimitry Andric return CI->isTailCall() && !isUARSafeCall(CI); 352bdd1243dSDimitry Andric return false; 353bdd1243dSDimitry Andric } 354bdd1243dSDimitry Andric 35506c3fb27SDimitry Andric bool SanitizerBinaryMetadata::pretendAtomicAccess(const Value *Addr) { 35606c3fb27SDimitry Andric if (!Addr) 35706c3fb27SDimitry Andric return false; 35806c3fb27SDimitry Andric 35906c3fb27SDimitry Andric Addr = Addr->stripInBoundsOffsets(); 36006c3fb27SDimitry Andric auto *GV = dyn_cast<GlobalVariable>(Addr); 36106c3fb27SDimitry Andric if (!GV) 36206c3fb27SDimitry Andric return false; 36306c3fb27SDimitry Andric 36406c3fb27SDimitry Andric // Some compiler-generated accesses are known racy, to avoid false positives 36506c3fb27SDimitry Andric // in data-race analysis pretend they're atomic. 36606c3fb27SDimitry Andric if (GV->hasSection()) { 36706c3fb27SDimitry Andric const auto OF = Triple(Mod.getTargetTriple()).getObjectFormat(); 36806c3fb27SDimitry Andric const auto ProfSec = 36906c3fb27SDimitry Andric getInstrProfSectionName(IPSK_cnts, OF, /*AddSegmentInfo=*/false); 370*5f757f3fSDimitry Andric if (GV->getSection().ends_with(ProfSec)) 37106c3fb27SDimitry Andric return true; 37206c3fb27SDimitry Andric } 373*5f757f3fSDimitry Andric if (GV->getName().starts_with("__llvm_gcov") || 374*5f757f3fSDimitry Andric GV->getName().starts_with("__llvm_gcda")) 37506c3fb27SDimitry Andric return true; 37606c3fb27SDimitry Andric 37706c3fb27SDimitry Andric return false; 37806c3fb27SDimitry Andric } 37906c3fb27SDimitry Andric 38006c3fb27SDimitry Andric // Returns true if the memory at `Addr` may be shared with other threads. 38106c3fb27SDimitry Andric bool maybeSharedMutable(const Value *Addr) { 38206c3fb27SDimitry Andric // By default assume memory may be shared. 38306c3fb27SDimitry Andric if (!Addr) 38406c3fb27SDimitry Andric return true; 38506c3fb27SDimitry Andric 38606c3fb27SDimitry Andric if (isa<AllocaInst>(getUnderlyingObject(Addr)) && 38706c3fb27SDimitry Andric !PointerMayBeCaptured(Addr, true, true)) 38806c3fb27SDimitry Andric return false; // Object is on stack but does not escape. 38906c3fb27SDimitry Andric 39006c3fb27SDimitry Andric Addr = Addr->stripInBoundsOffsets(); 39106c3fb27SDimitry Andric if (auto *GV = dyn_cast<GlobalVariable>(Addr)) { 39206c3fb27SDimitry Andric if (GV->isConstant()) 39306c3fb27SDimitry Andric return false; // Shared, but not mutable. 39406c3fb27SDimitry Andric } 39506c3fb27SDimitry Andric 39606c3fb27SDimitry Andric return true; 39706c3fb27SDimitry Andric } 39806c3fb27SDimitry Andric 399bdd1243dSDimitry Andric bool SanitizerBinaryMetadata::runOn(Instruction &I, MetadataInfoSet &MIS, 40006c3fb27SDimitry Andric MDBuilder &MDB, uint64_t &FeatureMask) { 401bdd1243dSDimitry Andric SmallVector<const MetadataInfo *, 1> InstMetadata; 402bdd1243dSDimitry Andric bool RequiresCovered = false; 403bdd1243dSDimitry Andric 40406c3fb27SDimitry Andric // Only call if at least 1 type of metadata is requested. 40506c3fb27SDimitry Andric assert(Options.UAR || Options.Atomics); 40606c3fb27SDimitry Andric 407bdd1243dSDimitry Andric if (Options.UAR && !(FeatureMask & kSanitizerBinaryMetadataUAR)) { 408bdd1243dSDimitry Andric if (useAfterReturnUnsafe(I)) 409bdd1243dSDimitry Andric FeatureMask |= kSanitizerBinaryMetadataUAR; 410bdd1243dSDimitry Andric } 411bdd1243dSDimitry Andric 41206c3fb27SDimitry Andric if (Options.Atomics) { 41306c3fb27SDimitry Andric const Value *Addr = nullptr; 41406c3fb27SDimitry Andric if (auto *SI = dyn_cast<StoreInst>(&I)) 41506c3fb27SDimitry Andric Addr = SI->getPointerOperand(); 41606c3fb27SDimitry Andric else if (auto *LI = dyn_cast<LoadInst>(&I)) 41706c3fb27SDimitry Andric Addr = LI->getPointerOperand(); 41806c3fb27SDimitry Andric 41906c3fb27SDimitry Andric if (I.mayReadOrWriteMemory() && maybeSharedMutable(Addr)) { 420bdd1243dSDimitry Andric auto SSID = getAtomicSyncScopeID(&I); 42106c3fb27SDimitry Andric if ((SSID.has_value() && *SSID != SyncScope::SingleThread) || 42206c3fb27SDimitry Andric pretendAtomicAccess(Addr)) { 423bdd1243dSDimitry Andric NumMetadataAtomics++; 424bdd1243dSDimitry Andric InstMetadata.push_back(&MetadataInfo::Atomics); 425bdd1243dSDimitry Andric } 42606c3fb27SDimitry Andric FeatureMask |= kSanitizerBinaryMetadataAtomics; 427bdd1243dSDimitry Andric RequiresCovered = true; 428bdd1243dSDimitry Andric } 42906c3fb27SDimitry Andric } 430bdd1243dSDimitry Andric 431bdd1243dSDimitry Andric // Attach MD_pcsections to instruction. 432bdd1243dSDimitry Andric if (!InstMetadata.empty()) { 433bdd1243dSDimitry Andric MIS.insert(InstMetadata.begin(), InstMetadata.end()); 434bdd1243dSDimitry Andric SmallVector<MDBuilder::PCSection, 1> Sections; 435bdd1243dSDimitry Andric for (const auto &MI : InstMetadata) 436bdd1243dSDimitry Andric Sections.push_back({getSectionName(MI->SectionSuffix), {}}); 437bdd1243dSDimitry Andric I.setMetadata(LLVMContext::MD_pcsections, MDB.createPCSections(Sections)); 438bdd1243dSDimitry Andric } 439bdd1243dSDimitry Andric 440bdd1243dSDimitry Andric return RequiresCovered; 441bdd1243dSDimitry Andric } 442bdd1243dSDimitry Andric 443bdd1243dSDimitry Andric GlobalVariable * 444bdd1243dSDimitry Andric SanitizerBinaryMetadata::getSectionMarker(const Twine &MarkerName, Type *Ty) { 445bdd1243dSDimitry Andric // Use ExternalWeak so that if all sections are discarded due to section 446bdd1243dSDimitry Andric // garbage collection, the linker will not report undefined symbol errors. 447bdd1243dSDimitry Andric auto *Marker = new GlobalVariable(Mod, Ty, /*isConstant=*/false, 448bdd1243dSDimitry Andric GlobalVariable::ExternalWeakLinkage, 449bdd1243dSDimitry Andric /*Initializer=*/nullptr, MarkerName); 450bdd1243dSDimitry Andric Marker->setVisibility(GlobalValue::HiddenVisibility); 451bdd1243dSDimitry Andric return Marker; 452bdd1243dSDimitry Andric } 453bdd1243dSDimitry Andric 454bdd1243dSDimitry Andric StringRef SanitizerBinaryMetadata::getSectionName(StringRef SectionSuffix) { 45506c3fb27SDimitry Andric // FIXME: Other TargetTriples. 45606c3fb27SDimitry Andric // Request ULEB128 encoding for all integer constants. 45706c3fb27SDimitry Andric return StringPool.save(SectionSuffix + "!C"); 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric Twine SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) { 461bdd1243dSDimitry Andric return "__start_" + SectionSuffix; 462bdd1243dSDimitry Andric } 463bdd1243dSDimitry Andric 464bdd1243dSDimitry Andric Twine SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) { 465bdd1243dSDimitry Andric return "__stop_" + SectionSuffix; 466bdd1243dSDimitry Andric } 467bdd1243dSDimitry Andric 468bdd1243dSDimitry Andric } // namespace 469bdd1243dSDimitry Andric 470bdd1243dSDimitry Andric SanitizerBinaryMetadataPass::SanitizerBinaryMetadataPass( 47106c3fb27SDimitry Andric SanitizerBinaryMetadataOptions Opts, ArrayRef<std::string> IgnorelistFiles) 47206c3fb27SDimitry Andric : Options(std::move(Opts)), IgnorelistFiles(std::move(IgnorelistFiles)) {} 473bdd1243dSDimitry Andric 474bdd1243dSDimitry Andric PreservedAnalyses 475bdd1243dSDimitry Andric SanitizerBinaryMetadataPass::run(Module &M, AnalysisManager<Module> &AM) { 47606c3fb27SDimitry Andric std::unique_ptr<SpecialCaseList> Ignorelist; 47706c3fb27SDimitry Andric if (!IgnorelistFiles.empty()) { 47806c3fb27SDimitry Andric Ignorelist = SpecialCaseList::createOrDie(IgnorelistFiles, 47906c3fb27SDimitry Andric *vfs::getRealFileSystem()); 48006c3fb27SDimitry Andric if (Ignorelist->inSection("metadata", "src", M.getSourceFileName())) 48106c3fb27SDimitry Andric return PreservedAnalyses::all(); 48206c3fb27SDimitry Andric } 48306c3fb27SDimitry Andric 48406c3fb27SDimitry Andric SanitizerBinaryMetadata Pass(M, Options, std::move(Ignorelist)); 485bdd1243dSDimitry Andric if (Pass.run()) 486bdd1243dSDimitry Andric return PreservedAnalyses::none(); 487bdd1243dSDimitry Andric return PreservedAnalyses::all(); 488bdd1243dSDimitry Andric } 489