[compiler-rt] r190410 - [Sanitizer] Refactor symbolization interface: use class instead of several functions. Move some code around to get rid of extra source files

Alexey Samsonov samsonov at google.com
Tue Sep 10 07:36:17 PDT 2013


Author: samsonov
Date: Tue Sep 10 09:36:16 2013
New Revision: 190410

URL: http://llvm.org/viewvc/llvm-project?rev=190410&view=rev
Log:
[Sanitizer] Refactor symbolization interface: use class instead of several functions. Move some code around to get rid of extra source files

Removed:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_itanium.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/lsan/lsan.cc
    compiler-rt/trunk/lib/lsan/lsan_common.cc
    compiler-rt/trunk/lib/msan/msan.cc
    compiler-rt/trunk/lib/msan/msan_report.cc
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc
    compiler-rt/trunk/lib/ubsan/ubsan_diag.cc

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Tue Sep 10 09:36:16 2013
@@ -180,7 +180,8 @@ static bool IsASCII(unsigned char c) {
 static const char *MaybeDemangleGlobalName(const char *name) {
   // We can spoil names of globals with C linkage, so use an heuristic
   // approach to check if the name should be demangled.
-  return (name[0] == '_' && name[1] == 'Z') ? Demangle(name) : name;
+  return (name[0] == '_' && name[1] == 'Z') ? getSymbolizer()->Demangle(name)
+                                            : name;
 }
 
 // Check if the global is a zero-terminated ASCII string. If so, print it.
@@ -550,12 +551,12 @@ class ScopedInErrorReport {
 
 static void ReportSummary(const char *error_type, StackTrace *stack) {
   if (!stack->size) return;
-  if (IsSymbolizerAvailable()) {
+  if (getSymbolizer()->IsAvailable()) {
     AddressInfo ai;
     // Currently, we include the first stack frame into the report summary.
     // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
     uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
-    SymbolizeCode(pc, &ai, 1);
+    getSymbolizer()->SymbolizeCode(pc, &ai, 1);
     ReportErrorSummary(error_type,
                        StripPathPrefix(ai.file,
                                        common_flags()->strip_path_prefix),

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Tue Sep 10 09:36:16 2013
@@ -532,7 +532,8 @@ void __asan_init() {
 
   // Start symbolizer process if necessary.
   if (common_flags()->symbolize) {
-    InitializeExternalSymbolizer(common_flags()->external_symbolizer_path);
+    getSymbolizer()
+        ->InitializeExternal(common_flags()->external_symbolizer_path);
   }
 
   // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited

Modified: compiler-rt/trunk/lib/lsan/lsan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan.cc Tue Sep 10 09:36:16 2013
@@ -53,7 +53,8 @@ void Init() {
 
   // Start symbolizer process if necessary.
   if (common_flags()->symbolize) {
-    InitializeExternalSymbolizer(common_flags()->external_symbolizer_path);
+    getSymbolizer()
+        ->InitializeExternal(common_flags()->external_symbolizer_path);
   }
 
   InitCommonLsan();

Modified: compiler-rt/trunk/lib/lsan/lsan_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.cc Tue Sep 10 09:36:16 2013
@@ -402,8 +402,8 @@ static Suppression *GetSuppressionForAdd
   static const uptr kMaxAddrFrames = 16;
   InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
   for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo();
-  uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
-                                                    kMaxAddrFrames);
+  uptr addr_frames_num =
+      getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames);
   for (uptr i = 0; i < addr_frames_num; i++) {
     Suppression* s;
     if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||

Modified: compiler-rt/trunk/lib/msan/msan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.cc (original)
+++ compiler-rt/trunk/lib/msan/msan.cc Tue Sep 10 09:36:16 2013
@@ -324,7 +324,8 @@ void __msan_init() {
   }
 
   const char *external_symbolizer = common_flags()->external_symbolizer_path;
-  bool symbolizer_started = InitializeExternalSymbolizer(external_symbolizer);
+  bool symbolizer_started =
+      getSymbolizer()->InitializeExternal(external_symbolizer);
   if (external_symbolizer && external_symbolizer[0]) {
     CHECK(symbolizer_started);
   }

Modified: compiler-rt/trunk/lib/msan/msan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_report.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_report.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_report.cc Tue Sep 10 09:36:16 2013
@@ -52,8 +52,8 @@ static void DescribeOrigin(u32 origin) {
     Printf("%s", d.Origin());
     Printf("  %sUninitialized value was created by an allocation of '%s%s%s'"
            " in the stack frame of function '%s%s%s'%s\n",
-           d.Origin(), d.Name(), s, d.Origin(), d.Name(), Demangle(sep + 1),
-           d.Origin(), d.End());
+           d.Origin(), d.Name(), s, d.Origin(), d.Name(),
+           getSymbolizer()->Demangle(sep + 1), d.Origin(), d.End());
     InternalFree(s);
   } else {
     uptr size = 0;
@@ -65,12 +65,12 @@ static void DescribeOrigin(u32 origin) {
 }
 
 static void ReportSummary(const char *error_type, StackTrace *stack) {
-  if (!stack->size || !IsSymbolizerAvailable()) return;
+  if (!stack->size || !getSymbolizer()->IsAvailable()) return;
   AddressInfo ai;
   uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
   {
     SymbolizerScope sym_scope;
-    SymbolizeCode(pc, &ai, 1);
+    getSymbolizer()->SymbolizeCode(pc, &ai, 1);
   }
   ReportErrorSummary(error_type,
                      StripPathPrefix(ai.file,

Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Tue Sep 10 09:36:16 2013
@@ -15,9 +15,6 @@ set(SANITIZER_SOURCES
   sanitizer_stackdepot.cc
   sanitizer_stacktrace.cc
   sanitizer_suppressions.cc
-  sanitizer_symbolizer_itanium.cc
-  sanitizer_symbolizer_linux.cc
-  sanitizer_symbolizer_mac.cc
   sanitizer_symbolizer_win.cc
   sanitizer_thread_registry.cc
   sanitizer_win.cc)
@@ -27,8 +24,6 @@ set(SANITIZER_LIBCDEP_SOURCES
   sanitizer_linux_libcdep.cc
   sanitizer_posix_libcdep.cc
   sanitizer_stoptheworld_linux_libcdep.cc
-  sanitizer_symbolizer_libcdep.cc
-  sanitizer_symbolizer_linux_libcdep.cc
   sanitizer_symbolizer_posix_libcdep.cc)
 
 # Explicitly list all sanitizer_common headers. Not all of these are

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc Tue Sep 10 09:36:16 2013
@@ -146,6 +146,27 @@ void ReportErrorSummary(const char *erro
   __sanitizer_report_error_summary(buff.data());
 }
 
+LoadedModule::LoadedModule(const char *module_name, uptr base_address) {
+  full_name_ = internal_strdup(module_name);
+  base_address_ = base_address;
+  n_ranges_ = 0;
+}
+
+void LoadedModule::addAddressRange(uptr beg, uptr end) {
+  CHECK_LT(n_ranges_, kMaxNumberOfAddressRanges);
+  ranges_[n_ranges_].beg = beg;
+  ranges_[n_ranges_].end = end;
+  n_ranges_++;
+}
+
+bool LoadedModule::containsAddress(uptr address) const {
+  for (uptr i = 0; i < n_ranges_; i++) {
+    if (ranges_[i].beg <= address && address < ranges_[i].end)
+      return true;
+  }
+  return false;
+}
+
 }  // namespace __sanitizer
 
 using namespace __sanitizer;  // NOLINT

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Tue Sep 10 09:36:16 2013
@@ -402,6 +402,37 @@ uptr InternalBinarySearch(const Containe
   return not_found;
 }
 
+// Represents a binary loaded into virtual memory (e.g. this can be an
+// executable or a shared object).
+class LoadedModule {
+ public:
+  LoadedModule(const char *module_name, uptr base_address);
+  void addAddressRange(uptr beg, uptr end);
+  bool containsAddress(uptr address) const;
+
+  const char *full_name() const { return full_name_; }
+  uptr base_address() const { return base_address_; }
+
+ private:
+  struct AddressRange {
+    uptr beg;
+    uptr end;
+  };
+  char *full_name_;
+  uptr base_address_;
+  static const uptr kMaxNumberOfAddressRanges = 6;
+  AddressRange ranges_[kMaxNumberOfAddressRanges];
+  uptr n_ranges_;
+};
+
+// OS-dependent function that fills array with descriptions of at most
+// "max_modules" currently loaded modules. Returns the number of
+// initialized modules. If filter is nonzero, ignores modules for which
+// filter(full_name) is false.
+typedef bool (*string_predicate_t)(const char *);
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+                      string_predicate_t filter);
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_COMMON_H

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Tue Sep 10 09:36:16 2013
@@ -310,7 +310,7 @@ void PrepareForSandboxing() {
   // cached mappings.
   MemoryMappingLayout::CacheMemoryMappings();
   // Same for /proc/self/exe in the symbolizer.
-  SymbolizerPrepareForSandboxing();
+  getSymbolizer()->PrepareForSandboxing();
 }
 
 // ----------------- sanitizer_procmaps.h
@@ -676,6 +676,39 @@ uptr GetPageSize() {
 #endif
 }
 
+static char proc_self_exe_cache_str[kMaxPathLength];
+static uptr proc_self_exe_cache_len = 0;
+
+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;
+}
+
+void CacheBinaryName() {
+  if (!proc_self_exe_cache_len) {
+    proc_self_exe_cache_len =
+        ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength);
+  }
+}
+
 // Match full names of the form /path/to/base_name{-,.}*
 bool LibraryNameIs(const char *full_name, const char *base_name) {
   const char *name = full_name;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h Tue Sep 10 09:36:16 2013
@@ -13,6 +13,8 @@
 #ifndef SANITIZER_LINUX_H
 #define SANITIZER_LINUX_H
 
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
 #include "sanitizer_common.h"
 #include "sanitizer_internal_defs.h"
 
@@ -69,10 +71,13 @@ bool LibraryNameIs(const char *full_name
 
 // Read the name of the current binary from /proc/self/exe.
 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
+// Cache the value of /proc/self/exe.
+void CacheBinaryName();
 
 // Call cb for each region mapped by map.
 void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
 
 }  // namespace __sanitizer
 
+#endif  // SANITIZER_LINUX
 #endif  // SANITIZER_LINUX_H

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Tue Sep 10 09:36:16 2013
@@ -16,6 +16,8 @@
 #if SANITIZER_LINUX
 
 #include "sanitizer_common.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_placement_new.h"
 #include "sanitizer_procmaps.h"
 #include "sanitizer_stacktrace.h"
 
@@ -25,6 +27,11 @@
 #include <sys/resource.h>
 #include <unwind.h>
 
+#if !SANITIZER_ANDROID
+#include <elf.h>
+#include <link.h>
+#endif
+
 namespace __sanitizer {
 
 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
@@ -284,6 +291,63 @@ void AdjustStackSizeLinux(void *attr_, i
   }
 }
 
+#if SANITIZER_ANDROID
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+                      string_predicate_t filter) {
+  return 0;
+}
+#else  // SANITIZER_ANDROID
+typedef ElfW(Phdr) Elf_Phdr;
+
+struct DlIteratePhdrData {
+  LoadedModule *modules;
+  uptr current_n;
+  bool first;
+  uptr max_n;
+  string_predicate_t filter;
+};
+
+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)
+    return 0;
+  InternalScopedBuffer<char> module_name(kMaxPathLength);
+  module_name.data()[0] = '\0';
+  if (data->first) {
+    data->first = false;
+    // First module is the binary itself.
+    ReadBinaryName(module_name.data(), module_name.size());
+  } else if (info->dlpi_name) {
+    internal_strncpy(module_name.data(), info->dlpi_name, module_name.size());
+  }
+  if (module_name.data()[0] == '\0')
+    return 0;
+  if (data->filter && !data->filter(module_name.data()))
+    return 0;
+  void *mem = &data->modules[data->current_n];
+  LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(),
+                                                   info->dlpi_addr);
+  data->current_n++;
+  for (int i = 0; i < info->dlpi_phnum; i++) {
+    const Elf_Phdr *phdr = &info->dlpi_phdr[i];
+    if (phdr->p_type == PT_LOAD) {
+      uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
+      uptr cur_end = cur_beg + phdr->p_memsz;
+      cur_module->addAddressRange(cur_beg, cur_end);
+    }
+  }
+  return 0;
+}
+
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+                      string_predicate_t filter) {
+  CHECK(modules);
+  DlIteratePhdrData data = {modules, 0, true, max_modules, filter};
+  dl_iterate_phdr(dl_iterate_phdr_cb, &data);
+  return data.current_n;
+}
+#endif  // SANITIZER_ANDROID
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_LINUX

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Tue Sep 10 09:36:16 2013
@@ -25,6 +25,7 @@
 #include "sanitizer_common.h"
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_libc.h"
+#include "sanitizer_placement_new.h"
 #include "sanitizer_procmaps.h"
 
 #include <crt_externs.h>  // for _NSGetEnviron
@@ -371,6 +372,37 @@ void GetThreadStackAndTls(bool main, upt
 #endif
 }
 
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+                      string_predicate_t filter) {
+  MemoryMappingLayout memory_mapping(false);
+  memory_mapping.Reset();
+  uptr cur_beg, cur_end, cur_offset;
+  InternalScopedBuffer<char> module_name(kMaxPathLength);
+  uptr n_modules = 0;
+  for (uptr i = 0;
+       n_modules < max_modules &&
+           memory_mapping.Next(&cur_beg, &cur_end, &cur_offset,
+                               module_name.data(), module_name.size(), 0);
+       i++) {
+    const char *cur_name = module_name.data();
+    if (cur_name[0] == '\0')
+      continue;
+    if (filter && !filter(cur_name))
+      continue;
+    LoadedModule *cur_module = 0;
+    if (n_modules > 0 &&
+        0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) {
+      cur_module = &modules[n_modules - 1];
+    } else {
+      void *mem = &modules[n_modules];
+      cur_module = new(mem) LoadedModule(cur_name, cur_beg);
+      n_modules++;
+    }
+    cur_module->addAddressRange(cur_beg, cur_end);
+  }
+  return n_modules;
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc Tue Sep 10 09:36:16 2013
@@ -86,10 +86,10 @@ void StackTrace::PrintStack(const uptr *
         frame_num++;
       }
     }
-    if (symbolize && addr_frames_num == 0 && &SymbolizeCode) {
+    if (symbolize && addr_frames_num == 0 && &getSymbolizer) {
       // Use our own (online) symbolizer, if necessary.
-      addr_frames_num = SymbolizeCode(pc, addr_frames.data(),
-                                      addr_frames.size());
+      addr_frames_num = getSymbolizer()->SymbolizeCode(
+          pc, addr_frames.data(), addr_frames.size());
       for (uptr j = 0; j < addr_frames_num; j++) {
         AddressInfo &info = addr_frames[j];
         PrintStackFramePrefix(frame_num, pc);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h Tue Sep 10 09:36:16 2013
@@ -24,6 +24,7 @@
 #ifndef SANITIZER_SYMBOLIZER_H
 #define SANITIZER_SYMBOLIZER_H
 
+#include "sanitizer_allocator_internal.h"
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_libc.h"
 // WARNING: Do not include system headers here. See details above.
@@ -42,8 +43,14 @@ struct AddressInfo {
   AddressInfo() {
     internal_memset(this, 0, sizeof(AddressInfo));
   }
+
   // Deletes all strings and sets all fields to zero.
-  SANITIZER_WEAK_ATTRIBUTE void Clear();
+  void Clear() {
+    InternalFree(module);
+    InternalFree(function);
+    InternalFree(file);
+    internal_memset(this, 0, sizeof(AddressInfo));
+  }
 
   void FillAddressAndModuleInfo(uptr addr, const char *mod_name,
                                 uptr mod_offset) {
@@ -62,64 +69,39 @@ struct DataInfo {
   uptr size;
 };
 
-// Fills at most "max_frames" elements of "frames" with descriptions
-// for a given address (in all inlined functions). Returns the number
-// of descriptions actually filled.
-// This function should NOT be called from two threads simultaneously.
-SANITIZER_WEAK_ATTRIBUTE
-uptr SymbolizeCode(uptr address, AddressInfo *frames, uptr max_frames);
-bool SymbolizeData(uptr address, DataInfo *info);
-
-bool IsSymbolizerAvailable();
-void FlushSymbolizer();  // releases internal caches (if any)
-
-// Attempts to demangle the provided C++ mangled name.
-const char *Demangle(const char *name);
-// Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
-const char *DemangleCXXABI(const char *name);
-
-// Starts external symbolizer program in a subprocess. Sanitizer communicates
-// with external symbolizer via pipes. If path_to_symbolizer is NULL or empty,
-// tries to look for llvm-symbolizer in PATH.
-bool InitializeExternalSymbolizer(const char *path_to_symbolizer);
-
-const int kSymbolizerStartupTimeMillis = 10;
-
-class LoadedModule {
+class SymbolizerInterface {
  public:
-  LoadedModule(const char *module_name, uptr base_address);
-  void addAddressRange(uptr beg, uptr end);
-  bool containsAddress(uptr address) const;
-
-  const char *full_name() const { return full_name_; }
-  uptr base_address() const { return base_address_; }
-
- private:
-  struct AddressRange {
-    uptr beg;
-    uptr end;
-  };
-  char *full_name_;
-  uptr base_address_;
-  static const uptr kMaxNumberOfAddressRanges = 6;
-  AddressRange ranges_[kMaxNumberOfAddressRanges];
-  uptr n_ranges_;
+  // Fills at most "max_frames" elements of "frames" with descriptions
+  // for a given address (in all inlined functions). Returns the number
+  // of descriptions actually filled.
+  virtual uptr SymbolizeCode(uptr address, AddressInfo *frames,
+                             uptr max_frames) {
+    return 0;
+  }
+  virtual bool SymbolizeData(uptr address, DataInfo *info) {
+    return false;
+  }
+  virtual bool IsAvailable() {
+    return false;
+  }
+  // Release internal caches (if any).
+  virtual void Flush() {}
+  // Attempts to demangle the provided C++ mangled name.
+  virtual const char *Demangle(const char *name) {
+    return name;
+  }
+  virtual void PrepareForSandboxing() {}
+  // Starts external symbolizer program in a subprocess. Sanitizer communicates
+  // with external symbolizer via pipes. If path_to_symbolizer is NULL or empty,
+  // tries to look for llvm-symbolizer in PATH.
+  virtual bool InitializeExternal(const char *path_to_symbolizer) {
+    return false;
+  }
 };
 
-// Creates external symbolizer connected via pipe, user should write
-// to output_fd and read from input_fd.
-bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
-                               int *input_fd, int *output_fd);
-
-// OS-dependent function that fills array with descriptions of at most
-// "max_modules" currently loaded modules. Returns the number of
-// initialized modules. If filter is nonzero, ignores modules for which
-// filter(full_name) is false.
-typedef bool (*string_predicate_t)(const char *);
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
-                      string_predicate_t filter);
-
-void SymbolizerPrepareForSandboxing();
+// Returns platform-specific implementation of SymbolizerInterface. It can't be
+// used from multiple threads simultaneously.
+SANITIZER_WEAK_ATTRIBUTE SymbolizerInterface *getSymbolizer();
 
 }  // namespace __sanitizer
 

Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_itanium.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_itanium.cc?rev=190409&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_itanium.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_itanium.cc (removed)
@@ -1,44 +0,0 @@
-//===-- sanitizer_symbolizer_itanium.cc -----------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between the sanitizer run-time libraries.
-// Itanium C++ ABI-specific implementation of symbolizer parts.
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_platform.h"
-#if SANITIZER_MAC || SANITIZER_LINUX
-
-#include "sanitizer_symbolizer.h"
-
-#include <stdlib.h>
-
-// C++ demangling function, as required by Itanium C++ ABI. This is weak,
-// because we do not require a C++ ABI library to be linked to a program
-// using sanitizers; if it's not present, we'll just use the mangled name.
-namespace __cxxabiv1 {
-  extern "C" SANITIZER_WEAK_ATTRIBUTE
-  char *__cxa_demangle(const char *mangled, char *buffer,
-                                  size_t *length, int *status);
-}
-
-const char *__sanitizer::DemangleCXXABI(const char *name) {
-  // FIXME: __cxa_demangle aggressively insists on allocating memory.
-  // There's not much we can do about that, short of providing our
-  // own demangler (libc++abi's implementation could be adapted so that
-  // it does not allocate). For now, we just call it anyway, and we leak
-  // the returned value.
-  if (__cxxabiv1::__cxa_demangle)
-    if (const char *demangled_name =
-          __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
-      return demangled_name;
-
-  return name;
-}
-
-#endif  // SANITIZER_MAC || SANITIZER_LINUX

Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc?rev=190409&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc (removed)
@@ -1,491 +0,0 @@
-//===-- sanitizer_symbolizer_libcdep.cc -----------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries. See sanitizer_symbolizer.h for details.
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_allocator_internal.h"
-#include "sanitizer_common.h"
-#include "sanitizer_placement_new.h"
-#include "sanitizer_procmaps.h"
-#include "sanitizer_symbolizer.h"
-
-namespace __sanitizer {
-
-void AddressInfo::Clear() {
-  InternalFree(module);
-  InternalFree(function);
-  InternalFree(file);
-  internal_memset(this, 0, sizeof(AddressInfo));
-}
-
-LoadedModule::LoadedModule(const char *module_name, uptr base_address) {
-  full_name_ = internal_strdup(module_name);
-  base_address_ = base_address;
-  n_ranges_ = 0;
-}
-
-void LoadedModule::addAddressRange(uptr beg, uptr end) {
-  CHECK_LT(n_ranges_, kMaxNumberOfAddressRanges);
-  ranges_[n_ranges_].beg = beg;
-  ranges_[n_ranges_].end = end;
-  n_ranges_++;
-}
-
-bool LoadedModule::containsAddress(uptr address) const {
-  for (uptr i = 0; i < n_ranges_; i++) {
-    if (ranges_[i].beg <= address && address < ranges_[i].end)
-      return true;
-  }
-  return false;
-}
-
-// Extracts the prefix of "str" that consists of any characters not
-// present in "delims" string, and copies this prefix to "result", allocating
-// space for it.
-// Returns a pointer to "str" after skipping extracted prefix and first
-// delimiter char.
-static const char *ExtractToken(const char *str, const char *delims,
-                                char **result) {
-  uptr prefix_len = internal_strcspn(str, delims);
-  *result = (char*)InternalAlloc(prefix_len + 1);
-  internal_memcpy(*result, str, prefix_len);
-  (*result)[prefix_len] = '\0';
-  const char *prefix_end = str + prefix_len;
-  if (*prefix_end != '\0') prefix_end++;
-  return prefix_end;
-}
-
-// Same as ExtractToken, but converts extracted token to integer.
-static const char *ExtractInt(const char *str, const char *delims,
-                              int *result) {
-  char *buff;
-  const char *ret = ExtractToken(str, delims, &buff);
-  if (buff != 0) {
-    *result = (int)internal_atoll(buff);
-  }
-  InternalFree(buff);
-  return ret;
-}
-
-static const char *ExtractUptr(const char *str, const char *delims,
-                               uptr *result) {
-  char *buff;
-  const char *ret = ExtractToken(str, delims, &buff);
-  if (buff != 0) {
-    *result = (uptr)internal_atoll(buff);
-  }
-  InternalFree(buff);
-  return ret;
-}
-
-// ExternalSymbolizer encapsulates communication between the tool and
-// external symbolizer program, running in a different subprocess,
-// For now we assume the following protocol:
-// For each request of the form
-//   <module_name> <module_offset>
-// passed to STDIN, external symbolizer prints to STDOUT response:
-//   <function_name>
-//   <file_name>:<line_number>:<column_number>
-//   <function_name>
-//   <file_name>:<line_number>:<column_number>
-//   ...
-//   <empty line>
-class ExternalSymbolizer {
- public:
-  ExternalSymbolizer(const char *path, int input_fd, int output_fd)
-      : path_(path),
-        input_fd_(input_fd),
-        output_fd_(output_fd),
-        times_restarted_(0) {
-    CHECK(path_);
-    CHECK_NE(input_fd_, kInvalidFd);
-    CHECK_NE(output_fd_, kInvalidFd);
-  }
-
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    CHECK(module_name);
-    internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
-                      is_data ? "DATA " : "", module_name, module_offset);
-    if (!writeToSymbolizer(buffer_, internal_strlen(buffer_)))
-      return 0;
-    if (!readFromSymbolizer(buffer_, kBufferSize))
-      return 0;
-    return buffer_;
-  }
-
-  bool Restart() {
-    if (times_restarted_ >= kMaxTimesRestarted) return false;
-    times_restarted_++;
-    internal_close(input_fd_);
-    internal_close(output_fd_);
-    return StartSymbolizerSubprocess(path_, &input_fd_, &output_fd_);
-  }
-
-  void Flush() {
-  }
-
- private:
-  bool readFromSymbolizer(char *buffer, uptr max_length) {
-    if (max_length == 0)
-      return true;
-    uptr read_len = 0;
-    while (true) {
-      uptr just_read = internal_read(input_fd_, buffer + read_len,
-                                     max_length - read_len);
-      // We can't read 0 bytes, as we don't expect external symbolizer to close
-      // its stdout.
-      if (just_read == 0 || just_read == (uptr)-1) {
-        Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
-        return false;
-      }
-      read_len += just_read;
-      // Empty line marks the end of symbolizer output.
-      if (read_len >= 2 && buffer[read_len - 1] == '\n' &&
-                           buffer[read_len - 2] == '\n') {
-        break;
-      }
-    }
-    return true;
-  }
-
-  bool writeToSymbolizer(const char *buffer, uptr length) {
-    if (length == 0)
-      return true;
-    uptr write_len = internal_write(output_fd_, buffer, length);
-    if (write_len == 0 || write_len == (uptr)-1) {
-      Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
-      return false;
-    }
-    return true;
-  }
-
-  const char *path_;
-  int input_fd_;
-  int output_fd_;
-
-  static const uptr kBufferSize = 16 * 1024;
-  char buffer_[kBufferSize];
-
-  static const uptr kMaxTimesRestarted = 5;
-  uptr times_restarted_;
-};
-
-static LowLevelAllocator symbolizer_allocator;  // Linker initialized.
-
-#if SANITIZER_SUPPORTS_WEAK_HOOKS
-extern "C" {
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
-bool __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
-                                char *Buffer, int MaxLength);
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
-bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
-                                char *Buffer, int MaxLength);
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
-void __sanitizer_symbolize_flush();
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
-int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
-                                   int MaxLength);
-}  // extern "C"
-
-class InternalSymbolizer {
- public:
-  typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
-
-  static InternalSymbolizer *get() {
-    if (__sanitizer_symbolize_code != 0 &&
-        __sanitizer_symbolize_data != 0) {
-      void *mem = symbolizer_allocator.Allocate(sizeof(InternalSymbolizer));
-      return new(mem) InternalSymbolizer();
-    }
-    return 0;
-  }
-
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    SanitizerSymbolizeFn symbolize_fn = is_data ? __sanitizer_symbolize_data
-                                                : __sanitizer_symbolize_code;
-    if (symbolize_fn(module_name, module_offset, buffer_, kBufferSize))
-      return buffer_;
-    return 0;
-  }
-
-  void Flush() {
-    if (__sanitizer_symbolize_flush)
-      __sanitizer_symbolize_flush();
-  }
-
-  const char *Demangle(const char *name) {
-    if (__sanitizer_symbolize_demangle) {
-      for (uptr res_length = 1024;
-           res_length <= InternalSizeClassMap::kMaxSize;) {
-        char *res_buff = static_cast<char*>(InternalAlloc(res_length));
-        uptr req_length =
-            __sanitizer_symbolize_demangle(name, res_buff, res_length);
-        if (req_length > res_length) {
-          res_length = req_length + 1;
-          InternalFree(res_buff);
-          continue;
-        }
-        return res_buff;
-      }
-    }
-    return name;
-  }
-
- private:
-  InternalSymbolizer() { }
-
-  static const int kBufferSize = 16 * 1024;
-  static const int kMaxDemangledNameSize = 1024;
-  char buffer_[kBufferSize];
-};
-#else  // SANITIZER_SUPPORTS_WEAK_HOOKS
-
-class InternalSymbolizer {
- public:
-  static InternalSymbolizer *get() { return 0; }
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    return 0;
-  }
-  void Flush() { }
-  const char *Demangle(const char *name) { return name; }
-};
-
-#endif  // SANITIZER_SUPPORTS_WEAK_HOOKS
-
-class Symbolizer {
-  // This class has no constructor, as global constructors are forbidden in
-  // sanitizer_common. It should be linker initialized instead.
- public:
-  uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
-    if (max_frames == 0)
-      return 0;
-    LoadedModule *module = FindModuleForAddress(addr);
-    if (module == 0)
-      return 0;
-    const char *module_name = module->full_name();
-    uptr module_offset = addr - module->base_address();
-    const char *str = SendCommand(false, module_name, module_offset);
-    if (str == 0) {
-      // External symbolizer was not initialized or failed. Fill only data
-      // about module name and offset.
-      AddressInfo *info = &frames[0];
-      info->Clear();
-      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
-      return 1;
-    }
-    uptr frame_id = 0;
-    for (frame_id = 0; frame_id < max_frames; frame_id++) {
-      AddressInfo *info = &frames[frame_id];
-      char *function_name = 0;
-      str = ExtractToken(str, "\n", &function_name);
-      CHECK(function_name);
-      if (function_name[0] == '\0') {
-        // There are no more frames.
-        break;
-      }
-      info->Clear();
-      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
-      info->function = function_name;
-      // Parse <file>:<line>:<column> buffer.
-      char *file_line_info = 0;
-      str = ExtractToken(str, "\n", &file_line_info);
-      CHECK(file_line_info);
-      const char *line_info = ExtractToken(file_line_info, ":", &info->file);
-      line_info = ExtractInt(line_info, ":", &info->line);
-      line_info = ExtractInt(line_info, "", &info->column);
-      InternalFree(file_line_info);
-
-      // Functions and filenames can be "??", in which case we write 0
-      // to address info to mark that names are unknown.
-      if (0 == internal_strcmp(info->function, "??")) {
-        InternalFree(info->function);
-        info->function = 0;
-      }
-      if (0 == internal_strcmp(info->file, "??")) {
-        InternalFree(info->file);
-        info->file = 0;
-      }
-    }
-    if (frame_id == 0) {
-      // Make sure we return at least one frame.
-      AddressInfo *info = &frames[0];
-      info->Clear();
-      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
-      frame_id = 1;
-    }
-    return frame_id;
-  }
-
-  bool SymbolizeData(uptr addr, DataInfo *info) {
-    LoadedModule *module = FindModuleForAddress(addr);
-    if (module == 0)
-      return false;
-    const char *module_name = module->full_name();
-    uptr module_offset = addr - module->base_address();
-    internal_memset(info, 0, sizeof(*info));
-    info->address = addr;
-    info->module = internal_strdup(module_name);
-    info->module_offset = module_offset;
-    const char *str = SendCommand(true, module_name, module_offset);
-    if (str == 0)
-      return true;
-    str = ExtractToken(str, "\n", &info->name);
-    str = ExtractUptr(str, " ", &info->start);
-    str = ExtractUptr(str, "\n", &info->size);
-    info->start += module->base_address();
-    return true;
-  }
-
-  bool InitializeExternalSymbolizer(const char *path_to_symbolizer) {
-    if (!path_to_symbolizer || path_to_symbolizer[0] == '\0') {
-      path_to_symbolizer = FindPathToBinary("llvm-symbolizer");
-      if (!path_to_symbolizer)
-        return false;
-    }
-    int input_fd, output_fd;
-    if (!StartSymbolizerSubprocess(path_to_symbolizer, &input_fd, &output_fd))
-      return false;
-    void *mem = symbolizer_allocator.Allocate(sizeof(ExternalSymbolizer));
-    external_symbolizer_ = new(mem) ExternalSymbolizer(path_to_symbolizer,
-                                                       input_fd, output_fd);
-    return true;
-  }
-
-  bool IsSymbolizerAvailable() {
-    if (internal_symbolizer_ == 0)
-      internal_symbolizer_ = InternalSymbolizer::get();
-    return internal_symbolizer_ || external_symbolizer_;
-  }
-
-  void Flush() {
-    if (internal_symbolizer_)
-      internal_symbolizer_->Flush();
-    if (external_symbolizer_)
-      external_symbolizer_->Flush();
-  }
-
-  const char *Demangle(const char *name) {
-    if (IsSymbolizerAvailable() && internal_symbolizer_ != 0)
-      return internal_symbolizer_->Demangle(name);
-    return DemangleCXXABI(name);
-  }
-
- private:
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    // First, try to use internal symbolizer.
-    if (!IsSymbolizerAvailable()) {
-      return 0;
-    }
-    if (internal_symbolizer_) {
-      return internal_symbolizer_->SendCommand(is_data, module_name,
-                                               module_offset);
-    }
-    // Otherwise, fall back to external symbolizer.
-    if (external_symbolizer_ == 0) {
-      ReportExternalSymbolizerError(
-          "WARNING: Trying to symbolize code, but external "
-          "symbolizer is not initialized!\n");
-      return 0;
-    }
-    for (;;) {
-      char *reply = external_symbolizer_->SendCommand(is_data, module_name,
-          module_offset);
-      if (reply)
-        return reply;
-      // Try to restart symbolizer subprocess. If we don't succeed, forget
-      // about it and don't try to use it later.
-      if (!external_symbolizer_->Restart()) {
-        ReportExternalSymbolizerError(
-            "WARNING: Failed to use and restart external symbolizer!\n");
-        external_symbolizer_ = 0;
-        return 0;
-      }
-    }
-  }
-
-  LoadedModule *FindModuleForAddress(uptr address) {
-    bool modules_were_reloaded = false;
-    if (modules_ == 0 || !modules_fresh_) {
-      modules_ = (LoadedModule*)(symbolizer_allocator.Allocate(
-          kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
-      CHECK(modules_);
-      n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
-                                    /* filter */ 0);
-      // FIXME: Return this check when GetListOfModules is implemented on Mac.
-      // CHECK_GT(n_modules_, 0);
-      CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
-      modules_fresh_ = true;
-      modules_were_reloaded = true;
-    }
-    for (uptr i = 0; i < n_modules_; i++) {
-      if (modules_[i].containsAddress(address)) {
-        return &modules_[i];
-      }
-    }
-    // Reload the modules and look up again, if we haven't tried it yet.
-    if (!modules_were_reloaded) {
-      // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors.
-      // It's too aggressive to reload the list of modules each time we fail
-      // to find a module for a given address.
-      modules_fresh_ = false;
-      return FindModuleForAddress(address);
-    }
-    return 0;
-  }
-
-  void ReportExternalSymbolizerError(const char *msg) {
-    // Don't use atomics here for now, as SymbolizeCode can't be called
-    // from multiple threads anyway.
-    static bool reported;
-    if (!reported) {
-      Report(msg);
-      reported = true;
-    }
-  }
-
-  // 16K loaded modules should be enough for everyone.
-  static const uptr kMaxNumberOfModuleContexts = 1 << 14;
-  LoadedModule *modules_;  // Array of module descriptions is leaked.
-  uptr n_modules_;
-  // If stale, need to reload the modules before looking up addresses.
-  bool modules_fresh_;
-
-  ExternalSymbolizer *external_symbolizer_;  // Leaked.
-  InternalSymbolizer *internal_symbolizer_;  // Leaked.
-};
-
-static Symbolizer symbolizer;  // Linker initialized.
-
-uptr SymbolizeCode(uptr address, AddressInfo *frames, uptr max_frames) {
-  return symbolizer.SymbolizeCode(address, frames, max_frames);
-}
-
-bool SymbolizeData(uptr address, DataInfo *info) {
-  return symbolizer.SymbolizeData(address, info);
-}
-
-bool InitializeExternalSymbolizer(const char *path_to_symbolizer) {
-  return symbolizer.InitializeExternalSymbolizer(path_to_symbolizer);
-}
-
-bool IsSymbolizerAvailable() {
-  return symbolizer.IsSymbolizerAvailable();
-}
-
-void FlushSymbolizer() {
-  symbolizer.Flush();
-}
-
-const char *Demangle(const char *name) {
-  return symbolizer.Demangle(name);
-}
-
-}  // namespace __sanitizer

Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux.cc?rev=190409&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux.cc (removed)
@@ -1,63 +0,0 @@
-//===-- sanitizer_symbolizer_linux.cc -------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries.
-// Linux-specific implementation of symbolizer parts.
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_platform.h"
-#if SANITIZER_LINUX
-#include "sanitizer_common.h"
-#include "sanitizer_linux.h"
-
-namespace __sanitizer {
-
-#if SANITIZER_ANDROID
-void SymbolizerPrepareForSandboxing() {
-  // Do nothing on Android.
-}
-#else
-static char proc_self_exe_cache_str[kMaxPathLength];
-static uptr proc_self_exe_cache_len = 0;
-
-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;
-}
-
-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
-
-#endif  // SANITIZER_LINUX

Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc?rev=190409&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_linux_libcdep.cc (removed)
@@ -1,100 +0,0 @@
-//===-- sanitizer_symbolizer_linux_libcdep.cc -----------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries.
-// Linux-specific implementation of symbolizer parts.
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_platform.h"
-#if SANITIZER_LINUX
-#include "sanitizer_common.h"
-#include "sanitizer_internal_defs.h"
-#include "sanitizer_libc.h"
-#include "sanitizer_linux.h"
-#include "sanitizer_placement_new.h"
-#include "sanitizer_symbolizer.h"
-
-// Android NDK r8e elf.h depends on stdint.h without including the latter.
-#include <stdint.h>
-
-#include <elf.h>
-#include <errno.h>
-#include <poll.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#if !SANITIZER_ANDROID
-#include <link.h>
-#endif
-
-namespace __sanitizer {
-
-#if SANITIZER_ANDROID
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
-                      string_predicate_t filter) {
-  return 0;
-}
-#else  // SANITIZER_ANDROID
-typedef ElfW(Phdr) Elf_Phdr;
-
-struct DlIteratePhdrData {
-  LoadedModule *modules;
-  uptr current_n;
-  bool first;
-  uptr max_n;
-  string_predicate_t filter;
-};
-
-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)
-    return 0;
-  InternalScopedBuffer<char> module_name(kMaxPathLength);
-  module_name.data()[0] = '\0';
-  if (data->first) {
-    data->first = false;
-    // First module is the binary itself.
-    ReadBinaryName(module_name.data(), module_name.size());
-  } else if (info->dlpi_name) {
-    internal_strncpy(module_name.data(), info->dlpi_name, module_name.size());
-  }
-  if (module_name.data()[0] == '\0')
-    return 0;
-  if (data->filter && !data->filter(module_name.data()))
-    return 0;
-  void *mem = &data->modules[data->current_n];
-  LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(),
-                                                   info->dlpi_addr);
-  data->current_n++;
-  for (int i = 0; i < info->dlpi_phnum; i++) {
-    const Elf_Phdr *phdr = &info->dlpi_phdr[i];
-    if (phdr->p_type == PT_LOAD) {
-      uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
-      uptr cur_end = cur_beg + phdr->p_memsz;
-      cur_module->addAddressRange(cur_beg, cur_end);
-    }
-  }
-  return 0;
-}
-
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
-                      string_predicate_t filter) {
-  CHECK(modules);
-  DlIteratePhdrData data = {modules, 0, true, max_modules, filter};
-  dl_iterate_phdr(dl_iterate_phdr_cb, &data);
-  return data.current_n;
-}
-#endif  // SANITIZER_ANDROID
-
-}  // namespace __sanitizer
-
-#endif  // SANITIZER_LINUX

Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc?rev=190409&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc (removed)
@@ -1,62 +0,0 @@
-//===-- sanitizer_symbolizer_mac.cc ---------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries.
-// Mac-specific implementation of symbolizer parts.
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_platform.h"
-#if SANITIZER_MAC
-#include "sanitizer_common.h"
-#include "sanitizer_internal_defs.h"
-#include "sanitizer_placement_new.h"
-#include "sanitizer_procmaps.h"
-#include "sanitizer_symbolizer.h"
-
-namespace __sanitizer {
-
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
-                      string_predicate_t filter) {
-  MemoryMappingLayout memory_mapping(false);
-  memory_mapping.Reset();
-  uptr cur_beg, cur_end, cur_offset;
-  InternalScopedBuffer<char> module_name(kMaxPathLength);
-  uptr n_modules = 0;
-  for (uptr i = 0;
-       n_modules < max_modules &&
-           memory_mapping.Next(&cur_beg, &cur_end, &cur_offset,
-                               module_name.data(), module_name.size(), 0);
-       i++) {
-    const char *cur_name = module_name.data();
-    if (cur_name[0] == '\0')
-      continue;
-    if (filter && !filter(cur_name))
-      continue;
-    LoadedModule *cur_module = 0;
-    if (n_modules > 0 &&
-        0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) {
-      cur_module = &modules[n_modules - 1];
-    } else {
-      void *mem = &modules[n_modules];
-      cur_module = new(mem) LoadedModule(cur_name, cur_beg);
-      n_modules++;
-    }
-    cur_module->addAddressRange(cur_beg, cur_end);
-  }
-  return n_modules;
-}
-
-void SymbolizerPrepareForSandboxing() {
-  // Do nothing on Mac.
-}
-
-}  // namespace __sanitizer
-
-#endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc Tue Sep 10 09:36:16 2013
@@ -14,16 +14,45 @@
 
 #include "sanitizer_platform.h"
 #if SANITIZER_POSIX
