]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/compiler-rt/lib/asan/asan_posix.cc
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / compiler-rt / lib / asan / asan_posix.cc
1 //===-- asan_posix.cc -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of AddressSanitizer, an address sanity checker.
10 //
11 // Posix-specific details.
12 //===----------------------------------------------------------------------===//
13
14 #include "sanitizer_common/sanitizer_platform.h"
15 #if SANITIZER_POSIX
16
17 #include "asan_internal.h"
18 #include "asan_interceptors.h"
19 #include "asan_mapping.h"
20 #include "asan_report.h"
21 #include "asan_stack.h"
22 #include "sanitizer_common/sanitizer_libc.h"
23 #include "sanitizer_common/sanitizer_posix.h"
24 #include "sanitizer_common/sanitizer_procmaps.h"
25
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <sys/time.h>
29 #include <sys/resource.h>
30 #include <unistd.h>
31
32 namespace __asan {
33
34 void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
35   StartReportDeadlySignal();
36   SignalContext sig(siginfo, context);
37   ReportDeadlySignal(sig);
38 }
39
40 // ---------------------- TSD ---------------- {{{1
41
42 #if SANITIZER_NETBSD && !ASAN_DYNAMIC
43 // Thread Static Data cannot be used in early static ASan init on NetBSD.
44 // Reuse the Asan TSD API for compatibility with existing code
45 // with an alternative implementation.
46
47 static void (*tsd_destructor)(void *tsd) = nullptr;
48
49 struct tsd_key {
50   tsd_key() : key(nullptr) {}
51   ~tsd_key() {
52     CHECK(tsd_destructor);
53     if (key)
54       (*tsd_destructor)(key);
55   }
56   void *key;
57 };
58
59 static thread_local struct tsd_key key;
60
61 void AsanTSDInit(void (*destructor)(void *tsd)) {
62   CHECK(!tsd_destructor);
63   tsd_destructor = destructor;
64 }
65
66 void *AsanTSDGet() {
67   CHECK(tsd_destructor);
68   return key.key;
69 }
70
71 void AsanTSDSet(void *tsd) {
72   CHECK(tsd_destructor);
73   CHECK(tsd);
74   CHECK(!key.key);
75   key.key = tsd;
76 }
77
78 void PlatformTSDDtor(void *tsd) {
79   CHECK(tsd_destructor);
80   CHECK_EQ(key.key, tsd);
81   key.key = nullptr;
82   // Make sure that signal handler can not see a stale current thread pointer.
83   atomic_signal_fence(memory_order_seq_cst);
84   AsanThread::TSDDtor(tsd);
85 }
86 #else
87 static pthread_key_t tsd_key;
88 static bool tsd_key_inited = false;
89 void AsanTSDInit(void (*destructor)(void *tsd)) {
90   CHECK(!tsd_key_inited);
91   tsd_key_inited = true;
92   CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
93 }
94
95 void *AsanTSDGet() {
96   CHECK(tsd_key_inited);
97   return pthread_getspecific(tsd_key);
98 }
99
100 void AsanTSDSet(void *tsd) {
101   CHECK(tsd_key_inited);
102   pthread_setspecific(tsd_key, tsd);
103 }
104
105 void PlatformTSDDtor(void *tsd) {
106   AsanThreadContext *context = (AsanThreadContext*)tsd;
107   if (context->destructor_iterations > 1) {
108     context->destructor_iterations--;
109     CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
110     return;
111   }
112   AsanThread::TSDDtor(tsd);
113 }
114 #endif
115 }  // namespace __asan
116
117 #endif  // SANITIZER_POSIX