[SanitizerCoverage] Prevent /OPT:REF from stripping constructors

Summary:
Linking with the /OPT:REF linker flag when building COFF files causes
the linker to strip SanitizerCoverage's constructors. Prevent this by
giving the constructors WeakODR linkage and by passing the linker a
directive to include sancov.module_ctor.

Include a test in compiler-rt to verify libFuzzer can be linked using
/OPT:REF

Reviewers: morehouse, rnk

Reviewed By: morehouse, rnk

Subscribers: rnk, morehouse, hiraditya

Differential Revision: https://reviews.llvm.org/D52119

llvm-svn: 344391
This commit is contained in:
Jonathan Metzman 2018-10-12 18:11:47 +00:00
parent f45bbd4c12
commit 0b94e88007
2 changed files with 30 additions and 0 deletions

View File

@ -0,0 +1,9 @@
REQUIRES: windows
// Verify that the linker eliminating unreferenced functions (/OPT:REF) does not
// strip sancov module constructor.
RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest /link /OPT:REF
RUN: not %run %t-SimpleCmpTest -seed=1 -runs=100000000 2>&1 | FileCheck %s
CHECK-NOT: ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting.
CHECK: BINGO

View File

@ -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"
@ -298,6 +299,26 @@ Function *SanitizerCoverageModule::CreateInitCallsForSections(
} else {
appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
}
if (TargetTriple.getObjectFormat() == Triple::COFF) {
// 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 tell the linker to
// always include the sancov constructor. This way the linker can
// deduplicate the constructors but always leave one copy.
CtorFunc->setLinkage(GlobalValue::WeakODRLinkage);
SmallString<20> PartialIncDirective("/include:");
// Get constructor's mangled name in order to support i386.
SmallString<40> MangledName;
Mangler().getNameWithPrefix(MangledName, CtorFunc, true);
Twine IncDirective = PartialIncDirective + MangledName;
Metadata *Args[1] = {MDString::get(*C, IncDirective.str())};
MDNode *MetadataNode = MDNode::get(*C, Args);
NamedMDNode *NamedMetadata =
M.getOrInsertNamedMetadata("llvm.linker.options");
NamedMetadata->addOperand(MetadataNode);
}
return CtorFunc;
}