[ASan] add new ASan option 'strip_path_prefix' to remove useless prefices from filenames in stack traces

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@161321 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_flags.h b/lib/asan/asan_flags.h
index ca9cf84..5c18a31 100644
--- a/lib/asan/asan_flags.h
+++ b/lib/asan/asan_flags.h
@@ -87,6 +87,8 @@
   // By default, disable core dumper on 64-bit - it makes little sense
   // to dump 16T+ core.
   bool disable_core;
+  // Strips this prefix from file paths in error reports.
+  const char *strip_path_prefix;
 };
 
 Flags *flags();
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index 34324fa..ad51e01 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -35,7 +35,7 @@
     while (1) { }
   }
   if (flags()->sleep_before_dying) {
-    Report("Sleeping for %zd second(s)\n", flags()->sleep_before_dying);
+    Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
     SleepForSeconds(flags()->sleep_before_dying);
   }
   if (flags()->unmap_shadow_on_exit)
@@ -96,6 +96,7 @@
   ParseFlag(str, &f->abort_on_error, "abort_on_error");
   ParseFlag(str, &f->atexit, "atexit");
   ParseFlag(str, &f->disable_core, "disable_core");
+  ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
 }
 
 extern "C" {
@@ -128,6 +129,7 @@
   f->abort_on_error = false;
   f->atexit = false;
   f->disable_core = (__WORDSIZE == 64);
+  f->strip_path_prefix = "";
 
   // Override from user-specified string.
   ParseFlagsFromString(f, __asan_default_options());
diff --git a/lib/asan/asan_stack.cc b/lib/asan/asan_stack.cc
index d6103c2..703cc69 100644
--- a/lib/asan/asan_stack.cc
+++ b/lib/asan/asan_stack.cc
@@ -26,6 +26,13 @@
 
 namespace __asan {
 
+static const char *StripPathPrefix(const char *filepath) {
+  const char *path_prefix = flags()->strip_path_prefix;
+  if (filepath == internal_strstr(filepath, path_prefix))
+    return filepath + internal_strlen(path_prefix);
+  return filepath;
+}
+
 // ----------------------- AsanStackTrace ----------------------------- {{{1
 // PCs in stack traces are actually the return addresses, that is,
 // addresses of the next instructions after the call. That's why we
@@ -46,7 +53,10 @@
       pc = patch_pc(pc);
     char buff[4096];
     ASAN_USE_EXTERNAL_SYMBOLIZER((void*)pc, buff, sizeof(buff));
-    AsanPrintf("  #%zu 0x%zx %s\n", i, pc, buff);
+    // We can't know anything about the string returned by external
+    // symbolizer, but if it starts with filename, try to strip path prefix
+    // from it.
+    AsanPrintf("  #%zu 0x%zx %s\n", i, pc, StripPathPrefix(buff));
   }
 }
 
@@ -72,9 +82,11 @@
           AsanPrintf(" in %s", info.function);
         }
         if (info.file) {
-          AsanPrintf(" %s:%d:%d", info.file, info.line, info.column);
+          AsanPrintf(" %s:%d:%d", StripPathPrefix(info.file), info.line,
+                                  info.column);
         } else if (info.module) {
-          AsanPrintf(" (%s+0x%zx)", info.module, info.module_offset);
+          AsanPrintf(" (%s+0x%zx)", StripPathPrefix(info.module),
+                                    info.module_offset);
         }
         AsanPrintf("\n");
         info.Clear();
@@ -85,8 +97,8 @@
       char filename[4096];
       if (proc_maps.GetObjectNameAndOffset(pc, &offset,
                                            filename, sizeof(filename))) {
-        AsanPrintf("    #%zu 0x%zx (%s+0x%zx)\n", frame_num, pc, filename,
-                                                  offset);
+        AsanPrintf("    #%zu 0x%zx (%s+0x%zx)\n",
+                   frame_num, pc, StripPathPrefix(filename), offset);
       } else {
         AsanPrintf("    #%zu 0x%zx\n", frame_num, pc);
       }
diff --git a/lib/asan/output_tests/test_output.sh b/lib/asan/output_tests/test_output.sh
index 6510043..8dc93eb 100755
--- a/lib/asan/output_tests/test_output.sh
+++ b/lib/asan/output_tests/test_output.sh
@@ -39,6 +39,13 @@
 export ASAN_OPTIONS=""
 rm ./a.out
 
+echo "Checking strip_path_prefix option"
+$CC -g -faddress-sanitizer -O2 $C_TEST.c
+export ASAN_OPTIONS="strip_path_prefix='/'"
+./a.out 2>&1 | $FILE_CHECK $C_TEST.c --check-prefix=CHECKSTRIP
+export ASAN_OPTIONS=""
+rm ./a.out
+
 # FIXME: some tests do not need to be ran for all the combinations of arch
 # and optimization mode.
 for t in  *.cc; do
diff --git a/lib/asan/output_tests/use-after-free.c b/lib/asan/output_tests/use-after-free.c
index 801d3f6..4ee541a 100644
--- a/lib/asan/output_tests/use-after-free.c
+++ b/lib/asan/output_tests/use-after-free.c
@@ -7,3 +7,4 @@
 
 // CHECK: heap-use-after-free
 // CHECKSLEEP: Sleeping for 1 second
+// CHECKSTRIP-NOT: #0 0x{{.*}} ({{[/].*}})