[llvm] 2b02df7 - [ASan] Introduce a flag -asan-constructor-kind to control the generation of the Asan module constructor.
usama hameed via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 24 15:37:49 PST 2023
Author: usama hameed
Date: 2023-01-24T15:36:21-08:00
New Revision: 2b02df781928897beb640df24078dc3c4eb2eb14
URL: https://github.com/llvm/llvm-project/commit/2b02df781928897beb640df24078dc3c4eb2eb14
DIFF: https://github.com/llvm/llvm-project/commit/2b02df781928897beb640df24078dc3c4eb2eb14.diff
LOG: [ASan] Introduce a flag -asan-constructor-kind to control the generation of the Asan module constructor.
By default, ASan generates an asan.module_ctor function that initializes asan and
registers the globals in the module. This function is added to the
@llvm.global_ctors array. Previously, there was no way to control the
generation of this function.
This patch adds a way to control the generation of this function. The
flag -asan-constructor-kind has two options:
global: This is the default option and the default behavior of ASan. It generates an
asan.module_ctor function.
none: This skips the generation of the asan.module_ctor function.
rdar://104448572
Differential revision: https://reviews.llvm.org/D142505
Added:
llvm/test/Instrumentation/AddressSanitizer/no-global-ctors.ll
Modified:
llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
index 41ca345885083..ca54387306664 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
@@ -37,7 +37,8 @@ class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
public:
AddressSanitizerPass(const AddressSanitizerOptions &Options,
bool UseGlobalGC = true, bool UseOdrIndicator = true,
- AsanDtorKind DestructorKind = AsanDtorKind::Global);
+ AsanDtorKind DestructorKind = AsanDtorKind::Global,
+ AsanCtorKind ConstructorKind = AsanCtorKind::Global);
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName);
@@ -48,6 +49,7 @@ class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
bool UseGlobalGC;
bool UseOdrIndicator;
AsanDtorKind DestructorKind;
+ AsanCtorKind ConstructorKind;
};
struct ASanAccessInfo {
diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h
index 187aaedb60004..d697b72cde05e 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h
@@ -19,6 +19,12 @@ enum class AsanDtorKind {
Invalid, ///< Not a valid destructor Kind.
};
+/// Types of ASan module constructors supported
+enum class AsanCtorKind {
+ None,
+ Global
+};
+
/// Mode of ASan detect stack use after return
enum class AsanDetectStackUseAfterReturnMode {
Never, ///< Never detect stack use after return.
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index d7bf846dc336a..599eeeabc143c 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -349,6 +349,13 @@ static cl::opt<bool> ClSkipPromotableAllocas(
cl::desc("Do not instrument promotable allocas"), cl::Hidden,
cl::init(true));
+static cl::opt<AsanCtorKind> ClConstructorKind(
+ "asan-constructor-kind",
+ cl::desc("Sets the ASan constructor kind"),
+ cl::values(clEnumValN(AsanCtorKind::None, "none", "No constructors"),
+ clEnumValN(AsanCtorKind::Global, "global",
+ "Use global constructors")),
+ cl::init(AsanCtorKind::Global), cl::Hidden);
// These flags allow to change the shadow mapping.
// The shadow mapping looks like
// Shadow = (Mem >> scale) + offset
@@ -772,7 +779,8 @@ class ModuleAddressSanitizer {
ModuleAddressSanitizer(Module &M, bool CompileKernel = false,
bool Recover = false, bool UseGlobalsGC = true,
bool UseOdrIndicator = true,
- AsanDtorKind DestructorKind = AsanDtorKind::Global)
+ AsanDtorKind DestructorKind = AsanDtorKind::Global,
+ AsanCtorKind ConstructorKind = AsanCtorKind::Global)
: CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan
: CompileKernel),
Recover(ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover),
@@ -792,7 +800,8 @@ class ModuleAddressSanitizer {
// ClWithComdat and ClUseGlobalsGC unless the frontend says it's ok to
// do globals-gc.
UseCtorComdat(UseGlobalsGC && ClWithComdat && !this->CompileKernel),
- DestructorKind(DestructorKind) {
+ DestructorKind(DestructorKind),
+ ConstructorKind(ConstructorKind) {
C = &(M.getContext());
int LongSize = M.getDataLayout().getPointerSizeInBits();
IntptrTy = Type::getIntNTy(*C, LongSize);
@@ -850,6 +859,7 @@ class ModuleAddressSanitizer {
bool UseOdrIndicator;
bool UseCtorComdat;
AsanDtorKind DestructorKind;
+ AsanCtorKind ConstructorKind;
Type *IntptrTy;
LLVMContext *C;
Triple TargetTriple;
@@ -1131,15 +1141,18 @@ void AddressSanitizerPass::printPipeline(
AddressSanitizerPass::AddressSanitizerPass(
const AddressSanitizerOptions &Options, bool UseGlobalGC,
- bool UseOdrIndicator, AsanDtorKind DestructorKind)
+ bool UseOdrIndicator, AsanDtorKind DestructorKind,
+ AsanCtorKind ConstructorKind)
: Options(Options), UseGlobalGC(UseGlobalGC),
- UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind) {}
+ UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
+ ConstructorKind(ClConstructorKind) {}
PreservedAnalyses AddressSanitizerPass::run(Module &M,
ModuleAnalysisManager &MAM) {
ModuleAddressSanitizer ModuleSanitizer(M, Options.CompileKernel,
Options.Recover, UseGlobalGC,
- UseOdrIndicator, DestructorKind);
+ UseOdrIndicator, DestructorKind,
+ ConstructorKind);
bool Modified = false;
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
const StackSafetyGlobalInfo *const SSGI =
@@ -2095,7 +2108,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsELF(
StopELFMetadata->setVisibility(GlobalVariable::HiddenVisibility);
// Create a call to register the globals with the runtime.
- IRB.CreateCall(AsanRegisterElfGlobals,
+ if (ConstructorKind == AsanCtorKind::Global)
+ IRB.CreateCall(AsanRegisterElfGlobals,
{IRB.CreatePointerCast(RegisteredFlag, IntptrTy),
IRB.CreatePointerCast(StartELFMetadata, IntptrTy),
IRB.CreatePointerCast(StopELFMetadata, IntptrTy)});
@@ -2158,7 +2172,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsMachO(
ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName);
RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility);
- IRB.CreateCall(AsanRegisterImageGlobals,
+ if (ConstructorKind == AsanCtorKind::Global)
+ IRB.CreateCall(AsanRegisterImageGlobals,
{IRB.CreatePointerCast(RegisteredFlag, IntptrTy)});
// We also need to unregister globals at the end, e.g., when a shared library
@@ -2187,7 +2202,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
if (Mapping.Scale > 3)
AllGlobals->setAlignment(Align(1ULL << Mapping.Scale));
- IRB.CreateCall(AsanRegisterGlobals,
+ if (ConstructorKind == AsanCtorKind::Global)
+ IRB.CreateCall(AsanRegisterGlobals,
{IRB.CreatePointerCast(AllGlobals, IntptrTy),
ConstantInt::get(IntptrTy, N)});
@@ -2443,24 +2459,32 @@ bool ModuleAddressSanitizer::instrumentModule(Module &M) {
// Create a module constructor. A destructor is created lazily because not all
// platforms, and not all modules need it.
- if (CompileKernel) {
- // The kernel always builds with its own runtime, and therefore does not
- // need the init and version check calls.
- AsanCtorFunction = createSanitizerCtor(M, kAsanModuleCtorName);
- } else {
- std::string AsanVersion = std::to_string(GetAsanVersion(M));
- std::string VersionCheckName =
- ClInsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : "";
- std::tie(AsanCtorFunction, std::ignore) =
- createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName,
- kAsanInitName, /*InitArgTypes=*/{},
- /*InitArgs=*/{}, VersionCheckName);
+ if (ConstructorKind == AsanCtorKind::Global) {
+ if (CompileKernel) {
+ // The kernel always builds with its own runtime, and therefore does not
+ // need the init and version check calls.
+ AsanCtorFunction = createSanitizerCtor(M, kAsanModuleCtorName);
+ } else {
+ std::string AsanVersion = std::to_string(GetAsanVersion(M));
+ std::string VersionCheckName =
+ ClInsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : "";
+ std::tie(AsanCtorFunction, std::ignore) =
+ createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName,
+ kAsanInitName, /*InitArgTypes=*/{},
+ /*InitArgs=*/{}, VersionCheckName);
+ }
}
bool CtorComdat = true;
if (ClGlobals) {
- IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
- InstrumentGlobals(IRB, M, &CtorComdat);
+ assert(AsanCtorFunction || ConstructorKind == AsanCtorKind::None);
+ if (AsanCtorFunction) {
+ IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
+ InstrumentGlobals(IRB, M, &CtorComdat);
+ } else {
+ IRBuilder<> IRB(*C);
+ InstrumentGlobals(IRB, M, &CtorComdat);
+ }
}
const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);
@@ -2469,14 +2493,17 @@ bool ModuleAddressSanitizer::instrumentModule(Module &M) {
// (1) global instrumentation is not TU-specific
// (2) target is ELF.
if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
- AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
- appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
+ if (AsanCtorFunction) {
+ AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
+ appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
+ }
if (AsanDtorFunction) {
AsanDtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleDtorName));
appendToGlobalDtors(M, AsanDtorFunction, Priority, AsanDtorFunction);
}
} else {
- appendToGlobalCtors(M, AsanCtorFunction, Priority);
+ if (AsanCtorFunction)
+ appendToGlobalCtors(M, AsanCtorFunction, Priority);
if (AsanDtorFunction)
appendToGlobalDtors(M, AsanDtorFunction, Priority);
}
diff --git a/llvm/test/Instrumentation/AddressSanitizer/no-global-ctors.ll b/llvm/test/Instrumentation/AddressSanitizer/no-global-ctors.ll
new file mode 100644
index 0000000000000..79ed0b78fd6a4
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/no-global-ctors.ll
@@ -0,0 +1,17 @@
+; Check Default behaviour still emits ctors
+; RUN: opt < %s -passes=asan -S | \
+; RUN: FileCheck -check-prefix=CHECK-DEFAULT %s
+; CHECK-DEFAULT: llvm.global_ctor{{.+}}asan.module_ctor
+; CHECK-DEFAULT: define internal void @asan.module_ctor
+
+; Check with ctor emission disabled
+; RUN: opt < %s -passes=asan \
+; RUN: -asan-constructor-kind=none -S | \
+; RUN: FileCheck %s
+; CHECK-NOT: llvm.global_ctor{{.+}}asan.module_ctor
+; CHECK-NOT: define internal void @asan.module_ctor
+
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx11.0.0"
+
+ at foo = dso_local global i32 0, align 4
More information about the llvm-commits
mailing list