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