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__) 15 16 #include "sanitizer_common.h" 17 #include "sanitizer_libc.h" 18 #include "sanitizer_procmaps.h" 19 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> 31 32 namespace __sanitizer { 33 34 // ------------- sanitizer_common.h 35 uptr GetPageSize() { 36 return sysconf(_SC_PAGESIZE); 37 } 38 39 uptr GetMmapGranularity() { 40 return GetPageSize(); 41 } 42 43 int GetPid() { 44 return getpid(); 45 } 46 47 u32 GetUid() { 48 return getuid(); 49 } 50 51 uptr GetThreadSelf() { 52 return (uptr)pthread_self(); 53 } 54 55 void *MmapOrDie(uptr size, const char *mem_type) { 56 size = RoundUpTo(size, GetPageSizeCached()); 57 void *res = internal_mmap(0, size, 58 PROT_READ | PROT_WRITE, 59 MAP_PRIVATE | MAP_ANON, -1, 0); 60 if (res == (void*)-1) { 61 static int recursion_count; 62 if (recursion_count) { 63 // The Report() and CHECK calls below may call mmap recursively and fail. 64 // If we went into recursion, just die. 65 RawWrite("ERROR: Failed to mmap\n"); 66 Die(); 67 } 68 recursion_count++; 69 Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %d\n", 70 SanitizerToolName, size, size, mem_type, errno); 71 DumpProcessMap(); 72 CHECK("unable to mmap" && 0); 73 } 74 return res; 75 } 76 77 void UnmapOrDie(void *addr, uptr size) { 78 if (!addr || !size) return; 79 int res = internal_munmap(addr, size); 80 if (res != 0) { 81 Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n", 82 SanitizerToolName, size, size, addr); 83 CHECK("unable to unmap" && 0); 84 } 85 } 86 87 void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { 88 uptr PageSize = GetPageSizeCached(); 89 void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)), 90 RoundUpTo(size, PageSize), 91 PROT_READ | PROT_WRITE, 92 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 93 -1, 0); 94 if (p == (void*)-1) 95 Report("ERROR: " 96 "%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n", 97 SanitizerToolName, size, size, fixed_addr, errno); 98 return p; 99 } 100 101 void *MmapFixedOrDie(uptr fixed_addr, uptr size) { 102 uptr PageSize = GetPageSizeCached(); 103 void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)), 104 RoundUpTo(size, PageSize), 105 PROT_READ | PROT_WRITE, 106 MAP_PRIVATE | MAP_ANON | MAP_FIXED, 107 -1, 0); 108 if (p == (void*)-1) { 109 Report("ERROR:" 110 " %s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n", 111 SanitizerToolName, size, size, fixed_addr, errno); 112 CHECK("unable to mmap" && 0); 113 } 114 return p; 115 } 116 117 void *Mprotect(uptr fixed_addr, uptr size) { 118 return internal_mmap((void*)fixed_addr, size, 119 PROT_NONE, 120 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 121 -1, 0); 122 } 123 124 void FlushUnneededShadowMemory(uptr addr, uptr size) { 125 madvise((void*)addr, size, MADV_DONTNEED); 126 } 127 128 void *MapFileToMemory(const char *file_name, uptr *buff_size) { 129 fd_t fd = OpenFile(file_name, false); 130 CHECK_NE(fd, kInvalidFd); 131 uptr fsize = internal_filesize(fd); 132 CHECK_NE(fsize, (uptr)-1); 133 CHECK_GT(fsize, 0); 134 *buff_size = RoundUpTo(fsize, GetPageSizeCached()); 135 void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); 136 return (map == MAP_FAILED) ? 0 : map; 137 } 138 139 140 static inline bool IntervalsAreSeparate(uptr start1, uptr end1, 141 uptr start2, uptr end2) { 142 CHECK(start1 <= end1); 143 CHECK(start2 <= end2); 144 return (end1 < start2) || (end2 < start1); 145 } 146 147 // FIXME: this is thread-unsafe, but should not cause problems most of the time. 148 // When the shadow is mapped only a single thread usually exists (plus maybe 149 // several worker threads on Mac, which aren't expected to map big chunks of 150 // memory). 151 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 152 MemoryMappingLayout procmaps; 153 uptr start, end; 154 while (procmaps.Next(&start, &end, 155 /*offset*/0, /*filename*/0, /*filename_size*/0, 156 /*protection*/0)) { 157 if (!IntervalsAreSeparate(start, end, range_start, range_end)) 158 return false; 159 } 160 return true; 161 } 162 163 void DumpProcessMap() { 164 MemoryMappingLayout proc_maps; 165 uptr start, end; 166 const sptr kBufSize = 4095; 167 char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__); 168 Report("Process memory map follows:\n"); 169 while (proc_maps.Next(&start, &end, /* file_offset */0, 170 filename, kBufSize, /* protection */0)) { 171 Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename); 172 } 173 Report("End of process memory map.\n"); 174 UnmapOrDie(filename, kBufSize); 175 } 176 177 const char *GetPwd() { 178 return GetEnv("PWD"); 179 } 180 181 void DisableCoreDumper() { 182 struct rlimit nocore; 183 nocore.rlim_cur = 0; 184 nocore.rlim_max = 0; 185 setrlimit(RLIMIT_CORE, &nocore); 186 } 187 188 bool StackSizeIsUnlimited() { 189 struct rlimit rlim; 190 CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim)); 191 return (rlim.rlim_cur == (uptr)-1); 192 } 193 194 void SetStackSizeLimitInBytes(uptr limit) { 195 struct rlimit rlim; 196 rlim.rlim_cur = limit; 197 rlim.rlim_max = limit; 198 if (setrlimit(RLIMIT_STACK, &rlim)) { 199 Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno); 200 Die(); 201 } 202 CHECK(!StackSizeIsUnlimited()); 203 } 204 205 void SleepForSeconds(int seconds) { 206 sleep(seconds); 207 } 208 209 void SleepForMillis(int millis) { 210 usleep(millis * 1000); 211 } 212 213 void Abort() { 214 abort(); 215 } 216 217 int Atexit(void (*function)(void)) { 218 #ifndef SANITIZER_GO 219 return atexit(function); 220 #else 221 return 0; 222 #endif 223 } 224 225 int internal_isatty(fd_t fd) { 226 return isatty(fd); 227 } 228 229 } // namespace __sanitizer 230 231 #endif // __linux__ || __APPLE_ 232