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 | 2781ad6265SDimitry Andric SanitizerKind::HWAddress | SanitizerKind::MemTag); 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric 3081ad6265SDimitry Andric SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { 3181ad6265SDimitry Andric if (Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress)) 3281ad6265SDimitry Andric Mask |= SanitizerKind::Address | SanitizerKind::KernelAddress; 3381ad6265SDimitry Andric // Note: KHWASan doesn't support globals. 3481ad6265SDimitry Andric return Mask; 3581ad6265SDimitry Andric } 3681ad6265SDimitry Andric 3781ad6265SDimitry Andric void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, 380b57cec5SDimitry Andric SourceLocation Loc, StringRef Name, 3981ad6265SDimitry Andric QualType Ty, 4081ad6265SDimitry Andric SanitizerMask NoSanitizeAttrMask, 4181ad6265SDimitry Andric bool IsDynInit) { 4281ad6265SDimitry Andric SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize; 4381ad6265SDimitry Andric if (!isAsanHwasanOrMemTag(FsanitizeArgument)) 440b57cec5SDimitry Andric return; 450b57cec5SDimitry Andric 4681ad6265SDimitry Andric FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask); 4781ad6265SDimitry Andric NoSanitizeAttrMask = expandKernelSanitizerMasks(NoSanitizeAttrMask); 4881ad6265SDimitry Andric SanitizerSet NoSanitizeAttrSet = {NoSanitizeAttrMask & 4981ad6265SDimitry Andric FsanitizeArgument.Mask}; 5081ad6265SDimitry Andric 5181ad6265SDimitry Andric llvm::GlobalVariable::SanitizerMetadata Meta; 5281ad6265SDimitry Andric if (GV->hasSanitizerMetadata()) 5381ad6265SDimitry Andric Meta = GV->getSanitizerMetadata(); 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric Meta.NoAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::Address); 5681ad6265SDimitry Andric Meta.NoAddress |= CGM.isInNoSanitizeList( 5781ad6265SDimitry Andric FsanitizeArgument.Mask & SanitizerKind::Address, GV, Loc, Ty); 5881ad6265SDimitry Andric 5981ad6265SDimitry Andric Meta.NoHWAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::HWAddress); 6081ad6265SDimitry Andric Meta.NoHWAddress |= CGM.isInNoSanitizeList( 6181ad6265SDimitry Andric FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty); 6281ad6265SDimitry Andric 63*753f127fSDimitry Andric Meta.Memtag |= 64*753f127fSDimitry Andric static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals); 65*753f127fSDimitry Andric Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag); 66*753f127fSDimitry Andric Meta.Memtag &= !CGM.isInNoSanitizeList( 6781ad6265SDimitry Andric FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty); 6881ad6265SDimitry Andric 69*753f127fSDimitry Andric Meta.IsDynInit = IsDynInit && !Meta.NoAddress && 70*753f127fSDimitry Andric FsanitizeArgument.has(SanitizerKind::Address) && 71*753f127fSDimitry Andric !CGM.isInNoSanitizeList(SanitizerKind::Address | 7281ad6265SDimitry Andric SanitizerKind::KernelAddress, 7381ad6265SDimitry Andric GV, Loc, Ty, "init"); 740b57cec5SDimitry Andric 7581ad6265SDimitry Andric GV->setSanitizerMetadata(Meta); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 7881ad6265SDimitry Andric void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, 7981ad6265SDimitry 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 8681ad6265SDimitry Andric auto getNoSanitizeMask = [](const VarDecl &D) { 8781ad6265SDimitry Andric if (D.hasAttr<DisableSanitizerInstrumentationAttr>()) 8881ad6265SDimitry Andric return SanitizerKind::All; 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric SanitizerMask NoSanitizeMask; 9181ad6265SDimitry Andric for (auto *Attr : D.specific_attrs<NoSanitizeAttr>()) 9281ad6265SDimitry Andric NoSanitizeMask |= Attr->getMask(); 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric return NoSanitizeMask; 9581ad6265SDimitry Andric }; 9681ad6265SDimitry Andric 9781ad6265SDimitry Andric reportGlobal(GV, D.getLocation(), OS.str(), D.getType(), getNoSanitizeMask(D), 9881ad6265SDimitry Andric IsDynInit); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { 10281ad6265SDimitry Andric reportGlobal(GV, SourceLocation(), "", QualType(), SanitizerKind::All); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { 10681ad6265SDimitry Andric I->setMetadata(llvm::LLVMContext::MD_nosanitize, 1070b57cec5SDimitry Andric llvm::MDNode::get(CGM.getLLVMContext(), None)); 1080b57cec5SDimitry Andric } 109