sanitizer_posix_libcdep.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
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
33namespace __sanitizer {
34
35u32 GetUid() {
36  return getuid();
37}
38
39uptr GetThreadSelf() {
40  return (uptr)pthread_self();
41}
42
43void FlushUnneededShadowMemory(uptr addr, uptr size) {
44  madvise((void*)addr, size, MADV_DONTNEED);
45}
46
47void DisableCoreDumper() {
48  struct rlimit nocore;
49  nocore.rlim_cur = 0;
50  nocore.rlim_max = 0;
51  setrlimit(RLIMIT_CORE, &nocore);
52}
53
54bool StackSizeIsUnlimited() {
55  struct rlimit rlim;
56  CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim));
57  return ((uptr)rlim.rlim_cur == (uptr)-1);
58}
59
60void 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
71void SleepForSeconds(int seconds) {
72  sleep(seconds);
73}
74
75void SleepForMillis(int millis) {
76  usleep(millis * 1000);
77}
78
79void Abort() {
80  abort();
81}
82
83int Atexit(void (*function)(void)) {
84#ifndef SANITIZER_GO
85  return atexit(function);
86#else
87  return 0;
88#endif
89}
90
91int 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.
97static const uptr kAltStackSize = SIGSTKSZ * 4;  // SIGSTKSZ is not enough.
98
99void 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
115void 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
124typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
125static 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
138void 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
151