diff options
Diffstat (limited to 'lib/sanitizer_common/sanitizer_common.h')
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 214 |
1 files changed, 110 insertions, 104 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 1fbaee7e39a1..3b999edfbe58 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -39,11 +39,7 @@ struct StackTrace; const uptr kWordSize = SANITIZER_WORDSIZE / 8; const uptr kWordSizeInBits = 8 * kWordSize; -#if defined(__powerpc__) || defined(__powerpc64__) - const uptr kCacheLineSize = 128; -#else - const uptr kCacheLineSize = 64; -#endif +const uptr kCacheLineSize = SANITIZER_CACHE_LINE_SIZE; const uptr kMaxPathLength = 4096; @@ -52,7 +48,7 @@ const uptr kMaxThreadStackSize = 1 << 30; // 1Gb static const uptr kErrorMessageBufferSize = 1 << 16; // Denotes fake PC values that come from JIT/JAVA/etc. -// For such PC values __tsan_symbolize_external() will be called. +// For such PC values __tsan_symbolize_external_ex() will be called. const u64 kExternalPCBit = 1ULL << 60; extern const char *SanitizerToolName; // Can be changed by the tool. @@ -92,8 +88,8 @@ void UnmapOrDie(void *addr, uptr size); // Behaves just like MmapOrDie, but tolerates out of memory condition, in that // case returns nullptr. void *MmapOrDieOnFatalError(uptr size, const char *mem_type); -void *MmapFixedNoReserve(uptr fixed_addr, uptr size, - const char *name = nullptr); +bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr) + WARN_UNUSED_RESULT; void *MmapNoReserveOrDie(uptr size, const char *mem_type); void *MmapFixedOrDie(uptr fixed_addr, uptr size); // Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in @@ -110,9 +106,11 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, bool MprotectNoAccess(uptr addr, uptr size); bool MprotectReadOnly(uptr addr, uptr size); +void MprotectMallocZones(void *addr, int prot); + // Find an available address space. uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, - uptr *largest_gap_found); + uptr *largest_gap_found, uptr *max_occupied_addr); // Used to check if we can map shadow memory to a fixed location. bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); @@ -122,8 +120,8 @@ void ReleaseMemoryPagesToOS(uptr beg, uptr end); void IncreaseTotalMmap(uptr size); void DecreaseTotalMmap(uptr size); uptr GetRSS(); -void NoHugePagesInRegion(uptr addr, uptr length); -void DontDumpShadowMemory(uptr addr, uptr length); +bool NoHugePagesInRegion(uptr addr, uptr length); +bool DontDumpShadowMemory(uptr addr, uptr length); // Check if the built VMA size matches the runtime one. void CheckVMASize(); void RunMallocHooks(const void *ptr, uptr size); @@ -153,49 +151,6 @@ typedef void (*fill_profile_f)(uptr start, uptr rss, bool file, // |stats_size| elements. void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size); -// InternalScopedBuffer can be used instead of large stack arrays to -// keep frame size low. -// FIXME: use InternalAlloc instead of MmapOrDie once -// InternalAlloc is made libc-free. -template <typename T> -class InternalScopedBuffer { - public: - explicit InternalScopedBuffer(uptr cnt) { - cnt_ = cnt; - ptr_ = (T *)MmapOrDie(cnt * sizeof(T), "InternalScopedBuffer"); - } - ~InternalScopedBuffer() { UnmapOrDie(ptr_, cnt_ * sizeof(T)); } - T &operator[](uptr i) { return ptr_[i]; } - T *data() { return ptr_; } - uptr size() { return cnt_ * sizeof(T); } - - private: - T *ptr_; - uptr cnt_; - // Disallow copies and moves. - InternalScopedBuffer(const InternalScopedBuffer &) = delete; - InternalScopedBuffer &operator=(const InternalScopedBuffer &) = delete; - InternalScopedBuffer(InternalScopedBuffer &&) = delete; - InternalScopedBuffer &operator=(InternalScopedBuffer &&) = delete; -}; - -class InternalScopedString : public InternalScopedBuffer<char> { - public: - explicit InternalScopedString(uptr max_length) - : InternalScopedBuffer<char>(max_length), length_(0) { - (*this)[0] = '\0'; - } - uptr length() { return length_; } - void clear() { - (*this)[0] = '\0'; - length_ = 0; - } - void append(const char *format, ...); - - private: - uptr length_; -}; - // Simple low-level (mmap-based) allocator for internal use. Doesn't have // constructor, so all instances of LowLevelAllocator should be // linker initialized. @@ -243,15 +198,6 @@ class ScopedErrorReportLock { extern uptr stoptheworld_tracer_pid; extern uptr stoptheworld_tracer_ppid; -// 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'. -// The total number of read bytes is stored in '*read_len'. -// Returns true if file was successfully opened and read. -bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, - uptr *read_len, uptr max_len = 1 << 26, - error_t *errno_p = nullptr); - bool IsAccessibleMemoryRange(uptr beg, uptr size); // Error report formatting. @@ -275,6 +221,7 @@ bool SetEnv(const char *name, const char *value); u32 GetUid(); void ReExec(); +void CheckASLR(); char **GetArgv(); void PrintCmdline(); bool StackSizeIsUnlimited(); @@ -283,7 +230,7 @@ void SetStackSizeLimitInBytes(uptr limit); bool AddressSpaceIsUnlimited(); void SetAddressSpaceUnlimited(); void AdjustStackSize(void *attr); -void PrepareForSandboxing(__sanitizer_sandbox_arguments *args); +void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args); void SetSandboxingCallback(void (*f)()); void InitializeCoverage(bool enabled, const char *coverage_dir); @@ -297,8 +244,6 @@ void SleepForMillis(int millis); u64 NanoTime(); u64 MonotonicNanoTime(); int Atexit(void (*function)(void)); -void SortArray(uptr *array, uptr size); -void SortArray(u32 *array, uptr size); bool TemplateMatch(const char *templ, const char *str); // Exit @@ -310,13 +255,6 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, const char *mmap_type, error_t err, bool raw_report = false); -// Set the name of the current thread to 'name', return true on succees. -// The name may be truncated to a system-dependent limit. -bool SanitizerSetThreadName(const char *name); -// Get the name of the current thread (no more than max_len bytes), -// return true on succees. name should have space for at least max_len+1 bytes. -bool SanitizerGetThreadName(char *name, int max_len); - // Specific tools may override behavior of "Die" and "CheckFailed" functions // to do tool-specific job. typedef void (*DieCallbackType)(void); @@ -382,6 +320,8 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info, void ReportErrorSummary(const char *error_type, const StackTrace *trace, const char *alt_tool_name = nullptr); +void ReportMmapWriteExec(int prot); + // Math #if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__) extern "C" { @@ -489,13 +429,12 @@ template<typename T> class InternalMmapVectorNoCtor { public: void Initialize(uptr initial_capacity) { - capacity_ = Max(initial_capacity, (uptr)1); + capacity_bytes_ = 0; size_ = 0; - data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVectorNoCtor"); - } - void Destroy() { - UnmapOrDie(data_, capacity_ * sizeof(T)); + data_ = 0; + reserve(initial_capacity); } + void Destroy() { UnmapOrDie(data_, capacity_bytes_); } T &operator[](uptr i) { CHECK_LT(i, size_); return data_[i]; @@ -505,10 +444,10 @@ class InternalMmapVectorNoCtor { return data_[i]; } void push_back(const T &element) { - CHECK_LE(size_, capacity_); - if (size_ == capacity_) { + CHECK_LE(size_, capacity()); + if (size_ == capacity()) { uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1); - Resize(new_capacity); + Realloc(new_capacity); } internal_memcpy(&data_[size_++], &element, sizeof(T)); } @@ -529,12 +468,15 @@ class InternalMmapVectorNoCtor { T *data() { return data_; } - uptr capacity() const { - return capacity_; + uptr capacity() const { return capacity_bytes_ / sizeof(T); } + void reserve(uptr new_size) { + // Never downsize internal buffer. + if (new_size > capacity()) + Realloc(new_size); } void resize(uptr new_size) { - Resize(new_size); if (new_size > size_) { + reserve(new_size); internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_)); } size_ = new_size; @@ -556,39 +498,84 @@ class InternalMmapVectorNoCtor { return data() + size(); } + void swap(InternalMmapVectorNoCtor &other) { + Swap(data_, other.data_); + Swap(capacity_bytes_, other.capacity_bytes_); + Swap(size_, other.size_); + } + private: - void Resize(uptr new_capacity) { + void Realloc(uptr new_capacity) { CHECK_GT(new_capacity, 0); CHECK_LE(size_, new_capacity); - T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T), - "InternalMmapVector"); + uptr new_capacity_bytes = + RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached()); + T *new_data = (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector"); internal_memcpy(new_data, data_, size_ * sizeof(T)); - T *old_data = data_; + UnmapOrDie(data_, capacity_bytes_); data_ = new_data; - UnmapOrDie(old_data, capacity_ * sizeof(T)); - capacity_ = new_capacity; + capacity_bytes_ = new_capacity_bytes; } T *data_; - uptr capacity_; + uptr capacity_bytes_; uptr size_; }; +template <typename T> +bool operator==(const InternalMmapVectorNoCtor<T> &lhs, + const InternalMmapVectorNoCtor<T> &rhs) { + if (lhs.size() != rhs.size()) return false; + return internal_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0; +} + +template <typename T> +bool operator!=(const InternalMmapVectorNoCtor<T> &lhs, + const InternalMmapVectorNoCtor<T> &rhs) { + return !(lhs == rhs); +} + template<typename T> class InternalMmapVector : public InternalMmapVectorNoCtor<T> { public: - explicit InternalMmapVector(uptr initial_capacity) { - InternalMmapVectorNoCtor<T>::Initialize(initial_capacity); + InternalMmapVector() { InternalMmapVectorNoCtor<T>::Initialize(1); } + explicit InternalMmapVector(uptr cnt) { + InternalMmapVectorNoCtor<T>::Initialize(cnt); + this->resize(cnt); } ~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); } - // Disallow evil constructors. - InternalMmapVector(const InternalMmapVector&); - void operator=(const InternalMmapVector&); + // Disallow copies and moves. + InternalMmapVector(const InternalMmapVector &) = delete; + InternalMmapVector &operator=(const InternalMmapVector &) = delete; + InternalMmapVector(InternalMmapVector &&) = delete; + InternalMmapVector &operator=(InternalMmapVector &&) = delete; +}; + +class InternalScopedString : public InternalMmapVector<char> { + public: + explicit InternalScopedString(uptr max_length) + : InternalMmapVector<char>(max_length), length_(0) { + (*this)[0] = '\0'; + } + uptr length() { return length_; } + void clear() { + (*this)[0] = '\0'; + length_ = 0; + } + void append(const char *format, ...); + + private: + uptr length_; +}; + +template <class T> +struct CompareLess { + bool operator()(const T &a, const T &b) const { return a < b; } }; // HeapSort for arrays and InternalMmapVector. -template<class Container, class Compare> -void InternalSort(Container *v, uptr size, Compare comp) { +template <class T, class Compare = CompareLess<T>> +void Sort(T *v, uptr size, Compare comp = {}) { if (size < 2) return; // Stage 1: insert elements to the heap. @@ -596,8 +583,8 @@ void InternalSort(Container *v, uptr size, Compare comp) { uptr j, p; for (j = i; j > 0; j = p) { p = (j - 1) / 2; - if (comp((*v)[p], (*v)[j])) - Swap((*v)[j], (*v)[p]); + if (comp(v[p], v[j])) + Swap(v[j], v[p]); else break; } @@ -605,18 +592,18 @@ void InternalSort(Container *v, uptr size, Compare comp) { // Stage 2: swap largest element with the last one, // and sink the new top. for (uptr i = size - 1; i > 0; i--) { - Swap((*v)[0], (*v)[i]); + Swap(v[0], v[i]); uptr j, max_ind; for (j = 0; j < i; j = max_ind) { uptr left = 2 * j + 1; uptr right = 2 * j + 2; max_ind = j; - if (left < i && comp((*v)[max_ind], (*v)[left])) + if (left < i && comp(v[max_ind], v[left])) max_ind = left; - if (right < i && comp((*v)[max_ind], (*v)[right])) + if (right < i && comp(v[max_ind], v[right])) max_ind = right; if (max_ind != j) - Swap((*v)[j], (*v)[max_ind]); + Swap(v[j], v[max_ind]); else break; } @@ -650,6 +637,25 @@ enum ModuleArch { kModuleArchARM64 }; +// Opens the file 'file_name" and reads up to 'max_len' bytes. +// The resulting buffer is mmaped and stored in '*buff'. +// Returns true if file was successfully opened and read. +bool ReadFileToVector(const char *file_name, + InternalMmapVectorNoCtor<char> *buff, + uptr max_len = 1 << 26, error_t *errno_p = nullptr); + +// Opens the file 'file_name" and reads up to 'max_len' bytes. +// This function is less I/O efficient than ReadFileToVector as it may reread +// file multiple times to avoid mmap during read attempts. It's used to read +// procmap, so short reads with mmap in between can produce inconsistent result. +// The resulting buffer is mmaped and stored in '*buff'. +// The size of the mmaped region is stored in '*buff_size'. +// The total number of read bytes is stored in '*read_len'. +// Returns true if file was successfully opened and read. +bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, + uptr *read_len, uptr max_len = 1 << 26, + error_t *errno_p = nullptr); + // When adding a new architecture, don't forget to also update // script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cc. inline const char *ModuleArchToString(ModuleArch arch) { |