namespace llvm {
class GlobalVariable;
-class Function;
}
namespace clang {
public:
SanitizerBlacklist(StringRef BlacklistPath, SourceManager &SM);
- bool isIn(const llvm::Function &F) const;
bool isIn(const llvm::GlobalVariable &G,
StringRef Category = StringRef()) const;
bool isBlacklistedType(StringRef MangledTypeName,
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/SanitizerBlacklist.h"
-#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
SourceManager &SM)
: SCL(llvm::SpecialCaseList::createOrDie(BlacklistPath)), SM(SM) {}
-bool SanitizerBlacklist::isIn(const llvm::Function &F) const {
- return isBlacklistedFile(F.getParent()->getModuleIdentifier()) ||
- isBlacklistedFunction(F.getName());
-}
-
bool SanitizerBlacklist::isIn(const llvm::GlobalVariable &G,
StringRef Category) const {
return isBlacklistedFile(G.getParent()->getModuleIdentifier(), Category) ||
llvm::raw_svector_ostream Out(FnName);
CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);
}
- llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(ty, FnName.str());
+ llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(ty, FnName.str(),
+ VD.getLocation());
CodeGenFunction CGF(CGM);
CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
}
-llvm::Function *
-CodeGenModule::CreateGlobalInitOrDestructFunction(llvm::FunctionType *FTy,
- const Twine &Name, bool TLS) {
+llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
+ llvm::FunctionType *FTy, const Twine &Name, SourceLocation Loc, bool TLS) {
llvm::Function *Fn =
llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
Name, &getModule());
if (!getLangOpts().Exceptions)
Fn->setDoesNotThrow();
- if (!getSanitizerBlacklist().isIn(*Fn)) {
+ if (!isInSanitizerBlacklist(Fn, Loc)) {
if (getLangOpts().Sanitize.Address)
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
if (getLangOpts().Sanitize.Thread)
}
// Create a variable initialization function.
- llvm::Function *Fn = CreateGlobalInitOrDestructFunction(FTy, FnName.str());
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(FTy, FnName.str(), D->getLocation());
auto *ISA = D->getAttr<InitSegAttr>();
CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
getContext().VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
- llvm::Function *fn =
- CGM.CreateGlobalInitOrDestructFunction(FTy, "__cxx_global_array_dtor");
+ llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, "__cxx_global_array_dtor", VD->getLocation());
StartFunction(VD, getContext().VoidTy, fn, FI, args);
Out);
// Blacklist based on the mangled type.
- if (!CGM.getSanitizerBlacklist().isBlacklistedType(Out.str())) {
+ if (!CGM.getContext().getSanitizerBlacklist().isBlacklistedType(
+ Out.str())) {
llvm::hash_code TypeHash = hash_value(Out.str());
// Load the vptr, and compute hash_16_bytes(TypeHash, vptr).
CurFnInfo = &FnInfo;
assert(CurFn->isDeclaration() && "Function already has body?");
- if (CGM.getSanitizerBlacklist().isIn(*Fn))
+ if (CGM.isInSanitizerBlacklist(Fn, Loc))
SanOpts = &SanitizerOptions::Disabled;
// Pass inline keyword to optimizer if it appears explicitly on any
B.addAttribute(llvm::Attribute::StackProtectReq);
// Add sanitizer attributes if function is not blacklisted.
- if (!getSanitizerBlacklist().isIn(*F)) {
+ if (!isInSanitizerBlacklist(F, D->getLocation())) {
// When AddressSanitizer is enabled, set SanitizeAddress attribute
// unless __attribute__((no_sanitize_address)) is used.
if (LangOpts.Sanitize.Address && !D->hasAttr<NoSanitizeAddressAttr>())
Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation()));
}
+bool CodeGenModule::isInSanitizerBlacklist(llvm::Function *Fn,
+ SourceLocation Loc) const {
+ const auto &SanitizerBL = getContext().getSanitizerBlacklist();
+ // Blacklist by function name.
+ if (SanitizerBL.isBlacklistedFunction(Fn->getName()))
+ return true;
+ // Blacklist by location.
+ if (!Loc.isInvalid())
+ return SanitizerBL.isBlacklistedLocation(Loc);
+ // If location is unknown, this may be a compiler-generated function. Assume
+ // it's located in the main file.
+ auto &SM = Context.getSourceManager();
+ if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
+ return SanitizerBL.isBlacklistedFile(MainFile->getName());
+ }
+ return false;
+}
+
bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified.
if (LangOpts.EmitAllDecls)
CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty,
llvm::GlobalValue::LinkageTypes Linkage);
- llvm::Function *CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty,
- const Twine &name,
- bool TLS = false);
+ llvm::Function *
+ CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name,
+ SourceLocation Loc = SourceLocation(),
+ bool TLS = false);
/// Return the address space of the underlying global variable for D, as
/// determined by its declaration. Normally this is the same as the address
/// annotations are emitted during finalization of the LLVM code.
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
- const SanitizerBlacklist &getSanitizerBlacklist() const {
- return Context.getSanitizerBlacklist();
- }
+ bool isInSanitizerBlacklist(llvm::Function *Fn, SourceLocation Loc) const;
SanitizerMetadata *getSanitizerMetadata() {
return SanitizerMD.get();
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
InitFunc = CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init",
+ SourceLocation(),
/*TLS=*/true);
llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false,
if (!NonComdatInits.empty()) {
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
- llvm::Function *InitFunc =
- CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init",
- /*TLS=*/true);
+ llvm::Function *InitFunc = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, "__tls_init", SourceLocation(),
+ /*TLS=*/true);
CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits);
AddToXDU(InitFunc);
bool IsDynInit, bool IsBlacklisted) {
if (!CGM.getLangOpts().Sanitize.Address)
return;
- IsDynInit &= !CGM.getSanitizerBlacklist().isIn(*GV, "init");
- IsBlacklisted |= CGM.getSanitizerBlacklist().isIn(*GV);
+ IsDynInit &= !CGM.getContext().getSanitizerBlacklist().isIn(*GV, "init");
+ IsBlacklisted |= CGM.getContext().getSanitizerBlacklist().isIn(*GV);
llvm::Value *LocDescr = nullptr;
llvm::Value *GlobalName = nullptr;
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=address | FileCheck -check-prefix=ASAN %s
-// RUN: echo "src:%s" > %t.file.blacklist
+int DefinedInDifferentFile(int *a);
+// RUN: echo "int DefinedInDifferentFile(int *a) { return *a; }" > %t.extra-source.cpp
+// RUN: echo "struct S { S(){} ~S(){} };" >> %t.extra-source.cpp
+// RUN: echo "S glob_array[5];" >> %t.extra-source.cpp
+
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp | FileCheck -check-prefix=WITHOUT %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address | FileCheck -check-prefix=ASAN %s
+
// RUN: echo "fun:*BlacklistedFunction*" > %t.func.blacklist
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s
+
+// RUN: echo "src:%s" > %t.file.blacklist
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s
// FIXME: %t.file.blacklist is like "src:x:\path\to\clang\test\CodeGen\address-safety-attr.cpp"
// REQUIRES: shell
// when AddressSanitizer is enabled, unless no_sanitize_address attribute
// is present.
-// WITHOUT: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
+// Attributes for function defined in different source file:
+// WITHOUT: DefinedInDifferentFile{{.*}} [[NOATTR:#[0-9]+]]
+// BLFILE: DefinedInDifferentFile{{.*}} [[WITH:#[0-9]+]]
+// BLFUNC: DefinedInDifferentFile{{.*}} [[WITH:#[0-9]+]]
+// ASAN: DefinedInDifferentFile{{.*}} [[WITH:#[0-9]+]]
+
+// Check that functions generated for global in different source file are
+// not blacklisted.
+// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]]
+// WITHOUT: @__cxx_global_array_dtor{{.*}}[[NOATTR_NO_TF]]
+// BLFILE: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]]
+// BLFILE: @__cxx_global_array_dtor{{.*}}[[WITH_NO_TF]]
+// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]]
+// BLFUNC: @__cxx_global_array_dtor{{.*}}[[WITH_NO_TF]]
+// ASAN: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]]
+// ASAN: @__cxx_global_array_dtor{{.*}}[[WITH_NO_TF]]
+
+
+// WITHOUT: NoAddressSafety1{{.*}}) [[NOATTR]]
// BLFILE: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
// BLFUNC: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
// ASAN: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
// WITHOUT: AddressSafetyOk{{.*}}) [[NOATTR]]
// BLFILE: AddressSafetyOk{{.*}}) [[NOATTR]]
-// BLFUNC: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]]
-// ASAN: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]]
+// BLFUNC: AddressSafetyOk{{.*}}) [[WITH]]
+// ASAN: AddressSafetyOk{{.*}}) [[WITH]]
int AddressSafetyOk(int *a) { return *a; }
// WITHOUT: BlacklistedFunction{{.*}}) [[NOATTR]]
// Check that __cxx_global_var_init* get the sanitize_address attribute.
int global1 = 0;
int global2 = *(int*)((char*)&global1+1);
-// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]]
+// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF]]
// BLFILE: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]]
-// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]]
-// ASAN: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]]
+// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH_NO_TF]]
+// ASAN: @__cxx_global_var_init{{.*}}[[WITH_NO_TF]]
// WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} }
// WITHOUT: attributes [[NOATTR_NO_TF]] = { nounwind }
-// BLFILE: attributes [[NOATTR]] = { nounwind{{.*}} }
+// BLFILE: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
+// BLFILE: attributes [[WITH_NO_TF]] = { nounwind sanitize_address }
// BLFILE: attributes [[NOATTR_NO_TF]] = { nounwind }
+// BLFILE: attributes [[NOATTR]] = { nounwind{{.*}} }
-// BLFUNC: attributes [[NOATTR]] = { nounwind{{.*}} }
// BLFUNC: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
// BLFUNC: attributes [[WITH_NO_TF]] = { nounwind sanitize_address }
+// BLFUNC: attributes [[NOATTR]] = { nounwind{{.*}} }
-// ASAN: attributes [[NOATTR]] = { nounwind{{.*}} }
// ASAN: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
// ASAN: attributes [[WITH_NO_TF]] = { nounwind sanitize_address }
+// ASAN: attributes [[NOATTR]] = { nounwind{{.*}} }