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 | SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} |
24 | |
25 | static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) { |
26 | return SS.hasOneOf(K: SanitizerKind::Address | SanitizerKind::KernelAddress | |
27 | SanitizerKind::HWAddress | SanitizerKind::MemTag); |
28 | } |
29 | |
30 | SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { |
31 | if (Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress)) |
32 | Mask |= SanitizerKind::Address | SanitizerKind::KernelAddress; |
33 | // Note: KHWASan doesn't support globals. |
34 | return Mask; |
35 | } |
36 | |
37 | void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, |
38 | SourceLocation Loc, StringRef Name, |
39 | QualType Ty, |
40 | SanitizerMask NoSanitizeAttrMask, |
41 | bool IsDynInit) { |
42 | SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize; |
43 | if (!isAsanHwasanOrMemTag(SS: FsanitizeArgument)) |
44 | return; |
45 | |
46 | FsanitizeArgument.Mask = expandKernelSanitizerMasks(Mask: FsanitizeArgument.Mask); |
47 | NoSanitizeAttrMask = expandKernelSanitizerMasks(Mask: NoSanitizeAttrMask); |
48 | SanitizerSet NoSanitizeAttrSet = {.Mask: NoSanitizeAttrMask & |
49 | FsanitizeArgument.Mask}; |
50 | |
51 | llvm::GlobalVariable::SanitizerMetadata Meta; |
52 | if (GV->hasSanitizerMetadata()) |
53 | Meta = GV->getSanitizerMetadata(); |
54 | |
55 | Meta.NoAddress |= NoSanitizeAttrSet.hasOneOf(K: SanitizerKind::Address); |
56 | Meta.NoAddress |= CGM.isInNoSanitizeList( |
57 | Kind: FsanitizeArgument.Mask & SanitizerKind::Address, GV, Loc, Ty); |
58 | |
59 | Meta.NoHWAddress |= NoSanitizeAttrSet.hasOneOf(K: SanitizerKind::HWAddress); |
60 | Meta.NoHWAddress |= CGM.isInNoSanitizeList( |
61 | Kind: FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty); |
62 | |
63 | Meta.Memtag |= |
64 | static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals); |
65 | Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(K: SanitizerKind::MemTag); |
66 | Meta.Memtag &= !CGM.isInNoSanitizeList( |
67 | Kind: FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty); |
68 | |
69 | Meta.IsDynInit = IsDynInit && !Meta.NoAddress && |
70 | FsanitizeArgument.has(K: SanitizerKind::Address) && |
71 | !CGM.isInNoSanitizeList(Kind: SanitizerKind::Address | |
72 | SanitizerKind::KernelAddress, |
73 | GV, Loc, Ty, Category: "init" ); |
74 | |
75 | GV->setSanitizerMetadata(Meta); |
76 | } |
77 | |
78 | void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, |
79 | bool IsDynInit) { |
80 | if (!isAsanHwasanOrMemTag(SS: CGM.getLangOpts().Sanitize)) |
81 | return; |
82 | std::string QualName; |
83 | llvm::raw_string_ostream OS(QualName); |
84 | D.printQualifiedName(OS); |
85 | |
86 | auto getNoSanitizeMask = [](const VarDecl &D) { |
87 | if (D.hasAttr<DisableSanitizerInstrumentationAttr>()) |
88 | return SanitizerKind::All; |
89 | |
90 | SanitizerMask NoSanitizeMask; |
91 | for (auto *Attr : D.specific_attrs<NoSanitizeAttr>()) |
92 | NoSanitizeMask |= Attr->getMask(); |
93 | |
94 | return NoSanitizeMask; |
95 | }; |
96 | |
97 | reportGlobal(GV, D.getLocation(), OS.str(), D.getType(), getNoSanitizeMask(D), |
98 | IsDynInit); |
99 | } |
100 | |
101 | void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { |
102 | reportGlobal(GV, Loc: SourceLocation(), Name: "" , Ty: QualType(), NoSanitizeAttrMask: SanitizerKind::All); |
103 | } |
104 | |