[asan] add some colors to asan output if printing to tty (following ubsan)

llvm-svn: 170418
This commit is contained in:
Kostya Serebryany 2012-12-18 07:32:16 +00:00
parent 6d315cbcc3
commit bad01549b6
2 changed files with 102 additions and 12 deletions

View File

@ -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<sptr>(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);

View File

@ -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