From 889fcf316bb355bf9dbd4cc33cdd78deaf6ad4e7 Mon Sep 17 00:00:00 2001 From: Filipe Cabecinhas Date: Thu, 12 May 2016 16:51:36 +0000 Subject: [PATCH] [ubsan] Add -fsanitize-undefined-strip-path-components=N Summary: This option allows the user to control how much of the file name is emitted by UBSan. Tuning this option allows one to save space in the resulting binary, which is helpful for restricted execution environments. With a positive N, UBSan skips the first N path components. With a negative N, UBSan only keeps the last N path components. Reviewers: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D19666 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269309 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/UndefinedBehaviorSanitizer.rst | 20 ++++++++++++++ include/clang/Driver/Options.td | 4 +++ include/clang/Frontend/CodeGenOptions.def | 4 +++ lib/CodeGen/CGExpr.cpp | 29 +++++++++++++++++++- lib/Driver/Tools.cpp | 4 +++ lib/Frontend/CompilerInvocation.cpp | 3 ++ test/CodeGen/ubsan-strip-path-components.cpp | 29 ++++++++++++++++++++ test/Driver/fubsan-strip-path-components.cpp | 2 ++ 8 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/ubsan-strip-path-components.cpp create mode 100644 test/Driver/fubsan-strip-path-components.cpp diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst index db1325cc02..7babb96a65 100644 --- a/docs/UndefinedBehaviorSanitizer.rst +++ b/docs/UndefinedBehaviorSanitizer.rst @@ -228,6 +228,26 @@ UndefinedBehaviorSanitizer is available on selected platforms starting from LLVM 3.3. The test suite is integrated into the CMake build and can be run with ``check-ubsan`` command. +Additional Configuration +======================== + +UndefinedBehaviorSanitizer adds static check data for each check unless it is +in trap mode. This check data includes the full file name. The option +``-fsanitize-undefined-strip-path-components=N`` can be used to trim this +information. If ``N`` is positive, file information emitted by +UndefinedBehaviorSanitizer will drop the first ``N`` components from the file +path. If ``N`` is negative, the last ``N`` components will be kept. + +Example +------- + +For a file called ``/code/library/file.cpp``, here is what would be emitted: +* Default (No flag, or ``-fsanitize-undefined-strip-path-components=0``): ``/code/library/file.cpp`` +* ``-fsanitize-undefined-strip-path-components=1``: ``code/library/file.cpp`` +* ``-fsanitize-undefined-strip-path-components=2``: ``library/file.cpp`` +* ``-fsanitize-undefined-strip-path-components=-1``: ``file.cpp`` +* ``-fsanitize-undefined-strip-path-components=-2``: ``library/file.cpp`` + More Information ================ diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 602e8fa7de..4dd092599a 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -677,6 +677,10 @@ def fsanitize_stats : Flag<["-"], "fsanitize-stats">, def fno_sanitize_stats : Flag<["-"], "fno-sanitize-stats">, Group, Flags<[CC1Option]>, HelpText<"Disable sanitizer statistics gathering.">; +def fsanitize_undefined_strip_path_components_EQ : Joined<["-"], "fsanitize-undefined-strip-path-components=">, + Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Strip (or keep only, if negative) a given number of path components " + "when emitting check metadata.">; def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index d0d4f7a693..2e2344a8e4 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -225,6 +225,10 @@ ENUM_CODEGENOPT(VecLib, VectorLibrary, 1, NoLibrary) /// The default TLS model to use. ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) +/// Number of path components to strip when emitting checks. (0 == full +/// filename) +VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0) + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 3ecd8e3f0f..8896eb4db1 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Path.h" #include "llvm/Transforms/Utils/SanitizerStats.h" using namespace clang; @@ -2367,7 +2368,33 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) { PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc); if (PLoc.isValid()) { - auto FilenameGV = CGM.GetAddrOfConstantCString(PLoc.getFilename(), ".src"); + StringRef FilenameString = PLoc.getFilename(); + + int PathComponentsToStrip = + CGM.getCodeGenOpts().EmitCheckPathComponentsToStrip; + if (PathComponentsToStrip < 0) { + assert(PathComponentsToStrip != INT_MIN); + int PathComponentsToKeep = -PathComponentsToStrip; + auto I = llvm::sys::path::rbegin(FilenameString); + auto E = llvm::sys::path::rend(FilenameString); + while (I != E && --PathComponentsToKeep) + ++I; + + FilenameString = FilenameString.substr(I - E); + } else if (PathComponentsToStrip > 0) { + auto I = llvm::sys::path::begin(FilenameString); + auto E = llvm::sys::path::end(FilenameString); + while (I != E && PathComponentsToStrip--) + ++I; + + if (I != E) + FilenameString = + FilenameString.substr(I - llvm::sys::path::begin(FilenameString)); + else + FilenameString = llvm::sys::path::filename(FilenameString); + } + + auto FilenameGV = CGM.GetAddrOfConstantCString(FilenameString, ".src"); CGM.getSanitizerMetadata()->disableSanitizerForGlobal( cast(FilenameGV.getPointer())); Filename = FilenameGV.getPointer(); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 98c0d1deeb..5da1fd6c96 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -5607,6 +5607,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ)) A->render(Args, CmdArgs); + if (Arg *A = Args.getLastArg( + options::OPT_fsanitize_undefined_strip_path_components_EQ)) + A->render(Args, CmdArgs); + // -fdollars-in-identifiers default varies depending on platform and // language; only pass if specified. if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index f11188d0ff..8e93ff1a4b 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -823,6 +823,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.Backchain = Args.hasArg(OPT_mbackchain); + Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue( + Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags); + return Success; } diff --git a/test/CodeGen/ubsan-strip-path-components.cpp b/test/CodeGen/ubsan-strip-path-components.cpp new file mode 100644 index 0000000000..7a95324d12 --- /dev/null +++ b/test/CodeGen/ubsan-strip-path-components.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - | FileCheck %s -check-prefix=REGULAR -check-prefix=CHECK +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=0 | FileCheck %s -check-prefix=REGULAR -check-prefix=CHECK +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=2 | FileCheck %s -check-prefix=REMOVE-FIRST-TWO -check-prefix=CHECK + +// Try to strip too much: +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=-99999 | FileCheck %s -check-prefix=REGULAR +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=99999 | FileCheck %s -check-prefix=LAST-ONLY + +// Check stripping from the file name +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=-2 | FileCheck %s -check-prefix=LAST-TWO +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -o - -fsanitize-undefined-strip-path-components=-1 | FileCheck %s -check-prefix=LAST-ONLY + +// REGULAR: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*test(.|\\5C)CodeGen(.|\\5C)ubsan-strip-path-components\.cpp}}\00", align 1 + +// First path component: "/" or "$drive_letter:", then a name, or '\5C' on Windows +// REMOVE-FIRST-TWO: @[[STR:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"{{(.:|/)([^\\/]*(/|\\5C))}}[[REST:.*ubsan-strip-path-components\.cpp]]\00", align 1 +// REMOVE-FIRST-TWO: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"[[REST]]\00", align 1 + +// LAST-TWO: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"CodeGen{{/|\\5C}}ubsan-strip-path-components.cpp\00", align 1 +// LAST-ONLY: @[[SRC:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"ubsan-strip-path-components.cpp\00", align 1 + +// CHECK: @[[STATIC_DATA:[0-9.a-zA-Z_]+]] = private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 } } { { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 [[@LINE+6]], i32 3 } } +void g(const char *); +void f() { + // CHECK-LABEL: @_Z1fv( + g(__FILE__); + // CHECK: call void @__ubsan_handle_builtin_unreachable(i8* bitcast ({ { [{{.*}} x i8]*, i32, i32 } }* @[[STATIC_DATA]] to i8*)) {{.*}}, !nosanitize + __builtin_unreachable(); +} diff --git a/test/Driver/fubsan-strip-path-components.cpp b/test/Driver/fubsan-strip-path-components.cpp new file mode 100644 index 0000000000..130024142f --- /dev/null +++ b/test/Driver/fubsan-strip-path-components.cpp @@ -0,0 +1,2 @@ +// RUN: %clang %s -### -o %t.o -fsanitize-undefined-strip-path-components=42 2>&1 | FileCheck %s +// CHECK: "-fsanitize-undefined-strip-path-components=42" -- 2.40.0