* configure.ac: Change target-libasan to target-libsanitizer.
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_posix.cc
blob8f71cfc049dd7034a621f7213e2f7a401f600d7f
1 //===-- sanitizer_posix.cc ------------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements POSIX-specific functions from
10 // sanitizer_libc.h.
11 //===----------------------------------------------------------------------===//
12 #if defined(__linux__) || defined(__APPLE__)
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
16 #include "sanitizer_procmaps.h"
18 #include <errno.h>
19 #include <pthread.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/mman.h>
25 #include <sys/resource.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <unistd.h>
30 namespace __sanitizer {
32 // ------------- sanitizer_common.h
34 int GetPid() {
35 return getpid();
38 uptr GetThreadSelf() {
39 return (uptr)pthread_self();
42 void *MmapOrDie(uptr size, const char *mem_type) {
43 size = RoundUpTo(size, kPageSize);
44 void *res = internal_mmap(0, size,
45 PROT_READ | PROT_WRITE,
46 MAP_PRIVATE | MAP_ANON, -1, 0);
47 if (res == (void*)-1) {
48 static int recursion_count;
49 if (recursion_count) {
50 // The Report() and CHECK calls below may call mmap recursively and fail.
51 // If we went into recursion, just die.
52 RawWrite("AddressSanitizer is unable to mmap\n");
53 Die();
55 recursion_count++;
56 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
57 size, size, mem_type, strerror(errno));
58 DumpProcessMap();
59 CHECK("unable to mmap" && 0);
61 return res;
64 void UnmapOrDie(void *addr, uptr size) {
65 if (!addr || !size) return;
66 int res = internal_munmap(addr, size);
67 if (res != 0) {
68 Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n",
69 size, size, addr);
70 CHECK("unable to unmap" && 0);
74 void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
75 return internal_mmap((void*)fixed_addr, size,
76 PROT_READ | PROT_WRITE,
77 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
78 -1, 0);
81 void *Mprotect(uptr fixed_addr, uptr size) {
82 return internal_mmap((void*)fixed_addr, size,
83 PROT_NONE,
84 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
85 -1, 0);
88 void *MapFileToMemory(const char *file_name, uptr *buff_size) {
89 fd_t fd = internal_open(file_name, false);
90 CHECK_NE(fd, kInvalidFd);
91 uptr fsize = internal_filesize(fd);
92 CHECK_NE(fsize, (uptr)-1);
93 CHECK_GT(fsize, 0);
94 *buff_size = RoundUpTo(fsize, kPageSize);
95 void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0);
96 return (map == MAP_FAILED) ? 0 : map;
100 static inline bool IntervalsAreSeparate(uptr start1, uptr end1,
101 uptr start2, uptr end2) {
102 CHECK(start1 <= end1);
103 CHECK(start2 <= end2);
104 return (end1 < start2) || (end2 < start1);
107 // FIXME: this is thread-unsafe, but should not cause problems most of the time.
108 // When the shadow is mapped only a single thread usually exists (plus maybe
109 // several worker threads on Mac, which aren't expected to map big chunks of
110 // memory).
111 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
112 MemoryMappingLayout procmaps;
113 uptr start, end;
114 while (procmaps.Next(&start, &end,
115 /*offset*/0, /*filename*/0, /*filename_size*/0)) {
116 if (!IntervalsAreSeparate(start, end, range_start, range_end))
117 return false;
119 return true;
122 void DumpProcessMap() {
123 MemoryMappingLayout proc_maps;
124 uptr start, end;
125 const sptr kBufSize = 4095;
126 char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__);
127 Report("Process memory map follows:\n");
128 while (proc_maps.Next(&start, &end, /* file_offset */0,
129 filename, kBufSize)) {
130 Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename);
132 Report("End of process memory map.\n");
133 UnmapOrDie(filename, kBufSize);
136 const char *GetPwd() {
137 return GetEnv("PWD");
140 void DisableCoreDumper() {
141 struct rlimit nocore;
142 nocore.rlim_cur = 0;
143 nocore.rlim_max = 0;
144 setrlimit(RLIMIT_CORE, &nocore);
147 bool StackSizeIsUnlimited() {
148 struct rlimit rlim;
149 CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim));
150 return (rlim.rlim_cur == (uptr)-1);
153 void SetStackSizeLimitInBytes(uptr limit) {
154 struct rlimit rlim;
155 rlim.rlim_cur = limit;
156 rlim.rlim_max = limit;
157 CHECK_EQ(0, setrlimit(RLIMIT_STACK, &rlim));
158 CHECK(!StackSizeIsUnlimited());
161 void SleepForSeconds(int seconds) {
162 sleep(seconds);
165 void SleepForMillis(int millis) {
166 usleep(millis * 1000);
169 void Exit(int exitcode) {
170 _exit(exitcode);
173 void Abort() {
174 abort();
177 int Atexit(void (*function)(void)) {
178 #ifndef SANITIZER_GO
179 return atexit(function);
180 #else
181 return 0;
182 #endif
185 } // namespace __sanitizer
187 #endif // __linux__ || __APPLE_