sanitizer_common.h revision ff7c14f911463db91b574533f62eb847a2e08b1c
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 36extern const char *SanitizerToolName; // Can be changed by the tool. 37extern uptr SanitizerVerbosity; 38 39uptr GetPageSize(); 40uptr GetPageSizeCached(); 41uptr GetMmapGranularity(); 42// Threads 43int GetPid(); 44uptr GetTid(); 45uptr GetThreadSelf(); 46void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 47 uptr *stack_bottom); 48 49// Memory management 50void *MmapOrDie(uptr size, const char *mem_type); 51void UnmapOrDie(void *addr, uptr size); 52void *MmapFixedNoReserve(uptr fixed_addr, uptr size); 53void *MmapFixedOrDie(uptr fixed_addr, uptr size); 54void *Mprotect(uptr fixed_addr, uptr size); 55// Map aligned chunk of address space; size and alignment are powers of two. 56void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type); 57// Used to check if we can map shadow memory to a fixed location. 58bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); 59void FlushUnneededShadowMemory(uptr addr, uptr size); 60 61// Internal allocator 62void *InternalAlloc(uptr size); 63void InternalFree(void *p); 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(); 110void Printf(const char *format, ...); 111void Report(const char *format, ...); 112void SetPrintfAndReportCallback(void (*callback)(const char *)); 113// Can be used to prevent mixing error reports from different sanitizers. 114extern StaticSpinMutex CommonSanitizerReportMutex; 115 116fd_t OpenFile(const char *filename, bool write); 117// Opens the file 'file_name" and reads up to 'max_len' bytes. 118// The resulting buffer is mmaped and stored in '*buff'. 119// The size of the mmaped region is stored in '*buff_size', 120// Returns the number of read bytes or 0 if file can not be opened. 121uptr ReadFileToBuffer(const char *file_name, char **buff, 122 uptr *buff_size, uptr max_len); 123// Maps given file to virtual memory, and returns pointer to it 124// (or NULL if the mapping failes). Stores the size of mmaped region 125// in '*buff_size'. 126void *MapFileToMemory(const char *file_name, uptr *buff_size); 127 128// OS 129void DisableCoreDumper(); 130void DumpProcessMap(); 131bool FileExists(const char *filename); 132const char *GetEnv(const char *name); 133bool SetEnv(const char *name, const char *value); 134const char *GetPwd(); 135u32 GetUid(); 136void ReExec(); 137bool StackSizeIsUnlimited(); 138void SetStackSizeLimitInBytes(uptr limit); 139void PrepareForSandboxing(); 140 141void InitTlsSize(); 142uptr GetTlsSize(); 143 144// Other 145void SleepForSeconds(int seconds); 146void SleepForMillis(int millis); 147u64 NanoTime(); 148int Atexit(void (*function)(void)); 149void SortArray(uptr *array, uptr size); 150 151// Exit 152void NORETURN Abort(); 153void NORETURN Die(); 154void NORETURN SANITIZER_INTERFACE_ATTRIBUTE 155CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); 156 157// Set the name of the current thread to 'name', return true on succees. 158// The name may be truncated to a system-dependent limit. 159bool SanitizerSetThreadName(const char *name); 160// Get the name of the current thread (no more than max_len bytes), 161// return true on succees. name should have space for at least max_len+1 bytes. 162bool SanitizerGetThreadName(char *name, int max_len); 163 164// Specific tools may override behavior of "Die" and "CheckFailed" functions 165// to do tool-specific job. 166void SetDieCallback(void (*callback)(void)); 167typedef void (*CheckFailedCallbackType)(const char *, int, const char *, 168 u64, u64); 169void SetCheckFailedCallback(CheckFailedCallbackType callback); 170 171// Construct a one-line string like 172// SanitizerToolName: error_type file:line function 173// and call __sanitizer_report_error_summary on it. 174void ReportErrorSummary(const char *error_type, const char *file, 175 int line, const char *function); 176 177// Math 178#if SANITIZER_WINDOWS && !defined(__clang__) 179extern "C" { 180unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT 181unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT 182#if defined(_WIN64) 183unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT 184unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT 185#endif 186} 187#endif 188 189INLINE uptr MostSignificantSetBitIndex(uptr x) { 190 CHECK_NE(x, 0U); 191 unsigned long up; // NOLINT 192#if !SANITIZER_WINDOWS || defined(__clang__) 193 up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x); 194#elif defined(_WIN64) 195 _BitScanReverse64(&up, x); 196#else 197 _BitScanReverse(&up, x); 198#endif 199 return up; 200} 201 202INLINE bool IsPowerOfTwo(uptr x) { 203 return (x & (x - 1)) == 0; 204} 205 206INLINE uptr RoundUpToPowerOfTwo(uptr size) { 207 CHECK(size); 208 if (IsPowerOfTwo(size)) return size; 209 210 uptr up = MostSignificantSetBitIndex(size); 211 CHECK(size < (1ULL << (up + 1))); 212 CHECK(size > (1ULL << up)); 213 return 1UL << (up + 1); 214} 215 216INLINE uptr RoundUpTo(uptr size, uptr boundary) { 217 CHECK(IsPowerOfTwo(boundary)); 218 return (size + boundary - 1) & ~(boundary - 1); 219} 220 221INLINE uptr RoundDownTo(uptr x, uptr boundary) { 222 return x & ~(boundary - 1); 223} 224 225INLINE bool IsAligned(uptr a, uptr alignment) { 226 return (a & (alignment - 1)) == 0; 227} 228 229INLINE uptr Log2(uptr x) { 230 CHECK(IsPowerOfTwo(x)); 231#if !SANITIZER_WINDOWS || defined(__clang__) 232 return __builtin_ctzl(x); 233#elif defined(_WIN64) 234 unsigned long ret; // NOLINT 235 _BitScanForward64(&ret, x); 236 return ret; 237#else 238 unsigned long ret; // NOLINT 239 _BitScanForward(&ret, x); 240 return ret; 241#endif 242} 243 244// Don't use std::min, std::max or std::swap, to minimize dependency 245// on libstdc++. 246template<class T> T Min(T a, T b) { return a < b ? a : b; } 247template<class T> T Max(T a, T b) { return a > b ? a : b; } 248template<class T> void Swap(T& a, T& b) { 249 T tmp = a; 250 a = b; 251 b = tmp; 252} 253 254// Char handling 255INLINE bool IsSpace(int c) { 256 return (c == ' ') || (c == '\n') || (c == '\t') || 257 (c == '\f') || (c == '\r') || (c == '\v'); 258} 259INLINE bool IsDigit(int c) { 260 return (c >= '0') && (c <= '9'); 261} 262INLINE int ToLower(int c) { 263 return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c; 264} 265 266#if SANITIZER_WORDSIZE == 64 267# define FIRST_32_SECOND_64(a, b) (b) 268#else 269# define FIRST_32_SECOND_64(a, b) (a) 270#endif 271 272// A low-level vector based on mmap. May incur a significant memory overhead for 273// small vectors. 274// WARNING: The current implementation supports only POD types. 275template<typename T> 276class InternalVector { 277 public: 278 explicit InternalVector(uptr initial_capacity) { 279 CHECK_GT(initial_capacity, 0); 280 capacity_ = initial_capacity; 281 size_ = 0; 282 data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalVector"); 283 } 284 ~InternalVector() { 285 UnmapOrDie(data_, capacity_ * sizeof(T)); 286 } 287 T &operator[](uptr i) { 288 CHECK_LT(i, size_); 289 return data_[i]; 290 } 291 const T &operator[](uptr i) const { 292 CHECK_LT(i, size_); 293 return data_[i]; 294 } 295 void push_back(const T &element) { 296 CHECK_LE(size_, capacity_); 297 if (size_ == capacity_) { 298 uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1); 299 Resize(new_capacity); 300 } 301 data_[size_++] = element; 302 } 303 T &back() { 304 CHECK_GT(size_, 0); 305 return data_[size_ - 1]; 306 } 307 void pop_back() { 308 CHECK_GT(size_, 0); 309 size_--; 310 } 311 uptr size() const { 312 return size_; 313 } 314 const T *data() const { 315 return data_; 316 } 317 uptr capacity() const { 318 return capacity_; 319 } 320 321 private: 322 void Resize(uptr new_capacity) { 323 CHECK_GT(new_capacity, 0); 324 CHECK_LE(size_, new_capacity); 325 T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T), 326 "InternalVector"); 327 internal_memcpy(new_data, data_, size_ * sizeof(T)); 328 T *old_data = data_; 329 data_ = new_data; 330 UnmapOrDie(old_data, capacity_ * sizeof(T)); 331 capacity_ = new_capacity; 332 } 333 // Disallow evil constructors. 334 InternalVector(const InternalVector&); 335 void operator=(const InternalVector&); 336 337 T *data_; 338 uptr capacity_; 339 uptr size_; 340}; 341} // namespace __sanitizer 342 343#endif // SANITIZER_COMMON_H 344