1353944Sdim//===-- asan_posix.cpp ----------------------------------------------------===//
2353944Sdim//
3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353944Sdim// See https://llvm.org/LICENSE.txt for license information.
5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353944Sdim//
7353944Sdim//===----------------------------------------------------------------------===//
8353944Sdim//
9353944Sdim// This file is a part of AddressSanitizer, an address sanity checker.
10353944Sdim//
11353944Sdim// Posix-specific details.
12353944Sdim//===----------------------------------------------------------------------===//
13353944Sdim
14353944Sdim#include "sanitizer_common/sanitizer_platform.h"
15353944Sdim#if SANITIZER_POSIX
16353944Sdim
17353944Sdim#include "asan_internal.h"
18353944Sdim#include "asan_interceptors.h"
19353944Sdim#include "asan_mapping.h"
20353944Sdim#include "asan_report.h"
21353944Sdim#include "asan_stack.h"
22353944Sdim#include "sanitizer_common/sanitizer_libc.h"
23353944Sdim#include "sanitizer_common/sanitizer_posix.h"
24353944Sdim#include "sanitizer_common/sanitizer_procmaps.h"
25353944Sdim
26353944Sdim#include <pthread.h>
27353944Sdim#include <stdlib.h>
28353944Sdim#include <sys/time.h>
29353944Sdim#include <sys/resource.h>
30353944Sdim#include <unistd.h>
31353944Sdim
32353944Sdimnamespace __asan {
33353944Sdim
34353944Sdimvoid AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
35353944Sdim  StartReportDeadlySignal();
36353944Sdim  SignalContext sig(siginfo, context);
37353944Sdim  ReportDeadlySignal(sig);
38353944Sdim}
39353944Sdim
40353944Sdim// ---------------------- TSD ---------------- {{{1
41353944Sdim
42353944Sdim#if SANITIZER_NETBSD && !ASAN_DYNAMIC
43353944Sdim// Thread Static Data cannot be used in early static ASan init on NetBSD.
44353944Sdim// Reuse the Asan TSD API for compatibility with existing code
45353944Sdim// with an alternative implementation.
46353944Sdim
47353944Sdimstatic void (*tsd_destructor)(void *tsd) = nullptr;
48353944Sdim
49353944Sdimstruct tsd_key {
50353944Sdim  tsd_key() : key(nullptr) {}
51353944Sdim  ~tsd_key() {
52353944Sdim    CHECK(tsd_destructor);
53353944Sdim    if (key)
54353944Sdim      (*tsd_destructor)(key);
55353944Sdim  }
56353944Sdim  void *key;
57353944Sdim};
58353944Sdim
59353944Sdimstatic thread_local struct tsd_key key;
60353944Sdim
61353944Sdimvoid AsanTSDInit(void (*destructor)(void *tsd)) {
62353944Sdim  CHECK(!tsd_destructor);
63353944Sdim  tsd_destructor = destructor;
64353944Sdim}
65353944Sdim
66353944Sdimvoid *AsanTSDGet() {
67353944Sdim  CHECK(tsd_destructor);
68353944Sdim  return key.key;
69353944Sdim}
70353944Sdim
71353944Sdimvoid AsanTSDSet(void *tsd) {
72353944Sdim  CHECK(tsd_destructor);
73353944Sdim  CHECK(tsd);
74353944Sdim  CHECK(!key.key);
75353944Sdim  key.key = tsd;
76353944Sdim}
77353944Sdim
78353944Sdimvoid PlatformTSDDtor(void *tsd) {
79353944Sdim  CHECK(tsd_destructor);
80353944Sdim  CHECK_EQ(key.key, tsd);
81353944Sdim  key.key = nullptr;
82353944Sdim  // Make sure that signal handler can not see a stale current thread pointer.
83353944Sdim  atomic_signal_fence(memory_order_seq_cst);
84353944Sdim  AsanThread::TSDDtor(tsd);
85353944Sdim}
86353944Sdim#else
87353944Sdimstatic pthread_key_t tsd_key;
88353944Sdimstatic bool tsd_key_inited = false;
89353944Sdimvoid AsanTSDInit(void (*destructor)(void *tsd)) {
90353944Sdim  CHECK(!tsd_key_inited);
91353944Sdim  tsd_key_inited = true;
92353944Sdim  CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
93353944Sdim}
94353944Sdim
95353944Sdimvoid *AsanTSDGet() {
96353944Sdim  CHECK(tsd_key_inited);
97353944Sdim  return pthread_getspecific(tsd_key);
98353944Sdim}
99353944Sdim
100353944Sdimvoid AsanTSDSet(void *tsd) {
101353944Sdim  CHECK(tsd_key_inited);
102353944Sdim  pthread_setspecific(tsd_key, tsd);
103353944Sdim}
104353944Sdim
105353944Sdimvoid PlatformTSDDtor(void *tsd) {
106353944Sdim  AsanThreadContext *context = (AsanThreadContext*)tsd;
107353944Sdim  if (context->destructor_iterations > 1) {
108353944Sdim    context->destructor_iterations--;
109353944Sdim    CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
110353944Sdim    return;
111353944Sdim  }
112353944Sdim  AsanThread::TSDDtor(tsd);
113353944Sdim}
114353944Sdim#endif
115353944Sdim}  // namespace __asan
116353944Sdim
117353944Sdim#endif  // SANITIZER_POSIX
118