• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
InternalScopedBuffer(uptr cnt)71   explicit InternalScopedBuffer(uptr cnt) {
72     cnt_ = cnt;
73     ptr_ = (T*)MmapOrDie(cnt * sizeof(T), "InternalScopedBuffer");
74   }
~InternalScopedBuffer()75   ~InternalScopedBuffer() {
76     UnmapOrDie(ptr_, cnt_ * sizeof(T));
77   }
78   T &operator[](uptr i) { return ptr_[i]; }
data()79   T *data() { return ptr_; }
size()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 
MostSignificantSetBitIndex(uptr x)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 
IsPowerOfTwo(uptr x)197 INLINE bool IsPowerOfTwo(uptr x) {
198   return (x & (x - 1)) == 0;
199 }
200 
RoundUpToPowerOfTwo(uptr size)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 
RoundUpTo(uptr size,uptr boundary)211 INLINE uptr RoundUpTo(uptr size, uptr boundary) {
212   CHECK(IsPowerOfTwo(boundary));
213   return (size + boundary - 1) & ~(boundary - 1);
214 }
215 
RoundDownTo(uptr x,uptr boundary)216 INLINE uptr RoundDownTo(uptr x, uptr boundary) {
217   return x & ~(boundary - 1);
218 }
219 
IsAligned(uptr a,uptr alignment)220 INLINE bool IsAligned(uptr a, uptr alignment) {
221   return (a & (alignment - 1)) == 0;
222 }
223 
Log2(uptr x)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++.
Min(T a,T b)241 template<class T> T Min(T a, T b) { return a < b ? a : b; }
Max(T a,T b)242 template<class T> T Max(T a, T b) { return a > b ? a : b; }
Swap(T & a,T & 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
IsSpace(int c)250 INLINE bool IsSpace(int c) {
251   return (c == ' ') || (c == '\n') || (c == '\t') ||
252          (c == '\f') || (c == '\r') || (c == '\v');
253 }
IsDigit(int c)254 INLINE bool IsDigit(int c) {
255   return (c >= '0') && (c <= '9');
256 }
ToLower(int c)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:
InternalVector(uptr initial_capacity)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   }
~InternalVector()279   ~InternalVector() {
280     UnmapOrDie(data_, capacity_ * sizeof(T));
281   }
282   T &operator[](uptr i) {
283     CHECK_LT(i, size_);
284     return data_[i];
285   }
push_back(const T & element)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   }
back()294   T &back() {
295     CHECK_GT(size_, 0);
296     return data_[size_ - 1];
297   }
pop_back()298   void pop_back() {
299     CHECK_GT(size_, 0);
300     size_--;
301   }
size()302   uptr size() {
303     return size_;
304   }
305 
306  private:
Resize(uptr new_capacity)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