melver updated this revision to Diff 449671.
melver marked 4 inline comments as done.
melver added a comment.
Address comments.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D130888/new/
https://reviews.llvm.org/D130888
Files:
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Basic/CodeGenOptions.h
clang/include/clang/Driver/Options.td
clang/include/clang/Driver/SanitizerArgs.h
clang/lib/CodeGen/BackendUtil.cpp
clang/lib/Driver/SanitizerArgs.cpp
clang/test/Driver/fsanitize-metadata.c
Index: clang/test/Driver/fsanitize-metadata.c
===================================================================
--- /dev/null
+++ clang/test/Driver/fsanitize-metadata.c
@@ -0,0 +1,34 @@
+// RUN: %clang --target=x86_64-linux-gnu \
+// RUN: -fexperimental-sanitize-metadata=all \
+// RUN: -fno-experimental-sanitize-metadata=all %s -### 2>&1 | FileCheck %s
+// CHECK-NOT: -fexperimental-sanitize-metadata
+
+// RUN: %clang --target=x86_64-linux-gnu -fexperimental-sanitize-metadata=bad_arg %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-INVALID %s
+// CHECK-INVALID: error: unsupported argument 'bad_arg' to option '-fexperimental-sanitize-metadata='
+
+// RUN: %clang --target=x86_64-linux-gnu -fexperimental-sanitize-metadata=covered %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-COVERED %s
+// RUN: %clang --target=x86_64-linux-gnu \
+// RUN: -fexperimental-sanitize-metadata=atomics \
+// RUN: -fno-experimental-sanitize-metadata=atomics \
+// RUN: -fexperimental-sanitize-metadata=covered %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-COVERED %s
+// CHECK-COVERED: "-fexperimental-sanitize-metadata=covered"
+// CHECK-COVERED-NOT: "-fexperimental-sanitize-metadata=atomics"
+
+// RUN: %clang --target=x86_64-linux-gnu -fexperimental-sanitize-metadata=atomics %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-ATOMICS %s
+// CHECK-ATOMICS: "-fexperimental-sanitize-metadata=atomics"
+
+// RUN: %clang --target=x86_64-linux-gnu \
+// RUN: -fexperimental-sanitize-metadata=covered,atomics %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-ALL %s
+// RUN: %clang --target=x86_64-linux-gnu \
+// RUN: -fexperimental-sanitize-metadata=covered \
+// RUN: -fexperimental-sanitize-metadata=atomics %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-ALL %s
+// RUN: %clang --target=x86_64-linux-gnu -fexperimental-sanitize-metadata=all %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-ALL %s
+// CHECK-ALL: "-fexperimental-sanitize-metadata=covered"
+// CHECK-ALL: "-fexperimental-sanitize-metadata=atomics"
Index: clang/lib/Driver/SanitizerArgs.cpp
===================================================================
--- clang/lib/Driver/SanitizerArgs.cpp
+++ clang/lib/Driver/SanitizerArgs.cpp
@@ -98,6 +98,11 @@
CoverageTraceStores = 1 << 17,
};
+enum BinaryMetadataFeature {
+ BinaryMetadataCovered = 1 << 0,
+ BinaryMetadataAtomics = 1 << 1,
+};
+
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
/// invalid components. Returns a SanitizerMask.
static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
@@ -108,6 +113,11 @@
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
bool DiagnoseErrors);
+/// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid
+/// components. Returns OR of members of \c BinaryMetadataFeature enumeration.
+static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
+ bool DiagnoseErrors);
+
/// Produce an argument string from ArgList \p Args, which shows how it
/// provides some sanitizer kind from \p Mask. For example, the argument list
/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
@@ -825,6 +835,22 @@
DiagnoseErrors);
}
+ // Parse -f(no-)?sanitize-metadata.
+ for (const auto *Arg :
+ Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
+ options::OPT_fno_experimental_sanitize_metadata_EQ)) {
+ if (Arg->getOption().matches(
+ options::OPT_fexperimental_sanitize_metadata_EQ)) {
+ Arg->claim();
+ BinaryMetadataFeatures |=
+ parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
+ } else {
+ Arg->claim();
+ BinaryMetadataFeatures &=
+ ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
+ }
+ }
+
SharedRuntime =
Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
@@ -1086,6 +1112,17 @@
addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
CoverageIgnorelistFiles);
+ // Translate available BinaryMetadataFeatures to corresponding clang-cc1
+ // flags. Does not depend on any other sanitizers.
+ const std::pair<int, std::string> BinaryMetadataFlags[] = {
+ std::make_pair(BinaryMetadataCovered, "covered"),
+ std::make_pair(BinaryMetadataAtomics, "atomics")};
+ for (const auto &F : BinaryMetadataFlags) {
+ if (BinaryMetadataFeatures & F.first)
+ CmdArgs.push_back(
+ Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
+ }
+
if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
// Instruct the code generator to embed linker directives in the object file
// that cause the required runtime libraries to be linked.
@@ -1332,6 +1369,28 @@
return Features;
}
+int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
+ bool DiagnoseErrors) {
+ assert(
+ A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
+ A->getOption().matches(
+ options::OPT_fno_experimental_sanitize_metadata_EQ));
+ int Features = 0;
+ for (int i = 0, n = A->getNumValues(); i != n; ++i) {
+ const char *Value = A->getValue(i);
+ int F = llvm::StringSwitch<int>(Value)
+ .Case("covered", BinaryMetadataCovered)
+ .Case("atomics", BinaryMetadataAtomics)
+ .Case("all", ~0)
+ .Default(0);
+ if (F == 0 && DiagnoseErrors)
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ Features |= F;
+ }
+ return Features;
+}
+
std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
SanitizerMask Mask) {
for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -73,6 +73,7 @@
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
+#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
@@ -218,6 +219,14 @@
return Opts;
}
+static SanitizerBinaryMetadataOptions
+getSanitizerBinaryMetadataOptions(const CodeGenOptions &CGOpts) {
+ SanitizerBinaryMetadataOptions Opts;
+ Opts.Covered = CGOpts.SanitizeBinaryMetadataCovered;
+ Opts.Atomics = CGOpts.SanitizeBinaryMetadataAtomics;
+ return Opts;
+}
+
// Check if ASan should use GC-friendly instrumentation for globals.
// First of all, there is no point if -fdata-sections is off (expect for MachO,
// where this is not a factor). Also, on ELF this feature requires an assembler
@@ -632,6 +641,11 @@
CodeGenOpts.SanitizeCoverageIgnorelistFiles));
}
+ if (CodeGenOpts.hasSanitizeBinaryMetadata()) {
+ MPM.addPass(ModuleSanitizerBinaryMetadataPass(
+ getSanitizerBinaryMetadataOptions(CodeGenOpts)));
+ }
+
auto MSanPass = [&](SanitizerMask Mask, bool CompileKernel) {
if (LangOpts.Sanitize.has(Mask)) {
int TrackOrigins = CodeGenOpts.SanitizeMemoryTrackOrigins;
Index: clang/include/clang/Driver/SanitizerArgs.h
===================================================================
--- clang/include/clang/Driver/SanitizerArgs.h
+++ clang/include/clang/Driver/SanitizerArgs.h
@@ -31,6 +31,7 @@
std::vector<std::string> CoverageAllowlistFiles;
std::vector<std::string> CoverageIgnorelistFiles;
int CoverageFeatures = 0;
+ int BinaryMetadataFeatures = 0;
int MsanTrackOrigins = 0;
bool MsanUseAfterDtor = true;
bool MsanParamRetval = false;
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1683,6 +1683,12 @@
Group<f_clang_Group>, Flags<[CoreOption, HelpHidden]>,
Alias<fsanitize_coverage_ignorelist>,
HelpText<"Deprecated, use -fsanitize-coverage-ignorelist= instead">;
+def fexperimental_sanitize_metadata_EQ : CommaJoined<["-"], "fexperimental-sanitize-metadata=">,
+ Group<f_clang_Group>,
+ HelpText<"Specify the type of metadata to emit for binary analysis sanitizers">;
+def fno_experimental_sanitize_metadata_EQ : CommaJoined<["-"], "fno-experimental-sanitize-metadata=">,
+ Group<f_clang_Group>, Flags<[CoreOption, NoXarchOption]>,
+ HelpText<"Disable emitting metadata for binary analysis sanitizers">;
def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">,
Group<f_clang_Group>,
HelpText<"Enable origins tracking in MemorySanitizer">,
@@ -5493,6 +5499,14 @@
: Flag<["-"], "fsanitize-coverage-trace-stores">,
HelpText<"Enable tracing of stores">,
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceStores">>;
+def fexperimental_sanitize_metadata_EQ_covered
+ : Flag<["-"], "fexperimental-sanitize-metadata=covered">,
+ HelpText<"Emit PCs for code covered with binary analysis sanitizers">,
+ MarshallingInfoFlag<CodeGenOpts<"SanitizeBinaryMetadataCovered">>;
+def fexperimental_sanitize_metadata_EQ_atomics
+ : Flag<["-"], "fexperimental-sanitize-metadata=atomics">,
+ HelpText<"Emit PCs for atomic operations used by binary analysis sanitizers">,
+ MarshallingInfoFlag<CodeGenOpts<"SanitizeBinaryMetadataAtomics">>;
def fpatchable_function_entry_offset_EQ
: Joined<["-"], "fpatchable-function-entry-offset=">, MetaVarName<"<M>">,
HelpText<"Generate M NOPs before function entry">,
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -485,6 +485,11 @@
SanitizeCoverageTraceCmp || SanitizeCoverageTraceLoads ||
SanitizeCoverageTraceStores;
}
+
+ // Check if any one of SanitizeBinaryMetadata* is enabled.
+ bool hasSanitizeBinaryMetadata() const {
+ return SanitizeBinaryMetadataCovered || SanitizeBinaryMetadataAtomics;
+ }
};
} // end namespace clang
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -284,6 +284,8 @@
CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing
CODEGENOPT(SanitizeCoverageTraceLoads, 1, 0) ///< Enable tracing of loads.
CODEGENOPT(SanitizeCoverageTraceStores, 1, 0) ///< Enable tracing of stores.
+CODEGENOPT(SanitizeBinaryMetadataCovered, 1, 0) ///< Emit PCs for covered functions.
+CODEGENOPT(SanitizeBinaryMetadataAtomics, 1, 0) ///< Emit PCs for atomic operations.
CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers.
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits