123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- //===-- sanitizer_common.h --------------------------------------*- C++ -*-===//
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is shared between AddressSanitizer and ThreadSanitizer
- // run-time libraries.
- // It declares common functions and classes that are used in both runtimes.
- // Implementation of some functions are provided in sanitizer_common, while
- // others must be defined by run-time library itself.
- //===----------------------------------------------------------------------===//
- #ifndef SANITIZER_COMMON_H
- #define SANITIZER_COMMON_H
- #include "sanitizer_internal_defs.h"
- #include "sanitizer_libc.h"
- #include "sanitizer_mutex.h"
- #include "sanitizer_flags.h"
- namespace __sanitizer {
- struct StackTrace;
- // Constants.
- 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 kMaxPathLength = 512;
- const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
- extern const char *SanitizerToolName; // Can be changed by the tool.
- uptr GetPageSize();
- uptr GetPageSizeCached();
- uptr GetMmapGranularity();
- uptr GetMaxVirtualAddress();
- // Threads
- uptr GetTid();
- uptr GetThreadSelf();
- void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
- uptr *stack_bottom);
- void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
- uptr *tls_addr, uptr *tls_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 *MmapNoReserveOrDie(uptr size, const char *mem_type);
- void *MmapFixedOrDie(uptr fixed_addr, uptr size);
- void *Mprotect(uptr fixed_addr, uptr size);
- // Map aligned chunk of address space; size and alignment are powers of two.
- void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
- // 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);
- void IncreaseTotalMmap(uptr size);
- void DecreaseTotalMmap(uptr 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 evil constructors.
- InternalScopedBuffer(const InternalScopedBuffer&);
- void operator=(const InternalScopedBuffer&);
- };
- 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.
- class LowLevelAllocator {
- public:
- // Requires an external lock.
- void *Allocate(uptr size);
- private:
- char *allocated_end_;
- char *allocated_current_;
- };
- typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
- // Allows to register tool-specific callbacks for LowLevelAllocator.
- // Passing NULL removes the callback.
- void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
- // IO
- void RawWrite(const char *buffer);
- bool PrintsToTty();
- // Caching version of PrintsToTty(). Not thread-safe.
- bool PrintsToTtyCached();
- bool ColorizeReports();
- void Printf(const char *format, ...);
- void Report(const char *format, ...);
- void SetPrintfAndReportCallback(void (*callback)(const char *));
- #define VReport(level, ...) \
- do { \
- if ((uptr)common_flags()->verbosity >= (level)) Report(__VA_ARGS__); \
- } while (0)
- #define VPrintf(level, ...) \
- do { \
- if ((uptr)common_flags()->verbosity >= (level)) Printf(__VA_ARGS__); \
- } while (0)
- // Can be used to prevent mixing error reports from different sanitizers.
- extern StaticSpinMutex CommonSanitizerReportMutex;
- void MaybeOpenReportFile();
- extern fd_t report_fd;
- extern bool log_to_file;
- extern char report_path_prefix[4096];
- extern uptr report_fd_pid;
- extern uptr stoptheworld_tracer_pid;
- extern uptr stoptheworld_tracer_ppid;
- uptr OpenFile(const char *filename, bool write);
- // 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);
- // Maps given file to virtual memory, and returns pointer to it
- // (or NULL if the mapping failes). 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);
- bool IsAccessibleMemoryRange(uptr beg, uptr size);
- // Error report formatting.
- const char *StripPathPrefix(const char *filepath,
- const char *strip_file_prefix);
- // Strip the directories from the module name.
- const char *StripModuleName(const char *module);
- // OS
- void DisableCoreDumperIfNecessary();
- void DumpProcessMap();
- bool FileExists(const char *filename);
- const char *GetEnv(const char *name);
- bool SetEnv(const char *name, const char *value);
- const char *GetPwd();
- char *FindPathToBinary(const char *name);
- u32 GetUid();
- void ReExec();
- bool StackSizeIsUnlimited();
- void SetStackSizeLimitInBytes(uptr limit);
- bool AddressSpaceIsUnlimited();
- void SetAddressSpaceUnlimited();
- void AdjustStackSize(void *attr);
- void PrepareForSandboxing(__sanitizer_sandbox_arguments *args);
- void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
- void SetSandboxingCallback(void (*f)());
- void CovUpdateMapping(uptr caller_pc = 0);
- void CovBeforeFork();
- void CovAfterFork(int child_pid);
- void InitTlsSize();
- uptr GetTlsSize();
- // Other
- void SleepForSeconds(int seconds);
- void SleepForMillis(int millis);
- u64 NanoTime();
- int Atexit(void (*function)(void));
- void SortArray(uptr *array, uptr size);
- // Exit
- void NORETURN Abort();
- void NORETURN Die();
- void NORETURN
- CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
- // 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);
- void SetDieCallback(DieCallbackType);
- DieCallbackType GetDieCallback();
- typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
- u64, u64);
- void SetCheckFailedCallback(CheckFailedCallbackType callback);
- // Functions related to signal handling.
- typedef void (*SignalHandlerType)(int, void *, void *);
- bool IsDeadlySignal(int signum);
- void InstallDeadlySignalHandlers(SignalHandlerType handler);
- // Alternative signal stack (POSIX-only).
- void SetAlternateSignalStack();
- void UnsetAlternateSignalStack();
- // We don't want a summary too long.
- const int kMaxSummaryLength = 1024;
- // Construct a one-line string:
- // SUMMARY: SanitizerToolName: error_message
- // 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);
- void ReportErrorSummary(const char *error_type, StackTrace *trace);
- // Math
- #if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
- extern "C" {
- unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT
- unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT
- #if defined(_WIN64)
- unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT
- unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT
- #endif
- }
- #endif
- INLINE uptr MostSignificantSetBitIndex(uptr x) {
- CHECK_NE(x, 0U);
- unsigned long up; // NOLINT
- #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
- up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
- #elif defined(_WIN64)
- _BitScanReverse64(&up, x);
- #else
- _BitScanReverse(&up, x);
- #endif
- return up;
- }
- INLINE uptr LeastSignificantSetBitIndex(uptr x) {
- CHECK_NE(x, 0U);
- unsigned long up; // NOLINT
- #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
- up = __builtin_ctzl(x);
- #elif defined(_WIN64)
- _BitScanForward64(&up, x);
- #else
- _BitScanForward(&up, x);
- #endif
- return up;
- }
- INLINE bool IsPowerOfTwo(uptr x) {
- return (x & (x - 1)) == 0;
- }
- INLINE uptr RoundUpToPowerOfTwo(uptr size) {
- CHECK(size);
- if (IsPowerOfTwo(size)) return size;
- uptr up = MostSignificantSetBitIndex(size);
- CHECK(size < (1ULL << (up + 1)));
- CHECK(size > (1ULL << up));
- return 1UL << (up + 1);
- }
- INLINE uptr RoundUpTo(uptr size, uptr boundary) {
- CHECK(IsPowerOfTwo(boundary));
- return (size + boundary - 1) & ~(boundary - 1);
- }
- INLINE uptr RoundDownTo(uptr x, uptr boundary) {
- return x & ~(boundary - 1);
- }
- INLINE bool IsAligned(uptr a, uptr alignment) {
- return (a & (alignment - 1)) == 0;
- }
- 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
- }
- // Don't use std::min, std::max or std::swap, to minimize dependency
- // on libstdc++.
- template<class T> T Min(T a, T b) { return a < b ? a : b; }
- template<class T> T Max(T a, T b) { return a > b ? a : b; }
- template<class T> void Swap(T& a, T& b) {
- T tmp = a;
- a = b;
- b = tmp;
- }
- // Char handling
- INLINE bool IsSpace(int c) {
- return (c == ' ') || (c == '\n') || (c == '\t') ||
- (c == '\f') || (c == '\r') || (c == '\v');
- }
- INLINE bool IsDigit(int c) {
- return (c >= '0') && (c <= '9');
- }
- INLINE int ToLower(int c) {
- return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
- }
- // A low-level vector based on mmap. May incur a significant memory overhead for
- // small vectors.
- // WARNING: The current implementation supports only POD types.
- template<typename T>
- class InternalMmapVector {
- public:
- explicit InternalMmapVector(uptr initial_capacity) {
- capacity_ = Max(initial_capacity, (uptr)1);
- size_ = 0;
- data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVector");
- }
- ~InternalMmapVector() {
- UnmapOrDie(data_, capacity_ * sizeof(T));
- }
- T &operator[](uptr i) {
- CHECK_LT(i, size_);
- return data_[i];
- }
- const T &operator[](uptr i) const {
- CHECK_LT(i, size_);
- return data_[i];
- }
- void push_back(const T &element) {
- CHECK_LE(size_, capacity_);
- if (size_ == capacity_) {
- uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
- Resize(new_capacity);
- }
- data_[size_++] = element;
- }
- T &back() {
- CHECK_GT(size_, 0);
- return data_[size_ - 1];
- }
- void pop_back() {
- CHECK_GT(size_, 0);
- size_--;
- }
- uptr size() const {
- return size_;
- }
- const T *data() const {
- return data_;
- }
- uptr capacity() const {
- return capacity_;
- }
- void clear() { size_ = 0; }
- private:
- void Resize(uptr new_capacity) {
- CHECK_GT(new_capacity, 0);
- CHECK_LE(size_, new_capacity);
- T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T),
- "InternalMmapVector");
- internal_memcpy(new_data, data_, size_ * sizeof(T));
- T *old_data = data_;
- data_ = new_data;
- UnmapOrDie(old_data, capacity_ * sizeof(T));
- capacity_ = new_capacity;
- }
- // Disallow evil constructors.
- InternalMmapVector(const InternalMmapVector&);
- void operator=(const InternalMmapVector&);
- T *data_;
- uptr capacity_;
- uptr size_;
- };
- // HeapSort for arrays and InternalMmapVector.
- template<class Container, class Compare>
- void InternalSort(Container *v, uptr size, Compare comp) {
- if (size < 2)
- return;
- // Stage 1: insert elements to the heap.
- for (uptr i = 1; i < size; i++) {
- 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]);
- else
- break;
- }
- }
- // 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]);
- 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]))
- max_ind = left;
- if (right < i && comp((*v)[max_ind], (*v)[right]))
- max_ind = right;
- if (max_ind != j)
- Swap((*v)[j], (*v)[max_ind]);
- else
- break;
- }
- }
- }
- template<class Container, class Value, class Compare>
- uptr InternalBinarySearch(const Container &v, uptr first, uptr last,
- const Value &val, Compare comp) {
- uptr not_found = last + 1;
- while (last >= first) {
- uptr mid = (first + last) / 2;
- if (comp(v[mid], val))
- first = mid + 1;
- else if (comp(val, v[mid]))
- last = mid - 1;
- else
- return mid;
- }
- return not_found;
- }
- // Represents a binary loaded into virtual memory (e.g. this can be an
- // executable or a shared object).
- class LoadedModule {
- public:
- LoadedModule(const char *module_name, uptr base_address);
- void addAddressRange(uptr beg, uptr end, bool executable);
- bool containsAddress(uptr address) const;
- const char *full_name() const { return full_name_; }
- uptr base_address() const { return base_address_; }
- uptr n_ranges() const { return n_ranges_; }
- uptr address_range_start(int i) const { return ranges_[i].beg; }
- uptr address_range_end(int i) const { return ranges_[i].end; }
- bool address_range_executable(int i) const { return exec_[i]; }
- private:
- struct AddressRange {
- uptr beg;
- uptr end;
- };
- char *full_name_;
- uptr base_address_;
- static const uptr kMaxNumberOfAddressRanges = 6;
- AddressRange ranges_[kMaxNumberOfAddressRanges];
- bool exec_[kMaxNumberOfAddressRanges];
- uptr n_ranges_;
- };
- // OS-dependent function that fills array with descriptions of at most
- // "max_modules" currently loaded modules. Returns the number of
- // initialized modules. If filter is nonzero, ignores modules for which
- // filter(full_name) is false.
- 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);
- #if (SANITIZER_FREEBSD || SANITIZER_LINUX) && !defined(SANITIZER_GO)
- extern uptr indirect_call_wrapper;
- void SetIndirectCallWrapper(uptr wrapper);
- template <typename F>
- F IndirectExternCall(F f) {
- typedef F (*WrapF)(F);
- return indirect_call_wrapper ? ((WrapF)indirect_call_wrapper)(f) : f;
- }
- #else
- INLINE void SetIndirectCallWrapper(uptr wrapper) {}
- template <typename F>
- F IndirectExternCall(F f) {
- return f;
- }
- #endif
- #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();
- #else
- INLINE void AndroidLogInit() {}
- INLINE void AndroidLogWrite(const char *buffer_unused) {}
- INLINE void GetExtraActivationFlags(char *buf, uptr size) { *buf = '\0'; }
- INLINE void SanitizerInitializeUnwinder() {}
- #endif
- } // namespace __sanitizer
- inline void *operator new(__sanitizer::operator_new_size_type size,
- __sanitizer::LowLevelAllocator &alloc) {
- return alloc.Allocate(size);
- }
- struct StackDepotStats {
- uptr n_uniq_ids;
- uptr allocated;
- };
- #endif // SANITIZER_COMMON_H
|