forked from OSchip/llvm-project
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:
parent
2e767d1972
commit
41f41635f9
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue