clang  9.0.0svn
SanitizerMetadata.cpp
Go to the documentation of this file.
1 //===--- SanitizerMetadata.cpp - Blacklist 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/Type.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/IR/Constants.h"
17 
18 using namespace clang;
19 using namespace CodeGen;
20 
21 SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
22 
23 void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
24  SourceLocation Loc, StringRef Name,
25  QualType Ty, bool IsDynInit,
26  bool IsBlacklisted) {
27  if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
28  SanitizerKind::KernelAddress |
29  SanitizerKind::HWAddress |
30  SanitizerKind::KernelHWAddress))
31  return;
32  IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init");
33  IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty);
34 
35  llvm::Metadata *LocDescr = nullptr;
36  llvm::Metadata *GlobalName = nullptr;
37  llvm::LLVMContext &VMContext = CGM.getLLVMContext();
38  if (!IsBlacklisted) {
39  // Don't generate source location and global name if it is blacklisted -
40  // it won't be instrumented anyway.
41  LocDescr = getLocationMetadata(Loc);
42  if (!Name.empty())
43  GlobalName = llvm::MDString::get(VMContext, Name);
44  }
45 
46  llvm::Metadata *GlobalMetadata[] = {
47  llvm::ConstantAsMetadata::get(GV), LocDescr, GlobalName,
48  llvm::ConstantAsMetadata::get(
49  llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit)),
50  llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
51  llvm::Type::getInt1Ty(VMContext), IsBlacklisted))};
52 
53  llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
54  llvm::NamedMDNode *AsanGlobals =
55  CGM.getModule().getOrInsertNamedMetadata("llvm.asan.globals");
56  AsanGlobals->addOperand(ThisGlobal);
57 }
58 
59 void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
60  const VarDecl &D, bool IsDynInit) {
61  if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
62  SanitizerKind::KernelAddress |
63  SanitizerKind::HWAddress |
64  SanitizerKind::KernelHWAddress))
65  return;
66  std::string QualName;
67  llvm::raw_string_ostream OS(QualName);
68  D.printQualifiedName(OS);
69 
70  bool IsBlacklisted = false;
71  for (auto Attr : D.specific_attrs<NoSanitizeAttr>())
72  if (Attr->getMask() & SanitizerKind::Address)
73  IsBlacklisted = true;
74  reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit,
75  IsBlacklisted);
76 }
77 
78 void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
79  // For now, just make sure the global is not modified by the ASan
80  // instrumentation.
81  if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
82  SanitizerKind::KernelAddress |
83  SanitizerKind::HWAddress |
84  SanitizerKind::KernelHWAddress))
85  reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
86 }
87 
89  I->setMetadata(CGM.getModule().getMDKindID("nosanitize"),
90  llvm::MDNode::get(CGM.getLLVMContext(), None));
91 }
92 
93 llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) {
95  if (!PLoc.isValid())
96  return nullptr;
97  llvm::LLVMContext &VMContext = CGM.getLLVMContext();
98  llvm::Metadata *LocMetadata[] = {
99  llvm::MDString::get(VMContext, PLoc.getFilename()),
100  llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
101  llvm::Type::getInt32Ty(VMContext), PLoc.getLine())),
102  llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
103  llvm::Type::getInt32Ty(VMContext), PLoc.getColumn())),
104  };
105  return llvm::MDNode::get(VMContext, LocMetadata);
106 }
A (possibly-)qualified type.
Definition: Type.h:634
llvm::LLVMContext & getLLVMContext()
SanitizerSet Sanitize
Set of enabled sanitizers.
Definition: LangOptions.h:183
C Language Family Type Representation.
Represents a variable declaration or definition.
Definition: Decl.h:812
bool hasOneOf(SanitizerMask K) const
Check if one or more sanitizers are enabled.
Definition: Sanitizers.h:57
void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D, bool IsDynInit=false)
void disableSanitizerForInstruction(llvm::Instruction *I)
bool isInSanitizerBlacklist(SanitizerMask Kind, llvm::Function *Fn, SourceLocation Loc) const
bool isValid() const
unsigned getLine() const
Return the presumed line number of this location.
Represents an unpacked "presumed" location which can be presented to the user.
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
Definition: Decl.cpp:1526
const LangOptions & getLangOpts() const
ASTContext & getContext() const
const char * getFilename() const
Return the presumed filename of this location.
void disableSanitizerForGlobal(llvm::GlobalVariable *GV)
unsigned getColumn() const
Return the presumed column number of this location.
Encodes a location in the source.
This class organizes the cross-function state that is used while generating LLVM code.
Dataflow Directional Tag Classes.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
llvm::Module & getModule() const
SourceManager & getSourceManager()
Definition: ASTContext.h:661
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:515
QualType getType() const
Definition: Decl.h:647
Attr - This represents one attribute.
Definition: Attr.h:43
SourceLocation getLocation() const
Definition: DeclBase.h:420