melver created this revision. melver added reviewers: dvyukov, vitalybuka. Herald added subscribers: Enna1, ormris, hiraditya. Herald added a project: All. melver requested review of this revision. Herald added subscribers: llvm-commits, cfe-commits, MaskRay. Herald added projects: clang, LLVM.
For large projects it will be required to opt out entire subdirectories. In the absence of fine-grained control over the flags passed via the build system, introduce -fexperimental-sanitize-metadata-ignorelist=. The format is identical to other sanitizer ignore lists, and its effect will be to simply not instrument either functions or entire modules based on the rules in the ignore list file. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D143664 Files: clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Basic/DiagnosticDriverKinds.td clang/include/clang/Driver/Options.td clang/include/clang/Driver/SanitizerArgs.h clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp clang/test/CodeGen/sanitize-metadata-ignorelist.c clang/test/Driver/fsanitize-metadata-ignorelist.c llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
Index: llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp @@ -38,13 +38,16 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include <array> #include <cstdint> +#include <memory> using namespace llvm; @@ -121,9 +124,11 @@ class SanitizerBinaryMetadata { public: - SanitizerBinaryMetadata(Module &M, SanitizerBinaryMetadataOptions Opts) + SanitizerBinaryMetadata(Module &M, SanitizerBinaryMetadataOptions Opts, + std::unique_ptr<SpecialCaseList> Ignorelist) : Mod(M), Options(transformOptionsFromCl(std::move(Opts))), - TargetTriple(M.getTargetTriple()), IRB(M.getContext()) { + Ignorelist(std::move(Ignorelist)), TargetTriple(M.getTargetTriple()), + IRB(M.getContext()) { // FIXME: Make it work with other formats. assert(TargetTriple.isOSBinFormatELF() && "ELF only"); } @@ -168,6 +173,7 @@ Module &Mod; const SanitizerBinaryMetadataOptions Options; + std::unique_ptr<SpecialCaseList> Ignorelist; const Triple TargetTriple; IRBuilder<> IRB; BumpPtrAllocator Alloc; @@ -243,6 +249,8 @@ return; if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; + if (Ignorelist && Ignorelist->inSection("metadata", "fun", F.getName())) + return; // Don't touch available_externally functions, their actual body is elsewhere. if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return; @@ -455,12 +463,20 @@ } // namespace SanitizerBinaryMetadataPass::SanitizerBinaryMetadataPass( - SanitizerBinaryMetadataOptions Opts) - : Options(std::move(Opts)) {} + SanitizerBinaryMetadataOptions Opts, ArrayRef<std::string> IgnorelistFiles) + : Options(std::move(Opts)), IgnorelistFiles(std::move(IgnorelistFiles)) {} PreservedAnalyses SanitizerBinaryMetadataPass::run(Module &M, AnalysisManager<Module> &AM) { - SanitizerBinaryMetadata Pass(M, Options); + std::unique_ptr<SpecialCaseList> Ignorelist; + if (!IgnorelistFiles.empty()) { + Ignorelist = SpecialCaseList::createOrDie(IgnorelistFiles, + *vfs::getRealFileSystem()); + if (Ignorelist->inSection("metadata", "src", M.getSourceFileName())) + return PreservedAnalyses::all(); + } + + SanitizerBinaryMetadata Pass(M, Options, std::move(Ignorelist)); if (Pass.run()) return PreservedAnalyses::none(); return PreservedAnalyses::all(); Index: llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h =================================================================== --- llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h +++ llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h @@ -12,6 +12,7 @@ #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERBINARYMETADATA_H #define LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERBINARYMETADATA_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" @@ -50,12 +51,14 @@ : public PassInfoMixin<SanitizerBinaryMetadataPass> { public: explicit SanitizerBinaryMetadataPass( - SanitizerBinaryMetadataOptions Opts = {}); + SanitizerBinaryMetadataOptions Opts = {}, + ArrayRef<std::string> IgnorelistFiles = {}); PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); static bool isRequired() { return true; } private: const SanitizerBinaryMetadataOptions Options; + const ArrayRef<std::string> IgnorelistFiles; }; } // namespace llvm Index: clang/test/Driver/fsanitize-metadata-ignorelist.c =================================================================== --- /dev/null +++ clang/test/Driver/fsanitize-metadata-ignorelist.c @@ -0,0 +1,6 @@ +// RUN: echo "fun:foo" > %t.good +// RUN: echo "fun:bar" > %t.second + +// RUN: %clang -target x86_64-linux-gnu -fexperimental-sanitize-metadata=all -fexperimental-sanitize-metadata-ignorelist=%t.good -fexperimental-sanitize-metadata-ignorelist=%t.second %s -### 2>&1 | FileCheck %s +// RUN: %clang -target aarch64-linux-gnu -fexperimental-sanitize-metadata=all -fexperimental-sanitize-metadata-ignorelist=%t.good -fexperimental-sanitize-metadata-ignorelist=%t.second %s -### 2>&1 | FileCheck %s +// CHECK: -fexperimental-sanitize-metadata-ignorelist={{.*}}.good" "-fexperimental-sanitize-metadata-ignorelist={{.*}}.second Index: clang/test/CodeGen/sanitize-metadata-ignorelist.c =================================================================== --- /dev/null +++ clang/test/CodeGen/sanitize-metadata-ignorelist.c @@ -0,0 +1,55 @@ +// RUN: %clang -O -fexperimental-sanitize-metadata=all -target x86_64-gnu-linux -x c -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALLOW +// RUN: echo "fun:foo" > %t.fun +// RUN: %clang -O -fexperimental-sanitize-metadata=all -fexperimental-sanitize-metadata-ignorelist=%t.fun -target x86_64-gnu-linux -x c -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=FUN +// RUN: echo "src:%s" > %t.src +// RUN: %clang -O -fexperimental-sanitize-metadata=all -fexperimental-sanitize-metadata-ignorelist=%t.src -target x86_64-gnu-linux -x c -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=SRC + +int y; + +// ALLOW-LABEL: define {{[^@]+}}@foo +// ALLOW-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] !pcsections !5 { +// ALLOW-NEXT: entry: +// ALLOW-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @y, i32 1 monotonic, align 4, !pcsections !7 +// ALLOW-NEXT: ret void +// +// FUN-LABEL: define {{[^@]+}}@foo +// FUN-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] { +// FUN-NEXT: entry: +// FUN-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @y, i32 1 monotonic, align 4 +// FUN-NEXT: ret void +// +// SRC-LABEL: define {{[^@]+}}@foo +// SRC-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SRC-NEXT: entry: +// SRC-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @y, i32 1 monotonic, align 4 +// SRC-NEXT: ret void +// +void foo() { + __atomic_fetch_add(&y, 1, __ATOMIC_RELAXED); +} + +// ALLOW-LABEL: define {{[^@]+}}@bar +// ALLOW-SAME: () local_unnamed_addr #[[ATTR0]] !pcsections !5 { +// ALLOW-NEXT: entry: +// ALLOW-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @y, i32 2 monotonic, align 4, !pcsections !7 +// ALLOW-NEXT: ret void +// +// FUN-LABEL: define {{[^@]+}}@bar +// FUN-SAME: () local_unnamed_addr #[[ATTR0]] !pcsections !5 { +// FUN-NEXT: entry: +// FUN-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @y, i32 2 monotonic, align 4, !pcsections !7 +// FUN-NEXT: ret void +// +// SRC-LABEL: define {{[^@]+}}@bar +// SRC-SAME: () local_unnamed_addr #[[ATTR0]] { +// SRC-NEXT: entry: +// SRC-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @y, i32 2 monotonic, align 4 +// SRC-NEXT: ret void +// +void bar() { + __atomic_fetch_add(&y, 2, __ATOMIC_RELAXED); +} + +// ALLOW: __sanitizer_metadata_covered.module_ctor +// FUN: __sanitizer_metadata_covered.module_ctor +// SRC-NOT: __sanitizer_metadata_covered.module_ctor Index: clang/lib/Driver/SanitizerArgs.cpp =================================================================== --- clang/lib/Driver/SanitizerArgs.cpp +++ clang/lib/Driver/SanitizerArgs.cpp @@ -864,6 +864,16 @@ } } + // Parse -fsanitize-metadata-ignorelist option if enabled. + if (BinaryMetadataFeatures) { + parseSpecialCaseListArg( + D, Args, BinaryMetadataIgnorelistFiles, + options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ, + OptSpecifier(), // Cannot clear ignore list, only append. + clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist, + DiagnoseErrors); + } + SharedRuntime = Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan, TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() || @@ -1141,6 +1151,9 @@ CmdArgs.push_back( Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second)); } + addSpecialCaseListOpt(Args, CmdArgs, + "-fexperimental-sanitize-metadata-ignorelist=", + BinaryMetadataIgnorelistFiles); if (TC.getTriple().isOSWindows() && needsUbsanRt()) { // Instruct the code generator to embed linker directives in the object file Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -665,7 +665,8 @@ if (CodeGenOpts.hasSanitizeBinaryMetadata()) { MPM.addPass(SanitizerBinaryMetadataPass( - getSanitizerBinaryMetadataOptions(CodeGenOpts))); + getSanitizerBinaryMetadataOptions(CodeGenOpts), + CodeGenOpts.SanitizeMetadataIgnorelistFiles)); } auto MSanPass = [&](SanitizerMask Mask, bool CompileKernel) { Index: clang/include/clang/Driver/SanitizerArgs.h =================================================================== --- clang/include/clang/Driver/SanitizerArgs.h +++ clang/include/clang/Driver/SanitizerArgs.h @@ -30,6 +30,7 @@ std::vector<std::string> SystemIgnorelistFiles; std::vector<std::string> CoverageAllowlistFiles; std::vector<std::string> CoverageIgnorelistFiles; + std::vector<std::string> BinaryMetadataIgnorelistFiles; int CoverageFeatures = 0; int BinaryMetadataFeatures = 0; int MsanTrackOrigins = 0; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1756,6 +1756,10 @@ def fno_experimental_sanitize_metadata_EQ : CommaJoined<["-"], "fno-experimental-sanitize-metadata=">, Group<f_Group>, Flags<[CoreOption]>, HelpText<"Disable emitting metadata for binary analysis sanitizers">; +def fexperimental_sanitize_metadata_ignorelist_EQ : Joined<["-"], "fexperimental-sanitize-metadata-ignorelist=">, + Group<f_Group>, Flags<[CoreOption]>, + HelpText<"Disable sanitizer metadata for modules and functions that match the provided special case list">, + MarshallingInfoStringVector<CodeGenOpts<"SanitizeMetadataIgnorelistFiles">>; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, Group<f_clang_Group>, HelpText<"Enable origins tracking in MemorySanitizer">, Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -215,6 +215,8 @@ "malformed sanitizer coverage allowlist: '%0'">; def err_drv_malformed_sanitizer_coverage_ignorelist : Error< "malformed sanitizer coverage ignorelist: '%0'">; +def err_drv_malformed_sanitizer_metadata_ignorelist : Error< + "malformed sanitizer metadata ignorelist: '%0'">; def err_drv_unsupported_static_ubsan_darwin : Error< "static UndefinedBehaviorSanitizer runtime is not supported on darwin">; def err_drv_duplicate_config : Error< Index: clang/include/clang/Basic/CodeGenOptions.h =================================================================== --- clang/include/clang/Basic/CodeGenOptions.h +++ clang/include/clang/Basic/CodeGenOptions.h @@ -417,6 +417,11 @@ /// coverage pass should actually not be instrumented. std::vector<std::string> SanitizeCoverageIgnorelistFiles; + /// Path to ignorelist file specifying which objects + /// (files, functions) listed for instrumentation by sanitizer + /// binary metadata pass should not be instrumented. + std::vector<std::string> SanitizeMetadataIgnorelistFiles; + /// Name of the stack usage file (i.e., .su file) if user passes /// -fstack-usage. If empty, it can be implied that -fstack-usage is not /// passed on the command line.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits