sanitizer_common.h revision 9578a3ecfc35a264ede1135033398e2a77a6cad6
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); 48void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 49 uptr *tls_addr, uptr *tls_size); 50 51// Memory management 52void *MmapOrDie(uptr size, const char *mem_type); 53void UnmapOrDie(void *addr, uptr size); 54void *MmapFixedNoReserve(uptr fixed_addr, uptr size); 55void *MmapFixedOrDie(uptr fixed_addr, uptr size); 56void *Mprotect(uptr fixed_addr, uptr size); 57// Map aligned chunk of address space; size and alignment are powers of two. 58void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type); 59// Used to check if we can map shadow memory to a fixed location. 60bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); 61void FlushUnneededShadowMemory(uptr addr, uptr size); 62 63// Internal allocator 64void *InternalAlloc(uptr size); 65void InternalFree(void *p); 66 67// InternalScopedBuffer can be used instead of large stack arrays to 68// keep frame size low. 69// FIXME: use InternalAlloc instead of MmapOrDie once 70// InternalAlloc is made libc-free. 71template<typename T> 72class InternalScopedBuffer { 73 public: 74 explicit InternalScopedBuffer(uptr cnt) { 75 cnt_ = cnt; 76 ptr_ = (T*)MmapOrDie(cnt * sizeof(T), "InternalScopedBuffer"); 77 } 78 ~InternalScopedBuffer() { 79 UnmapOrDie(ptr_, cnt_ * sizeof(T)); 80 } 81 T &operator[](uptr i) { return ptr_[i]; } 82 T *data() { return ptr_; } 83 uptr size() { return cnt_ * sizeof(T); } 84 85 private: 86 T *ptr_; 87 uptr cnt_; 88 // Disallow evil constructors. 89 InternalScopedBuffer(const InternalScopedBuffer&); 90 void operator=(const InternalScopedBuffer&); 91}; 92 93// Simple low-level (mmap-based) allocator for internal use. Doesn't have 94// constructor, so all instances of LowLevelAllocator should be 95// linker initialized. 96class LowLevelAllocator { 97 public: 98 // Requires an external lock. 99 void *Allocate(uptr size); 100 private: 101 char *allocated_end_; 102 char *allocated_current_; 103}; 104typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size); 105// Allows to register tool-specific callbacks for LowLevelAllocator. 106// Passing NULL removes the callback. 107void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); 108 109// IO 110void RawWrite(const char *buffer); 111bool PrintsToTty(); 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; 117 118uptr 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. 123uptr 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'. 128void *MapFileToMemory(const char *file_name, uptr *buff_size); 129 130// OS 131void DisableCoreDumper(); 132void DumpProcessMap(); 133bool FileExists(const char *filename); 134const char *GetEnv(const char *name); 135bool SetEnv(const char *name, const char *value); 136const char *GetPwd(); 137u32 GetUid(); 138void ReExec(); 139bool StackSizeIsUnlimited(); 140void SetStackSizeLimitInBytes(uptr limit); 141void PrepareForSandboxing(); 142 143void InitTlsSize(); 144uptr GetTlsSize(); 145 146// Other 147void SleepForSeconds(int seconds); 148void SleepForMillis(int millis); 149u64 NanoTime(); 150int Atexit(void (*function)(void)); 151void SortArray(uptr *array, uptr size); 152 153// Exit 154void NORETURN Abort(); 155void NORETURN Die(); 156void NORETURN SANITIZER_INTERFACE_ATTRIBUTE 157CheckFailed(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. 161bool 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. 164bool SanitizerGetThreadName(char *name, int max_len); 165 166// Specific tools may override behavior of "Die" and "CheckFailed" functions 167// to do tool-specific job. 168void SetDieCallback(void (*callback)(void)); 169typedef void (*CheckFailedCallbackType)(const char *, int, const char *, 170 u64, u64); 171void 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. 176void ReportErrorSummary(const char *error_type, const char *file, 177 int line, const char *function); 178 179// Math 180#if SANITIZER_WINDOWS && !defined(__clang__) 181extern "C" { 182unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT 183unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT 184#if defined(_WIN64) 185unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT 186unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT 187#endif 188} 189#endif 190 191INLINE uptr MostSignificantSetBitIndex(uptr x) { 192 CHECK_NE(x, 0U); 193 unsigned long up; // NOLINT 194#if !SANITIZER_WINDOWS || defined(__clang__) 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 204INLINE bool IsPowerOfTwo(uptr x) { 205 return (x & (x - 1)) == 0; 206} 207 208INLINE 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 218INLINE uptr RoundUpTo(uptr size, uptr boundary) { 219 CHECK(IsPowerOfTwo(boundary)); 220 return (size + boundary - 1) & ~(boundary - 1); 221} 222 223INLINE uptr RoundDownTo(uptr x, uptr boundary) { 224 return x & ~(boundary - 1); 225} 226 227INLINE bool IsAligned(uptr a, uptr alignment) { 228 return (a & (alignment - 1)) == 0; 229} 230 231INLINE uptr Log2(uptr x) { 232 CHECK(IsPowerOfTwo(x)); 233#if !SANITIZER_WINDOWS || defined(__clang__) 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++. 248template<class T> T Min(T a, T b) { return a < b ? a : b; } 249template<class T> T Max(T a, T b) { return a > b ? a : b; } 250template<class T> void Swap(T& a, T& b) { 251 T tmp = a; 252 a = b; 253 b = tmp; 254} 255 256// Char handling 257INLINE bool IsSpace(int c) { 258 return (c == ' ') || (c == '\n') || (c == '\t') || 259 (c == '\f') || (c == '\r') || (c == '\v'); 260} 261INLINE bool IsDigit(int c) { 262 return (c >= '0') && (c <= '9'); 263} 264INLINE 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. 277template<typename T> 278class InternalVector { 279 public: 280 explicit InternalVector(uptr initial_capacity) { 281 CHECK_GT(initial_capacity, 0); 282 capacity_ = initial_capacity; 283 size_ = 0; 284 data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalVector"); 285 } 286 ~InternalVector() { 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 "InternalVector"); 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 InternalVector(const InternalVector&); 337 void operator=(const InternalVector&); 338 339 T *data_; 340 uptr capacity_; 341 uptr size_; 342}; 343} // namespace __sanitizer 344 345#endif // SANITIZER_COMMON_H 346