1e64fcdf8SMelanie Blower //===--- SanitizerMetadata.cpp - Ignored entities for sanitizers ----------===//
24b8de11cSAlexey Samsonov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64b8de11cSAlexey Samsonov //
74b8de11cSAlexey Samsonov //===----------------------------------------------------------------------===//
84b8de11cSAlexey Samsonov //
94b8de11cSAlexey Samsonov // Class which emits metadata consumed by sanitizer instrumentation passes.
104b8de11cSAlexey Samsonov //
114b8de11cSAlexey Samsonov //===----------------------------------------------------------------------===//
124b8de11cSAlexey Samsonov #include "SanitizerMetadata.h"
134b8de11cSAlexey Samsonov #include "CodeGenModule.h"
149803178aSReid Kleckner #include "clang/AST/Attr.h"
15a0ac3c2bSAlexey Samsonov #include "clang/AST/Type.h"
1686565c13SReid Kleckner #include "clang/Basic/SourceManager.h"
174b8de11cSAlexey Samsonov #include "llvm/ADT/StringRef.h"
184b8de11cSAlexey Samsonov #include "llvm/IR/Constants.h"
194b8de11cSAlexey Samsonov 
204b8de11cSAlexey Samsonov using namespace clang;
214b8de11cSAlexey Samsonov using namespace CodeGen;
224b8de11cSAlexey Samsonov 
SanitizerMetadata(CodeGenModule & CGM)234b8de11cSAlexey Samsonov SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
244b8de11cSAlexey Samsonov 
isAsanHwasanOrMemTag(const SanitizerSet & SS)25c5e7f562SEvgeniy Stepanov static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) {
26c5e7f562SEvgeniy Stepanov   return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress |
2777475ffdSMitch Phillips                      SanitizerKind::HWAddress | SanitizerKind::MemTag);
2877475ffdSMitch Phillips }
2977475ffdSMitch Phillips 
expandKernelSanitizerMasks(SanitizerMask Mask)3077475ffdSMitch Phillips SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) {
3177475ffdSMitch Phillips   if (Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress))
3277475ffdSMitch Phillips     Mask |= SanitizerKind::Address | SanitizerKind::KernelAddress;
3377475ffdSMitch Phillips   // Note: KHWASan doesn't support globals.
3477475ffdSMitch Phillips   return Mask;
35c5e7f562SEvgeniy Stepanov }
36c5e7f562SEvgeniy Stepanov 
reportGlobal(llvm::GlobalVariable * GV,SourceLocation Loc,StringRef Name,QualType Ty,SanitizerMask NoSanitizeAttrMask,bool IsDynInit)37f49a5844SMitch Phillips void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
384b8de11cSAlexey Samsonov                                      SourceLocation Loc, StringRef Name,
3977475ffdSMitch Phillips                                      QualType Ty,
4077475ffdSMitch Phillips                                      SanitizerMask NoSanitizeAttrMask,
4177475ffdSMitch Phillips                                      bool IsDynInit) {
4277475ffdSMitch Phillips   SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize;
4377475ffdSMitch Phillips   if (!isAsanHwasanOrMemTag(FsanitizeArgument))
4477475ffdSMitch Phillips     return;
454b8de11cSAlexey Samsonov 
4677475ffdSMitch Phillips   FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask);
4777475ffdSMitch Phillips   NoSanitizeAttrMask = expandKernelSanitizerMasks(NoSanitizeAttrMask);
4877475ffdSMitch Phillips   SanitizerSet NoSanitizeAttrSet = {NoSanitizeAttrMask &
4977475ffdSMitch Phillips                                     FsanitizeArgument.Mask};
5077475ffdSMitch Phillips 
5177475ffdSMitch Phillips   llvm::GlobalVariable::SanitizerMetadata Meta;
5277475ffdSMitch Phillips   if (GV->hasSanitizerMetadata())
5377475ffdSMitch Phillips     Meta = GV->getSanitizerMetadata();
5477475ffdSMitch Phillips 
5577475ffdSMitch Phillips   Meta.NoAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::Address);
5677475ffdSMitch Phillips   Meta.NoAddress |= CGM.isInNoSanitizeList(
5777475ffdSMitch Phillips       FsanitizeArgument.Mask & SanitizerKind::Address, GV, Loc, Ty);
5877475ffdSMitch Phillips 
5977475ffdSMitch Phillips   Meta.NoHWAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::HWAddress);
6077475ffdSMitch Phillips   Meta.NoHWAddress |= CGM.isInNoSanitizeList(
6177475ffdSMitch Phillips       FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty);
6277475ffdSMitch Phillips 
63*90e5a8acSMitch Phillips   Meta.Memtag |=
64*90e5a8acSMitch Phillips       static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals);
65*90e5a8acSMitch Phillips   Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);
66*90e5a8acSMitch Phillips   Meta.Memtag &= !CGM.isInNoSanitizeList(
6777475ffdSMitch Phillips       FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty);
6877475ffdSMitch Phillips 
69f18de761SMitch Phillips   Meta.IsDynInit = IsDynInit && !Meta.NoAddress &&
70f18de761SMitch Phillips                    FsanitizeArgument.has(SanitizerKind::Address) &&
71f18de761SMitch Phillips                    !CGM.isInNoSanitizeList(SanitizerKind::Address |
7277475ffdSMitch Phillips                                                SanitizerKind::KernelAddress,
7377475ffdSMitch Phillips                                            GV, Loc, Ty, "init");
7477475ffdSMitch Phillips 
7577475ffdSMitch Phillips   GV->setSanitizerMetadata(Meta);
764b8de11cSAlexey Samsonov }
774b8de11cSAlexey Samsonov 
reportGlobal(llvm::GlobalVariable * GV,const VarDecl & D,bool IsDynInit)78f49a5844SMitch Phillips void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D,
79f49a5844SMitch Phillips                                      bool IsDynInit) {
80c5e7f562SEvgeniy Stepanov   if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
814b8de11cSAlexey Samsonov     return;
824b8de11cSAlexey Samsonov   std::string QualName;
834b8de11cSAlexey Samsonov   llvm::raw_string_ostream OS(QualName);
844b8de11cSAlexey Samsonov   D.printQualifiedName(OS);
853ed0f643SDouglas Katzman 
86d7df3f0aSVitaly Buka   auto getNoSanitizeMask = [](const VarDecl &D) {
87c85a2645SAlexander Potapenko     if (D.hasAttr<DisableSanitizerInstrumentationAttr>())
88d7df3f0aSVitaly Buka       return SanitizerKind::All;
89d7df3f0aSVitaly Buka 
90d7df3f0aSVitaly Buka     SanitizerMask NoSanitizeMask;
91d7df3f0aSVitaly Buka     for (auto *Attr : D.specific_attrs<NoSanitizeAttr>())
92d7df3f0aSVitaly Buka       NoSanitizeMask |= Attr->getMask();
93d7df3f0aSVitaly Buka 
94d7df3f0aSVitaly Buka     return NoSanitizeMask;
95d7df3f0aSVitaly Buka   };
964b8de11cSAlexey Samsonov 
9777475ffdSMitch Phillips   reportGlobal(GV, D.getLocation(), OS.str(), D.getType(), getNoSanitizeMask(D),
9877475ffdSMitch Phillips                IsDynInit);
99f32ad570SVitaly Buka }
100f32ad570SVitaly Buka 
disableSanitizerForGlobal(llvm::GlobalVariable * GV)1014b8de11cSAlexey Samsonov void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
10277475ffdSMitch Phillips   reportGlobal(GV, SourceLocation(), "", QualType(), SanitizerKind::All);
1034b8de11cSAlexey Samsonov }
104d9ad5cecSAlexey Samsonov 
disableSanitizerForInstruction(llvm::Instruction * I)1054ee69042SKostya Serebryany void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) {
10652992f13SEnna1   I->setMetadata(llvm::LLVMContext::MD_nosanitize,
107fb494914SDuncan P. N. Exon Smith                  llvm::MDNode::get(CGM.getLLVMContext(), None));
1084ee69042SKostya Serebryany }
109