filcab created this revision.
filcab added a reviewer: rsmith.
filcab added a subscriber: cfe-commits.

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.

http://reviews.llvm.org/D19666

Files:
  docs/UndefinedBehaviorSanitizer.rst
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CGExpr.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/ubsan-strip-path-components.cpp
  test/Driver/fubsan-strip-path-components.cpp

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"
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: 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: 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/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<llvm::GlobalVariable>(FilenameGV.getPointer()));
     Filename = FilenameGV.getPointer();
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: 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<f_clang_Group>, Flags<[CC1Option]>, MetaVarName<"<number>">,
+  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: 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
 ================
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to