xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/SanitizerMetadata.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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 
SanitizerMetadata(CodeGenModule & CGM)230b57cec5SDimitry Andric SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
240b57cec5SDimitry Andric 
isAsanHwasanOrMemTag(const SanitizerSet & SS)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 
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,
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 
reportGlobal(llvm::GlobalVariable * GV,const VarDecl & D,bool IsDynInit)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 
disableSanitizerForGlobal(llvm::GlobalVariable * GV)1010b57cec5SDimitry Andric void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
10281ad6265SDimitry Andric   reportGlobal(GV, SourceLocation(), "", QualType(), SanitizerKind::All);
1030b57cec5SDimitry Andric }
104