[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:
Alexey Samsonov 2014-11-04 20:52:37 +00:00
parent a11cab3120
commit e3754634c0
6 changed files with 64 additions and 82 deletions

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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;

View File

@ -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