forked from OSchip/llvm-project
Rename DescribeHeapAddress to DescribeAddressIfHeap and split it into a function to get all the information about the address, and one to print it.
Summary: Replacement for part of D23518 This deals with heap addresses, and renames DescribeHeapAddress. Requires D23520, which moves code around to make it accessible in asan_describers.cc (and still accessible in asan_report.cc if needed). Reviewers: kcc, samsonov Subscribers: kubabrecka, llvm-commits Differential Revision: https://reviews.llvm.org/D23569 llvm-svn: 278917
This commit is contained in:
parent
d43ae376d4
commit
e068de5137
|
@ -673,6 +673,9 @@ uptr AsanChunkView::End() { return Beg() + UsedSize(); }
|
|||
uptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); }
|
||||
uptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; }
|
||||
uptr AsanChunkView::FreeTid() { return chunk_->free_tid; }
|
||||
AllocType AsanChunkView::AllocType() {
|
||||
return (enum AllocType)chunk_->alloc_type;
|
||||
}
|
||||
|
||||
static StackTrace GetStackTraceFromId(u32 id) {
|
||||
CHECK(id);
|
||||
|
|
|
@ -62,6 +62,7 @@ class AsanChunkView {
|
|||
u32 GetFreeStackId();
|
||||
StackTrace GetAllocStack();
|
||||
StackTrace GetFreeStack();
|
||||
AllocType AllocType();
|
||||
bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
|
||||
if (addr >= Beg() && (addr + access_size) <= End()) {
|
||||
*offset = addr - Beg();
|
||||
|
|
|
@ -101,4 +101,124 @@ bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Heap descriptions
|
||||
static void GetAccessToHeapChunkInformation(ChunkAccess *descr,
|
||||
AsanChunkView chunk, uptr addr,
|
||||
uptr access_size) {
|
||||
descr->bad_addr = addr;
|
||||
if (chunk.AddrIsAtLeft(addr, access_size, &descr->offset)) {
|
||||
descr->access_type = kAccessTypeLeft;
|
||||
} else if (chunk.AddrIsAtRight(addr, access_size, &descr->offset)) {
|
||||
descr->access_type = kAccessTypeRight;
|
||||
if (descr->offset < 0) {
|
||||
descr->bad_addr -= descr->offset;
|
||||
descr->offset = 0;
|
||||
}
|
||||
} else if (chunk.AddrIsInside(addr, access_size, &descr->offset)) {
|
||||
descr->access_type = kAccessTypeInside;
|
||||
} else {
|
||||
descr->access_type = kAccessTypeUnknown;
|
||||
}
|
||||
descr->chunk_begin = chunk.Beg();
|
||||
descr->chunk_size = chunk.UsedSize();
|
||||
descr->alloc_type = chunk.AllocType();
|
||||
}
|
||||
|
||||
static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) {
|
||||
Decorator d;
|
||||
InternalScopedString str(4096);
|
||||
str.append("%s", d.Location());
|
||||
switch (descr.access_type) {
|
||||
case kAccessTypeLeft:
|
||||
str.append("%p is located %zd bytes to the left of",
|
||||
(void *)descr.bad_addr, descr.offset);
|
||||
break;
|
||||
case kAccessTypeRight:
|
||||
str.append("%p is located %zd bytes to the right of",
|
||||
(void *)descr.bad_addr, descr.offset);
|
||||
break;
|
||||
case kAccessTypeInside:
|
||||
str.append("%p is located %zd bytes inside of", (void *)descr.bad_addr,
|
||||
descr.offset);
|
||||
break;
|
||||
case kAccessTypeUnknown:
|
||||
str.append(
|
||||
"%p is located somewhere around (this is AddressSanitizer bug!)",
|
||||
(void *)descr.bad_addr);
|
||||
}
|
||||
str.append(" %zu-byte region [%p,%p)\n", descr.chunk_size,
|
||||
(void *)descr.chunk_begin,
|
||||
(void *)(descr.chunk_begin + descr.chunk_size));
|
||||
str.append("%s", d.EndLocation());
|
||||
Printf("%s", str.data());
|
||||
}
|
||||
|
||||
bool GetHeapAddressInformation(uptr addr, uptr access_size,
|
||||
HeapAddressDescription *descr) {
|
||||
AsanChunkView chunk = FindHeapChunkByAddress(addr);
|
||||
if (!chunk.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
descr->addr = addr;
|
||||
GetAccessToHeapChunkInformation(&descr->chunk_access, chunk, addr,
|
||||
access_size);
|
||||
CHECK_NE(chunk.AllocTid(), kInvalidTid);
|
||||
descr->alloc_tid = chunk.AllocTid();
|
||||
descr->alloc_stack_id = chunk.GetAllocStackId();
|
||||
descr->free_tid = chunk.FreeTid();
|
||||
if (descr->free_tid != kInvalidTid)
|
||||
descr->free_stack_id = chunk.GetFreeStackId();
|
||||
return true;
|
||||
}
|
||||
|
||||
static StackTrace GetStackTraceFromId(u32 id) {
|
||||
CHECK(id);
|
||||
StackTrace res = StackDepotGet(id);
|
||||
CHECK(res.trace);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DescribeAddressIfHeap(uptr addr, uptr access_size) {
|
||||
HeapAddressDescription descr;
|
||||
if (!GetHeapAddressInformation(addr, access_size, &descr)) {
|
||||
Printf(
|
||||
"AddressSanitizer can not describe address in more detail "
|
||||
"(wild memory access suspected).\n");
|
||||
return false;
|
||||
}
|
||||
PrintHeapChunkAccess(addr, descr.chunk_access);
|
||||
|
||||
asanThreadRegistry().CheckLocked();
|
||||
AsanThreadContext *alloc_thread =
|
||||
GetThreadContextByTidLocked(descr.alloc_tid);
|
||||
StackTrace alloc_stack = GetStackTraceFromId(descr.alloc_stack_id);
|
||||
|
||||
char tname[128];
|
||||
Decorator d;
|
||||
AsanThreadContext *free_thread = nullptr;
|
||||
if (descr.free_tid != kInvalidTid) {
|
||||
free_thread = GetThreadContextByTidLocked(descr.free_tid);
|
||||
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 = GetStackTraceFromId(descr.free_stack_id);
|
||||
free_stack.Print();
|
||||
Printf("%spreviously allocated by thread T%d%s here:%s\n", d.Allocation(),
|
||||
alloc_thread->tid,
|
||||
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
|
||||
d.EndAllocation());
|
||||
} else {
|
||||
Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
|
||||
alloc_thread->tid,
|
||||
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
|
||||
d.EndAllocation());
|
||||
}
|
||||
alloc_stack.Print();
|
||||
DescribeThread(GetCurrentThread());
|
||||
if (free_thread) DescribeThread(free_thread);
|
||||
DescribeThread(alloc_thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// TODO(filcab): Most struct definitions should move to the interface headers.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_internal.h"
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_thread.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_report_decorator.h"
|
||||
|
@ -94,4 +94,33 @@ struct ShadowAddressDescription {
|
|||
bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
|
||||
bool DescribeAddressIfShadow(uptr addr);
|
||||
|
||||
enum AccessType {
|
||||
kAccessTypeLeft,
|
||||
kAccessTypeRight,
|
||||
kAccessTypeInside,
|
||||
kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
|
||||
};
|
||||
|
||||
struct ChunkAccess {
|
||||
uptr bad_addr;
|
||||
sptr offset;
|
||||
uptr chunk_begin;
|
||||
uptr chunk_size;
|
||||
u32 access_type : 2;
|
||||
u32 alloc_type : 2;
|
||||
};
|
||||
|
||||
struct HeapAddressDescription {
|
||||
uptr addr;
|
||||
uptr alloc_tid;
|
||||
uptr free_tid;
|
||||
u32 alloc_stack_id;
|
||||
u32 free_stack_id;
|
||||
ChunkAccess chunk_access;
|
||||
};
|
||||
|
||||
bool GetHeapAddressInformation(uptr addr, uptr access_size,
|
||||
HeapAddressDescription *descr);
|
||||
bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
|
||||
|
||||
} // namespace __asan
|
||||
|
|
|
@ -417,73 +417,6 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
|
||||
uptr access_size) {
|
||||
sptr offset;
|
||||
Decorator d;
|
||||
InternalScopedString str(4096);
|
||||
str.append("%s", d.Location());
|
||||
if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
|
||||
str.append("%p is located %zd bytes to the left of", (void *)addr, offset);
|
||||
} else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
|
||||
if (offset < 0) {
|
||||
addr -= offset;
|
||||
offset = 0;
|
||||
}
|
||||
str.append("%p is located %zd bytes to the right of", (void *)addr, offset);
|
||||
} else if (chunk.AddrIsInside(addr, access_size, &offset)) {
|
||||
str.append("%p is located %zd bytes inside of", (void*)addr, offset);
|
||||
} else {
|
||||
str.append("%p is located somewhere around (this is AddressSanitizer bug!)",
|
||||
(void *)addr);
|
||||
}
|
||||
str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
|
||||
(void *)(chunk.Beg()), (void *)(chunk.End()));
|
||||
str.append("%s", d.EndLocation());
|
||||
Printf("%s", str.data());
|
||||
}
|
||||
|
||||
void DescribeHeapAddress(uptr addr, uptr access_size) {
|
||||
AsanChunkView chunk = FindHeapChunkByAddress(addr);
|
||||
if (!chunk.IsValid()) {
|
||||
Printf("AddressSanitizer can not describe address in more detail "
|
||||
"(wild memory access suspected).\n");
|
||||
return;
|
||||
}
|
||||
DescribeAccessToHeapChunk(chunk, addr, access_size);
|
||||
CHECK_NE(chunk.AllocTid(), kInvalidTid);
|
||||
asanThreadRegistry().CheckLocked();
|
||||
AsanThreadContext *alloc_thread =
|
||||
GetThreadContextByTidLocked(chunk.AllocTid());
|
||||
StackTrace alloc_stack = chunk.GetAllocStack();
|
||||
char tname[128];
|
||||
Decorator d;
|
||||
AsanThreadContext *free_thread = nullptr;
|
||||
if (chunk.FreeTid() != kInvalidTid) {
|
||||
free_thread = GetThreadContextByTidLocked(chunk.FreeTid());
|
||||
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.Print();
|
||||
Printf("%spreviously allocated by thread T%d%s here:%s\n",
|
||||
d.Allocation(), alloc_thread->tid,
|
||||
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
|
||||
d.EndAllocation());
|
||||
} else {
|
||||
Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
|
||||
alloc_thread->tid,
|
||||
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
|
||||
d.EndAllocation());
|
||||
}
|
||||
alloc_stack.Print();
|
||||
DescribeThread(GetCurrentThread());
|
||||
if (free_thread)
|
||||
DescribeThread(free_thread);
|
||||
DescribeThread(alloc_thread);
|
||||
}
|
||||
|
||||
static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {
|
||||
// Check if this is shadow or shadow gap.
|
||||
if (DescribeAddressIfShadow(addr))
|
||||
|
@ -494,7 +427,7 @@ static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {
|
|||
if (DescribeAddressIfStack(addr, access_size))
|
||||
return;
|
||||
// Assume it is a heap address.
|
||||
DescribeHeapAddress(addr, access_size);
|
||||
DescribeAddressIfHeap(addr, access_size);
|
||||
}
|
||||
|
||||
// -------------------- Different kinds of reports ----------------- {{{1
|
||||
|
@ -685,7 +618,7 @@ void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
|
|||
ScarinessScore::PrintSimple(42, "double-free");
|
||||
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
|
||||
stack.Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
DescribeAddressIfHeap(addr);
|
||||
ReportErrorSummary("double-free", &stack);
|
||||
}
|
||||
|
||||
|
@ -708,7 +641,7 @@ void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size,
|
|||
ScarinessScore::PrintSimple(10, "new-delete-type-mismatch");
|
||||
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
|
||||
stack.Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
DescribeAddressIfHeap(addr);
|
||||
ReportErrorSummary("new-delete-type-mismatch", &stack);
|
||||
Report("HINT: if you don't care about these errors you may set "
|
||||
"ASAN_OPTIONS=new_delete_type_mismatch=0\n");
|
||||
|
@ -728,7 +661,7 @@ void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
|
|||
ScarinessScore::PrintSimple(40, "bad-free");
|
||||
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
|
||||
stack.Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
DescribeAddressIfHeap(addr);
|
||||
ReportErrorSummary("bad-free", &stack);
|
||||
}
|
||||
|
||||
|
@ -750,7 +683,7 @@ void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
|
|||
ScarinessScore::PrintSimple(10, "alloc-dealloc-mismatch");
|
||||
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
|
||||
stack.Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
DescribeAddressIfHeap(addr);
|
||||
ReportErrorSummary("alloc-dealloc-mismatch", &stack);
|
||||
Report("HINT: if you don't care about these errors you may set "
|
||||
"ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
|
||||
|
@ -765,7 +698,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
|
|||
"not owned: %p\n", addr);
|
||||
Printf("%s", d.EndWarning());
|
||||
stack->Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
DescribeAddressIfHeap(addr);
|
||||
ReportErrorSummary("bad-malloc_usable_size", stack);
|
||||
}
|
||||
|
||||
|
@ -779,7 +712,7 @@ void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
|
|||
"not owned: %p\n", addr);
|
||||
Printf("%s", d.EndWarning());
|
||||
stack->Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
DescribeAddressIfHeap(addr);
|
||||
ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack);
|
||||
}
|
||||
|
||||
|
@ -903,7 +836,7 @@ void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
|
|||
addr);
|
||||
PrintZoneForPointer(addr, zone_ptr, zone_name);
|
||||
stack->Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
DescribeAddressIfHeap(addr);
|
||||
}
|
||||
|
||||
// -------------- SuppressErrorReport -------------- {{{1
|
||||
|
|
|
@ -40,7 +40,6 @@ int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
|
|||
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
|
||||
// The following functions prints address description depending
|
||||
// on the memory type (shadow/heap/stack/global).
|
||||
void DescribeHeapAddress(uptr addr, uptr access_size);
|
||||
bool ParseFrameDescription(const char *frame_descr,
|
||||
InternalMmapVector<StackVarDescr> *vars);
|
||||
bool DescribeAddressIfStack(uptr addr, uptr access_size);
|
||||
|
|
Loading…
Reference in New Issue