1//===-- asan_posix.cpp ----------------------------------------------------===//
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
32namespace __asan {
33
34void 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
47static void (*tsd_destructor)(void *tsd) = nullptr;
48
49struct 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
59static thread_local struct tsd_key key;
60
61void AsanTSDInit(void (*destructor)(void *tsd)) {
62  CHECK(!tsd_destructor);
63  tsd_destructor = destructor;
64}
65
66void *AsanTSDGet() {
67  CHECK(tsd_destructor);
68  return key.key;
69}
70
71void AsanTSDSet(void *tsd) {
72  CHECK(tsd_destructor);
73  CHECK(tsd);
74  CHECK(!key.key);
75  key.key = tsd;
76}
77
78void 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
87static pthread_key_t tsd_key;
88static bool tsd_key_inited = false;
89void 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
95void *AsanTSDGet() {
96  CHECK(tsd_key_inited);
97  return pthread_getspecific(tsd_key);
98}
99
100void AsanTSDSet(void *tsd) {
101  CHECK(tsd_key_inited);
102  pthread_setspecific(tsd_key, tsd);
103}
104
105void 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
118