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