]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 DisableCoreDumper() { | |
48 | struct rlimit nocore; | |
49 | nocore.rlim_cur = 0; | |
50 | nocore.rlim_max = 0; | |
51 | setrlimit(RLIMIT_CORE, &nocore); | |
52 | } | |
53 | ||
54 | bool StackSizeIsUnlimited() { | |
55 | struct rlimit rlim; | |
56 | CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim)); | |
57 | return ((uptr)rlim.rlim_cur == (uptr)-1); | |
58 | } | |
59 | ||
60 | void SetStackSizeLimitInBytes(uptr limit) { | |
61 | struct rlimit rlim; | |
62 | rlim.rlim_cur = limit; | |
63 | rlim.rlim_max = limit; | |
64 | if (setrlimit(RLIMIT_STACK, &rlim)) { | |
65 | Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno); | |
66 | Die(); | |
67 | } | |
68 | CHECK(!StackSizeIsUnlimited()); | |
69 | } | |
70 | ||
71 | void SleepForSeconds(int seconds) { | |
72 | sleep(seconds); | |
73 | } | |
74 | ||
75 | void SleepForMillis(int millis) { | |
76 | usleep(millis * 1000); | |
77 | } | |
78 | ||
79 | void Abort() { | |
80 | abort(); | |
81 | } | |
82 | ||
83 | int Atexit(void (*function)(void)) { | |
84 | #ifndef SANITIZER_GO | |
85 | return atexit(function); | |
86 | #else | |
87 | return 0; | |
88 | #endif | |
89 | } | |
90 | ||
91 | int internal_isatty(fd_t fd) { | |
92 | return isatty(fd); | |
93 | } | |
94 | ||
95 | #ifndef SANITIZER_GO | |
96 | // TODO(glider): different tools may require different altstack size. | |
97 | static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. | |
98 | ||
99 | void SetAlternateSignalStack() { | |
100 | stack_t altstack, oldstack; | |
101 | CHECK_EQ(0, sigaltstack(0, &oldstack)); | |
102 | // If the alternate stack is already in place, do nothing. | |
103 | // Android always sets an alternate stack, but it's too small for us. | |
104 | if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return; | |
105 | // TODO(glider): the mapped stack should have the MAP_STACK flag in the | |
106 | // future. It is not required by man 2 sigaltstack now (they're using | |
107 | // malloc()). | |
108 | void* base = MmapOrDie(kAltStackSize, __func__); | |
109 | altstack.ss_sp = (char*) base; | |
110 | altstack.ss_flags = 0; | |
111 | altstack.ss_size = kAltStackSize; | |
112 | CHECK_EQ(0, sigaltstack(&altstack, 0)); | |
113 | } | |
114 | ||
115 | void UnsetAlternateSignalStack() { | |
116 | stack_t altstack, oldstack; | |
117 | altstack.ss_sp = 0; | |
118 | altstack.ss_flags = SS_DISABLE; | |
119 | altstack.ss_size = kAltStackSize; // Some sane value required on Darwin. | |
120 | CHECK_EQ(0, sigaltstack(&altstack, &oldstack)); | |
121 | UnmapOrDie(oldstack.ss_sp, oldstack.ss_size); | |
122 | } | |
123 | ||
124 | typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); | |
125 | static void MaybeInstallSigaction(int signum, | |
126 | SignalHandlerType handler) { | |
127 | if (!IsDeadlySignal(signum)) | |
128 | return; | |
129 | struct sigaction sigact; | |
130 | internal_memset(&sigact, 0, sizeof(sigact)); | |
131 | sigact.sa_sigaction = (sa_sigaction_t)handler; | |
132 | sigact.sa_flags = SA_SIGINFO; | |
133 | if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK; | |
134 | CHECK_EQ(0, internal_sigaction(signum, &sigact, 0)); | |
135 | VReport(1, "Installed the sigaction for signal %d\n", signum); | |
136 | } | |
137 | ||
138 | void InstallDeadlySignalHandlers(SignalHandlerType handler) { | |
139 | // Set the alternate signal stack for the main thread. | |
140 | // This will cause SetAlternateSignalStack to be called twice, but the stack | |
141 | // will be actually set only once. | |
142 | if (common_flags()->use_sigaltstack) SetAlternateSignalStack(); | |
143 | MaybeInstallSigaction(SIGSEGV, handler); | |
144 | MaybeInstallSigaction(SIGBUS, handler); | |
145 | } | |
146 | #endif // SANITIZER_GO | |
147 | ||
148 | } // namespace __sanitizer | |
149 | ||
150 | #endif // SANITIZER_POSIX |