Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_common.h --------------------------------------*- C++ -*-===//
      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.
     12 // It declares common functions and classes that are used in both runtimes.
     13 // Implementation of some functions are provided in sanitizer_common, while
     14 // others must be defined by run-time library itself.
     15 //===----------------------------------------------------------------------===//
     16 #ifndef SANITIZER_COMMON_H
     17 #define SANITIZER_COMMON_H
     18 
     19 #include "sanitizer_internal_defs.h"
     20 #include "sanitizer_libc.h"
     21 #include "sanitizer_mutex.h"
     22 
     23 namespace __sanitizer {
     24 struct StackTrace;
     25 
     26 // Constants.
     27 const uptr kWordSize = SANITIZER_WORDSIZE / 8;
     28 const uptr kWordSizeInBits = 8 * kWordSize;
     29 
     30 #if defined(__powerpc__) || defined(__powerpc64__)
     31 const uptr kCacheLineSize = 128;
     32 #else
     33 const uptr kCacheLineSize = 64;
     34 #endif
     35 
     36 const uptr kMaxPathLength = 512;
     37 
     38 extern const char *SanitizerToolName;  // Can be changed by the tool.
     39 extern uptr SanitizerVerbosity;
     40 
     41 uptr GetPageSize();
     42 uptr GetPageSizeCached();
     43 uptr GetMmapGranularity();
     44 uptr GetMaxVirtualAddress();
     45 // Threads
     46 uptr GetTid();
     47 uptr GetThreadSelf();
     48 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
     49                                 uptr *stack_bottom);
     50 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
     51                           uptr *tls_addr, uptr *tls_size);
     52 
     53 // Memory management
     54 void *MmapOrDie(uptr size, const char *mem_type);
     55 void UnmapOrDie(void *addr, uptr size);
     56 void *MmapFixedNoReserve(uptr fixed_addr, uptr size);
     57 void *MmapFixedOrDie(uptr fixed_addr, uptr size);
     58 void *Mprotect(uptr fixed_addr, uptr size);
     59 // Map aligned chunk of address space; size and alignment are powers of two.
     60 void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
     61 // Used to check if we can map shadow memory to a fixed location.
     62 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
     63 void FlushUnneededShadowMemory(uptr addr, uptr size);
     64 
     65 // InternalScopedBuffer can be used instead of large stack arrays to
     66 // keep frame size low.
     67 // FIXME: use InternalAlloc instead of MmapOrDie once
     68 // InternalAlloc is made libc-free.
     69 template<typename T>
     70 class InternalScopedBuffer {
     71  public:
     72   explicit InternalScopedBuffer(uptr cnt) {
     73     cnt_ = cnt;
     74     ptr_ = (T*)MmapOrDie(cnt * sizeof(T), "InternalScopedBuffer");
     75   }
     76   ~InternalScopedBuffer() {
     77     UnmapOrDie(ptr_, cnt_ * sizeof(T));
     78   }
     79   T &operator[](uptr i) { return ptr_[i]; }
     80   T *data() { return ptr_; }
     81   uptr size() { return cnt_ * sizeof(T); }
     82 
     83  private:
     84   T *ptr_;
     85   uptr cnt_;
     86   // Disallow evil constructors.
     87   InternalScopedBuffer(const InternalScopedBuffer&);
     88   void operator=(const InternalScopedBuffer&);
     89 };
     90 
     91 // Simple low-level (mmap-based) allocator for internal use. Doesn't have
     92 // constructor, so all instances of LowLevelAllocator should be
     93 // linker initialized.
     94 class LowLevelAllocator {
     95  public:
     96   // Requires an external lock.
     97   void *Allocate(uptr size);
     98  private:
     99   char *allocated_end_;
    100   char *allocated_current_;
    101 };
    102 typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
    103 // Allows to register tool-specific callbacks for LowLevelAllocator.
    104 // Passing NULL removes the callback.
    105 void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
    106 
    107 // IO
    108 void RawWrite(const char *buffer);
    109 bool PrintsToTty();
    110 void Printf(const char *format, ...);
    111 void Report(const char *format, ...);
    112 void SetPrintfAndReportCallback(void (*callback)(const char *));
    113 // Can be used to prevent mixing error reports from different sanitizers.
    114 extern StaticSpinMutex CommonSanitizerReportMutex;
    115 void MaybeOpenReportFile();
    116 extern fd_t report_fd;
    117 
    118 uptr OpenFile(const char *filename, bool write);
    119 // Opens the file 'file_name" and reads up to 'max_len' bytes.
    120 // The resulting buffer is mmaped and stored in '*buff'.
    121 // The size of the mmaped region is stored in '*buff_size',
    122 // Returns the number of read bytes or 0 if file can not be opened.
    123 uptr ReadFileToBuffer(const char *file_name, char **buff,
    124                       uptr *buff_size, uptr max_len);
    125 // Maps given file to virtual memory, and returns pointer to it
    126 // (or NULL if the mapping failes). Stores the size of mmaped region
    127 // in '*buff_size'.
    128 void *MapFileToMemory(const char *file_name, uptr *buff_size);
    129 
    130 // OS
    131 void DisableCoreDumper();
    132 void DumpProcessMap();
    133 bool FileExists(const char *filename);
    134 const char *GetEnv(const char *name);
    135 bool SetEnv(const char *name, const char *value);
    136 const char *GetPwd();
    137 u32 GetUid();
    138 void ReExec();
    139 bool StackSizeIsUnlimited();
    140 void SetStackSizeLimitInBytes(uptr limit);
    141 void PrepareForSandboxing();
    142 
    143 void InitTlsSize();
    144 uptr GetTlsSize();
    145 
    146 // Other
    147 void SleepForSeconds(int seconds);
    148 void SleepForMillis(int millis);
    149 u64 NanoTime();
    150 int Atexit(void (*function)(void));
    151 void SortArray(uptr *array, uptr size);
    152 
    153 // Exit
    154 void NORETURN Abort();
    155 void NORETURN Die();
    156 void NORETURN SANITIZER_INTERFACE_ATTRIBUTE
    157 CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
    158 
    159 // Set the name of the current thread to 'name', return true on succees.
    160 // The name may be truncated to a system-dependent limit.
    161 bool SanitizerSetThreadName(const char *name);
    162 // Get the name of the current thread (no more than max_len bytes),
    163 // return true on succees. name should have space for at least max_len+1 bytes.
    164 bool SanitizerGetThreadName(char *name, int max_len);
    165 
    166 // Specific tools may override behavior of "Die" and "CheckFailed" functions
    167 // to do tool-specific job.
    168 void SetDieCallback(void (*callback)(void));
    169 typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
    170                                        u64, u64);
    171 void SetCheckFailedCallback(CheckFailedCallbackType callback);
    172 
    173 // Construct a one-line string like
    174 //  SanitizerToolName: error_type file:line function
    175 // and call __sanitizer_report_error_summary on it.
    176 void ReportErrorSummary(const char *error_type, const char *file,
    177                         int line, const char *function);
    178 
    179 // Math
    180 #if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
    181 extern "C" {
    182 unsigned char _BitScanForward(unsigned long *index, unsigned long mask);  // NOLINT
    183 unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);  // NOLINT
    184 #if defined(_WIN64)
    185 unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);  // NOLINT
    186 unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);  // NOLINT
    187 #endif
    188 }
    189 #endif
    190 
    191 INLINE uptr MostSignificantSetBitIndex(uptr x) {
    192   CHECK_NE(x, 0U);
    193   unsigned long up;  // NOLINT
    194 #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
    195   up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
    196 #elif defined(_WIN64)
    197   _BitScanReverse64(&up, x);
    198 #else
    199   _BitScanReverse(&up, x);
    200 #endif
    201   return up;
    202 }
    203 
    204 INLINE bool IsPowerOfTwo(uptr x) {
    205   return (x & (x - 1)) == 0;
    206 }
    207 
    208 INLINE uptr RoundUpToPowerOfTwo(uptr size) {
    209   CHECK(size);
    210   if (IsPowerOfTwo(size)) return size;
    211 
    212   uptr up = MostSignificantSetBitIndex(size);
    213   CHECK(size < (1ULL << (up + 1)));
    214   CHECK(size > (1ULL << up));
    215   return 1UL << (up + 1);
    216 }
    217 
    218 INLINE uptr RoundUpTo(uptr size, uptr boundary) {
    219   CHECK(IsPowerOfTwo(boundary));
    220   return (size + boundary - 1) & ~(boundary - 1);
    221 }
    222 
    223 INLINE uptr RoundDownTo(uptr x, uptr boundary) {
    224   return x & ~(boundary - 1);
    225 }
    226 
    227 INLINE bool IsAligned(uptr a, uptr alignment) {
    228   return (a & (alignment - 1)) == 0;
    229 }
    230 
    231 INLINE uptr Log2(uptr x) {
    232   CHECK(IsPowerOfTwo(x));
    233 #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
    234   return __builtin_ctzl(x);
    235 #elif defined(_WIN64)
    236   unsigned long ret;  // NOLINT
    237   _BitScanForward64(&ret, x);
    238   return ret;
    239 #else
    240   unsigned long ret;  // NOLINT
    241   _BitScanForward(&ret, x);
    242   return ret;
    243 #endif
    244 }
    245 
    246 // Don't use std::min, std::max or std::swap, to minimize dependency
    247 // on libstdc++.
    248 template<class T> T Min(T a, T b) { return a < b ? a : b; }
    249 template<class T> T Max(T a, T b) { return a > b ? a : b; }
    250 template<class T> void Swap(T& a, T& b) {
    251   T tmp = a;
    252   a = b;
    253   b = tmp;
    254 }
    255 
    256 // Char handling
    257 INLINE bool IsSpace(int c) {
    258   return (c == ' ') || (c == '\n') || (c == '\t') ||
    259          (c == '\f') || (c == '\r') || (c == '\v');
    260 }
    261 INLINE bool IsDigit(int c) {
    262   return (c >= '0') && (c <= '9');
    263 }
    264 INLINE int ToLower(int c) {
    265   return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
    266 }
    267 
    268 #if SANITIZER_WORDSIZE == 64
    269 # define FIRST_32_SECOND_64(a, b) (b)
    270 #else
    271 # define FIRST_32_SECOND_64(a, b) (a)
    272 #endif
    273 
    274 // A low-level vector based on mmap. May incur a significant memory overhead for
    275 // small vectors.
    276 // WARNING: The current implementation supports only POD types.
    277 template<typename T>
    278 class InternalMmapVector {
    279  public:
    280   explicit InternalMmapVector(uptr initial_capacity) {
    281     CHECK_GT(initial_capacity, 0);
    282     capacity_ = initial_capacity;
    283     size_ = 0;
    284     data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVector");
    285   }
    286   ~InternalMmapVector() {
    287     UnmapOrDie(data_, capacity_ * sizeof(T));
    288   }
    289   T &operator[](uptr i) {
    290     CHECK_LT(i, size_);
    291     return data_[i];
    292   }
    293   const T &operator[](uptr i) const {
    294     CHECK_LT(i, size_);
    295     return data_[i];
    296   }
    297   void push_back(const T &element) {
    298     CHECK_LE(size_, capacity_);
    299     if (size_ == capacity_) {
    300       uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
    301       Resize(new_capacity);
    302     }
    303     data_[size_++] = element;
    304   }
    305   T &back() {
    306     CHECK_GT(size_, 0);
    307     return data_[size_ - 1];
    308   }
    309   void pop_back() {
    310     CHECK_GT(size_, 0);
    311     size_--;
    312   }
    313   uptr size() const {
    314     return size_;
    315   }
    316   const T *data() const {
    317     return data_;
    318   }
    319   uptr capacity() const {
    320     return capacity_;
    321   }
    322 
    323  private:
    324   void Resize(uptr new_capacity) {
    325     CHECK_GT(new_capacity, 0);
    326     CHECK_LE(size_, new_capacity);
    327     T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T),
    328                                  "InternalMmapVector");
    329     internal_memcpy(new_data, data_, size_ * sizeof(T));
    330     T *old_data = data_;
    331     data_ = new_data;
    332     UnmapOrDie(old_data, capacity_ * sizeof(T));
    333     capacity_ = new_capacity;
    334   }
    335   // Disallow evil constructors.
    336   InternalMmapVector(const InternalMmapVector&);
    337   void operator=(const InternalMmapVector&);
    338 
    339   T *data_;
    340   uptr capacity_;
    341   uptr size_;
    342 };
    343 
    344 // HeapSort for arrays and InternalMmapVector.
    345 template<class Container, class Compare>
    346 void InternalSort(Container *v, uptr size, Compare comp) {
    347   if (size < 2)
    348     return;
    349   // Stage 1: insert elements to the heap.
    350   for (uptr i = 1; i < size; i++) {
    351     uptr j, p;
    352     for (j = i; j > 0; j = p) {
    353       p = (j - 1) / 2;
    354       if (comp((*v)[p], (*v)[j]))
    355         Swap((*v)[j], (*v)[p]);
    356       else
    357         break;
    358     }
    359   }
    360   // Stage 2: swap largest element with the last one,
    361   // and sink the new top.
    362   for (uptr i = size - 1; i > 0; i--) {
    363     Swap((*v)[0], (*v)[i]);
    364     uptr j, max_ind;
    365     for (j = 0; j < i; j = max_ind) {
    366       uptr left = 2 * j + 1;
    367       uptr right = 2 * j + 2;
    368       max_ind = j;
    369       if (left < i && comp((*v)[max_ind], (*v)[left]))
    370         max_ind = left;
    371       if (right < i && comp((*v)[max_ind], (*v)[right]))
    372         max_ind = right;
    373       if (max_ind != j)
    374         Swap((*v)[j], (*v)[max_ind]);
    375       else
    376         break;
    377     }
    378   }
    379 }
    380 
    381 }  // namespace __sanitizer
    382 
    383 #endif  // SANITIZER_COMMON_H
    384