summaryrefslogtreecommitdiff
path: root/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Instrumentation/SanitizerCoverage.cpp')
-rw-r--r--lib/Transforms/Instrumentation/SanitizerCoverage.cpp81
1 files changed, 52 insertions, 29 deletions
diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index a4dd48c8dd6a..0ba8d5765e8c 100644
--- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -29,6 +29,7 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
@@ -211,8 +212,8 @@ private:
bool IsLeafFunc = true);
Function *CreateInitCallsForSections(Module &M, const char *InitFunctionName,
Type *Ty, const char *Section);
- std::pair<GlobalVariable *, GlobalVariable *>
- CreateSecStartEnd(Module &M, const char *Section, Type *Ty);
+ std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section,
+ Type *Ty);
void SetNoSanitizeMetadata(Instruction *I) {
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
@@ -234,6 +235,7 @@ private:
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
*Int16Ty, *Int8Ty, *Int8PtrTy;
Module *CurModule;
+ std::string CurModuleUniqueId;
Triple TargetTriple;
LLVMContext *C;
const DataLayout *DL;
@@ -249,7 +251,7 @@ private:
} // namespace
-std::pair<GlobalVariable *, GlobalVariable *>
+std::pair<Value *, Value *>
SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section,
Type *Ty) {
GlobalVariable *SecStart =
@@ -260,22 +262,28 @@ SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section,
new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
nullptr, getSectionEnd(Section));
SecEnd->setVisibility(GlobalValue::HiddenVisibility);
-
- return std::make_pair(SecStart, SecEnd);
+ IRBuilder<> IRB(M.getContext());
+ Value *SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty);
+ if (!TargetTriple.isOSBinFormatCOFF())
+ return std::make_pair(IRB.CreatePointerCast(SecStart, Ty), SecEndPtr);
+
+ // Account for the fact that on windows-msvc __start_* symbols actually
+ // point to a uint64_t before the start of the array.
+ auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
+ auto GEP = IRB.CreateGEP(SecStartI8Ptr,
+ ConstantInt::get(IntptrTy, sizeof(uint64_t)));
+ return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr);
}
-
Function *SanitizerCoverageModule::CreateInitCallsForSections(
Module &M, const char *InitFunctionName, Type *Ty,
const char *Section) {
- IRBuilder<> IRB(M.getContext());
auto SecStartEnd = CreateSecStartEnd(M, Section, Ty);
auto SecStart = SecStartEnd.first;
auto SecEnd = SecStartEnd.second;
Function *CtorFunc;
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
- M, SanCovModuleCtorName, InitFunctionName, {Ty, Ty},
- {IRB.CreatePointerCast(SecStart, Ty), IRB.CreatePointerCast(SecEnd, Ty)});
+ M, SanCovModuleCtorName, InitFunctionName, {Ty, Ty}, {SecStart, SecEnd});
if (TargetTriple.supportsCOMDAT()) {
// Use comdat to dedup CtorFunc.
@@ -284,6 +292,17 @@ Function *SanitizerCoverageModule::CreateInitCallsForSections(
} else {
appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
}
+
+ if (TargetTriple.isOSBinFormatCOFF()) {
+ // In COFF files, if the contructors are set as COMDAT (they are because
+ // COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced
+ // functions and data) is used, the constructors get stripped. To prevent
+ // this, give the constructors weak ODR linkage and ensure the linker knows
+ // to include the sancov constructor. This way the linker can deduplicate
+ // the constructors but always leave one copy.
+ CtorFunc->setLinkage(GlobalValue::WeakODRLinkage);
+ appendToUsed(M, CtorFunc);
+ }
return CtorFunc;
}
@@ -293,6 +312,7 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
C = &(M.getContext());
DL = &M.getDataLayout();
CurModule = &M;
+ CurModuleUniqueId = getUniqueModuleId(CurModule);
TargetTriple = Triple(M.getTargetTriple());
FunctionGuardArray = nullptr;
Function8bitCounterArray = nullptr;
@@ -397,9 +417,7 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
Function *InitFunction = declareSanitizerInitFunction(
M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy});
IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
- IRBCtor.CreateCall(InitFunction,
- {IRB.CreatePointerCast(SecStartEnd.first, IntptrPtrTy),
- IRB.CreatePointerCast(SecStartEnd.second, IntptrPtrTy)});
+ IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
}
// We don't reference these arrays directly in any of our runtime functions,
// so we need to prevent them from being dead stripped.
@@ -549,11 +567,19 @@ GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection(
auto Array = new GlobalVariable(
*CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
Constant::getNullValue(ArrayTy), "__sancov_gen_");
- if (auto Comdat = F.getComdat())
- Array->setComdat(Comdat);
+
+ if (TargetTriple.supportsCOMDAT() && !F.isInterposable())
+ if (auto Comdat =
+ GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
+ Array->setComdat(Comdat);
Array->setSection(getSectionName(Section));
Array->setAlignment(Ty->isPointerTy() ? DL->getPointerSize()
: Ty->getPrimitiveSizeInBits() / 8);
+ GlobalsToAppendToUsed.push_back(Array);
+ GlobalsToAppendToCompilerUsed.push_back(Array);
+ MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F));
+ Array->addMetadata(LLVMContext::MD_associated, *MD);
+
return Array;
}
@@ -587,24 +613,16 @@ SanitizerCoverageModule::CreatePCArray(Function &F,
void SanitizerCoverageModule::CreateFunctionLocalArrays(
Function &F, ArrayRef<BasicBlock *> AllBlocks) {
- if (Options.TracePCGuard) {
+ if (Options.TracePCGuard)
FunctionGuardArray = CreateFunctionLocalArrayInSection(
AllBlocks.size(), F, Int32Ty, SanCovGuardsSectionName);
- GlobalsToAppendToUsed.push_back(FunctionGuardArray);
- }
- if (Options.Inline8bitCounters) {
+
+ if (Options.Inline8bitCounters)
Function8bitCounterArray = CreateFunctionLocalArrayInSection(
AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName);
- GlobalsToAppendToCompilerUsed.push_back(Function8bitCounterArray);
- MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F));
- Function8bitCounterArray->addMetadata(LLVMContext::MD_associated, *MD);
- }
- if (Options.PCTable) {
+
+ if (Options.PCTable)
FunctionPCsArray = CreatePCArray(F, AllBlocks);
- GlobalsToAppendToCompilerUsed.push_back(FunctionPCsArray);
- MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F));
- FunctionPCsArray->addMetadata(LLVMContext::MD_associated, *MD);
- }
}
bool SanitizerCoverageModule::InjectCoverage(Function &F,
@@ -806,8 +824,13 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
std::string
SanitizerCoverageModule::getSectionName(const std::string &Section) const {
- if (TargetTriple.getObjectFormat() == Triple::COFF)
- return ".SCOV$M";
+ if (TargetTriple.isOSBinFormatCOFF()) {
+ if (Section == SanCovCountersSectionName)
+ return ".SCOV$CM";
+ if (Section == SanCovPCsSectionName)
+ return ".SCOVP$M";
+ return ".SCOV$GM"; // For SanCovGuardsSectionName.
+ }
if (TargetTriple.isOSBinFormatMachO())
return "__DATA,__" + Section;
return "__" + Section;