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