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