[llvm] [sancov] add -sanitizer-coverage-drop-ctors (PR #137980)
Alexander Potapenko via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 30 08:32:57 PDT 2025
https://github.com/ramosian-glider created https://github.com/llvm/llvm-project/pull/137980
- **[sancov] apply clang-format**
- **[sancov] add -sanitizer-coverage-drop-ctors**
>From 4b60e89c5ccb70ad81ec87db4141fa246469562f Mon Sep 17 00:00:00 2001
From: Alexander Potapenko <glider at google.com>
Date: Wed, 30 Apr 2025 12:34:19 +0200
Subject: [PATCH 1/2] [sancov] apply clang-format
No functional change.
---
.../Instrumentation/SanitizerCoverage.cpp | 109 ++++++++----------
1 file changed, 51 insertions(+), 58 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index e52269637b92d..14f4ca4c673f1 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -288,11 +288,11 @@ class ModuleSanitizerCoverage {
LLVMContext *C;
const DataLayout *DL;
- GlobalVariable *FunctionGuardArray; // for trace-pc-guard.
- GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters.
- GlobalVariable *FunctionBoolArray; // for inline-bool-flag.
- GlobalVariable *FunctionPCsArray; // for pc-table.
- GlobalVariable *FunctionCFsArray; // for control flow table
+ GlobalVariable *FunctionGuardArray; // for trace-pc-guard.
+ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters.
+ GlobalVariable *FunctionBoolArray; // for inline-bool-flag.
+ GlobalVariable *FunctionPCsArray; // for pc-table.
+ GlobalVariable *FunctionCFsArray; // for control flow table
SmallVector<GlobalValue *, 20> GlobalsToAppendToUsed;
SmallVector<GlobalValue *, 20> GlobalsToAppendToCompilerUsed;
@@ -336,13 +336,11 @@ ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section,
GlobalValue::LinkageTypes Linkage = TargetTriple.isOSBinFormatCOFF()
? GlobalVariable::ExternalLinkage
: GlobalVariable::ExternalWeakLinkage;
- GlobalVariable *SecStart =
- new GlobalVariable(M, Ty, false, Linkage, nullptr,
- getSectionStart(Section));
+ GlobalVariable *SecStart = new GlobalVariable(M, Ty, false, Linkage, nullptr,
+ getSectionStart(Section));
SecStart->setVisibility(GlobalValue::HiddenVisibility);
- GlobalVariable *SecEnd =
- new GlobalVariable(M, Ty, false, Linkage, nullptr,
- getSectionEnd(Section));
+ GlobalVariable *SecEnd = new GlobalVariable(M, Ty, false, Linkage, nullptr,
+ getSectionEnd(Section));
SecEnd->setVisibility(GlobalValue::HiddenVisibility);
IRBuilder<> IRB(M.getContext());
if (!TargetTriple.isOSBinFormatCOFF())
@@ -447,25 +445,16 @@ bool ModuleSanitizerCoverage::instrumentModule() {
// Loads.
SanCovLoadFunction[0] = M.getOrInsertFunction(SanCovLoad1, VoidTy, PtrTy);
- SanCovLoadFunction[1] =
- M.getOrInsertFunction(SanCovLoad2, VoidTy, PtrTy);
- SanCovLoadFunction[2] =
- M.getOrInsertFunction(SanCovLoad4, VoidTy, PtrTy);
- SanCovLoadFunction[3] =
- M.getOrInsertFunction(SanCovLoad8, VoidTy, PtrTy);
- SanCovLoadFunction[4] =
- M.getOrInsertFunction(SanCovLoad16, VoidTy, PtrTy);
+ SanCovLoadFunction[1] = M.getOrInsertFunction(SanCovLoad2, VoidTy, PtrTy);
+ SanCovLoadFunction[2] = M.getOrInsertFunction(SanCovLoad4, VoidTy, PtrTy);
+ SanCovLoadFunction[3] = M.getOrInsertFunction(SanCovLoad8, VoidTy, PtrTy);
+ SanCovLoadFunction[4] = M.getOrInsertFunction(SanCovLoad16, VoidTy, PtrTy);
// Stores.
- SanCovStoreFunction[0] =
- M.getOrInsertFunction(SanCovStore1, VoidTy, PtrTy);
- SanCovStoreFunction[1] =
- M.getOrInsertFunction(SanCovStore2, VoidTy, PtrTy);
- SanCovStoreFunction[2] =
- M.getOrInsertFunction(SanCovStore4, VoidTy, PtrTy);
- SanCovStoreFunction[3] =
- M.getOrInsertFunction(SanCovStore8, VoidTy, PtrTy);
- SanCovStoreFunction[4] =
- M.getOrInsertFunction(SanCovStore16, VoidTy, PtrTy);
+ SanCovStoreFunction[0] = M.getOrInsertFunction(SanCovStore1, VoidTy, PtrTy);
+ SanCovStoreFunction[1] = M.getOrInsertFunction(SanCovStore2, VoidTy, PtrTy);
+ SanCovStoreFunction[2] = M.getOrInsertFunction(SanCovStore4, VoidTy, PtrTy);
+ SanCovStoreFunction[3] = M.getOrInsertFunction(SanCovStore8, VoidTy, PtrTy);
+ SanCovStoreFunction[4] = M.getOrInsertFunction(SanCovStore16, VoidTy, PtrTy);
{
AttributeList AL;
@@ -534,16 +523,16 @@ bool ModuleSanitizerCoverage::instrumentModule() {
}
if (Ctor && Options.PCTable) {
auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrTy);
- FunctionCallee InitFunction = declareSanitizerInitFunction(
- M, SanCovPCsInitName, {PtrTy, PtrTy});
+ FunctionCallee InitFunction =
+ declareSanitizerInitFunction(M, SanCovPCsInitName, {PtrTy, PtrTy});
IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
}
if (Ctor && Options.CollectControlFlow) {
auto SecStartEnd = CreateSecStartEnd(M, SanCovCFsSectionName, IntptrTy);
- FunctionCallee InitFunction = declareSanitizerInitFunction(
- M, SanCovCFsInitName, {PtrTy, PtrTy});
+ FunctionCallee InitFunction =
+ declareSanitizerInitFunction(M, SanCovCFsInitName, {PtrTy, PtrTy});
IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
}
@@ -600,8 +589,8 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
// Do not instrument full dominators, or full post-dominators with multiple
// predecessors.
- return !isFullDominator(BB, DT)
- && !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor());
+ return !isFullDominator(BB, DT) &&
+ !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor());
}
// Returns true iff From->To is a backedge.
@@ -776,16 +765,16 @@ ModuleSanitizerCoverage::CreatePCArray(Function &F,
for (size_t i = 0; i < N; i++) {
if (&F.getEntryBlock() == AllBlocks[i]) {
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
- PCs.push_back((Constant *)IRB.CreateIntToPtr(
- ConstantInt::get(IntptrTy, 1), PtrTy));
+ PCs.push_back(
+ (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
} else {
PCs.push_back((Constant *)IRB.CreatePointerCast(
BlockAddress::get(AllBlocks[i]), PtrTy));
PCs.push_back(Constant::getNullValue(PtrTy));
}
}
- auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, PtrTy,
- SanCovPCsSectionName);
+ auto *PCArray =
+ CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName);
PCArray->setInitializer(
ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs));
PCArray->setConstant(true);
@@ -840,7 +829,8 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &F,
ArrayRef<BasicBlock *> AllBlocks,
Value *&FunctionGateCmp,
bool IsLeafFunc) {
- if (AllBlocks.empty()) return false;
+ if (AllBlocks.empty())
+ return false;
CreateFunctionLocalArrays(F, AllBlocks);
for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
InjectCoverageAtBlock(F, *AllBlocks[i], i, FunctionGateCmp, IsLeafFunc);
@@ -923,13 +913,14 @@ void ModuleSanitizerCoverage::InjectTraceForDiv(
for (auto *BO : DivTraceTargets) {
InstrumentationIRBuilder IRB(BO);
Value *A1 = BO->getOperand(1);
- if (isa<ConstantInt>(A1)) continue;
+ if (isa<ConstantInt>(A1))
+ continue;
if (!A1->getType()->isIntegerTy())
continue;
uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType());
- int CallbackIdx = TypeSize == 32 ? 0 :
- TypeSize == 64 ? 1 : -1;
- if (CallbackIdx < 0) continue;
+ int CallbackIdx = TypeSize == 32 ? 0 : TypeSize == 64 ? 1 : -1;
+ if (CallbackIdx < 0)
+ continue;
auto Ty = Type::getIntNTy(*C, TypeSize);
IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx],
{IRB.CreateIntCast(A1, Ty, true)});
@@ -987,17 +978,20 @@ void ModuleSanitizerCoverage::InjectTraceForCmp(
if (!A0->getType()->isIntegerTy())
continue;
uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType());
- int CallbackIdx = TypeSize == 8 ? 0 :
- TypeSize == 16 ? 1 :
- TypeSize == 32 ? 2 :
- TypeSize == 64 ? 3 : -1;
- if (CallbackIdx < 0) continue;
+ int CallbackIdx = TypeSize == 8 ? 0
+ : TypeSize == 16 ? 1
+ : TypeSize == 32 ? 2
+ : TypeSize == 64 ? 3
+ : -1;
+ if (CallbackIdx < 0)
+ continue;
// __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];
bool FirstIsConst = isa<ConstantInt>(A0);
bool SecondIsConst = isa<ConstantInt>(A1);
// If both are const, then we don't need such a comparison.
- if (FirstIsConst && SecondIsConst) continue;
+ if (FirstIsConst && SecondIsConst)
+ continue;
// If only one is const, then make it the first callback argument.
if (FirstIsConst || SecondIsConst) {
CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx];
@@ -1136,13 +1130,13 @@ void ModuleSanitizerCoverage::createFunctionControlFlow(Function &F) {
if (&BB == &F.getEntryBlock())
CFs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
else
- CFs.push_back((Constant *)IRB.CreatePointerCast(BlockAddress::get(&BB),
- PtrTy));
+ CFs.push_back(
+ (Constant *)IRB.CreatePointerCast(BlockAddress::get(&BB), PtrTy));
for (auto SuccBB : successors(&BB)) {
assert(SuccBB != &F.getEntryBlock());
- CFs.push_back((Constant *)IRB.CreatePointerCast(BlockAddress::get(SuccBB),
- PtrTy));
+ CFs.push_back(
+ (Constant *)IRB.CreatePointerCast(BlockAddress::get(SuccBB), PtrTy));
}
CFs.push_back((Constant *)Constant::getNullValue(PtrTy));
@@ -1156,8 +1150,7 @@ void ModuleSanitizerCoverage::createFunctionControlFlow(Function &F) {
} else {
auto CalledF = CB->getCalledFunction();
if (CalledF && !CalledF->isIntrinsic())
- CFs.push_back(
- (Constant *)IRB.CreatePointerCast(CalledF, PtrTy));
+ CFs.push_back((Constant *)IRB.CreatePointerCast(CalledF, PtrTy));
}
}
}
@@ -1165,8 +1158,8 @@ void ModuleSanitizerCoverage::createFunctionControlFlow(Function &F) {
CFs.push_back((Constant *)Constant::getNullValue(PtrTy));
}
- FunctionCFsArray = CreateFunctionLocalArrayInSection(
- CFs.size(), F, PtrTy, SanCovCFsSectionName);
+ FunctionCFsArray = CreateFunctionLocalArrayInSection(CFs.size(), F, PtrTy,
+ SanCovCFsSectionName);
FunctionCFsArray->setInitializer(
ConstantArray::get(ArrayType::get(PtrTy, CFs.size()), CFs));
FunctionCFsArray->setConstant(true);
>From 3eeb10dc8878417f50fe964754493e76c68ede5b Mon Sep 17 00:00:00 2001
From: Alexander Potapenko <glider at google.com>
Date: Wed, 30 Apr 2025 17:01:27 +0200
Subject: [PATCH 2/2] [sancov] add -sanitizer-coverage-drop-ctors
Add a hidden flag to omit the @sancov.module_ctor* constructors.
When building kernel modules with sanitizer coverage enabled,
constructors may reference global symbols, creating unsupported
relocations. Because the kernel does not strictly need these
constructors in order for coverage to work, just omit them.
Fixes PR132393.
---
.../Instrumentation/SanitizerCoverage.cpp | 7 +++++++
.../SanitizerCoverage/trace-pc-guard.ll | 13 +++++++------
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 14f4ca4c673f1..57d96353dd537 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -117,6 +117,11 @@ static cl::opt<bool>
cl::desc("increments 8-bit counter for every edge"),
cl::Hidden);
+static cl::opt<bool>
+ ClSancovDropCtors("sanitizer-coverage-drop-ctors",
+ cl::desc("do not emit module ctors for global counters"),
+ cl::Hidden);
+
static cl::opt<bool>
ClInlineBoolFlag("sanitizer-coverage-inline-bool-flag",
cl::desc("sets a boolean flag for every edge"),
@@ -356,6 +361,8 @@ ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section,
Function *ModuleSanitizerCoverage::CreateInitCallsForSections(
Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty,
const char *Section) {
+ if (ClSancovDropCtors)
+ return nullptr;
auto SecStartEnd = CreateSecStartEnd(M, Section, Ty);
auto SecStart = SecStartEnd.first;
auto SecEnd = SecStartEnd.second;
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard.ll b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard.ll
index 5deb74eb8c6aa..5d46c23058b8e 100644
--- a/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard.ll
+++ b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard.ll
@@ -1,8 +1,9 @@
-; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -mtriple=x86_64 -S | FileCheck %s --check-prefixes=CHECK,COMDAT,ELF
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -mtriple=x86_64 -S | FileCheck %s --check-prefixes=CHECK,CHECK-CTOR,COMDAT,ELF,ELF-CTOR
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-drop-ctors=1 -mtriple=x86_64 -S | FileCheck %s --check-prefixes=CHECK,COMDAT,ELF
-; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -mtriple=aarch64-apple-darwin -S | FileCheck %s --check-prefixes=CHECK,MACHO
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -mtriple=aarch64-apple-darwin -S | FileCheck %s --check-prefixes=CHECK,CHECK-CTOR,MACHO
-; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -mtriple=x86_64-windows -S | FileCheck %s --check-prefixes=CHECK,COMDAT,WIN
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -mtriple=x86_64-windows -S | FileCheck %s --check-prefixes=CHECK,CHECK-CTOR,COMDAT,WIN
; COMDAT: $foo = comdat nodeduplicate
; COMDAT: $CallViaVptr = comdat nodeduplicate
@@ -20,7 +21,7 @@
; WIN-NEXT: @__sancov_gen_.1 = private global [1 x i32] zeroinitializer, section ".SCOV$GM", comdat($CallViaVptr), align 4{{$}}
; WIN-NEXT: @__sancov_gen_.2 = private global [1 x i32] zeroinitializer, section ".SCOV$GM", comdat($DirectBitcastCall), align 4{{$}}
-; ELF: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_trace_pc_guard]
+; ELF-CTOR: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_trace_pc_guard]
; ELF: @llvm.compiler.used = appending global [3 x ptr] [ptr @__sancov_gen_, ptr @__sancov_gen_.1, ptr @__sancov_gen_.2], section "llvm.metadata"
; MACHO: @llvm.used = appending global [4 x ptr] [ptr @sancov.module_ctor_trace_pc_guard, ptr @__sancov_gen_, ptr @__sancov_gen_.1, ptr @__sancov_gen_.2]
; MACHO-NOT: @llvm.compiler.used =
@@ -73,7 +74,7 @@ define void @DirectBitcastCall() sanitize_address {
ret void
}
-; ELF-LABEL: define internal void @sancov.module_ctor_trace_pc_guard() #2 comdat {
+; ELF-CTOR-LABEL: define internal void @sancov.module_ctor_trace_pc_guard() #2 comdat {
; MACHO-LABEL: define internal void @sancov.module_ctor_trace_pc_guard() #2 {
-; CHECK: attributes #2 = { nounwind }
+; CHECK-CTOR: attributes #2 = { nounwind }
More information about the llvm-commits
mailing list