1 //===-- sanitizer_posix.cc ------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements POSIX-specific functions from
11 //===----------------------------------------------------------------------===//
12 #if defined(__linux__) || defined(__APPLE__)
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
16 #include "sanitizer_procmaps.h"
25 #include <sys/resource.h>
27 #include <sys/types.h>
30 namespace __sanitizer
{
32 // ------------- sanitizer_common.h
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");
56 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
57 size
, size
, mem_type
, strerror(errno
));
59 CHECK("unable to mmap" && 0);
64 void UnmapOrDie(void *addr
, uptr size
) {
65 if (!addr
|| !size
) return;
66 int res
= internal_munmap(addr
, size
);
68 Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n",
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
,
81 void *Mprotect(uptr fixed_addr
, uptr size
) {
82 return internal_mmap((void*)fixed_addr
, size
,
84 MAP_PRIVATE
| MAP_ANON
| MAP_FIXED
| MAP_NORESERVE
,
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);
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
111 bool MemoryRangeIsAvailable(uptr range_start
, uptr range_end
) {
112 MemoryMappingLayout procmaps
;
114 while (procmaps
.Next(&start
, &end
,
115 /*offset*/0, /*filename*/0, /*filename_size*/0)) {
116 if (!IntervalsAreSeparate(start
, end
, range_start
, range_end
))
122 void DumpProcessMap() {
123 MemoryMappingLayout proc_maps
;
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
;
144 setrlimit(RLIMIT_CORE
, &nocore
);
147 bool StackSizeIsUnlimited() {
149 CHECK_EQ(0, getrlimit(RLIMIT_STACK
, &rlim
));
150 return (rlim
.rlim_cur
== (uptr
)-1);
153 void SetStackSizeLimitInBytes(uptr limit
) {
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
) {
165 void SleepForMillis(int millis
) {
166 usleep(millis
* 1000);
169 void Exit(int exitcode
) {
177 int Atexit(void (*function
)(void)) {
179 return atexit(function
);
185 } // namespace __sanitizer
187 #endif // __linux__ || __APPLE_