Split DescribeAddressIfGlobal between a function that gets all the information, and one that prints it.

Summary:
Replacement for part of D23518
This deals with global variable addresses.

(This commit is written on top of D23605, but can be applied by itself)

Reviewers: kcc, samsonov

Subscribers: kubabrecka, llvm-commits

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

llvm-svn: 278959
This commit is contained in:
Filipe Cabecinhas 2016-08-17 19:52:12 +00:00
parent 2e767d1972
commit 41f41635f9
6 changed files with 115 additions and 109 deletions

View File

@ -71,7 +71,13 @@ void AsanLocateAddress(uptr addr, AddressDescription *descr) {
descr->region_kind = ShadowNames[shadow_descr.kind];
return;
}
if (GetInfoForAddressIfGlobal(addr, descr)) {
GlobalAddressDescription global_descr;
if (GetGlobalAddressInformation(addr, &global_descr)) {
descr->region_kind = "global";
auto &g = global_descr.globals[0];
internal_strlcpy(descr->name, g.name, descr->name_size);
descr->region_address = g.beg;
descr->region_size = g.size;
return;
}
asanThreadRegistry().Lock();

View File

@ -353,4 +353,54 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
return true;
}
// Global descriptions
static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
const __asan_global &g) {
InternalScopedString str(4096);
Decorator d;
str.append("%s", d.Location());
if (addr < g.beg) {
str.append("%p is located %zd bytes to the left", (void *)addr,
g.beg - addr);
} else if (addr + access_size > g.beg + g.size) {
if (addr < g.beg + g.size) addr = g.beg + g.size;
str.append("%p is located %zd bytes to the right", (void *)addr,
addr - (g.beg + g.size));
} else {
// Can it happen?
str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg);
}
str.append(" of global variable '%s' defined in '",
MaybeDemangleGlobalName(g.name));
PrintGlobalLocation(&str, g);
str.append("' (0x%zx) of size %zu\n", g.beg, g.size);
str.append("%s", d.EndLocation());
PrintGlobalNameIfASCII(&str, g);
Printf("%s", str.data());
}
bool GetGlobalAddressInformation(uptr addr, GlobalAddressDescription *descr) {
descr->addr = addr;
int globals_num = GetGlobalsForAddress(addr, descr->globals, descr->reg_sites,
ARRAY_SIZE(descr->globals));
descr->size = globals_num;
return globals_num != 0;
}
bool DescribeAddressIfGlobal(uptr addr, uptr access_size,
const char *bug_type) {
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();
}
}
return true;
}
} // namespace __asan

View File

@ -133,4 +133,16 @@ struct StackAddressDescription {
bool GetStackAddressInformation(uptr addr, StackAddressDescription *descr);
bool DescribeAddressIfStack(uptr addr, uptr access_size);
struct GlobalAddressDescription {
uptr addr;
// Assume address is close to at most four globals.
static const int kMaxGlobals = 4;
__asan_global globals[kMaxGlobals];
u32 reg_sites[kMaxGlobals];
u8 size;
};
bool GetGlobalAddressInformation(uptr addr, GlobalAddressDescription *descr);
bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
} // namespace __asan

View File

