sanitizer_posix.cc revision 859778a4e2dffa4024fa3e13b105fd62eca44b1c
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 32namespace __sanitizer { 33 34// ------------- sanitizer_common.h 35uptr GetPageSize() { 36 return sysconf(_SC_PAGESIZE); 37} 38 39uptr GetMmapGranularity() { 40 return GetPageSize(); 41} 42 43int GetPid() { 44 return getpid(); 45} 46 47uptr GetThreadSelf() { 48 return (uptr)pthread_self(); 49} 50 51void *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(); 63 } 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); 69 } 70 return res; 71} 72 73void 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); 80 } 81} 82 83void *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; 95} 96 97void *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); 109 } 110 return p; 111} 112 113void *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); 118} 119 120void FlushUnneededShadowMemory(uptr addr, uptr size) { 121 madvise((void*)addr, size, MADV_DONTNEED); 122} 123 124void *MapFileToMemory(const char *file_name, uptr *buff_size) { 125 fd_t fd = internal_open(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; 133} 134 135 136static 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); 141} 142 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). 147bool 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; 154 } 155 return true; 156} 157 158void 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); 167 } 168 Report("End of process memory map.\n"); 169 UnmapOrDie(filename, kBufSize); 170} 171 172const char *GetPwd() { 173 return GetEnv("PWD"); 174} 175 176void DisableCoreDumper() { 177 struct rlimit nocore; 178 nocore.rlim_cur = 0; 179 nocore.rlim_max = 0; 180 setrlimit(RLIMIT_CORE, &nocore); 181} 182 183bool StackSizeIsUnlimited() { 184 struct rlimit rlim; 185 CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim)); 186 return (rlim.rlim_cur == (uptr)-1); 187} 188 189void 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(); 196 } 197 CHECK(!StackSizeIsUnlimited()); 198} 199 200void SleepForSeconds(int seconds) { 201 sleep(seconds); 202} 203 204void SleepForMillis(int millis) { 205 usleep(millis * 1000); 206} 207 208void Exit(int exitcode) { 209 _exit(exitcode); 210} 211 212void Abort() { 213 abort(); 214} 215 216int Atexit(void (*function)(void)) { 217#ifndef SANITIZER_GO 218 return atexit(function); 219#else 220 return 0; 221#endif 222} 223 224int internal_isatty(fd_t fd) { 225 return isatty(fd); 226} 227 228} // namespace __sanitizer 229 230#endif // __linux__ || __APPLE_ 231