Cleanup: Move the *AddressDescription printing code to Print() members inside those structs.

Summary:
The Print() members might take optional access_size and bug_type
parameters to still be able to provide the same information

Reviewers: kcc, samsonov

Subscribers: kubabrecka, llvm-commits

Differential Revision: https://reviews.llvm.org/D23658

llvm-svn: 279237
This commit is contained in:
Filipe Cabecinhas
2016-08-19 13:07:23 +00:00
parent a2f96619cb
commit 53a45fa4e3
3 changed files with 166 additions and 115 deletions

View File

@@ -88,8 +88,7 @@ static bool GetShadowKind(uptr addr, ShadowKind *shadow_kind) {
bool DescribeAddressIfShadow(uptr addr) {
ShadowAddressDescription descr;
if (!GetShadowAddressInformation(addr, &descr)) return false;
Printf("Address %p is located in the %s area.\n", addr,
ShadowNames[descr.kind]);
descr.Print();
return true;
}
@@ -188,38 +187,7 @@ bool DescribeAddressIfHeap(uptr addr, uptr access_size) {
"(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);
descr.Print();
return true;
}
@@ -297,59 +265,7 @@ static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
bool DescribeAddressIfStack(uptr addr, uptr access_size) {
StackAddressDescription descr;
if (!GetStackAddressInformation(addr, &descr)) return false;
Decorator d;
char tname[128];
Printf("%s", d.Location());
Printf("Address %p is located in stack of thread T%d%s", addr, descr.tid,
ThreadNameWithParenthesis(descr.tid, tname, sizeof(tname)));
if (!descr.frame_descr) {
Printf("%s\n", d.EndLocation());
return true;
}
Printf(" at offset %zu in frame%s\n", descr.offset, d.EndLocation());
// Now we print the frame where the alloca has happened.
// We print this frame as a stack trace with one element.
// The symbolizer may print more than one frame if inlining was involved.
// The frame numbers may be different than those in the stack trace printed
// previously. That's unfortunate, but I have no better solution,
// especially given that the alloca may be from entirely different place
// (e.g. use-after-scope, or different thread's stack).
Printf("%s", d.EndLocation());
StackTrace alloca_stack(&descr.frame_pc, 1);
alloca_stack.Print();
InternalMmapVector<StackVarDescr> vars(16);
if (!ParseFrameDescription(descr.frame_descr, &vars)) {
Printf(
"AddressSanitizer can't parse the stack frame "
"descriptor: |%s|\n",
descr.frame_descr);
// 'addr' is a stack address, so return true even if we can't parse frame
return true;
}
uptr n_objects = vars.size();
// Report the number of stack objects.
Printf(" This frame has %zu object(s):\n", n_objects);
// Report all objects in this frame.
for (uptr i = 0; i < n_objects; i++) {
uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0;
uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL);
PrintAccessAndVarIntersection(vars[i], descr.offset, access_size,
prev_var_end, next_var_beg);
}
Printf(
"HINT: this may be a false positive if your program uses "
"some custom stack unwind mechanism or swapcontext\n");
if (SANITIZER_WINDOWS)
Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n");
else
Printf(" (longjmp and C++ exceptions *are* supported)\n");
DescribeThread(GetThreadContextByTidLocked(descr.tid));
descr.Print(access_size);
return true;
}
@@ -392,15 +308,143 @@ bool DescribeAddressIfGlobal(uptr addr, uptr access_size,
GlobalAddressDescription descr;
if (!GetGlobalAddressInformation(addr, &descr)) return false;
for (int i = 0; i < descr.size; i++) {
DescribeAddressRelativeToGlobal(descr.addr, access_size, descr.globals[i]);
if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") &&
descr.reg_sites[i]) {
Printf(" registered at:\n");
StackDepotGet(descr.reg_sites[i]).Print();
}
}
descr.Print(access_size, bug_type);
return true;
}
void ShadowAddressDescription::Print() {
Printf("Address %p is located in the %s area.\n", addr, ShadowNames[kind]);
}
void GlobalAddressDescription::Print(uptr access_size, const char *bug_type) {
for (int i = 0; i < size; i++) {
DescribeAddressRelativeToGlobal(addr, access_size, globals[i]);
if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") &&
reg_sites[i]) {
Printf(" registered at:\n");
StackDepotGet(reg_sites[i]).Print();
}
}
}
void StackAddressDescription::Print(uptr access_size) {
Decorator d;
char tname[128];
Printf("%s", d.Location());
Printf("Address %p is located in stack of thread T%d%s", addr, tid,
ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
if (!frame_descr) {
Printf("%s\n", d.EndLocation());
return;
}
Printf(" at offset %zu in frame%s\n", offset, d.EndLocation());
// Now we print the frame where the alloca has happened.
// We print this frame as a stack trace with one element.
// The symbolizer may print more than one frame if inlining was involved.
// The frame numbers may be different than those in the stack trace printed
// previously. That's unfortunate, but I have no better solution,
// especially given that the alloca may be from entirely different place
// (e.g. use-after-scope, or different thread's stack).
Printf("%s", d.EndLocation());
StackTrace alloca_stack(&frame_pc, 1);
alloca_stack.Print();
InternalMmapVector<StackVarDescr> vars(16);
if (!ParseFrameDescription(frame_descr, &vars)) {
Printf(
"AddressSanitizer can't parse the stack frame "
"descriptor: |%s|\n",
frame_descr);
// 'addr' is a stack address, so return true even if we can't parse frame
return;
}
uptr n_objects = vars.size();
// Report the number of stack objects.
Printf(" This frame has %zu object(s):\n", n_objects);
// Report all objects in this frame.
for (uptr i = 0; i < n_objects; i++) {
uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0;
uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL);
PrintAccessAndVarIntersection(vars[i], offset, access_size, prev_var_end,
next_var_beg);
}
Printf(
"HINT: this may be a false positive if your program uses "
"some custom stack unwind mechanism or swapcontext\n");
if (SANITIZER_WINDOWS)
Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n");
else
Printf(" (longjmp and C++ exceptions *are* supported)\n");
DescribeThread(GetThreadContextByTidLocked(tid));
}
void HeapAddressDescription::Print() {
PrintHeapChunkAccess(addr, chunk_access);
asanThreadRegistry().CheckLocked();
AsanThreadContext *alloc_thread = GetThreadContextByTidLocked(alloc_tid);
StackTrace alloc_stack = GetStackTraceFromId(alloc_stack_id);
char tname[128];
Decorator d;
AsanThreadContext *free_thread = nullptr;
if (free_tid != kInvalidTid) {
free_thread = GetThreadContextByTidLocked(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(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);
}
void PrintAddressDescription(uptr addr, uptr access_size,
const char *bug_type) {
ShadowAddressDescription shadow_descr;
if (GetShadowAddressInformation(addr, &shadow_descr)) {
shadow_descr.Print();
return;
}
GlobalAddressDescription global_descr;
if (GetGlobalAddressInformation(addr, &global_descr)) {
global_descr.Print(access_size, bug_type);
return;
}
StackAddressDescription stack_descr;
if (GetStackAddressInformation(addr, &stack_descr)) {
stack_descr.Print(access_size);
return;
}
HeapAddressDescription heap_descr;
if (GetHeapAddressInformation(addr, access_size, &heap_descr)) {
heap_descr.Print();
return;
}
// We exhausted our possibilities. Bail out.
Printf(
"AddressSanitizer can not describe address in more detail "
"(wild memory access suspected).\n");
}
} // namespace __asan

View File

@@ -90,6 +90,8 @@ struct ShadowAddressDescription {
uptr addr;
ShadowKind kind;
u8 shadow_byte;
void Print();
};
bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
@@ -118,6 +120,8 @@ struct HeapAddressDescription {
u32 alloc_stack_id;
u32 free_stack_id;
ChunkAccess chunk_access;
void Print();
};
bool GetHeapAddressInformation(uptr addr, uptr access_size,
@@ -130,7 +134,10 @@ struct StackAddressDescription {
uptr offset;
uptr frame_pc;
const char *frame_descr;
void Print(uptr access_size = 1);
};
bool GetStackAddressInformation(uptr addr, StackAddressDescription *descr);
bool DescribeAddressIfStack(uptr addr, uptr access_size);
@@ -141,11 +148,24 @@ struct GlobalAddressDescription {
__asan_global globals[kMaxGlobals];
u32 reg_sites[kMaxGlobals];
u8 size;
void Print(uptr access_size = 1, const char *bug_type = "");
};
bool GetGlobalAddressInformation(uptr addr, GlobalAddressDescription *descr);
bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
// General function to describe an address. Will try to describe the address as
// a shadow, global (variable), stack, or heap address.
// bug_type is optional and is used for checking if we're reporting an
// initialization-order-fiasco
// The proper access_size should be passed for stack, global, and heap
// addresses. Defaults to 1.
// Each of the *AddressDescription functions has its own Print() member, which
// may take access_size and bug_type parameters if needed.
void PrintAddressDescription(uptr addr, uptr access_size = 1,
const char *bug_type = "");
} // namespace __asan
#endif // ASAN_DESCRIPTIONS_H

View File

@@ -212,19 +212,6 @@ bool ParseFrameDescription(const char *frame_descr,
return true;
}
static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {
// Check if this is shadow or shadow gap.
if (DescribeAddressIfShadow(addr))
return;
CHECK(AddrIsInMem(addr));
if (DescribeAddressIfGlobal(addr, access_size, bug_type))
return;
if (DescribeAddressIfStack(addr, access_size))
return;
// Assume it is a heap address.
DescribeAddressIfHeap(addr, access_size);
}
// -------------------- Different kinds of reports ----------------- {{{1
// Use ScopedInErrorReport to run common actions just before and
@@ -526,8 +513,8 @@ void ReportStringFunctionMemoryRangesOverlap(const char *function,
Printf("%s", d.EndWarning());
ScarinessScore::PrintSimple(10, bug_type);
stack->Print();
DescribeAddress((uptr)offset1, length1, bug_type);
DescribeAddress((uptr)offset2, length2, bug_type);
PrintAddressDescription((uptr)offset1, length1, bug_type);
PrintAddressDescription((uptr)offset2, length2, bug_type);
ReportErrorSummary(bug_type, stack);
}
@@ -541,7 +528,7 @@ void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
Printf("%s", d.EndWarning());
ScarinessScore::PrintSimple(10, bug_type);
stack->Print();
DescribeAddress(offset, size, bug_type);
PrintAddressDescription(offset, size, bug_type);
ReportErrorSummary(bug_type, stack);
}
@@ -603,8 +590,8 @@ ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {
Printf("%s", d.EndWarning());
GET_STACK_TRACE_FATAL(pc, bp);
stack.Print();
DescribeAddress(a1, 1, bug_type);
DescribeAddress(a2, 1, bug_type);
PrintAddressDescription(a1, 1, bug_type);
PrintAddressDescription(a2, 1, bug_type);
ReportErrorSummary(bug_type, &stack);
}
@@ -792,7 +779,7 @@ void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
GET_STACK_TRACE_FATAL(pc, bp);
stack.Print();
DescribeAddress(addr, access_size, bug_descr);
PrintAddressDescription(addr, access_size, bug_descr);
if (shadow_val == kAsanContiguousContainerOOBMagic)
PrintContainerOverflowHint();
ReportErrorSummary(bug_descr, &stack);
@@ -819,7 +806,7 @@ void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
void __asan_describe_address(uptr addr) {
// Thread registry must be locked while we're describing an address.
asanThreadRegistry().Lock();
DescribeAddress(addr, 1, "");
PrintAddressDescription(addr, 1, "");
asanThreadRegistry().Unlock();
}