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