[llvm-commits] [compiler-rt] r165000 - in /compiler-rt/trunk: include/sanitizer/asan_interface.h lib/asan/asan_internal.h lib/asan/asan_rtl.cc lib/asan/asan_stack.cc lib/asan/asan_win.cc lib/asan/lit_tests/symbolize_callback.cc lib/sanitizer_common/sanitizer_stacktrace.cc

Alexey Samsonov samsonov at google.com
Tue Oct 2 05:11:17 PDT 2012


Author: samsonov
Date: Tue Oct  2 07:11:17 2012
New Revision: 165000

URL: http://llvm.org/viewvc/llvm-project?rev=165000&view=rev
Log:
[Sanitizer/ASan] Simplify the code that prints and symbolizes stack traces. Fall back to module+offset if user-provided symbolizer failed. Use weak function __asan_symbolize instead of __asan_set_symbolize_callback in ASan interface, so that we're able to symbolize reports for errors that happen before the main() is called, for example, during module initialization.

Modified:
    compiler-rt/trunk/include/sanitizer/asan_interface.h
    compiler-rt/trunk/lib/asan/asan_internal.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/asan/asan_stack.cc
    compiler-rt/trunk/lib/asan/asan_win.cc
    compiler-rt/trunk/lib/asan/lit_tests/symbolize_callback.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc

Modified: compiler-rt/trunk/include/sanitizer/asan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/asan_interface.h?rev=165000&r1=164999&r2=165000&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/asan_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/asan_interface.h Tue Oct  2 07:11:17 2012
@@ -135,15 +135,13 @@
   void __asan_set_on_error_callback(void (*callback)(void))
       SANITIZER_INTERFACE_ATTRIBUTE;
 
-  // User may register its own symbolization function. It should print
-  // the description of instruction at address "pc" to "out_buffer".
-  // Description should be at most "out_size" bytes long.
+  // User may provide its own implementation for symbolization function.
+  // It should print the description of instruction at address "pc" to
+  // "out_buffer". Description should be at most "out_size" bytes long.
   // User-specified function should return true if symbolization was
   // successful.
-  typedef bool (*__asan_symbolize_callback)(const void *pc, char *out_buffer,
-                                            int out_size);
-  void __asan_set_symbolize_callback(__asan_symbolize_callback callback)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  bool __asan_symbolize(const void *pc, char *out_buffer, int out_size)
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
 
   // Returns the estimated number of bytes that will be reserved by allocator
   // for request of "size" bytes. If ASan allocator can't allocate that much

Modified: compiler-rt/trunk/lib/asan/asan_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_internal.h?rev=165000&r1=164999&r2=165000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_internal.h Tue Oct  2 07:11:17 2012
@@ -149,10 +149,6 @@
 extern bool asan_init_is_running;
 extern void (*death_callback)(void);
 
-#ifdef _WIN32
-bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size);
-#endif  // _WIN32
-
 // These magic values are written to shadow for better error reporting.
 const int kAsanHeapLeftRedzoneMagic = 0xfa;
 const int kAsanHeapRightRedzoneMagic = 0xfb;

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=165000&r1=164999&r2=165000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Tue Oct  2 07:11:17 2012
@@ -247,7 +247,7 @@
     case 33: __asan_after_dynamic_init(); break;
     case 34: __asan_malloc_hook(0, 0); break;
     case 35: __asan_free_hook(0); break;
-    case 36: __asan_set_symbolize_callback(0); break;
+    case 36: __asan_symbolize(0, 0, 0); break;
   }
 }
 
@@ -376,9 +376,6 @@
       InitializeExternalSymbolizer(external_symbolizer);
     }
   }
-#ifdef _WIN32
-  __asan_set_symbolize_callback(WinSymbolize);
-#endif  // _WIN32
 
   // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
   // should be set to 1 prior to initializing the threads.

Modified: compiler-rt/trunk/lib/asan/asan_stack.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_stack.cc?rev=165000&r1=164999&r2=165000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_stack.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_stack.cc Tue Oct  2 07:11:17 2012
@@ -17,20 +17,21 @@
 
 namespace __asan {
 
-static __asan_symbolize_callback symbolize_callback;
-
 void PrintStack(StackTrace *stack) {
   stack->PrintStack(stack->trace, stack->size, flags()->symbolize,
-                    flags()->strip_path_prefix, symbolize_callback);
+                    flags()->strip_path_prefix, __asan_symbolize);
 }
 
