]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
Update compiler-rt to trunk r228651. This enables using Address
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_posix_libcdep.cc
1 //===-- sanitizer_posix_libcdep.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 shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries and implements libc-dependent POSIX-specific functions
12 // from sanitizer_libc.h.
13 //===----------------------------------------------------------------------===//
14
15 #include "sanitizer_platform.h"
16
17 #if SANITIZER_POSIX
18 #include "sanitizer_common.h"
19 #include "sanitizer_flags.h"
20 #include "sanitizer_platform_limits_posix.h"
21 #include "sanitizer_stacktrace.h"
22
23 #include <errno.h>
24 #include <pthread.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <sys/mman.h>
28 #include <sys/resource.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32
33 namespace __sanitizer {
34
35 u32 GetUid() {
36   return getuid();
37 }
38
39 uptr GetThreadSelf() {
40   return (uptr)pthread_self();
41 }
42
43 void FlushUnneededShadowMemory(uptr addr, uptr size) {
44   madvise((void*)addr, size, MADV_DONTNEED);
45 }
46
47 void NoHugePagesInRegion(uptr addr, uptr size) {
48 #ifdef MADV_NOHUGEPAGE  // May not be defined on old systems.
49   madvise((void *)addr, size, MADV_NOHUGEPAGE);
50 #endif  // MADV_NOHUGEPAGE
51 }
52
53 void DontDumpShadowMemory(uptr addr, uptr length) {
54 #ifdef MADV_DONTDUMP
55   madvise((void *)addr, length, MADV_DONTDUMP);
56 #endif
57 }
58
59 static rlim_t getlim(int res) {
60   rlimit rlim;
61   CHECK_EQ(0, getrlimit(res, &rlim));
62   return rlim.rlim_cur;
63 }
64
65 static void setlim(int res, rlim_t lim) {
66   // The following magic is to prevent clang from replacing it with memset.
67   volatile struct rlimit rlim;
68   rlim.rlim_cur = lim;
69   rlim.rlim_max = lim;
70   if (setrlimit(res, const_cast<struct rlimit *>(&rlim))) {
71     Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
72     Die();
73   }
74 }
75
76 void DisableCoreDumperIfNecessary() {
77   if (common_flags()->disable_coredump) {
78     setlim(RLIMIT_CORE, 0);
79   }
80 }
81
82 bool StackSizeIsUnlimited() {
83   rlim_t stack_size = getlim(RLIMIT_STACK);
84   return (stack_size == RLIM_INFINITY);
85 }
86
87 void SetStackSizeLimitInBytes(uptr limit) {
88   setlim(RLIMIT_STACK, (rlim_t)limit);
89   CHECK(!StackSizeIsUnlimited());
90 }
91
92 bool AddressSpaceIsUnlimited() {
93   rlim_t as_size = getlim(RLIMIT_AS);
94   return (as_size == RLIM_INFINITY);
95 }
96
97 void SetAddressSpaceUnlimited() {
98   setlim(RLIMIT_AS, RLIM_INFINITY);
99   CHECK(AddressSpaceIsUnlimited());
100 }
101
102 void SleepForSeconds(int seconds) {
103   sleep(seconds);
104 }
105
106 void SleepForMillis(int millis) {
107   usleep(millis * 1000);
108 }
109
110 void Abort() {
111   abort();
112 }
113
114 int Atexit(void (*function)(void)) {
115 #ifndef SANITIZER_GO
116   return atexit(function);
117 #else
118   return 0;
119 #endif
120 }
121
122 int internal_isatty(fd_t fd) {
123   return isatty(fd);
124 }
125
126 #ifndef SANITIZER_GO
127 // TODO(glider): different tools may require different altstack size.
128 static const uptr kAltStackSize = SIGSTKSZ * 4;  // SIGSTKSZ is not enough.
129
130 void SetAlternateSignalStack() {
131   stack_t altstack, oldstack;
132   CHECK_EQ(0, sigaltstack(0, &oldstack));
133   // If the alternate stack is already in place, do nothing.
134   // Android always sets an alternate stack, but it's too small for us.
135   if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return;
136   // TODO(glider): the mapped stack should have the MAP_STACK flag in the
137   // future. It is not required by man 2 sigaltstack now (they're using
138   // malloc()).
139   void* base = MmapOrDie(kAltStackSize, __func__);
140   altstack.ss_sp = (char*) base;
141   altstack.ss_flags = 0;
142   altstack.ss_size = kAltStackSize;
143   CHECK_EQ(0, sigaltstack(&altstack, 0));
144 }
145
146 void UnsetAlternateSignalStack() {
147   stack_t altstack, oldstack;
148   altstack.ss_sp = 0;
149   altstack.ss_flags = SS_DISABLE;
150   altstack.ss_size = kAltStackSize;  // Some sane value required on Darwin.
151   CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
152   UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
153 }
154
155 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
156 static void MaybeInstallSigaction(int signum,
157                                   SignalHandlerType handler) {
158   if (!IsDeadlySignal(signum))
159     return;
160   struct sigaction sigact;
161   internal_memset(&sigact, 0, sizeof(sigact));
162   sigact.sa_sigaction = (sa_sigaction_t)handler;
163   // Do not block the signal from being received in that signal's handler.
164   // Clients are responsible for handling this correctly.
165   sigact.sa_flags = SA_SIGINFO | SA_NODEFER;
166   if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
167   CHECK_EQ(0, internal_sigaction(signum, &sigact, 0));
168   VReport(1, "Installed the sigaction for signal %d\n", signum);
169 }
170
171 void InstallDeadlySignalHandlers(SignalHandlerType handler) {
172   // Set the alternate signal stack for the main thread.
173   // This will cause SetAlternateSignalStack to be called twice, but the stack
174   // will be actually set only once.
175   if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
176   MaybeInstallSigaction(SIGSEGV, handler);
177   MaybeInstallSigaction(SIGBUS, handler);
178 }
179 #endif  // SANITIZER_GO
180
181 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
182   uptr page_size = GetPageSizeCached();
183   // Checking too large memory ranges is slow.
184   CHECK_LT(size, page_size * 10);
185   int sock_pair[2];
186   if (pipe(sock_pair))
187     return false;
188   uptr bytes_written =
189       internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
190   int write_errno;
191   bool result;
192   if (internal_iserror(bytes_written, &write_errno)) {
193     CHECK_EQ(EFAULT, write_errno);
194     result = false;
195   } else {
196     result = (bytes_written == size);
197   }
198   internal_close(sock_pair[0]);
199   internal_close(sock_pair[1]);
200   return result;
201 }
202
203 }  // namespace __sanitizer
204
205 #endif  // SANITIZER_POSIX