diff options
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp | 400 |
1 files changed, 74 insertions, 326 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 8f94172a6402..7a5a74aa4fff 100644 --- 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" @@ -42,14 +43,12 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" -#include "llvm/IR/InstIterator.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" @@ -63,15 +62,12 @@ #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/Value.h" -#include "llvm/InitializePasses.h" #include "llvm/MC/MCSectionMachO.h" -#include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h" @@ -87,7 +83,6 @@ #include <cstdint> #include <iomanip> #include <limits> -#include <memory> #include <sstream> #include <string> #include <tuple> @@ -116,7 +111,7 @@ static const uint64_t kFreeBSDKasan_ShadowOffset64 = 0xdffff7c000000000; static const uint64_t kNetBSD_ShadowOffset32 = 1ULL << 30; static const uint64_t kNetBSD_ShadowOffset64 = 1ULL << 46; static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff900000000000; -static const uint64_t kPS4CPU_ShadowOffset64 = 1ULL << 40; +static const uint64_t kPS_ShadowOffset64 = 1ULL << 40; static const uint64_t kWindowsShadowOffset32 = 3ULL << 28; static const uint64_t kEmscriptenShadowOffset = 0; @@ -335,6 +330,11 @@ static cl::opt<std::string> ClMemoryAccessCallbackPrefix( cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_")); +static cl::opt<bool> ClKasanMemIntrinCallbackPrefix( + "asan-kernel-mem-intrinsic-prefix", + cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, + cl::init(false)); + static cl::opt<bool> ClInstrumentDynamicAllocas("asan-instrument-dynamic-allocas", cl::desc("instrument dynamic allocas"), @@ -465,11 +465,12 @@ struct ShadowMapping { static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize, bool IsKasan) { bool IsAndroid = TargetTriple.isAndroid(); - bool IsIOS = TargetTriple.isiOS() || TargetTriple.isWatchOS(); + bool IsIOS = TargetTriple.isiOS() || TargetTriple.isWatchOS() || + TargetTriple.isDriverKit(); bool IsMacOS = TargetTriple.isMacOSX(); bool IsFreeBSD = TargetTriple.isOSFreeBSD(); bool IsNetBSD = TargetTriple.isOSNetBSD(); - bool IsPS4CPU = TargetTriple.isPS4CPU(); + bool IsPS = TargetTriple.isPS(); bool IsLinux = TargetTriple.isOSLinux(); bool IsPPC64 = TargetTriple.getArch() == Triple::ppc64 || TargetTriple.getArch() == Triple::ppc64le; @@ -528,8 +529,8 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize, Mapping.Offset = kNetBSDKasan_ShadowOffset64; else Mapping.Offset = kNetBSD_ShadowOffset64; - } else if (IsPS4CPU) - Mapping.Offset = kPS4CPU_ShadowOffset64; + } else if (IsPS) + Mapping.Offset = kPS_ShadowOffset64; else if (IsLinux && IsX86_64) { if (IsKasan) Mapping.Offset = kLinuxKasan_ShadowOffset64; @@ -568,7 +569,7 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize, // offset is not necessary 1/8-th of the address space. On SystemZ, // we could OR the constant in a single instruction, but it's more // efficient to load it once and use indexed addressing. - Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS4CPU && + Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS && !IsRISCV64 && !(Mapping.Offset & (Mapping.Offset - 1)) && Mapping.Offset != kDynamicShadowSentinel; @@ -621,41 +622,9 @@ static uint64_t GetCtorAndDtorPriority(Triple &TargetTriple) { namespace { -/// Module analysis for getting various metadata about the module. -class ASanGlobalsMetadataWrapperPass : public ModulePass { -public: - static char ID; - - ASanGlobalsMetadataWrapperPass() : ModulePass(ID) { - initializeASanGlobalsMetadataWrapperPassPass( - *PassRegistry::getPassRegistry()); - } - - bool runOnModule(Module &M) override { - GlobalsMD = GlobalsMetadata(M); - return false; - } - - StringRef getPassName() const override { - return "ASanGlobalsMetadataWrapperPass"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - GlobalsMetadata &getGlobalsMD() { return GlobalsMD; } - -private: - GlobalsMetadata GlobalsMD; -}; - -char ASanGlobalsMetadataWrapperPass::ID = 0; - /// 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 = @@ -666,7 +635,7 @@ struct AddressSanitizer { 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); @@ -779,7 +748,6 @@ private: FunctionCallee AsanMemmove, AsanMemcpy, AsanMemset; Value *LocalDynamicShadow = nullptr; - const GlobalsMetadata &GlobalsMD; const StackSafetyGlobalInfo *SSGI; DenseMap<const AllocaInst *, bool> ProcessedAllocas; @@ -787,60 +755,13 @@ private: FunctionCallee AMDGPUAddressPrivate; }; -class AddressSanitizerLegacyPass : public FunctionPass { -public: - static char ID; - - explicit AddressSanitizerLegacyPass( - bool CompileKernel = false, bool Recover = false, - bool UseAfterScope = false, - AsanDetectStackUseAfterReturnMode UseAfterReturn = - AsanDetectStackUseAfterReturnMode::Runtime) - : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover), - UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn) { - initializeAddressSanitizerLegacyPassPass(*PassRegistry::getPassRegistry()); - } - - StringRef getPassName() const override { - return "AddressSanitizerFunctionPass"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<ASanGlobalsMetadataWrapperPass>(); - if (ClUseStackSafety) - AU.addRequired<StackSafetyGlobalInfoWrapperPass>(); - AU.addRequired<TargetLibraryInfoWrapperPass>(); - } - - bool runOnFunction(Function &F) override { - GlobalsMetadata &GlobalsMD = - getAnalysis<ASanGlobalsMetadataWrapperPass>().getGlobalsMD(); - const StackSafetyGlobalInfo *const SSGI = - ClUseStackSafety - ? &getAnalysis<StackSafetyGlobalInfoWrapperPass>().getResult() - : nullptr; - const TargetLibraryInfo *TLI = - &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); - AddressSanitizer ASan(*F.getParent(), &GlobalsMD, SSGI, CompileKernel, - Recover, UseAfterScope, UseAfterReturn); - return ASan.instrumentFunction(F, TLI); - } - -private: - bool CompileKernel; - bool Recover; - bool UseAfterScope; - AsanDetectStackUseAfterReturnMode UseAfterReturn; -}; - 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), @@ -906,7 +827,6 @@ private: uint64_t getRedzoneSizeForGlobal(uint64_t SizeInBytes) const; int GetAsanVersion(const Module &M) const; - const GlobalsMetadata &GlobalsMD; bool CompileKernel; bool Recover; bool UseGlobalsGC; @@ -931,44 +851,6 @@ private: Function *AsanDtorFunction = nullptr; }; -class ModuleAddressSanitizerLegacyPass : public ModulePass { -public: - static char ID; - - explicit ModuleAddressSanitizerLegacyPass( - bool CompileKernel = false, bool Recover = false, bool UseGlobalGC = true, - bool UseOdrIndicator = false, - AsanDtorKind DestructorKind = AsanDtorKind::Global) - : ModulePass(ID), CompileKernel(CompileKernel), Recover(Recover), - UseGlobalGC(UseGlobalGC), UseOdrIndicator(UseOdrIndicator), - DestructorKind(DestructorKind) { - initializeModuleAddressSanitizerLegacyPassPass( - *PassRegistry::getPassRegistry()); - } - - StringRef getPassName() const override { return "ModuleAddressSanitizer"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<ASanGlobalsMetadataWrapperPass>(); - } - - bool runOnModule(Module &M) override { - GlobalsMetadata &GlobalsMD = - getAnalysis<ASanGlobalsMetadataWrapperPass>().getGlobalsMD(); - ModuleAddressSanitizer ASanModule(M, &GlobalsMD, CompileKernel, Recover, - UseGlobalGC, UseOdrIndicator, - DestructorKind); - return ASanModule.instrumentModule(M); - } - -private: - bool CompileKernel; - bool Recover; - bool UseGlobalGC; - bool UseOdrIndicator; - AsanDtorKind DestructorKind; -}; - // Stack poisoning does not play well with exception handling. // When an exception is thrown, we essentially bypass the code // that unpoisones the stack. This is why the run-time library has @@ -1221,85 +1103,6 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> { } // end anonymous namespace -void LocationMetadata::parse(MDNode *MDN) { - assert(MDN->getNumOperands() == 3); - MDString *DIFilename = cast<MDString>(MDN->getOperand(0)); - Filename = DIFilename->getString(); - LineNo = mdconst::extract<ConstantInt>(MDN->getOperand(1))->getLimitedValue(); - ColumnNo = - mdconst::extract<ConstantInt>(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<Constant>(MDN->getOperand(0)); - // The optimizer may optimize away a global entirely. - if (!V) - continue; - auto *StrippedV = V->stripPointerCasts(); - auto *GV = dyn_cast<GlobalVariable>(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<MDNode>(MDN->getOperand(1))) - E.SourceLoc.parse(Loc); - if (auto *Name = cast_or_null<MDString>(MDN->getOperand(2))) - E.Name = Name->getString(); - ConstantInt *IsDynInit = mdconst::extract<ConstantInt>(MDN->getOperand(3)); - E.IsDynInit |= IsDynInit->isOne(); - ConstantInt *IsExcluded = - mdconst::extract<ConstantInt>(MDN->getOperand(4)); - E.IsExcluded |= IsExcluded->isOne(); - } -} - -AnalysisKey ASanGlobalsMetadataAnalysis::Key; - -GlobalsMetadata ASanGlobalsMetadataAnalysis::run(Module &M, - ModuleAnalysisManager &AM) { - return GlobalsMetadata(M); -} - -PreservedAnalyses AddressSanitizerPass::run(Function &F, - AnalysisManager<Function> &AM) { - auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); - Module &M = *F.getParent(); - if (auto *R = MAMProxy.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) { - const TargetLibraryInfo *TLI = &AM.getResult<TargetLibraryAnalysis>(F); - AddressSanitizer Sanitizer(M, R, nullptr, Options.CompileKernel, - Options.Recover, Options.UseAfterScope, - Options.UseAfterReturn); - if (Sanitizer.instrumentFunction(F, TLI)) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); - } - - report_fatal_error( - "The ASanGlobalsMetadataAnalysis is required to run before " - "AddressSanitizer can run"); - return PreservedAnalyses::all(); -} - -void AddressSanitizerPass::printPipeline( - raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { - static_cast<PassInfoMixin<AddressSanitizerPass> *>(this)->printPipeline( - OS, MapClassName2PassName); - OS << "<"; - if (Options.CompileKernel) - OS << "kernel"; - OS << ">"; -} - void ModuleAddressSanitizerPass::printPipeline( raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { static_cast<PassInfoMixin<ModuleAddressSanitizerPass> *>(this)->printPipeline( @@ -1318,8 +1121,7 @@ ModuleAddressSanitizerPass::ModuleAddressSanitizerPass( PreservedAnalyses ModuleAddressSanitizerPass::run(Module &M, ModuleAnalysisManager &MAM) { - GlobalsMetadata &GlobalsMD = MAM.getResult<ASanGlobalsMetadataAnalysis>(M); - ModuleAddressSanitizer ModuleSanitizer(M, &GlobalsMD, Options.CompileKernel, + ModuleAddressSanitizer ModuleSanitizer(M, Options.CompileKernel, Options.Recover, UseGlobalGC, UseOdrIndicator, DestructorKind); bool Modified = false; @@ -1327,9 +1129,9 @@ PreservedAnalyses ModuleAddressSanitizerPass::run(Module &M, const StackSafetyGlobalInfo *const SSGI = ClUseStackSafety ? &MAM.getResult<StackSafetyGlobalAnalysis>(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<TargetLibraryAnalysis>(F); Modified |= FunctionSanitizer.instrumentFunction(F, &TLI); } @@ -1337,75 +1139,20 @@ PreservedAnalyses ModuleAddressSanitizerPass::run(Module &M, return Modified ? PreservedAnalyses::none() : PreservedAnalyses::all(); } -INITIALIZE_PASS(ASanGlobalsMetadataWrapperPass, "asan-globals-md", - "Read metadata to mark which globals should be instrumented " - "when running ASan.", - false, true) - -char AddressSanitizerLegacyPass::ID = 0; - -INITIALIZE_PASS_BEGIN( - AddressSanitizerLegacyPass, "asan", - "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, - false) -INITIALIZE_PASS_DEPENDENCY(ASanGlobalsMetadataWrapperPass) -INITIALIZE_PASS_DEPENDENCY(StackSafetyGlobalInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_END( - AddressSanitizerLegacyPass, "asan", - "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, - false) - -FunctionPass *llvm::createAddressSanitizerFunctionPass( - bool CompileKernel, bool Recover, bool UseAfterScope, - AsanDetectStackUseAfterReturnMode UseAfterReturn) { - assert(!CompileKernel || Recover); - return new AddressSanitizerLegacyPass(CompileKernel, Recover, UseAfterScope, - UseAfterReturn); -} - -char ModuleAddressSanitizerLegacyPass::ID = 0; - -INITIALIZE_PASS( - ModuleAddressSanitizerLegacyPass, "asan-module", - "AddressSanitizer: detects use-after-free and out-of-bounds bugs." - "ModulePass", - false, false) - -ModulePass *llvm::createModuleAddressSanitizerLegacyPassPass( - bool CompileKernel, bool Recover, bool UseGlobalsGC, bool UseOdrIndicator, - AsanDtorKind Destructor) { - assert(!CompileKernel || Recover); - return new ModuleAddressSanitizerLegacyPass( - CompileKernel, Recover, UseGlobalsGC, UseOdrIndicator, Destructor); -} - static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { size_t Res = countTrailingZeros(TypeSize / 8); assert(Res < kNumberOfAccessSizes); 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. - if (G->getName().startswith("llvm.")) + if (G->getName().startswith("llvm.") || + // Do not instrument gcov counter arrays. + G->getName().startswith("__llvm_gcov_ctr") || + // Do not instrument rtti proxy symbols for function sanitizer. + G->getName().startswith("__llvm_rtti_proxy")) return true; // Do not instrument asan globals. @@ -1414,10 +1161,6 @@ static bool GlobalWasGeneratedByCompiler(GlobalVariable *G) { G->getName().startswith(kODRGenPrefix)) return true; - // Do not instrument gcov counter arrays. - if (G->getName() == "__llvm_gcov_ctr") - return true; - return false; } @@ -1518,10 +1261,6 @@ bool AddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) { void AddressSanitizer::getInterestingMemoryOperands( Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting) { - // Skip memory accesses inserted by another instrumentation. - if (I->hasMetadata("nosanitize")) - return; - // Do not instrument the load fetching the dynamic shadow address. if (LocalDynamicShadow == I) return; @@ -1613,10 +1352,13 @@ bool AddressSanitizer::GlobalIsLinkerInitialized(GlobalVariable *G) { // 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->hasInitializer()) + return false; + + if (G->hasSanitizerMetadata() && G->getSanitizerMetadata().IsDynInit) + return false; + + return true; } void AddressSanitizer::instrumentPointerComparisonOrSubtraction( @@ -1977,9 +1719,8 @@ bool ModuleAddressSanitizer::shouldInstrumentGlobal(GlobalVariable *G) const { 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().NoAddress) + return false; if (!Ty->isSized()) return false; if (!G->hasInitializer()) return false; // Globals in address space 1 and 4 are supported for AMDGPU. @@ -2125,6 +1866,8 @@ bool ModuleAddressSanitizer::ShouldUseMachOGlobalsSection() const { return true; if (TargetTriple.isWatchOS() && !TargetTriple.isOSVersionLT(2)) return true; + if (TargetTriple.isDriverKit()) + return true; return false; } @@ -2136,7 +1879,9 @@ StringRef ModuleAddressSanitizer::getGlobalMetadataSection() const { case Triple::MachO: return "__DATA,__asan_globals,regular"; case Triple::Wasm: case Triple::GOFF: + case Triple::SPIRV: case Triple::XCOFF: + case Triple::DXContainer: report_fatal_error( "ModuleAddressSanitizer not implemented for object file format"); case Triple::UnknownObjectFormat: @@ -2470,7 +2215,7 @@ bool ModuleAddressSanitizer::InstrumentGlobals(IRBuilder<> &IRB, Module &M, // 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 = @@ -2489,15 +2234,16 @@ bool ModuleAddressSanitizer::InstrumentGlobals(IRBuilder<> &IRB, Module &M, 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(); - // 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); + GlobalValue::SanitizerMetadata MD; + if (G->hasSanitizerMetadata()) + MD = G->getSanitizerMetadata(); + + // TODO: Symbol names in the descriptor can be demangled by the runtime + // library. This could save ~0.4% of VM size for a private large binary. + std::string NameForGlobal = llvm::demangle(G->getName().str()); + GlobalVariable *Name = + createPrivateGlobalForString(M, NameForGlobal, + /*AllowMerging*/ true, kAsanGenPrefix); Type *Ty = G->getValueType(); const uint64_t SizeInBytes = DL.getTypeAllocSize(Ty); @@ -2545,14 +2291,6 @@ bool ModuleAddressSanitizer::InstrumentGlobals(IRBuilder<> &IRB, Module &M, 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; @@ -2593,10 +2331,12 @@ bool ModuleAddressSanitizer::InstrumentGlobals(IRBuilder<> &IRB, Module &M, ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), ConstantExpr::getPointerCast(Name, IntptrTy), ConstantExpr::getPointerCast(ModuleName, IntptrTy), - ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc, + ConstantInt::get(IntptrTy, MD.IsDynInit), + Constant::getNullValue(IntptrTy), ConstantExpr::getPointerCast(ODRIndicator, IntptrTy)); - if (ClInitializers && MD.IsDynInit) HasDynamicallyInitializedGlobals = true; + if (ClInitializers && MD.IsDynInit) + HasDynamicallyInitializedGlobals = true; LLVM_DEBUG(dbgs() << "NEW GLOBAL: " << *NewGlobal << "\n"); @@ -2759,7 +2499,9 @@ void AddressSanitizer::initializeCallbacks(Module &M) { } const std::string MemIntrinCallbackPrefix = - CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix; + (CompileKernel && !ClKasanMemIntrinCallbackPrefix) + ? std::string("") + : ClMemoryAccessCallbackPrefix; AsanMemmove = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy); @@ -2888,6 +2630,9 @@ bool AddressSanitizer::instrumentFunction(Function &F, // Leave if the function doesn't need instrumentation. if (!F.hasFnAttribute(Attribute::SanitizeAddress)) return FunctionModified; + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) + return FunctionModified; + LLVM_DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n"); initializeCallbacks(*F.getParent()); @@ -2908,7 +2653,6 @@ bool AddressSanitizer::instrumentFunction(Function &F, SmallVector<Instruction *, 8> NoReturnCalls; SmallVector<BasicBlock *, 16> AllBlocks; SmallVector<Instruction *, 16> PointerComparisonsOrSubtracts; - int NumAllocas = 0; // Fill the set of memory operations to instrument. for (auto &BB : F) { @@ -2917,6 +2661,9 @@ bool AddressSanitizer::instrumentFunction(Function &F, int NumInsnsPerBB = 0; for (auto &Inst : BB) { if (LooksLikeCodeInBug11395(&Inst)) return false; + // Skip instructions inserted by another instrumentation. + if (Inst.hasMetadata(LLVMContext::MD_nosanitize)) + continue; SmallVector<InterestingMemoryOperand, 1> InterestingOperands; getInterestingMemoryOperands(&Inst, InterestingOperands); @@ -2948,11 +2695,10 @@ bool AddressSanitizer::instrumentFunction(Function &F, IntrinToInstrument.push_back(MI); NumInsnsPerBB++; } else { - if (isa<AllocaInst>(Inst)) NumAllocas++; if (auto *CB = dyn_cast<CallBase>(&Inst)) { // A call inside BB. TempsToInstrument.clear(); - if (CB->doesNotReturn() && !CB->hasMetadata("nosanitize")) + if (CB->doesNotReturn()) NoReturnCalls.push_back(CB); } if (CallInst *CI = dyn_cast<CallInst>(&Inst)) @@ -3347,7 +3093,7 @@ void FunctionStackPoisoner::processStaticAllocas() { ASanStackVariableDescription D = {AI->getName().data(), ASan.getAllocaSizeInBytes(*AI), 0, - AI->getAlignment(), + AI->getAlign().value(), AI, 0, 0}; @@ -3611,7 +3357,7 @@ void FunctionStackPoisoner::poisonAlloca(Value *V, uint64_t Size, void FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) { IRBuilder<> IRB(AI); - const uint64_t Alignment = std::max(kAllocaRzSize, AI->getAlignment()); + const Align Alignment = std::max(Align(kAllocaRzSize), AI->getAlign()); const uint64_t AllocaRedzoneMask = kAllocaRzSize - 1; Value *Zero = Constant::getNullValue(IntptrTy); @@ -3642,17 +3388,19 @@ void FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) { // Alignment is added to locate left redzone, PartialPadding for possible // partial redzone and kAllocaRzSize for right redzone respectively. Value *AdditionalChunkSize = IRB.CreateAdd( - ConstantInt::get(IntptrTy, Alignment + kAllocaRzSize), PartialPadding); + ConstantInt::get(IntptrTy, Alignment.value() + kAllocaRzSize), + PartialPadding); Value *NewSize = IRB.CreateAdd(OldSize, AdditionalChunkSize); // Insert new alloca with new NewSize and Alignment params. AllocaInst *NewAlloca = IRB.CreateAlloca(IRB.getInt8Ty(), NewSize); - NewAlloca->setAlignment(Align(Alignment)); + NewAlloca->setAlignment(Alignment); // NewAddress = Address + Alignment - Value *NewAddress = IRB.CreateAdd(IRB.CreatePtrToInt(NewAlloca, IntptrTy), - ConstantInt::get(IntptrTy, Alignment)); + Value *NewAddress = + IRB.CreateAdd(IRB.CreatePtrToInt(NewAlloca, IntptrTy), + ConstantInt::get(IntptrTy, Alignment.value())); // Insert __asan_alloca_poison call for new created alloca. IRB.CreateCall(AsanAllocaPoisonFunc, {NewAddress, OldSize}); |