@ -25,6 +25,7 @@
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
namespace __asan {
@ -123,18 +124,6 @@ int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
return res;
}
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
Global g = {};
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;
descr->region_kind = "global";
return true;
}
return false;
}
enum GlobalSymbolState {
UNREGISTERED = 0,
REGISTERED = 1
@ -279,6 +268,46 @@ void StopInitOrderChecking() {
}
}
static bool IsASCII(unsigned char c) { return /*0x00 <= c &&*/ c <= 0x7F; }
const char *MaybeDemangleGlobalName(const char *name) {
// We can spoil names of globals with C linkage, so use an heuristic
// approach to check if the name should be demangled.
bool should_demangle = false;
if (name[0] == '_' && name[1] == 'Z')
should_demangle = true;
else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?')
should_demangle = true;
return should_demangle ? Symbolizer::GetOrInit()->Demangle(name) : name;
}
// Check if the global is a zero-terminated ASCII string. If so, print it.
void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g) {
for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
unsigned char c = *(unsigned char *)p;
if (c == '\0' || !IsASCII(c)) return;
}
if (*(char *)(g.beg + g.size - 1) != '\0') return;
str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name),
(char *)g.beg);
}
static const char *GlobalFilename(const __asan_global &g) {
const char *res = g.module_name;
// Prefer the filename from source location, if is available.
if (g.location) res = g.location->filename;
CHECK(res);
return res;
}
void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
str->append("%s", GlobalFilename(g));
if (!g.location) return;
if (g.location->line_no) str->append(":%d", g.location->line_no);
if (g.location->column_no) str->append(":%d", g.location->column_no);
}
} // namespace __asan
// ---------------------- Interface ---------------- {{{1

View File

@ -187,101 +187,6 @@ static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
// ---------------------- Address Descriptions ------------------- {{{1
static bool IsASCII(unsigned char c) {
return /*0x00 <= c &&*/ c <= 0x7F;
}
static const char *MaybeDemangleGlobalName(const char *name) {
// We can spoil names of globals with C linkage, so use an heuristic
// approach to check if the name should be demangled.
bool should_demangle = false;
if (name[0] == '_' && name[1] == 'Z')
should_demangle = true;
else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?')
should_demangle = true;
return should_demangle ? Symbolizer::GetOrInit()->Demangle(name) : name;
}
// Check if the global is a zero-terminated ASCII string. If so, print it.
static void PrintGlobalNameIfASCII(InternalScopedString *str,
const __asan_global &g) {
for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
unsigned char c = *(unsigned char*)p;
if (c == '\0' || !IsASCII(c)) return;
}
if (*(char*)(g.beg + g.size - 1) != '\0') return;
str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name),
(char *)g.beg);
}
static const char *GlobalFilename(const __asan_global &g) {
const char *res = g.module_name;
// Prefer the filename from source location, if is available.
if (g.location)
res = g.location->filename;
CHECK(res);
return res;
}
static void PrintGlobalLocation(InternalScopedString *str,
const __asan_global &g) {
str->append("%s", GlobalFilename(g));
if (!g.location)
return;
if (g.location->line_no)
str->append(":%d", g.location->line_no);
if (g.location->column_no)
str->append(":%d", g.location->column_no);
}
static void DescribeAddressRelativeToGlobal(uptr addr, uptr size,
const __asan_global &g) {
InternalScopedString str(4096);
Decorator d;
str.append("%s", d.Location());
if (addr < g.beg) {
str.append("%p is located %zd bytes to the left", (void *)addr,
g.beg - addr);
} else if (addr + size > g.beg + g.size) {
if (addr < g.beg + g.size)
addr = g.beg + g.size;
str.append("%p is located %zd bytes to the right", (void *)addr,
addr - (g.beg + g.size));
} else {
// Can it happen?
str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg);
}
str.append(" of global variable '%s' defined in '",
MaybeDemangleGlobalName(g.name));
PrintGlobalLocation(&str, g);
str.append("' (0x%zx) of size %zu\n", g.beg, g.size);
str.append("%s", d.EndLocation());
PrintGlobalNameIfASCII(&str, g);
Printf("%s", str.data());
}
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];
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++) {
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;
}
bool ParseFrameDescription(const char *frame_descr,
InternalMmapVector<StackVarDescr> *vars) {
CHECK(frame_descr);

View File

@ -37,7 +37,11 @@ struct AddressDescription {
// them to "globals" array.
int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
int max_globals);
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
const char *MaybeDemangleGlobalName(const char *name);
void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g);
void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g);
// The following functions prints address description depending
// on the memory type (shadow/heap/stack/global).
bool ParseFrameDescription(const char *frame_descr,