Skip to content

Commit e911554

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 8a33a7f commit e911554

File tree

4 files changed

+80
-28
lines changed

4 files changed

+80
-28
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ struct AddressSanitizerOptions {
3636
class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
3737
public:
3838
AddressSanitizerPass(const AddressSanitizerOptions &Options,
39-
bool UseGlobalGC = true, bool UseOdrIndicator = false,
40-
AsanDtorKind DestructorKind = AsanDtorKind::Global);
39+
bool UseGlobalGC = true, bool UseOdrIndicator = true,
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: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,13 @@ static cl::opt<bool> ClSkipPromotableAllocas(
348348
cl::desc("Do not instrument promotable allocas"), cl::Hidden,
349349
cl::init(true));
350350

351+
static cl::opt<AsanCtorKind> ClConstructorKind(
352+
"asan-constructor-kind",
353+
cl::desc("Sets the ASan constructor kind"),
354+
cl::values(clEnumValN(AsanCtorKind::None, "none", "No constructors"),
355+
clEnumValN(AsanCtorKind::Global, "global",
356+
"Use global constructors")),
357+
cl::init(AsanCtorKind::Global), cl::Hidden);
351358
// These flags allow to change the shadow mapping.
352359
// The shadow mapping looks like
353360
// Shadow = (Mem >> scale) + offset
@@ -767,8 +774,9 @@ class ModuleAddressSanitizer {
767774
public:
768775
ModuleAddressSanitizer(Module &M, bool CompileKernel = false,
769776
bool Recover = false, bool UseGlobalsGC = true,
770-
bool UseOdrIndicator = false,
771-
AsanDtorKind DestructorKind = AsanDtorKind::Global)
777+
bool UseOdrIndicator = true,
778+
AsanDtorKind DestructorKind = AsanDtorKind::Global,
779+
AsanCtorKind ConstructorKind = AsanCtorKind::Global)
772780
: CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan
773781
: CompileKernel),
774782
Recover(ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover),
@@ -784,7 +792,8 @@ class ModuleAddressSanitizer {
784792
// ClWithComdat and ClUseGlobalsGC unless the frontend says it's ok to
785793
// do globals-gc.
786794
UseCtorComdat(UseGlobalsGC && ClWithComdat && !this->CompileKernel),
787-
DestructorKind(DestructorKind) {
795+
DestructorKind(DestructorKind),
796+
ConstructorKind(ConstructorKind) {
788797
C = &(M.getContext());
789798
int LongSize = M.getDataLayout().getPointerSizeInBits();
790799
IntptrTy = Type::getIntNTy(*C, LongSize);
@@ -842,6 +851,7 @@ class ModuleAddressSanitizer {
842851
bool UseOdrIndicator;
843852
bool UseCtorComdat;
844853
AsanDtorKind DestructorKind;
854+
AsanCtorKind ConstructorKind;
845855
Type *IntptrTy;
846856
LLVMContext *C;
847857
Triple TargetTriple;
@@ -1123,15 +1133,18 @@ void AddressSanitizerPass::printPipeline(
11231133

11241134
AddressSanitizerPass::AddressSanitizerPass(
11251135
const AddressSanitizerOptions &Options, bool UseGlobalGC,
1126-
bool UseOdrIndicator, AsanDtorKind DestructorKind)
1136+
bool UseOdrIndicator, AsanDtorKind DestructorKind,
1137+
AsanCtorKind ConstructorKind)
11271138
: Options(Options), UseGlobalGC(UseGlobalGC),
1128-
UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind) {}
1139+
UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
1140+
ConstructorKind(ClConstructorKind) {}
11291141

11301142
PreservedAnalyses AddressSanitizerPass::run(Module &M,
11311143
ModuleAnalysisManager &MAM) {
11321144
ModuleAddressSanitizer ModuleSanitizer(M, Options.CompileKernel,
11331145
Options.Recover, UseGlobalGC,
1134-
UseOdrIndicator, DestructorKind);
1146+
UseOdrIndicator, DestructorKind,
1147+
ConstructorKind);
11351148
bool Modified = false;
11361149
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
11371150
const StackSafetyGlobalInfo *const SSGI =
@@ -2089,7 +2102,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsELF(
20892102
StopELFMetadata->setVisibility(GlobalVariable::HiddenVisibility);
20902103

20912104
// Create a call to register the globals with the runtime.
2092-
IRB.CreateCall(AsanRegisterElfGlobals,
2105+
if (ConstructorKind == AsanCtorKind::Global)
2106+
IRB.CreateCall(AsanRegisterElfGlobals,
20932107
{IRB.CreatePointerCast(RegisteredFlag, IntptrTy),
20942108
IRB.CreatePointerCast(StartELFMetadata, IntptrTy),
20952109
IRB.CreatePointerCast(StopELFMetadata, IntptrTy)});
@@ -2152,7 +2166,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsMachO(
21522166
ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName);
21532167
RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility);
21542168

2155-
IRB.CreateCall(AsanRegisterImageGlobals,
2169+
if (ConstructorKind == AsanCtorKind::Global)
2170+
IRB.CreateCall(AsanRegisterImageGlobals,
21562171
{IRB.CreatePointerCast(RegisteredFlag, IntptrTy)});
21572172

21582173
// We also need to unregister globals at the end, e.g., when a shared library
@@ -2181,7 +2196,8 @@ void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
21812196
if (Mapping.Scale > 3)
21822197
AllGlobals->setAlignment(Align(1ULL << Mapping.Scale));
21832198

2184-
IRB.CreateCall(AsanRegisterGlobals,
2199+
if (ConstructorKind == AsanCtorKind::Global)
2200+
IRB.CreateCall(AsanRegisterGlobals,
21852201
{IRB.CreatePointerCast(AllGlobals, IntptrTy),
21862202
ConstantInt::get(IntptrTy, N)});
21872203

@@ -2436,24 +2452,32 @@ bool ModuleAddressSanitizer::instrumentModule(Module &M) {
24362452

24372453
// Create a module constructor. A destructor is created lazily because not all
24382454
// platforms, and not all modules need it.
2439-
if (CompileKernel) {
2440-
// The kernel always builds with its own runtime, and therefore does not
2441-
// need the init and version check calls.
2442-
AsanCtorFunction = createSanitizerCtor(M, kAsanModuleCtorName);
2443-
} else {
2444-
std::string AsanVersion = std::to_string(GetAsanVersion(M));
2445-
std::string VersionCheckName =
2446-
ClInsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : "";
2447-
std::tie(AsanCtorFunction, std::ignore) =
2448-
createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName,
2449-
kAsanInitName, /*InitArgTypes=*/{},
2450-
/*InitArgs=*/{}, VersionCheckName);
2455+
if (ConstructorKind == AsanCtorKind::Global) {
2456+
if (CompileKernel) {
2457+
// The kernel always builds with its own runtime, and therefore does not
2458+
// need the init and version check calls.
2459+
AsanCtorFunction = createSanitizerCtor(M, kAsanModuleCtorName);
2460+
} else {
2461+
std::string AsanVersion = std::to_string(GetAsanVersion(M));
2462+
std::string VersionCheckName =
2463+
ClInsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : "";
2464+
std::tie(AsanCtorFunction, std::ignore) =
2465+
createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName,
2466+
kAsanInitName, /*InitArgTypes=*/{},
2467+
/*InitArgs=*/{}, VersionCheckName);
2468+
}
24512469
}
24522470

24532471
bool CtorComdat = true;
24542472
if (ClGlobals) {
2455-
IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2456-
InstrumentGlobals(IRB, M, &CtorComdat);
2473+
assert(AsanCtorFunction || ConstructorKind == AsanCtorKind::None);
2474+
if (AsanCtorFunction) {
2475+
IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2476+
InstrumentGlobals(IRB, M, &CtorComdat);
2477+
} else {
2478+
IRBuilder<> IRB(*C);
2479+
InstrumentGlobals(IRB, M, &CtorComdat);
2480+
}
24572481
}
24582482

24592483
const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);
@@ -2462,14 +2486,17 @@ bool ModuleAddressSanitizer::instrumentModule(Module &M) {
24622486
// (1) global instrumentation is not TU-specific
24632487
// (2) target is ELF.
24642488
if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
2465-
AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
2466-
appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
2489+
if (AsanCtorFunction) {
2490+
AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
2491+
appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
2492+
}
24672493
if (AsanDtorFunction) {
24682494
AsanDtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleDtorName));
24692495
appendToGlobalDtors(M, AsanDtorFunction, Priority, AsanDtorFunction);
24702496
}
24712497
} else {
2472-
appendToGlobalCtors(M, AsanCtorFunction, Priority);
2498+
if (AsanCtorFunction)
2499+
appendToGlobalCtors(M, AsanCtorFunction, Priority);
24732500
if (AsanDtorFunction)
24742501
appendToGlobalDtors(M, AsanDtorFunction, Priority);
24752502
}
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)