[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