-
 }  // namespace __asan
 
 // ------------------ Interface -------------- {{{1
-using namespace __asan;  // NOLINT
 
-void NOINLINE __asan_set_symbolize_callback(
-    __asan_symbolize_callback callback) {
-  symbolize_callback = callback;
+// Provide default implementation of __asan_symbolize that does nothing
+// and may be overriden by user if he wants to use his own symbolization.
+// ASan on Windows has its own implementation of this.
+#ifndef _WIN32
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
+bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
+  return false;
 }
+#endif

Modified: compiler-rt/trunk/lib/asan/asan_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win.cc?rev=165000&r1=164999&r2=165000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win.cc Tue Oct  2 07:11:17 2012
@@ -55,47 +55,6 @@
     stack->trace[i] = (uptr)tmp[i + offset];
 }
 
-bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size) {
-  ScopedLock lock(&dbghelp_lock);
-  if (!dbghelp_initialized) {
-    SymSetOptions(SYMOPT_DEFERRED_LOADS |
-                  SYMOPT_UNDNAME |
-                  SYMOPT_LOAD_LINES);
-    CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
-    // FIXME: We don't call SymCleanup() on exit yet - should we?
-    dbghelp_initialized = true;
-  }
-
-  // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
-  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
-  PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
-  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
-  symbol->MaxNameLen = MAX_SYM_NAME;
-  DWORD64 offset = 0;
-  BOOL got_objname = SymFromAddr(GetCurrentProcess(),
-                                 (DWORD64)addr, &offset, symbol);
-  if (!got_objname)
-    return false;
-
-  DWORD  unused;
-  IMAGEHLP_LINE64 info;
-  info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-  BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
-                                           (DWORD64)addr, &unused, &info);
-  int written = 0;
-  out_buffer[0] = '\0';
-  // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
-  if (got_fileline) {
-    written += internal_snprintf(out_buffer + written, buffer_size - written,
-                        " %s %s:%d", symbol->Name,
-                        info.FileName, info.LineNumber);
-  } else {
-    written += internal_snprintf(out_buffer + written, buffer_size - written,
-                        " %s+0x%p", symbol->Name, offset);
-  }
-  return true;
-}
-
 // ---------------------- AsanLock ---------------- {{{1
 enum LockState {
   LOCK_UNINITIALIZED = 0,
@@ -182,4 +141,50 @@
 
 }  // namespace __asan
 
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;  // NOLINT
+
+bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) {
+  ScopedLock lock(&dbghelp_lock);
+  if (!dbghelp_initialized) {
+    SymSetOptions(SYMOPT_DEFERRED_LOADS |
+                  SYMOPT_UNDNAME |
+                  SYMOPT_LOAD_LINES);
+    CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
+    // FIXME: We don't call SymCleanup() on exit yet - should we?
+    dbghelp_initialized = true;
+  }
+
+  // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
+  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
+  PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
+  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+  symbol->MaxNameLen = MAX_SYM_NAME;
+  DWORD64 offset = 0;
+  BOOL got_objname = SymFromAddr(GetCurrentProcess(),
+                                 (DWORD64)addr, &offset, symbol);
+  if (!got_objname)
+    return false;
+
+  DWORD  unused;
+  IMAGEHLP_LINE64 info;
+  info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+  BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
+                                           (DWORD64)addr, &unused, &info);
+  int written = 0;
+  out_buffer[0] = '\0';
+  // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
+  if (got_fileline) {
+    written += internal_snprintf(out_buffer + written, buffer_size - written,
+                        " %s %s:%d", symbol->Name,
+                        info.FileName, info.LineNumber);
+  } else {
+    written += internal_snprintf(out_buffer + written, buffer_size - written,
+                        " %s+0x%p", symbol->Name, offset);
+  }
+  return true;
+}
+
+
+
 #endif  // _WIN32

Modified: compiler-rt/trunk/lib/asan/lit_tests/symbolize_callback.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/symbolize_callback.cc?rev=165000&r1=164999&r2=165000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/symbolize_callback.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/symbolize_callback.cc Tue Oct  2 07:11:17 2012
@@ -3,17 +3,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-bool MySymbolizer(const void *pc, char *out_buffer, int out_size) {
+extern "C"
+bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
   snprintf(out_buffer, out_size, "MySymbolizer");
   return true;
 }
 
