summaryrefslogtreecommitdiff
path: root/lib/tsan
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-03-21 08:44:14 +0000
committerDmitry Vyukov <dvyukov@google.com>2018-03-21 08:44:14 +0000
commit6f6e03a3c09e31ff6fda4ad9f215ca0c6d495d34 (patch)
tree41ef242b0459054369f95a04a80ed6ac4f7bdbec /lib/tsan
parentdef0ac6300d4511350d7abbb883f42faf708a132 (diff)
tsan: support inlined frames in external symbolization
New API passes a callback function to the external symbolizer, allowing it to add multiple frames to the traceback. Note that the old interface API will be still supported until the clients migrate to the new one. Author: asmundak (Alexander Smundak) Reviewed in: https://reviews.llvm.org/D44714 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@328079 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan')
-rw-r--r--lib/tsan/rtl/tsan_rtl_report.cc4
-rw-r--r--lib/tsan/rtl/tsan_symbolize.cc42
2 files changed, 44 insertions, 2 deletions
diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index cc582ab50..febb6cef2 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/lib/tsan/rtl/tsan_rtl_report.cc
@@ -649,8 +649,8 @@ void ReportRace(ThreadState *thr) {
// callback. Most likely, TraceTopPC will now return a EventTypeFuncExit
// event. Later we subtract -1 from it (in GetPreviousInstructionPc)
// and the resulting PC has kExternalPCBit set, so we pass it to
- // __tsan_symbolize_external. __tsan_symbolize_external is within its rights
- // to crash since the PC is completely bogus.
+ // __tsan_symbolize_external_ex. __tsan_symbolize_external_ex is within its
+ // rights to crash since the PC is completely bogus.
// test/tsan/double_race.cc contains a test case for this.
toppc = 0;
}
diff --git a/lib/tsan/rtl/tsan_symbolize.cc b/lib/tsan/rtl/tsan_symbolize.cc
index b24239517..de50c4eb3 100644
--- a/lib/tsan/rtl/tsan_symbolize.cc
+++ b/lib/tsan/rtl/tsan_symbolize.cc
@@ -36,6 +36,7 @@ void ExitSymbolizer() {
thr->ignore_interceptors--;
}
+// Legacy API.
// May be overriden by JIT/JAVA/etc,
// whatever produces PCs marked with kExternalPCBit.
SANITIZER_WEAK_DEFAULT_IMPL
@@ -45,9 +46,50 @@ bool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz,
return false;
}
+// New API: call __tsan_symbolize_external_ex only when it exists.
+// Once old clients are gone, provide dummy implementation.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+void __tsan_symbolize_external_ex(uptr pc,
+ void (*add_frame)(void *, const char *,
+ const char *, int, int),
+ void *ctx);
+
+struct SymbolizedStackBuilder {
+ SymbolizedStack *head;
+ SymbolizedStack *tail;
+ uptr addr;
+};
+
+static void AddFrame(void *ctx, const char *function_name, const char *file,
+ int line, int column) {
+ SymbolizedStackBuilder *ssb = (struct SymbolizedStackBuilder *)ctx;
+ if (ssb->tail) {
+ ssb->tail->next = SymbolizedStack::New(ssb->addr);
+ ssb->tail = ssb->tail->next;
+ } else {
+ ssb->head = ssb->tail = SymbolizedStack::New(ssb->addr);
+ }
+ AddressInfo *info = &ssb->tail->info;
+ if (function_name) {
+ info->function = internal_strdup(function_name);
+ }
+ if (file) {
+ info->file = internal_strdup(file);
+ }
+ info->line = line;
+ info->column = column;
+}
+
SymbolizedStack *SymbolizeCode(uptr addr) {
// Check if PC comes from non-native land.
if (addr & kExternalPCBit) {
+ if (__tsan_symbolize_external_ex) {
+ SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};
+ __tsan_symbolize_external_ex(addr, AddFrame, &ssb);
+ return ssb.head ? ssb.head : SymbolizedStack::New(addr);
+ }
+ // Legacy code: remove along with the declaration above
+ // once all clients using this API are gone.
// Declare static to not consume too much stack space.
// We symbolize reports in a single thread, so this is fine.
static char func_buf[1024];