1 //===-- tsan_external.cc --------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
12 //===----------------------------------------------------------------------===//
14 #include "tsan_interceptors.h"
18 #define CALLERPC ((uptr)__builtin_return_address(0))
20 const uptr kMaxTag = 128; // Limited to 65,536, since MBlock only stores tags
21 // as 16-bit values, see tsan_defs.h.
23 const char *registered_tags[kMaxTag];
24 static atomic_uint32_t used_tags{1}; // Tag 0 means "no tag". NOLINT
26 const char *GetObjectTypeFromTag(uptr tag) {
27 if (tag == 0) return nullptr;
28 // Invalid/corrupted tag? Better return NULL and let the caller deal with it.
29 if (tag >= atomic_load(&used_tags, memory_order_relaxed)) return nullptr;
30 return registered_tags[tag];
33 typedef void(*AccessFunc)(ThreadState *, uptr, uptr, int);
34 void ExternalAccess(void *addr, void *caller_pc, void *tag, AccessFunc access) {
35 CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
36 ThreadState *thr = cur_thread();
37 thr->external_tag = (uptr)tag;
38 if (caller_pc) FuncEntry(thr, (uptr)caller_pc);
40 if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) {
41 access(thr, CALLERPC, (uptr)addr, kSizeLog1);
43 if (caller_pc) FuncExit(thr);
44 thr->external_tag = 0;
48 SANITIZER_INTERFACE_ATTRIBUTE
49 void *__tsan_external_register_tag(const char *object_type) {
50 uptr new_tag = atomic_fetch_add(&used_tags, 1, memory_order_relaxed);
51 CHECK_LT(new_tag, kMaxTag);
52 registered_tags[new_tag] = internal_strdup(object_type);
53 return (void *)new_tag;
56 SANITIZER_INTERFACE_ATTRIBUTE
57 void __tsan_external_assign_tag(void *addr, void *tag) {
58 CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
59 Allocator *a = allocator();
61 if (a->PointerIsMine((void *)addr)) {
62 void *block_begin = a->GetBlockBegin((void *)addr);
63 if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin);
70 SANITIZER_INTERFACE_ATTRIBUTE
71 void __tsan_external_read(void *addr, void *caller_pc, void *tag) {
72 ExternalAccess(addr, caller_pc, tag, MemoryRead);
75 SANITIZER_INTERFACE_ATTRIBUTE
76 void __tsan_external_write(void *addr, void *caller_pc, void *tag) {
77 ExternalAccess(addr, caller_pc, tag, MemoryWrite);