+#include "sanitizer_allocator_internal.h"
 #include "sanitizer_common.h"
 #include "sanitizer_internal_defs.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
 #include "sanitizer_symbolizer.h"
 
 #include <errno.h>
+#include <stdlib.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
+// C++ demangling function, as required by Itanium C++ ABI. This is weak,
+// because we do not require a C++ ABI library to be linked to a program
+// using sanitizers; if it's not present, we'll just use the mangled name.
+namespace __cxxabiv1 {
+  extern "C" SANITIZER_WEAK_ATTRIBUTE
+  char *__cxa_demangle(const char *mangled, char *buffer,
+                                  size_t *length, int *status);
+}
+
 namespace __sanitizer {
 
+// Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
+static const char *DemangleCXXABI(const char *name) {
+  // FIXME: __cxa_demangle aggressively insists on allocating memory.
+  // There's not much we can do about that, short of providing our
+  // own demangler (libc++abi's implementation could be adapted so that
+  // it does not allocate). For now, we just call it anyway, and we leak
+  // the returned value.
+  if (__cxxabiv1::__cxa_demangle)
+    if (const char *demangled_name =
+          __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
+      return demangled_name;
+
+  return name;
+}
+
 #if defined(__x86_64__)
 static const char* const kSymbolizerArch = "--default-arch=x86_64";
 #elif defined(__i386__)
@@ -34,8 +63,12 @@ static const char* const kSymbolizerArch
 static const char* const kSymbolizerArch = "--default-arch=unknown";
 #endif
 
-bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
-                               int *input_fd, int *output_fd) {
+static const int kSymbolizerStartupTimeMillis = 10;
+
+// Creates external symbolizer connected via pipe, user should write
+// to output_fd and read from input_fd.
+static bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
+                                      int *input_fd, int *output_fd) {
   if (!FileExists(path_to_symbolizer)) {
     Report("WARNING: invalid path to external symbolizer!\n");
     return false;
@@ -121,6 +154,433 @@ bool StartSymbolizerSubprocess(const cha
   return true;
 }
 
+// Extracts the prefix of "str" that consists of any characters not
+// present in "delims" string, and copies this prefix to "result", allocating
+// space for it.
+// Returns a pointer to "str" after skipping extracted prefix and first
+// delimiter char.
+static const char *ExtractToken(const char *str, const char *delims,
+                                char **result) {
+  uptr prefix_len = internal_strcspn(str, delims);
+  *result = (char*)InternalAlloc(prefix_len + 1);
+  internal_memcpy(*result, str, prefix_len);
+  (*result)[prefix_len] = '\0';
+  const char *prefix_end = str + prefix_len;
+  if (*prefix_end != '\0') prefix_end++;
+  return prefix_end;
+}
+
+// Same as ExtractToken, but converts extracted token to integer.
+static const char *ExtractInt(const char *str, const char *delims,
+                              int *result) {
+  char *buff;
+  const char *ret = ExtractToken(str, delims, &buff);
+  if (buff != 0) {
+    *result = (int)internal_atoll(buff);
+  }
+  InternalFree(buff);
+  return ret;
+}
+
+static const char *ExtractUptr(const char *str, const char *delims,
+                               uptr *result) {
+  char *buff;
+  const char *ret = ExtractToken(str, delims, &buff);
+  if (buff != 0) {
+    *result = (uptr)internal_atoll(buff);
+  }
+  InternalFree(buff);
+  return ret;
+}
+
+// ExternalSymbolizer encapsulates communication between the tool and
+// external symbolizer program, running in a different subprocess,
+// For now we assume the following protocol:
+// For each request of the form
+//   <module_name> <module_offset>
+// passed to STDIN, external symbolizer prints to STDOUT response:
+//   <function_name>
+//   <file_name>:<line_number>:<column_number>
+//   <function_name>
+//   <file_name>:<line_number>:<column_number>
+//   ...
+//   <empty line>
+class ExternalSymbolizer {
+ public:
+  ExternalSymbolizer(const char *path, int input_fd, int output_fd)
+      : path_(path),
+        input_fd_(input_fd),
+        output_fd_(output_fd),
+        times_restarted_(0) {
+    CHECK(path_);
+    CHECK_NE(input_fd_, kInvalidFd);
+    CHECK_NE(output_fd_, kInvalidFd);
+  }
+
+  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+    CHECK(module_name);
+    internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
+                      is_data ? "DATA " : "", module_name, module_offset);
+    if (!writeToSymbolizer(buffer_, internal_strlen(buffer_)))
+      return 0;
+    if (!readFromSymbolizer(buffer_, kBufferSize))
+      return 0;
+    return buffer_;
+  }
+
+  bool Restart() {
+    if (times_restarted_ >= kMaxTimesRestarted) return false;
+    times_restarted_++;
+    internal_close(input_fd_);
+    internal_close(output_fd_);
+    return StartSymbolizerSubprocess(path_, &input_fd_, &output_fd_);
+  }
+
+  void Flush() {
+  }
+
+ private:
+  bool readFromSymbolizer(char *buffer, uptr max_length) {
+    if (max_length == 0)
+      return true;
+    uptr read_len = 0;
+    while (true) {
+      uptr just_read = internal_read(input_fd_, buffer + read_len,
+                                     max_length - read_len);
+      // We can't read 0 bytes, as we don't expect external symbolizer to close
+      // its stdout.
+      if (just_read == 0 || just_read == (uptr)-1) {
+        Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
+        return false;
+      }
+      read_len += just_read;
+      // Empty line marks the end of symbolizer output.
+      if (read_len >= 2 && buffer[read_len - 1] == '\n' &&
+                           buffer[read_len - 2] == '\n') {
+        break;
+      }
+    }
+    return true;
+  }
+
+  bool writeToSymbolizer(const char *buffer, uptr length) {
+    if (length == 0)
+      return true;
+    uptr write_len = internal_write(output_fd_, buffer, length);
+    if (write_len == 0 || write_len == (uptr)-1) {
+      Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
+      return false;
+    }
+    return true;
+  }
+
+  const char *path_;
+  int input_fd_;
+  int output_fd_;
+
+  static const uptr kBufferSize = 16 * 1024;
+  char buffer_[kBufferSize];
+
+  static const uptr kMaxTimesRestarted = 5;
+  uptr times_restarted_;
+};
+
+static LowLevelAllocator symbolizer_allocator;  // Linker initialized.
+
+#if SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+bool __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
+                                char *Buffer, int MaxLength);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
+                                char *Buffer, int MaxLength);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+void __sanitizer_symbolize_flush();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
+                                   int MaxLength);
+}  // extern "C"
+
+class InternalSymbolizer {
+ public:
+  typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
+
+  static InternalSymbolizer *get() {
+    if (__sanitizer_symbolize_code != 0 &&
+        __sanitizer_symbolize_data != 0) {
+      void *mem = symbolizer_allocator.Allocate(sizeof(InternalSymbolizer));
+      return new(mem) InternalSymbolizer();
+    }
+    return 0;
+  }
+
+  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+    SanitizerSymbolizeFn symbolize_fn = is_data ? __sanitizer_symbolize_data
+                                                : __sanitizer_symbolize_code;
+    if (symbolize_fn(module_name, module_offset, buffer_, kBufferSize))
+      return buffer_;
+    return 0;
+  }
+
+  void Flush() {
+    if (__sanitizer_symbolize_flush)
+      __sanitizer_symbolize_flush();
+  }
+
+  const char *Demangle(const char *name) {
+    if (__sanitizer_symbolize_demangle) {
+      for (uptr res_length = 1024;
+           res_length <= InternalSizeClassMap::kMaxSize;) {
+        char *res_buff = static_cast<char*>(InternalAlloc(res_length));
+        uptr req_length =
+            __sanitizer_symbolize_demangle(name, res_buff, res_length);
+        if (req_length > res_length) {
+          res_length = req_length + 1;
+          InternalFree(res_buff);
+          continue;
+        }
+        return res_buff;
+      }
+    }
+    return name;
+  }
+
+ private:
+  InternalSymbolizer() { }
+
+  static const int kBufferSize = 16 * 1024;
+  static const int kMaxDemangledNameSize = 1024;
+  char buffer_[kBufferSize];
+};
+#else  // SANITIZER_SUPPORTS_WEAK_HOOKS
+
+class InternalSymbolizer {
+ public:
+  static InternalSymbolizer *get() { return 0; }
+  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+    return 0;
+  }
+  void Flush() { }
+  const char *Demangle(const char *name) { return name; }
+};
+
+#endif  // SANITIZER_SUPPORTS_WEAK_HOOKS
+
+class Symbolizer : public SymbolizerInterface {
+  // This class has no constructor, as global constructors are forbidden in
+  // sanitizer_common. It should be linker initialized instead.
+ public:
+  uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
+    if (max_frames == 0)
+      return 0;
+    LoadedModule *module = FindModuleForAddress(addr);
+    if (module == 0)
+      return 0;
+    const char *module_name = module->full_name();
+    uptr module_offset = addr - module->base_address();
+    const char *str = SendCommand(false, module_name, module_offset);
+    if (str == 0) {
+      // External symbolizer was not initialized or failed. Fill only data
+      // about module name and offset.
+      AddressInfo *info = &frames[0];
+      info->Clear();
+      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
+      return 1;
+    }
+    uptr frame_id = 0;
+    for (frame_id = 0; frame_id < max_frames; frame_id++) {
+      AddressInfo *info = &frames[frame_id];
+      char *function_name = 0;
+      str = ExtractToken(str, "\n", &function_name);
+      CHECK(function_name);
+      if (function_name[0] == '\0') {
+        // There are no more frames.
+        break;
+      }
+      info->Clear();
+      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
+      info->function = function_name;
+      // Parse <file>:<line>:<column> buffer.
+      char *file_line_info = 0;
+      str = ExtractToken(str, "\n", &file_line_info);
+      CHECK(file_line_info);
+      const char *line_info = ExtractToken(file_line_info, ":", &info->file);
+      line_info = ExtractInt(line_info, ":", &info->line);
+      line_info = ExtractInt(line_info, "", &info->column);
+      InternalFree(file_line_info);
+
+      // Functions and filenames can be "??", in which case we write 0
+      // to address info to mark that names are unknown.
+      if (0 == internal_strcmp(info->function, "??")) {
+        InternalFree(info->function);
+        info->function = 0;
+      }
+      if (0 == internal_strcmp(info->file, "??")) {
+        InternalFree(info->file);
+        info->file = 0;
+      }
+    }
+    if (frame_id == 0) {
+      // Make sure we return at least one frame.
+      AddressInfo *info = &frames[0];
+      info->Clear();
+      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
+      frame_id = 1;
+    }
+    return frame_id;
+  }
+
+  bool SymbolizeData(uptr addr, DataInfo *info) {
+    LoadedModule *module = FindModuleForAddress(addr);
+    if (module == 0)
+      return false;
+    const char *module_name = module->full_name();
+    uptr module_offset = addr - module->base_address();
+    internal_memset(info, 0, sizeof(*info));
+    info->address = addr;
+    info->module = internal_strdup(module_name);
+    info->module_offset = module_offset;
+    const char *str = SendCommand(true, module_name, module_offset);
+    if (str == 0)
+      return true;
+    str = ExtractToken(str, "\n", &info->name);
+    str = ExtractUptr(str, " ", &info->start);
+    str = ExtractUptr(str, "\n", &info->size);
+    info->start += module->base_address();
+    return true;
+  }
+
+  bool InitializeExternal(const char *path_to_symbolizer) {
+    if (!path_to_symbolizer || path_to_symbolizer[0] == '\0') {
+      path_to_symbolizer = FindPathToBinary("llvm-symbolizer");
+      if (!path_to_symbolizer)
+        return false;
+    }
+    int input_fd, output_fd;
+    if (!StartSymbolizerSubprocess(path_to_symbolizer, &input_fd, &output_fd))
+      return false;
+    void *mem = symbolizer_allocator.Allocate(sizeof(ExternalSymbolizer));
+    external_symbolizer_ = new(mem) ExternalSymbolizer(path_to_symbolizer,
+                                                       input_fd, output_fd);
+    return true;
+  }
+
+  bool IsAvailable() {
+    if (internal_symbolizer_ == 0)
+      internal_symbolizer_ = InternalSymbolizer::get();
+    return internal_symbolizer_ || external_symbolizer_;
+  }
+
+  void Flush() {
+    if (internal_symbolizer_)
+      internal_symbolizer_->Flush();
+    if (external_symbolizer_)
+      external_symbolizer_->Flush();
+  }
+
+  const char *Demangle(const char *name) {
+    if (IsAvailable() && internal_symbolizer_ != 0)
+      return internal_symbolizer_->Demangle(name);
+    return DemangleCXXABI(name);
+  }
+
+  void PrepareForSandboxing() {
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+    // Cache /proc/self/exe on Linux.
+    CacheBinaryName();
+#endif
+  }
+
+ private:
+  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+    // First, try to use internal symbolizer.
+    if (!IsAvailable()) {
+      return 0;
+    }
+    if (internal_symbolizer_) {
+      return internal_symbolizer_->SendCommand(is_data, module_name,
+                                               module_offset);
+    }
+    // Otherwise, fall back to external symbolizer.
+    if (external_symbolizer_ == 0) {
+      ReportExternalSymbolizerError(
+          "WARNING: Trying to symbolize code, but external "
+          "symbolizer is not initialized!\n");
+      return 0;
+    }
+    for (;;) {
+      char *reply = external_symbolizer_->SendCommand(is_data, module_name,
+          module_offset);
+      if (reply)
+        return reply;
+      // Try to restart symbolizer subprocess. If we don't succeed, forget
+      // about it and don't try to use it later.
+      if (!external_symbolizer_->Restart()) {
+        ReportExternalSymbolizerError(
+            "WARNING: Failed to use and restart external symbolizer!\n");
+        external_symbolizer_ = 0;
+        return 0;
+      }
+    }
+  }
+
+  LoadedModule *FindModuleForAddress(uptr address) {
+    bool modules_were_reloaded = false;
+    if (modules_ == 0 || !modules_fresh_) {
+      modules_ = (LoadedModule*)(symbolizer_allocator.Allocate(
+          kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
+      CHECK(modules_);
+      n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
+                                    /* filter */ 0);
+      // FIXME: Return this check when GetListOfModules is implemented on Mac.
+      // CHECK_GT(n_modules_, 0);
+      CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
+      modules_fresh_ = true;
+      modules_were_reloaded = true;
+    }
+    for (uptr i = 0; i < n_modules_; i++) {
+      if (modules_[i].containsAddress(address)) {
+        return &modules_[i];
+      }
+    }
+    // Reload the modules and look up again, if we haven't tried it yet.
+    if (!modules_were_reloaded) {
+      // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors.
+      // It's too aggressive to reload the list of modules each time we fail
+      // to find a module for a given address.
+      modules_fresh_ = false;
+      return FindModuleForAddress(address);
+    }
+    return 0;
+  }
+
+  void ReportExternalSymbolizerError(const char *msg) {
+    // Don't use atomics here for now, as SymbolizeCode can't be called
+    // from multiple threads anyway.
+    static bool reported;
+    if (!reported) {
+      Report(msg);
+      reported = true;
+    }
+  }
+
+  // 16K loaded modules should be enough for everyone.
+  static const uptr kMaxNumberOfModuleContexts = 1 << 14;
+  LoadedModule *modules_;  // Array of module descriptions is leaked.
+  uptr n_modules_;
+  // If stale, need to reload the modules before looking up addresses.
+  bool modules_fresh_;
+
+  ExternalSymbolizer *external_symbolizer_;  // Leaked.
+  InternalSymbolizer *internal_symbolizer_;  // Leaked.
+};
+
+static Symbolizer symbolizer;  // Linker initialized.
+
+SymbolizerInterface *getSymbolizer() {
+  return &symbolizer;
+}
 
 }  // namespace __sanitizer
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc Tue Sep 10 09:36:16 2013
@@ -14,29 +14,15 @@
 
 #include "sanitizer_platform.h"
 #if SANITIZER_WINDOWS
