From 5c153faa535f671dd0e8d40ab43397f2d3c6f6f5 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Tue, 18 Sep 2012 07:38:10 +0000 Subject: [ASan] Move printing descriptions of heap addresses in error report from allocator internals to asan_report.cc. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@164112 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_allocator.cc | 129 +++++++++++++++++---------------------------- lib/asan/asan_allocator.h | 20 +++++++ lib/asan/asan_report.cc | 48 +++++++++++++++++ 3 files changed, 117 insertions(+), 80 deletions(-) (limited to 'lib') diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc index dcec1ec78..de3713756 100644 --- a/lib/asan/asan_allocator.cc +++ b/lib/asan/asan_allocator.cc @@ -199,50 +199,50 @@ struct AsanChunk: public ChunkBase { if (REDZONE < sizeof(ChunkBase)) return 0; return (REDZONE) / sizeof(u32); } +}; - bool AddrIsInside(uptr addr, uptr access_size, uptr *offset) { - if (addr >= Beg() && (addr + access_size) <= (Beg() + used_size)) { - *offset = addr - Beg(); - return true; - } - return false; - } +uptr AsanChunkView::Beg() { return chunk_->Beg(); } +uptr AsanChunkView::End() { return Beg() + UsedSize(); } +uptr AsanChunkView::UsedSize() { return chunk_->used_size; } +uptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; } +uptr AsanChunkView::FreeTid() { return chunk_->free_tid; } - bool AddrIsAtLeft(uptr addr, uptr access_size, uptr *offset) { - if (addr < Beg()) { - *offset = Beg() - addr; - return true; - } - return false; +void AsanChunkView::GetAllocStack(StackTrace *stack) { + StackTrace::UncompressStack(stack, chunk_->compressed_alloc_stack(), + chunk_->compressed_alloc_stack_size()); +} + +void AsanChunkView::GetFreeStack(StackTrace *stack) { + StackTrace::UncompressStack(stack, chunk_->compressed_free_stack(), + chunk_->compressed_free_stack_size()); +} + +bool AsanChunkView::AddrIsInside(uptr addr, uptr access_size, uptr *offset) { + if (addr >= Beg() && (addr + access_size) <= End()) { + *offset = addr - Beg(); + return true; } + return false; +} - bool AddrIsAtRight(uptr addr, uptr access_size, uptr *offset) { - if (addr + access_size >= Beg() + used_size) { - if (addr <= Beg() + used_size) - *offset = 0; - else - *offset = addr - (Beg() + used_size); - return true; - } - return false; +bool AsanChunkView::AddrIsAtLeft(uptr addr, uptr access_size, uptr *offset) { + if (addr < Beg()) { + *offset = Beg() - addr; + return true; } + return false; +} - void DescribeAddress(uptr addr, uptr access_size) { - uptr offset; - Printf("%p is located ", (void*)addr); - if (AddrIsInside(addr, access_size, &offset)) { - Printf("%zu bytes inside of", offset); - } else if (AddrIsAtLeft(addr, access_size, &offset)) { - Printf("%zu bytes to the left of", offset); - } else if (AddrIsAtRight(addr, access_size, &offset)) { - Printf("%zu bytes to the right of", offset); - } else { - Printf(" somewhere around (this is AddressSanitizer bug!)"); - } - Printf(" %zu-byte region [%p,%p)\n", - used_size, (void*)Beg(), (void*)(Beg() + used_size)); +bool AsanChunkView::AddrIsAtRight(uptr addr, uptr access_size, uptr *offset) { + if (addr + access_size >= End()) { + if (addr <= End()) + *offset = 0; + else + *offset = addr - End(); + return true; } -}; + return false; +} static AsanChunk *PtrToChunk(uptr ptr) { AsanChunk *m = (AsanChunk*)(ptr - REDZONE); @@ -252,7 +252,6 @@ static AsanChunk *PtrToChunk(uptr ptr) { return m; } - void AsanChunkFifoList::PushList(AsanChunkFifoList *q) { CHECK(q->size() > 0); if (last_) { @@ -368,9 +367,9 @@ class MallocInfo { quarantine_.Push(chunk); } - AsanChunk *FindMallocedOrFreed(uptr addr, uptr access_size) { + AsanChunk *FindChunkByAddr(uptr addr) { ScopedLock lock(&mu_); - return FindChunkByAddr(addr); + return FindChunkByAddrUnlocked(addr); } uptr AllocationSize(uptr ptr) { @@ -379,7 +378,7 @@ class MallocInfo { // Make sure this is our chunk and |ptr| actually points to the beginning // of the allocated memory. - AsanChunk *m = FindChunkByAddr(ptr); + AsanChunk *m = FindChunkByAddrUnlocked(ptr); if (!m || m->Beg() != ptr) return 0; if (m->chunk_state == CHUNK_ALLOCATED) { @@ -463,14 +462,14 @@ class MallocInfo { return left_chunk; // Choose based on offset. uptr l_offset = 0, r_offset = 0; - CHECK(left_chunk->AddrIsAtRight(addr, 1, &l_offset)); - CHECK(right_chunk->AddrIsAtLeft(addr, 1, &r_offset)); + CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset)); + CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset)); if (l_offset < r_offset) return left_chunk; return right_chunk; } - AsanChunk *FindChunkByAddr(uptr addr) { + AsanChunk *FindChunkByAddrUnlocked(uptr addr) { PageGroup *g = FindPageGroupUnlocked(addr); if (!g) return 0; CHECK(g->size_of_chunk); @@ -483,17 +482,18 @@ class MallocInfo { m->chunk_state == CHUNK_AVAILABLE || m->chunk_state == CHUNK_QUARANTINE); uptr offset = 0; - if (m->AddrIsInside(addr, 1, &offset)) + AsanChunkView m_view(m); + if (m_view.AddrIsInside(addr, 1, &offset)) return m; - if (m->AddrIsAtRight(addr, 1, &offset)) { + if (m_view.AddrIsAtRight(addr, 1, &offset)) { if (this_chunk_addr == g->last_chunk) // rightmost chunk return m; uptr right_chunk_addr = this_chunk_addr + g->size_of_chunk; CHECK(g->InRange(right_chunk_addr)); return ChooseChunk(addr, m, (AsanChunk*)right_chunk_addr); } else { - CHECK(m->AddrIsAtLeft(addr, 1, &offset)); + CHECK(m_view.AddrIsAtLeft(addr, 1, &offset)); if (this_chunk_addr == g->beg) // leftmost chunk return m; uptr left_chunk_addr = this_chunk_addr - g->size_of_chunk; @@ -585,39 +585,8 @@ void AsanThreadLocalMallocStorage::CommitBack() { malloc_info.SwallowThreadLocalMallocStorage(this, true); } -void DescribeHeapAddress(uptr addr, uptr access_size) { - AsanChunk *m = malloc_info.FindMallocedOrFreed(addr, access_size); - if (!m) return; - m->DescribeAddress(addr, access_size); - CHECK(m->alloc_tid >= 0); - AsanThreadSummary *alloc_thread = - asanThreadRegistry().FindByTid(m->alloc_tid); - StackTrace alloc_stack; - StackTrace::UncompressStack(&alloc_stack, m->compressed_alloc_stack(), - m->compressed_alloc_stack_size()); - AsanThread *t = asanThreadRegistry().GetCurrent(); - CHECK(t); - if (m->free_tid != kInvalidTid) { - AsanThreadSummary *free_thread = - asanThreadRegistry().FindByTid(m->free_tid); - Printf("freed by thread T%d here:\n", free_thread->tid()); - StackTrace free_stack; - StackTrace::UncompressStack(&free_stack, m->compressed_free_stack(), - m->compressed_free_stack_size()); - PrintStack(&free_stack); - Printf("previously allocated by thread T%d here:\n", - alloc_thread->tid()); - - PrintStack(&alloc_stack); - DescribeThread(t->summary()); - DescribeThread(free_thread); - DescribeThread(alloc_thread); - } else { - Printf("allocated by thread T%d here:\n", alloc_thread->tid()); - PrintStack(&alloc_stack); - DescribeThread(t->summary()); - DescribeThread(alloc_thread); - } +AsanChunkView FindHeapChunkByAddress(uptr address) { + return AsanChunkView(malloc_info.FindChunkByAddr(address)); } static u8 *Allocate(uptr alignment, uptr size, StackTrace *stack) { diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h index c5e1aabbb..1c6c30b22 100644 --- a/lib/asan/asan_allocator.h +++ b/lib/asan/asan_allocator.h @@ -23,6 +23,26 @@ namespace __asan { static const uptr kNumberOfSizeClasses = 255; struct AsanChunk; +class AsanChunkView { + public: + explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} + bool IsValid() { return chunk_ != 0; } + uptr Beg(); // first byte of user memory. + uptr End(); // last byte of user memory. + uptr UsedSize(); // size requested by the user. + uptr AllocTid(); + uptr FreeTid(); + void GetAllocStack(StackTrace *stack); + void GetFreeStack(StackTrace *stack); + bool AddrIsInside(uptr addr, uptr access_size, uptr *offset); + bool AddrIsAtLeft(uptr addr, uptr access_size, uptr *offset); + bool AddrIsAtRight(uptr addr, uptr access_size, uptr *offset); + private: + AsanChunk *const chunk_; +}; + +AsanChunkView FindHeapChunkByAddress(uptr address); + class AsanChunkFifoList { public: explicit AsanChunkFifoList(LinkerInitialized) { } diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index d31c97ff3..5baba4580 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -188,6 +188,54 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) { return true; } +static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, + uptr access_size) { + uptr offset; + Printf("%p is located ", (void*)addr); + if (chunk.AddrIsInside(addr, access_size, &offset)) { + Printf("%zu bytes inside of", offset); + } else if (chunk.AddrIsAtLeft(addr, access_size, &offset)) { + Printf("%zu bytes to the left of", offset); + } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) { + Printf("%zu bytes to the right of", offset); + } else { + Printf(" somewhere around (this is AddressSanitizer bug!)"); + } + Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(), + (void*)(chunk.Beg()), (void*)(chunk.End())); +} + +void DescribeHeapAddress(uptr addr, uptr access_size) { + AsanChunkView chunk = FindHeapChunkByAddress(addr); + if (!chunk.IsValid()) return; + DescribeAccessToHeapChunk(chunk, addr, access_size); + CHECK(chunk.AllocTid() != kInvalidTid); + AsanThreadSummary *alloc_thread = + asanThreadRegistry().FindByTid(chunk.AllocTid()); + StackTrace alloc_stack; + chunk.GetAllocStack(&alloc_stack); + AsanThread *t = asanThreadRegistry().GetCurrent(); + CHECK(t); + if (chunk.FreeTid() != kInvalidTid) { + AsanThreadSummary *free_thread = + asanThreadRegistry().FindByTid(chunk.FreeTid()); + Printf("freed by thread T%d here:\n", free_thread->tid()); + StackTrace free_stack; + chunk.GetFreeStack(&free_stack); + PrintStack(&free_stack); + Printf("previously allocated by thread T%d here:\n", alloc_thread->tid()); + PrintStack(&alloc_stack); + DescribeThread(t->summary()); + DescribeThread(free_thread); + DescribeThread(alloc_thread); + } else { + Printf("allocated by thread T%d here:\n", alloc_thread->tid()); + PrintStack(&alloc_stack); + DescribeThread(t->summary()); + DescribeThread(alloc_thread); + } +} + void DescribeAddress(uptr addr, uptr access_size) { // Check if this is shadow or shadow gap. if (DescribeAddressIfShadow(addr)) -- cgit v1.2.3