]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/tsan/rtl/tsan_external.cc
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r301441, and update
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / tsan / rtl / tsan_external.cc
1 //===-- tsan_external.cc --------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "tsan_rtl.h"
14 #include "tsan_interceptors.h"
15
16 namespace __tsan {
17
18 #define CALLERPC ((uptr)__builtin_return_address(0))
19
20 const uptr kMaxTag = 128;  // Limited to 65,536, since MBlock only stores tags
21                            // as 16-bit values, see tsan_defs.h.
22
23 const char *registered_tags[kMaxTag];
24 static atomic_uint32_t used_tags{1};  // Tag 0 means "no tag". NOLINT
25
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];
31 }
32
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);
39   bool in_ignored_lib;
40   if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) {
41     access(thr, CALLERPC, (uptr)addr, kSizeLog1);
42   }
43   if (caller_pc) FuncExit(thr);
44   thr->external_tag = 0;
45 }
46
47 extern "C" {
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;
54 }
55
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();
60   MBlock *b = nullptr;
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);
64   }
65   if (b) {
66     b->tag = (uptr)tag;
67   }
68 }
69
70 SANITIZER_INTERFACE_ATTRIBUTE
71 void __tsan_external_read(void *addr, void *caller_pc, void *tag) {
72   ExternalAccess(addr, caller_pc, tag, MemoryRead);
73 }
74
75 SANITIZER_INTERFACE_ATTRIBUTE
76 void __tsan_external_write(void *addr, void *caller_pc, void *tag) {
77   ExternalAccess(addr, caller_pc, tag, MemoryWrite);
78 }
79 }  // extern "C"
80
81 }  // namespace __tsan