-#include <windows.h>
-
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_symbolizer.h"
 
 namespace __sanitizer {
 
-bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
-                               int *input_fd, int *output_fd) {
-  UNIMPLEMENTED();
-}
-
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
-                      string_predicate_t filter) {
-  UNIMPLEMENTED();
-};
-
-void SymbolizerPrepareForSandboxing() {
-  // Do nothing on Windows.
-}
+static SymbolizerInterface win_symbolizer;  // Linker initialized.
 
-const char *DemangleCXXABI(const char *name) {
-  return name;
+SymbolizerInterface *getSymbolizer() {
+  return &win_symbolizer;
 }
 
 }  // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Tue Sep 10 09:36:16 2013
@@ -218,6 +218,11 @@ void Abort() {
   _exit(-1);  // abort is not NORETURN on Windows.
 }
 
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+                      string_predicate_t filter) {
+  UNIMPLEMENTED();
+};
+
 #ifndef SANITIZER_GO
 int Atexit(void (*function)(void)) {
   return atexit(function);

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc Tue Sep 10 09:36:16 2013
@@ -217,7 +217,7 @@ void Initialize(ThreadState *thr) {
   // Initialize external symbolizer before internal threads are started.
   const char *external_symbolizer = flags()->external_symbolizer_path;
   if (external_symbolizer != 0 && external_symbolizer[0] != '\0') {
-    if (!InitializeExternalSymbolizer(external_symbolizer)) {
+    if (!getSymbolizer()->InitializeExternal(external_symbolizer)) {
       Printf("Failed to start external symbolizer: '%s'\n",
              external_symbolizer);
       Die();

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc Tue Sep 10 09:36:16 2013
@@ -70,15 +70,15 @@ static ReportStack *NewReportStackEntry(
 }
 
 ReportStack *SymbolizeCode(uptr addr) {
-  if (!IsSymbolizerAvailable())
+  if (!getSymbolizer()->IsAvailable())
     return SymbolizeCodeAddr2Line(addr);
   ScopedInSymbolizer in_symbolizer;
   static const uptr kMaxAddrFrames = 16;
   InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
   for (uptr i = 0; i < kMaxAddrFrames; i++)
     new(&addr_frames[i]) AddressInfo();
-  uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
-                                                    kMaxAddrFrames);
+  uptr addr_frames_num =
+      getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames);
   if (addr_frames_num == 0)
     return NewReportStackEntry(addr);
   ReportStack *top = 0;
@@ -97,11 +97,11 @@ ReportStack *SymbolizeCode(uptr addr) {
 }
 
 ReportLocation *SymbolizeData(uptr addr) {
-  if (!IsSymbolizerAvailable())
+  if (!getSymbolizer()->IsAvailable())
     return 0;
   ScopedInSymbolizer in_symbolizer;
   DataInfo info;
-  if (!__sanitizer::SymbolizeData(addr, &info))
+  if (!getSymbolizer()->SymbolizeData(addr, &info))
     return 0;
   ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack,
                                                         sizeof(ReportLocation));
@@ -117,10 +117,10 @@ ReportLocation *SymbolizeData(uptr addr)
 }
 
 void SymbolizeFlush() {
-  if (!IsSymbolizerAvailable())
+  if (!getSymbolizer()->IsAvailable())
     return;
   ScopedInSymbolizer in_symbolizer;
-  __sanitizer::FlushSymbolizer();
+  getSymbolizer()->Flush();
 }
 
 }  // namespace __tsan

Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=190410&r1=190409&r2=190410&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Tue Sep 10 09:36:16 2013
@@ -28,7 +28,8 @@ Location __ubsan::getCallerLocation(uptr
   uptr Loc = StackTrace::GetPreviousInstructionPc(CallerLoc);
 
   AddressInfo Info;
-  if (!SymbolizeCode(Loc, &Info, 1) || !Info.module || !*Info.module)
+  if (!getSymbolizer()->SymbolizeCode(Loc, &Info, 1) ||
+      !Info.module || !*Info.module)
     return Location(Loc);
 
   if (!Info.file)
@@ -109,7 +110,7 @@ static void renderText(const char *Messa
         Printf("%s", A.String);
         break;
       case Diag::AK_Mangled: {
-        Printf("'%s'", Demangle(A.String));
+        Printf("'%s'", getSymbolizer()->Demangle(A.String));
         break;
       }
       case Diag::AK_SInt:





More information about the llvm-commits mailing list