[ASan] Print global registration site in init-order-checker reports.

llvm-svn: 235540
This commit is contained in:
Alexey Samsonov 2015-04-22 20:30:19 +00:00
parent e74ec45b88
commit 9e463ba35d
4 changed files with 47 additions and 34 deletions

View File

@ -91,9 +91,19 @@ static void ReportGlobal(const Global &g, const char *prefix) {
}
}
// Returns the number of globals close to the provided address and copies
// them to "globals" array.
int GetGlobalsForAddress(uptr addr, Global *globals, int max_globals) {
static u32 FindRegistrationSite(const Global *g) {
mu_for_globals.CheckLocked();
CHECK(global_registration_site_vector);
for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) {
GlobalRegistrationSite &grs = (*global_registration_site_vector)[i];
if (g >= grs.g_first && g <= grs.g_last)
return grs.stack_id;
}
return 0;
}
int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
int max_globals) {
if (!flags()->report_globals) return 0;
BlockingMutexLock lock(&mu_for_globals);
int res = 0;
@ -102,7 +112,10 @@ int GetGlobalsForAddress(uptr addr, Global *globals, int max_globals) {
if (flags()->report_globals >= 2)
ReportGlobal(g, "Search");
if (IsAddressNearGlobal(addr, g)) {
globals[res++] = g;
globals[res] = g;
if (reg_sites)
reg_sites[res] = FindRegistrationSite(&g);
res++;
if (res == max_globals) break;
}
}
@ -111,7 +124,7 @@ int GetGlobalsForAddress(uptr addr, Global *globals, int max_globals) {
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
Global g = {};
if (GetGlobalsForAddress(addr, &g, 1)) {
if (GetGlobalsForAddress(addr, &g, nullptr, 1)) {
internal_strncpy(descr->name, g.name, descr->name_size);
descr->region_address = g.beg;
descr->region_size = g.size;
@ -121,16 +134,6 @@ bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
return false;
}
u32 FindRegistrationSite(const Global *g) {
CHECK(global_registration_site_vector);
for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) {
GlobalRegistrationSite &grs = (*global_registration_site_vector)[i];
if (g >= grs.g_first && g <= grs.g_last)
return grs.stack_id;
}
return 0;
}
// Register a global variable.
// This function may be called more than once for every global
// so we store the globals in a map.

View File

@ -307,15 +307,24 @@ static void DescribeAddressRelativeToGlobal(uptr addr, uptr size,
Printf("%s", str.data());
}
static bool DescribeAddressIfGlobal(uptr addr, uptr size) {
static bool DescribeAddressIfGlobal(uptr addr, uptr size,
const char *bug_type) {
// Assume address is close to at most four globals.
const int kMaxGlobalsInReport = 4;
__asan_global globals[kMaxGlobalsInReport];
int globals_num = GetGlobalsForAddress(addr, globals, ARRAY_SIZE(globals));
u32 reg_sites[kMaxGlobalsInReport];
int globals_num =
GetGlobalsForAddress(addr, globals, reg_sites, ARRAY_SIZE(globals));
if (globals_num == 0)
return false;
for (int i = 0; i < globals_num; i++)
for (int i = 0; i < globals_num; i++) {
DescribeAddressRelativeToGlobal(addr, size, globals[i]);
if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") &&
reg_sites[i]) {
Printf(" registered at:\n");
StackDepotGet(reg_sites[i]).Print();
}
}
return true;
}
@ -561,12 +570,12 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
DescribeThread(alloc_thread);
}
void DescribeAddress(uptr addr, uptr access_size) {
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))
if (DescribeAddressIfGlobal(addr, access_size, bug_type))
return;
if (DescribeAddressIfStack(addr, access_size))
return;
@ -820,8 +829,8 @@ void ReportStringFunctionMemoryRangesOverlap(const char *function,
bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
Printf("%s", d.EndWarning());
stack->Print();
DescribeAddress((uptr)offset1, length1);
DescribeAddress((uptr)offset2, length2);
DescribeAddress((uptr)offset1, length1, bug_type);
DescribeAddress((uptr)offset2, length2, bug_type);
ReportErrorSummary(bug_type, stack);
}
@ -834,7 +843,7 @@ void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);
Printf("%s", d.EndWarning());
stack->Print();
DescribeAddress(offset, size);
DescribeAddress(offset, size, bug_type);
ReportErrorSummary(bug_type, stack);
}
@ -889,15 +898,16 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
static NOINLINE void
ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {
ScopedInErrorReport in_report;
const char *bug_type = "invalid-pointer-pair";
Decorator d;
Printf("%s", d.Warning());
Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2);
Printf("%s", d.EndWarning());
GET_STACK_TRACE_FATAL(pc, bp);
stack.Print();
DescribeAddress(a1, 1);
DescribeAddress(a2, 1);
ReportErrorSummary("invalid-pointer-pair", &stack);
DescribeAddress(a1, 1, bug_type);
DescribeAddress(a2, 1, bug_type);
ReportErrorSummary(bug_type, &stack);
}
static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
@ -1044,7 +1054,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
GET_STACK_TRACE_FATAL(pc, bp);
stack.Print();
DescribeAddress(addr, access_size);
DescribeAddress(addr, access_size, bug_descr);
ReportErrorSummary(bug_descr, &stack);
PrintShadowMemoryForAddress(addr);
}
@ -1062,7 +1072,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);
DescribeAddress(addr, 1, "");
asanThreadRegistry().Unlock();
}

View File

@ -35,7 +35,8 @@ struct AddressDescription {
// Returns the number of globals close to the provided address and copies
// them to "globals" array.
int GetGlobalsForAddress(uptr addr, __asan_global *globals, int max_globals);
int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
int max_globals);
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
// The following functions prints address description depending
// on the memory type (shadow/heap/stack/global).
@ -45,9 +46,6 @@ bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr = nullptr,
bool ParseFrameDescription(const char *frame_descr,
InternalMmapVector<StackVarDescr> *vars);
bool DescribeAddressIfStack(uptr addr, uptr access_size);
// Determines memory type on its own.
void DescribeAddress(uptr addr, uptr access_size);
void DescribeThread(AsanThreadContext *context);
// Different kinds of error reports.

View File

@ -1,7 +1,7 @@
// Test to make sure basic initialization order errors are caught.
// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t
// RUN: env ASAN_OPTIONS=check_initialization_order=true not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t-INIT-ORDER-EXE
// RUN: env ASAN_OPTIONS=check_initialization_order=true not %run %t-INIT-ORDER-EXE 2>&1 | FileCheck %s
// Do not test with optimization -- the error may be optimized away.
@ -32,6 +32,8 @@ int __attribute__((noinline)) initX() {
// CHECK: {{AddressSanitizer: initialization-order-fiasco}}
// CHECK: {{READ of size .* at 0x.* thread T0}}
// CHECK: {{0x.* is located 0 bytes inside of global variable .*(y|z).*}}
// CHECK: registered at:
// CHECK: 0x{{.*}} in asan.module_ctor {{.*}}INIT-ORDER-EXE
}
// This initializer begins our initialization order problems.