sanitizer_common.h revision c519335c2d6d32acaac32c0595f08a05081567e7
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(); 44uptr GetMaxVirtualAddress(); 45// Threads 46uptr GetTid(); 47uptr GetThreadSelf(); 48void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 49 uptr *stack_bottom); 50void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 51 uptr *tls_addr, uptr *tls_size); 52 53// Memory management 54void *MmapOrDie(uptr size, const char *mem_type); 55void UnmapOrDie(void *addr, uptr size); 56void *MmapFixedNoReserve(uptr fixed_addr, uptr size); 57void *MmapFixedOrDie(uptr fixed_addr, uptr size); 58void *Mprotect(uptr fixed_addr, uptr size); 59// Map aligned chunk of address space; size and alignment are powers of two. 60void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type); 61// Used to check if we can map shadow memory to a fixed location. 62bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); 63void 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. 69template<typename T> 70class 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. 94class LowLevelAllocator { 95 public: 96 // Requires an external lock. 97 void *Allocate(uptr size); 98 private: 99 char *allocated_end_; 100 char *allocated_current_; 101}; 102typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size); 103// Allows to register tool-specific callbacks for LowLevelAllocator. 104// Passing NULL removes the callback. 105void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); 106 107// IO 108void RawWrite(const char *buffer); 109bool PrintsToTty(); 110// Caching version of PrintsToTty(). Not thread-safe. 111bool PrintsToTtyCached(); 112void Printf(const char *format, ...); 113void Report(const char *format, ...); 114void SetPrintfAndReportCallback(void (*callback)(const char *)); 115// Can be used to prevent mixing error reports from different sanitizers. 116extern StaticSpinMutex CommonSanitizerReportMutex; 117void MaybeOpenReportFile(); 118extern fd_t report_fd; 119extern bool log_to_file; 120extern char report_path_prefix[4096]; 121extern uptr report_fd_pid; 122 123uptr OpenFile(const char *filename, bool write); 124// Opens the file 'file_name" and reads up to 'max_len' bytes. 125// The resulting buffer is mmaped and stored in '*buff'. 126// The size of the mmaped region is stored in '*buff_size', 127// Returns the number of read bytes or 0 if file can not be opened. 128uptr ReadFileToBuffer(const char *file_name, char **buff, 129 uptr *buff_size, uptr max_len); 130// Maps given file to virtual memory, and returns pointer to it 131// (or NULL if the mapping failes). Stores the size of mmaped region 132// in '*buff_size'. 133void *MapFileToMemory(const char *file_name, uptr *buff_size); 134 135// Error report formatting. 136const char *StripPathPrefix(const char *filepath, 137 const char *strip_file_prefix); 138void PrintSourceLocation(const char *file, int line, int column); 139void PrintModuleAndOffset(const char *module, uptr offset); 140 141 142// OS 143void DisableCoreDumper(); 144void DumpProcessMap(); 145bool FileExists(const char *filename); 146const char *GetEnv(const char *name); 147bool SetEnv(const char *name, const char *value); 148const char *GetPwd(); 149char *FindPathToBinary(const char *name); 150u32 GetUid(); 151void ReExec(); 152bool StackSizeIsUnlimited(); 153void SetStackSizeLimitInBytes(uptr limit); 154void PrepareForSandboxing(); 155 156void InitTlsSize(); 157uptr GetTlsSize(); 158 159// Other 160void SleepForSeconds(int seconds); 161void SleepForMillis(int millis); 162u64 NanoTime(); 163int Atexit(void (*function)(void)); 164void SortArray(uptr *array, uptr size); 165 166// Exit 167void NORETURN Abort(); 168void NORETURN Die(); 169void NORETURN 170CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); 171 172// Set the name of the current thread to 'name', return true on succees. 173// The name may be truncated to a system-dependent limit. 174bool SanitizerSetThreadName(const char *name); 175// Get the name of the current thread (no more than max_len bytes), 176// return true on succees. name should have space for at least max_len+1 bytes. 177bool SanitizerGetThreadName(char *name, int max_len); 178 179// Specific tools may override behavior of "Die" and "CheckFailed" functions 180// to do tool-specific job. 181typedef void (*DieCallbackType)(void); 182void SetDieCallback(DieCallbackType); 183DieCallbackType GetDieCallback(); 184typedef void (*CheckFailedCallbackType)(const char *, int, const char *, 185 u64, u64); 186void SetCheckFailedCallback(CheckFailedCallbackType callback); 187 188// Construct a one-line string like 189// SanitizerToolName: error_type file:line function 190// and call __sanitizer_report_error_summary on it. 191void ReportErrorSummary(const char *error_type, const char *file, 192 int line, const char *function); 193 194// Math 195#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__) 196extern "C" { 197unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT 198unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT 199#if defined(_WIN64) 200unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT 201unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT 202#endif 203} 204#endif 205 206INLINE uptr MostSignificantSetBitIndex(uptr x) { 207 CHECK_NE(x, 0U); 208 unsigned long up; // NOLINT 209#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) 210 up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x); 211#elif defined(_WIN64) 212 _BitScanReverse64(&up, x); 213#else 214 _BitScanReverse(&up, x); 215#endif 216 return up; 217} 218 219INLINE bool IsPowerOfTwo(uptr x) { 220 return (x & (x - 1)) == 0; 221} 222 223INLINE uptr RoundUpToPowerOfTwo(uptr size) { 224 CHECK(size); 225 if (IsPowerOfTwo(size)) return size; 226 227 uptr up = MostSignificantSetBitIndex(size); 228 CHECK(size < (1ULL << (up + 1))); 229 CHECK(size > (1ULL << up)); 230 return 1UL << (up + 1); 231} 232 233INLINE uptr RoundUpTo(uptr size, uptr boundary) { 234 CHECK(IsPowerOfTwo(boundary)); 235 return (size + boundary - 1) & ~(boundary - 1); 236} 237 238INLINE uptr RoundDownTo(uptr x, uptr boundary) { 239 return x & ~(boundary - 1); 240} 241 242INLINE bool IsAligned(uptr a, uptr alignment) { 243 return (a & (alignment - 1)) == 0; 244} 245 246INLINE uptr Log2(uptr x) { 247 CHECK(IsPowerOfTwo(x)); 248#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) 249 return __builtin_ctzl(x); 250#elif defined(_WIN64) 251 unsigned long ret; // NOLINT 252 _BitScanForward64(&ret, x); 253 return ret; 254#else 255 unsigned long ret; // NOLINT 256 _BitScanForward(&ret, x); 257 return ret; 258#endif 259} 260 261// Don't use std::min, std::max or std::swap, to minimize dependency 262// on libstdc++. 263template<class T> T Min(T a, T b) { return a < b ? a : b; } 264template<class T> T Max(T a, T b) { return a > b ? a : b; } 265template<class T> void Swap(T& a, T& b) { 266 T tmp = a; 267 a = b; 268 b = tmp; 269} 270 271// Char handling 272INLINE bool IsSpace(int c) { 273 return (c == ' ') || (c == '\n') || (c == '\t') || 274 (c == '\f') || (c == '\r') || (c == '\v'); 275} 276INLINE bool IsDigit(int c) { 277 return (c >= '0') && (c <= '9'); 278} 279INLINE int ToLower(int c) { 280 return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c; 281} 282 283#if SANITIZER_WORDSIZE == 64 284# define FIRST_32_SECOND_64(a, b) (b) 285#else 286# define FIRST_32_SECOND_64(a, b) (a) 287#endif 288 289// A low-level vector based on mmap. May incur a significant memory overhead for 290// small vectors. 291// WARNING: The current implementation supports only POD types. 292template<typename T> 293class InternalMmapVector { 294 public: 295 explicit InternalMmapVector(uptr initial_capacity) { 296 CHECK_GT(initial_capacity, 0); 297 capacity_ = initial_capacity; 298 size_ = 0; 299 data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVector"); 300 } 301 ~InternalMmapVector() { 302 UnmapOrDie(data_, capacity_ * sizeof(T)); 303 } 304 T &operator[](uptr i) { 305 CHECK_LT(i, size_); 306 return data_[i]; 307 } 308 const T &operator[](uptr i) const { 309 CHECK_LT(i, size_); 310 return data_[i]; 311 } 312 void push_back(const T &element) { 313 CHECK_LE(size_, capacity_); 314 if (size_ == capacity_) { 315 uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1); 316 Resize(new_capacity); 317 } 318 data_[size_++] = element; 319 } 320 T &back() { 321 CHECK_GT(size_, 0); 322 return data_[size_ - 1]; 323 } 324 void pop_back() { 325 CHECK_GT(size_, 0); 326 size_--; 327 } 328 uptr size() const { 329 return size_; 330 } 331 const T *data() const { 332 return data_; 333 } 334 uptr capacity() const { 335 return capacity_; 336 } 337 338 private: 339 void Resize(uptr new_capacity) { 340 CHECK_GT(new_capacity, 0); 341 CHECK_LE(size_, new_capacity); 342 T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T), 343 "InternalMmapVector"); 344 internal_memcpy(new_data, data_, size_ * sizeof(T)); 345 T *old_data = data_; 346 data_ = new_data; 347 UnmapOrDie(old_data, capacity_ * sizeof(T)); 348 capacity_ = new_capacity; 349 } 350 // Disallow evil constructors. 351 InternalMmapVector(const InternalMmapVector&); 352 void operator=(const InternalMmapVector&); 353 354 T *data_; 355 uptr capacity_; 356 uptr size_; 357}; 358 359// HeapSort for arrays and InternalMmapVector. 360template<class Container, class Compare> 361void InternalSort(Container *v, uptr size, Compare comp) { 362 if (size < 2) 363 return; 364 // Stage 1: insert elements to the heap. 365 for (uptr i = 1; i < size; i++) { 366 uptr j, p; 367 for (j = i; j > 0; j = p) { 368 p = (j - 1) / 2; 369 if (comp((*v)[p], (*v)[j])) 370 Swap((*v)[j], (*v)[p]); 371 else 372 break; 373 } 374 } 375 // Stage 2: swap largest element with the last one, 376 // and sink the new top. 377 for (uptr i = size - 1; i > 0; i--) { 378 Swap((*v)[0], (*v)[i]); 379 uptr j, max_ind; 380 for (j = 0; j < i; j = max_ind) { 381 uptr left = 2 * j + 1; 382 uptr right = 2 * j + 2; 383 max_ind = j; 384 if (left < i && comp((*v)[max_ind], (*v)[left])) 385 max_ind = left; 386 if (right < i && comp((*v)[max_ind], (*v)[right])) 387 max_ind = right; 388 if (max_ind != j) 389 Swap((*v)[j], (*v)[max_ind]); 390 else 391 break; 392 } 393 } 394} 395 396template<class Container, class Value, class Compare> 397uptr InternalBinarySearch(const Container &v, uptr first, uptr last, 398 const Value &val, Compare comp) { 399 uptr not_found = last + 1; 400 while (last >= first) { 401 uptr mid = (first + last) / 2; 402 if (comp(v[mid], val)) 403 first = mid + 1; 404 else if (comp(val, v[mid])) 405 last = mid - 1; 406 else 407 return mid; 408 } 409 return not_found; 410} 411 412// Represents a binary loaded into virtual memory (e.g. this can be an 413// executable or a shared object). 414class LoadedModule { 415 public: 416 LoadedModule(const char *module_name, uptr base_address); 417 void addAddressRange(uptr beg, uptr end); 418 bool containsAddress(uptr address) const; 419 420 const char *full_name() const { return full_name_; } 421 uptr base_address() const { return base_address_; } 422 423 private: 424 struct AddressRange { 425 uptr beg; 426 uptr end; 427 }; 428 char *full_name_; 429 uptr base_address_; 430 static const uptr kMaxNumberOfAddressRanges = 6; 431 AddressRange ranges_[kMaxNumberOfAddressRanges]; 432 uptr n_ranges_; 433}; 434 435// OS-dependent function that fills array with descriptions of at most 436// "max_modules" currently loaded modules. Returns the number of 437// initialized modules. If filter is nonzero, ignores modules for which 438// filter(full_name) is false. 439typedef bool (*string_predicate_t)(const char *); 440uptr GetListOfModules(LoadedModule *modules, uptr max_modules, 441 string_predicate_t filter); 442 443#if SANITIZER_POSIX 444const uptr kPthreadDestructorIterations = 4; 445#else 446// Unused on Windows. 447const uptr kPthreadDestructorIterations = 0; 448#endif 449 450// Callback type for iterating over a set of memory ranges. 451typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg); 452} // namespace __sanitizer 453 454#endif // SANITIZER_COMMON_H 455