11f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//===-- sanitizer_posix.cc ------------------------------------------------===// 21f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// 31f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// The LLVM Compiler Infrastructure 41f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// 51f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// This file is distributed under the University of Illinois Open Source 61f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// License. See LICENSE.TXT for details. 71f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// 81f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//===----------------------------------------------------------------------===// 91f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// 101f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer 111f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// run-time libraries and implements POSIX-specific functions from 121f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// sanitizer_libc.h. 131f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//===----------------------------------------------------------------------===// 141f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#if defined(__linux__) || defined(__APPLE__) 151f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 16230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include "sanitizer_common.h" 171f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#include "sanitizer_libc.h" 18be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov#include "sanitizer_procmaps.h" 191f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 200aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany#include <errno.h> 21fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov#include <pthread.h> 221f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#include <stdarg.h> 231f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#include <stdio.h> 24fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov#include <stdlib.h> 250aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany#include <string.h> 26230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include <sys/mman.h> 27be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov#include <sys/resource.h> 28be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov#include <sys/time.h> 29230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include <sys/types.h> 30230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include <unistd.h> 311f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 321f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovnamespace __sanitizer { 331f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 34be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov// ------------- sanitizer_common.h 35be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov 36230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovint GetPid() { 37230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov return getpid(); 38230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov} 39230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov 40fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovuptr GetThreadSelf() { 41fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov return (uptr)pthread_self(); 42fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov} 43fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov 44a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonovvoid *MmapOrDie(uptr size, const char *mem_type) { 45230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov size = RoundUpTo(size, kPageSize); 46230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov void *res = internal_mmap(0, size, 47230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov PROT_READ | PROT_WRITE, 48230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov MAP_PRIVATE | MAP_ANON, -1, 0); 49230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov if (res == (void*)-1) { 500aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s: %s\n", 510aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany size, size, mem_type, strerror(errno)); 520aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany DumpProcessMap(); 53a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov CHECK("unable to mmap" && 0); 54230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov } 55230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov return res; 56230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov} 57230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov 58230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovvoid UnmapOrDie(void *addr, uptr size) { 59230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov if (!addr || !size) return; 60230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov int res = internal_munmap(addr, size); 61230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov if (res != 0) { 62a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n", 63a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov size, size, addr); 64a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov CHECK("unable to unmap" && 0); 65230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov } 66230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov} 67230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov 68f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonovvoid *MmapFixedNoReserve(uptr fixed_addr, uptr size) { 69f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov return internal_mmap((void*)fixed_addr, size, 70f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov PROT_READ | PROT_WRITE, 71f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 7284902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov -1, 0); 73f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov} 74f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov 75f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonovvoid *Mprotect(uptr fixed_addr, uptr size) { 76f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov return internal_mmap((void*)fixed_addr, size, 77f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov PROT_NONE, 78f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 7984902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov -1, 0); 80f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov} 81f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov 82a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonovvoid *MapFileToMemory(const char *file_name, uptr *buff_size) { 83a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov fd_t fd = internal_open(file_name, false); 84a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov CHECK_NE(fd, kInvalidFd); 85a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov uptr fsize = internal_filesize(fd); 86a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov CHECK_NE(fsize, (uptr)-1); 87a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov CHECK_GT(fsize, 0); 88a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov *buff_size = RoundUpTo(fsize, kPageSize); 89a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); 90a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov return (map == MAP_FAILED) ? 0 : map; 91a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov} 92a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov 93a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov 94dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonovstatic inline bool IntervalsAreSeparate(uptr start1, uptr end1, 95dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov uptr start2, uptr end2) { 96dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov CHECK(start1 <= end1); 97dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov CHECK(start2 <= end2); 98dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov return (end1 < start2) || (end2 < start1); 99dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov} 100dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov 101dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// FIXME: this is thread-unsafe, but should not cause problems most of the time. 102dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// When the shadow is mapped only a single thread usually exists (plus maybe 103dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// several worker threads on Mac, which aren't expected to map big chunks of 104dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// memory). 105dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonovbool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 106e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov MemoryMappingLayout procmaps; 107dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov uptr start, end; 108dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov while (procmaps.Next(&start, &end, 109dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov /*offset*/0, /*filename*/0, /*filename_size*/0)) { 110dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov if (!IntervalsAreSeparate(start, end, range_start, range_end)) 111dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov return false; 112dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov } 113dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov return true; 114dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov} 115dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov 116be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonovvoid DumpProcessMap() { 117e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov MemoryMappingLayout proc_maps; 118be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov uptr start, end; 119be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov const sptr kBufSize = 4095; 120b84ee029ada36949c30c57c5f701191783990574Alexey Samsonov char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__); 121be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov Report("Process memory map follows:\n"); 122be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov while (proc_maps.Next(&start, &end, /* file_offset */0, 123be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov filename, kBufSize)) { 124be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename); 125be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov } 126be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov Report("End of process memory map.\n"); 127b84ee029ada36949c30c57c5f701191783990574Alexey Samsonov UnmapOrDie(filename, kBufSize); 128be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov} 129be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov 1300969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovconst char *GetPwd() { 1310969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov return GetEnv("PWD"); 1320969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1330969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 134be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonovvoid DisableCoreDumper() { 135be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov struct rlimit nocore; 136be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov nocore.rlim_cur = 0; 137be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov nocore.rlim_max = 0; 138be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov setrlimit(RLIMIT_CORE, &nocore); 139be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov} 140be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov 141fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid SleepForSeconds(int seconds) { 142fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov sleep(seconds); 143fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov} 144fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov 1450969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovvoid SleepForMillis(int millis) { 1460969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov usleep(millis * 1000); 1470969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1480969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 149fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid Exit(int exitcode) { 150fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov _exit(exitcode); 151fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov} 152fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov 153fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid Abort() { 154fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov abort(); 155fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov} 156fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov 157fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovint Atexit(void (*function)(void)) { 158b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef SANITIZER_GO 159fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov return atexit(function); 160b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 161b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return 0; 162b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 163fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov} 164fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov 1651f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} // namespace __sanitizer 1661f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 1671f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#endif // __linux__ || __APPLE_ 168