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