diff options
Diffstat (limited to 'lib/sanitizer_common/sanitizer_common.h')
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 144 |
1 files changed, 111 insertions, 33 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index ff13ef164045..2c5a8dbe1238 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -23,8 +23,14 @@ #include "sanitizer_list.h" #include "sanitizer_mutex.h" +#ifdef _MSC_VER +extern "C" void _ReadWriteBarrier(); +#pragma intrinsic(_ReadWriteBarrier) +#endif + namespace __sanitizer { struct StackTrace; +struct AddressInfo; // Constants. const uptr kWordSize = SANITIZER_WORDSIZE / 8; @@ -38,8 +44,15 @@ const uptr kWordSizeInBits = 8 * kWordSize; const uptr kMaxPathLength = 4096; +// 16K loaded modules should be enough for everyone. +static const uptr kMaxNumberOfModules = 1 << 14; + const uptr kMaxThreadStackSize = 1 << 30; // 1Gb +// Denotes fake PC values that come from JIT/JAVA/etc. +// For such PC values __tsan_symbolize_external() will be called. +const u64 kExternalPCBit = 1ULL << 60; + extern const char *SanitizerToolName; // Can be changed by the tool. extern atomic_uint32_t current_verbosity; @@ -65,12 +78,17 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, // Memory management void *MmapOrDie(uptr size, const char *mem_type); void UnmapOrDie(void *addr, uptr size); -void *MmapFixedNoReserve(uptr fixed_addr, uptr size); +void *MmapFixedNoReserve(uptr fixed_addr, uptr size, + const char *name = nullptr); void *MmapNoReserveOrDie(uptr size, const char *mem_type); void *MmapFixedOrDie(uptr fixed_addr, uptr size); -void *Mprotect(uptr fixed_addr, uptr size); +void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr); // Map aligned chunk of address space; size and alignment are powers of two. void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type); +// Disallow access to a memory range. Use MmapNoAccess to allocate an +// unaccessible memory. +bool MprotectNoAccess(uptr addr, uptr size); + // Used to check if we can map shadow memory to a fixed location. bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); void FlushUnneededShadowMemory(uptr addr, uptr size); @@ -159,7 +177,7 @@ extern StaticSpinMutex CommonSanitizerReportMutex; struct ReportFile { void Write(const char *buffer, uptr length); - bool PrintsToTty(); + bool SupportsColors(); void SetReportPath(const char *path); // Don't use fields directly. They are only declared public to allow @@ -186,18 +204,39 @@ extern ReportFile report_file; extern uptr stoptheworld_tracer_pid; extern uptr stoptheworld_tracer_ppid; -uptr OpenFile(const char *filename, bool write); +enum FileAccessMode { + RdOnly, + WrOnly, + RdWr +}; + +// Returns kInvalidFd on error. +fd_t OpenFile(const char *filename, FileAccessMode mode, + error_t *errno_p = nullptr); +void CloseFile(fd_t); + +// Return true on success, false on error. +bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, + uptr *bytes_read = nullptr, error_t *error_p = nullptr); +bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, + uptr *bytes_written = nullptr, error_t *error_p = nullptr); + +bool RenameFile(const char *oldpath, const char *newpath, + error_t *error_p = nullptr); + +bool SupportsColoredOutput(fd_t fd); + // Opens the file 'file_name" and reads up to 'max_len' bytes. // The resulting buffer is mmaped and stored in '*buff'. // The size of the mmaped region is stored in '*buff_size', // Returns the number of read bytes or 0 if file can not be opened. uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, - uptr max_len, int *errno_p = nullptr); + uptr max_len, error_t *errno_p = nullptr); // Maps given file to virtual memory, and returns pointer to it -// (or NULL if the mapping failes). Stores the size of mmaped region +// (or NULL if mapping fails). Stores the size of mmaped region // in '*buff_size'. void *MapFileToMemory(const char *file_name, uptr *buff_size); -void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset); +void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset); bool IsAccessibleMemoryRange(uptr beg, uptr size); @@ -208,6 +247,10 @@ const char *StripPathPrefix(const char *filepath, const char *StripModuleName(const char *module); // OS +uptr ReadBinaryName(/*out*/char *buf, uptr buf_len); +uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len); +const char *GetBinaryBasename(); +void CacheBinaryName(); void DisableCoreDumperIfNecessary(); void DumpProcessMap(); bool FileExists(const char *filename); @@ -215,6 +258,9 @@ const char *GetEnv(const char *name); bool SetEnv(const char *name, const char *value); const char *GetPwd(); char *FindPathToBinary(const char *name); +bool IsPathSeparator(const char c); +bool IsAbsolutePath(const char *path); + u32 GetUid(); void ReExec(); bool StackSizeIsUnlimited(); @@ -288,9 +334,9 @@ const int kMaxSummaryLength = 1024; // and pass it to __sanitizer_report_error_summary. void ReportErrorSummary(const char *error_message); // Same as above, but construct error_message as: -// error_type file:line function -void ReportErrorSummary(const char *error_type, const char *file, - int line, const char *function); +// error_type file:line[:column][ function] +void ReportErrorSummary(const char *error_type, const AddressInfo &info); +// Same as above, but obtains AddressInfo by symbolizing top stack trace frame. void ReportErrorSummary(const char *error_type, StackTrace *trace); // Math @@ -309,7 +355,11 @@ INLINE uptr MostSignificantSetBitIndex(uptr x) { CHECK_NE(x, 0U); unsigned long up; // NOLINT #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) +# ifdef _WIN64 + up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x); +# else up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x); +# endif #elif defined(_WIN64) _BitScanReverse64(&up, x); #else @@ -322,7 +372,11 @@ INLINE uptr LeastSignificantSetBitIndex(uptr x) { CHECK_NE(x, 0U); unsigned long up; // NOLINT #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) +# ifdef _WIN64 + up = __builtin_ctzll(x); +# else up = __builtin_ctzl(x); +# endif #elif defined(_WIN64) _BitScanForward64(&up, x); #else @@ -342,7 +396,7 @@ INLINE uptr RoundUpToPowerOfTwo(uptr size) { uptr up = MostSignificantSetBitIndex(size); CHECK(size < (1ULL << (up + 1))); CHECK(size > (1ULL << up)); - return 1UL << (up + 1); + return 1ULL << (up + 1); } INLINE uptr RoundUpTo(uptr size, uptr boundary) { @@ -360,17 +414,7 @@ INLINE bool IsAligned(uptr a, uptr alignment) { INLINE uptr Log2(uptr x) { CHECK(IsPowerOfTwo(x)); -#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) - return __builtin_ctzl(x); -#elif defined(_WIN64) - unsigned long ret; // NOLINT - _BitScanForward64(&ret, x); - return ret; -#else - unsigned long ret; // NOLINT - _BitScanForward(&ret, x); - return ret; -#endif + return LeastSignificantSetBitIndex(x); } // Don't use std::min, std::max or std::swap, to minimize dependency @@ -439,11 +483,15 @@ class InternalMmapVectorNoCtor { const T *data() const { return data_; } + T *data() { + return data_; + } uptr capacity() const { return capacity_; } void clear() { size_ = 0; } + bool empty() const { return size() == 0; } private: void Resize(uptr new_capacity) { @@ -532,7 +580,8 @@ uptr InternalBinarySearch(const Container &v, uptr first, uptr last, // executable or a shared object). class LoadedModule { public: - LoadedModule(const char *module_name, uptr base_address); + LoadedModule() : full_name_(nullptr), base_address_(0) { ranges_.clear(); } + void set(const char *module_name, uptr base_address); void clear(); void addAddressRange(uptr beg, uptr end, bool executable); bool containsAddress(uptr address) const; @@ -567,28 +616,41 @@ typedef bool (*string_predicate_t)(const char *); uptr GetListOfModules(LoadedModule *modules, uptr max_modules, string_predicate_t filter); -#if SANITIZER_POSIX -const uptr kPthreadDestructorIterations = 4; -#else -// Unused on Windows. -const uptr kPthreadDestructorIterations = 0; -#endif - // Callback type for iterating over a set of memory ranges. typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg); +enum AndroidApiLevel { + ANDROID_NOT_ANDROID = 0, + ANDROID_KITKAT = 19, + ANDROID_LOLLIPOP_MR1 = 22, + ANDROID_POST_LOLLIPOP = 23 +}; + #if SANITIZER_ANDROID // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); void AndroidLogWrite(const char *buffer); void GetExtraActivationFlags(char *buf, uptr size); void SanitizerInitializeUnwinder(); +AndroidApiLevel AndroidGetApiLevel(); #else INLINE void AndroidLogInit() {} INLINE void AndroidLogWrite(const char *buffer_unused) {} INLINE void GetExtraActivationFlags(char *buf, uptr size) { *buf = '\0'; } INLINE void SanitizerInitializeUnwinder() {} +INLINE AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; } +#endif + +INLINE uptr GetPthreadDestructorIterations() { +#if SANITIZER_ANDROID + return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4; +#elif SANITIZER_POSIX + return 4; +#else +// Unused on Windows. + return 0; #endif +} void *internal_start_thread(void(*func)(void*), void *arg); void internal_join_thread(void *th); @@ -599,14 +661,30 @@ void MaybeStartBackgroudThread(); // compiler from recognising it and turning it into an actual call to // memset/memcpy/etc. static inline void SanitizerBreakOptimization(void *arg) { -#if _MSC_VER - // FIXME: make sure this is actually enough. - __asm; +#if _MSC_VER && !defined(__clang__) + _ReadWriteBarrier(); #else __asm__ __volatile__("" : : "r" (arg) : "memory"); #endif } +struct SignalContext { + void *context; + uptr addr; + uptr pc; + uptr sp; + uptr bp; + + SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) : + context(context), addr(addr), pc(pc), sp(sp), bp(bp) { + } + + // Creates signal context in a platform-specific manner. + static SignalContext Create(void *siginfo, void *context); +}; + +void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); + } // namespace __sanitizer inline void *operator new(__sanitizer::operator_new_size_type size, |