sanitizer_posix.cc revision 7dccf3f92a867f917ad19f9a6b37bcf93e64b35b
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 <syscall.h> 31#include <unistd.h> 32 33namespace __sanitizer { 34 35// ------------- sanitizer_common.h 36 37int GetPid() { 38 return getpid(); 39} 40 41int GetTid() { 42 return syscall(__NR_gettid); 43} 44 45uptr GetThreadSelf() { 46 return (uptr)pthread_self(); 47} 48 49void *MmapOrDie(uptr size, const char *mem_type) { 50 size = RoundUpTo(size, kPageSize); 51 void *res = internal_mmap(0, size, 52 PROT_READ | PROT_WRITE, 53 MAP_PRIVATE | MAP_ANON, -1, 0); 54 if (res == (void*)-1) { 55 Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s: %s\n", 56 size, size, mem_type, strerror(errno)); 57 DumpProcessMap(); 58 CHECK("unable to mmap" && 0); 59 } 60 return res; 61} 62 63void UnmapOrDie(void *addr, uptr size) { 64 if (!addr || !size) return; 65 int res = internal_munmap(addr, size); 66 if (res != 0) { 67 Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n", 68 size, size, addr); 69 CHECK("unable to unmap" && 0); 70 } 71} 72 73void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { 74 return internal_mmap((void*)fixed_addr, size, 75 PROT_READ | PROT_WRITE, 76 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 77 -1, 0); 78} 79 80void *Mprotect(uptr fixed_addr, uptr size) { 81 return internal_mmap((void*)fixed_addr, size, 82 PROT_NONE, 83 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 84 -1, 0); 85} 86 87void *MapFileToMemory(const char *file_name, uptr *buff_size) { 88 fd_t fd = internal_open(file_name, false); 89 CHECK_NE(fd, kInvalidFd); 90 uptr fsize = internal_filesize(fd); 91 CHECK_NE(fsize, (uptr)-1); 92 CHECK_GT(fsize, 0); 93 *buff_size = RoundUpTo(fsize, kPageSize); 94 void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); 95 return (map == MAP_FAILED) ? 0 : map; 96} 97 98 99static inline bool IntervalsAreSeparate(uptr start1, uptr end1, 100 uptr start2, uptr end2) { 101 CHECK(start1 <= end1); 102 CHECK(start2 <= end2); 103 return (end1 < start2) || (end2 < start1); 104} 105 106// FIXME: this is thread-unsafe, but should not cause problems most of the time. 107// When the shadow is mapped only a single thread usually exists (plus maybe 108// several worker threads on Mac, which aren't expected to map big chunks of 109// memory). 110bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 111 MemoryMappingLayout procmaps; 112 uptr start, end; 113 while (procmaps.Next(&start, &end, 114 /*offset*/0, /*filename*/0, /*filename_size*/0)) { 115 if (!IntervalsAreSeparate(start, end, range_start, range_end)) 116 return false; 117 } 118 return true; 119} 120 121void DumpProcessMap() { 122 MemoryMappingLayout proc_maps; 123 uptr start, end; 124 const sptr kBufSize = 4095; 125 char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__); 126 Report("Process memory map follows:\n"); 127 while (proc_maps.Next(&start, &end, /* file_offset */0, 128 filename, kBufSize)) { 129 Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename); 130 } 131 Report("End of process memory map.\n"); 132 UnmapOrDie(filename, kBufSize); 133} 134 135const char *GetPwd() { 136 return GetEnv("PWD"); 137} 138 139void DisableCoreDumper() { 140 struct rlimit nocore; 141 nocore.rlim_cur = 0; 142 nocore.rlim_max = 0; 143 setrlimit(RLIMIT_CORE, &nocore); 144} 145 146bool StackSizeIsUnlimited() { 147 struct rlimit rlim; 148 CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim)); 149 return (rlim.rlim_cur == (uptr)-1); 150} 151 152void SetStackSizeLimitInBytes(uptr limit) { 153 struct rlimit rlim; 154 rlim.rlim_cur = limit; 155 rlim.rlim_max = limit; 156 CHECK_EQ(0, setrlimit(RLIMIT_STACK, &rlim)); 157 CHECK(!StackSizeIsUnlimited()); 158} 159 160void SleepForSeconds(int seconds) { 161 sleep(seconds); 162} 163 164void SleepForMillis(int millis) { 165 usleep(millis * 1000); 166} 167 168void Exit(int exitcode) { 169 _exit(exitcode); 170} 171 172void Abort() { 173 abort(); 174} 175 176int Atexit(void (*function)(void)) { 177#ifndef SANITIZER_GO 178 return atexit(function); 179#else 180 return 0; 181#endif 182} 183 184} // namespace __sanitizer 185 186#endif // __linux__ || __APPLE_ 187