forked from OSchip/llvm-project
[TSan] Make ReportStack contain __sanitizer::AddressInfo object.
AddressInfo contains the results of symbolization. Store this object directly in the symbolized stack, instead of copying data around and making unnecessary memory allocations. No functionality change. llvm-svn: 221294
This commit is contained in:
parent
a11cab3120
commit
e3754634c0
|
@ -39,14 +39,6 @@ ReportLocation *SymbolizeData(uptr addr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
ReportStack *NewReportStackEntry(uptr addr) {
|
||||
ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
|
||||
sizeof(ReportStack));
|
||||
internal_memset(ent, 0, sizeof(*ent));
|
||||
ent->pc = addr;
|
||||
return ent;
|
||||
}
|
||||
|
||||
void *internal_alloc(MBlockType typ, uptr sz) {
|
||||
return InternalAlloc(sz);
|
||||
}
|
||||
|
@ -68,20 +60,17 @@ struct SymbolizeContext {
|
|||
static void (*symbolize_cb)(SymbolizeContext *ctx);
|
||||
|
||||
ReportStack *SymbolizeCode(uptr addr) {
|
||||
ReportStack *s = (ReportStack*)internal_alloc(MBlockReportStack,
|
||||
sizeof(ReportStack));
|
||||
internal_memset(s, 0, sizeof(*s));
|
||||
s->pc = addr;
|
||||
ReportStack *s = ReportStack::New(addr);
|
||||
SymbolizeContext ctx;
|
||||
internal_memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.pc = addr;
|
||||
symbolize_cb(&ctx);
|
||||
if (ctx.res) {
|
||||
s->offset = ctx.off;
|
||||
s->func = internal_strdup(ctx.func ? ctx.func : "??");
|
||||
s->file = internal_strdup(ctx.file ? ctx.file : "-");
|
||||
s->line = ctx.line;
|
||||
s->col = 0;
|
||||
s->info.module_offset = ctx.off;
|
||||
s->info.function = internal_strdup(ctx.func ? ctx.func : "??");
|
||||
s->info.file = internal_strdup(ctx.file ? ctx.file : "-");
|
||||
s->info.line = ctx.line;
|
||||
s->info.column = 0;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -13,10 +13,20 @@
|
|||
#include "tsan_report.h"
|
||||
#include "tsan_platform.h"
|
||||
#include "tsan_rtl.h"
|
||||
#include "sanitizer_common/sanitizer_placement_new.h"
|
||||
#include "sanitizer_common/sanitizer_report_decorator.h"
|
||||
|
||||
namespace __tsan {
|
||||
|
||||
ReportStack::ReportStack() : next(nullptr), info(), suppressable(false) {}
|
||||
|
||||
ReportStack *ReportStack::New(uptr addr) {
|
||||
void *mem = internal_alloc(MBlockReportStack, sizeof(ReportStack));
|
||||
ReportStack *res = new(mem) ReportStack();
|
||||
res->info.address = addr;
|
||||
return res;
|
||||
}
|
||||
|
||||
class Decorator: public __sanitizer::SanitizerCommonDecorator {
|
||||
public:
|
||||
Decorator() : SanitizerCommonDecorator() { }
|
||||
|
@ -108,16 +118,18 @@ void PrintStack(const ReportStack *ent) {
|
|||
return;
|
||||
}
|
||||
for (int i = 0; ent; ent = ent->next, i++) {
|
||||
const AddressInfo &info = ent->info;
|
||||
Printf(" #%d %s %s:%d", i,
|
||||
StripFunctionName(ent->func, "__interceptor_"),
|
||||
StripPathPrefix(ent->file, common_flags()->strip_path_prefix),
|
||||
ent->line);
|
||||
if (ent->col)
|
||||
Printf(":%d", ent->col);
|
||||
if (ent->module && ent->offset) {
|
||||
Printf(" (%s+%p)\n", StripModuleName(ent->module), (void*)ent->offset);
|
||||
StripFunctionName(info.function, "__interceptor_"),
|
||||
StripPathPrefix(info.file, common_flags()->strip_path_prefix),
|
||||
info.line);
|
||||
if (info.column)
|
||||
Printf(":%d", info.column);
|
||||
if (info.module && info.module_offset) {
|
||||
Printf(" (%s+%p)\n", StripModuleName(info.module),
|
||||
(void *)info.module_offset);
|
||||
} else {
|
||||
Printf(" (%p)\n", (void*)ent->pc);
|
||||
Printf(" (%p)\n", (void *)info.address);
|
||||
}
|
||||
}
|
||||
Printf("\n");
|
||||
|
@ -318,8 +330,10 @@ void PrintReport(const ReportDesc *rep) {
|
|||
if (rep->typ == ReportTypeThreadLeak && rep->count > 1)
|
||||
Printf(" And %d more similar thread leaks.\n\n", rep->count - 1);
|
||||
|
||||
if (ReportStack *ent = SkipTsanInternalFrames(ChooseSummaryStack(rep)))
|
||||
ReportErrorSummary(rep_typ_str, ent->file, ent->line, ent->func);
|
||||
if (ReportStack *ent = SkipTsanInternalFrames(ChooseSummaryStack(rep))) {
|
||||
const AddressInfo &info = ent->info;
|
||||
ReportErrorSummary(rep_typ_str, info.file, info.line, info.function);
|
||||
}
|
||||
|
||||
Printf("==================\n");
|
||||
}
|
||||
|
@ -334,8 +348,9 @@ void PrintStack(const ReportStack *ent) {
|
|||
return;
|
||||
}
|
||||
for (int i = 0; ent; ent = ent->next, i++) {
|
||||
Printf(" %s()\n %s:%d +0x%zx\n",
|
||||
ent->func, ent->file, ent->line, (void*)ent->offset);
|
||||
const AddressInfo &info = ent->info;
|
||||
Printf(" %s()\n %s:%d +0x%zx\n", info.function, info.file, info.line,
|
||||
(void *)info.module_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#ifndef TSAN_REPORT_H
|
||||
#define TSAN_REPORT_H
|
||||
|
||||
#include "sanitizer_common/sanitizer_symbolizer.h"
|
||||
#include "tsan_defs.h"
|
||||
#include "tsan_vector.h"
|
||||
|
||||
|
@ -36,14 +37,12 @@ enum ReportType {
|
|||
|
||||
struct ReportStack {
|
||||
ReportStack *next;
|
||||
char *module;
|
||||
uptr offset;
|
||||
uptr pc;
|
||||
char *func;
|
||||
char *file;
|
||||
int line;
|
||||
int col;
|
||||
AddressInfo info;
|
||||
bool suppressable;
|
||||
static ReportStack *New(uptr addr);
|
||||
|
||||
private:
|
||||
ReportStack();
|
||||
};
|
||||
|
||||
struct ReportMopMutex {
|
||||
|
|
|
@ -66,9 +66,9 @@ static void StackStripMain(ReportStack *stack) {
|
|||
|
||||
if (last_frame2 == 0)
|
||||
return;
|
||||
const char *last = last_frame->func;
|
||||
const char *last = last_frame->info.function;
|
||||
#ifndef TSAN_GO
|
||||
const char *last2 = last_frame2->func;
|
||||
const char *last2 = last_frame2->info.function;
|
||||
// Strip frame above 'main'
|
||||
if (last2 && 0 == internal_strcmp(last2, "main")) {
|
||||
last_frame2->next = 0;
|
||||
|
@ -122,10 +122,10 @@ static ReportStack *SymbolizeStack(StackTrace trace) {
|
|||
CHECK_NE(ent, 0);
|
||||
ReportStack *last = ent;
|
||||
while (last->next) {
|
||||
last->pc = pc; // restore original pc for report
|
||||
last->info.address = pc; // restore original pc for report
|
||||
last = last->next;
|
||||
}
|
||||
last->pc = pc; // restore original pc for report
|
||||
last->info.address = pc; // restore original pc for report
|
||||
last->next = stack;
|
||||
stack = ent;
|
||||
}
|
||||
|
@ -558,10 +558,13 @@ static bool IsFiredSuppression(Context *ctx,
|
|||
}
|
||||
|
||||
bool FrameIsInternal(const ReportStack *frame) {
|
||||
return frame != 0 && frame->file != 0
|
||||
&& (internal_strstr(frame->file, "tsan_interceptors.cc") ||
|
||||
internal_strstr(frame->file, "sanitizer_common_interceptors.inc") ||
|
||||
internal_strstr(frame->file, "tsan_interface_"));
|
||||
if (frame == 0)
|
||||
return false;
|
||||
const char *file = frame->info.file;
|
||||
return file != 0 &&
|
||||
(internal_strstr(file, "tsan_interceptors.cc") ||
|
||||
internal_strstr(file, "sanitizer_common_interceptors.inc") ||
|
||||
internal_strstr(file, "tsan_interface_"));
|
||||
}
|
||||
|
||||
static bool RaceBetweenAtomicAndFree(ThreadState *thr) {
|
||||
|
|
|
@ -93,13 +93,14 @@ uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
|
|||
return 0;
|
||||
Suppression *s;
|
||||
for (const ReportStack *frame = stack; frame; frame = frame->next) {
|
||||
if (SuppressionContext::Get()->Match(frame->func, stype, &s) ||
|
||||
SuppressionContext::Get()->Match(frame->file, stype, &s) ||
|
||||
SuppressionContext::Get()->Match(frame->module, stype, &s)) {
|
||||
const AddressInfo &info = frame->info;
|
||||
if (SuppressionContext::Get()->Match(info.function, stype, &s) ||
|
||||
SuppressionContext::Get()->Match(info.file, stype, &s) ||
|
||||
SuppressionContext::Get()->Match(info.module, stype, &s)) {
|
||||
DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
|
||||
s->hit_count++;
|
||||
*sp = s;
|
||||
return frame->pc;
|
||||
return info.address;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -36,28 +36,6 @@ void ExitSymbolizer() {
|
|||
thr->ignore_interceptors--;
|
||||
}
|
||||
|
||||
ReportStack *NewReportStackEntry(uptr addr) {
|
||||
ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
|
||||
sizeof(ReportStack));
|
||||
internal_memset(ent, 0, sizeof(*ent));
|
||||
ent->pc = addr;
|
||||
return ent;
|
||||
}
|
||||
|
||||
static ReportStack *NewReportStackEntry(const AddressInfo &info) {
|
||||
ReportStack *ent = NewReportStackEntry(info.address);
|
||||
if (info.module)
|
||||
ent->module = internal_strdup(info.module);
|
||||
ent->offset = info.module_offset;
|
||||
if (info.function)
|
||||
ent->func = internal_strdup(info.function);
|
||||
if (info.file)
|
||||
ent->file = internal_strdup(info.file);
|
||||
ent->line = info.line;
|
||||
ent->col = info.column;
|
||||
return ent;
|
||||
}
|
||||
|
||||
// Denotes fake PC values that come from JIT/JAVA/etc.
|
||||
// For such PC values __tsan_symbolize_external() will be called.
|
||||
const uptr kExternalPCBit = 1ULL << 60;
|
||||
|
@ -85,16 +63,14 @@ ReportStack *SymbolizeCode(uptr addr) {
|
|||
static char func_buf[1024];
|
||||
static char file_buf[1024];
|
||||
int line, col;
|
||||
ReportStack *ent = ReportStack::New(addr);
|
||||
if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf),
|
||||
file_buf, sizeof(file_buf), &line, &col))
|
||||
return NewReportStackEntry(addr);
|
||||
ReportStack *ent = NewReportStackEntry(addr);
|
||||
ent->module = 0;
|
||||
ent->offset = 0;
|
||||
ent->func = internal_strdup(func_buf);
|
||||
ent->file = internal_strdup(file_buf);
|
||||
ent->line = line;
|
||||
ent->col = col;
|
||||
return ent;
|
||||
ent->info.function = internal_strdup(func_buf);
|
||||
ent->info.file = internal_strdup(file_buf);
|
||||
ent->info.line = line;
|
||||
ent->info.column = col;
|
||||
return ent;
|
||||
}
|
||||
static const uptr kMaxAddrFrames = 16;
|
||||
|
@ -104,13 +80,12 @@ ReportStack *SymbolizeCode(uptr addr) {
|
|||
uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
|
||||
addr, addr_frames.data(), kMaxAddrFrames);
|
||||
if (addr_frames_num == 0)
|
||||
return NewReportStackEntry(addr);
|
||||
return ReportStack::New(addr);
|
||||
ReportStack *top = 0;
|
||||
ReportStack *bottom = 0;
|
||||
for (uptr i = 0; i < addr_frames_num; i++) {
|
||||
ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
|
||||
CHECK(cur_entry);
|
||||
addr_frames[i].Clear();
|
||||
ReportStack *cur_entry = ReportStack::New(addr);
|
||||
cur_entry->info = addr_frames[i];
|
||||
if (i == 0)
|
||||
top = cur_entry;
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue