[ASan] Introduce SymbolizerPrepareForSandboxing(), which is a no-op on every platform except Linux (because we don't support sandboxing anywhere else yet)
On Linux we pre-cache the value of readlink("/proc/self/exe"), so that it can be later used when the sandbox has been turned on.


git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@182579 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index 09e9c42..6e234e5 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -23,6 +23,7 @@
 #include "sanitizer_placement_new.h"
 #include "sanitizer_procmaps.h"
 #include "sanitizer_stacktrace.h"
+#include "sanitizer_symbolizer.h"
 
 #include <asm/param.h>
 #include <dlfcn.h>
@@ -305,6 +306,8 @@
   // process will be able to load additional libraries, so it's fine to use the
   // cached mappings.
   MemoryMappingLayout::CacheMemoryMappings();
+  // Same for /proc/self/exe in the symbolizer.
+  SymbolizerPrepareForSandboxing();
 }
 
 // ----------------- sanitizer_procmaps.h
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.h b/lib/sanitizer_common/sanitizer_symbolizer.h
index 54f3c68..ef37fd3 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer.h
+++ b/lib/sanitizer_common/sanitizer_symbolizer.h
@@ -114,6 +114,8 @@
 uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
                       string_predicate_t filter);
 
+void SymbolizerPrepareForSandboxing();
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_SYMBOLIZER_H
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc
index 48549ec..82ce50e 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc
@@ -131,6 +131,10 @@
                       string_predicate_t filter) {
   return 0;
 }
+
+void SymbolizerPrepareForSandboxing() {
+  // Do nothing on Android.
+}
 #else  // SANITIZER_ANDROID
 typedef ElfW(Phdr) Elf_Phdr;
 
@@ -144,6 +148,32 @@
 
 static const uptr kMaxPathLength = 512;
 
+static char proc_self_exe_cache_str[kMaxPathLength];
+static uptr proc_self_exe_cache_len = 0;
+
+static uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+  uptr module_name_len = internal_readlink(
+      "/proc/self/exe", buf, buf_len);
+  int readlink_error;
+  if (internal_iserror(buf_len, &readlink_error)) {
+    if (proc_self_exe_cache_len) {
+      // If available, use the cached module name.
+      CHECK_LE(proc_self_exe_cache_len, buf_len);
+      internal_strncpy(buf, proc_self_exe_cache_str, buf_len);
+      module_name_len = internal_strlen(proc_self_exe_cache_str);
+    } else {
+      // We can't read /proc/self/exe for some reason, assume the name of the
+      // binary is unknown.
+      Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, "
+             "some stack frames may not be symbolized\n", readlink_error);
+      module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe");
+    }
+    CHECK_LT(module_name_len, buf_len);
+    buf[module_name_len] = '\0';
+  }
+  return module_name_len;
+}
+
 static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
   DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
   if (data->current_n == data->max_n)
@@ -153,19 +183,7 @@
   if (data->first) {
     data->first = false;
     // First module is the binary itself.
-    uptr module_name_len = internal_readlink(
-        "/proc/self/exe", module_name.data(), module_name.size());
-    int readlink_error;
-    if (internal_iserror(module_name_len, &readlink_error)) {
-      // We can't read /proc/self/exe for some reason, assume the name of the
-      // binary is unknown.
-      Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, some "
-             "stack frames may not be symbolized\n", readlink_error);
-      module_name_len = internal_snprintf(module_name.data(),
-                                          module_name.size(), "/proc/self/exe");
-    }
-    CHECK_LT(module_name_len, module_name.size());
-    module_name[module_name_len] = '\0';
+    ReadBinaryName(module_name.data(), module_name.size());
   } else if (info->dlpi_name) {
     internal_strncpy(module_name.data(), info->dlpi_name, module_name.size());
   }
@@ -195,6 +213,13 @@
   dl_iterate_phdr(dl_iterate_phdr_cb, &data);
   return data.current_n;
 }
+
+void SymbolizerPrepareForSandboxing() {
+  if (!proc_self_exe_cache_len) {
+    proc_self_exe_cache_len =
+        ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength);
+  }
+}
 #endif  // SANITIZER_ANDROID
 
 }  // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_mac.cc b/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
index c8a91fd..9d96690 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
@@ -31,6 +31,10 @@
   return 0;
 }
 
+void SymbolizerPrepareForSandboxing() {
+  // Do nothing on Mac.
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
index d3e6975..993261a 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
@@ -31,6 +31,10 @@
   UNIMPLEMENTED();
 };
 
+void SymbolizerPrepareForSandboxing() {
+  // Do nothing on Windows.
+}
+
 const char *Demangle(const char *MangledName) {
   return MangledName;
 }