1*0b57cec5SDimitry Andric //===--- SanitizerMetadata.cpp - Blacklist for sanitizers -----------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // Class which emits metadata consumed by sanitizer instrumentation passes. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric #include "SanitizerMetadata.h" 13*0b57cec5SDimitry Andric #include "CodeGenModule.h" 14*0b57cec5SDimitry Andric #include "clang/AST/Type.h" 15*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 16*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric using namespace clang; 19*0b57cec5SDimitry Andric using namespace CodeGen; 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric static bool isAsanHwasanOrMemTag(const SanitizerSet& SS) { 24*0b57cec5SDimitry Andric return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | 25*0b57cec5SDimitry Andric SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | 26*0b57cec5SDimitry Andric SanitizerKind::MemTag); 27*0b57cec5SDimitry Andric } 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, 30*0b57cec5SDimitry Andric SourceLocation Loc, StringRef Name, 31*0b57cec5SDimitry Andric QualType Ty, bool IsDynInit, 32*0b57cec5SDimitry Andric bool IsBlacklisted) { 33*0b57cec5SDimitry Andric if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) 34*0b57cec5SDimitry Andric return; 35*0b57cec5SDimitry Andric IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init"); 36*0b57cec5SDimitry Andric IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty); 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric llvm::Metadata *LocDescr = nullptr; 39*0b57cec5SDimitry Andric llvm::Metadata *GlobalName = nullptr; 40*0b57cec5SDimitry Andric llvm::LLVMContext &VMContext = CGM.getLLVMContext(); 41*0b57cec5SDimitry Andric if (!IsBlacklisted) { 42*0b57cec5SDimitry Andric // Don't generate source location and global name if it is blacklisted - 43*0b57cec5SDimitry Andric // it won't be instrumented anyway. 44*0b57cec5SDimitry Andric LocDescr = getLocationMetadata(Loc); 45*0b57cec5SDimitry Andric if (!Name.empty()) 46*0b57cec5SDimitry Andric GlobalName = llvm::MDString::get(VMContext, Name); 47*0b57cec5SDimitry Andric } 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric llvm::Metadata *GlobalMetadata[] = { 50*0b57cec5SDimitry Andric llvm::ConstantAsMetadata::get(GV), LocDescr, GlobalName, 51*0b57cec5SDimitry Andric llvm::ConstantAsMetadata::get( 52*0b57cec5SDimitry Andric llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit)), 53*0b57cec5SDimitry Andric llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( 54*0b57cec5SDimitry Andric llvm::Type::getInt1Ty(VMContext), IsBlacklisted))}; 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata); 57*0b57cec5SDimitry Andric llvm::NamedMDNode *AsanGlobals = 58*0b57cec5SDimitry Andric CGM.getModule().getOrInsertNamedMetadata("llvm.asan.globals"); 59*0b57cec5SDimitry Andric AsanGlobals->addOperand(ThisGlobal); 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, 63*0b57cec5SDimitry Andric const VarDecl &D, bool IsDynInit) { 64*0b57cec5SDimitry Andric if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) 65*0b57cec5SDimitry Andric return; 66*0b57cec5SDimitry Andric std::string QualName; 67*0b57cec5SDimitry Andric llvm::raw_string_ostream OS(QualName); 68*0b57cec5SDimitry Andric D.printQualifiedName(OS); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric bool IsBlacklisted = false; 71*0b57cec5SDimitry Andric for (auto Attr : D.specific_attrs<NoSanitizeAttr>()) 72*0b57cec5SDimitry Andric if (Attr->getMask() & SanitizerKind::Address) 73*0b57cec5SDimitry Andric IsBlacklisted = true; 74*0b57cec5SDimitry Andric reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit, 75*0b57cec5SDimitry Andric IsBlacklisted); 76*0b57cec5SDimitry Andric } 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { 79*0b57cec5SDimitry Andric // For now, just make sure the global is not modified by the ASan 80*0b57cec5SDimitry Andric // instrumentation. 81*0b57cec5SDimitry Andric if (isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) 82*0b57cec5SDimitry Andric reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true); 83*0b57cec5SDimitry Andric } 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { 86*0b57cec5SDimitry Andric I->setMetadata(CGM.getModule().getMDKindID("nosanitize"), 87*0b57cec5SDimitry Andric llvm::MDNode::get(CGM.getLLVMContext(), None)); 88*0b57cec5SDimitry Andric } 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) { 91*0b57cec5SDimitry Andric PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc); 92*0b57cec5SDimitry Andric if (!PLoc.isValid()) 93*0b57cec5SDimitry Andric return nullptr; 94*0b57cec5SDimitry Andric llvm::LLVMContext &VMContext = CGM.getLLVMContext(); 95*0b57cec5SDimitry Andric llvm::Metadata *LocMetadata[] = { 96*0b57cec5SDimitry Andric llvm::MDString::get(VMContext, PLoc.getFilename()), 97*0b57cec5SDimitry Andric llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( 98*0b57cec5SDimitry Andric llvm::Type::getInt32Ty(VMContext), PLoc.getLine())), 99*0b57cec5SDimitry Andric llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( 100*0b57cec5SDimitry Andric llvm::Type::getInt32Ty(VMContext), PLoc.getColumn())), 101*0b57cec5SDimitry Andric }; 102*0b57cec5SDimitry Andric return llvm::MDNode::get(VMContext, LocMetadata); 103*0b57cec5SDimitry Andric } 104