mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-09 21:26:06 +00:00

This commit changes the way we blacklist functions in ASan, TSan, MSan and UBSan. We used to treat function as "blacklisted" and turned off instrumentation in it in two cases: 1) Function is explicitly blacklisted by its mangled name. This part is not changed. 2) Function is located in llvm::Module, whose identifier is contained in the list of blacklisted sources. This is completely wrong, as llvm::Module may not correspond to the actual source file function is defined in. Also, function can be defined in a header, in which case user had to blacklist the .cpp file this header was #include'd into, not the header itself. Such functions could cause other problems - for instance, if the header was included in multiple source files, compiled separately and linked into a single executable, we could end up with both instrumented and non-instrumented version of the same function participating in the same link. After this change we will make blacklisting decision based on the SourceLocation of a function definition. If a function is not explicitly defined in the source file, (for example, the function is compiler-generated and responsible for initialization/destruction of a global variable), then it will be blacklisted if the corresponding global variable is defined in blacklisted source file, and will be instrumented otherwise. After this commit, the active users of blacklist files may have to revisit them. This is a backwards-incompatible change, but I don't think it's possible or makes sense to support the old incorrect behavior. I plan to make similar change for blacklisting GlobalVariables (which is ASan-specific). llvm-svn: 219997
89 lines
3.4 KiB
C++
89 lines
3.4 KiB
C++
//===--- SanitizerMetadata.cpp - Blacklist for sanitizers -----------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Class which emits metadata consumed by sanitizer instrumentation passes.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "SanitizerMetadata.h"
|
|
#include "CodeGenModule.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
using namespace clang;
|
|
using namespace CodeGen;
|
|
|
|
SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
|
|
|
|
void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
|
|
SourceLocation Loc, StringRef Name,
|
|
bool IsDynInit, bool IsBlacklisted) {
|
|
if (!CGM.getLangOpts().Sanitize.Address)
|
|
return;
|
|
IsDynInit &= !CGM.getContext().getSanitizerBlacklist().isIn(*GV, "init");
|
|
IsBlacklisted |= CGM.getContext().getSanitizerBlacklist().isIn(*GV);
|
|
|
|
llvm::Value *LocDescr = nullptr;
|
|
llvm::Value *GlobalName = nullptr;
|
|
llvm::LLVMContext &VMContext = CGM.getLLVMContext();
|
|
if (!IsBlacklisted) {
|
|
// Don't generate source location and global name if it is blacklisted -
|
|
// it won't be instrumented anyway.
|
|
LocDescr = getLocationMetadata(Loc);
|
|
if (!Name.empty())
|
|
GlobalName = llvm::MDString::get(VMContext, Name);
|
|
}
|
|
|
|
llvm::Value *GlobalMetadata[] = {
|
|
GV, LocDescr, GlobalName,
|
|
llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit),
|
|
llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsBlacklisted)};
|
|
|
|
llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
|
|
llvm::NamedMDNode *AsanGlobals =
|
|
CGM.getModule().getOrInsertNamedMetadata("llvm.asan.globals");
|
|
AsanGlobals->addOperand(ThisGlobal);
|
|
}
|
|
|
|
void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
|
|
const VarDecl &D, bool IsDynInit) {
|
|
if (!CGM.getLangOpts().Sanitize.Address)
|
|
return;
|
|
std::string QualName;
|
|
llvm::raw_string_ostream OS(QualName);
|
|
D.printQualifiedName(OS);
|
|
reportGlobalToASan(GV, D.getLocation(), OS.str(), IsDynInit);
|
|
}
|
|
|
|
void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
|
|
// For now, just make sure the global is not modified by the ASan
|
|
// instrumentation.
|
|
if (CGM.getLangOpts().Sanitize.Address)
|
|
reportGlobalToASan(GV, SourceLocation(), "", false, true);
|
|
}
|
|
|
|
void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) {
|
|
I->setMetadata(
|
|
CGM.getModule().getMDKindID("nosanitize"),
|
|
llvm::MDNode::get(CGM.getLLVMContext(), ArrayRef<llvm::Value *>()));
|
|
}
|
|
|
|
llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) {
|
|
PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc);
|
|
if (!PLoc.isValid())
|
|
return nullptr;
|
|
llvm::LLVMContext &VMContext = CGM.getLLVMContext();
|
|
llvm::Value *LocMetadata[] = {
|
|
llvm::MDString::get(VMContext, PLoc.getFilename()),
|
|
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), PLoc.getLine()),
|
|
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
|
|
PLoc.getColumn()),
|
|
};
|
|
return llvm::MDNode::get(VMContext, LocMetadata);
|
|
}
|