[compiler-rt] r194686 - [Sanitizer] Print symbolized stack frame using a single Printf() call.

Alexey Samsonov samsonov at google.com
Thu Nov 14 01:41:25 PST 2013


Author: samsonov
Date: Thu Nov 14 03:41:24 2013
New Revision: 194686

URL: http://llvm.org/viewvc/llvm-project?rev=194686&view=rev
Log:
[Sanitizer] Print symbolized stack frame using a single Printf() call.

This reduces the number of "write" syscalls performed to print a single
stack frame description, and makes sanitizer output less intermixed with
program output. Also, add a number of unit tests.

Modified:
    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_printf.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc

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=194686&r1=194685&r2=194686&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc Thu Nov 14 03:41:24 2013
@@ -150,19 +150,23 @@ const char *StripPathPrefix(const char *
   return pos;
 }
 
-void PrintSourceLocation(const char *file, int line, int column) {
+void PrintSourceLocation(InternalScopedString *buffer, const char *file,
+                         int line, int column) {
   CHECK(file);
-  Printf("%s", StripPathPrefix(file, common_flags()->strip_path_prefix));
+  buffer->append("%s",
+                 StripPathPrefix(file, common_flags()->strip_path_prefix));
   if (line > 0) {
-    Printf(":%d", line);
+    buffer->append(":%d", line);
     if (column > 0)
-      Printf(":%d", column);
+      buffer->append(":%d", column);
   }
 }
 
-void PrintModuleAndOffset(const char *module, uptr offset) {
-  Printf("(%s+0x%zx)",
-         StripPathPrefix(module, common_flags()->strip_path_prefix), offset);
+void PrintModuleAndOffset(InternalScopedString *buffer, const char *module,
+                          uptr offset) {
+  buffer->append("(%s+0x%zx)",
+                 StripPathPrefix(module, common_flags()->strip_path_prefix),
+                 offset);
 }
 
 void ReportErrorSummary(const char *error_message) {

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=194686&r1=194685&r2=194686&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Thu Nov 14 03:41:24 2013
@@ -87,6 +87,23 @@ class InternalScopedBuffer {
   void operator=(const InternalScopedBuffer&);
 };
 
+class InternalScopedString : public InternalScopedBuffer<char> {
+ public:
+  explicit InternalScopedString(uptr max_length)
+      : InternalScopedBuffer<char>(max_length), length_(0) {
+    (*this)[0] = '\0';
+  }
+  uptr length() { return length_; }
+  void clear() {
+    (*this)[0] = '\0';
+    length_ = 0;
+  }
+  void append(const char *format, ...);
+
+ private:
+  uptr length_;
+};
+
 // Simple low-level (mmap-based) allocator for internal use. Doesn't have
 // constructor, so all instances of LowLevelAllocator should be
 // linker initialized.
@@ -111,6 +128,7 @@ bool PrintsToTtyCached();
 void Printf(const char *format, ...);
 void Report(const char *format, ...);
 void SetPrintfAndReportCallback(void (*callback)(const char *));
+
 // Can be used to prevent mixing error reports from different sanitizers.
 extern StaticSpinMutex CommonSanitizerReportMutex;
 void MaybeOpenReportFile();
@@ -134,9 +152,10 @@ void *MapFileToMemory(const char *file_n
 // Error report formatting.
 const char *StripPathPrefix(const char *filepath,
                             const char *strip_file_prefix);
-void PrintSourceLocation(const char *file, int line, int column);
-void PrintModuleAndOffset(const char *module, uptr offset);
-
+void PrintSourceLocation(InternalScopedString *buffer, const char *file,
+                         int line, int column);
+void PrintModuleAndOffset(InternalScopedString *buffer,
+                          const char *module, uptr offset);
 
 // OS
 void DisableCoreDumper();

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_printf.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_printf.cc?rev=194686&r1=194685&r2=194686&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_printf.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_printf.cc Thu Nov 14 03:41:24 2013
@@ -294,4 +294,13 @@ int internal_snprintf(char *buffer, uptr
   return needed_length;
 }
 
+void InternalScopedString::append(const char *format, ...) {
+  CHECK_LT(length_, size());
+  va_list args;
+  va_start(args, format);
+  VSNPrintf(data() + length_, size() - length_, format, args);
+  va_end(args);
+  length_ += internal_strlen(data() + length_);
+}
+
 }  // namespace __sanitizer

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=194686&r1=194685&r2=194686&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.cc Thu Nov 14 03:41:24 2013
@@ -34,8 +34,9 @@ uptr StackTrace::GetPreviousInstructionP
 #endif
 }
 
-static void PrintStackFramePrefix(uptr frame_num, uptr pc) {
-  Printf("    #%zu 0x%zx", frame_num, pc);
+static void PrintStackFramePrefix(InternalScopedString *buffer, uptr frame_num,
+                                  uptr pc) {
+  buffer->append("    #%zu 0x%zx", frame_num, pc);
 }
 
 void StackTrace::PrintStack(const uptr *addr, uptr size,
@@ -47,6 +48,7 @@ void StackTrace::PrintStack(const uptr *
   MemoryMappingLayout proc_maps(/*cache_enabled*/true);
   InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
   InternalScopedBuffer<AddressInfo> addr_frames(64);
+  InternalScopedString frame_desc(GetPageSizeCached() * 2);
   uptr frame_num = 0;
   for (uptr i = 0; i < size && addr[i]; i++) {
     // PCs in stack traces are actually the return addresses, that is,
@@ -57,12 +59,15 @@ void StackTrace::PrintStack(const uptr *
     if (symbolize_callback) {
       if (symbolize_callback((void*)pc, buff.data(), buff.size())) {
         addr_frames_num = 1;
-        PrintStackFramePrefix(frame_num, pc);
+        frame_desc.clear();
+        PrintStackFramePrefix(&frame_desc, 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(), common_flags()->strip_path_prefix));
+        frame_desc.append(
+            " %s",
+            StripPathPrefix(buff.data(), common_flags()->strip_path_prefix));
+        Printf("%s\n", frame_desc.data());
         frame_num++;
       }
     }
@@ -73,34 +78,36 @@ void StackTrace::PrintStack(const uptr *
             sym->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);
+        frame_desc.clear();
+        PrintStackFramePrefix(&frame_desc, frame_num, pc);
         if (info.function) {
-          Printf(" in %s", info.function);
+          frame_desc.append(" in %s", info.function);
         }
         if (info.file) {
-          Printf(" ");
-          PrintSourceLocation(info.file, info.line, info.column);
+          frame_desc.append(" ");
+          PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
         } else if (info.module) {
-          Printf(" ");
-          PrintModuleAndOffset(info.module, info.module_offset);
+          frame_desc.append(" ");
+          PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
         }
-        Printf("\n");
-        info.Clear();
+        Printf("%s\n", frame_desc.data());
         frame_num++;
+        info.Clear();
       }
     }
     if (addr_frames_num == 0) {
       // If online symbolization failed, try to output at least module and
       // offset for instruction.
-      PrintStackFramePrefix(frame_num, pc);
+      frame_desc.clear();
+      PrintStackFramePrefix(&frame_desc, frame_num, pc);
       uptr offset;
       if (proc_maps.GetObjectNameAndOffset(pc, &offset,
                                            buff.data(), buff.size(),
                                            /* protection */0)) {
-        Printf(" ");
-        PrintModuleAndOffset(buff.data(), offset);
+        frame_desc.append(" ");
+        PrintModuleAndOffset(&frame_desc, buff.data(), offset);
       }
-      Printf("\n");
+      Printf("%s\n", frame_desc.data());
       frame_num++;
     }
   }

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc?rev=194686&r1=194685&r2=194686&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc Thu Nov 14 03:41:24 2013
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 #include "sanitizer_common/sanitizer_allocator_internal.h"
 #include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_platform.h"
 #include "gtest/gtest.h"
@@ -192,4 +193,67 @@ TEST(SanitizerCommon, StripPathPrefix) {
   EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/"));
 }
 
+TEST(SanitizerCommon, InternalScopedString) {
+  InternalScopedString str(10);
+  EXPECT_EQ(0U, str.length());
+  EXPECT_STREQ("", str.data());
+
+  str.append("foo");
+  EXPECT_EQ(3U, str.length());
+  EXPECT_STREQ("foo", str.data());
+
+  int x = 1234;
+  str.append("%d", x);
+  EXPECT_EQ(7U, str.length());
+  EXPECT_STREQ("foo1234", str.data());
+
+  str.append("%d", x);
+  EXPECT_EQ(9U, str.length());
+  EXPECT_STREQ("foo123412", str.data());
+
+  str.clear();
+  EXPECT_EQ(0U, str.length());
+  EXPECT_STREQ("", str.data());
+
+  str.append("0123456789");
+  EXPECT_EQ(9U, str.length());
+  EXPECT_STREQ("012345678", str.data());
+}
+
+TEST(SanitizerCommon, PrintSourceLocation) {
+  InternalScopedString str(128);
+  PrintSourceLocation(&str, "/dir/file.cc", 10, 5);
+  EXPECT_STREQ("/dir/file.cc:10:5", str.data());
+
+  str.clear();
+  PrintSourceLocation(&str, "/dir/file.cc", 11, 0);
+  EXPECT_STREQ("/dir/file.cc:11", str.data());
+
+  str.clear();
+  PrintSourceLocation(&str, "/dir/file.cc", 0, 0);
+  EXPECT_STREQ("/dir/file.cc", str.data());
+
+  // Check that we strip file prefix if necessary.
+  const char *old_strip_path_prefix = common_flags()->strip_path_prefix;
+  common_flags()->strip_path_prefix = "/dir/";
+  str.clear();
+  PrintSourceLocation(&str, "/dir/file.cc", 10, 5);
+  EXPECT_STREQ("file.cc:10:5", str.data());
+  common_flags()->strip_path_prefix = old_strip_path_prefix;
+}
+
+TEST(SanitizerCommon, PrintModuleAndOffset) {
+  InternalScopedString str(128);
+  PrintModuleAndOffset(&str, "/dir/exe", 0x123);
+  EXPECT_STREQ("(/dir/exe+0x123)", str.data());
+
+  // Check that we strip file prefix if necessary.
+  const char *old_strip_path_prefix = common_flags()->strip_path_prefix;
+  common_flags()->strip_path_prefix = "/dir/";
+  str.clear();
+  PrintModuleAndOffset(&str, "/dir/exe", 0x123);
+  EXPECT_STREQ("(exe+0x123)", str.data());
+  common_flags()->strip_path_prefix = old_strip_path_prefix;
+}
+
 }  // namespace __sanitizer





More information about the llvm-commits mailing list