1*7c3d14c8STreehugger Robot //===-- sanitizer_common.h --------------------------------------*- C++ -*-===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is shared between run-time libraries of sanitizers.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot // It declares common functions and classes that are used in both runtimes.
13*7c3d14c8STreehugger Robot // Implementation of some functions are provided in sanitizer_common, while
14*7c3d14c8STreehugger Robot // others must be defined by run-time library itself.
15*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
16*7c3d14c8STreehugger Robot #ifndef SANITIZER_COMMON_H
17*7c3d14c8STreehugger Robot #define SANITIZER_COMMON_H
18*7c3d14c8STreehugger Robot
19*7c3d14c8STreehugger Robot #include "sanitizer_flags.h"
20*7c3d14c8STreehugger Robot #include "sanitizer_interface_internal.h"
21*7c3d14c8STreehugger Robot #include "sanitizer_internal_defs.h"
22*7c3d14c8STreehugger Robot #include "sanitizer_libc.h"
23*7c3d14c8STreehugger Robot #include "sanitizer_list.h"
24*7c3d14c8STreehugger Robot #include "sanitizer_mutex.h"
25*7c3d14c8STreehugger Robot
26*7c3d14c8STreehugger Robot #if defined(_MSC_VER) && !defined(__clang__)
27*7c3d14c8STreehugger Robot extern "C" void _ReadWriteBarrier();
28*7c3d14c8STreehugger Robot #pragma intrinsic(_ReadWriteBarrier)
29*7c3d14c8STreehugger Robot #endif
30*7c3d14c8STreehugger Robot
31*7c3d14c8STreehugger Robot namespace __sanitizer {
32*7c3d14c8STreehugger Robot struct StackTrace;
33*7c3d14c8STreehugger Robot struct AddressInfo;
34*7c3d14c8STreehugger Robot
35*7c3d14c8STreehugger Robot // Constants.
36*7c3d14c8STreehugger Robot const uptr kWordSize = SANITIZER_WORDSIZE / 8;
37*7c3d14c8STreehugger Robot const uptr kWordSizeInBits = 8 * kWordSize;
38*7c3d14c8STreehugger Robot
39*7c3d14c8STreehugger Robot #if defined(__powerpc__) || defined(__powerpc64__)
40*7c3d14c8STreehugger Robot const uptr kCacheLineSize = 128;
41*7c3d14c8STreehugger Robot #else
42*7c3d14c8STreehugger Robot const uptr kCacheLineSize = 64;
43*7c3d14c8STreehugger Robot #endif
44*7c3d14c8STreehugger Robot
45*7c3d14c8STreehugger Robot const uptr kMaxPathLength = 4096;
46*7c3d14c8STreehugger Robot
47*7c3d14c8STreehugger Robot const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
48*7c3d14c8STreehugger Robot
49*7c3d14c8STreehugger Robot static const uptr kErrorMessageBufferSize = 1 << 16;
50*7c3d14c8STreehugger Robot
51*7c3d14c8STreehugger Robot // Denotes fake PC values that come from JIT/JAVA/etc.
52*7c3d14c8STreehugger Robot // For such PC values __tsan_symbolize_external() will be called.
53*7c3d14c8STreehugger Robot const u64 kExternalPCBit = 1ULL << 60;
54*7c3d14c8STreehugger Robot
55*7c3d14c8STreehugger Robot extern const char *SanitizerToolName; // Can be changed by the tool.
56*7c3d14c8STreehugger Robot
57*7c3d14c8STreehugger Robot extern atomic_uint32_t current_verbosity;
SetVerbosity(int verbosity)58*7c3d14c8STreehugger Robot INLINE void SetVerbosity(int verbosity) {
59*7c3d14c8STreehugger Robot atomic_store(¤t_verbosity, verbosity, memory_order_relaxed);
60*7c3d14c8STreehugger Robot }
Verbosity()61*7c3d14c8STreehugger Robot INLINE int Verbosity() {
62*7c3d14c8STreehugger Robot return atomic_load(¤t_verbosity, memory_order_relaxed);
63*7c3d14c8STreehugger Robot }
64*7c3d14c8STreehugger Robot
65*7c3d14c8STreehugger Robot uptr GetPageSize();
66*7c3d14c8STreehugger Robot extern uptr PageSizeCached;
GetPageSizeCached()67*7c3d14c8STreehugger Robot INLINE uptr GetPageSizeCached() {
68*7c3d14c8STreehugger Robot if (!PageSizeCached)
69*7c3d14c8STreehugger Robot PageSizeCached = GetPageSize();
70*7c3d14c8STreehugger Robot return PageSizeCached;
71*7c3d14c8STreehugger Robot }
72*7c3d14c8STreehugger Robot uptr GetMmapGranularity();
73*7c3d14c8STreehugger Robot uptr GetMaxVirtualAddress();
74*7c3d14c8STreehugger Robot // Threads
75*7c3d14c8STreehugger Robot uptr GetTid();
76*7c3d14c8STreehugger Robot uptr GetThreadSelf();
77*7c3d14c8STreehugger Robot void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
78*7c3d14c8STreehugger Robot uptr *stack_bottom);
79*7c3d14c8STreehugger Robot void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
80*7c3d14c8STreehugger Robot uptr *tls_addr, uptr *tls_size);
81*7c3d14c8STreehugger Robot
82*7c3d14c8STreehugger Robot // Memory management
83*7c3d14c8STreehugger Robot void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
MmapOrDieQuietly(uptr size,const char * mem_type)84*7c3d14c8STreehugger Robot INLINE void *MmapOrDieQuietly(uptr size, const char *mem_type) {
85*7c3d14c8STreehugger Robot return MmapOrDie(size, mem_type, /*raw_report*/ true);
86*7c3d14c8STreehugger Robot }
87*7c3d14c8STreehugger Robot void UnmapOrDie(void *addr, uptr size);
88*7c3d14c8STreehugger Robot void *MmapFixedNoReserve(uptr fixed_addr, uptr size,
89*7c3d14c8STreehugger Robot const char *name = nullptr);
90*7c3d14c8STreehugger Robot void *MmapNoReserveOrDie(uptr size, const char *mem_type);
91*7c3d14c8STreehugger Robot void *MmapFixedOrDie(uptr fixed_addr, uptr size);
92*7c3d14c8STreehugger Robot void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);
93*7c3d14c8STreehugger Robot void *MmapNoAccess(uptr size);
94*7c3d14c8STreehugger Robot // Map aligned chunk of address space; size and alignment are powers of two.
95*7c3d14c8STreehugger Robot void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
96*7c3d14c8STreehugger Robot // Disallow access to a memory range. Use MmapFixedNoAccess to allocate an
97*7c3d14c8STreehugger Robot // unaccessible memory.
98*7c3d14c8STreehugger Robot bool MprotectNoAccess(uptr addr, uptr size);
99*7c3d14c8STreehugger Robot bool MprotectReadOnly(uptr addr, uptr size);
100*7c3d14c8STreehugger Robot
101*7c3d14c8STreehugger Robot // Used to check if we can map shadow memory to a fixed location.
102*7c3d14c8STreehugger Robot bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
103*7c3d14c8STreehugger Robot void FlushUnneededShadowMemory(uptr addr, uptr size);
104*7c3d14c8STreehugger Robot void IncreaseTotalMmap(uptr size);
105*7c3d14c8STreehugger Robot void DecreaseTotalMmap(uptr size);
106*7c3d14c8STreehugger Robot uptr GetRSS();
107*7c3d14c8STreehugger Robot void NoHugePagesInRegion(uptr addr, uptr length);
108*7c3d14c8STreehugger Robot void DontDumpShadowMemory(uptr addr, uptr length);
109*7c3d14c8STreehugger Robot // Check if the built VMA size matches the runtime one.
110*7c3d14c8STreehugger Robot void CheckVMASize();
111*7c3d14c8STreehugger Robot void RunMallocHooks(const void *ptr, uptr size);
112*7c3d14c8STreehugger Robot void RunFreeHooks(const void *ptr);
113*7c3d14c8STreehugger Robot
114*7c3d14c8STreehugger Robot // InternalScopedBuffer can be used instead of large stack arrays to
115*7c3d14c8STreehugger Robot // keep frame size low.
116*7c3d14c8STreehugger Robot // FIXME: use InternalAlloc instead of MmapOrDie once
117*7c3d14c8STreehugger Robot // InternalAlloc is made libc-free.
118*7c3d14c8STreehugger Robot template<typename T>
119*7c3d14c8STreehugger Robot class InternalScopedBuffer {
120*7c3d14c8STreehugger Robot public:
InternalScopedBuffer(uptr cnt)121*7c3d14c8STreehugger Robot explicit InternalScopedBuffer(uptr cnt) {
122*7c3d14c8STreehugger Robot cnt_ = cnt;
123*7c3d14c8STreehugger Robot ptr_ = (T*)MmapOrDie(cnt * sizeof(T), "InternalScopedBuffer");
124*7c3d14c8STreehugger Robot }
~InternalScopedBuffer()125*7c3d14c8STreehugger Robot ~InternalScopedBuffer() {
126*7c3d14c8STreehugger Robot UnmapOrDie(ptr_, cnt_ * sizeof(T));
127*7c3d14c8STreehugger Robot }
128*7c3d14c8STreehugger Robot T &operator[](uptr i) { return ptr_[i]; }
data()129*7c3d14c8STreehugger Robot T *data() { return ptr_; }
size()130*7c3d14c8STreehugger Robot uptr size() { return cnt_ * sizeof(T); }
131*7c3d14c8STreehugger Robot
132*7c3d14c8STreehugger Robot private:
133*7c3d14c8STreehugger Robot T *ptr_;
134*7c3d14c8STreehugger Robot uptr cnt_;
135*7c3d14c8STreehugger Robot // Disallow evil constructors.
136*7c3d14c8STreehugger Robot InternalScopedBuffer(const InternalScopedBuffer&);
137*7c3d14c8STreehugger Robot void operator=(const InternalScopedBuffer&);
138*7c3d14c8STreehugger Robot };
139*7c3d14c8STreehugger Robot
140*7c3d14c8STreehugger Robot class InternalScopedString : public InternalScopedBuffer<char> {
141*7c3d14c8STreehugger Robot public:
InternalScopedString(uptr max_length)142*7c3d14c8STreehugger Robot explicit InternalScopedString(uptr max_length)
143*7c3d14c8STreehugger Robot : InternalScopedBuffer<char>(max_length), length_(0) {
144*7c3d14c8STreehugger Robot (*this)[0] = '\0';
145*7c3d14c8STreehugger Robot }
length()146*7c3d14c8STreehugger Robot uptr length() { return length_; }
clear()147*7c3d14c8STreehugger Robot void clear() {
148*7c3d14c8STreehugger Robot (*this)[0] = '\0';
149*7c3d14c8STreehugger Robot length_ = 0;
150*7c3d14c8STreehugger Robot }
151*7c3d14c8STreehugger Robot void append(const char *format, ...);
152*7c3d14c8STreehugger Robot
153*7c3d14c8STreehugger Robot private:
154*7c3d14c8STreehugger Robot uptr length_;
155*7c3d14c8STreehugger Robot };
156*7c3d14c8STreehugger Robot
157*7c3d14c8STreehugger Robot // Simple low-level (mmap-based) allocator for internal use. Doesn't have
158*7c3d14c8STreehugger Robot // constructor, so all instances of LowLevelAllocator should be
159*7c3d14c8STreehugger Robot // linker initialized.
160*7c3d14c8STreehugger Robot class LowLevelAllocator {
161*7c3d14c8STreehugger Robot public:
162*7c3d14c8STreehugger Robot // Requires an external lock.
163*7c3d14c8STreehugger Robot void *Allocate(uptr size);
164*7c3d14c8STreehugger Robot private:
165*7c3d14c8STreehugger Robot char *allocated_end_;
166*7c3d14c8STreehugger Robot char *allocated_current_;
167*7c3d14c8STreehugger Robot };
168*7c3d14c8STreehugger Robot typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
169*7c3d14c8STreehugger Robot // Allows to register tool-specific callbacks for LowLevelAllocator.
170*7c3d14c8STreehugger Robot // Passing NULL removes the callback.
171*7c3d14c8STreehugger Robot void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
172*7c3d14c8STreehugger Robot
173*7c3d14c8STreehugger Robot // IO
174*7c3d14c8STreehugger Robot void RawWrite(const char *buffer);
175*7c3d14c8STreehugger Robot bool ColorizeReports();
176*7c3d14c8STreehugger Robot void RemoveANSIEscapeSequencesFromString(char *buffer);
177*7c3d14c8STreehugger Robot void Printf(const char *format, ...);
178*7c3d14c8STreehugger Robot void Report(const char *format, ...);
179*7c3d14c8STreehugger Robot void SetPrintfAndReportCallback(void (*callback)(const char *));
180*7c3d14c8STreehugger Robot #define VReport(level, ...) \
181*7c3d14c8STreehugger Robot do { \
182*7c3d14c8STreehugger Robot if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \
183*7c3d14c8STreehugger Robot } while (0)
184*7c3d14c8STreehugger Robot #define VPrintf(level, ...) \
185*7c3d14c8STreehugger Robot do { \
186*7c3d14c8STreehugger Robot if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \
187*7c3d14c8STreehugger Robot } while (0)
188*7c3d14c8STreehugger Robot
189*7c3d14c8STreehugger Robot // Can be used to prevent mixing error reports from different sanitizers.
190*7c3d14c8STreehugger Robot extern StaticSpinMutex CommonSanitizerReportMutex;
191*7c3d14c8STreehugger Robot
192*7c3d14c8STreehugger Robot struct ReportFile {
193*7c3d14c8STreehugger Robot void Write(const char *buffer, uptr length);
194*7c3d14c8STreehugger Robot bool SupportsColors();
195*7c3d14c8STreehugger Robot void SetReportPath(const char *path);
196*7c3d14c8STreehugger Robot
197*7c3d14c8STreehugger Robot // Don't use fields directly. They are only declared public to allow
198*7c3d14c8STreehugger Robot // aggregate initialization.
199*7c3d14c8STreehugger Robot
200*7c3d14c8STreehugger Robot // Protects fields below.
201*7c3d14c8STreehugger Robot StaticSpinMutex *mu;
202*7c3d14c8STreehugger Robot // Opened file descriptor. Defaults to stderr. It may be equal to
203*7c3d14c8STreehugger Robot // kInvalidFd, in which case new file will be opened when necessary.
204*7c3d14c8STreehugger Robot fd_t fd;
205*7c3d14c8STreehugger Robot // Path prefix of report file, set via __sanitizer_set_report_path.
206*7c3d14c8STreehugger Robot char path_prefix[kMaxPathLength];
207*7c3d14c8STreehugger Robot // Full path to report, obtained as <path_prefix>.PID
208*7c3d14c8STreehugger Robot char full_path[kMaxPathLength];
209*7c3d14c8STreehugger Robot // PID of the process that opened fd. If a fork() occurs,
210*7c3d14c8STreehugger Robot // the PID of child will be different from fd_pid.
211*7c3d14c8STreehugger Robot uptr fd_pid;
212*7c3d14c8STreehugger Robot
213*7c3d14c8STreehugger Robot private:
214*7c3d14c8STreehugger Robot void ReopenIfNecessary();
215*7c3d14c8STreehugger Robot };
216*7c3d14c8STreehugger Robot extern ReportFile report_file;
217*7c3d14c8STreehugger Robot
218*7c3d14c8STreehugger Robot extern uptr stoptheworld_tracer_pid;
219*7c3d14c8STreehugger Robot extern uptr stoptheworld_tracer_ppid;
220*7c3d14c8STreehugger Robot
221*7c3d14c8STreehugger Robot enum FileAccessMode {
222*7c3d14c8STreehugger Robot RdOnly,
223*7c3d14c8STreehugger Robot WrOnly,
224*7c3d14c8STreehugger Robot RdWr
225*7c3d14c8STreehugger Robot };
226*7c3d14c8STreehugger Robot
227*7c3d14c8STreehugger Robot // Returns kInvalidFd on error.
228*7c3d14c8STreehugger Robot fd_t OpenFile(const char *filename, FileAccessMode mode,
229*7c3d14c8STreehugger Robot error_t *errno_p = nullptr);
230*7c3d14c8STreehugger Robot void CloseFile(fd_t);
231*7c3d14c8STreehugger Robot
232*7c3d14c8STreehugger Robot // Return true on success, false on error.
233*7c3d14c8STreehugger Robot bool ReadFromFile(fd_t fd, void *buff, uptr buff_size,
234*7c3d14c8STreehugger Robot uptr *bytes_read = nullptr, error_t *error_p = nullptr);
235*7c3d14c8STreehugger Robot bool WriteToFile(fd_t fd, const void *buff, uptr buff_size,
236*7c3d14c8STreehugger Robot uptr *bytes_written = nullptr, error_t *error_p = nullptr);
237*7c3d14c8STreehugger Robot
238*7c3d14c8STreehugger Robot bool RenameFile(const char *oldpath, const char *newpath,
239*7c3d14c8STreehugger Robot error_t *error_p = nullptr);
240*7c3d14c8STreehugger Robot
241*7c3d14c8STreehugger Robot // Scoped file handle closer.
242*7c3d14c8STreehugger Robot struct FileCloser {
FileCloserFileCloser243*7c3d14c8STreehugger Robot explicit FileCloser(fd_t fd) : fd(fd) {}
~FileCloserFileCloser244*7c3d14c8STreehugger Robot ~FileCloser() { CloseFile(fd); }
245*7c3d14c8STreehugger Robot fd_t fd;
246*7c3d14c8STreehugger Robot };
247*7c3d14c8STreehugger Robot
248*7c3d14c8STreehugger Robot bool SupportsColoredOutput(fd_t fd);
249*7c3d14c8STreehugger Robot
250*7c3d14c8STreehugger Robot // Opens the file 'file_name" and reads up to 'max_len' bytes.
251*7c3d14c8STreehugger Robot // The resulting buffer is mmaped and stored in '*buff'.
252*7c3d14c8STreehugger Robot // The size of the mmaped region is stored in '*buff_size'.
253*7c3d14c8STreehugger Robot // The total number of read bytes is stored in '*read_len'.
254*7c3d14c8STreehugger Robot // Returns true if file was successfully opened and read.
255*7c3d14c8STreehugger Robot bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
256*7c3d14c8STreehugger Robot uptr *read_len, uptr max_len = 1 << 26,
257*7c3d14c8STreehugger Robot error_t *errno_p = nullptr);
258*7c3d14c8STreehugger Robot // Maps given file to virtual memory, and returns pointer to it
259*7c3d14c8STreehugger Robot // (or NULL if mapping fails). Stores the size of mmaped region
260*7c3d14c8STreehugger Robot // in '*buff_size'.
261*7c3d14c8STreehugger Robot void *MapFileToMemory(const char *file_name, uptr *buff_size);
262*7c3d14c8STreehugger Robot void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset);
263*7c3d14c8STreehugger Robot
264*7c3d14c8STreehugger Robot bool IsAccessibleMemoryRange(uptr beg, uptr size);
265*7c3d14c8STreehugger Robot
266*7c3d14c8STreehugger Robot // Error report formatting.
267*7c3d14c8STreehugger Robot const char *StripPathPrefix(const char *filepath,
268*7c3d14c8STreehugger Robot const char *strip_file_prefix);
269*7c3d14c8STreehugger Robot // Strip the directories from the module name.
270*7c3d14c8STreehugger Robot const char *StripModuleName(const char *module);
271*7c3d14c8STreehugger Robot
272*7c3d14c8STreehugger Robot // OS
273*7c3d14c8STreehugger Robot uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
274*7c3d14c8STreehugger Robot uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);
275*7c3d14c8STreehugger Robot uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);
276*7c3d14c8STreehugger Robot const char *GetProcessName();
277*7c3d14c8STreehugger Robot void UpdateProcessName();
278*7c3d14c8STreehugger Robot void CacheBinaryName();
279*7c3d14c8STreehugger Robot void DisableCoreDumperIfNecessary();
280*7c3d14c8STreehugger Robot void DumpProcessMap();
281*7c3d14c8STreehugger Robot bool FileExists(const char *filename);
282*7c3d14c8STreehugger Robot const char *GetEnv(const char *name);
283*7c3d14c8STreehugger Robot bool SetEnv(const char *name, const char *value);
284*7c3d14c8STreehugger Robot const char *GetPwd();
285*7c3d14c8STreehugger Robot char *FindPathToBinary(const char *name);
286*7c3d14c8STreehugger Robot bool IsPathSeparator(const char c);
287*7c3d14c8STreehugger Robot bool IsAbsolutePath(const char *path);
288*7c3d14c8STreehugger Robot // Starts a subprocess and returs its pid.
289*7c3d14c8STreehugger Robot // If *_fd parameters are not kInvalidFd their corresponding input/output
290*7c3d14c8STreehugger Robot // streams will be redirect to the file. The files will always be closed
291*7c3d14c8STreehugger Robot // in parent process even in case of an error.
292*7c3d14c8STreehugger Robot // The child process will close all fds after STDERR_FILENO
293*7c3d14c8STreehugger Robot // before passing control to a program.
294*7c3d14c8STreehugger Robot pid_t StartSubprocess(const char *filename, const char *const argv[],
295*7c3d14c8STreehugger Robot fd_t stdin_fd = kInvalidFd, fd_t stdout_fd = kInvalidFd,
296*7c3d14c8STreehugger Robot fd_t stderr_fd = kInvalidFd);
297*7c3d14c8STreehugger Robot // Checks if specified process is still running
298*7c3d14c8STreehugger Robot bool IsProcessRunning(pid_t pid);
299*7c3d14c8STreehugger Robot // Waits for the process to finish and returns its exit code.
300*7c3d14c8STreehugger Robot // Returns -1 in case of an error.
301*7c3d14c8STreehugger Robot int WaitForProcess(pid_t pid);
302*7c3d14c8STreehugger Robot
303*7c3d14c8STreehugger Robot u32 GetUid();
304*7c3d14c8STreehugger Robot void ReExec();
305*7c3d14c8STreehugger Robot char **GetArgv();
306*7c3d14c8STreehugger Robot void PrintCmdline();
307*7c3d14c8STreehugger Robot bool StackSizeIsUnlimited();
308*7c3d14c8STreehugger Robot uptr GetStackSizeLimitInBytes();
309*7c3d14c8STreehugger Robot void SetStackSizeLimitInBytes(uptr limit);
310*7c3d14c8STreehugger Robot bool AddressSpaceIsUnlimited();
311*7c3d14c8STreehugger Robot void SetAddressSpaceUnlimited();
312*7c3d14c8STreehugger Robot void AdjustStackSize(void *attr);
313*7c3d14c8STreehugger Robot void PrepareForSandboxing(__sanitizer_sandbox_arguments *args);
314*7c3d14c8STreehugger Robot void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
315*7c3d14c8STreehugger Robot void SetSandboxingCallback(void (*f)());
316*7c3d14c8STreehugger Robot
317*7c3d14c8STreehugger Robot void CoverageUpdateMapping();
318*7c3d14c8STreehugger Robot void CovBeforeFork();
319*7c3d14c8STreehugger Robot void CovAfterFork(int child_pid);
320*7c3d14c8STreehugger Robot
321*7c3d14c8STreehugger Robot void InitializeCoverage(bool enabled, const char *coverage_dir);
322*7c3d14c8STreehugger Robot void ReInitializeCoverage(bool enabled, const char *coverage_dir);
323*7c3d14c8STreehugger Robot
324*7c3d14c8STreehugger Robot void InitTlsSize();
325*7c3d14c8STreehugger Robot uptr GetTlsSize();
326*7c3d14c8STreehugger Robot
327*7c3d14c8STreehugger Robot // Other
328*7c3d14c8STreehugger Robot void SleepForSeconds(int seconds);
329*7c3d14c8STreehugger Robot void SleepForMillis(int millis);
330*7c3d14c8STreehugger Robot u64 NanoTime();
331*7c3d14c8STreehugger Robot int Atexit(void (*function)(void));
332*7c3d14c8STreehugger Robot void SortArray(uptr *array, uptr size);
333*7c3d14c8STreehugger Robot bool TemplateMatch(const char *templ, const char *str);
334*7c3d14c8STreehugger Robot
335*7c3d14c8STreehugger Robot // Exit
336*7c3d14c8STreehugger Robot void NORETURN Abort();
337*7c3d14c8STreehugger Robot void NORETURN Die();
338*7c3d14c8STreehugger Robot void NORETURN
339*7c3d14c8STreehugger Robot CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
340*7c3d14c8STreehugger Robot void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
341*7c3d14c8STreehugger Robot const char *mmap_type, error_t err,
342*7c3d14c8STreehugger Robot bool raw_report = false);
343*7c3d14c8STreehugger Robot
344*7c3d14c8STreehugger Robot // Set the name of the current thread to 'name', return true on succees.
345*7c3d14c8STreehugger Robot // The name may be truncated to a system-dependent limit.
346*7c3d14c8STreehugger Robot bool SanitizerSetThreadName(const char *name);
347*7c3d14c8STreehugger Robot // Get the name of the current thread (no more than max_len bytes),
348*7c3d14c8STreehugger Robot // return true on succees. name should have space for at least max_len+1 bytes.
349*7c3d14c8STreehugger Robot bool SanitizerGetThreadName(char *name, int max_len);
350*7c3d14c8STreehugger Robot
351*7c3d14c8STreehugger Robot // Specific tools may override behavior of "Die" and "CheckFailed" functions
352*7c3d14c8STreehugger Robot // to do tool-specific job.
353*7c3d14c8STreehugger Robot typedef void (*DieCallbackType)(void);
354*7c3d14c8STreehugger Robot
355*7c3d14c8STreehugger Robot // It's possible to add several callbacks that would be run when "Die" is
356*7c3d14c8STreehugger Robot // called. The callbacks will be run in the opposite order. The tools are
357*7c3d14c8STreehugger Robot // strongly recommended to setup all callbacks during initialization, when there
358*7c3d14c8STreehugger Robot // is only a single thread.
359*7c3d14c8STreehugger Robot bool AddDieCallback(DieCallbackType callback);
360*7c3d14c8STreehugger Robot bool RemoveDieCallback(DieCallbackType callback);
361*7c3d14c8STreehugger Robot
362*7c3d14c8STreehugger Robot void SetUserDieCallback(DieCallbackType callback);
363*7c3d14c8STreehugger Robot
364*7c3d14c8STreehugger Robot typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
365*7c3d14c8STreehugger Robot u64, u64);
366*7c3d14c8STreehugger Robot void SetCheckFailedCallback(CheckFailedCallbackType callback);
367*7c3d14c8STreehugger Robot
368*7c3d14c8STreehugger Robot // Callback will be called if soft_rss_limit_mb is given and the limit is
369*7c3d14c8STreehugger Robot // exceeded (exceeded==true) or if rss went down below the limit
370*7c3d14c8STreehugger Robot // (exceeded==false).
371*7c3d14c8STreehugger Robot // The callback should be registered once at the tool init time.
372*7c3d14c8STreehugger Robot void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded));
373*7c3d14c8STreehugger Robot
374*7c3d14c8STreehugger Robot // Functions related to signal handling.
375*7c3d14c8STreehugger Robot typedef void (*SignalHandlerType)(int, void *, void *);
376*7c3d14c8STreehugger Robot bool IsHandledDeadlySignal(int signum);
377*7c3d14c8STreehugger Robot void InstallDeadlySignalHandlers(SignalHandlerType handler);
378*7c3d14c8STreehugger Robot // Alternative signal stack (POSIX-only).
379*7c3d14c8STreehugger Robot void SetAlternateSignalStack();
380*7c3d14c8STreehugger Robot void UnsetAlternateSignalStack();
381*7c3d14c8STreehugger Robot
382*7c3d14c8STreehugger Robot // We don't want a summary too long.
383*7c3d14c8STreehugger Robot const int kMaxSummaryLength = 1024;
384*7c3d14c8STreehugger Robot // Construct a one-line string:
385*7c3d14c8STreehugger Robot // SUMMARY: SanitizerToolName: error_message
386*7c3d14c8STreehugger Robot // and pass it to __sanitizer_report_error_summary.
387*7c3d14c8STreehugger Robot void ReportErrorSummary(const char *error_message);
388*7c3d14c8STreehugger Robot // Same as above, but construct error_message as:
389*7c3d14c8STreehugger Robot // error_type file:line[:column][ function]
390*7c3d14c8STreehugger Robot void ReportErrorSummary(const char *error_type, const AddressInfo &info);
391*7c3d14c8STreehugger Robot // Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
392*7c3d14c8STreehugger Robot void ReportErrorSummary(const char *error_type, StackTrace *trace);
393*7c3d14c8STreehugger Robot
394*7c3d14c8STreehugger Robot // Math
395*7c3d14c8STreehugger Robot #if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
396*7c3d14c8STreehugger Robot extern "C" {
397*7c3d14c8STreehugger Robot unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT
398*7c3d14c8STreehugger Robot unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT
399*7c3d14c8STreehugger Robot #if defined(_WIN64)
400*7c3d14c8STreehugger Robot unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT
401*7c3d14c8STreehugger Robot unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT
402*7c3d14c8STreehugger Robot #endif
403*7c3d14c8STreehugger Robot }
404*7c3d14c8STreehugger Robot #endif
405*7c3d14c8STreehugger Robot
MostSignificantSetBitIndex(uptr x)406*7c3d14c8STreehugger Robot INLINE uptr MostSignificantSetBitIndex(uptr x) {
407*7c3d14c8STreehugger Robot CHECK_NE(x, 0U);
408*7c3d14c8STreehugger Robot unsigned long up; // NOLINT
409*7c3d14c8STreehugger Robot #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
410*7c3d14c8STreehugger Robot # ifdef _WIN64
411*7c3d14c8STreehugger Robot up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
412*7c3d14c8STreehugger Robot # else
413*7c3d14c8STreehugger Robot up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
414*7c3d14c8STreehugger Robot # endif
415*7c3d14c8STreehugger Robot #elif defined(_WIN64)
416*7c3d14c8STreehugger Robot _BitScanReverse64(&up, x);
417*7c3d14c8STreehugger Robot #else
418*7c3d14c8STreehugger Robot _BitScanReverse(&up, x);
419*7c3d14c8STreehugger Robot #endif
420*7c3d14c8STreehugger Robot return up;
421*7c3d14c8STreehugger Robot }
422*7c3d14c8STreehugger Robot
LeastSignificantSetBitIndex(uptr x)423*7c3d14c8STreehugger Robot INLINE uptr LeastSignificantSetBitIndex(uptr x) {
424*7c3d14c8STreehugger Robot CHECK_NE(x, 0U);
425*7c3d14c8STreehugger Robot unsigned long up; // NOLINT
426*7c3d14c8STreehugger Robot #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
427*7c3d14c8STreehugger Robot # ifdef _WIN64
428*7c3d14c8STreehugger Robot up = __builtin_ctzll(x);
429*7c3d14c8STreehugger Robot # else
430*7c3d14c8STreehugger Robot up = __builtin_ctzl(x);
431*7c3d14c8STreehugger Robot # endif
432*7c3d14c8STreehugger Robot #elif defined(_WIN64)
433*7c3d14c8STreehugger Robot _BitScanForward64(&up, x);
434*7c3d14c8STreehugger Robot #else
435*7c3d14c8STreehugger Robot _BitScanForward(&up, x);
436*7c3d14c8STreehugger Robot #endif
437*7c3d14c8STreehugger Robot return up;
438*7c3d14c8STreehugger Robot }
439*7c3d14c8STreehugger Robot
IsPowerOfTwo(uptr x)440*7c3d14c8STreehugger Robot INLINE bool IsPowerOfTwo(uptr x) {
441*7c3d14c8STreehugger Robot return (x & (x - 1)) == 0;
442*7c3d14c8STreehugger Robot }
443*7c3d14c8STreehugger Robot
RoundUpToPowerOfTwo(uptr size)444*7c3d14c8STreehugger Robot INLINE uptr RoundUpToPowerOfTwo(uptr size) {
445*7c3d14c8STreehugger Robot CHECK(size);
446*7c3d14c8STreehugger Robot if (IsPowerOfTwo(size)) return size;
447*7c3d14c8STreehugger Robot
448*7c3d14c8STreehugger Robot uptr up = MostSignificantSetBitIndex(size);
449*7c3d14c8STreehugger Robot CHECK(size < (1ULL << (up + 1)));
450*7c3d14c8STreehugger Robot CHECK(size > (1ULL << up));
451*7c3d14c8STreehugger Robot return 1ULL << (up + 1);
452*7c3d14c8STreehugger Robot }
453*7c3d14c8STreehugger Robot
RoundUpTo(uptr size,uptr boundary)454*7c3d14c8STreehugger Robot INLINE uptr RoundUpTo(uptr size, uptr boundary) {
455*7c3d14c8STreehugger Robot RAW_CHECK(IsPowerOfTwo(boundary));
456*7c3d14c8STreehugger Robot return (size + boundary - 1) & ~(boundary - 1);
457*7c3d14c8STreehugger Robot }
458*7c3d14c8STreehugger Robot
RoundDownTo(uptr x,uptr boundary)459*7c3d14c8STreehugger Robot INLINE uptr RoundDownTo(uptr x, uptr boundary) {
460*7c3d14c8STreehugger Robot return x & ~(boundary - 1);
461*7c3d14c8STreehugger Robot }
462*7c3d14c8STreehugger Robot
IsAligned(uptr a,uptr alignment)463*7c3d14c8STreehugger Robot INLINE bool IsAligned(uptr a, uptr alignment) {
464*7c3d14c8STreehugger Robot return (a & (alignment - 1)) == 0;
465*7c3d14c8STreehugger Robot }
466*7c3d14c8STreehugger Robot
Log2(uptr x)467*7c3d14c8STreehugger Robot INLINE uptr Log2(uptr x) {
468*7c3d14c8STreehugger Robot CHECK(IsPowerOfTwo(x));
469*7c3d14c8STreehugger Robot return LeastSignificantSetBitIndex(x);
470*7c3d14c8STreehugger Robot }
471*7c3d14c8STreehugger Robot
472*7c3d14c8STreehugger Robot // Don't use std::min, std::max or std::swap, to minimize dependency
473*7c3d14c8STreehugger Robot // on libstdc++.
Min(T a,T b)474*7c3d14c8STreehugger Robot template<class T> T Min(T a, T b) { return a < b ? a : b; }
Max(T a,T b)475*7c3d14c8STreehugger Robot template<class T> T Max(T a, T b) { return a > b ? a : b; }
Swap(T & a,T & b)476*7c3d14c8STreehugger Robot template<class T> void Swap(T& a, T& b) {
477*7c3d14c8STreehugger Robot T tmp = a;
478*7c3d14c8STreehugger Robot a = b;
479*7c3d14c8STreehugger Robot b = tmp;
480*7c3d14c8STreehugger Robot }
481*7c3d14c8STreehugger Robot
482*7c3d14c8STreehugger Robot // Char handling
IsSpace(int c)483*7c3d14c8STreehugger Robot INLINE bool IsSpace(int c) {
484*7c3d14c8STreehugger Robot return (c == ' ') || (c == '\n') || (c == '\t') ||
485*7c3d14c8STreehugger Robot (c == '\f') || (c == '\r') || (c == '\v');
486*7c3d14c8STreehugger Robot }
IsDigit(int c)487*7c3d14c8STreehugger Robot INLINE bool IsDigit(int c) {
488*7c3d14c8STreehugger Robot return (c >= '0') && (c <= '9');
489*7c3d14c8STreehugger Robot }
ToLower(int c)490*7c3d14c8STreehugger Robot INLINE int ToLower(int c) {
491*7c3d14c8STreehugger Robot return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
492*7c3d14c8STreehugger Robot }
493*7c3d14c8STreehugger Robot
494*7c3d14c8STreehugger Robot // A low-level vector based on mmap. May incur a significant memory overhead for
495*7c3d14c8STreehugger Robot // small vectors.
496*7c3d14c8STreehugger Robot // WARNING: The current implementation supports only POD types.
497*7c3d14c8STreehugger Robot template<typename T>
498*7c3d14c8STreehugger Robot class InternalMmapVectorNoCtor {
499*7c3d14c8STreehugger Robot public:
Initialize(uptr initial_capacity)500*7c3d14c8STreehugger Robot void Initialize(uptr initial_capacity) {
501*7c3d14c8STreehugger Robot capacity_ = Max(initial_capacity, (uptr)1);
502*7c3d14c8STreehugger Robot size_ = 0;
503*7c3d14c8STreehugger Robot data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVectorNoCtor");
504*7c3d14c8STreehugger Robot }
Destroy()505*7c3d14c8STreehugger Robot void Destroy() {
506*7c3d14c8STreehugger Robot UnmapOrDie(data_, capacity_ * sizeof(T));
507*7c3d14c8STreehugger Robot }
508*7c3d14c8STreehugger Robot T &operator[](uptr i) {
509*7c3d14c8STreehugger Robot CHECK_LT(i, size_);
510*7c3d14c8STreehugger Robot return data_[i];
511*7c3d14c8STreehugger Robot }
512*7c3d14c8STreehugger Robot const T &operator[](uptr i) const {
513*7c3d14c8STreehugger Robot CHECK_LT(i, size_);
514*7c3d14c8STreehugger Robot return data_[i];
515*7c3d14c8STreehugger Robot }
push_back(const T & element)516*7c3d14c8STreehugger Robot void push_back(const T &element) {
517*7c3d14c8STreehugger Robot CHECK_LE(size_, capacity_);
518*7c3d14c8STreehugger Robot if (size_ == capacity_) {
519*7c3d14c8STreehugger Robot uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
520*7c3d14c8STreehugger Robot Resize(new_capacity);
521*7c3d14c8STreehugger Robot }
522*7c3d14c8STreehugger Robot internal_memcpy(&data_[size_++], &element, sizeof(T));
523*7c3d14c8STreehugger Robot }
back()524*7c3d14c8STreehugger Robot T &back() {
525*7c3d14c8STreehugger Robot CHECK_GT(size_, 0);
526*7c3d14c8STreehugger Robot return data_[size_ - 1];
527*7c3d14c8STreehugger Robot }
pop_back()528*7c3d14c8STreehugger Robot void pop_back() {
529*7c3d14c8STreehugger Robot CHECK_GT(size_, 0);
530*7c3d14c8STreehugger Robot size_--;
531*7c3d14c8STreehugger Robot }
size()532*7c3d14c8STreehugger Robot uptr size() const {
533*7c3d14c8STreehugger Robot return size_;
534*7c3d14c8STreehugger Robot }
data()535*7c3d14c8STreehugger Robot const T *data() const {
536*7c3d14c8STreehugger Robot return data_;
537*7c3d14c8STreehugger Robot }
data()538*7c3d14c8STreehugger Robot T *data() {
539*7c3d14c8STreehugger Robot return data_;
540*7c3d14c8STreehugger Robot }
capacity()541*7c3d14c8STreehugger Robot uptr capacity() const {
542*7c3d14c8STreehugger Robot return capacity_;
543*7c3d14c8STreehugger Robot }
544*7c3d14c8STreehugger Robot
clear()545*7c3d14c8STreehugger Robot void clear() { size_ = 0; }
empty()546*7c3d14c8STreehugger Robot bool empty() const { return size() == 0; }
547*7c3d14c8STreehugger Robot
begin()548*7c3d14c8STreehugger Robot const T *begin() const {
549*7c3d14c8STreehugger Robot return data();
550*7c3d14c8STreehugger Robot }
begin()551*7c3d14c8STreehugger Robot T *begin() {
552*7c3d14c8STreehugger Robot return data();
553*7c3d14c8STreehugger Robot }
end()554*7c3d14c8STreehugger Robot const T *end() const {
555*7c3d14c8STreehugger Robot return data() + size();
556*7c3d14c8STreehugger Robot }
end()557*7c3d14c8STreehugger Robot T *end() {
558*7c3d14c8STreehugger Robot return data() + size();
559*7c3d14c8STreehugger Robot }
560*7c3d14c8STreehugger Robot
561*7c3d14c8STreehugger Robot private:
Resize(uptr new_capacity)562*7c3d14c8STreehugger Robot void Resize(uptr new_capacity) {
563*7c3d14c8STreehugger Robot CHECK_GT(new_capacity, 0);
564*7c3d14c8STreehugger Robot CHECK_LE(size_, new_capacity);
565*7c3d14c8STreehugger Robot T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T),
566*7c3d14c8STreehugger Robot "InternalMmapVector");
567*7c3d14c8STreehugger Robot internal_memcpy(new_data, data_, size_ * sizeof(T));
568*7c3d14c8STreehugger Robot T *old_data = data_;
569*7c3d14c8STreehugger Robot data_ = new_data;
570*7c3d14c8STreehugger Robot UnmapOrDie(old_data, capacity_ * sizeof(T));
571*7c3d14c8STreehugger Robot capacity_ = new_capacity;
572*7c3d14c8STreehugger Robot }
573*7c3d14c8STreehugger Robot
574*7c3d14c8STreehugger Robot T *data_;
575*7c3d14c8STreehugger Robot uptr capacity_;
576*7c3d14c8STreehugger Robot uptr size_;
577*7c3d14c8STreehugger Robot };
578*7c3d14c8STreehugger Robot
579*7c3d14c8STreehugger Robot template<typename T>
580*7c3d14c8STreehugger Robot class InternalMmapVector : public InternalMmapVectorNoCtor<T> {
581*7c3d14c8STreehugger Robot public:
InternalMmapVector(uptr initial_capacity)582*7c3d14c8STreehugger Robot explicit InternalMmapVector(uptr initial_capacity) {
583*7c3d14c8STreehugger Robot InternalMmapVectorNoCtor<T>::Initialize(initial_capacity);
584*7c3d14c8STreehugger Robot }
~InternalMmapVector()585*7c3d14c8STreehugger Robot ~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }
586*7c3d14c8STreehugger Robot // Disallow evil constructors.
587*7c3d14c8STreehugger Robot InternalMmapVector(const InternalMmapVector&);
588*7c3d14c8STreehugger Robot void operator=(const InternalMmapVector&);
589*7c3d14c8STreehugger Robot };
590*7c3d14c8STreehugger Robot
591*7c3d14c8STreehugger Robot // HeapSort for arrays and InternalMmapVector.
592*7c3d14c8STreehugger Robot template<class Container, class Compare>
InternalSort(Container * v,uptr size,Compare comp)593*7c3d14c8STreehugger Robot void InternalSort(Container *v, uptr size, Compare comp) {
594*7c3d14c8STreehugger Robot if (size < 2)
595*7c3d14c8STreehugger Robot return;
596*7c3d14c8STreehugger Robot // Stage 1: insert elements to the heap.
597*7c3d14c8STreehugger Robot for (uptr i = 1; i < size; i++) {
598*7c3d14c8STreehugger Robot uptr j, p;
599*7c3d14c8STreehugger Robot for (j = i; j > 0; j = p) {
600*7c3d14c8STreehugger Robot p = (j - 1) / 2;
601*7c3d14c8STreehugger Robot if (comp((*v)[p], (*v)[j]))
602*7c3d14c8STreehugger Robot Swap((*v)[j], (*v)[p]);
603*7c3d14c8STreehugger Robot else
604*7c3d14c8STreehugger Robot break;
605*7c3d14c8STreehugger Robot }
606*7c3d14c8STreehugger Robot }
607*7c3d14c8STreehugger Robot // Stage 2: swap largest element with the last one,
608*7c3d14c8STreehugger Robot // and sink the new top.
609*7c3d14c8STreehugger Robot for (uptr i = size - 1; i > 0; i--) {
610*7c3d14c8STreehugger Robot Swap((*v)[0], (*v)[i]);
611*7c3d14c8STreehugger Robot uptr j, max_ind;
612*7c3d14c8STreehugger Robot for (j = 0; j < i; j = max_ind) {
613*7c3d14c8STreehugger Robot uptr left = 2 * j + 1;
614*7c3d14c8STreehugger Robot uptr right = 2 * j + 2;
615*7c3d14c8STreehugger Robot max_ind = j;
616*7c3d14c8STreehugger Robot if (left < i && comp((*v)[max_ind], (*v)[left]))
617*7c3d14c8STreehugger Robot max_ind = left;
618*7c3d14c8STreehugger Robot if (right < i && comp((*v)[max_ind], (*v)[right]))
619*7c3d14c8STreehugger Robot max_ind = right;
620*7c3d14c8STreehugger Robot if (max_ind != j)
621*7c3d14c8STreehugger Robot Swap((*v)[j], (*v)[max_ind]);
622*7c3d14c8STreehugger Robot else
623*7c3d14c8STreehugger Robot break;
624*7c3d14c8STreehugger Robot }
625*7c3d14c8STreehugger Robot }
626*7c3d14c8STreehugger Robot }
627*7c3d14c8STreehugger Robot
628*7c3d14c8STreehugger Robot template<class Container, class Value, class Compare>
InternalBinarySearch(const Container & v,uptr first,uptr last,const Value & val,Compare comp)629*7c3d14c8STreehugger Robot uptr InternalBinarySearch(const Container &v, uptr first, uptr last,
630*7c3d14c8STreehugger Robot const Value &val, Compare comp) {
631*7c3d14c8STreehugger Robot uptr not_found = last + 1;
632*7c3d14c8STreehugger Robot while (last >= first) {
633*7c3d14c8STreehugger Robot uptr mid = (first + last) / 2;
634*7c3d14c8STreehugger Robot if (comp(v[mid], val))
635*7c3d14c8STreehugger Robot first = mid + 1;
636*7c3d14c8STreehugger Robot else if (comp(val, v[mid]))
637*7c3d14c8STreehugger Robot last = mid - 1;
638*7c3d14c8STreehugger Robot else
639*7c3d14c8STreehugger Robot return mid;
640*7c3d14c8STreehugger Robot }
641*7c3d14c8STreehugger Robot return not_found;
642*7c3d14c8STreehugger Robot }
643*7c3d14c8STreehugger Robot
644*7c3d14c8STreehugger Robot // Represents a binary loaded into virtual memory (e.g. this can be an
645*7c3d14c8STreehugger Robot // executable or a shared object).
646*7c3d14c8STreehugger Robot class LoadedModule {
647*7c3d14c8STreehugger Robot public:
LoadedModule()648*7c3d14c8STreehugger Robot LoadedModule() : full_name_(nullptr), base_address_(0) { ranges_.clear(); }
649*7c3d14c8STreehugger Robot void set(const char *module_name, uptr base_address);
650*7c3d14c8STreehugger Robot void clear();
651*7c3d14c8STreehugger Robot void addAddressRange(uptr beg, uptr end, bool executable);
652*7c3d14c8STreehugger Robot bool containsAddress(uptr address) const;
653*7c3d14c8STreehugger Robot
full_name()654*7c3d14c8STreehugger Robot const char *full_name() const { return full_name_; }
base_address()655*7c3d14c8STreehugger Robot uptr base_address() const { return base_address_; }
656*7c3d14c8STreehugger Robot
657*7c3d14c8STreehugger Robot struct AddressRange {
658*7c3d14c8STreehugger Robot AddressRange *next;
659*7c3d14c8STreehugger Robot uptr beg;
660*7c3d14c8STreehugger Robot uptr end;
661*7c3d14c8STreehugger Robot bool executable;
662*7c3d14c8STreehugger Robot
AddressRangeAddressRange663*7c3d14c8STreehugger Robot AddressRange(uptr beg, uptr end, bool executable)
664*7c3d14c8STreehugger Robot : next(nullptr), beg(beg), end(end), executable(executable) {}
665*7c3d14c8STreehugger Robot };
666*7c3d14c8STreehugger Robot
ranges()667*7c3d14c8STreehugger Robot const IntrusiveList<AddressRange> &ranges() const { return ranges_; }
668*7c3d14c8STreehugger Robot
669*7c3d14c8STreehugger Robot private:
670*7c3d14c8STreehugger Robot char *full_name_; // Owned.
671*7c3d14c8STreehugger Robot uptr base_address_;
672*7c3d14c8STreehugger Robot IntrusiveList<AddressRange> ranges_;
673*7c3d14c8STreehugger Robot };
674*7c3d14c8STreehugger Robot
675*7c3d14c8STreehugger Robot // List of LoadedModules. OS-dependent implementation is responsible for
676*7c3d14c8STreehugger Robot // filling this information.
677*7c3d14c8STreehugger Robot class ListOfModules {
678*7c3d14c8STreehugger Robot public:
ListOfModules()679*7c3d14c8STreehugger Robot ListOfModules() : modules_(kInitialCapacity) {}
~ListOfModules()680*7c3d14c8STreehugger Robot ~ListOfModules() { clear(); }
681*7c3d14c8STreehugger Robot void init();
begin()682*7c3d14c8STreehugger Robot const LoadedModule *begin() const { return modules_.begin(); }
begin()683*7c3d14c8STreehugger Robot LoadedModule *begin() { return modules_.begin(); }
end()684*7c3d14c8STreehugger Robot const LoadedModule *end() const { return modules_.end(); }
end()685*7c3d14c8STreehugger Robot LoadedModule *end() { return modules_.end(); }
size()686*7c3d14c8STreehugger Robot uptr size() const { return modules_.size(); }
687*7c3d14c8STreehugger Robot const LoadedModule &operator[](uptr i) const {
688*7c3d14c8STreehugger Robot CHECK_LT(i, modules_.size());
689*7c3d14c8STreehugger Robot return modules_[i];
690*7c3d14c8STreehugger Robot }
691*7c3d14c8STreehugger Robot
692*7c3d14c8STreehugger Robot private:
clear()693*7c3d14c8STreehugger Robot void clear() {
694*7c3d14c8STreehugger Robot for (auto &module : modules_) module.clear();
695*7c3d14c8STreehugger Robot modules_.clear();
696*7c3d14c8STreehugger Robot }
697*7c3d14c8STreehugger Robot
698*7c3d14c8STreehugger Robot InternalMmapVector<LoadedModule> modules_;
699*7c3d14c8STreehugger Robot // We rarely have more than 16K loaded modules.
700*7c3d14c8STreehugger Robot static const uptr kInitialCapacity = 1 << 14;
701*7c3d14c8STreehugger Robot };
702*7c3d14c8STreehugger Robot
703*7c3d14c8STreehugger Robot // Callback type for iterating over a set of memory ranges.
704*7c3d14c8STreehugger Robot typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
705*7c3d14c8STreehugger Robot
706*7c3d14c8STreehugger Robot enum AndroidApiLevel {
707*7c3d14c8STreehugger Robot ANDROID_NOT_ANDROID = 0,
708*7c3d14c8STreehugger Robot ANDROID_KITKAT = 19,
709*7c3d14c8STreehugger Robot ANDROID_LOLLIPOP_MR1 = 22,
710*7c3d14c8STreehugger Robot ANDROID_POST_LOLLIPOP = 23
711*7c3d14c8STreehugger Robot };
712*7c3d14c8STreehugger Robot
713*7c3d14c8STreehugger Robot void WriteToSyslog(const char *buffer);
714*7c3d14c8STreehugger Robot
715*7c3d14c8STreehugger Robot #if SANITIZER_MAC
716*7c3d14c8STreehugger Robot void LogFullErrorReport(const char *buffer);
717*7c3d14c8STreehugger Robot #else
LogFullErrorReport(const char * buffer)718*7c3d14c8STreehugger Robot INLINE void LogFullErrorReport(const char *buffer) {}
719*7c3d14c8STreehugger Robot #endif
720*7c3d14c8STreehugger Robot
721*7c3d14c8STreehugger Robot #if SANITIZER_LINUX || SANITIZER_MAC
722*7c3d14c8STreehugger Robot void WriteOneLineToSyslog(const char *s);
723*7c3d14c8STreehugger Robot void LogMessageOnPrintf(const char *str);
724*7c3d14c8STreehugger Robot #else
WriteOneLineToSyslog(const char * s)725*7c3d14c8STreehugger Robot INLINE void WriteOneLineToSyslog(const char *s) {}
LogMessageOnPrintf(const char * str)726*7c3d14c8STreehugger Robot INLINE void LogMessageOnPrintf(const char *str) {}
727*7c3d14c8STreehugger Robot #endif
728*7c3d14c8STreehugger Robot
729*7c3d14c8STreehugger Robot #if SANITIZER_LINUX
730*7c3d14c8STreehugger Robot // Initialize Android logging. Any writes before this are silently lost.
731*7c3d14c8STreehugger Robot void AndroidLogInit();
732*7c3d14c8STreehugger Robot #else
AndroidLogInit()733*7c3d14c8STreehugger Robot INLINE void AndroidLogInit() {}
734*7c3d14c8STreehugger Robot #endif
735*7c3d14c8STreehugger Robot
736*7c3d14c8STreehugger Robot #if SANITIZER_ANDROID
737*7c3d14c8STreehugger Robot void SanitizerInitializeUnwinder();
738*7c3d14c8STreehugger Robot AndroidApiLevel AndroidGetApiLevel();
739*7c3d14c8STreehugger Robot #else
AndroidLogWrite(const char * buffer_unused)740*7c3d14c8STreehugger Robot INLINE void AndroidLogWrite(const char *buffer_unused) {}
SanitizerInitializeUnwinder()741*7c3d14c8STreehugger Robot INLINE void SanitizerInitializeUnwinder() {}
AndroidGetApiLevel()742*7c3d14c8STreehugger Robot INLINE AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; }
743*7c3d14c8STreehugger Robot #endif
744*7c3d14c8STreehugger Robot
GetPthreadDestructorIterations()745*7c3d14c8STreehugger Robot INLINE uptr GetPthreadDestructorIterations() {
746*7c3d14c8STreehugger Robot #if SANITIZER_ANDROID
747*7c3d14c8STreehugger Robot return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;
748*7c3d14c8STreehugger Robot #elif SANITIZER_POSIX
749*7c3d14c8STreehugger Robot return 4;
750*7c3d14c8STreehugger Robot #else
751*7c3d14c8STreehugger Robot // Unused on Windows.
752*7c3d14c8STreehugger Robot return 0;
753*7c3d14c8STreehugger Robot #endif
754*7c3d14c8STreehugger Robot }
755*7c3d14c8STreehugger Robot
756*7c3d14c8STreehugger Robot void *internal_start_thread(void(*func)(void*), void *arg);
757*7c3d14c8STreehugger Robot void internal_join_thread(void *th);
758*7c3d14c8STreehugger Robot void MaybeStartBackgroudThread();
759*7c3d14c8STreehugger Robot
760*7c3d14c8STreehugger Robot // Make the compiler think that something is going on there.
761*7c3d14c8STreehugger Robot // Use this inside a loop that looks like memset/memcpy/etc to prevent the
762*7c3d14c8STreehugger Robot // compiler from recognising it and turning it into an actual call to
763*7c3d14c8STreehugger Robot // memset/memcpy/etc.
SanitizerBreakOptimization(void * arg)764*7c3d14c8STreehugger Robot static inline void SanitizerBreakOptimization(void *arg) {
765*7c3d14c8STreehugger Robot #if defined(_MSC_VER) && !defined(__clang__)
766*7c3d14c8STreehugger Robot _ReadWriteBarrier();
767*7c3d14c8STreehugger Robot #else
768*7c3d14c8STreehugger Robot __asm__ __volatile__("" : : "r" (arg) : "memory");
769*7c3d14c8STreehugger Robot #endif
770*7c3d14c8STreehugger Robot }
771*7c3d14c8STreehugger Robot
772*7c3d14c8STreehugger Robot struct SignalContext {
773*7c3d14c8STreehugger Robot void *context;
774*7c3d14c8STreehugger Robot uptr addr;
775*7c3d14c8STreehugger Robot uptr pc;
776*7c3d14c8STreehugger Robot uptr sp;
777*7c3d14c8STreehugger Robot uptr bp;
778*7c3d14c8STreehugger Robot bool is_memory_access;
779*7c3d14c8STreehugger Robot
780*7c3d14c8STreehugger Robot enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
781*7c3d14c8STreehugger Robot
SignalContextSignalContext782*7c3d14c8STreehugger Robot SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp,
783*7c3d14c8STreehugger Robot bool is_memory_access, WriteFlag write_flag)
784*7c3d14c8STreehugger Robot : context(context),
785*7c3d14c8STreehugger Robot addr(addr),
786*7c3d14c8STreehugger Robot pc(pc),
787*7c3d14c8STreehugger Robot sp(sp),
788*7c3d14c8STreehugger Robot bp(bp),
789*7c3d14c8STreehugger Robot is_memory_access(is_memory_access),
790*7c3d14c8STreehugger Robot write_flag(write_flag) {}
791*7c3d14c8STreehugger Robot
792*7c3d14c8STreehugger Robot // Creates signal context in a platform-specific manner.
793*7c3d14c8STreehugger Robot static SignalContext Create(void *siginfo, void *context);
794*7c3d14c8STreehugger Robot
795*7c3d14c8STreehugger Robot // Returns true if the "context" indicates a memory write.
796*7c3d14c8STreehugger Robot static WriteFlag GetWriteFlag(void *context);
797*7c3d14c8STreehugger Robot };
798*7c3d14c8STreehugger Robot
799*7c3d14c8STreehugger Robot void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
800*7c3d14c8STreehugger Robot
801*7c3d14c8STreehugger Robot void MaybeReexec();
802*7c3d14c8STreehugger Robot
803*7c3d14c8STreehugger Robot template <typename Fn>
804*7c3d14c8STreehugger Robot class RunOnDestruction {
805*7c3d14c8STreehugger Robot public:
RunOnDestruction(Fn fn)806*7c3d14c8STreehugger Robot explicit RunOnDestruction(Fn fn) : fn_(fn) {}
~RunOnDestruction()807*7c3d14c8STreehugger Robot ~RunOnDestruction() { fn_(); }
808*7c3d14c8STreehugger Robot
809*7c3d14c8STreehugger Robot private:
810*7c3d14c8STreehugger Robot Fn fn_;
811*7c3d14c8STreehugger Robot };
812*7c3d14c8STreehugger Robot
813*7c3d14c8STreehugger Robot // A simple scope guard. Usage:
814*7c3d14c8STreehugger Robot // auto cleanup = at_scope_exit([]{ do_cleanup; });
815*7c3d14c8STreehugger Robot template <typename Fn>
at_scope_exit(Fn fn)816*7c3d14c8STreehugger Robot RunOnDestruction<Fn> at_scope_exit(Fn fn) {
817*7c3d14c8STreehugger Robot return RunOnDestruction<Fn>(fn);
818*7c3d14c8STreehugger Robot }
819*7c3d14c8STreehugger Robot
820*7c3d14c8STreehugger Robot // Linux on 64-bit s390 had a nasty bug that crashes the whole machine
821*7c3d14c8STreehugger Robot // if a process uses virtual memory over 4TB (as many sanitizers like
822*7c3d14c8STreehugger Robot // to do). This function will abort the process if running on a kernel
823*7c3d14c8STreehugger Robot // that looks vulnerable.
824*7c3d14c8STreehugger Robot #if SANITIZER_LINUX && SANITIZER_S390_64
825*7c3d14c8STreehugger Robot void AvoidCVE_2016_2143();
826*7c3d14c8STreehugger Robot #else
AvoidCVE_2016_2143()827*7c3d14c8STreehugger Robot INLINE void AvoidCVE_2016_2143() {}
828*7c3d14c8STreehugger Robot #endif
829*7c3d14c8STreehugger Robot
830*7c3d14c8STreehugger Robot } // namespace __sanitizer
831*7c3d14c8STreehugger Robot
new(__sanitizer::operator_new_size_type size,__sanitizer::LowLevelAllocator & alloc)832*7c3d14c8STreehugger Robot inline void *operator new(__sanitizer::operator_new_size_type size,
833*7c3d14c8STreehugger Robot __sanitizer::LowLevelAllocator &alloc) {
834*7c3d14c8STreehugger Robot return alloc.Allocate(size);
835*7c3d14c8STreehugger Robot }
836*7c3d14c8STreehugger Robot
837*7c3d14c8STreehugger Robot struct StackDepotStats {
838*7c3d14c8STreehugger Robot uptr n_uniq_ids;
839*7c3d14c8STreehugger Robot uptr allocated;
840*7c3d14c8STreehugger Robot };
841*7c3d14c8STreehugger Robot
842*7c3d14c8STreehugger Robot #endif // SANITIZER_COMMON_H
843