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