1fe6060f1SDimitry Andric //===--- SanitizerMetadata.cpp - Ignored entities for sanitizers ----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Class which emits metadata consumed by sanitizer instrumentation passes. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric #include "SanitizerMetadata.h" 130b57cec5SDimitry Andric #include "CodeGenModule.h" 14480093f4SDimitry Andric #include "clang/AST/Attr.h" 150b57cec5SDimitry Andric #include "clang/AST/Type.h" 165ffd83dbSDimitry Andric #include "clang/Basic/SourceManager.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 180b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using namespace clang; 210b57cec5SDimitry Andric using namespace CodeGen; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) { 260b57cec5SDimitry Andric return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | 27*81ad6265SDimitry Andric SanitizerKind::HWAddress | SanitizerKind::MemTag); 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric 30*81ad6265SDimitry Andric SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { 31*81ad6265SDimitry Andric if (Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress)) 32*81ad6265SDimitry Andric Mask |= SanitizerKind::Address | SanitizerKind::KernelAddress; 33*81ad6265SDimitry Andric // Note: KHWASan doesn't support globals. 34*81ad6265SDimitry Andric return Mask; 35*81ad6265SDimitry Andric } 36*81ad6265SDimitry Andric 37*81ad6265SDimitry Andric void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, 380b57cec5SDimitry Andric SourceLocation Loc, StringRef Name, 39*81ad6265SDimitry Andric QualType Ty, 40*81ad6265SDimitry Andric SanitizerMask NoSanitizeAttrMask, 41*81ad6265SDimitry Andric bool IsDynInit) { 42*81ad6265SDimitry Andric SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize; 43*81ad6265SDimitry Andric if (!isAsanHwasanOrMemTag(FsanitizeArgument)) 440b57cec5SDimitry Andric return; 450b57cec5SDimitry Andric 46*81ad6265SDimitry Andric FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask); 47*81ad6265SDimitry Andric NoSanitizeAttrMask = expandKernelSanitizerMasks(NoSanitizeAttrMask); 48*81ad6265SDimitry Andric SanitizerSet NoSanitizeAttrSet = {NoSanitizeAttrMask & 49*81ad6265SDimitry Andric FsanitizeArgument.Mask}; 50*81ad6265SDimitry Andric 51*81ad6265SDimitry Andric llvm::GlobalVariable::SanitizerMetadata Meta; 52*81ad6265SDimitry Andric if (GV->hasSanitizerMetadata()) 53*81ad6265SDimitry Andric Meta = GV->getSanitizerMetadata(); 54*81ad6265SDimitry Andric 55*81ad6265SDimitry Andric Meta.NoAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::Address); 56*81ad6265SDimitry Andric Meta.NoAddress |= CGM.isInNoSanitizeList( 57*81ad6265SDimitry Andric FsanitizeArgument.Mask & SanitizerKind::Address, GV, Loc, Ty); 58*81ad6265SDimitry Andric 59*81ad6265SDimitry Andric Meta.NoHWAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::HWAddress); 60*81ad6265SDimitry Andric Meta.NoHWAddress |= CGM.isInNoSanitizeList( 61*81ad6265SDimitry Andric FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty); 62*81ad6265SDimitry Andric 63*81ad6265SDimitry Andric Meta.NoMemtag |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag); 64*81ad6265SDimitry Andric Meta.NoMemtag |= CGM.isInNoSanitizeList( 65*81ad6265SDimitry Andric FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty); 66*81ad6265SDimitry Andric 67*81ad6265SDimitry Andric if (FsanitizeArgument.has(SanitizerKind::Address)) { 68*81ad6265SDimitry Andric // TODO(hctim): Make this conditional when we migrate off llvm.asan.globals. 69*81ad6265SDimitry Andric IsDynInit &= !CGM.isInNoSanitizeList(SanitizerKind::Address | 70*81ad6265SDimitry Andric SanitizerKind::KernelAddress, 71*81ad6265SDimitry Andric GV, Loc, Ty, "init"); 72*81ad6265SDimitry Andric Meta.IsDynInit = IsDynInit; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 75*81ad6265SDimitry Andric GV->setSanitizerMetadata(Meta); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 78*81ad6265SDimitry Andric void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, 79*81ad6265SDimitry Andric bool IsDynInit) { 800b57cec5SDimitry Andric if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) 810b57cec5SDimitry Andric return; 820b57cec5SDimitry Andric std::string QualName; 830b57cec5SDimitry Andric llvm::raw_string_ostream OS(QualName); 840b57cec5SDimitry Andric D.printQualifiedName(OS); 850b57cec5SDimitry Andric 86*81ad6265SDimitry Andric auto getNoSanitizeMask = [](const VarDecl &D) { 87*81ad6265SDimitry Andric if (D.hasAttr<DisableSanitizerInstrumentationAttr>()) 88*81ad6265SDimitry Andric return SanitizerKind::All; 89*81ad6265SDimitry Andric 90*81ad6265SDimitry Andric SanitizerMask NoSanitizeMask; 91*81ad6265SDimitry Andric for (auto *Attr : D.specific_attrs<NoSanitizeAttr>()) 92*81ad6265SDimitry Andric NoSanitizeMask |= Attr->getMask(); 93*81ad6265SDimitry Andric 94*81ad6265SDimitry Andric return NoSanitizeMask; 95*81ad6265SDimitry Andric }; 96*81ad6265SDimitry Andric 97*81ad6265SDimitry Andric reportGlobal(GV, D.getLocation(), OS.str(), D.getType(), getNoSanitizeMask(D), 98*81ad6265SDimitry Andric IsDynInit); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { 102*81ad6265SDimitry Andric reportGlobal(GV, SourceLocation(), "", QualType(), SanitizerKind::All); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { 106*81ad6265SDimitry Andric I->setMetadata(llvm::LLVMContext::MD_nosanitize, 1070b57cec5SDimitry Andric llvm::MDNode::get(CGM.getLLVMContext(), None)); 1080b57cec5SDimitry Andric } 109