1fe6060f1SDimitry Andric //===--- SanitizerMetadata.cpp - Ignored entities 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"
14480093f4SDimitry Andric #include "clang/AST/Attr.h"
15*0b57cec5SDimitry Andric #include "clang/AST/Type.h"
165ffd83dbSDimitry Andric #include "clang/Basic/SourceManager.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
18*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
19*0b57cec5SDimitry Andric 
20*0b57cec5SDimitry Andric using namespace clang;
21*0b57cec5SDimitry Andric using namespace CodeGen;
22*0b57cec5SDimitry Andric 
SanitizerMetadata(CodeGenModule & CGM)23*0b57cec5SDimitry Andric SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
24*0b57cec5SDimitry Andric 
isAsanHwasanOrMemTag(const SanitizerSet & SS)25*0b57cec5SDimitry Andric static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) {
26*0b57cec5SDimitry Andric   return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress |
2781ad6265SDimitry Andric                      SanitizerKind::HWAddress | SanitizerKind::MemTag);
28*0b57cec5SDimitry Andric }
29*0b57cec5SDimitry Andric 
expandKernelSanitizerMasks(SanitizerMask Mask)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 
reportGlobal(llvm::GlobalVariable * GV,SourceLocation Loc,StringRef Name,QualType Ty,SanitizerMask NoSanitizeAttrMask,bool IsDynInit)3781ad6265SDimitry Andric void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
38*0b57cec5SDimitry 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))
44*0b57cec5SDimitry Andric     return;
45*0b57cec5SDimitry 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 
63753f127fSDimitry Andric   Meta.Memtag |=
64753f127fSDimitry Andric       static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals);
65753f127fSDimitry Andric   Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);
66753f127fSDimitry Andric   Meta.Memtag &= !CGM.isInNoSanitizeList(
6781ad6265SDimitry Andric       FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty);
6881ad6265SDimitry Andric 
69753f127fSDimitry Andric   Meta.IsDynInit = IsDynInit && !Meta.NoAddress &&
70753f127fSDimitry Andric                    FsanitizeArgument.has(SanitizerKind::Address) &&
71753f127fSDimitry Andric                    !CGM.isInNoSanitizeList(SanitizerKind::Address |
7281ad6265SDimitry Andric                                                SanitizerKind::KernelAddress,
7381ad6265SDimitry Andric                                            GV, Loc, Ty, "init");
74*0b57cec5SDimitry Andric 
7581ad6265SDimitry Andric   GV->setSanitizerMetadata(Meta);
76*0b57cec5SDimitry Andric }
77*0b57cec5SDimitry Andric 
reportGlobal(llvm::GlobalVariable * GV,const VarDecl & D,bool IsDynInit)7881ad6265SDimitry Andric void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D,
7981ad6265SDimitry Andric                                      bool IsDynInit) {
80*0b57cec5SDimitry Andric   if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
81*0b57cec5SDimitry Andric     return;
82*0b57cec5SDimitry Andric   std::string QualName;
83*0b57cec5SDimitry Andric   llvm::raw_string_ostream OS(QualName);
84*0b57cec5SDimitry Andric   D.printQualifiedName(OS);
85*0b57cec5SDimitry 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);
99*0b57cec5SDimitry Andric }
100*0b57cec5SDimitry Andric 
disableSanitizerForGlobal(llvm::GlobalVariable * GV)101*0b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
10281ad6265SDimitry Andric   reportGlobal(GV, SourceLocation(), "", QualType(), SanitizerKind::All);
103*0b57cec5SDimitry Andric }
104