1 //===--- SanitizerMetadata.cpp - Blacklist for sanitizers -----------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Class which emits metadata consumed by sanitizer instrumentation passes.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "SanitizerMetadata.h"
14 #include "CodeGenModule.h"
15 #include "clang/AST/Type.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/IR/Constants.h"
18 
19 using namespace clang;
20 using namespace CodeGen;
21 
22 SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
23 
24 void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
25                                            SourceLocation Loc, StringRef Name,
26                                            QualType Ty, bool IsDynInit,
27                                            bool IsBlacklisted) {
28   if (!CGM.getLangOpts().Sanitize.Address)
29     return;
30   IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init");
31   IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty);
32 
33   llvm::Value *LocDescr = nullptr;
34   llvm::Value *GlobalName = nullptr;
35   llvm::LLVMContext &VMContext = CGM.getLLVMContext();
36   if (!IsBlacklisted) {
37     // Don't generate source location and global name if it is blacklisted -
38     // it won't be instrumented anyway.
39     LocDescr = getLocationMetadata(Loc);
40     if (!Name.empty())
41       GlobalName = llvm::MDString::get(VMContext, Name);
42   }
43 
44   llvm::Value *GlobalMetadata[] = {
45       GV, LocDescr, GlobalName,
46       llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit),
47       llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsBlacklisted)};
48 
49   llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
50   llvm::NamedMDNode *AsanGlobals =
51       CGM.getModule().getOrInsertNamedMetadata("llvm.asan.globals");
52   AsanGlobals->addOperand(ThisGlobal);
53 }
54 
55 void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
56                                            const VarDecl &D, bool IsDynInit) {
57   if (!CGM.getLangOpts().Sanitize.Address)
58     return;
59   std::string QualName;
60   llvm::raw_string_ostream OS(QualName);
61   D.printQualifiedName(OS);
62   reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit);
63 }
64 
65 void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
66   // For now, just make sure the global is not modified by the ASan
67   // instrumentation.
68   if (CGM.getLangOpts().Sanitize.Address)
69     reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
70 }
71 
72 void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) {
73   I->setMetadata(
74       CGM.getModule().getMDKindID("nosanitize"),
75       llvm::MDNode::get(CGM.getLLVMContext(), ArrayRef<llvm::Value *>()));
76 }
77 
78 llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) {
79   PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc);
80   if (!PLoc.isValid())
81     return nullptr;
82   llvm::LLVMContext &VMContext = CGM.getLLVMContext();
83   llvm::Value *LocMetadata[] = {
84       llvm::MDString::get(VMContext, PLoc.getFilename()),
85       llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), PLoc.getLine()),
86       llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
87                              PLoc.getColumn()),
88   };
89   return llvm::MDNode::get(VMContext, LocMetadata);
90 }
91