Index: docs/UndefinedBehaviorSanitizer.rst =================================================================== --- docs/UndefinedBehaviorSanitizer.rst +++ docs/UndefinedBehaviorSanitizer.rst @@ -228,6 +228,26 @@ 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. option +``-fubsan-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 ``-fubsan-strip-path-components=0``): ``/code/library/file.cpp`` +* ``-fubsan-strip-path-components=1``: ``code/library/file.cpp`` +* ``-fubsan-strip-path-components=2``: ``library/file.cpp`` +* ``-fubsan-strip-path-components=-1``: ``file.cpp`` +* ``-fubsan-strip-path-components=-2``: ``library/file.cpp`` + More Information ================ Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1099,6 +1099,10 @@ HelpText<"Warn if a function definition returns or accepts an object larger " "in bytes than a given value">, Flags<[HelpHidden]>; def Wlarge_by_value_copy_EQ : Joined<["-"], "Wlarge-by-value-copy=">, Flags<[CC1Option]>; +def fubsan_strip_path_components_EQ : Joined<["-"], "fubsan-strip-path-components=">, + Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Strip (or keep only, if negative) a given number of path components " + "when emitting check metadata.">; // These "special" warning flags are effectively processed as f_Group flags by the driver: // Just silence warnings about -Wlarger-than for now. Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -218,6 +218,10 @@ /// 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 Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ 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,38 @@ 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) { + int PathComponentsToKeep = -PathComponentsToStrip; + if (PathComponentsToKeep) { + auto I = llvm::sys::path::rbegin(FilenameString); + auto E = llvm::sys::path::rend(FilenameString); + while (I != E && --PathComponentsToKeep) + ++I; + + if (I != E) + FilenameString = *I; + else + FilenameString = llvm::sys::path::filename(FilenameString); + } + } 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 = *I; + else + FilenameString = llvm::sys::path::filename(FilenameString); + } + + // We're calling .data() to get the full string from this component onwards. + // Not just the current component. + auto FilenameGV = CGM.GetAddrOfConstantCString(FilenameString.data(), ".src"); CGM.getSanitizerMetadata()->disableSanitizerForGlobal( cast(FilenameGV.getPointer())); Filename = FilenameGV.getPointer(); Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -5621,6 +5621,9 @@ if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ)) A->render(Args, CmdArgs); + if (Arg *A = Args.getLastArg(options::OPT_fubsan_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, Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -783,6 +783,9 @@ Opts.CudaGpuBinaryFileNames = Args.getAllArgValues(OPT_fcuda_include_gpubinary); + Opts.EmitCheckPathComponentsToStrip = + getLastArgIntValue(Args, OPT_fubsan_strip_path_components_EQ, 0, Diags); + return Success; } Index: test/CodeGen/ubsan-strip-path-components.cpp =================================================================== --- /dev/null +++ test/CodeGen/ubsan-strip-path-components.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - | FileCheck %s -check-prefix=REGULAR -check-prefix=CHECK +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - -fubsan-strip-path-components=0 | FileCheck %s -check-prefix=REGULAR -check-prefix=CHECK +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - -fubsan-strip-path-components=2 | FileCheck %s -check-prefix=REMOVE-FIRST-TWO -check-prefix=CHECK +// We can't easily check stripping one or two levels. + +// Try to strip too much: +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - -fubsan-strip-path-components=-99999 | FileCheck %s -check-prefix=LAST-ONLY +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - -fubsan-strip-path-components=99999 | FileCheck %s -check-prefix=LAST-ONLY + +// Check stripping from the file name +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - -fubsan-strip-path-components=-2 | FileCheck %s -check-prefix=LAST-TWO +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - -fubsan-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.CodeGen.ubsan-strip-path-components\.cpp}}\00", align 1 + +// We have an optional space in the regex in the next line because the }} eagerly closes the regex +// REMOVE-FIRST-TWO: @[[STR:[0-9.a-zA-Z_]+]] = private unnamed_addr constant [{{.*}} x i8] c"{{([^\\/]*)?(.[^\\/]+).}}[[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{{.}}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(); +} Index: test/Driver/fubsan-strip-path-components.cpp =================================================================== --- /dev/null +++ test/Driver/fubsan-strip-path-components.cpp @@ -0,0 +1,2 @@ +// RUN: %clang %s -### -o %t.o -fubsan-strip-path-components=42 2>&1 | FileCheck %s +// CHECK: "-fubsan-strip-path-components=42"