diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.cc | 18 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 25 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_printf.cc | 9 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_stacktrace.cc | 41 | ||||
-rw-r--r-- | lib/sanitizer_common/tests/sanitizer_common_test.cc | 64 |
5 files changed, 130 insertions, 27 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 9c331a8e4..3af4d4fb6 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -150,19 +150,23 @@ const char *StripPathPrefix(const char *filepath, 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) { diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index dda72b59b..daf9892d9 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -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_name, uptr *buff_size); // 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(); diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 4f3968ad2..bbdb24b68 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -294,4 +294,13 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) { 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 diff --git a/lib/sanitizer_common/sanitizer_stacktrace.cc b/lib/sanitizer_common/sanitizer_stacktrace.cc index 8e591189d..62cb12d8d 100644 --- a/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -34,8 +34,9 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) { #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 *addr, uptr size, 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 *addr, uptr size, 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 *addr, uptr size, 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++; } } diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc index fd51e4fcb..608f90487 100644 --- a/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_common_test.cc @@ -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 |