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