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