summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-12-02 19:48:40 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-12-02 19:48:40 +0000
commit0c7f6f6156b0169240c40d3a77839cd09929aac4 (patch)
tree79201d3484d35f850dcf02367ed946aac97ebbc1
parenta80ff0c4dde117d65c7424b9c104ebe60877e932 (diff)
Simplify Symbolizer::SymbolizePC() interface.
Return a linked list of AddressInfo objects, instead of using an array of these objects as an output parameter. This simplifies the code in callers of this function (especially TSan). Fix a few memory leaks from internal allocator, when the returned AddressInfo objects were not properly cleared. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@223145 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/lsan/lsan_common.cc27
-rw-r--r--lib/sanitizer_common/sanitizer_common_libcdep.cc10
-rw-r--r--lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc19
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer.cc48
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer.h63
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc63
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h4
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc53
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_win.cc23
-rwxr-xr-xlib/tsan/go/buildgo.sh1
-rw-r--r--lib/tsan/go/tsan_go.cc15
-rw-r--r--lib/tsan/rtl/tsan_report.cc48
-rw-r--r--lib/tsan/rtl/tsan_report.h5
-rw-r--r--lib/tsan/rtl/tsan_rtl.h2
-rw-r--r--lib/tsan/rtl/tsan_rtl_report.cc56
-rw-r--r--lib/tsan/rtl/tsan_suppressions.cc3
-rw-r--r--lib/tsan/rtl/tsan_symbolize.cc41
-rw-r--r--lib/tsan/rtl/tsan_symbolize.h2
-rw-r--r--lib/ubsan/ubsan_diag.cc22
19 files changed, 269 insertions, 236 deletions
diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc
index 746244cf1..3375663bb 100644
--- a/lib/lsan/lsan_common.cc
+++ b/lib/lsan/lsan_common.cc
@@ -457,30 +457,27 @@ void DoLeakCheck() {
}
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<AddressInfo> 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) {
diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc
index 4374f56a8..328ea648e 100644
--- a/lib/sanitizer_common/sanitizer_common_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc
@@ -52,16 +52,20 @@ void SetSandboxingCallback(void (*f)()) {
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
diff --git a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
index 13fb01f92..0d90980e6 100644
--- a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
@@ -24,30 +24,21 @@ void StackTrace::Print() const {
Printf(" <empty stack>\n\n");
return;
}
- const int kMaxAddrFrames = 64;
- InternalScopedBuffer<AddressInfo> 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");
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.cc b/lib/sanitizer_common/sanitizer_symbolizer.cc
index 8aa9de072..135720ed5 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer.cc
+++ b/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_;
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.h b/lib/sanitizer_common/sanitizer_symbolizer.h
index 82093e454..3ccfce999 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer.h
+++ b/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 @@ struct AddressInfo {
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 @@ class Symbolizer {
/// 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;
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
index 4ec6f0a19..bb8ba6b81 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
@@ -83,44 +83,52 @@ char *CplusV3Demangle(const char *name) {
}
# 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 @@ LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
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 @@ LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
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) {
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
index 6c536cc36..a335cb237 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
@@ -32,8 +32,8 @@ class LibbacktraceSymbolizer {
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);
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index e4c3f8d23..d46c249e6 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -514,34 +514,32 @@ class POSIXSymbolizer : public Symbolizer {
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 @@ class POSIXSymbolizer : public Symbolizer {
// 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 <file>:<line>:<column> buffer.
char *file_line_info = 0;
@@ -572,14 +580,7 @@ class POSIXSymbolizer : public Symbolizer {
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 {
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
index e60ab23b2..6bb7d3805 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
@@ -26,9 +26,8 @@ class WinSymbolizer : public Symbolizer {
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 @@ class WinSymbolizer : public Symbolizer {
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 {
diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh
index dbb92f377..697a5de2a 100755
--- a/lib/tsan/go/buildgo.sh
+++ b/lib/tsan/go/buildgo.sh
@@ -27,6 +27,7 @@ SRCS="
../../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
diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc
index c1d401f6f..cccf72ced 100644
--- a/lib/tsan/go/tsan_go.cc
+++ b/lib/tsan/go/tsan_go.cc
@@ -59,18 +59,19 @@ struct SymbolizeContext {
// 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;
}
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index f4a1ddb69..255793198 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/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 @@ static const char *ReportTypeString(ReportType typ) {
}
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 @@ static ReportStack *ChooseSummaryStack(const ReportDesc *rep) {
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 @@ 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))) {
- 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 @@ void PrintReport(const ReportDesc *rep) {
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);
}
diff --git a/lib/tsan/rtl/tsan_report.h b/lib/tsan/rtl/tsan_report.h
index e6d853508..3e344a048 100644
--- a/lib/tsan/rtl/tsan_report.h
+++ b/lib/tsan/rtl/tsan_report.h
@@ -36,10 +36,9 @@ enum ReportType {
};
struct ReportStack {
- ReportStack *next;
- AddressInfo info;
+ SymbolizedStack *frames;
bool suppressable;
- static ReportStack *New(uptr addr);
+ static ReportStack *New();
private:
ReportStack();
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 591d10d33..cce2e2d8b 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -568,8 +568,6 @@ bool IsFiredSuppression(Context *ctx, const ScopedReport &srep,
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
diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index c7a00c906..889fe7bb6 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/lib/tsan/rtl/tsan_rtl_report.cc
@@ -56,40 +56,43 @@ bool WEAK OnReport(const ReportDesc *rep, bool suppressed) {
}
#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 @@ ReportStack *SymbolizeStackId(u32 stack_id) {
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 @@ static ReportStack *SymbolizeStack(StackTrace trace) {
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 @@ static bool IsFiredSuppression(Context *ctx,
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]);
diff --git a/lib/tsan/rtl/tsan_suppressions.cc b/lib/tsan/rtl/tsan_suppressions.cc
index 1c5bea01f..2fb089305 100644
--- a/lib/tsan/rtl/tsan_suppressions.cc
+++ b/lib/tsan/rtl/tsan_suppressions.cc
@@ -92,7 +92,8 @@ uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
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) ||
diff --git a/lib/tsan/rtl/tsan_symbolize.cc b/lib/tsan/rtl/tsan_symbolize.cc
index c08de6a37..3c2ea7993 100644
--- a/lib/tsan/rtl/tsan_symbolize.cc
+++ b/lib/tsan/rtl/tsan_symbolize.cc
@@ -55,7 +55,7 @@ bool __tsan_symbolize_external(uptr pc,
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 @@ 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 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<AddressInfo> 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) {
diff --git a/lib/tsan/rtl/tsan_symbolize.h b/lib/tsan/rtl/tsan_symbolize.h
index 828edc9bd..5a9710a3c 100644
--- a/lib/tsan/rtl/tsan_symbolize.h
+++ b/lib/tsan/rtl/tsan_symbolize.h
@@ -20,7 +20,7 @@ namespace __tsan {
void EnterSymbolizer();
void ExitSymbolizer();
-ReportStack *SymbolizeCode(uptr addr);
+SymbolizedStack *SymbolizeCode(uptr addr);
ReportLocation *SymbolizeData(uptr addr);
void SymbolizeFlush();
diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc
index f56250849..76ce2bd39 100644
--- a/lib/ubsan/ubsan_diag.cc
+++ b/lib/ubsan/ubsan_diag.cc
@@ -79,18 +79,26 @@ Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) {
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) {