Home | History | Annotate | Line # | Download | only in CodeGen
      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(SanitizerKind::Address | SanitizerKind::KernelAddress |
     27                      SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress |
     28                      SanitizerKind::MemTag);
     29 }
     30 
     31 void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
     32                                            SourceLocation Loc, StringRef Name,
     33                                            QualType Ty, bool IsDynInit,
     34                                            bool IsExcluded) {
     35   if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
     36     return;
     37   IsDynInit &= !CGM.isInNoSanitizeList(GV, Loc, Ty, "init");
     38   IsExcluded |= CGM.isInNoSanitizeList(GV, Loc, Ty);
     39 
     40   llvm::Metadata *LocDescr = nullptr;
     41   llvm::Metadata *GlobalName = nullptr;
     42   llvm::LLVMContext &VMContext = CGM.getLLVMContext();
     43   if (!IsExcluded) {
     44     // Don't generate source location and global name if it is on
     45     // the NoSanitizeList - it won't be instrumented anyway.
     46     LocDescr = getLocationMetadata(Loc);
     47     if (!Name.empty())
     48       GlobalName = llvm::MDString::get(VMContext, Name);
     49   }
     50 
     51   llvm::Metadata *GlobalMetadata[] = {
     52       llvm::ConstantAsMetadata::get(GV), LocDescr, GlobalName,
     53       llvm::ConstantAsMetadata::get(
     54           llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit)),
     55       llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
     56           llvm::Type::getInt1Ty(VMContext), IsExcluded))};
     57 
     58   llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
     59   llvm::NamedMDNode *AsanGlobals =
     60       CGM.getModule().getOrInsertNamedMetadata("llvm.asan.globals");
     61   AsanGlobals->addOperand(ThisGlobal);
     62 }
     63 
     64 void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
     65                                            const VarDecl &D, bool IsDynInit) {
     66   if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
     67     return;
     68   std::string QualName;
     69   llvm::raw_string_ostream OS(QualName);
     70   D.printQualifiedName(OS);
     71 
     72   bool IsExcluded = false;
     73   for (auto Attr : D.specific_attrs<NoSanitizeAttr>())
     74     if (Attr->getMask() & SanitizerKind::Address)
     75       IsExcluded = true;
     76   reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit,
     77                      IsExcluded);
     78 }
     79 
     80 void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
     81   // For now, just make sure the global is not modified by the ASan
     82   // instrumentation.
     83   if (isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
     84     reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
     85 }
     86 
     87 void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) {
     88   I->setMetadata(CGM.getModule().getMDKindID("nosanitize"),
     89                  llvm::MDNode::get(CGM.getLLVMContext(), None));
     90 }
     91 
     92 llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) {
     93   PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc);
     94   if (!PLoc.isValid())
     95     return nullptr;
     96   llvm::LLVMContext &VMContext = CGM.getLLVMContext();
     97   llvm::Metadata *LocMetadata[] = {
     98       llvm::MDString::get(VMContext, PLoc.getFilename()),
     99       llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
    100           llvm::Type::getInt32Ty(VMContext), PLoc.getLine())),
    101       llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
    102           llvm::Type::getInt32Ty(VMContext), PLoc.getColumn())),
    103   };
    104   return llvm::MDNode::get(VMContext, LocMetadata);
    105 }
    106