summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl/tsan_external.cc
diff options
context:
space:
mode:
authorKuba Mracek <mracek@apple.com>2017-04-30 20:35:18 +0000
committerKuba Mracek <mracek@apple.com>2017-04-30 20:35:18 +0000
commitaa1c977562f63984d19f8c1fc97adb94b9e493eb (patch)
tree05e4736196fce2bd67c3b11d8020c095626827bc /lib/tsan/rtl/tsan_external.cc
parentfce320da7a80b1b0f2d1228b9be6a83280315d40 (diff)
[tsan] Track external tags in thread traces
To make the TSan external API work with Swift and other use cases, we need to track "tags" for individual memory accesses. Since there is no space to store this information in shadow cells, let's use the thread traces for that. This patch stores the tag as an extra frame in the stack traces (by calling FuncEntry and FuncExit with the address of a registered tag), this extra frame is then stripped before printing the backtrace to stderr. Differential Revision: https://reviews.llvm.org/D32382 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@301777 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan/rtl/tsan_external.cc')
-rw-r--r--lib/tsan/rtl/tsan_external.cc29
1 files changed, 21 insertions, 8 deletions
diff --git a/lib/tsan/rtl/tsan_external.cc b/lib/tsan/rtl/tsan_external.cc
index 88468e406..2d32b6dac 100644
--- a/lib/tsan/rtl/tsan_external.cc
+++ b/lib/tsan/rtl/tsan_external.cc
@@ -17,11 +17,8 @@ namespace __tsan {
#define CALLERPC ((uptr)__builtin_return_address(0))
-const uptr kMaxTag = 128; // Limited to 65,536, since MBlock only stores tags
- // as 16-bit values, see tsan_defs.h.
-
-const char *registered_tags[kMaxTag];
-static atomic_uint32_t used_tags{1}; // Tag 0 means "no tag". NOLINT
+const char *registered_tags[kExternalTagMax];
+static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable}; // NOLINT.
const char *GetObjectTypeFromTag(uptr tag) {
if (tag == 0) return nullptr;
@@ -30,25 +27,39 @@ const char *GetObjectTypeFromTag(uptr tag) {
return registered_tags[tag];
}
+void InsertShadowStackFrameForTag(ThreadState *thr, uptr tag) {
+ FuncEntry(thr, (uptr)&registered_tags[tag]);
+}
+
+uptr TagFromShadowStackFrame(uptr pc) {
+ uptr tag_count = atomic_load(&used_tags, memory_order_relaxed);
+ void *pc_ptr = (void *)pc;
+ if (pc_ptr < &registered_tags[0] || pc_ptr >= &registered_tags[tag_count])
+ return 0;
+ return (const char **)pc_ptr - &registered_tags[0];
+}
+
+#if !SANITIZER_GO
+
typedef void(*AccessFunc)(ThreadState *, uptr, uptr, int);
void ExternalAccess(void *addr, void *caller_pc, void *tag, AccessFunc access) {
CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
ThreadState *thr = cur_thread();
- thr->external_tag = (uptr)tag;
if (caller_pc) FuncEntry(thr, (uptr)caller_pc);
+ InsertShadowStackFrameForTag(thr, (uptr)tag);
bool in_ignored_lib;
if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) {
access(thr, CALLERPC, (uptr)addr, kSizeLog1);
}
+ FuncExit(thr);
if (caller_pc) FuncExit(thr);
- thr->external_tag = 0;
}
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void *__tsan_external_register_tag(const char *object_type) {
uptr new_tag = atomic_fetch_add(&used_tags, 1, memory_order_relaxed);
- CHECK_LT(new_tag, kMaxTag);
+ CHECK_LT(new_tag, kExternalTagMax);
registered_tags[new_tag] = internal_strdup(object_type);
return (void *)new_tag;
}
@@ -78,4 +89,6 @@ void __tsan_external_write(void *addr, void *caller_pc, void *tag) {
}
} // extern "C"
+#endif // !SANITIZER_GO
+
} // namespace __tsan