[Sanitizer] extend internal libc with stat/fstat/lstat functions
[blocksruntime.git] / lib / sanitizer_common / sanitizer_posix.cc
blob05ed6046632e1ef749bdd1cff2efe0f9a00b47a0
1 //===-- sanitizer_posix.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 POSIX-specific functions from
12 // sanitizer_libc.h.
13 //===----------------------------------------------------------------------===//
14 #if defined(__linux__) || defined(__APPLE__)
16 #include "sanitizer_common.h"
17 #include "sanitizer_libc.h"
18 #include "sanitizer_procmaps.h"
20 #include <errno.h>
21 #include <pthread.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/mman.h>
27 #include <sys/resource.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <unistd.h>
32 namespace __sanitizer {
34 // ------------- sanitizer_common.h
35 uptr GetPageSize() {
36 return sysconf(_SC_PAGESIZE);
39 uptr GetMmapGranularity() {
40 return GetPageSize();
43 int GetPid() {
44 return getpid();
47 uptr GetThreadSelf() {
48 return (uptr)pthread_self();
51 void *MmapOrDie(uptr size, const char *mem_type) {
52 size = RoundUpTo(size, GetPageSizeCached());
53 void *res = internal_mmap(0, size,
54 PROT_READ | PROT_WRITE,
55 MAP_PRIVATE | MAP_ANON, -1, 0);
56 if (res == (void*)-1) {
57 static int recursion_count;
58 if (recursion_count) {
59 // The Report() and CHECK calls below may call mmap recursively and fail.
60 // If we went into recursion, just die.
61 RawWrite("ERROR: Failed to mmap\n");
62 Die();
64 recursion_count++;
65 Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
66 SanitizerToolName, size, size, mem_type, strerror(errno));
67 DumpProcessMap();
68 CHECK("unable to mmap" && 0);
70 return res;
73 void UnmapOrDie(void *addr, uptr size) {
74 if (!addr || !size) return;
75 int res = internal_munmap(addr, size);
76 if (res != 0) {
77 Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
78 SanitizerToolName, size, size, addr);
79 CHECK("unable to unmap" && 0);
83 void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
84 uptr PageSize = GetPageSizeCached();
85 void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
86 RoundUpTo(size, PageSize),
87 PROT_READ | PROT_WRITE,
88 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
89 -1, 0);
90 if (p == (void*)-1)
91 Report("ERROR: "
92 "%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
93 SanitizerToolName, size, size, fixed_addr, errno);
94 return p;
97 void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
98 uptr PageSize = GetPageSizeCached();
99 void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
100 RoundUpTo(size, PageSize),
101 PROT_READ | PROT_WRITE,
102 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
103 -1, 0);
104 if (p == (void*)-1) {
105 Report("ERROR:"
106 " %s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
107 SanitizerToolName, size, size, fixed_addr, errno);
108 CHECK("unable to mmap" && 0);
110 return p;
113 void *Mprotect(uptr fixed_addr, uptr size) {
114 return internal_mmap((void*)fixed_addr, size,
115 PROT_NONE,
116 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
117 -1, 0);
120 void FlushUnneededShadowMemory(uptr addr, uptr size) {
121 madvise((void*)addr, size, MADV_DONTNEED);
124 void *MapFileToMemory(const char *file_name, uptr *buff_size) {
125 fd_t fd = OpenFile(file_name, false);
126 CHECK_NE(fd, kInvalidFd);
127 uptr fsize = internal_filesize(fd);
128 CHECK_NE(fsize, (uptr)-1);
129 CHECK_GT(fsize, 0);
130 *buff_size = RoundUpTo(fsize, GetPageSizeCached());
131 void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0);
132 return (map == MAP_FAILED) ? 0 : map;
136 static inline bool IntervalsAreSeparate(uptr start1, uptr end1,
137 uptr start2, uptr end2) {
138 CHECK(start1 <= end1);
139 CHECK(start2 <= end2);
140 return (end1 < start2) || (end2 < start1);
143 // FIXME: this is thread-unsafe, but should not cause problems most of the time.
144 // When the shadow is mapped only a single thread usually exists (plus maybe
145 // several worker threads on Mac, which aren't expected to map big chunks of
146 // memory).
147 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
148 MemoryMappingLayout procmaps;
149 uptr start, end;
150 while (procmaps.Next(&start, &end,
151 /*offset*/0, /*filename*/0, /*filename_size*/0)) {
152 if (!IntervalsAreSeparate(start, end, range_start, range_end))
153 return false;
155 return true;
158 void DumpProcessMap() {
159 MemoryMappingLayout proc_maps;
160 uptr start, end;
161 const sptr kBufSize = 4095;
162 char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__);
163 Report("Process memory map follows:\n");
164 while (proc_maps.Next(&start, &end, /* file_offset */0,
165 filename, kBufSize)) {
166 Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename);
168 Report("End of process memory map.\n");
169 UnmapOrDie(filename, kBufSize);
172 const char *GetPwd() {
173 return GetEnv("PWD");
176 void DisableCoreDumper() {
177 struct rlimit nocore;
178 nocore.rlim_cur = 0;
179 nocore.rlim_max = 0;
180 setrlimit(RLIMIT_CORE, &nocore);
183 bool StackSizeIsUnlimited() {
184 struct rlimit rlim;
185 CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim));
186 return (rlim.rlim_cur == (uptr)-1);
189 void SetStackSizeLimitInBytes(uptr limit) {
190 struct rlimit rlim;
191 rlim.rlim_cur = limit;
192 rlim.rlim_max = limit;
193 if (setrlimit(RLIMIT_STACK, &rlim)) {
194 Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
195 Die();
197 CHECK(!StackSizeIsUnlimited());
200 void SleepForSeconds(int seconds) {
201 sleep(seconds);
204 void SleepForMillis(int millis) {
205 usleep(millis * 1000);
208 void Exit(int exitcode) {
209 _exit(exitcode);
212 void Abort() {
213 abort();
216 int Atexit(void (*function)(void)) {
217 #ifndef SANITIZER_GO
218 return atexit(function);
219 #else
220 return 0;
221 #endif
224 int internal_isatty(fd_t fd) {
225 return isatty(fd);
228 } // namespace __sanitizer
230 #endif // __linux__ || __APPLE_