-typedef bool (*asan_symbolize_callback)(const void*, char*, int);
-extern "C"
-void __asan_set_symbolize_callback(asan_symbolize_callback);
-
 int main() {
-  __asan_set_symbolize_callback(MySymbolizer);
   char *x = (char*)malloc(10 * sizeof(char));
   free(x);
   return x[5];

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=165000&r1=164999&r2=165000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc Tue Oct  2 07:11:17 2012
@@ -36,6 +36,26 @@
   return pc - 1;
 }
 
+static void PrintStackFramePrefix(uptr frame_num, uptr pc) {
+  Printf("    #%zu 0x%zx", frame_num, pc);
+}
+
+static void PrintSourceLocation(const char *file, int line, int column,
+                                const char *strip_file_prefix) {
+  CHECK(file);
+  Printf(" %s", StripPathPrefix(file, strip_file_prefix));
+  if (line > 0) {
+    Printf(":%d", line);
+    if (column > 0)
+      Printf(":%d", column);
+  }
+}
+
+static void PrintModuleAndOffset(const char *module, uptr offset,
+                                 const char *strip_file_prefix) {
+  Printf(" (%s+0x%zx)", StripPathPrefix(module, strip_file_prefix), offset);
+}
+
 void StackTrace::PrintStack(const uptr *addr, uptr size,
                             bool symbolize, const char *strip_file_prefix,
                             SymbolizeCallback symbolize_callback ) {
@@ -45,45 +65,49 @@
   uptr frame_num = 0;
   for (uptr i = 0; i < size && addr[i]; i++) {
     uptr pc = patch_pc(addr[i]);
+    uptr addr_frames_num = 0;  // The number of stack frames for current
+                               // instruction address.
     if (symbolize_callback) {
-      symbolize_callback((void*)pc, buff.data(), buff.size());
-      // 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.
-      Printf("  #%zu 0x%zx %s\n", frame_num, pc,
-             StripPathPrefix(buff.data(), strip_file_prefix));
-      frame_num++;
-      continue;
-    }
-    uptr addr_frames_num =
-      symbolize ? SymbolizeCode(pc, addr_frames.data(), addr_frames.size()) : 0;
-    if (addr_frames_num > 0) {
+      if (symbolize_callback((void*)pc, buff.data(), buff.size())) {
+        addr_frames_num = 1;
+        PrintStackFramePrefix(frame_num, pc);
+        // 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.
+        Printf(" %s\n", StripPathPrefix(buff.data(), strip_file_prefix));
+        frame_num++;
+      }
+    } else if (symbolize) {
+      // Use our own (online) symbolizer, if necessary.
+      addr_frames_num = SymbolizeCode(pc, addr_frames.data(), addr_frames.size());
       for (uptr j = 0; j < addr_frames_num; j++) {
         AddressInfo &info = addr_frames[j];
-        Printf("    #%zu 0x%zx", frame_num, pc);
+        PrintStackFramePrefix(frame_num, pc);
         if (info.function) {
           Printf(" in %s", info.function);
         }
         if (info.file) {
-          Printf(" %s:%d:%d", StripPathPrefix(info.file, strip_file_prefix),
-                 info.line, info.column);
+          PrintSourceLocation(info.file, info.line, info.column,
+                              strip_file_prefix);
         } else if (info.module) {
-          Printf(" (%s+0x%zx)", StripPathPrefix(info.module, strip_file_prefix),
-                 info.module_offset);
+          PrintModuleAndOffset(info.module, info.module_offset,
+                               strip_file_prefix);
         }
         Printf("\n");
         info.Clear();
         frame_num++;
       }
-    } else {
+    }
+    if (addr_frames_num == 0) {
+      // If online symbolization failed, try to output at least module and
+      // offset for instruction.
+      PrintStackFramePrefix(frame_num, pc);
       uptr offset;
       if (proc_maps.GetObjectNameAndOffset(pc, &offset,
                                            buff.data(), buff.size())) {
-        Printf("    #%zu 0x%zx (%s+0x%zx)\n", frame_num, pc,
-               StripPathPrefix(buff.data(), strip_file_prefix), offset);
-      } else {
-        Printf("    #%zu 0x%zx\n", frame_num, pc);
+        PrintModuleAndOffset(buff.data(), offset, strip_file_prefix);
       }
+      Printf("\n");
       frame_num++;
     }
   }





More information about the llvm-commits mailing list