Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -489,6 +489,12 @@ const DataLayout &DL = GV->getParent()->getDataLayout(); uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); + uint64_t SymbolSize = 0; + if (GV->hasAttribute("global-symbol-size")) { + auto Attr = GV->getAttribute("global-symbol-size"); + if (Attr.isStringAttribute()) + SymbolSize = std::stoi(Attr.getValueAsString()); + } // If the alignment is specified, we *must* obey it. Overaligning a global // with a specified alignment is a prompt way to break globals emitted to @@ -499,18 +505,19 @@ NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, HI.TimerGroupDescription, TimePassesIsEnabled); - HI.Handler->setSymbolSize(GVSym, Size); + HI.Handler->setSymbolSize(GVSym, SymbolSize); } // Handle common symbols if (GVKind.isCommon()) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (SymbolSize == 0) SymbolSize = Size; unsigned Align = 1 << AlignLog; if (!getObjFileLowering().getCommDirectiveSupportsAlignment()) Align = 0; // .comm _foo, 42, 4 - OutStreamer->EmitCommonSymbol(GVSym, Size, Align); + OutStreamer->EmitCommonSymbol(GVSym, SymbolSize, Align); return; } @@ -523,10 +530,11 @@ TheSection->isVirtualSection()) { if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined. + if (SymbolSize == 0) SymbolSize = Size; unsigned Align = 1 << AlignLog; EmitLinkage(GV, GVSym); // .zerofill __DATA, __bss, _foo, 400, 5 - OutStreamer->EmitZerofill(TheSection, GVSym, Size, Align); + OutStreamer->EmitZerofill(TheSection, GVSym, SymbolSize, Align); return; } @@ -536,6 +544,7 @@ getObjFileLowering().getBSSSection() == TheSection) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (SymbolSize == 0) SymbolSize = Size; unsigned Align = 1 << AlignLog; // Use .lcomm only if it supports user-specified alignment. @@ -546,7 +555,7 @@ // Prefer to simply fall back to .local / .comm in this case. if (MAI->getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) { // .lcomm _foo, 42 - OutStreamer->EmitLocalCommonSymbol(GVSym, Size, Align); + OutStreamer->EmitLocalCommonSymbol(GVSym, SymbolSize, Align); return; } @@ -556,7 +565,7 @@ // .local _foo OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Local); // .comm _foo, 42, 4 - OutStreamer->EmitCommonSymbol(GVSym, Size, Align); + OutStreamer->EmitCommonSymbol(GVSym, SymbolSize, Align); return; } @@ -577,7 +586,7 @@ if (GVKind.isThreadBSS()) { TheSection = getObjFileLowering().getTLSBSSSection(); - OutStreamer->EmitTBSSSymbol(TheSection, MangSym, Size, 1 << AlignLog); + OutStreamer->EmitTBSSSymbol(TheSection, MangSym, SymbolSize, 1 << AlignLog); } else if (GVKind.isThreadData()) { OutStreamer->SwitchSection(TheSection); @@ -626,7 +635,7 @@ if (MAI->hasDotTypeDotSizeDirective()) // .size foo, 42 OutStreamer->emitELFSize(EmittedInitSym, - MCConstantExpr::create(Size, OutContext)); + MCConstantExpr::create(SymbolSize, OutContext)); OutStreamer->AddBlankLine(); } Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1697,6 +1697,12 @@ if (G->hasSection()) { StringRef Section = G->getSection(); + // There are many non-default sections in the kernel, many of which contain + // arrays of structures and pointers, which are merged together and + // traversed at runtime. Instrumenting them would break the kernel. + if (CompileKernel) + return false; + // Globals from llvm.metadata aren't emitted, do not instrument them. if (Section == "llvm.metadata") return false; // Do not instrument globals from special LLVM sections. @@ -2178,6 +2184,7 @@ NewGlobal->takeName(G); G->eraseFromParent(); NewGlobals[i] = NewGlobal; + NewGlobal->addAttribute("global-symbol-size", std::to_string(SizeInBytes)); Constant *SourceLoc; if (!MD.SourceLoc.empty()) { @@ -2251,7 +2258,9 @@ (UseGlobalsGC && TargetTriple.isOSBinFormatELF()) ? getUniqueModuleId(&M) : ""; - if (!ELFUniqueModuleId.empty()) { + // Clang emits invalid flags for section directives when trying to instrument + // kernel globals with InstrumentGlobalsELF(). + if (!ELFUniqueModuleId.empty() && !CompileKernel) { InstrumentGlobalsELF(IRB, M, NewGlobals, Initializers, ELFUniqueModuleId); *CtorComdat = true; } else if (UseGlobalsGC && TargetTriple.isOSBinFormatCOFF()) { @@ -2288,20 +2297,22 @@ Mapping = getShadowMapping(TargetTriple, LongSize, CompileKernel); initializeCallbacks(M); - if (CompileKernel) - return false; + // No need to emit __asan_init and __asan_version_mismatch_check_vXX for the + // kernel. + std::string VersionCheckName = + CompileKernel + ? "" + : kAsanVersionCheckNamePrefix + std::to_string(GetAsanVersion(M)); + std::string InitName = CompileKernel ? "" : kAsanInitName; // Create a module constructor. A destructor is created lazily because not all // platforms, and not all modules need it. - std::string VersionCheckName = - kAsanVersionCheckNamePrefix + std::to_string(GetAsanVersion(M)); std::tie(AsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions( - M, kAsanModuleCtorName, kAsanInitName, /*InitArgTypes=*/{}, + M, kAsanModuleCtorName, InitName, /*InitArgTypes=*/{}, /*InitArgs=*/{}, VersionCheckName); bool CtorComdat = true; bool Changed = false; - // TODO(glider): temporarily disabled globals instrumentation for KASan. if (ClGlobals) { IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator()); Changed |= InstrumentGlobals(IRB, M, &CtorComdat); @@ -2311,9 +2322,13 @@ // (1) global instrumentation is not TU-specific // (2) target is ELF. if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) { - AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName)); - appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority, - AsanCtorFunction); + // When building the kernel, don't emit the constructor if there're no + // globals. + if (!CompileKernel || Changed) { + AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName)); + appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority, + AsanCtorFunction); + } if (AsanDtorFunction) { AsanDtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleDtorName)); appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority, Index: lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- lib/Transforms/Utils/ModuleUtils.cpp +++ lib/Transforms/Utils/ModuleUtils.cpp @@ -155,14 +155,17 @@ assert(!InitName.empty() && "Expected init function name"); assert(InitArgs.size() == InitArgTypes.size() && "Sanitizer's init function expects different number of arguments"); - Function *InitFunction = - declareSanitizerInitFunction(M, InitName, InitArgTypes); + Function *InitFunction = nullptr; + Function *Ctor = Function::Create( FunctionType::get(Type::getVoidTy(M.getContext()), false), GlobalValue::InternalLinkage, CtorName, &M); BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor); IRBuilder<> IRB(ReturnInst::Create(M.getContext(), CtorBB)); - IRB.CreateCall(InitFunction, InitArgs); + if (!InitName.empty()) { + InitFunction = declareSanitizerInitFunction(M, InitName, InitArgTypes); + IRB.CreateCall(InitFunction, InitArgs); + } if (!VersionCheckName.empty()) { Function *VersionCheckFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( Index: test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll =================================================================== --- test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll +++ test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll @@ -1,5 +1,6 @@ ; RUN: opt < %s -asan -asan-module -S | FileCheck %s ; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -asan-kernel=1 -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"