From bad01549b6c0c2c3a9acbca22a9c9dae3b32654a Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Tue, 18 Dec 2012 07:32:16 +0000 Subject: [PATCH] [asan] add some colors to asan output if printing to tty (following ubsan) llvm-svn: 170418 --- compiler-rt/lib/asan/asan_report.cc | 77 ++++++++++++++++--- .../sanitizer_report_decorator.h | 37 +++++++++ 2 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index 5ad9115657de..168957d21eea 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -18,6 +18,8 @@ #include "asan_stack.h" #include "asan_thread.h" #include "asan_thread_registry.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_report_decorator.h" namespace __asan { @@ -40,6 +42,20 @@ void AppendToErrorMessageBuffer(const char *buffer) { } } +// ---------------------- Decorator ------------------------------ {{{1 +class Decorator: private __sanitizer::AnsiColorDecorator { + public: + Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTty()) { } + const char *Warning() { return Red(); } + const char *EndWarning() { return Default(); } + const char *Access() { return Blue(); } + const char *EndAccess() { return Default(); } + const char *Location() { return Green(); } + const char *EndLocation() { return Default(); } + const char *Allocation() { return Magenta(); } + const char *EndAllocation() { return Default(); } +}; + // ---------------------- Helper functions ----------------------- {{{1 static void PrintBytes(const char *before, uptr *a) { @@ -100,6 +116,8 @@ static void PrintGlobalNameIfASCII(const __asan_global &g) { bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) { if (addr < g.beg - kGlobalAndStackRedzone) return false; if (addr >= g.beg + g.size_with_redzone) return false; + Decorator d; + Printf("%s", d.Location()); Printf("%p is located ", (void*)addr); if (addr < g.beg) { Printf("%zd bytes to the left", g.beg - addr); @@ -110,6 +128,7 @@ bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) { } Printf(" of global variable '%s' (0x%zx) of size %zu\n", g.name, g.beg, g.size); + Printf("%s", d.EndLocation()); PrintGlobalNameIfASCII(g); return true; } @@ -153,9 +172,12 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) { internal_strncat(buf, frame_descr, Min(kBufSize, static_cast(name_end - frame_descr))); + Decorator d; + Printf("%s", d.Location()); Printf("Address %p is located at offset %zu " "in frame <%s> of T%d's stack:\n", (void*)addr, offset, buf, t->tid()); + Printf("%s", d.EndLocation()); // Report the number of stack objects. char *p; uptr n_objects = internal_simple_strtoll(name_end, &p, 10); @@ -189,6 +211,8 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) { static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, uptr access_size) { uptr offset; + Decorator d; + Printf("%s", d.Location()); Printf("%p is located ", (void*)addr); if (chunk.AddrIsInside(addr, access_size, &offset)) { Printf("%zu bytes inside of", offset); @@ -201,6 +225,7 @@ static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, } Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(), (void*)(chunk.Beg()), (void*)(chunk.End())); + Printf("%s", d.EndLocation()); } // Return " (thread_name) " or an empty string if the name is empty. @@ -234,24 +259,30 @@ void DescribeHeapAddress(uptr addr, uptr access_size) { AsanThread *t = asanThreadRegistry().GetCurrent(); CHECK(t); char tname[128]; + Decorator d; if (chunk.FreeTid() != kInvalidTid) { AsanThreadSummary *free_thread = asanThreadRegistry().FindByTid(chunk.FreeTid()); - Printf("freed by thread T%d%s here:\n", free_thread->tid(), - ThreadNameWithParenthesis(free_thread, tname, sizeof(tname))); + Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), + free_thread->tid(), + ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)), + d.EndAllocation()); StackTrace free_stack; chunk.GetFreeStack(&free_stack); PrintStack(&free_stack); - Printf("previously allocated by thread T%d%s here:\n", - alloc_thread->tid(), - ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname))); + Printf("%spreviously allocated by thread T%d%s here:%s\n", + d.Allocation(), alloc_thread->tid(), + ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), + d.EndAllocation()); PrintStack(&alloc_stack); DescribeThread(t->summary()); DescribeThread(free_thread); DescribeThread(alloc_thread); } else { - Printf("allocated by thread T%d%s here:\n", alloc_thread->tid(), - ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname))); + Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(), + alloc_thread->tid(), + ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), + d.EndAllocation()); PrintStack(&alloc_stack); DescribeThread(t->summary()); DescribeThread(alloc_thread); @@ -353,10 +384,13 @@ class ScopedInErrorReport { void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { ScopedInErrorReport in_report; + Decorator d; + Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: SEGV on unknown address %p" " (pc %p sp %p bp %p T%d)\n", (void*)addr, (void*)pc, (void*)sp, (void*)bp, asanThreadRegistry().GetCurrentTidOrInvalid()); + Printf("%s", d.EndWarning()); Printf("AddressSanitizer can not provide additional info.\n"); GET_STACK_TRACE_FATAL(pc, bp); PrintStack(&stack); @@ -364,33 +398,45 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { void ReportDoubleFree(uptr addr, StackTrace *stack) { ScopedInErrorReport in_report; + Decorator d; + Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr); + Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); } void ReportFreeNotMalloced(uptr addr, StackTrace *stack) { ScopedInErrorReport in_report; + Decorator d; + Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: attempting free on address " "which was not malloc()-ed: %p\n", addr); + Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); } void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) { ScopedInErrorReport in_report; + Decorator d; + Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: attempting to call " "malloc_usable_size() for pointer which is " "not owned: %p\n", addr); + Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); } void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) { ScopedInErrorReport in_report; + Decorator d; + Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: attempting to call " "__asan_get_allocated_size() for pointer which is " "not owned: %p\n", addr); + Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); } @@ -399,9 +445,12 @@ void ReportStringFunctionMemoryRangesOverlap( const char *function, const char *offset1, uptr length1, const char *offset2, uptr length2, StackTrace *stack) { ScopedInErrorReport in_report; + Decorator d; + Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: %s-param-overlap: " "memory ranges [%p,%p) and [%p, %p) overlap\n", \ function, offset1, offset1 + length1, offset2, offset2 + length2); + Printf("%s", d.EndWarning()); PrintStack(stack); DescribeAddress((uptr)offset1, length1); DescribeAddress((uptr)offset2, length2); @@ -494,17 +543,21 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, break; } } - + Decorator d; + Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: %s on address " "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n", bug_descr, (void*)addr, pc, bp, sp); + Printf("%s", d.EndWarning()); u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); char tname[128]; - Printf("%s of size %zu at %p thread T%d%s\n", - access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", - access_size, (void*)addr, curr_tid, - ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); + Printf("%s%s of size %zu at %p thread T%d%s%s\n", + d.Access(), + access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", + access_size, (void*)addr, curr_tid, + ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)), + d.EndAccess()); GET_STACK_TRACE_FATAL(pc, bp); PrintStack(&stack); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h b/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h new file mode 100644 index 000000000000..50a3ee572fdb --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h @@ -0,0 +1,37 @@ +//===-- sanitizer_report_decorator.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tags to decorate the sanitizer reports. +// Currently supported tags: +// * None. +// * ANSI color sequences. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_ALLOCATOR_H +#define SANITIZER_ALLOCATOR_H + +namespace __sanitizer { +class AnsiColorDecorator { + public: + explicit AnsiColorDecorator(bool use_ansi_colors) : ansi_(use_ansi_colors) { } + const char *Black() { return ansi_ ? "\033[1m\033[30m" : ""; } + const char *Red() { return ansi_ ? "\033[1m\033[31m" : ""; } + const char *Green() { return ansi_ ? "\033[1m\033[32m" : ""; } + const char *Yellow() { return ansi_ ? "\033[1m\033[33m" : ""; } + const char *Blue() { return ansi_ ? "\033[1m\033[34m" : ""; } + const char *Magenta() { return ansi_ ? "\033[1m\033[35m" : ""; } + const char *Cyan() { return ansi_ ? "\033[1m\033[36m" : ""; } + const char *White() { return ansi_ ? "\033[1m\033[37m" : ""; } + const char *Default() { return ansi_ ? "\033[1m\033[0m" : ""; } + private: + bool ansi_; +}; +} // namespace __sanitizer +#endif // SANITIZER_ALLOCATOR_H