Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -457,30 +457,27 @@ } static Suppression *GetSuppressionForAddr(uptr addr) { - Suppression *s; + Suppression *s = nullptr; // Suppress by module name. const char *module_name; uptr module_offset; - if (Symbolizer::GetOrInit() - ->GetModuleNameAndOffsetForPC(addr, &module_name, &module_offset) && + if (Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(addr, &module_name, + &module_offset) && SuppressionContext::Get()->Match(module_name, SuppressionLeak, &s)) return s; // Suppress by file or function name. - static const uptr kMaxAddrFrames = 16; - InternalScopedBuffer addr_frames(kMaxAddrFrames); - for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo(); - uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC( - addr, addr_frames.data(), kMaxAddrFrames); - for (uptr i = 0; i < addr_frames_num; i++) { - if (SuppressionContext::Get()->Match(addr_frames[i].function, - SuppressionLeak, &s) || - SuppressionContext::Get()->Match(addr_frames[i].file, SuppressionLeak, - &s)) - return s; + SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr); + for (SymbolizedStack *cur = frames; cur; cur = cur->next) { + if (SuppressionContext::Get()->Match(cur->info.function, SuppressionLeak, + &s) || + SuppressionContext::Get()->Match(cur->info.file, SuppressionLeak, &s)) { + break; + } } - return 0; + frames->ClearAll(); + return s; } static Suppression *GetSuppressionForStack(u32 stack_trace_id) { Index: lib/sanitizer_common/sanitizer_common_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_common_libcdep.cc +++ lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -52,16 +52,20 @@ void ReportErrorSummary(const char *error_type, StackTrace *stack) { if (!common_flags()->print_summary) return; - AddressInfo ai; #if !SANITIZER_GO if (stack->size > 0 && Symbolizer::GetOrInit()->CanReturnFileLineInfo()) { // Currently, we include the first stack frame into the report summary. // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); - Symbolizer::GetOrInit()->SymbolizePC(pc, &ai, 1); + SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); + const AddressInfo &ai = frame->info; + ReportErrorSummary(error_type, ai.file, ai.line, ai.function); + frame->ClearAll(); } -#endif +#else + AddressInfo ai; ReportErrorSummary(error_type, ai.file, ai.line, ai.function); +#endif } } // namespace __sanitizer Index: lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc +++ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc @@ -24,30 +24,21 @@ Printf(" \n\n"); return; } - const int kMaxAddrFrames = 64; - InternalScopedBuffer addr_frames(kMaxAddrFrames); - for (uptr i = 0; i < kMaxAddrFrames; i++) - new(&addr_frames[i]) AddressInfo(); InternalScopedString frame_desc(GetPageSizeCached() * 2); uptr frame_num = 0; for (uptr i = 0; i < size && trace[i]; i++) { // PCs in stack traces are actually the return addresses, that is, // addresses of the next instructions after the call. uptr pc = GetPreviousInstructionPc(trace[i]); - uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC( - pc, addr_frames.data(), kMaxAddrFrames); - if (addr_frames_num == 0) { - addr_frames[0].address = pc; - addr_frames_num = 1; - } - for (uptr j = 0; j < addr_frames_num; j++) { - AddressInfo &info = addr_frames[j]; + SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(pc); + CHECK(frames); + for (SymbolizedStack *cur = frames; cur; cur = cur->next) { frame_desc.clear(); RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++, - info, common_flags()->strip_path_prefix); + cur->info, common_flags()->strip_path_prefix); Printf("%s\n", frame_desc.data()); - info.Clear(); } + frames->ClearAll(); } // Always print a trailing empty line after stack trace. Printf("\n"); Index: lib/sanitizer_common/sanitizer_symbolizer.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.h +++ lib/sanitizer_common/sanitizer_symbolizer.h @@ -19,13 +19,14 @@ #ifndef SANITIZER_SYMBOLIZER_H #define SANITIZER_SYMBOLIZER_H -#include "sanitizer_allocator_internal.h" -#include "sanitizer_internal_defs.h" -#include "sanitizer_libc.h" +#include "sanitizer_common.h" +#include "sanitizer_mutex.h" namespace __sanitizer { struct AddressInfo { + // Owns all the string members. Storage for them is + // (de)allocated using sanitizer internal allocator. uptr address; char *module; @@ -39,45 +40,38 @@ int line; int column; - AddressInfo() { - internal_memset(this, 0, sizeof(AddressInfo)); - function_offset = kUnknown; - } - + AddressInfo(); // Deletes all strings and resets all fields. - void Clear() { - InternalFree(module); - InternalFree(function); - InternalFree(file); - internal_memset(this, 0, sizeof(AddressInfo)); - function_offset = kUnknown; - } - + void Clear(); void FillAddressAndModuleInfo(uptr addr, const char *mod_name, - uptr mod_offset) { - address = addr; - module = internal_strdup(mod_name); - module_offset = mod_offset; - } + uptr mod_offset); +}; + +// Linked list of symbolized frames (each frame is described by AddressInfo). +struct SymbolizedStack { + SymbolizedStack *next; + AddressInfo info; + static SymbolizedStack *New(uptr addr); + // Deletes current, and all subsequent frames in the linked list. + // The object cannot be accessed after the call to this function. + void ClearAll(); + + private: + SymbolizedStack(); }; // For now, DataInfo is used to describe global variable. struct DataInfo { + // Owns all the string members. Storage for them is + // (de)allocated using sanitizer internal allocator. char *module; uptr module_offset; char *name; uptr start; uptr size; - DataInfo() { - internal_memset(this, 0, sizeof(DataInfo)); - } - - void Clear() { - InternalFree(module); - InternalFree(name); - internal_memset(this, 0, sizeof(DataInfo)); - } + DataInfo(); + void Clear(); }; class Symbolizer { @@ -85,11 +79,10 @@ /// Initialize and return platform-specific implementation of symbolizer /// (if it wasn't already initialized). static Symbolizer *GetOrInit(); - // Fills at most "max_frames" elements of "frames" with descriptions - // for a given address (in all inlined functions). Returns the number - // of descriptions actually filled. - virtual uptr SymbolizePC(uptr address, AddressInfo *frames, uptr max_frames) { - return 0; + // Returns a list of symbolized frames for a given address (containing + // all inlined functions, if necessary). + virtual SymbolizedStack *SymbolizePC(uptr address) { + return SymbolizedStack::New(address); } virtual bool SymbolizeData(uptr address, DataInfo *info) { return false; Index: lib/sanitizer_common/sanitizer_symbolizer.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.cc +++ lib/sanitizer_common/sanitizer_symbolizer.cc @@ -11,13 +11,61 @@ // run-time libraries. //===----------------------------------------------------------------------===// +#include "sanitizer_allocator_internal.h" #include "sanitizer_platform.h" #include "sanitizer_internal_defs.h" +#include "sanitizer_libc.h" #include "sanitizer_placement_new.h" #include "sanitizer_symbolizer.h" namespace __sanitizer { +AddressInfo::AddressInfo() { + internal_memset(this, 0, sizeof(AddressInfo)); + function_offset = kUnknown; +} + +void AddressInfo::Clear() { + InternalFree(module); + InternalFree(function); + InternalFree(file); + internal_memset(this, 0, sizeof(AddressInfo)); + function_offset = kUnknown; +} + +void AddressInfo::FillAddressAndModuleInfo(uptr addr, const char *mod_name, + uptr mod_offset) { + address = addr; + module = internal_strdup(mod_name); + module_offset = mod_offset; +} + +SymbolizedStack::SymbolizedStack() : next(nullptr), info() {} + +SymbolizedStack *SymbolizedStack::New(uptr addr) { + void *mem = InternalAlloc(sizeof(SymbolizedStack)); + SymbolizedStack *res = new(mem) SymbolizedStack(); + res->info.address = addr; + return res; +} + +void SymbolizedStack::ClearAll() { + info.Clear(); + if (next) + next->ClearAll(); + InternalFree(this); +} + +DataInfo::DataInfo() { + internal_memset(this, 0, sizeof(DataInfo)); +} + +void DataInfo::Clear() { + InternalFree(module); + InternalFree(name); + internal_memset(this, 0, sizeof(DataInfo)); +} + Symbolizer *Symbolizer::symbolizer_; StaticSpinMutex Symbolizer::init_mu_; LowLevelAllocator Symbolizer::symbolizer_allocator_; Index: lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h +++ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h @@ -32,8 +32,8 @@ public: static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc); - uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames, - const char *module_name, uptr module_offset); + SymbolizedStack *SymbolizeCode(uptr addr, const char *module_name, + uptr module_offset); bool SymbolizeData(DataInfo *info); Index: lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc +++ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc @@ -83,44 +83,52 @@ } # endif // SANITIZER_CP_DEMANGLE -struct SymbolizeCodeData { - AddressInfo *frames; - uptr n_frames; - uptr max_frames; +struct SymbolizeCodeCallbackArg { + SymbolizedStack *first; + SymbolizedStack *last; const char *module_name; uptr module_offset; + + void append(SymbolizedStack *f) { + if (last != nullptr) { + last->next = f; + last = f; + } else { + first = f; + last = f; + } + } }; extern "C" { static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr, const char *filename, int lineno, const char *function) { - SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata; + SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata; if (function) { - AddressInfo *info = &cdata->frames[cdata->n_frames++]; - info->Clear(); + SymbolizedStack *cur = SymbolizedStack::New(addr); + cdata->append(cur); + AddressInfo *info = &cur->info; info->FillAddressAndModuleInfo(addr, cdata->module_name, cdata->module_offset); info->function = LibbacktraceSymbolizer::Demangle(function, true); if (filename) info->file = internal_strdup(filename); info->line = lineno; - if (cdata->n_frames == cdata->max_frames) - return 1; } return 0; } static void SymbolizeCodeCallback(void *vdata, uintptr_t addr, const char *symname, uintptr_t, uintptr_t) { - SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata; + SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata; if (symname) { - AddressInfo *info = &cdata->frames[0]; - info->Clear(); + SymbolizedStack *cur = SymbolizedStack::New(addr); + cdata->append(cur); + AddressInfo *info = &cur->info; info->FillAddressAndModuleInfo(addr, cdata->module_name, cdata->module_offset); info->function = LibbacktraceSymbolizer::Demangle(symname, true); - cdata->n_frames = 1; } } @@ -148,23 +156,21 @@ return new(*alloc) LibbacktraceSymbolizer(state); } -uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo *frames, - uptr max_frames, - const char *module_name, - uptr module_offset) { - SymbolizeCodeData data; - data.frames = frames; - data.n_frames = 0; - data.max_frames = max_frames; +SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr, + const char *module_name, + uptr module_offset) { + SymbolizeCodeCallbackArg data; + data.first = nullptr; + data.last = nullptr; data.module_name = module_name; data.module_offset = module_offset; backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback, ErrorCallback, &data); - if (data.n_frames) - return data.n_frames; + if (data.first) + return data.first; backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback, ErrorCallback, &data); - return data.n_frames; + return data.first; } bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) { @@ -179,12 +185,11 @@ return 0; } -uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo *frames, - uptr max_frames, - const char *module_name, - uptr module_offset) { +SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr, + const char *module_name, + uptr module_offset) { (void)state_; - return 0; + return nullptr; } bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) { Index: lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -514,34 +514,32 @@ internal_symbolizer_(internal_symbolizer), libbacktrace_symbolizer_(libbacktrace_symbolizer) {} - uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) override { + SymbolizedStack *SymbolizePC(uptr addr) override { BlockingMutexLock l(&mu_); - if (max_frames == 0) - return 0; const char *module_name; uptr module_offset; if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) - return 0; + return SymbolizedStack::New(addr); // First, try to use libbacktrace symbolizer (if it's available). if (libbacktrace_symbolizer_ != 0) { mu_.CheckLocked(); - uptr res = libbacktrace_symbolizer_->SymbolizeCode( - addr, frames, max_frames, module_name, module_offset); - if (res > 0) + if (SymbolizedStack *res = libbacktrace_symbolizer_->SymbolizeCode( + addr, module_name, module_offset)) return res; } + // Always fill data about module name and offset. + SymbolizedStack *res = SymbolizedStack::New(addr); + res->info.FillAddressAndModuleInfo(addr, module_name, module_offset); + const char *str = SendCommand(false, module_name, module_offset); if (str == 0) { - // Symbolizer was not initialized or failed. Fill only data - // about module name and offset. - AddressInfo *info = &frames[0]; - info->Clear(); - info->FillAddressAndModuleInfo(addr, module_name, module_offset); - return 1; + // Symbolizer was not initialized or failed. + return res; } - uptr frame_id = 0; - for (frame_id = 0; frame_id < max_frames; frame_id++) { - AddressInfo *info = &frames[frame_id]; + + bool top_frame = true; + SymbolizedStack *last = res; + while (true) { char *function_name = 0; str = ExtractToken(str, "\n", &function_name); CHECK(function_name); @@ -549,8 +547,18 @@ // There are no more frames. break; } - info->Clear(); - info->FillAddressAndModuleInfo(addr, module_name, module_offset); + SymbolizedStack *cur; + if (top_frame) { + cur = res; + top_frame = false; + } else { + cur = SymbolizedStack::New(addr); + cur->info.FillAddressAndModuleInfo(addr, module_name, module_offset); + last->next = cur; + last = cur; + } + + AddressInfo *info = &cur->info; info->function = function_name; // Parse :: buffer. char *file_line_info = 0; @@ -572,14 +580,7 @@ info->file = 0; } } - if (frame_id == 0) { - // Make sure we return at least one frame. - AddressInfo *info = &frames[0]; - info->Clear(); - info->FillAddressAndModuleInfo(addr, module_name, module_offset); - frame_id = 1; - } - return frame_id; + return res; } bool SymbolizeData(uptr addr, DataInfo *info) override { Index: lib/sanitizer_common/sanitizer_symbolizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -26,9 +26,8 @@ public: WinSymbolizer() : initialized_(false) {} - uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) override { - if (max_frames == 0) - return 0; + SymbolizedStack *SymbolizePC(uptr addr) override { + SymbolizedStack *frame = SymbolizedStack::New(addr); BlockingMutexLock l(&dbghelp_mu_); if (!initialized_) { @@ -60,29 +59,27 @@ BOOL got_objname = SymFromAddr(GetCurrentProcess(), (DWORD64)addr, &offset, symbol); if (!got_objname) - return 0; + return frame; DWORD unused; IMAGEHLP_LINE64 line_info; line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr, &unused, &line_info); - AddressInfo *info = &frames[0]; - info->Clear(); - info->function = internal_strdup(symbol->Name); - info->function_offset = (uptr)offset; + frame->info.function = internal_strdup(symbol->Name); + frame->info.function_offset = (uptr)offset; if (got_fileline) { - info->file = internal_strdup(line_info.FileName); - info->line = line_info.LineNumber; + frame->info.file = internal_strdup(line_info.FileName); + frame->info.line = line_info.LineNumber; } IMAGEHLP_MODULE64 mod_info; internal_memset(&mod_info, 0, sizeof(mod_info)); mod_info.SizeOfStruct = sizeof(mod_info); if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info)) - info->FillAddressAndModuleInfo(addr, mod_info.ImageName, - addr - (uptr)mod_info.BaseOfImage); - return 1; + frame->info.FillAddressAndModuleInfo(addr, mod_info.ImageName, + addr - (uptr)mod_info.BaseOfImage); + return frame; } bool CanReturnFileLineInfo() override { Index: lib/tsan/go/buildgo.sh =================================================================== --- lib/tsan/go/buildgo.sh +++ lib/tsan/go/buildgo.sh @@ -27,6 +27,7 @@ ../../sanitizer_common/sanitizer_thread_registry.cc ../../sanitizer_common/sanitizer_stackdepot.cc ../../sanitizer_common/sanitizer_stacktrace.cc + ../../sanitizer_common/sanitizer_symbolizer.cc " if [ "`uname -a | grep Linux`" != "" ]; then Index: lib/tsan/go/tsan_go.cc =================================================================== --- lib/tsan/go/tsan_go.cc +++ lib/tsan/go/tsan_go.cc @@ -59,18 +59,19 @@ // Callback into Go. static void (*symbolize_cb)(SymbolizeContext *ctx); -ReportStack *SymbolizeCode(uptr addr) { - ReportStack *s = ReportStack::New(addr); +SymbolizedStack *SymbolizeCode(uptr addr) { + SymbolizedStack *s = SymbolizedStack::New(addr); SymbolizeContext ctx; internal_memset(&ctx, 0, sizeof(ctx)); ctx.pc = addr; symbolize_cb(&ctx); if (ctx.res) { - 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; + AddressInfo &info = s->info; + info.module_offset = ctx.off; + info.function = internal_strdup(ctx.func ? ctx.func : "??"); + info.file = internal_strdup(ctx.file ? ctx.file : "-"); + info.line = ctx.line; + info.column = 0; } return s; } Index: lib/tsan/rtl/tsan_report.h =================================================================== --- lib/tsan/rtl/tsan_report.h +++ lib/tsan/rtl/tsan_report.h @@ -36,10 +36,9 @@ }; struct ReportStack { - ReportStack *next; - AddressInfo info; + SymbolizedStack *frames; bool suppressable; - static ReportStack *New(uptr addr); + static ReportStack *New(); private: ReportStack(); Index: lib/tsan/rtl/tsan_report.cc =================================================================== --- lib/tsan/rtl/tsan_report.cc +++ lib/tsan/rtl/tsan_report.cc @@ -19,13 +19,11 @@ namespace __tsan { -ReportStack::ReportStack() : next(nullptr), info(), suppressable(false) {} +ReportStack::ReportStack() : frames(nullptr), suppressable(false) {} -ReportStack *ReportStack::New(uptr addr) { +ReportStack *ReportStack::New() { void *mem = internal_alloc(MBlockReportStack, sizeof(ReportStack)); - ReportStack *res = new(mem) ReportStack(); - res->info.address = addr; - return res; + return new(mem) ReportStack(); } ReportLocation::ReportLocation(ReportLocationType type) @@ -114,13 +112,14 @@ } void PrintStack(const ReportStack *ent) { - if (ent == 0) { + if (ent == 0 || ent->frames == 0) { Printf(" [failed to restore the stack]\n\n"); return; } - for (int i = 0; ent && ent->info.address; ent = ent->next, i++) { + SymbolizedStack *frame = ent->frames; + for (int i = 0; frame && frame->info.address; frame = frame->next, i++) { InternalScopedString res(2 * GetPageSizeCached()); - RenderFrame(&res, common_flags()->stack_trace_format, i, ent->info, + RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info, common_flags()->strip_path_prefix, "__interceptor_"); Printf("%s\n", res.data()); } @@ -252,10 +251,20 @@ return 0; } -ReportStack *SkipTsanInternalFrames(ReportStack *ent) { - while (FrameIsInternal(ent) && ent->next) - ent = ent->next; - return ent; +static bool FrameIsInternal(const SymbolizedStack *frame) { + 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 SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) { + while (FrameIsInternal(frames) && frames->next) + frames = frames->next; + return frames; } void PrintReport(const ReportDesc *rep) { @@ -325,9 +334,11 @@ 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))) { - const AddressInfo &info = ent->info; - ReportErrorSummary(rep_typ_str, info.file, info.line, info.function); + if (ReportStack *stack = ChooseSummaryStack(rep)) { + if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames)) { + const AddressInfo &info = frame->info; + ReportErrorSummary(rep_typ_str, info.file, info.line, info.function); + } } Printf("==================\n"); @@ -338,12 +349,13 @@ const int kMainThreadId = 1; void PrintStack(const ReportStack *ent) { - if (ent == 0) { + if (ent == 0 || ent->frames == 0) { Printf(" [failed to restore the stack]\n"); return; } - for (int i = 0; ent; ent = ent->next, i++) { - const AddressInfo &info = ent->info; + SymbolizedStack *frame = ent->frames; + for (int i = 0; frame; frame = frame->next, i++) { + const AddressInfo &info = frame->info; Printf(" %s()\n %s:%d +0x%zx\n", info.function, info.file, info.line, (void *)info.module_offset); } Index: lib/tsan/rtl/tsan_rtl.h =================================================================== --- lib/tsan/rtl/tsan_rtl.h +++ lib/tsan/rtl/tsan_rtl.h @@ -568,8 +568,6 @@ StackTrace trace); bool IsExpectedReport(uptr addr, uptr size); void PrintMatchedBenignRaces(); -bool FrameIsInternal(const ReportStack *frame); -ReportStack *SkipTsanInternalFrames(ReportStack *ent); #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1 # define DPrintf Printf Index: lib/tsan/rtl/tsan_rtl_report.cc =================================================================== --- lib/tsan/rtl/tsan_rtl_report.cc +++ lib/tsan/rtl/tsan_rtl_report.cc @@ -56,40 +56,43 @@ } #endif -static void StackStripMain(ReportStack *stack) { - ReportStack *last_frame = 0; - ReportStack *last_frame2 = 0; - for (ReportStack *ent = stack; ent; ent = ent->next) { +static void StackStripMain(SymbolizedStack *frames) { + SymbolizedStack *last_frame = nullptr; + SymbolizedStack *last_frame2 = nullptr; + for (SymbolizedStack *cur = frames; cur; cur = cur->next) { last_frame2 = last_frame; - last_frame = ent; + last_frame = cur; } if (last_frame2 == 0) return; - const char *last = last_frame->info.function; #ifndef TSAN_GO + const char *last = last_frame->info.function; const char *last2 = last_frame2->info.function; // Strip frame above 'main' if (last2 && 0 == internal_strcmp(last2, "main")) { - last_frame2->next = 0; + last_frame->ClearAll(); + last_frame2->next = nullptr; // Strip our internal thread start routine. } else if (last && 0 == internal_strcmp(last, "__tsan_thread_start_func")) { - last_frame2->next = 0; + last_frame->ClearAll(); + last_frame2->next = nullptr; // Strip global ctors init. } else if (last && 0 == internal_strcmp(last, "__do_global_ctors_aux")) { - last_frame2->next = 0; + last_frame->ClearAll(); + last_frame2->next = nullptr; // If both are 0, then we probably just failed to symbolize. } else if (last || last2) { // Ensure that we recovered stack completely. Trimmed stack // can actually happen if we do not instrument some code, // so it's only a debug print. However we must try hard to not miss it // due to our fault. - DPrintf("Bottom stack frame of stack %zx is missed\n", stack->pc); + DPrintf("Bottom stack frame of stack %zx is missed\n", stack->info.address); } #else // The last frame always point into runtime (gosched0, goexit0, runtime.main). - last_frame2->next = 0; - (void)last; + last_frame->ClearAll(); + last_frame2->next = nullptr; #endif } @@ -105,12 +108,12 @@ static ReportStack *SymbolizeStack(StackTrace trace) { if (trace.size == 0) return 0; - ReportStack *stack = 0; + SymbolizedStack *top = nullptr; for (uptr si = 0; si < trace.size; si++) { const uptr pc = trace.trace[si]; #ifndef TSAN_GO - // We obtain the return address, that is, address of the next instruction, - // so offset it by 1 byte. + // We obtain the return address, but we're interested in the previous + // instruction. const uptr pc1 = StackTrace::GetPreviousInstructionPc(pc); #else // FIXME(dvyukov): Go sometimes uses address of a function as top pc. @@ -118,18 +121,21 @@ if (si != trace.size - 1) pc1 -= 1; #endif - ReportStack *ent = SymbolizeCode(pc1); + SymbolizedStack *ent = SymbolizeCode(pc1); CHECK_NE(ent, 0); - ReportStack *last = ent; + SymbolizedStack *last = ent; while (last->next) { last->info.address = pc; // restore original pc for report last = last->next; } last->info.address = pc; // restore original pc for report - last->next = stack; - stack = ent; + last->next = top; + top = ent; } - StackStripMain(stack); + StackStripMain(top); + + ReportStack *stack = ReportStack::New(); + stack->frames = top; return stack; } @@ -547,16 +553,6 @@ return false; } -bool FrameIsInternal(const ReportStack *frame) { - 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) { Shadow s0(thr->racy_state[0]); Shadow s1(thr->racy_state[1]); Index: lib/tsan/rtl/tsan_suppressions.cc =================================================================== --- lib/tsan/rtl/tsan_suppressions.cc +++ lib/tsan/rtl/tsan_suppressions.cc @@ -92,7 +92,8 @@ if (stype == SuppressionNone) return 0; Suppression *s; - for (const ReportStack *frame = stack; frame; frame = frame->next) { + for (const SymbolizedStack *frame = stack->frames; frame; + frame = frame->next) { const AddressInfo &info = frame->info; if (SuppressionContext::Get()->Match(info.function, stype, &s) || SuppressionContext::Get()->Match(info.file, stype, &s) || Index: lib/tsan/rtl/tsan_symbolize.h =================================================================== --- lib/tsan/rtl/tsan_symbolize.h +++ lib/tsan/rtl/tsan_symbolize.h @@ -20,7 +20,7 @@ void EnterSymbolizer(); void ExitSymbolizer(); -ReportStack *SymbolizeCode(uptr addr); +SymbolizedStack *SymbolizeCode(uptr addr); ReportLocation *SymbolizeData(uptr addr); void SymbolizeFlush(); Index: lib/tsan/rtl/tsan_symbolize.cc =================================================================== --- lib/tsan/rtl/tsan_symbolize.cc +++ lib/tsan/rtl/tsan_symbolize.cc @@ -55,7 +55,7 @@ return false; } -ReportStack *SymbolizeCode(uptr addr) { +SymbolizedStack *SymbolizeCode(uptr addr) { // Check if PC comes from non-native land. if (addr & kExternalPCBit) { // Declare static to not consume too much stack space. @@ -63,36 +63,17 @@ 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 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; + SymbolizedStack *frame = SymbolizedStack::New(addr); + if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), file_buf, + sizeof(file_buf), &line, &col)) { + frame->info.function = internal_strdup(func_buf); + frame->info.file = internal_strdup(file_buf); + frame->info.line = line; + frame->info.column = col; + } + return frame; } - static const uptr kMaxAddrFrames = 16; - InternalScopedBuffer addr_frames(kMaxAddrFrames); - for (uptr i = 0; i < kMaxAddrFrames; i++) - new(&addr_frames[i]) AddressInfo(); - uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC( - addr, addr_frames.data(), kMaxAddrFrames); - if (addr_frames_num == 0) - return ReportStack::New(addr); - ReportStack *top = 0; - ReportStack *bottom = 0; - for (uptr i = 0; i < addr_frames_num; i++) { - ReportStack *cur_entry = ReportStack::New(addr); - cur_entry->info = addr_frames[i]; - if (i == 0) - top = cur_entry; - else - bottom->next = cur_entry; - bottom = cur_entry; - } - return top; + return Symbolizer::GetOrInit()->SymbolizePC(addr); } ReportLocation *SymbolizeData(uptr addr) { Index: lib/ubsan/ubsan_diag.cc =================================================================== --- lib/ubsan/ubsan_diag.cc +++ lib/ubsan/ubsan_diag.cc @@ -79,18 +79,26 @@ return Location(); InitIfNecessary(); - AddressInfo Info; - if (!Symbolizer::GetOrInit()->SymbolizePC(Loc, &Info, 1) || !Info.module || - !*Info.module) + SymbolizedStack *Frames = Symbolizer::GetOrInit()->SymbolizePC(Loc); + const AddressInfo &Info = Frames->info; + + if (!Info.module) { + Frames->ClearAll(); return Location(Loc); + } if (FName && Info.function) - *FName = Info.function; + *FName = internal_strdup(Info.function); - if (!Info.file) - return ModuleLocation(Info.module, Info.module_offset); + if (!Info.file) { + ModuleLocation MLoc(internal_strdup(Info.module), Info.module_offset); + Frames->ClearAll(); + return MLoc; + } - return SourceLocation(Info.file, Info.line, Info.column); + SourceLocation SLoc(internal_strdup(Info.file), Info.line, Info.column); + Frames->ClearAll(); + return SLoc; } Diag &Diag::operator<<(const TypeDescriptor &V) {