Skip to content

Commit 2b02df7

Browse files
committed
[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
1 parent 5b6dbde commit 2b02df7

File tree

4 files changed

+78
-26
lines changed

4 files changed

+78
-26
lines changed

llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
3737
public:
3838
AddressSanitizerPass(const AddressSanitizerOptions &Options,
3939
bool UseGlobalGC = true, bool UseOdrIndicator = true,
40-
AsanDtorKind DestructorKind = AsanDtorKind::Global);
40+
AsanDtorKind DestructorKind = AsanDtorKind::Global,
41+
AsanCtorKind ConstructorKind = AsanCtorKind::Global);
4142
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
4243
void printPipeline(raw_ostream &OS,
4344
function_ref<StringRef(StringRef)> MapClassName2PassName);
@@ -48,6 +49,7 @@ class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
4849
bool UseGlobalGC;
4950
bool UseOdrIndicator;
5051
AsanDtorKind DestructorKind;
52+
AsanCtorKind ConstructorKind;
5153
};
5254

5355
struct ASanAccessInfo {

llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ enum class AsanDtorKind {
1919
Invalid, ///< Not a valid destructor Kind.
2020
};
2121

22+
/// Types of ASan module constructors supported
23+
enum class AsanCtorKind {
24+
None,
25+
Global
26+
};
27+
2228
/// Mode of ASan detect stack use after return
2329
enum class AsanDetectStackUseAfterReturnMode {
2430
Never, ///< Never detect stack use after return.

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,13 @@ static cl::opt<bool> ClSkipPromotableAllocas(
349349
cl::desc("Do not instrument promotable allocas"), cl::Hidden,
350350
cl::init(true));
351351

352+
static cl::opt<AsanCtorKind> ClConstructorKind(
353+
"asan-constructor-kind",
354+
cl::desc("Sets the ASan constructor kind"),
355+
cl::values(clEnumValN(AsanCtorKind::None, "none", "No constructors"),
356+
clEnumValN(AsanCtorKind::Global, "global",
357+
"Use global constructors")),
358+
cl::init(AsanCtorKind::Global), cl::Hidden);
352359
// These flags allow to change the shadow mapping.
353360
// The shadow mapping looks like
354361
// Shadow = (Mem >> scale) + offset
@@ -772,7 +779,8 @@ class ModuleAddressSanitizer {
772779
ModuleAddressSanitizer(Module &M, bool CompileKernel = false,
773780
bool Recover = false, bool UseGlobalsGC = true,
774781
bool UseOdrIndicator = true,
775-
AsanDtorKind DestructorKind = AsanDtorKind::Global)
782+
AsanDtorKind DestructorKind = AsanDtorKind::Global,
783+
AsanCtorKind ConstructorKind = AsanCtorKind::Global)
776784
: CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan
777785
: CompileKernel),
778786
Recover(ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover),
@@ -792,7 +800,8 @@ class ModuleAddressSanitizer {
792800
// ClWithComdat and ClUseGlobalsGC unless the frontend says it's ok to
793801
// do globals-gc.
794802
UseCtorComdat(UseGlobalsGC && ClWithComdat && !this->CompileKernel),
795-
DestructorKind(DestructorKind) {
803+
DestructorKind(DestructorKind),
804+
ConstructorKind(ConstructorKind) {
796805
C = &(M.getContext());
797806
int LongSize = M.getDataLayout().getPointerSizeInBits();
798807
IntptrTy = Type::getIntNTy(*C, LongSize);
@@ -850,6 +859,7 @@ class ModuleAddressSanitizer {
850859
bool UseOdrIndicator;
851860
bool UseCtorComdat;
852861
AsanDtorKind DestructorKind;
862+
AsanCtorKind ConstructorKind;
853863
Type *IntptrTy;
854864
LLVMContext *C;
855865
Triple TargetTriple;
@@ -1131,15 +1141,18 @@ void AddressSanitizerPass::printPipeline(
11311141

11321142
AddressSanitizerPass::AddressSanitizerPass(
11331143
const AddressSanitizerOptions &Options, bool UseGlobalGC,
1134-
bool UseOdrIndicator, AsanDtorKind DestructorKind)
1144+
bool UseOdrIndicator, AsanDtorKind DestructorKind,
1145+
AsanCtorKind ConstructorKind)
11351146
: Options(Options), UseGlobalGC(UseGlobalGC),
1136-
UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind) {}
1147+
UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
1148+
ConstructorKind(ClConstructorKind) {}
11371149

11381150
PreservedAnalyses AddressSanitizerPass::run(Module &M,
11391151
ModuleAnalysisManager &MAM) {
11401152
ModuleAddressSanitizer ModuleSanitizer(M, Options.CompileKernel,
11411153
Options.Recover, UseGlobalGC,
1142-
UseOdrIndicator, DestructorKind);
1154+
UseOdrIndicator, DestructorKind,
1155+
ConstructorKind);
11431156
bool Modified = false;
11441157
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
11451158
const StackSafetyGlobalInfo *const SSGI =
@@ -2095,7 +2108,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsELF(
20952108
StopELFMetadata->setVisibility(GlobalVariable::HiddenVisibility);
20962109

20972110
// Create a call to register the globals with the runtime.
2098-
IRB.CreateCall(AsanRegisterElfGlobals,
2111+
if (ConstructorKind == AsanCtorKind::Global)
2112+
IRB.CreateCall(AsanRegisterElfGlobals,
20992113
{IRB.CreatePointerCast(RegisteredFlag, IntptrTy),
21002114
IRB.CreatePointerCast(StartELFMetadata, IntptrTy),
21012115
IRB.CreatePointerCast(StopELFMetadata, IntptrTy)});
@@ -2158,7 +2172,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsMachO(
21582172
ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName);
21592173
RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility);
21602174

2161-
IRB.CreateCall(AsanRegisterImageGlobals,
2175+
if (ConstructorKind == AsanCtorKind::Global)
2176+
IRB.CreateCall(AsanRegisterImageGlobals,
21622177
{IRB.CreatePointerCast(RegisteredFlag, IntptrTy)});
21632178

21642179
// We also need to unregister globals at the end, e.g., when a shared library
@@ -2187,7 +2202,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
21872202
if (Mapping.Scale > 3)
21882203
AllGlobals->setAlignment(Align(1ULL << Mapping.Scale));
21892204

2190-
IRB.CreateCall(AsanRegisterGlobals,
2205+
if (ConstructorKind == AsanCtorKind::Global)
2206+
IRB.CreateCall(AsanRegisterGlobals,
21912207
{IRB.CreatePointerCast(AllGlobals, IntptrTy),
21922208
ConstantInt::get(IntptrTy, N)});
21932209

@@ -2443,24 +2459,32 @@ bool ModuleAddressSanitizer::instrumentModule(Module &M) {
24432459

24442460
// Create a module constructor. A destructor is created lazily because not all
24452461
// platforms, and not all modules need it.
2446-
if (CompileKernel) {
2447-
// The kernel always builds with its own runtime, and therefore does not
2448-
// need the init and version check calls.
2449-
AsanCtorFunction = createSanitizerCtor(M, kAsanModuleCtorName);
2450-
} else {
2451-
std::string AsanVersion = std::to_string(GetAsanVersion(M));
2452-
std::string VersionCheckName =
2453-
ClInsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : "";
2454-
std::tie(AsanCtorFunction, std::ignore) =
2455-
createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName,
2456-
kAsanInitName, /*InitArgTypes=*/{},
2457-
/*InitArgs=*/{}, VersionCheckName);
2462+
if (ConstructorKind == AsanCtorKind::Global) {
2463+
if (CompileKernel) {
2464+
// The kernel always builds with its own runtime, and therefore does not
2465+
// need the init and version check calls.
2466+
AsanCtorFunction = createSanitizerCtor(M, kAsanModuleCtorName);
2467+
} else {
2468+
std::string AsanVersion = std::to_string(GetAsanVersion(M));
2469+
std::string VersionCheckName =
2470+
ClInsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : "";
2471+
std::tie(AsanCtorFunction, std::ignore) =
2472+
createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName,
2473+
kAsanInitName, /*InitArgTypes=*/{},
2474+
/*InitArgs=*/{}, VersionCheckName);
2475+
}
24582476
}
24592477

24602478
bool CtorComdat = true;
24612479
if (ClGlobals) {
2462-
IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2463-
InstrumentGlobals(IRB, M, &CtorComdat);
2480+
assert(AsanCtorFunction || ConstructorKind == AsanCtorKind::None);
2481+
if (AsanCtorFunction) {
2482+
IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2483+
InstrumentGlobals(IRB, M, &CtorComdat);
2484+
} else {
2485+
IRBuilder<> IRB(*C);
2486+
InstrumentGlobals(IRB, M, &CtorComdat);
2487+
}
24642488
}
24652489

24662490
const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);
@@ -2469,14 +2493,17 @@ bool ModuleAddressSanitizer::instrumentModule(Module &M) {
24692493
// (1) global instrumentation is not TU-specific
24702494
// (2) target is ELF.
24712495
if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
2472-
AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
2473-
appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
2496+
if (AsanCtorFunction) {
2497+
AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
2498+
appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
2499+
}
24742500
if (AsanDtorFunction) {
24752501
AsanDtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleDtorName));
24762502
appendToGlobalDtors(M, AsanDtorFunction, Priority, AsanDtorFunction);
24772503
}
24782504
} else {
2479-
appendToGlobalCtors(M, AsanCtorFunction, Priority);
2505+
if (AsanCtorFunction)
2506+
appendToGlobalCtors(M, AsanCtorFunction, Priority);
24802507
if (AsanDtorFunction)
24812508
appendToGlobalDtors(M, AsanDtorFunction, Priority);
24822509
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; Check Default behaviour still emits ctors
2+
; RUN: opt < %s -passes=asan -S | \
3+
; RUN: FileCheck -check-prefix=CHECK-DEFAULT %s
4+
; CHECK-DEFAULT: llvm.global_ctor{{.+}}asan.module_ctor
5+
; CHECK-DEFAULT: define internal void @asan.module_ctor
6+
7+
; Check with ctor emission disabled
8+
; RUN: opt < %s -passes=asan \
9+
; RUN: -asan-constructor-kind=none -S | \
10+
; RUN: FileCheck %s
11+
; CHECK-NOT: llvm.global_ctor{{.+}}asan.module_ctor
12+
; CHECK-NOT: define internal void @asan.module_ctor
13+
14+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
15+
target triple = "x86_64-apple-macosx11.0.0"
16+
17+
@foo = dso_local global i32 0, align 4

0 commit comments

Comments
 (0)