Clang Project

clang_source_code/lib/CodeGen/SanitizerMetadata.cpp
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
18using namespace clang;
19using namespace CodeGen;
20
21SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
22
23void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
24                                           SourceLocation LocStringRef Name,
25                                           QualType Tybool 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(GVLocTy"init");
33  IsBlacklisted |= CGM.isInSanitizerBlacklist(GVLocTy);
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
59void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
60                                           const VarDecl &Dbool 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
78void 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(GVSourceLocation(), ""QualType(), falsetrue);
86}
87
88void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) {
89  I->setMetadata(CGM.getModule().getMDKindID("nosanitize"),
90                 llvm::MDNode::get(CGM.getLLVMContext(), None));
91}
92
93llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) {
94  PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(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}
107
clang::CodeGen::SanitizerMetadata::reportGlobalToASan
clang::CodeGen::SanitizerMetadata::reportGlobalToASan
clang::CodeGen::SanitizerMetadata::disableSanitizerForGlobal
clang::CodeGen::SanitizerMetadata::disableSanitizerForInstruction
clang::CodeGen::SanitizerMetadata::getLocationMetadata