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