diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -672,7 +672,6 @@ Opts.Recover = CodeGenOpts.SanitizeRecover.has(Mask); Opts.UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope; Opts.UseAfterReturn = CodeGenOpts.getSanitizeAddressUseAfterReturn(); - MPM.addPass(RequireAnalysisPass()); MPM.addPass(ModuleAddressSanitizerPass( Opts, UseGlobalGC, UseOdrIndicator, DestructorKind)); } diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -473,7 +473,7 @@ LocalDeclMap.find(&D)->second = Address(castedAddr, elemTy, alignment); CGM.setStaticLocalDeclAddress(&D, castedAddr); - CGM.getSanitizerMetadata()->reportGlobalToASan(var, D); + CGM.getSanitizerMetadataFactory()->reportGlobal(var, D); // Emit global variable debug descriptor for static vars. CGDebugInfo *DI = getDebugInfo(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3095,7 +3095,7 @@ CGM.getModule(), Descriptor->getType(), /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, Descriptor); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(GV); + CGM.getSanitizerMetadataFactory()->disableSanitizerForGlobal(GV); // Remember the descriptor for this type. CGM.setTypeDescriptorInMap(T, GV); @@ -3175,8 +3175,8 @@ auto FilenameGV = CGM.GetAddrOfConstantCString(std::string(FilenameString), ".src"); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal( - cast(FilenameGV.getPointer())); + CGM.getSanitizerMetadataFactory()->disableSanitizerForGlobal( + cast(FilenameGV.getPointer())); Filename = FilenameGV.getPointer(); Line = PLoc.getLine(); Column = PLoc.getColumn(); @@ -3348,7 +3348,7 @@ new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false, llvm::GlobalVariable::PrivateLinkage, Info); InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr); + CGM.getSanitizerMetadataFactory()->disableSanitizerForGlobal(InfoPtr); Args.push_back(Builder.CreateBitCast(InfoPtr, Int8PtrTy)); ArgTypes.push_back(Int8PtrTy); } @@ -3409,7 +3409,7 @@ new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false, llvm::GlobalVariable::PrivateLinkage, Info); InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr); + CGM.getSanitizerMetadataFactory()->disableSanitizerForGlobal(InfoPtr); SlowPathFn = CGM.getModule().getOrInsertFunction( "__cfi_slowpath_diag", diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1263,7 +1263,7 @@ new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false, llvm::GlobalVariable::PrivateLinkage, SLoc); SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr); + CGM.getSanitizerMetadataFactory()->disableSanitizerForGlobal(SLocPtr); assert(ReturnLocation.isValid() && "No valid return location"); Builder.CreateStore(Builder.CreateBitCast(SLocPtr, Int8PtrTy), ReturnLocation); diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -80,7 +80,7 @@ ModuleBuilder.cpp ObjectFilePCHContainerOperations.cpp PatternInit.cpp - SanitizerMetadata.cpp + SanitizerMetadataFactory.cpp SwiftCallingConv.cpp TargetInfo.cpp VarBypassDetector.cpp diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2510,7 +2510,7 @@ llvm::BasicBlock::iterator InsertPt) const { LoopStack.InsertHelper(I); if (IsSanitizerScope) - CGM.getSanitizerMetadata()->disableSanitizerForInstruction(I); + CGM.getSanitizerMetadataFactory()->disableSanitizerForInstruction(I); } void CGBuilderInserter::InsertHelper( diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -16,7 +16,7 @@ #include "CGVTables.h" #include "CodeGenTypeCache.h" #include "CodeGenTypes.h" -#include "SanitizerMetadata.h" +#include "SanitizerMetadataFactory.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" @@ -550,7 +550,7 @@ /// void @llvm.lifetime.end(i64 %size, i8* nocapture ) llvm::Function *LifetimeEndFn = nullptr; - std::unique_ptr SanitizerMD; + std::unique_ptr SanitizerMDFactory; llvm::MapVector DeferredEmptyCoverageMappingDecls; @@ -1310,8 +1310,8 @@ /// profile instrumentation. bool isProfileInstrExcluded(llvm::Function *Fn, SourceLocation Loc) const; - SanitizerMetadata *getSanitizerMetadata() { - return SanitizerMD.get(); + SanitizerMetadataFactory *getSanitizerMetadataFactory() { + return SanitizerMDFactory.get(); } void addDeferredVTable(const CXXRecordDecl *RD) { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -104,7 +104,7 @@ PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), Target(C.getTargetInfo()), ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this), VTables(*this), - SanitizerMD(new SanitizerMetadata(*this)) { + SanitizerMDFactory(new SanitizerMetadataFactory(*this)) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); @@ -2752,18 +2752,11 @@ bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, StringRef Category) const { - // For now globals can be ignored only in ASan and KASan. - const SanitizerMask EnabledAsanMask = - LangOpts.Sanitize.Mask & - (SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | - SanitizerKind::MemTag); - if (!EnabledAsanMask) - return false; const auto &NoSanitizeL = getContext().getNoSanitizeList(); - if (NoSanitizeL.containsGlobal(EnabledAsanMask, GV->getName(), Category)) + if (NoSanitizeL.containsGlobal(LangOpts.Sanitize.Mask, GV->getName(), + Category)) return true; - if (NoSanitizeL.containsLocation(EnabledAsanMask, Loc, Category)) + if (NoSanitizeL.containsLocation(LangOpts.Sanitize.Mask, Loc, Category)) return true; // Check global type. if (!Ty.isNull()) { @@ -2775,7 +2768,7 @@ // Only record types (classes, structs etc.) are ignored. if (Ty->isRecordType()) { std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy()); - if (NoSanitizeL.containsType(EnabledAsanMask, TypeStr, Category)) + if (NoSanitizeL.containsType(LangOpts.Sanitize.Mask, TypeStr, Category)) return true; } } @@ -4781,7 +4774,7 @@ if (NeedsGlobalCtor || NeedsGlobalDtor) EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); - SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor); + SanitizerMDFactory->reportGlobal(GV, *D, NeedsGlobalCtor); // Emit global variable debug information. if (CGDebugInfo *DI = getModuleDebugInfo()) @@ -5667,8 +5660,7 @@ if (Entry) *Entry = GV; - SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "", - QualType()); + SanitizerMDFactory->reportGlobal(GV, S->getStrTokenLoc(0), QualType()); return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), GV->getValueType(), Alignment); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2189,7 +2189,7 @@ (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() || CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) { // The store to the CookiePtr does not need to be instrumented. - CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI); + CGM.getSanitizerMetadataFactory()->disableSanitizerForInstruction(SI); llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); llvm::FunctionCallee F = diff --git a/clang/lib/CodeGen/SanitizerMetadata.h b/clang/lib/CodeGen/SanitizerMetadata.h deleted file mode 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.h +++ /dev/null @@ -1,52 +0,0 @@ -//===--- SanitizerMetadata.h - Metadata for sanitizers ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Class which emits metadata consumed by sanitizer instrumentation passes. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATA_H -#define LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATA_H - -#include "clang/AST/Type.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/SourceLocation.h" - -namespace llvm { -class GlobalVariable; -class Instruction; -class MDNode; -} - -namespace clang { -class VarDecl; - -namespace CodeGen { - -class CodeGenModule; - -class SanitizerMetadata { - SanitizerMetadata(const SanitizerMetadata &) = delete; - void operator=(const SanitizerMetadata &) = delete; - - CodeGenModule &CGM; -public: - SanitizerMetadata(CodeGenModule &CGM); - void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D, - bool IsDynInit = false); - void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc, - StringRef Name, QualType Ty, bool IsDynInit = false, - bool IsExcluded = false); - void disableSanitizerForGlobal(llvm::GlobalVariable *GV); - void disableSanitizerForInstruction(llvm::Instruction *I); -private: - llvm::MDNode *getLocationMetadata(SourceLocation Loc); -}; -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/clang/lib/CodeGen/SanitizerMetadata.cpp b/clang/lib/CodeGen/SanitizerMetadata.cpp deleted file mode 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//===--- SanitizerMetadata.cpp - Ignored entities for sanitizers ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Class which emits metadata consumed by sanitizer instrumentation passes. -// -//===----------------------------------------------------------------------===// -#include "SanitizerMetadata.h" -#include "CodeGenModule.h" -#include "clang/AST/Attr.h" -#include "clang/AST/Type.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Constants.h" - -using namespace clang; -using namespace CodeGen; - -SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} - -static bool isAsanHwasanOrMemTag(const SanitizerSet& SS) { - return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | - SanitizerKind::MemTag); -} - -void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, - SourceLocation Loc, StringRef Name, - QualType Ty, bool IsDynInit, - bool IsExcluded) { - if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) - return; - IsDynInit &= !CGM.isInNoSanitizeList(GV, Loc, Ty, "init"); - IsExcluded |= CGM.isInNoSanitizeList(GV, Loc, Ty); - - llvm::Metadata *LocDescr = nullptr; - llvm::Metadata *GlobalName = nullptr; - llvm::LLVMContext &VMContext = CGM.getLLVMContext(); - if (!IsExcluded) { - // Don't generate source location and global name if it is on - // the NoSanitizeList - it won't be instrumented anyway. - LocDescr = getLocationMetadata(Loc); - if (!Name.empty()) - GlobalName = llvm::MDString::get(VMContext, Name); - } - - llvm::Metadata *GlobalMetadata[] = { - llvm::ConstantAsMetadata::get(GV), LocDescr, GlobalName, - llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit)), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt1Ty(VMContext), IsExcluded))}; - - 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 (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) - return; - std::string QualName; - llvm::raw_string_ostream OS(QualName); - D.printQualifiedName(OS); - - bool IsExcluded = false; - for (auto Attr : D.specific_attrs()) - if (Attr->getMask() & SanitizerKind::Address) - IsExcluded = true; - if (D.hasAttr()) - IsExcluded = true; - reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit, - IsExcluded); -} - -void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { - // For now, just make sure the global is not modified by the ASan - // instrumentation. - if (isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) - reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true); -} - -void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { - I->setMetadata(CGM.getModule().getMDKindID("nosanitize"), - llvm::MDNode::get(CGM.getLLVMContext(), None)); -} - -llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) { - PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc); - if (!PLoc.isValid()) - return nullptr; - llvm::LLVMContext &VMContext = CGM.getLLVMContext(); - llvm::Metadata *LocMetadata[] = { - llvm::MDString::get(VMContext, PLoc.getFilename()), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(VMContext), PLoc.getLine())), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(VMContext), PLoc.getColumn())), - }; - return llvm::MDNode::get(VMContext, LocMetadata); -} diff --git a/clang/lib/CodeGen/SanitizerMetadataFactory.h b/clang/lib/CodeGen/SanitizerMetadataFactory.h new file mode 100644 --- /dev/null +++ b/clang/lib/CodeGen/SanitizerMetadataFactory.h @@ -0,0 +1,55 @@ +//===--- SanitizerMetadataFactory.h - Metadata for sanitizers ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Class which emits metadata consumed by sanitizer instrumentation passes. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATAFACTORY_H +#define LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATAFACTORY_H + +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Sanitizers.h" +#include "clang/Basic/SourceLocation.h" + +#include "llvm/IR/GlobalVariable.h" + +namespace llvm { +class Instruction; +} // namespace llvm + +namespace clang { +class VarDecl; + +namespace CodeGen { + +class CodeGenModule; + +class SanitizerMetadataFactory { + SanitizerMetadataFactory(const SanitizerMetadataFactory &) = delete; + void operator=(const SanitizerMetadataFactory &) = delete; + + CodeGenModule &CGM; + +public: + SanitizerMetadataFactory(CodeGenModule &CGM); + + void reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, + bool IsDynInit = false); + void reportGlobal(llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, + bool IsDynInit = false, SanitizerMask NoSanitizeMask = {}); + void setASanSpecificMetadata(llvm::GlobalVariable::SanitizerMetadata &Meta, + llvm::GlobalVariable *GV, SourceLocation Loc, + QualType Ty, bool IsDynInit = false); + void disableSanitizerForGlobal(llvm::GlobalVariable *GV); + void disableSanitizerForInstruction(llvm::Instruction *I); +}; +} // end namespace CodeGen +} // end namespace clang + +#endif // LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATAFACTORY_H diff --git a/clang/lib/CodeGen/SanitizerMetadataFactory.cpp b/clang/lib/CodeGen/SanitizerMetadataFactory.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/CodeGen/SanitizerMetadataFactory.cpp @@ -0,0 +1,116 @@ +//===--- SanitizerMetadataFactory.cpp - Ignored entities for sanitizers ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Class which emits metadata consumed by sanitizer instrumentation passes. +// +//===----------------------------------------------------------------------===// +#include "SanitizerMetadataFactory.h" +#include "CodeGenModule.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Type.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Constants.h" + +using GlobalVariable = llvm::GlobalVariable; +using SanitizerMetadata = GlobalVariable::SanitizerMetadata; +using GlobalSanitizer = SanitizerMetadata::GlobalSanitizer; + +namespace clang { +namespace CodeGen { + +SanitizerMetadataFactory::SanitizerMetadataFactory(CodeGenModule &CGM) + : CGM(CGM) {} + +void SanitizerMetadataFactory::setASanSpecificMetadata(SanitizerMetadata &Meta, + GlobalVariable *GV, + SourceLocation Loc, + QualType Ty, + bool IsDynInit) { + IsDynInit &= !CGM.isInNoSanitizeList(GV, Loc, Ty, "init"); + Meta.IsDynInit = IsDynInit; +} + +void SanitizerMetadataFactory::reportGlobal(GlobalVariable *GV, + SourceLocation Loc, QualType Ty, + bool IsDynInit, + SanitizerMask NoSanitizeMask) { + + SanitizerMetadata Meta; + if (GV->hasSanitizerMetadata()) + Meta = GV->getSanitizerMetadata(); + + if (CGM.isInNoSanitizeList(GV, Loc, Ty) || + NoSanitizeMask == SanitizerKind::All) { + Meta.AddSanitizer(GlobalSanitizer::NoSanitize); + GV->setSanitizerMetadata(Meta); + return; + } + + auto &SanTarget = CGM.getLangOpts().Sanitize; + SanitizerSet NoSanitizeSet; + NoSanitizeSet.Mask = NoSanitizeMask; + + if (SanTarget.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) { + if (NoSanitizeSet.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) + Meta.AddSanitizer(GlobalSanitizer::NoAddress); + else + Meta.AddSanitizer(GlobalSanitizer::Address); + + setASanSpecificMetadata(Meta, GV, Loc, Ty, IsDynInit); + } + if (SanTarget.hasOneOf(SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) { + if (NoSanitizeSet.hasOneOf(SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) + Meta.AddSanitizer(GlobalSanitizer::NoHWAddress); + else + Meta.AddSanitizer(GlobalSanitizer::HWAddress); + } + + if (SanTarget.hasOneOf(SanitizerKind::MemTag)) { + if (NoSanitizeSet.hasOneOf(SanitizerKind::MemTag)) + Meta.AddSanitizer(GlobalSanitizer::NoMemtag); + else + Meta.AddSanitizer(GlobalSanitizer::Memtag); + } + + GV->setSanitizerMetadata(Meta); +} + +void SanitizerMetadataFactory::reportGlobal(GlobalVariable *GV, + const VarDecl &D, bool IsDynInit) { + if (D.hasAttr()) { + SanitizerMetadata Meta; + Meta.AddSanitizer(GlobalSanitizer::NoSanitize); + GV->setSanitizerMetadata(Meta); + return; + } + + SanitizerMask NoSanitizeMask; + for (auto Attr : D.specific_attrs()) { + NoSanitizeMask |= Attr->getMask(); + } + + reportGlobal(GV, D.getLocation(), D.getType(), IsDynInit, NoSanitizeMask); +} + +void SanitizerMetadataFactory::disableSanitizerForGlobal(GlobalVariable *GV) { + reportGlobal(GV, SourceLocation(), QualType(), false, SanitizerKind::All); +} + +void SanitizerMetadataFactory::disableSanitizerForInstruction( + llvm::Instruction *I) { + I->setMetadata(CGM.getModule().getMDKindID("nosanitize"), + llvm::MDNode::get(CGM.getLLVMContext(), None)); +} + +} // namespace CodeGen +} // namespace clang diff --git a/clang/test/CodeGen/asan-globals-alias.cpp b/clang/test/CodeGen/asan-globals-alias.cpp --- a/clang/test/CodeGen/asan-globals-alias.cpp +++ b/clang/test/CodeGen/asan-globals-alias.cpp @@ -22,12 +22,12 @@ struct input_device_id joydev_ids[] = { { {1}, 1234 } }; // KASAN ignored extern struct input_device_id __attribute__((alias("joydev_ids"))) __mod_joydev_ids_device_table; -// ASAN: @aliased_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32 -// ASAN: @aliased_global_2{{.*}} global { i32, [28 x i8] }{{.*}}, align 32 -// ASAN: @joydev_ids{{.*}} global { {{.*}}[56 x i8] zeroinitializer }, align 32 +// ASAN: @aliased_global{{.*}} global { i32, [28 x i8] }{{.*}}, sanitize_address, align 32 +// ASAN: @aliased_global_2{{.*}} global { i32, [28 x i8] }{{.*}}, sanitize_address, align 32 +// ASAN: @joydev_ids{{.*}} global { {{.*}}[56 x i8] zeroinitializer }, sanitize_address, align 32 // KASAN: @aliased_global{{.*}} global i32 // KASAN: @aliased_global_2{{.*}} global i32 -// KASAN: @joydev_ids{{.*}} global [1 x {{.*}}i64 1234 }], align 16 +// KASAN: @joydev_ids{{.*}} global [1 x {{.*}}i64 1234 }], sanitize_address, align 16 // Check the aliases exist: // CHECK: @__global_alias ={{.*}} alias diff --git a/clang/test/CodeGen/asan-globals-odr.cpp b/clang/test/CodeGen/asan-globals-odr.cpp --- a/clang/test/CodeGen/asan-globals-odr.cpp +++ b/clang/test/CodeGen/asan-globals-odr.cpp @@ -14,7 +14,7 @@ return global; } -// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, align 32 +// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, sanitize_address, align 32 // INDICATOR0-NOT: __odr_asan_gen // INDICATOR1: [[ODR:@.*__odr_asan_gen_.*global.*]] = global i8 0, align 1 diff --git a/clang/test/CodeGen/asan-globals.cpp b/clang/test/CodeGen/asan-globals.cpp --- a/clang/test/CodeGen/asan-globals.cpp +++ b/clang/test/CodeGen/asan-globals.cpp @@ -1,7 +1,8 @@ // RUN: echo "int extra_global;" > %t.extra-source.cpp // RUN: echo "global:*ignorelisted_global*" > %t.ignorelist -// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,ASAN -// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=kernel-address -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,KASAN +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=kernel-address -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,GLOBS,KASAN + +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,GLOBS,ASAN // The ignorelist file uses regexps, so Windows path backslashes. // RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.ignorelist-src // RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-ignorelist=%t.ignorelist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=IGNORELIST-SRC @@ -23,10 +24,22 @@ const char *literal = "Hello, world!"; } -// ASAN: sectioned_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32 +// GLOBS: @extra_global = global {{.*}} sanitize_address +// GLOBS: @global = global {{.*}} sanitize_address +// GLOBS: @dyn_init_global = global {{.*}} sanitize_address, sanitize_address_dyninit +// GLOBS: @attributed_global = global {{.*}} no_sanitize_address +// GLOBS: @disable_instrumentation_global = global {{.*}} no_sanitize +// GLOBS: @ignorelisted_global = global {{.*}} no_sanitize + +// ASAN: sectioned_global{{.*}} global { i32, [28 x i8] }{{.*}}, sanitize_address, align 32 // KASAN: sectioned_global{{.*}} global i32 -// ASAN: @__special_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32 +// KASAN-NOT: sanitize_address +// ASAN: @__special_global{{.*}} global { i32, [28 x i8] }{{.*}}, sanitize_address, align 32 // KASAN: @__special_global{{.*}} global i32 +// KASAN-NOT: sanitize_address + +// GLOBS: @{{[^ ]*}}static_var{{[^ ]*}} = internal global {{.*}} sanitize_address +// GLOBS: @.str = internal constant {{.*}}"Hello, world!{{.*}} sanitize_address /// Without -fasynchronous-unwind-tables, ctor and dtor get the uwtable attribute. // CHECK-LABEL: define internal void @asan.module_ctor() #[[#ATTR:]] { @@ -51,34 +64,14 @@ // UWTABLE: attributes #[[#ATTR]] = { nounwind uwtable } // UWTABLE: ![[#]] = !{i32 7, !"uwtable", i32 2} -// CHECK: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[DISABLE_INSTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[SECTIONED_GLOBAL:[0-9]+]], ![[SPECIAL_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} -// CHECK: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} -// CHECK: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} -// CHECK: ![[GLOBAL]] = !{{{.*}} ![[GLOBAL_LOC:[0-9]+]], !"global", i1 false, i1 false} -// CHECK: ![[GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 10, i32 5} -// CHECK: ![[DYN_INIT_GLOBAL]] = !{{{.*}} ![[DYN_INIT_LOC:[0-9]+]], !"dyn_init_global", i1 true, i1 false} -// CHECK: ![[DYN_INIT_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 11, i32 5} -// CHECK: ![[ATTR_GLOBAL]] = !{{{.*attributed_global.*}}, null, null, i1 false, i1 true} -// CHECK: ![[DISABLE_INSTR_GLOBAL]] = !{{{.*disable_instrumentation_global.*}}, null, null, i1 false, i1 true} -// CHECK: ![[IGNORELISTED_GLOBAL]] = !{{{.*ignorelisted_global.*}}, null, null, i1 false, i1 true} -// CHECK: ![[SECTIONED_GLOBAL]] = !{{{.*}} ![[SECTIONED_GLOBAL_LOC:[0-9]+]], !"sectioned_global", i1 false, i1 false} -// CHECK: ![[SECTIONED_GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 16, i32 50} -// CHECK: ![[SPECIAL_GLOBAL]] = !{{{.*}} ![[SPECIAL_GLOBAL_LOC:[0-9]+]], !"__special_global", i1 false, i1 false} -// CHECK: ![[SPECIAL_GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 18, i32 5} -// CHECK: ![[STATIC_VAR]] = !{{{.*}} ![[STATIC_LOC:[0-9]+]], !"static_var", i1 false, i1 false} -// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 22, i32 14} -// CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"", i1 false, i1 false} -// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 23, i32 25} -// IGNORELIST-SRC: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[DISABLE_INSTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[SECTIONED_GLOBAL:[0-9]+]], ![[SPECIAL_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} -// IGNORELIST-SRC: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} -// IGNORELIST-SRC: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} -// IGNORELIST-SRC: ![[GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true} -// IGNORELIST-SRC: ![[DYN_INIT_GLOBAL]] = !{{{.*}} null, null, i1 true, i1 true} -// IGNORELIST-SRC: ![[ATTR_GLOBAL]] = !{{{.*attributed_global.*}}, null, null, i1 false, i1 true} -// IGNORELIST-SRC: ![[DISABLE_INSTR_GLOBAL]] = !{{{.*disable_instrumentation_global.*}}, null, null, i1 false, i1 true} -// IGNORELIST-SRC: ![[IGNORELISTED_GLOBAL]] = !{{{.*ignorelisted_global.*}}, null, null, i1 false, i1 true} -// IGNORELIST-SRC: ![[SECTIONED_GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true} -// IGNORELIST-SRC: ![[SPECIAL_GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true} -// IGNORELIST-SRC: ![[STATIC_VAR]] = !{{{.*}} null, null, i1 false, i1 true} -// IGNORELIST-SRC: ![[LITERAL]] = !{{{.*}} null, null, i1 false, i1 true} +// IGNORELIST-SRC: @extra_global = global {{.*}} sanitize_address +// IGNORELIST-SRC: @global = global {{.*}} no_sanitize +// IGNORELIST-SRC: @dyn_init_global = global {{.*}} no_sanitize, +// IGNORELIST-SRC: @attributed_global = global {{.*}} no_sanitize +// IGNORELIST-SRC: @disable_instrumentation_global = global {{.*}} no_sanitize +// IGNORELIST-SRC: @ignorelisted_global = global {{.*}} no_sanitize +// IGNORELIST-SRC: @sectioned_global = global {{.*}} no_sanitize +// IGNORELIST-SRC: @__special_global = global {{.*}} no_sanitize +// IGNORELIST-SRC: @{{[^ ]*}}static_var{{[^ ]*}} = internal global {{.*}} no_sanitize +// IGNORELIST-SRC: @.str = {{.*}} constant {{.*}}"Hello, world!{{.*}} no_sanitize diff --git a/clang/test/CodeGen/asan-static-odr.cpp b/clang/test/CodeGen/asan-static-odr.cpp --- a/clang/test/CodeGen/asan-static-odr.cpp +++ b/clang/test/CodeGen/asan-static-odr.cpp @@ -11,7 +11,7 @@ // CHECK-NOT: __odr_asan_gen // CHECK-NOT: private alias -// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, align 32 +// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, sanitize_address, align 32 // CHECK: @0 = internal global {{.*}} [[VAR]] to i64), {{.*}}, i64 -1 }] // CHECK: call void @__asan_register_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1) // CHECK: call void @__asan_unregister_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1) diff --git a/clang/test/CodeGen/asan-strings.c b/clang/test/CodeGen/asan-strings.c --- a/clang/test/CodeGen/asan-strings.c +++ b/clang/test/CodeGen/asan-strings.c @@ -10,8 +10,8 @@ const char *foo(void) { return "asdf"; } -// LINUX: @.str = private unnamed_addr constant [5 x i8] c"asdf\00", align 1 +// LINUX: @.str = private unnamed_addr constant [5 x i8] c"asdf\00", sanitize_address, align 1 -// WINDOWS: @"??_C@_04JIHMPGLA@asdf?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i8] c"asdf\00", comdat, align 1 +// WINDOWS: @"??_C@_04JIHMPGLA@asdf?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i8] c"asdf\00", sanitize_address, comdat, align 1 -// WINWRITE: @.str = private unnamed_addr global [5 x i8] c"asdf\00", align 1 +// WINWRITE: @.str = private unnamed_addr global [5 x i8] c"asdf\00", sanitize_address, align 1 diff --git a/clang/test/CodeGen/sanitize-init-order.cpp b/clang/test/CodeGen/sanitize-init-order.cpp --- a/clang/test/CodeGen/sanitize-init-order.cpp +++ b/clang/test/CodeGen/sanitize-init-order.cpp @@ -36,14 +36,12 @@ // Check that ASan init-order checking ignores structs with trivial default // constructor. -// CHECK: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]+]], ![[GLOB_4:[0-9]+]] -// CHECK: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false} -// CHECK: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} -// CHECK: ![[GLOB_3]] = !{%struct.PODWithCtorAndDtor* {{.*}}, i1 true, i1 false} -// CHECK: ![[GLOB_4]] = !{{{.*}}class.NS::PODWithCtor{{.*}}, i1 true, i1 false} - -// IGNORELIST: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]+]], ![[GLOB_4:[0-9]+]]} -// IGNORELIST: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false} -// IGNORELIST: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} -// IGNORELIST: ![[GLOB_3]] = !{%struct.PODWithCtorAndDtor* {{.*}}, i1 false, i1 false} -// IGNORELIST: ![[GLOB_4]] = !{{{.*}}class.NS::PODWithCtor{{.*}}, i1 false, i1 false} +// CHECK: = global { %struct.PODStruct, {{.*}} sanitize_address +// CHECK: = global { %struct.PODWithDtor, {{.*}} sanitize_address +// CHECK: = global { %struct.PODWithCtorAndDtor, {{.*}} sanitize_address, sanitize_address_dyninit +// CHECK: = global {{.*}} %"class.NS::PODWithCtor"{{.*}} sanitize_address, sanitize_address_dyninit + +// IGNORELIST: = global { %struct.PODStruct, {{.*}} sanitize_address +// IGNORELIST: = global { %struct.PODWithDtor, {{.*}} sanitize_address +// IGNORELIST: = global { %struct.PODWithCtorAndDtor, {{.*}} sanitize_address +// IGNORELIST: = global {{.*}} %"class.NS::PODWithCtor"{{.*}} sanitize_address diff --git a/clang/test/CodeGen/ubsan-strip-path-components.cpp b/clang/test/CodeGen/ubsan-strip-path-components.cpp --- a/clang/test/CodeGen/ubsan-strip-path-components.cpp +++ b/clang/test/CodeGen/ubsan-strip-path-components.cpp @@ -10,14 +10,14 @@ // RUN: %clang_cc1 -no-opaque-pointers %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=-2 | FileCheck %s -check-prefix=LAST-TWO // RUN: %clang_cc1 -no-opaque-pointers %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=-1 | FileCheck %s -check-prefix=LAST-ONLY -// REGULAR: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*test(.|\\\\)CodeGen(.|\\\\)ubsan-strip-path-components\.cpp}}\00", align 1 +// REGULAR: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*test(.|\\\\)CodeGen(.|\\\\)ubsan-strip-path-components\.cpp}}\00", no_sanitize, align 1 // First path component: "/" or "$drive_letter:", then a name, or '\\' on Windows // REMOVE-FIRST-TWO: @[[STR:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"{{(.:|/)([^\\/]*(/|\\\\))}}[[REST:.*ubsan-strip-path-components\.cpp]]\00", align 1 -// REMOVE-FIRST-TWO: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"[[REST]]\00", align 1 +// REMOVE-FIRST-TWO: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"[[REST]]\00", no_sanitize, align 1 -// LAST-TWO: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"CodeGen{{/|\\\\}}ubsan-strip-path-components.cpp\00", align 1 -// LAST-ONLY: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"ubsan-strip-path-components.cpp\00", align 1 +// LAST-TWO: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"CodeGen{{/|\\\\}}ubsan-strip-path-components.cpp\00", no_sanitize, align 1 +// LAST-ONLY: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"ubsan-strip-path-components.cpp\00", no_sanitize, align 1 // CHECK: @[[STATIC_DATA:[0-9.a-zA-Z_]+]] = private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 } } { { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 [[@LINE+6]], i32 3 } } void g(const char *); diff --git a/clang/test/CodeGenCXX/catch-undef-behavior.cpp b/clang/test/CodeGenCXX/catch-undef-behavior.cpp --- a/clang/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/clang/test/CodeGenCXX/catch-undef-behavior.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | opt -instnamer -S | FileCheck %s +// RUN: %clang_cc1 -Wno-return-type -no-opaque-pointers -no-enable-noundef-analysis -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | opt -instnamer -S | FileCheck %s // RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -std=c++11 -fsanitize=vptr,address -fsanitize-recover=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN // RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -std=c++11 -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL // RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple x86_64-linux-gnux32 | FileCheck %s --check-prefix=CHECK-X32 diff --git a/clang/test/CodeGenCXX/type-metadata.cpp b/clang/test/CodeGenCXX/type-metadata.cpp --- a/clang/test/CodeGenCXX/type-metadata.cpp +++ b/clang/test/CodeGenCXX/type-metadata.cpp @@ -36,7 +36,7 @@ // ITANIUM-DIAG-SAME: !type [[ALL32]] // ITANIUM-SAME: !type [[CF32:![0-9]+]] -// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}type-metadata.cpp\00", align 1 +// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}type-metadata.cpp\00", no_sanitize, align 1 // DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" } // DIAG: @[[BADTYPESTATIC:.*]] = private unnamed_addr global { i8, { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }* } { i8 0, { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 123, i32 3 }, { i16, i16, [4 x i8] }* @[[TYPE]] } diff --git a/compiler-rt/lib/asan/asan_globals.cpp b/compiler-rt/lib/asan/asan_globals.cpp --- a/compiler-rt/lib/asan/asan_globals.cpp +++ b/compiler-rt/lib/asan/asan_globals.cpp @@ -86,10 +86,11 @@ "odr_indicator=%p\n", prefix, (void *)&g, (void *)g.beg, g.size, g.size_with_redzone, g.name, g.module_name, g.has_dynamic_init, (void *)g.odr_indicator); - if (g.location) { - Report(" location (%p): name=%s[%p], %d %d\n", (void *)g.location, - g.location->filename, (void *)g.location->filename, - g.location->line_no, g.location->column_no); + + DataInfo info; + Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info); + if (info.line != 0) { + Report(" location (from debuginfo): name=%s, %d\n", info.file, info.line); } } @@ -295,19 +296,15 @@ (char *)g.beg); } -static const char *GlobalFilename(const __asan_global &g) { - const char *res = g.module_name; - // Prefer the filename from source location, if is available. - if (g.location) res = g.location->filename; - CHECK(res); - return res; -} - void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) { - str->append("%s", GlobalFilename(g)); - if (!g.location) return; - if (g.location->line_no) str->append(":%d", g.location->line_no); - if (g.location->column_no) str->append(":%d", g.location->column_no); + DataInfo info; + Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info); + + if (info.line != 0) { + str->append("%s:%d", info.file, info.line); + } else { + str->append("%s", g.module_name); + } } } // namespace __asan diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h --- a/compiler-rt/lib/asan/asan_interface_internal.h +++ b/compiler-rt/lib/asan/asan_interface_internal.h @@ -53,8 +53,9 @@ const char *module_name; // Module name as a C string. This pointer is a // unique identifier of a module. uptr has_dynamic_init; // Non-zero if the global has dynamic initializer. - __asan_global_source_location *location; // Source location of a global, - // or NULL if it is unknown. + uptr windows_padding; // TODO: Figure out how to remove this padding + // that's simply here to make the MSVC incremental + // linker happy... uptr odr_indicator; // The address of the ODR indicator symbol. }; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp @@ -371,6 +371,8 @@ str = ExtractToken(str, "\n", &info->name); str = ExtractUptr(str, " ", &info->start); str = ExtractUptr(str, "\n", &info->size); + str = ExtractToken(str, ":", &info->file); + str = ExtractUptr(str, "\n", &info->line); } static void ParseSymbolizeFrameOutput(const char *str, diff --git a/compiler-rt/test/asan/TestCases/Linux/odr-violation.cpp b/compiler-rt/test/asan/TestCases/Linux/odr-violation.cpp --- a/compiler-rt/test/asan/TestCases/Linux/odr-violation.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/odr-violation.cpp @@ -7,15 +7,15 @@ // pointers. This setting is not on by default because it's too expensive. // // Different size: detect a bug if detect_odr_violation>=1 -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %dynamiclib -// RUN: %clangxx_asan %s %ld_flags_rpath_exe -o %t-ODR-EXE +// RUN: %clangxx_asan -g -DBUILD_SO=1 -fPIC -shared %s -o %dynamiclib +// RUN: %clangxx_asan -g %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=1 not %run %t-ODR-EXE 2>&1 | FileCheck %s // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=0 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s // // Same size: report a bug only if detect_odr_violation>=2. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %dynamiclib -DSZ=100 +// RUN: %clangxx_asan -g -DBUILD_SO=1 -fPIC -shared %s -o %dynamiclib -DSZ=100 // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=1 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s @@ -26,18 +26,18 @@ // RUN: rm -f %t.supp // // Use private aliases for global variables without indicator symbol. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %dynamiclib -DSZ=100 -// RUN: %clangxx_asan -mllvm -asan-use-private-alias %s %ld_flags_rpath_exe -o %t-ODR-EXE +// RUN: %clangxx_asan -g -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %dynamiclib -DSZ=100 +// RUN: %clangxx_asan -g -mllvm -asan-use-private-alias %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED // Use private aliases for global variables: use indicator symbol to detect ODR violation. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s -o %dynamiclib -DSZ=100 -// RUN: %clangxx_asan -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s %ld_flags_rpath_exe -o %t-ODR-EXE +// RUN: %clangxx_asan -g -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s -o %dynamiclib -DSZ=100 +// RUN: %clangxx_asan -g -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s // Same as above but with clang switches. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -fsanitize-address-use-odr-indicator %s -o %dynamiclib -DSZ=100 -// RUN: %clangxx_asan -fsanitize-address-use-odr-indicator %s %ld_flags_rpath_exe -o %t-ODR-EXE +// RUN: %clangxx_asan -g -DBUILD_SO=1 -fPIC -shared -fsanitize-address-use-odr-indicator %s -o %dynamiclib -DSZ=100 +// RUN: %clangxx_asan -g -fsanitize-address-use-odr-indicator %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s // GNU driver doesn't handle .so files properly. @@ -55,7 +55,7 @@ #include namespace foo { char G[100]; } // CHECK: ERROR: AddressSanitizer: odr-violation -// CHECK: size=100 'foo::G' {{.*}}odr-violation.cpp:[[@LINE-2]]:22 +// CHECK: size=100 'foo::G' {{.*}}odr-violation.cpp:[[@LINE-2]] // CHECK: size={{4|100}} 'foo::G' int main(int argc, char **argv) { printf("PASS: %p\n", &foo::G); diff --git a/compiler-rt/test/asan/TestCases/global-location.cpp b/compiler-rt/test/asan/TestCases/global-location.cpp --- a/compiler-rt/test/asan/TestCases/global-location.cpp +++ b/compiler-rt/test/asan/TestCases/global-location.cpp @@ -1,21 +1,30 @@ -// RUN: %clangxx_asan -O2 %s -o %t +// RUN: %clangxx_asan -g -O2 %s -o %t // RUN: not %run %t g 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GLOB // RUN: not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CLASS_STATIC // RUN: not %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FUNC_STATIC // RUN: not %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=LITERAL +// RUN: %clangxx_asan -O2 %s -o %t +// RUN: llvm-strip -s %t +// RUN: not %run %t g 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GLOB-NO-G +// RUN: not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CLASS_STATIC-NO-G +// RUN: not %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FUNC_STATIC-NO-G +// RUN: not %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=LITERAL-NO-G + // CHECK: AddressSanitizer: global-buffer-overflow #include struct C { static int array[10]; + // CLASS_STATIC: 0x{{.*}} is located 4 bytes to the right of global variable 'C::array' defined in '{{.*}}global-location.cpp:[[@LINE-1]]' {{.*}} of size 40 + // CLASS_STATIC-NO-G: 0x{{.*}} is located 4 bytes to the right of global variable 'C::array' defined in '{{.*}}global-location.cpp' {{.*}} of size 40 }; int global[10]; -// GLOB: 0x{{.*}} is located 4 bytes to the right of global variable 'global' defined in '{{.*}}global-location.cpp:[[@LINE-1]]:5' {{.*}} of size 40 +// GLOB: 0x{{.*}} is located 4 bytes to the right of global variable 'global' defined in '{{.*}}global-location.cpp:[[@LINE-1]]' {{.*}} of size 40 +// GLOB-NO-G: 0x{{.*}} is located 4 bytes to the right of global variable 'global' defined in '{{.*}}global-location.cpp' {{.*}} of size 40 int C::array[10]; -// CLASS_STATIC: 0x{{.*}} is located 4 bytes to the right of global variable 'C::array' defined in '{{.*}}global-location.cpp:[[@LINE-1]]:8' {{.*}} of size 40 int main(int argc, char **argv) { int one = argc - 1; @@ -24,12 +33,14 @@ case 'c': return C::array[one * 11]; case 'f': static int array[10]; - // FUNC_STATIC: 0x{{.*}} is located 4 bytes to the right of global variable 'array' defined in '{{.*}}global-location.cpp:[[@LINE-1]]:16' {{.*}} of size 40 + // FUNC_STATIC: 0x{{.*}} is located 4 bytes to the right of global variable 'main::array' defined in '{{.*}}global-location.cpp:[[@LINE-1]]' {{.*}} of size 40 + // FUNC_STATIC-NO-G: 0x{{.*}} is located 4 bytes to the right of global variable 'main::array' defined in '{{.*}}global-location.cpp' {{.*}} of size 40 memset(array, 0, 10); return array[one * 11]; case 'l': const char *str = "0123456789"; - // LITERAL: 0x{{.*}} is located 0 bytes to the right of global variable {{.*}} defined in '{{.*}}global-location.cpp:[[@LINE-1]]:23' {{.*}} of size 11 + // LITERAL: 0x{{.*}} is located 0 bytes to the right of global variable {{.*}} defined in '{{.*}}global-location.cpp:[[@LINE-1]]' {{.*}} of size 11 + // LITERAL-NO-G: 0x{{.*}} is located 0 bytes to the right of global variable {{.*}} defined in '{{.*}}global-location.cpp' {{.*}} of size 11 return str[one * 11]; } return 0; diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -514,6 +514,7 @@ bool parseGlobalValueVector(SmallVectorImpl &Elts, Optional *InRangeOp = nullptr); bool parseOptionalComdat(StringRef GlobalName, Comdat *&C); + bool parseSanitizer(GlobalVariable *GV); bool parseMetadataAsValue(Value *&V, PerFunctionState &PFS); bool parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, PerFunctionState *PFS); diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -182,6 +182,7 @@ kw_alwaysinline, kw_argmemonly, kw_sanitize_address, + kw_sanitize_address_dyninit, kw_sanitize_hwaddress, kw_sanitize_memtag, kw_builtin, @@ -201,6 +202,10 @@ kw_minsize, kw_naked, kw_nest, + kw_no_sanitize, + kw_no_sanitize_address, + kw_no_sanitize_hwaddress, + kw_no_sanitize_memtag, kw_noalias, kw_noundef, kw_nobuiltin, diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h --- a/llvm/include/llvm/IR/GlobalValue.h +++ b/llvm/include/llvm/IR/GlobalValue.h @@ -79,14 +79,15 @@ ValueType(Ty), Visibility(DefaultVisibility), UnnamedAddrVal(unsigned(UnnamedAddr::None)), DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), - HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false) { + HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false), + HasSanitizerMetadata(false) { setLinkage(Linkage); setName(Name); } Type *ValueType; - static const unsigned GlobalValueSubClassDataBits = 16; + static const unsigned GlobalValueSubClassDataBits = 15; // All bitfields use unsigned as the underlying type so that MSVC will pack // them. @@ -111,9 +112,14 @@ /// https://lld.llvm.org/Partitions.html). unsigned HasPartition : 1; + /// True if this symbol has sanitizer metadata available. Should only happen + /// if sanitizers were enabled when building the translation unit which + /// contains this GV. + unsigned HasSanitizerMetadata : 1; + private: // Give subclasses access to what otherwise would be wasted padding. - // (16 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1) == 32. + // (15 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1 + 1) == 32. unsigned SubClassData : GlobalValueSubClassDataBits; friend class Constant; @@ -288,6 +294,47 @@ StringRef getPartition() const; void setPartition(StringRef Part); + struct SanitizerMetadata { + enum GlobalSanitizer : unsigned { + NoSanitize = 1 << 0, + Address = 1 << 1, + HWAddress = 1 << 2, + Memtag = 1 << 3, + NoAddress = 1 << 4, + NoHWAddress = 1 << 5, + NoMemtag = 1 << 6, + }; + // Bitset of sanitizer options. + std::underlying_type::type Sanitizer = 0; + + void AddSanitizer(GlobalSanitizer S) { Sanitizer |= S; } + void RemoveSanitizer(GlobalSanitizer S) { Sanitizer &= ~S; } + bool HasSanitizer(GlobalSanitizer S) const { + if (Sanitizer == GlobalSanitizer::NoSanitize) + return S == GlobalSanitizer::NoSanitize; + switch (S) { + case GlobalSanitizer::Address: + return (Sanitizer & S) && !(Sanitizer & GlobalSanitizer::NoAddress); + case GlobalSanitizer::HWAddress: + return (Sanitizer & S) && !(Sanitizer & GlobalSanitizer::NoHWAddress); + case GlobalSanitizer::Memtag: + return (Sanitizer & S) && !(Sanitizer & GlobalSanitizer::NoMemtag); + case GlobalSanitizer::NoSanitize: // clang doesn't see the handling above. + case GlobalSanitizer::NoAddress: + case GlobalSanitizer::NoHWAddress: + case GlobalSanitizer::NoMemtag: + return Sanitizer & S; + } + } + + // Metadata specific to ASan. + bool IsDynInit = false; + }; + + bool hasSanitizerMetadata() const { return HasSanitizerMetadata; } + const SanitizerMetadata &getSanitizerMetadata() const; + void setSanitizerMetadata(const SanitizerMetadata &Meta); + static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; } diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h --- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h +++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h @@ -25,75 +25,6 @@ class ModulePass; class raw_ostream; -/// Frontend-provided metadata for source location. -struct LocationMetadata { - StringRef Filename; - int LineNo = 0; - int ColumnNo = 0; - - LocationMetadata() = default; - - bool empty() const { return Filename.empty(); } - void parse(MDNode *MDN); -}; - -/// Frontend-provided metadata for global variables. -class GlobalsMetadata { -public: - struct Entry { - LocationMetadata SourceLoc; - StringRef Name; - bool IsDynInit = false; - bool IsExcluded = false; - - Entry() = default; - }; - - /// Create a default uninitialized GlobalsMetadata instance. - GlobalsMetadata() = default; - - /// Create an initialized GlobalsMetadata instance. - GlobalsMetadata(Module &M); - - /// Returns metadata entry for a given global. - Entry get(GlobalVariable *G) const { - auto Pos = Entries.find(G); - return (Pos != Entries.end()) ? Pos->second : Entry(); - } - - /// Handle invalidation from the pass manager. - /// These results are never invalidated. - bool invalidate(Module &, const PreservedAnalyses &, - ModuleAnalysisManager::Invalidator &) { - return false; - } - bool invalidate(Function &, const PreservedAnalyses &, - FunctionAnalysisManager::Invalidator &) { - return false; - } - -private: - DenseMap Entries; -}; - -/// The ASanGlobalsMetadataAnalysis initializes and returns a GlobalsMetadata -/// object. More specifically, ASan requires looking at all globals registered -/// in 'llvm.asan.globals' before running, which only depends on reading module -/// level metadata. This analysis is required to run before running the -/// AddressSanitizerPass since it collects that metadata. -/// The legacy pass manager equivalent of this is ASanGlobalsMetadataLegacyPass. -class ASanGlobalsMetadataAnalysis - : public AnalysisInfoMixin { -public: - using Result = GlobalsMetadata; - - Result run(Module &, ModuleAnalysisManager &); - -private: - friend AnalysisInfoMixin; - static AnalysisKey Key; -}; - struct AddressSanitizerOptions { bool CompileKernel = false; bool Recover = false; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -654,6 +654,10 @@ KEYWORD(minsize); KEYWORD(naked); KEYWORD(nest); + KEYWORD(no_sanitize); + KEYWORD(no_sanitize_address); + KEYWORD(no_sanitize_hwaddress); + KEYWORD(no_sanitize_memtag); KEYWORD(noalias); KEYWORD(nobuiltin); KEYWORD(nocallback); @@ -694,6 +698,7 @@ KEYWORD(safestack); KEYWORD(shadowcallstack); KEYWORD(sanitize_address); + KEYWORD(sanitize_address_dyninit); KEYWORD(sanitize_hwaddress); KEYWORD(sanitize_memtag); KEYWORD(sanitize_thread); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -52,6 +52,9 @@ using namespace llvm; +using SanitizerMetadata = GlobalValue::SanitizerMetadata; +using GlobalSanitizer = SanitizerMetadata::GlobalSanitizer; + static std::string getTypeString(Type *T) { std::string Result; raw_string_ostream Tmp(Result); @@ -1101,6 +1104,65 @@ return false; } +static bool isSanitizer(lltok::Kind Kind) { + switch (Kind) { + case lltok::kw_no_sanitize: + case lltok::kw_sanitize_address: + case lltok::kw_no_sanitize_address: + case lltok::kw_sanitize_hwaddress: + case lltok::kw_no_sanitize_hwaddress: + case lltok::kw_sanitize_memtag: + case lltok::kw_no_sanitize_memtag: + case lltok::kw_sanitize_address_dyninit: + return true; + default: + return false; + } +} + +bool LLParser::parseSanitizer(GlobalVariable *GV) { + SanitizerMetadata Meta; + if (GV->hasSanitizerMetadata()) + Meta = GV->getSanitizerMetadata(); + + switch (Lex.getKind()) { + case lltok::kw_no_sanitize: + Meta.AddSanitizer(GlobalSanitizer::NoSanitize); + break; + case lltok::kw_sanitize_address: + Meta.AddSanitizer(GlobalSanitizer::Address); + break; + case lltok::kw_no_sanitize_address: + Meta.AddSanitizer(GlobalSanitizer::NoAddress); + break; + case lltok::kw_sanitize_hwaddress: + Meta.AddSanitizer(GlobalSanitizer::HWAddress); + break; + case lltok::kw_no_sanitize_hwaddress: + Meta.AddSanitizer(GlobalSanitizer::NoHWAddress); + break; + case lltok::kw_sanitize_memtag: + Meta.AddSanitizer(GlobalSanitizer::Memtag); + break; + case lltok::kw_no_sanitize_memtag: + Meta.AddSanitizer(GlobalSanitizer::NoMemtag); + break; + case lltok::kw_sanitize_address_dyninit: + if (!GV->hasSanitizerMetadata() || + !GV->getSanitizerMetadata().HasSanitizer(SanitizerMetadata::Address)) { + return tokError( + "sanitize_address_dyninit must only occur after sanitize_address"); + } + Meta.IsDynInit = true; + break; + default: + return false; + } + GV->setSanitizerMetadata(Meta); + Lex.Lex(); + return false; +} + /// parseGlobal /// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier /// OptionalVisibility OptionalDLLStorageClass @@ -1219,6 +1281,9 @@ } else if (Lex.getKind() == lltok::MetadataVar) { if (parseGlobalObjectMetadataAttachment(*GV)) return true; + } else if (isSanitizer(Lex.getKind())) { + if (parseSanitizer(GV)) + return true; } else { Comdat *C; if (parseOptionalComdat(Name, C)) diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -3536,6 +3536,15 @@ if (Record.size() > 15) NewGV->setPartition(StringRef(Strtab.data() + Record[14], Record[15])); + if (Record.size() > 17 && Record[16] != UINT_MAX && Record[17] != UINT_MAX) { + llvm::GlobalValue::SanitizerMetadata Meta; + Meta.Sanitizer = + static_cast( + Record[16]); + Meta.IsDynInit = static_cast(Record[17]); + NewGV->setSanitizerMetadata(Meta); + } + return Error::success(); } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1341,7 +1341,8 @@ // GLOBALVAR: [strtab offset, strtab size, type, isconst, initid, // linkage, alignment, section, visibility, threadlocal, // unnamed_addr, externally_initialized, dllstorageclass, - // comdat, attributes, DSO_Local] + // comdat, attributes, DSO_Local, GlobalSanitizer::Sanitizer, + // GlobalSanitizer::IsDynInit] Vals.push_back(addToStrtab(GV.getName())); Vals.push_back(GV.getName().size()); Vals.push_back(VE.getTypeID(GV.getValueType())); @@ -1357,10 +1358,8 @@ GV.getUnnamedAddr() != GlobalValue::UnnamedAddr::None || GV.isExternallyInitialized() || GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass || - GV.hasComdat() || - GV.hasAttributes() || - GV.isDSOLocal() || - GV.hasPartition()) { + GV.hasComdat() || GV.hasAttributes() || GV.isDSOLocal() || + GV.hasPartition() || GV.hasSanitizerMetadata()) { Vals.push_back(getEncodedVisibility(GV)); Vals.push_back(getEncodedThreadLocalMode(GV)); Vals.push_back(getEncodedUnnamedAddr(GV)); @@ -1374,6 +1373,15 @@ Vals.push_back(GV.isDSOLocal()); Vals.push_back(addToStrtab(GV.getPartition())); Vals.push_back(GV.getPartition().size()); + + if (!GV.hasSanitizerMetadata()) { + Vals.push_back(UINT_MAX); + Vals.push_back(UINT_MAX); + } else { + const auto &MD = GV.getSanitizerMetadata(); + Vals.push_back(static_cast(MD.Sanitizer)); + Vals.push_back(MD.IsDynInit); + } } else { AbbrevToUse = SimpleGVarAbbrev; } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -100,6 +100,9 @@ using UseListOrderMap = DenseMap>>; +using SanitizerMetadata = llvm::GlobalValue::SanitizerMetadata; +using GlobalSanitizer = SanitizerMetadata::GlobalSanitizer; + /// Look for a value that might be wrapped as metadata, e.g. a value in a /// metadata operand. Returns the input value as-is if it is not wrapped. static const Value *skipMetadataWrapper(const Value *V) { @@ -3537,6 +3540,28 @@ Out << '"'; } + if (GV->hasSanitizerMetadata()) { + SanitizerMetadata MD = GV->getSanitizerMetadata(); + if (MD.HasSanitizer(SanitizerMetadata::NoSanitize)) { + Out << ", no_sanitize"; + } else { + if (MD.HasSanitizer(SanitizerMetadata::Address)) + Out << ", sanitize_address"; + if (MD.HasSanitizer(SanitizerMetadata::HWAddress)) + Out << ", sanitize_hwaddress"; + if (MD.HasSanitizer(SanitizerMetadata::Memtag)) + Out << ", sanitize_address"; + if (MD.HasSanitizer(SanitizerMetadata::NoAddress)) + Out << ", no_sanitize_address"; + if (MD.HasSanitizer(SanitizerMetadata::NoHWAddress)) + Out << ", no_sanitize_hwaddress"; + if (MD.HasSanitizer(SanitizerMetadata::NoMemtag)) + Out << ", no_sanitize_memtag"; + if (MD.HasSanitizer(GlobalSanitizer::Address) && MD.IsDynInit) + Out << ", sanitize_address_dyninit"; + } + } + maybePrintComdat(Out, *GV); if (MaybeAlign A = GV->getAlign()) Out << ", align " << A->value(); diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -67,6 +67,8 @@ setDLLStorageClass(Src->getDLLStorageClass()); setDSOLocal(Src->isDSOLocal()); setPartition(Src->getPartition()); + if (Src->hasSanitizerMetadata()) + setSanitizerMetadata(Src->getSanitizerMetadata()); } void GlobalValue::removeFromParent() { @@ -217,6 +219,18 @@ HasPartition = !S.empty(); } +using SanitizerMetadata = GlobalValue::SanitizerMetadata; +using GlobalSanitizer = GlobalValue::SanitizerMetadata::GlobalSanitizer; +const SanitizerMetadata &GlobalValue::getSanitizerMetadata() const { + assert(hasSanitizerMetadata()); + return getContext().pImpl->GlobalValueSanitizerMetadata[this]; +} + +void GlobalValue::setSanitizerMetadata(const SanitizerMetadata &Meta) { + getContext().pImpl->GlobalValueSanitizerMetadata[this] = Meta; + HasSanitizerMetadata = true; +} + StringRef GlobalObject::getSectionImpl() const { assert(hasSection()); return getContext().pImpl->GlobalObjectSections[this]; diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1503,6 +1503,9 @@ /// Collection of per-GlobalValue partitions used in this context. DenseMap GlobalValuePartitions; + DenseMap + GlobalValueSanitizerMetadata; + /// DiscriminatorTable - This table maps file:line locations to an /// integer representing the next DWARF path discriminator to assign to /// instructions in different blocks at the same location. diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -26,7 +26,6 @@ MODULE_ANALYSIS("stack-safety", StackSafetyGlobalAnalysis()) MODULE_ANALYSIS("verify", VerifierAnalysis()) MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) -MODULE_ANALYSIS("asan-globals-md", ASanGlobalsMetadataAnalysis()) MODULE_ANALYSIS("inline-advisor", InlineAdvisorAnalysis()) MODULE_ANALYSIS("ir-similarity", IRSimilarityAnalysis()) diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -31,6 +31,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -89,6 +90,7 @@ #include using namespace llvm; +using GlobalSanitizer = GlobalValue::SanitizerMetadata::GlobalSanitizer; #define DEBUG_TYPE "asan" @@ -625,8 +627,7 @@ /// AddressSanitizer: instrument the code in module to find memory bugs. struct AddressSanitizer { - AddressSanitizer(Module &M, const GlobalsMetadata *GlobalsMD, - const StackSafetyGlobalInfo *SSGI, + AddressSanitizer(Module &M, const StackSafetyGlobalInfo *SSGI, bool CompileKernel = false, bool Recover = false, bool UseAfterScope = false, AsanDetectStackUseAfterReturnMode UseAfterReturn = @@ -637,7 +638,7 @@ UseAfterScope(UseAfterScope || ClUseAfterScope), UseAfterReturn(ClUseAfterReturn.getNumOccurrences() ? ClUseAfterReturn : UseAfterReturn), - GlobalsMD(*GlobalsMD), SSGI(SSGI) { + SSGI(SSGI) { C = &(M.getContext()); LongSize = M.getDataLayout().getPointerSizeInBits(); IntptrTy = Type::getIntNTy(*C, LongSize); @@ -750,7 +751,6 @@ FunctionCallee AsanMemmove, AsanMemcpy, AsanMemset; Value *LocalDynamicShadow = nullptr; - const GlobalsMetadata &GlobalsMD; const StackSafetyGlobalInfo *SSGI; DenseMap ProcessedAllocas; @@ -760,12 +760,11 @@ class ModuleAddressSanitizer { public: - ModuleAddressSanitizer(Module &M, const GlobalsMetadata *GlobalsMD, - bool CompileKernel = false, bool Recover = false, - bool UseGlobalsGC = true, bool UseOdrIndicator = false, + ModuleAddressSanitizer(Module &M, bool CompileKernel = false, + bool Recover = false, bool UseGlobalsGC = true, + bool UseOdrIndicator = false, AsanDtorKind DestructorKind = AsanDtorKind::Global) - : GlobalsMD(*GlobalsMD), - CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan + : CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan : CompileKernel), Recover(ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover), UseGlobalsGC(UseGlobalsGC && ClUseGlobalsGC && !this->CompileKernel), @@ -831,7 +830,6 @@ uint64_t getRedzoneSizeForGlobal(uint64_t SizeInBytes) const; int GetAsanVersion(const Module &M) const; - const GlobalsMetadata &GlobalsMD; bool CompileKernel; bool Recover; bool UseGlobalsGC; @@ -1108,55 +1106,6 @@ } // end anonymous namespace -void LocationMetadata::parse(MDNode *MDN) { - assert(MDN->getNumOperands() == 3); - MDString *DIFilename = cast(MDN->getOperand(0)); - Filename = DIFilename->getString(); - LineNo = mdconst::extract(MDN->getOperand(1))->getLimitedValue(); - ColumnNo = - mdconst::extract(MDN->getOperand(2))->getLimitedValue(); -} - -// FIXME: It would be cleaner to instead attach relevant metadata to the globals -// we want to sanitize instead and reading this metadata on each pass over a -// function instead of reading module level metadata at first. -GlobalsMetadata::GlobalsMetadata(Module &M) { - NamedMDNode *Globals = M.getNamedMetadata("llvm.asan.globals"); - if (!Globals) - return; - for (auto MDN : Globals->operands()) { - // Metadata node contains the global and the fields of "Entry". - assert(MDN->getNumOperands() == 5); - auto *V = mdconst::extract_or_null(MDN->getOperand(0)); - // The optimizer may optimize away a global entirely. - if (!V) - continue; - auto *StrippedV = V->stripPointerCasts(); - auto *GV = dyn_cast(StrippedV); - if (!GV) - continue; - // We can already have an entry for GV if it was merged with another - // global. - Entry &E = Entries[GV]; - if (auto *Loc = cast_or_null(MDN->getOperand(1))) - E.SourceLoc.parse(Loc); - if (auto *Name = cast_or_null(MDN->getOperand(2))) - E.Name = Name->getString(); - ConstantInt *IsDynInit = mdconst::extract(MDN->getOperand(3)); - E.IsDynInit |= IsDynInit->isOne(); - ConstantInt *IsExcluded = - mdconst::extract(MDN->getOperand(4)); - E.IsExcluded |= IsExcluded->isOne(); - } -} - -AnalysisKey ASanGlobalsMetadataAnalysis::Key; - -GlobalsMetadata ASanGlobalsMetadataAnalysis::run(Module &M, - ModuleAnalysisManager &AM) { - return GlobalsMetadata(M); -} - void ModuleAddressSanitizerPass::printPipeline( raw_ostream &OS, function_ref MapClassName2PassName) { static_cast *>(this)->printPipeline( @@ -1175,8 +1124,7 @@ PreservedAnalyses ModuleAddressSanitizerPass::run(Module &M, ModuleAnalysisManager &MAM) { - GlobalsMetadata &GlobalsMD = MAM.getResult(M); - ModuleAddressSanitizer ModuleSanitizer(M, &GlobalsMD, Options.CompileKernel, + ModuleAddressSanitizer ModuleSanitizer(M, Options.CompileKernel, Options.Recover, UseGlobalGC, UseOdrIndicator, DestructorKind); bool Modified = false; @@ -1184,9 +1132,9 @@ const StackSafetyGlobalInfo *const SSGI = ClUseStackSafety ? &MAM.getResult(M) : nullptr; for (Function &F : M) { - AddressSanitizer FunctionSanitizer( - M, &GlobalsMD, SSGI, Options.CompileKernel, Options.Recover, - Options.UseAfterScope, Options.UseAfterReturn); + AddressSanitizer FunctionSanitizer(M, SSGI, Options.CompileKernel, + Options.Recover, Options.UseAfterScope, + Options.UseAfterReturn); const TargetLibraryInfo &TLI = FAM.getResult(F); Modified |= FunctionSanitizer.instrumentFunction(F, &TLI); } @@ -1200,22 +1148,6 @@ return Res; } -/// Create a global describing a source location. -static GlobalVariable *createPrivateGlobalForSourceLoc(Module &M, - LocationMetadata MD) { - Constant *LocData[] = { - createPrivateGlobalForString(M, MD.Filename, true, kAsanGenPrefix), - ConstantInt::get(Type::getInt32Ty(M.getContext()), MD.LineNo), - ConstantInt::get(Type::getInt32Ty(M.getContext()), MD.ColumnNo), - }; - auto LocStruct = ConstantStruct::getAnon(LocData); - auto GV = new GlobalVariable(M, LocStruct->getType(), true, - GlobalValue::PrivateLinkage, LocStruct, - kAsanGenPrefix); - GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - return GV; -} - /// Check if \p G has been created by a trusted compiler pass. static bool GlobalWasGeneratedByCompiler(GlobalVariable *G) { // Do not instrument @llvm.global_ctors, @llvm.used, etc. @@ -1427,10 +1359,10 @@ // If a global variable does not have dynamic initialization we don't // have to instrument it. However, if a global does not have initializer // at all, we assume it has dynamic initializer (in other TU). - // - // FIXME: Metadata should be attched directly to the global directly instead - // of being added to llvm.asan.globals. - return G->hasInitializer() && !GlobalsMD.get(G).IsDynInit; + if (G->hasSanitizerMetadata() && G->getSanitizerMetadata().IsDynInit) + return false; + + return G->hasInitializer(); } void AddressSanitizer::instrumentPointerComparisonOrSubtraction( @@ -1791,9 +1723,9 @@ Type *Ty = G->getValueType(); LLVM_DEBUG(dbgs() << "GLOBAL: " << *G << "\n"); - // FIXME: Metadata should be attched directly to the global directly instead - // of being added to llvm.asan.globals. - if (GlobalsMD.get(G).IsExcluded) return false; + if (G->hasSanitizerMetadata() && + G->getSanitizerMetadata().Sanitizer != GlobalSanitizer::Address) + return false; if (!Ty->isSized()) return false; if (!G->hasInitializer()) return false; // Globals in address space 1 and 4 are supported for AMDGPU. @@ -2105,8 +2037,8 @@ SmallVector MetadataGlobals(ExtendedGlobals.size()); for (size_t i = 0; i < ExtendedGlobals.size(); i++) { GlobalVariable *G = ExtendedGlobals[i]; - GlobalVariable *Metadata = - CreateMetadataGlobal(M, MetadataInitializers[i], G->getName()); + GlobalVariable *Metadata = CreateMetadataGlobal( + M, MetadataInitializers[i], llvm::demangle(std::string(G->getName()))); MDNode *MD = MDNode::get(M.getContext(), ValueAsMetadata::get(G)); Metadata->setMetadata(LLVMContext::MD_associated, MD); MetadataGlobals[i] = Metadata; @@ -2172,8 +2104,8 @@ for (size_t i = 0; i < ExtendedGlobals.size(); i++) { Constant *Initializer = MetadataInitializers[i]; GlobalVariable *G = ExtendedGlobals[i]; - GlobalVariable *Metadata = - CreateMetadataGlobal(M, Initializer, G->getName()); + GlobalVariable *Metadata = CreateMetadataGlobal( + M, Initializer, llvm::demangle(std::string(G->getName()))); // On recent Mach-O platforms, we emit the global metadata in a way that // allows the linker to properly strip dead globals. @@ -2269,8 +2201,18 @@ SmallVector GlobalsToChange; for (auto &G : M.globals()) { - if (!AliasedGlobalExclusions.count(&G) && shouldInstrumentGlobal(&G)) - GlobalsToChange.push_back(&G); + if (AliasedGlobalExclusions.count(&G)) + continue; + + if (!shouldInstrumentGlobal(&G)) { + GlobalValue::SanitizerMetadata Meta; + if (G.hasSanitizerMetadata()) + Meta = G.getSanitizerMetadata(); + Meta.RemoveSanitizer(GlobalSanitizer::Address); + G.setSanitizerMetadata(Meta); + continue; + } + GlobalsToChange.push_back(&G); } size_t n = GlobalsToChange.size(); @@ -2288,7 +2230,7 @@ // const char *name; // const char *module_name; // size_t has_dynamic_init; - // void *source_location; + // size_t padding_for_windows_msvc_incremental_link; // size_t odr_indicator; // We initialize an array of such structures and pass it to a run-time call. StructType *GlobalStructTy = @@ -2307,15 +2249,19 @@ for (size_t i = 0; i < n; i++) { GlobalVariable *G = GlobalsToChange[i]; - // FIXME: Metadata should be attched directly to the global directly instead - // of being added to llvm.asan.globals. - auto MD = GlobalsMD.get(G); - StringRef NameForGlobal = G->getName(); + GlobalValue::SanitizerMetadata Meta; + if (G->hasSanitizerMetadata()) + Meta = G->getSanitizerMetadata(); + else + // Sanitizers weren't notified when this global was created. + Meta.Sanitizer = GlobalSanitizer::Address; + + std::string NameForGlobal = llvm::demangle(std::string(G->getName())); // Create string holding the global name (use global name from metadata // if it's available, otherwise just write the name of global variable). - GlobalVariable *Name = createPrivateGlobalForString( - M, MD.Name.empty() ? NameForGlobal : MD.Name, - /*AllowMerging*/ true, kAsanGenPrefix); + GlobalVariable *Name = + createPrivateGlobalForString(M, NameForGlobal, + /*AllowMerging*/ true, kAsanGenPrefix); Type *Ty = G->getValueType(); const uint64_t SizeInBytes = DL.getTypeAllocSize(Ty); @@ -2363,14 +2309,6 @@ G->eraseFromParent(); NewGlobals[i] = NewGlobal; - Constant *SourceLoc; - if (!MD.SourceLoc.empty()) { - auto SourceLocGlobal = createPrivateGlobalForSourceLoc(M, MD.SourceLoc); - SourceLoc = ConstantExpr::getPointerCast(SourceLocGlobal, IntptrTy); - } else { - SourceLoc = ConstantInt::get(IntptrTy, 0); - } - Constant *ODRIndicator = ConstantExpr::getNullValue(IRB.getInt8PtrTy()); GlobalValue *InstrumentedGlobal = NewGlobal; @@ -2411,10 +2349,12 @@ ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), ConstantExpr::getPointerCast(Name, IntptrTy), ConstantExpr::getPointerCast(ModuleName, IntptrTy), - ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc, + ConstantInt::get(IntptrTy, Meta.IsDynInit), + ConstantInt::get(IntptrTy, 0), ConstantExpr::getPointerCast(ODRIndicator, IntptrTy)); - if (ClInitializers && MD.IsDynInit) HasDynamicallyInitializedGlobals = true; + if (ClInitializers && Meta.IsDynInit) + HasDynamicallyInitializedGlobals = true; LLVM_DEBUG(dbgs() << "NEW GLOBAL: " << *NewGlobal << "\n"); diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll @@ -21,12 +21,10 @@ ; Check emitted location descriptions: ; CHECK: [[VARNAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [7 x i8] c"global\00", align 1 -; CHECK: [[FILENAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [22 x i8] c"/tmp/asan-globals.cpp\00", align 1 -; CHECK: [[LOCDESCR:@___asan_gen_.[0-9]+]] = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* [[FILENAME]], i32 5, i32 5 } ; NOALIAS: @__asan_global_global = {{.*}}i64 ptrtoint ({ i32, [28 x i8] }* @global to i64){{.*}} section "asan_globals"{{.*}}, !associated ; NOALIAS: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [18 x i8] }* @{{.str|1}} to i64){{.*}} section "asan_globals"{{.*}}, !associated ; ALIAS: @__asan_global_global = {{.*}}i64 ptrtoint ({ i32, [28 x i8] }* @0 to i64){{.*}} section "asan_globals"{{.*}}, !associated -; ALIAS: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [18 x i8] }* @3 to i64){{.*}} section "asan_globals"{{.*}}, !associated +; ALIAS: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [18 x i8] }* @4 to i64){{.*}} section "asan_globals"{{.*}}, !associated ; The metadata has to be inserted to llvm.compiler.used to avoid being stripped ; during LTO. @@ -61,15 +59,8 @@ attributes #0 = { nounwind sanitize_address } attributes #1 = { nounwind sanitize_address "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -!llvm.asan.globals = !{!0, !1, !2, !3, !4} !llvm.ident = !{!5} -!0 = !{i32* @global, !6, !"global", i1 false, i1 false} -!1 = !{i32* @dyn_init_global, !7, !"dyn_init_global", i1 true, i1 false} -!2 = !{i32* @blocked_global, null, null, i1 false, i1 true} -!3 = !{i32* @_ZZ4funcvE10static_var, !8, !"static_var", i1 false, i1 false} -!4 = !{[14 x i8]* @.str, !9, !"", i1 false, i1 false} - !5 = !{!"clang version 3.5.0 (211282)"} !6 = !{!"/tmp/asan-globals.cpp", i32 5, i32 5} diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll @@ -19,12 +19,9 @@ ; Check emitted location descriptions: ; CHECK: [[VARNAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [7 x i8] c"global\00", align 1 -; CHECK: [[FILENAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [22 x i8] c"/tmp/asan-globals.cpp\00", align 1 -; CHECK: [[LOCDESCR:@___asan_gen_.[0-9]+]] = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* [[FILENAME]], i32 5, i32 5 } ; Check that location descriptors and global names were passed into __asan_register_globals: ; CHECK: i64 ptrtoint ([7 x i8]* [[VARNAME]] to i64) -; CHECK: i64 ptrtoint ({ [22 x i8]*, i32, i32 }* [[LOCDESCR]] to i64) ; Check alignment of metadata_array. ; CHECK-S5-SAME: {{align 32$}} @@ -54,15 +51,8 @@ attributes #0 = { nounwind sanitize_address } attributes #1 = { nounwind sanitize_address "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -!llvm.asan.globals = !{!0, !1, !2, !3, !4} !llvm.ident = !{!5} -!0 = !{i32* @global, !6, !"global", i1 false, i1 false} -!1 = !{i32* @dyn_init_global, !7, !"dyn_init_global", i1 true, i1 false} -!2 = !{i32* @blocked_global, null, null, i1 false, i1 true} -!3 = !{i32* @_ZZ4funcvE10static_var, !8, !"static_var", i1 false, i1 false} -!4 = !{[14 x i8]* @.str, !9, !"", i1 false, i1 false} - !5 = !{!"clang version 3.5.0 (211282)"} !6 = !{!"/tmp/asan-globals.cpp", i32 5, i32 5} diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_with_comdat.ll b/llvm/test/Instrumentation/AddressSanitizer/global_with_comdat.ll --- a/llvm/test/Instrumentation/AddressSanitizer/global_with_comdat.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_with_comdat.ll @@ -43,8 +43,6 @@ ; Check emitted location descriptions: ; CHECK: [[VARNAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [7 x i8] c"global\00", align 1 -; CHECK: [[FILENAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [22 x i8] c"/tmp/asan-globals.cpp\00", align 1 -; CHECK: [[LOCDESCR:@___asan_gen_.[0-9]+]] = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* [[FILENAME]], i32 5, i32 5 } ; COMDAT: @__asan_global_global = {{.*}}i64 ptrtoint ({ i32, [28 x i8] }* @global to i64){{.*}} section "asan_globals"{{.*}}, !associated ; COMDAT: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [18 x i8] }* @{{.str|1}} to i64){{.*}} section "asan_globals"{{.*}}, !associated @@ -81,15 +79,8 @@ attributes #0 = { nounwind sanitize_address } attributes #1 = { nounwind sanitize_address "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -!llvm.asan.globals = !{!0, !1, !2, !3, !4} !llvm.ident = !{!5} -!0 = !{i32* @global, !6, !"global", i1 false, i1 false} -!1 = !{i32* @dyn_init_global, !7, !"dyn_init_global", i1 true, i1 false} -!2 = !{i32* @blocked_global, null, null, i1 false, i1 true} -!3 = !{i32* @_ZZ4funcvE10static_var, !8, !"static_var", i1 false, i1 false} -!4 = !{[14 x i8]* @.str, !9, !"", i1 false, i1 false} - !5 = !{!"clang version 3.5.0 (211282)"} !6 = !{!"/tmp/asan-globals.cpp", i32 5, i32 5} diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll @@ -15,9 +15,9 @@ ; Test that we don't instrument global arrays with static initializer ; indexed with constants in-bounds. But instrument all other cases. -@GlobSt = global [10 x i32] zeroinitializer, align 16 ; static initializer -@GlobDy = global [10 x i32] zeroinitializer, align 16 ; dynamic initializer -@GlobEx = external global [10 x i32] , align 16 ; extern initializer +@GlobSt = global [10 x i32] zeroinitializer, align 16, sanitize_address ; static initializer +@GlobDy = global [10 x i32] zeroinitializer, align 16, sanitize_address, sanitize_address_dyninit ; dynamic initializer +@GlobEx = external global [10 x i32] , align 16, sanitize_address ; extern initializer ; GlobSt is declared here, and has static initializer -- ok to optimize. define i32 @AccessGlobSt_0_2() sanitize_address { @@ -69,10 +69,6 @@ ; CHECK: ret i32 } - -!llvm.asan.globals = !{!0} -!0 = !{[10 x i32]* @GlobDy, null, null, i1 true, i1 false} - ; CHECK-LABEL: define internal void @asan.module_ctor ; CHECK-NOT: ret ; CHECK: call void @__asan_register_elf_globals diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll @@ -2,17 +2,10 @@ ; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-scale=5 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" -@xxx = internal global i32 0, align 4 ; With dynamic initializer. -@XXX = global i32 0, align 4 ; With dynamic initializer. -@yyy = internal global i32 0, align 4 ; W/o dynamic initializer. -@YYY = global i32 0, align 4 ; W/o dynamic initializer. -; Clang will emit the following metadata identifying @xxx as dynamically -; initialized. -!0 = !{i32* @xxx, null, null, i1 true, i1 false} -!1 = !{i32* @XXX, null, null, i1 true, i1 false} -!2 = !{i32* @yyy, null, null, i1 false, i1 false} -!3 = !{i32* @YYY, null, null, i1 false, i1 false} -!llvm.asan.globals = !{!0, !1, !2, !3} +@xxx = internal global i32 0, align 4, sanitize_address, sanitize_address_dyninit ; With dynamic initializer. +@XXX = global i32 0, align 4, sanitize_address, sanitize_address_dyninit ; With dynamic initializer. +@yyy = internal global i32 0, align 4, sanitize_address ; W/o dynamic initializer. +@YYY = global i32 0, align 4, sanitize_address ; W/o dynamic initializer. define i32 @initializer() uwtable { entry: diff --git a/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll b/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll --- a/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll @@ -10,13 +10,12 @@ ; CHECK-SAME: linkonce_odr dso_local constant { [5 x i8], [27 x i8] } ; CHECK-SAME: { [5 x i8] c"asdf\00", [27 x i8] zeroinitializer }, comdat, align 32 -; CHECK: @"__asan_global_??_C@_04JIHMPGLA@asdf?$AA@" = +; CHECK: @"__asan_global_??_C@_04JIHMPGLA@asdf?$AA@" = ; CHECK-SAME: private global { i64, i64, i64, i64, i64, i64, i64, i64 } ; CHECK-SAME: { i64 ptrtoint ({ [5 x i8], [27 x i8] }* @"??_C@_04JIHMPGLA@asdf?$AA@" to i64), -; CHECK-SAME: i64 5, i64 32, i64 ptrtoint ([17 x i8]* @___asan_gen_.1 to i64), -; CHECK-SAME: i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, -; CHECK-SAME: i64 ptrtoint ({ [6 x i8]*, i32, i32 }* @___asan_gen_.3 to i64), i64 0 }, -; CHECK-SAME: section ".ASAN$GL", comdat($"??_C@_04JIHMPGLA@asdf?$AA@"), align 64 +; CHECK-SAME: i64 5, i64 32, i64 ptrtoint ([7 x i8]* @___asan_gen_.1 to i64), i64 ptrtoint ([8 +; CHECK-SAME: x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 0 }, section ".ASAN$GL", +; CHECK-SAME: comdat($"??_C@_04JIHMPGLA@asdf?$AA@"), align 64 ; ModuleID = 't.cpp' source_filename = "t.cpp" @@ -35,11 +34,9 @@ attributes #0 = { nounwind sanitize_address uwtable } -!llvm.asan.globals = !{!0} !llvm.module.flags = !{!2, !3} !llvm.ident = !{!4} -!0 = !{[5 x i8]* @"??_C@_04JIHMPGLA@asdf?$AA@", !1, !"", i1 false, i1 false} !1 = !{!"t.cpp", i32 1, i32 31} !2 = !{i32 1, !"wchar_size", i32 2} !3 = !{i32 7, !"PIC Level", i32 2} diff --git a/llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll b/llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll --- a/llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll @@ -2,7 +2,7 @@ ; Make sure asan does not instrument __sancov_gen_ ; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s -; RUN: opt < %s -passes='module(require,sancov-module,asan-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module,asan-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" $Foo = comdat any diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -357,8 +357,6 @@ ArrayRef) { AddressSanitizerOptions Opts; if (Name == "asan-pipeline") { - MPM.addPass( - RequireAnalysisPass()); MPM.addPass(ModuleAddressSanitizerPass(Opts)); return true; }