/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/CodeGen/SanitizerMetadata.cpp
Line | Count | Source |
1 | | //===--- SanitizerMetadata.cpp - Ignored entities for sanitizers ----------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // Class which emits metadata consumed by sanitizer instrumentation passes. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | #include "SanitizerMetadata.h" |
13 | | #include "CodeGenModule.h" |
14 | | #include "clang/AST/Attr.h" |
15 | | #include "clang/AST/Type.h" |
16 | | #include "clang/Basic/SourceManager.h" |
17 | | #include "llvm/ADT/StringRef.h" |
18 | | #include "llvm/IR/Constants.h" |
19 | | |
20 | | using namespace clang; |
21 | | using namespace CodeGen; |
22 | | |
23 | 36.4k | SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} |
24 | | |
25 | 132k | static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) { |
26 | 132k | return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | |
27 | 132k | SanitizerKind::HWAddress | SanitizerKind::MemTag); |
28 | 132k | } |
29 | | |
30 | 1.08k | SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { |
31 | 1.08k | if (Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress)) |
32 | 517 | Mask |= SanitizerKind::Address | SanitizerKind::KernelAddress; |
33 | | // Note: KHWASan doesn't support globals. |
34 | 1.08k | return Mask; |
35 | 1.08k | } |
36 | | |
37 | | void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, |
38 | | SourceLocation Loc, StringRef Name, |
39 | | QualType Ty, |
40 | | SanitizerMask NoSanitizeAttrMask, |
41 | 61.2k | bool IsDynInit) { |
42 | 61.2k | SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize; |
43 | 61.2k | if (!isAsanHwasanOrMemTag(FsanitizeArgument)) |
44 | 60.7k | return; |
45 | | |
46 | 544 | FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask); |
47 | 544 | NoSanitizeAttrMask = expandKernelSanitizerMasks(NoSanitizeAttrMask); |
48 | 544 | SanitizerSet NoSanitizeAttrSet = {NoSanitizeAttrMask & |
49 | 544 | FsanitizeArgument.Mask}; |
50 | | |
51 | 544 | llvm::GlobalVariable::SanitizerMetadata Meta; |
52 | 544 | if (GV->hasSanitizerMetadata()) |
53 | 249 | Meta = GV->getSanitizerMetadata(); |
54 | | |
55 | 544 | Meta.NoAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::Address); |
56 | 544 | Meta.NoAddress |= CGM.isInNoSanitizeList( |
57 | 544 | FsanitizeArgument.Mask & SanitizerKind::Address, GV, Loc, Ty); |
58 | | |
59 | 544 | Meta.NoHWAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::HWAddress); |
60 | 544 | Meta.NoHWAddress |= CGM.isInNoSanitizeList( |
61 | 544 | FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty); |
62 | | |
63 | 544 | Meta.Memtag |= |
64 | 544 | static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals); |
65 | 544 | Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag); |
66 | 544 | Meta.Memtag &= !CGM.isInNoSanitizeList( |
67 | 544 | FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty); |
68 | | |
69 | 544 | Meta.IsDynInit = IsDynInit && !Meta.NoAddress75 && |
70 | 544 | FsanitizeArgument.has(SanitizerKind::Address)71 && |
71 | 544 | !CGM.isInNoSanitizeList(SanitizerKind::Address | |
72 | 71 | SanitizerKind::KernelAddress, |
73 | 71 | GV, Loc, Ty, "init"); |
74 | | |
75 | 544 | GV->setSanitizerMetadata(Meta); |
76 | 544 | } |
77 | | |
78 | | void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, |
79 | 70.8k | bool IsDynInit) { |
80 | 70.8k | if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) |
81 | 70.3k | return; |
82 | 499 | std::string QualName; |
83 | 499 | llvm::raw_string_ostream OS(QualName); |
84 | 499 | D.printQualifiedName(OS); |
85 | | |
86 | 499 | auto getNoSanitizeMask = [](const VarDecl &D) { |
87 | 499 | if (D.hasAttr<DisableSanitizerInstrumentationAttr>()) |
88 | 18 | return SanitizerKind::All; |
89 | | |
90 | 481 | SanitizerMask NoSanitizeMask; |
91 | 481 | for (auto *Attr : D.specific_attrs<NoSanitizeAttr>()) |
92 | 25 | NoSanitizeMask |= Attr->getMask(); |
93 | | |
94 | 481 | return NoSanitizeMask; |
95 | 499 | }; |
96 | | |
97 | 499 | reportGlobal(GV, D.getLocation(), OS.str(), D.getType(), getNoSanitizeMask(D), |
98 | 499 | IsDynInit); |
99 | 499 | } |
100 | | |
101 | 4.06k | void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { |
102 | 4.06k | reportGlobal(GV, SourceLocation(), "", QualType(), SanitizerKind::All); |
103 | 4.06k | } |
104 | | |
105 | 15.6k | void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { |
106 | 15.6k | I->setMetadata(llvm::LLVMContext::MD_nosanitize, |
107 | 15.6k | llvm::MDNode::get(CGM.getLLVMContext(), None)); |
108 | 15.6k | } |