mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-12 05:47:11 +03:00
Replace -sanitize
with -fsanitize
and add -fsanitize-coverage
. (#2149)
This reworks the sanitizer interface to be identical with Clang's. What's left to do is pass the correct runtime libraries to the linker.
This commit is contained in:
parent
b82d87d6ee
commit
22b1accb59
14 changed files with 388 additions and 37 deletions
|
@ -334,6 +334,7 @@ file(GLOB IR_HDR ir/*.h)
|
|||
set(DRV_SRC
|
||||
driver/cache.cpp
|
||||
driver/cl_options.cpp
|
||||
driver/cl_options_sanitizers.cpp
|
||||
driver/codegenerator.cpp
|
||||
driver/configfile.cpp
|
||||
driver/dcomputecodegenerator.cpp
|
||||
|
@ -352,6 +353,7 @@ set(DRV_HDR
|
|||
driver/cache.h
|
||||
driver/cache_pruning.h
|
||||
driver/cl_options.h
|
||||
driver/cl_options_sanitizers.h
|
||||
driver/codegenerator.h
|
||||
driver/configfile.h
|
||||
driver/dcomputecodegenerator.h
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "ddmd/errors.h"
|
||||
#include "driver/cache_pruning.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "driver/cl_options_sanitizers.h"
|
||||
#include "driver/ldc-version.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/optimizer.h"
|
||||
|
@ -300,6 +301,7 @@ void outputIR2ObjRelevantCmdlineArgs(llvm::raw_ostream &hash_os) {
|
|||
// the possibility of different default settings on different platforms (while
|
||||
// sharing the cache).
|
||||
outputOptimizationSettings(hash_os);
|
||||
opts::outputSanitizerSettings(hash_os);
|
||||
hash_os << opts::mCPU;
|
||||
for (auto &attr : opts::mAttrs) {
|
||||
hash_os << attr;
|
||||
|
|
183
driver/cl_options_sanitizers.cpp
Normal file
183
driver/cl_options_sanitizers.cpp
Normal file
|
@ -0,0 +1,183 @@
|
|||
//===-- cl_options_sanitizers.cpp -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// LDC – the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Creates and handles the -fsanitize=... and -fsanitize-coverage=...
|
||||
// commandline options.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "driver/cl_options_sanitizers.h"
|
||||
|
||||
#include "ddmd/errors.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace opts;
|
||||
|
||||
cl::list<std::string> fSanitize(
|
||||
"fsanitize", cl::CommaSeparated,
|
||||
cl::desc("Turn on runtime checks for various forms of undefined or "
|
||||
"suspicious behavior."),
|
||||
cl::value_desc("checks"));
|
||||
|
||||
#ifdef ENABLE_COVERAGE_SANITIZER
|
||||
cl::list<std::string> fSanitizeCoverage(
|
||||
"fsanitize-coverage", cl::CommaSeparated,
|
||||
cl::desc("Specify the type of coverage instrumentation for -fsanitize"),
|
||||
cl::value_desc("type"));
|
||||
|
||||
llvm::SanitizerCoverageOptions sanitizerCoverageOptions;
|
||||
#endif
|
||||
|
||||
// Parse sanitizer name passed on commandline and return the corresponding
|
||||
// sanitizer bits.
|
||||
SanitizerCheck parseSanitizerName(llvm::StringRef name) {
|
||||
SanitizerCheck parsedValue =
|
||||
llvm::StringSwitch<SanitizerCheck>(name)
|
||||
.Case("address", AddressSanitizer)
|
||||
.Case("fuzzer", FuzzSanitizer)
|
||||
.Case("memory", MemorySanitizer)
|
||||
.Case("thread", ThreadSanitizer)
|
||||
.Default(NoneSanitizer);
|
||||
|
||||
if (parsedValue == NoneSanitizer) {
|
||||
error(Loc(), "Unrecognized -fsanitize value '%s'.", name.str().c_str());
|
||||
}
|
||||
|
||||
return parsedValue;
|
||||
}
|
||||
|
||||
SanitizerBits parseFSanitizeCmdlineParameter() {
|
||||
SanitizerBits retval = 0;
|
||||
for (const auto &name : fSanitize) {
|
||||
SanitizerCheck check = parseSanitizerName(name);
|
||||
retval |= SanitizerBits(check);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_COVERAGE_SANITIZER
|
||||
void parseFSanitizeCoverageParameter(llvm::StringRef name,
|
||||
llvm::SanitizerCoverageOptions &opts) {
|
||||
if (name == "func") {
|
||||
opts.CoverageType = std::max(opts.CoverageType,
|
||||
llvm::SanitizerCoverageOptions::SCK_Function);
|
||||
} else if (name == "bb") {
|
||||
opts.CoverageType =
|
||||
std::max(opts.CoverageType, llvm::SanitizerCoverageOptions::SCK_BB);
|
||||
} else if (name == "edge") {
|
||||
opts.CoverageType =
|
||||
std::max(opts.CoverageType, llvm::SanitizerCoverageOptions::SCK_Edge);
|
||||
} else if (name == "indirect-calls") {
|
||||
opts.IndirectCalls = true;
|
||||
} else if (name == "trace-bb") {
|
||||
opts.TraceBB = true;
|
||||
}
|
||||
else if (name == "trace-cmp") {
|
||||
opts.TraceCmp = true;
|
||||
}
|
||||
else if (name == "trace-div") {
|
||||
opts.TraceDiv = true;
|
||||
}
|
||||
else if (name == "trace-gep") {
|
||||
opts.TraceGep = true;
|
||||
}
|
||||
else if (name == "8bit-counters") {
|
||||
opts.Use8bitCounters = true;
|
||||
}
|
||||
else if (name == "trace-pc") {
|
||||
opts.TracePC = true;
|
||||
}
|
||||
else if (name == "trace-pc-guard") {
|
||||
opts.TracePCGuard = true;
|
||||
}
|
||||
#if LDC_LLVM_VER >= 500
|
||||
else if (name == "no-prune") {
|
||||
opts.NoPrune = true;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
error(Loc(), "Unrecognized -fsanitize-coverage option '%s'.", name.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void parseFSanitizeCoverageCmdlineParameter(llvm::SanitizerCoverageOptions &opts) {
|
||||
for (const auto &name : fSanitizeCoverage) {
|
||||
// Enable CoverageSanitizer when one or more -fsanitize-coverage parameters are passed
|
||||
enabledSanitizers |= CoverageSanitizer;
|
||||
|
||||
parseFSanitizeCoverageParameter(name, opts);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace opts {
|
||||
|
||||
SanitizerBits enabledSanitizers = 0;
|
||||
|
||||
void initializeSanitizerOptionsFromCmdline()
|
||||
{
|
||||
enabledSanitizers |= parseFSanitizeCmdlineParameter();
|
||||
|
||||
#ifdef ENABLE_COVERAGE_SANITIZER
|
||||
auto &sancovOpts = sanitizerCoverageOptions;
|
||||
|
||||
// The Fuzz sanitizer implies -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp
|
||||
if (isSanitizerEnabled(FuzzSanitizer)) {
|
||||
enabledSanitizers |= CoverageSanitizer;
|
||||
sancovOpts.TracePCGuard = true;
|
||||
sancovOpts.IndirectCalls = true;
|
||||
sancovOpts.TraceCmp = true;
|
||||
}
|
||||
|
||||
parseFSanitizeCoverageCmdlineParameter(sancovOpts);
|
||||
|
||||
// trace-pc and trace-pc-guard without specifying the insertion type implies
|
||||
// edge
|
||||
if ((sancovOpts.CoverageType == llvm::SanitizerCoverageOptions::SCK_None) &&
|
||||
(sancovOpts.TracePC || sancovOpts.TracePCGuard)) {
|
||||
sancovOpts.CoverageType = llvm::SanitizerCoverageOptions::SCK_Edge;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_COVERAGE_SANITIZER
|
||||
llvm::SanitizerCoverageOptions getSanitizerCoverageOptions() {
|
||||
return sanitizerCoverageOptions;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Output to `hash_os` all optimization settings that influence object code
|
||||
// output and that are not observable in the IR before running LLVM passes. This
|
||||
// is used to calculate the hash use for caching that uniquely identifies the
|
||||
// object file output.
|
||||
void outputSanitizerSettings(llvm::raw_ostream &hash_os) {
|
||||
hash_os << SanitizerBits(enabledSanitizers);
|
||||
|
||||
#ifdef ENABLE_COVERAGE_SANITIZER
|
||||
hash_os << sanitizerCoverageOptions.CoverageType;
|
||||
hash_os << sanitizerCoverageOptions.IndirectCalls;
|
||||
hash_os << sanitizerCoverageOptions.TraceBB;
|
||||
hash_os << sanitizerCoverageOptions.TraceCmp;
|
||||
hash_os << sanitizerCoverageOptions.TraceDiv;
|
||||
hash_os << sanitizerCoverageOptions.TraceGep;
|
||||
hash_os << sanitizerCoverageOptions.Use8bitCounters;
|
||||
hash_os << sanitizerCoverageOptions.TracePC;
|
||||
hash_os << sanitizerCoverageOptions.TracePCGuard;
|
||||
#if LDC_LLVM_VER >= 500
|
||||
hash_os << sanitizerCoverageOptions.NoPrune;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace opts
|
59
driver/cl_options_sanitizers.h
Normal file
59
driver/cl_options_sanitizers.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
//=== driver/cl_options_sanitizers.h - LDC command line options -*- C++ -*-===//
|
||||
//
|
||||
// LDC – the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Deals with -fsanitize=...
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LDC_DRIVER_CL_OPTIONS_SANITIZERS_H
|
||||
#define LDC_DRIVER_CL_OPTIONS_SANITIZERS_H
|
||||
|
||||
#include "gen/cl_helpers.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
|
||||
#if LDC_LLVM_VER >= 400
|
||||
// Enable coverage sanitizer options from LLVM 4.0 to simplify our code: earlier
|
||||
// versions do not have all options available.
|
||||
#define ENABLE_COVERAGE_SANITIZER
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
}
|
||||
|
||||
namespace opts {
|
||||
namespace cl = llvm::cl;
|
||||
|
||||
typedef unsigned SanitizerBits;
|
||||
enum SanitizerCheck : SanitizerBits {
|
||||
NoneSanitizer = 0,
|
||||
AddressSanitizer = 1 << 0,
|
||||
FuzzSanitizer = 1 << 1,
|
||||
MemorySanitizer = 1 << 2,
|
||||
ThreadSanitizer = 1 << 3,
|
||||
CoverageSanitizer = 1 << 4
|
||||
};
|
||||
extern SanitizerBits enabledSanitizers;
|
||||
|
||||
inline bool isAnySanitizerEnabled() { return enabledSanitizers; }
|
||||
inline bool isSanitizerEnabled(SanitizerCheck san) {
|
||||
return enabledSanitizers & san;
|
||||
}
|
||||
|
||||
void initializeSanitizerOptionsFromCmdline();
|
||||
|
||||
#ifdef ENABLE_COVERAGE_SANITIZER
|
||||
llvm::SanitizerCoverageOptions getSanitizerCoverageOptions();
|
||||
#endif
|
||||
|
||||
void outputSanitizerSettings(llvm::raw_ostream &hash_os);
|
||||
|
||||
} // namespace opts
|
||||
|
||||
#endif // LDC_DRIVER_CL_OPTIONS_SANITIZERS_H
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "errors.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "driver/cl_options_sanitizers.h"
|
||||
#include "driver/exe_path.h"
|
||||
#include "driver/tool.h"
|
||||
#include "gen/irstate.h"
|
||||
|
@ -242,13 +243,17 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
|
|||
|
||||
// Requires clang.
|
||||
void ArgsBuilder::addSanitizers() {
|
||||
if (opts::sanitize == opts::AddressSanitizer) {
|
||||
// TODO: instead of this, we should link with our own sanitizer libraries
|
||||
// because LDC's LLVM version could be different from the system clang.
|
||||
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
|
||||
args.push_back("-fsanitize=address");
|
||||
}
|
||||
if (opts::sanitize == opts::MemorySanitizer) {
|
||||
|
||||
if (opts::isSanitizerEnabled(opts::MemorySanitizer)) {
|
||||
args.push_back("-fsanitize=memory");
|
||||
}
|
||||
if (opts::sanitize == opts::ThreadSanitizer) {
|
||||
|
||||
if (opts::isSanitizerEnabled(opts::ThreadSanitizer)) {
|
||||
args.push_back("-fsanitize=thread");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "ddmd/target.h"
|
||||
#include "driver/cache.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "driver/cl_options_sanitizers.h"
|
||||
#include "driver/codegenerator.h"
|
||||
#include "driver/configfile.h"
|
||||
#include "driver/dcomputecodegenerator.h"
|
||||
|
@ -458,6 +459,8 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
|
|||
}
|
||||
#endif
|
||||
|
||||
initializeSanitizerOptionsFromCmdline();
|
||||
|
||||
processVersions(debugArgs, "debug", DebugCondition::setGlobalLevel,
|
||||
DebugCondition::addGlobalIdent);
|
||||
processVersions(versions, "version", VersionCondition::setGlobalLevel,
|
||||
|
@ -930,16 +933,17 @@ void registerPredefinedVersions() {
|
|||
VersionCondition::addPredefinedGlobalIdent("D_ObjectiveC");
|
||||
}
|
||||
|
||||
// Pass sanitizer arguments to linker. Requires clang.
|
||||
if (opts::sanitize == opts::AddressSanitizer) {
|
||||
// Define sanitizer versions.
|
||||
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LDC_AddressSanitizer");
|
||||
}
|
||||
|
||||
if (opts::sanitize == opts::MemorySanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::CoverageSanitizer)) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LDC_CoverageSanitizer");
|
||||
}
|
||||
if (opts::isSanitizerEnabled(opts::MemorySanitizer)) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LDC_MemorySanitizer");
|
||||
}
|
||||
|
||||
if (opts::sanitize == opts::ThreadSanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::ThreadSanitizer)) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LDC_ThreadSanitizer");
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "statement.h"
|
||||
#include "template.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "driver/cl_options_sanitizers.h"
|
||||
#include "gen/abi.h"
|
||||
#include "gen/arrays.h"
|
||||
#include "gen/classes.h"
|
||||
|
@ -945,17 +946,17 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
if (gABI->needsUnwindTables()) {
|
||||
func->addFnAttr(LLAttribute::UWTable);
|
||||
}
|
||||
if (opts::sanitize != opts::None) {
|
||||
if (opts::isAnySanitizerEnabled()) {
|
||||
// Set the required sanitizer attribute.
|
||||
if (opts::sanitize == opts::AddressSanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
|
||||
func->addFnAttr(LLAttribute::SanitizeAddress);
|
||||
}
|
||||
|
||||
if (opts::sanitize == opts::MemorySanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::MemorySanitizer)) {
|
||||
func->addFnAttr(LLAttribute::SanitizeMemory);
|
||||
}
|
||||
|
||||
if (opts::sanitize == opts::ThreadSanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::ThreadSanitizer)) {
|
||||
func->addFnAttr(LLAttribute::SanitizeThread);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gen/optimizer.h"
|
||||
|
||||
#include "errors.h"
|
||||
#include "gen/cl_helpers.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/passes/Passes.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "driver/cl_options_sanitizers.h"
|
||||
#include "driver/targetmachine.h"
|
||||
#include "llvm/LinkAllPasses.h"
|
||||
#if LDC_LLVM_VER >= 307
|
||||
|
@ -98,14 +100,6 @@ static cl::opt<bool> stripDebug(
|
|||
"strip-debug", cl::ZeroOrMore,
|
||||
cl::desc("Strip symbolic debug information before optimization"));
|
||||
|
||||
cl::opt<opts::SanitizerCheck> opts::sanitize(
|
||||
"sanitize", cl::desc("Enable runtime instrumentation for bug detection"),
|
||||
cl::init(opts::None),
|
||||
clEnumValues(clEnumValN(opts::AddressSanitizer, "address", "Memory errors"),
|
||||
clEnumValN(opts::MemorySanitizer, "memory", "Memory errors"),
|
||||
clEnumValN(opts::ThreadSanitizer, "thread",
|
||||
"Race detection")));
|
||||
|
||||
static cl::opt<bool> disableLoopUnrolling(
|
||||
"disable-loop-unrolling", cl::ZeroOrMore,
|
||||
cl::desc("Disable loop unrolling in all relevant passes"));
|
||||
|
@ -213,6 +207,14 @@ static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
|
|||
PM.add(createThreadSanitizerPass());
|
||||
}
|
||||
|
||||
static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
#ifdef ENABLE_COVERAGE_SANITIZER
|
||||
PM.add(
|
||||
createSanitizerCoverageModulePass(opts::getSanitizerCoverageOptions()));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Adds PGO instrumentation generation and use passes.
|
||||
static void addPGOPasses(legacy::PassManagerBase &mpm, unsigned optLevel) {
|
||||
#if LDC_WITH_PGO
|
||||
|
@ -303,27 +305,34 @@ static void addOptimizationPasses(PassManagerBase &mpm,
|
|||
builder.SLPVectorize =
|
||||
disableSLPVectorization ? false : optLevel > 1 && sizeLevel < 2;
|
||||
|
||||
if (opts::sanitize == opts::AddressSanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
|
||||
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addAddressSanitizerPasses);
|
||||
builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||
addAddressSanitizerPasses);
|
||||
}
|
||||
|
||||
if (opts::sanitize == opts::MemorySanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::MemorySanitizer)) {
|
||||
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addMemorySanitizerPass);
|
||||
builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||
addMemorySanitizerPass);
|
||||
}
|
||||
|
||||
if (opts::sanitize == opts::ThreadSanitizer) {
|
||||
if (opts::isSanitizerEnabled(opts::ThreadSanitizer)) {
|
||||
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addThreadSanitizerPass);
|
||||
builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||
addThreadSanitizerPass);
|
||||
}
|
||||
|
||||
if (opts::isSanitizerEnabled(opts::CoverageSanitizer)) {
|
||||
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addSanitizerCoveragePass);
|
||||
builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||
addSanitizerCoveragePass);
|
||||
}
|
||||
|
||||
if (!disableLangSpecificPasses) {
|
||||
if (!disableSimplifyDruntimeCalls) {
|
||||
builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd,
|
||||
|
@ -483,7 +492,6 @@ void outputOptimizationSettings(llvm::raw_ostream &hash_os) {
|
|||
hash_os << disableGCToStack;
|
||||
hash_os << unitAtATime;
|
||||
hash_os << stripDebug;
|
||||
hash_os << opts::sanitize;
|
||||
hash_os << disableLoopUnrolling;
|
||||
hash_os << disableLoopVectorization;
|
||||
hash_os << disableSLPVectorization;
|
||||
|
|
|
@ -24,18 +24,6 @@ namespace llvm {
|
|||
class raw_ostream;
|
||||
}
|
||||
|
||||
namespace opts {
|
||||
|
||||
enum SanitizerCheck {
|
||||
None,
|
||||
AddressSanitizer,
|
||||
MemorySanitizer,
|
||||
ThreadSanitizer
|
||||
};
|
||||
|
||||
extern llvm::cl::opt<SanitizerCheck> sanitize;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
}
|
||||
|
|
14
tests/sanitizers/fsanitize_address.d
Normal file
14
tests/sanitizers/fsanitize_address.d
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Test basic AddressSanitizer functionality
|
||||
|
||||
// RUN: %ldc -c -output-ll -g -fsanitize=address -of=%t.ll %s && FileCheck %s < %t.ll
|
||||
// RUN: %ldc -c -output-ll -g -fsanitize=address,thread -of=%t.tsan.ll %s && FileCheck %s --check-prefix=wTSAN < %t.tsan.ll
|
||||
|
||||
void foo() {
|
||||
// wTSAN: call {{.*}}_tsan_func_entry
|
||||
// CHECK: call {{.*}}_asan_stack_malloc
|
||||
// wTSAN: {{(call|invoke)}} {{.*}}_asan_stack_malloc
|
||||
int[10] i;
|
||||
// CHECK: call {{.*}}_asan_report_store
|
||||
// wTSAN: {{(call|invoke)}} {{.*}}_asan_report_store
|
||||
i[0] = 1;
|
||||
}
|
31
tests/sanitizers/fsanitize_coverage.d
Normal file
31
tests/sanitizers/fsanitize_coverage.d
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Test basic coverage sanitizer functionality
|
||||
|
||||
// REQUIRES: atleast_llvm400
|
||||
|
||||
// RUN: %ldc -c -output-ll -fsanitize-coverage=trace-pc-guard -of=%t.ll %s && FileCheck %s --check-prefix=PCGUARD < %t.ll
|
||||
// RUN: %ldc -c -output-ll -fsanitize-coverage=trace-pc-guard,trace-cmp -of=%t.cmp.ll %s && FileCheck %s --check-prefix=PCCMP < %t.cmp.ll
|
||||
// RUN: %ldc -c -output-ll -fsanitize-coverage=trace-pc-guard,func -of=%t.func.ll %s && FileCheck %s --check-prefix=PCFUNC < %t.func.ll
|
||||
|
||||
// PCGUARD-LABEL: define{{.*}} @{{.*}}FuzzMe
|
||||
// PCCMP-LABEL: define{{.*}} @{{.*}}FuzzMe
|
||||
// PCFUNC-LABEL: define{{.*}} @{{.*}}FuzzMe
|
||||
bool FuzzMe(const ubyte* data, size_t dataSize)
|
||||
{
|
||||
// PCGUARD: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// PCGUARD-NOT: call {{.*}}_sanitizer_cov_trace_cmp
|
||||
// PCGUARD: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// PCGUARD-NOT: call {{.*}}_sanitizer_cov_trace_cmp
|
||||
|
||||
// PCCMP: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// PCCMP: call {{.*}}_sanitizer_cov_trace_cmp
|
||||
|
||||
// PCFUNC: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// PCFUNC-NOT: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
|
||||
return dataSize >= 3 &&
|
||||
data[0] == 'F' &&
|
||||
data[1] == 'U' &&
|
||||
data[2] == 'Z' &&
|
||||
data[3] == 'Z'; // :‑<
|
||||
// PCFUNC: ret i1
|
||||
}
|
8
tests/sanitizers/fsanitize_error_diagnostic.d
Normal file
8
tests/sanitizers/fsanitize_error_diagnostic.d
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Test sanitizer errors on unrecognized values
|
||||
|
||||
// REQUIRES: atleast_llvm400
|
||||
|
||||
// RUN: not %ldc -c -fsanitize=poiuyt -fsanitize-coverage=aqswdefr %s 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK-DAG: Unrecognized -fsanitize value 'poiuyt'
|
||||
// CHECK-DAG: Unrecognized -fsanitize-coverage option 'aqswdefr'
|
36
tests/sanitizers/fsanitize_fuzzer.d
Normal file
36
tests/sanitizers/fsanitize_fuzzer.d
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Test basic Fuzz sanitizer functionality
|
||||
|
||||
// REQUIRES: atleast_llvm400
|
||||
|
||||
// RUN: %ldc -c -output-ll -O3 -fsanitize=fuzzer -of=%t.ll %s && FileCheck %s < %t.ll
|
||||
// RUN: %ldc -c -output-ll -fsanitize=fuzzer,address -of=%t.asan.ll %s && FileCheck %s --check-prefix=wASAN < %t.asan.ll
|
||||
|
||||
// CHECK-LABEL: define{{.*}} @{{.*}}FuzzMe
|
||||
// wASAN-LABEL: define{{.*}} @{{.*}}FuzzMe
|
||||
bool FuzzMe(const ubyte* data, size_t dataSize)
|
||||
{
|
||||
// CHECK: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// CHECK: call {{.*}}_sanitizer_cov_trace_cmp
|
||||
|
||||
return dataSize >= 3 &&
|
||||
data[0] == 'F' &&
|
||||
data[1] == 'U' &&
|
||||
data[2] == 'Z' &&
|
||||
data[3] == 'Z'; // :‑<
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{.*}} @{{.*}}allocInt
|
||||
// wASAN-LABEL: define{{.*}} @{{.*}}allocInt
|
||||
void allocInt() {
|
||||
// CHECK: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// wASAN: call {{.*}}_asan_stack_malloc
|
||||
int[10] a;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{.*}} @{{.*}}foo
|
||||
// wASAN-LABEL: define{{.*}} @{{.*}}foo
|
||||
void foo(int function() a) {
|
||||
// CHECK: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// CHECK: call void @__sanitizer_cov_trace_pc_indir
|
||||
a();
|
||||
}
|
10
tests/sanitizers/fsanitize_thread.d
Normal file
10
tests/sanitizers/fsanitize_thread.d
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Test basic ThreadSanitizer functionality
|
||||
|
||||
// RUN: %ldc -c -output-ll -g -fsanitize=thread -of=%t.ll %s && FileCheck %s < %t.ll
|
||||
|
||||
// CHECK-LABEL: define {{.*}}D16fsanitize_thread3foo
|
||||
int foo(int i) {
|
||||
// CHECK: call {{.*}}_tsan_func_entry
|
||||
return i + 1;
|
||||
// CHECK: ret i
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue