forked from OSchip/llvm-project
Add sanitizer blacklists to the rules generated with -M/-MM/-MD/-MMD.
Summary: Clang sanitizers, such as AddressSanitizer, ThreadSanitizer, MemorySanitizer, Control Flow Integrity and others, use blacklists to specify which types / functions should not be instrumented to avoid false positives or suppress known failures. This change adds the blacklist filenames to the list of dependencies of the rules, generated with -M/-MM/-MD/-MMD. This lets CMake/Ninja recognize that certain C/C++/ObjC files need to be recompiled (if a blacklist is updated). Reviewers: pcc Subscribers: rsmith, honggyu.kim, pcc, cfe-commits Differential Revision: http://reviews.llvm.org/D11968 llvm-svn: 244867
This commit is contained in:
parent
1142f83ce2
commit
1193f2cbc0
|
@ -47,6 +47,9 @@ public:
|
|||
/// must contain at least one entry.
|
||||
std::vector<std::string> Targets;
|
||||
|
||||
/// A list of filenames to be used as extra dependencies for every target.
|
||||
std::vector<std::string> ExtraDeps;
|
||||
|
||||
/// \brief The file to write GraphViz-formatted header dependencies to.
|
||||
std::string DOTOutputFile;
|
||||
|
||||
|
|
|
@ -148,6 +148,9 @@ public:
|
|||
/// AttachHeaderIncludeGen - Create a header include list generator, and attach
|
||||
/// it to the given preprocessor.
|
||||
///
|
||||
/// \param ExtraHeaders - If not empty, will write the header filenames, just
|
||||
/// like they were included during a regular preprocessing. Useful for
|
||||
/// implicit include dependencies, like sanitizer blacklists.
|
||||
/// \param ShowAllHeaders - If true, show all header information instead of just
|
||||
/// headers following the predefines buffer. This is useful for making sure
|
||||
/// includes mentioned on the command line are also reported, but differs from
|
||||
|
@ -156,7 +159,9 @@ public:
|
|||
/// information to, instead of writing to stderr.
|
||||
/// \param ShowDepth - Whether to indent to show the nesting of the includes.
|
||||
/// \param MSStyle - Whether to print in cl.exe /showIncludes style.
|
||||
void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false,
|
||||
void AttachHeaderIncludeGen(Preprocessor &PP,
|
||||
const std::vector<std::string> &ExtraHeaders,
|
||||
bool ShowAllHeaders = false,
|
||||
StringRef OutputPath = "",
|
||||
bool ShowDepth = true, bool MSStyle = false);
|
||||
|
||||
|
|
|
@ -354,17 +354,19 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
|
|||
|
||||
// Handle generating header include information, if requested.
|
||||
if (DepOpts.ShowHeaderIncludes)
|
||||
AttachHeaderIncludeGen(*PP);
|
||||
AttachHeaderIncludeGen(*PP, DepOpts.ExtraDeps);
|
||||
if (!DepOpts.HeaderIncludeOutputFile.empty()) {
|
||||
StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
|
||||
if (OutputPath == "-")
|
||||
OutputPath = "";
|
||||
AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
|
||||
AttachHeaderIncludeGen(*PP, DepOpts.ExtraDeps,
|
||||
/*ShowAllHeaders=*/true, OutputPath,
|
||||
/*ShowDepth=*/false);
|
||||
}
|
||||
|
||||
if (DepOpts.PrintShowIncludes) {
|
||||
AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/false, /*OutputPath=*/"",
|
||||
AttachHeaderIncludeGen(*PP, DepOpts.ExtraDeps,
|
||||
/*ShowAllHeaders=*/false, /*OutputPath=*/"",
|
||||
/*ShowDepth=*/true, /*MSStyle=*/true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -705,6 +705,10 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
|
|||
Args.getLastArgValue(OPT_module_dependency_dir);
|
||||
if (Args.hasArg(OPT_MV))
|
||||
Opts.OutputFormat = DependencyOutputFormat::NMake;
|
||||
// Add sanitizer blacklists as extra dependencies.
|
||||
// They won't be discovered by the regular preprocessor, so
|
||||
// we let make / ninja to know about this implicit dependency.
|
||||
Opts.ExtraDeps = Args.getAllArgValues(OPT_fsanitize_blacklist);
|
||||
}
|
||||
|
||||
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||
|
|
|
@ -182,7 +182,11 @@ public:
|
|||
AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
|
||||
SeenMissingHeader(false),
|
||||
IncludeModuleFiles(Opts.IncludeModuleFiles),
|
||||
OutputFormat(Opts.OutputFormat) {}
|
||||
OutputFormat(Opts.OutputFormat) {
|
||||
for (auto ExtraDep : Opts.ExtraDeps) {
|
||||
AddFilename(ExtraDep);
|
||||
}
|
||||
}
|
||||
|
||||
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType,
|
||||
|
|
|
@ -46,7 +46,36 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
|
||||
static void PrintHeaderInfo(raw_ostream *OutputFile, const char* Filename,
|
||||
bool ShowDepth, unsigned CurrentIncludeDepth,
|
||||
bool MSStyle) {
|
||||
// Write to a temporary string to avoid unnecessary flushing on errs().
|
||||
SmallString<512> Pathname(Filename);
|
||||
if (!MSStyle)
|
||||
Lexer::Stringify(Pathname);
|
||||
|
||||
SmallString<256> Msg;
|
||||
if (MSStyle)
|
||||
Msg += "Note: including file:";
|
||||
|
||||
if (ShowDepth) {
|
||||
// The main source file is at depth 1, so skip one dot.
|
||||
for (unsigned i = 1; i != CurrentIncludeDepth; ++i)
|
||||
Msg += MSStyle ? ' ' : '.';
|
||||
|
||||
if (!MSStyle)
|
||||
Msg += ' ';
|
||||
}
|
||||
Msg += Pathname;
|
||||
Msg += '\n';
|
||||
|
||||
OutputFile->write(Msg.data(), Msg.size());
|
||||
OutputFile->flush();
|
||||
}
|
||||
|
||||
void clang::AttachHeaderIncludeGen(Preprocessor &PP,
|
||||
const std::vector<std::string> &ExtraHeaders,
|
||||
bool ShowAllHeaders,
|
||||
StringRef OutputPath, bool ShowDepth,
|
||||
bool MSStyle) {
|
||||
raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs();
|
||||
|
@ -69,6 +98,14 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
|
|||
}
|
||||
}
|
||||
|
||||
// Print header info for extra headers, pretending they were discovered
|
||||
// by the regular preprocessor. The primary use case is to support
|
||||
// proper generation of Make / Ninja file dependencies for implicit includes,
|
||||
// such as sanitizer blacklists. It's only important for cl.exe
|
||||
// compatibility, the GNU way to generate rules is -M / -MM / -MD / -MMD.
|
||||
for (auto Header : ExtraHeaders) {
|
||||
PrintHeaderInfo(OutputFile, Header.c_str(), ShowDepth, 2, MSStyle);
|
||||
}
|
||||
PP.addPPCallbacks(llvm::make_unique<HeaderIncludesCallback>(&PP,
|
||||
ShowAllHeaders,
|
||||
OutputFile,
|
||||
|
@ -112,27 +149,7 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc,
|
|||
// Dump the header include information we are past the predefines buffer or
|
||||
// are showing all headers.
|
||||
if (ShowHeader && Reason == PPCallbacks::EnterFile) {
|
||||
// Write to a temporary string to avoid unnecessary flushing on errs().
|
||||
SmallString<512> Filename(UserLoc.getFilename());
|
||||
if (!MSStyle)
|
||||
Lexer::Stringify(Filename);
|
||||
|
||||
SmallString<256> Msg;
|
||||
if (MSStyle)
|
||||
Msg += "Note: including file:";
|
||||
|
||||
if (ShowDepth) {
|
||||
// The main source file is at depth 1, so skip one dot.
|
||||
for (unsigned i = 1; i != CurrentIncludeDepth; ++i)
|
||||
Msg += MSStyle ? ' ' : '.';
|
||||
|
||||
if (!MSStyle)
|
||||
Msg += ' ';
|
||||
}
|
||||
Msg += Filename;
|
||||
Msg += '\n';
|
||||
|
||||
OutputFile->write(Msg.data(), Msg.size());
|
||||
OutputFile->flush();
|
||||
PrintHeaderInfo(OutputFile, UserLoc.getFilename(),
|
||||
ShowDepth, CurrentIncludeDepth, MSStyle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,16 @@
|
|||
// RUN: cd a/b
|
||||
// RUN: %clang -MD -MF - %s -fsyntax-only -I ./ | FileCheck -check-prefix=CHECK-SIX %s
|
||||
// CHECK-SIX: {{ }}x.h
|
||||
|
||||
// RUN: echo "fun:foo" > %t.blacklist
|
||||
// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=cfi-vcall -flto -fsanitize-blacklist=%t.blacklist -I ./ | FileCheck -check-prefix=CHECK-SEVEN %s
|
||||
// CHECK-SEVEN: .blacklist
|
||||
// CHECK-SEVEN: {{ }}x.h
|
||||
// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=address -flto -I . | FileCheck -check-prefix=CHECK-EIGHT %s
|
||||
// CHECK-EIGHT: asan_blacklist.txt
|
||||
// CHECK-EIGHT: {{ }}x.h
|
||||
// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=address -flto -I . -fno-sanitize-blacklist | FileCheck -check-prefix=CHECK-NINE %s
|
||||
// CHECK-NINE-NOT: asan_blacklist.txt
|
||||
// CHECK-NINE: {{ }}x.h
|
||||
#ifndef INCLUDE_FLAG_TEST
|
||||
#include <x.h>
|
||||
#endif
|
||||
|
|
|
@ -13,4 +13,12 @@
|
|||
// MS: Note: including file: {{.*test2.h}}
|
||||
// MS-NOT: Note
|
||||
|
||||
// RUN: echo "fun:foo" > %t.blacklist
|
||||
// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t.blacklist -E --show-includes -o %t.out %s > %t.stdout
|
||||
// RUN: FileCheck --check-prefix=MS-BLACKLIST < %t.stdout %s
|
||||
// MS-BLACKLIST: Note: including file: {{.*\.blacklist}}
|
||||
// MS-BLACKLIST: Note: including file: {{.*test.h}}
|
||||
// MS-BLACKLIST: Note: including file: {{.*test2.h}}
|
||||
// MS-BLACKLIST-NOT: Note
|
||||
|
||||
#include "Inputs/test.h"
|
||||
|
|
Loading…
Reference in New Issue