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