1 //===-- sanitizer_posix.cc ------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries and implements POSIX-specific functions from
13 //===----------------------------------------------------------------------===//
14 #if defined(__linux__) || defined(__APPLE__)
16 #include "sanitizer_common.h"
17 #include "sanitizer_libc.h"
18 #include "sanitizer_procmaps.h"
27 #include <sys/resource.h>
29 #include <sys/types.h>
32 namespace __sanitizer
{
34 // ------------- sanitizer_common.h
36 return sysconf(_SC_PAGESIZE
);
39 uptr
GetMmapGranularity() {
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");
65 Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
66 SanitizerToolName
, size
, size
, mem_type
, strerror(errno
));
68 CHECK("unable to mmap" && 0);
73 void UnmapOrDie(void *addr
, uptr size
) {
74 if (!addr
|| !size
) return;
75 int res
= internal_munmap(addr
, size
);
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
,
92 "%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
93 SanitizerToolName
, size
, size
, fixed_addr
, errno
);
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
,
104 if (p
== (void*)-1) {
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);
113 void *Mprotect(uptr fixed_addr
, uptr size
) {
114 return internal_mmap((void*)fixed_addr
, size
,
116 MAP_PRIVATE
| MAP_ANON
| MAP_FIXED
| MAP_NORESERVE
,
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);
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
147 bool MemoryRangeIsAvailable(uptr range_start
, uptr range_end
) {
148 MemoryMappingLayout procmaps
;
150 while (procmaps
.Next(&start
, &end
,
151 /*offset*/0, /*filename*/0, /*filename_size*/0)) {
152 if (!IntervalsAreSeparate(start
, end
, range_start
, range_end
))
158 void DumpProcessMap() {
159 MemoryMappingLayout proc_maps
;
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
;
180 setrlimit(RLIMIT_CORE
, &nocore
);
183 bool StackSizeIsUnlimited() {
185 CHECK_EQ(0, getrlimit(RLIMIT_STACK
, &rlim
));
186 return (rlim
.rlim_cur
== (uptr
)-1);
189 void SetStackSizeLimitInBytes(uptr limit
) {
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
);
197 CHECK(!StackSizeIsUnlimited());
200 void SleepForSeconds(int seconds
) {
204 void SleepForMillis(int millis
) {
205 usleep(millis
* 1000);
208 void Exit(int exitcode
) {
216 int Atexit(void (*function
)(void)) {
218 return atexit(function
);
224 int internal_isatty(fd_t fd
) {
228 } // namespace __sanitizer
230 #endif // __linux__ || __APPLE_