Path: blob/main/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h
35233 views
//===-- sanitizer_common.h --------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is shared between run-time libraries of sanitizers.9//10// It declares common functions and classes that are used in both runtimes.11// Implementation of some functions are provided in sanitizer_common, while12// others must be defined by run-time library itself.13//===----------------------------------------------------------------------===//14#ifndef SANITIZER_COMMON_H15#define SANITIZER_COMMON_H1617#include "sanitizer_flags.h"18#include "sanitizer_internal_defs.h"19#include "sanitizer_libc.h"20#include "sanitizer_list.h"21#include "sanitizer_mutex.h"2223#if defined(_MSC_VER) && !defined(__clang__)24extern "C" void _ReadWriteBarrier();25#pragma intrinsic(_ReadWriteBarrier)26#endif2728namespace __sanitizer {2930struct AddressInfo;31struct BufferedStackTrace;32struct SignalContext;33struct StackTrace;34struct SymbolizedStack;3536// Constants.37const uptr kWordSize = SANITIZER_WORDSIZE / 8;38const uptr kWordSizeInBits = 8 * kWordSize;3940const uptr kCacheLineSize = SANITIZER_CACHE_LINE_SIZE;4142const uptr kMaxPathLength = 4096;4344const uptr kMaxThreadStackSize = 1 << 30; // 1Gb4546const uptr kErrorMessageBufferSize = 1 << 16;4748// Denotes fake PC values that come from JIT/JAVA/etc.49// For such PC values __tsan_symbolize_external_ex() will be called.50const u64 kExternalPCBit = 1ULL << 60;5152extern const char *SanitizerToolName; // Can be changed by the tool.5354extern atomic_uint32_t current_verbosity;55inline void SetVerbosity(int verbosity) {56atomic_store(¤t_verbosity, verbosity, memory_order_relaxed);57}58inline int Verbosity() {59return atomic_load(¤t_verbosity, memory_order_relaxed);60}6162#if SANITIZER_ANDROID && !defined(__aarch64__)63// 32-bit Android only has 4k pages.64inline uptr GetPageSize() { return 4096; }65inline uptr GetPageSizeCached() { return 4096; }66#else67uptr GetPageSize();68extern uptr PageSizeCached;69inline uptr GetPageSizeCached() {70if (!PageSizeCached)71PageSizeCached = GetPageSize();72return PageSizeCached;73}74#endif7576uptr GetMmapGranularity();77uptr GetMaxVirtualAddress();78uptr GetMaxUserVirtualAddress();79// Threads80tid_t GetTid();81int TgKill(pid_t pid, tid_t tid, int sig);82uptr GetThreadSelf();83void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,84uptr *stack_bottom);85void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,86uptr *tls_addr, uptr *tls_size);8788// Memory management89void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);9091inline void *MmapOrDieQuietly(uptr size, const char *mem_type) {92return MmapOrDie(size, mem_type, /*raw_report*/ true);93}94void UnmapOrDie(void *addr, uptr size, bool raw_report = false);95// Behaves just like MmapOrDie, but tolerates out of memory condition, in that96// case returns nullptr.97void *MmapOrDieOnFatalError(uptr size, const char *mem_type);98bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)99WARN_UNUSED_RESULT;100bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size,101const char *name = nullptr) WARN_UNUSED_RESULT;102void *MmapNoReserveOrDie(uptr size, const char *mem_type);103void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);104// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in105// that case returns nullptr.106void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size,107const char *name = nullptr);108void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);109void *MmapNoAccess(uptr size);110// Map aligned chunk of address space; size and alignment are powers of two.111// Dies on all but out of memory errors, in the latter case returns nullptr.112void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,113const char *mem_type);114// Disallow access to a memory range. Use MmapFixedNoAccess to allocate an115// unaccessible memory.116bool MprotectNoAccess(uptr addr, uptr size);117bool MprotectReadOnly(uptr addr, uptr size);118bool MprotectReadWrite(uptr addr, uptr size);119120void MprotectMallocZones(void *addr, int prot);121122#if SANITIZER_WINDOWS123// Zero previously mmap'd memory. Currently used only on Windows.124bool ZeroMmapFixedRegion(uptr fixed_addr, uptr size) WARN_UNUSED_RESULT;125#endif126127#if SANITIZER_LINUX128// Unmap memory. Currently only used on Linux.129void UnmapFromTo(uptr from, uptr to);130#endif131132// Maps shadow_size_bytes of shadow memory and returns shadow address. It will133// be aligned to the mmap granularity * 2^shadow_scale, or to134// 2^min_shadow_base_alignment if that is larger. The returned address will135// have max(2^min_shadow_base_alignment, mmap granularity) on the left, and136// shadow_size_bytes bytes on the right, which on linux is mapped no access.137// The high_mem_end may be updated if the original shadow size doesn't fit.138uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,139uptr min_shadow_base_alignment, uptr &high_mem_end,140uptr granularity);141142// Let S = max(shadow_size, num_aliases * alias_size, ring_buffer_size).143// Reserves 2*S bytes of address space to the right of the returned address and144// ring_buffer_size bytes to the left. The returned address is aligned to 2*S.145// Also creates num_aliases regions of accessible memory starting at offset S146// from the returned address. Each region has size alias_size and is backed by147// the same physical memory.148uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,149uptr num_aliases, uptr ring_buffer_size);150151// Reserve memory range [beg, end]. If madvise_shadow is true then apply152// madvise (e.g. hugepages, core dumping) requested by options.153void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,154bool madvise_shadow = true);155156// Protect size bytes of memory starting at addr. Also try to protect157// several pages at the start of the address space as specified by158// zero_base_shadow_start, at most up to the size or zero_base_max_shadow_start.159void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start,160uptr zero_base_max_shadow_start);161162// Find an available address space.163uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,164uptr *largest_gap_found, uptr *max_occupied_addr);165166// Used to check if we can map shadow memory to a fixed location.167bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);168// Releases memory pages entirely within the [beg, end] address range. Noop if169// the provided range does not contain at least one entire page.170void ReleaseMemoryPagesToOS(uptr beg, uptr end);171void IncreaseTotalMmap(uptr size);172void DecreaseTotalMmap(uptr size);173uptr GetRSS();174void SetShadowRegionHugePageMode(uptr addr, uptr length);175bool DontDumpShadowMemory(uptr addr, uptr length);176// Check if the built VMA size matches the runtime one.177void CheckVMASize();178void RunMallocHooks(void *ptr, uptr size);179int RunFreeHooks(void *ptr);180181class ReservedAddressRange {182public:183uptr Init(uptr size, const char *name = nullptr, uptr fixed_addr = 0);184uptr InitAligned(uptr size, uptr align, const char *name = nullptr);185uptr Map(uptr fixed_addr, uptr size, const char *name = nullptr);186uptr MapOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);187void Unmap(uptr addr, uptr size);188void *base() const { return base_; }189uptr size() const { return size_; }190191private:192void* base_;193uptr size_;194const char* name_;195uptr os_handle_;196};197198typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,199/*out*/ uptr *stats);200201// Parse the contents of /proc/self/smaps and generate a memory profile.202// |cb| is a tool-specific callback that fills the |stats| array.203void GetMemoryProfile(fill_profile_f cb, uptr *stats);204void ParseUnixMemoryProfile(fill_profile_f cb, uptr *stats, char *smaps,205uptr smaps_len);206207// Simple low-level (mmap-based) allocator for internal use. Doesn't have208// constructor, so all instances of LowLevelAllocator should be209// linker initialized.210//211// NOTE: Users should instead use the singleton provided via212// `GetGlobalLowLevelAllocator()` rather than create a new one. This way, the213// number of mmap fragments can be reduced and use the same contiguous mmap214// provided by this singleton.215class LowLevelAllocator {216public:217// Requires an external lock.218void *Allocate(uptr size);219220private:221char *allocated_end_;222char *allocated_current_;223};224// Set the min alignment of LowLevelAllocator to at least alignment.225void SetLowLevelAllocateMinAlignment(uptr alignment);226typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);227// Allows to register tool-specific callbacks for LowLevelAllocator.228// Passing NULL removes the callback.229void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);230231LowLevelAllocator &GetGlobalLowLevelAllocator();232233// IO234void CatastrophicErrorWrite(const char *buffer, uptr length);235void RawWrite(const char *buffer);236bool ColorizeReports();237void RemoveANSIEscapeSequencesFromString(char *buffer);238void Printf(const char *format, ...) FORMAT(1, 2);239void Report(const char *format, ...) FORMAT(1, 2);240void SetPrintfAndReportCallback(void (*callback)(const char *));241#define VReport(level, ...) \242do { \243if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \244} while (0)245#define VPrintf(level, ...) \246do { \247if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \248} while (0)249250// Lock sanitizer error reporting and protects against nested errors.251class ScopedErrorReportLock {252public:253ScopedErrorReportLock() SANITIZER_ACQUIRE(mutex_) { Lock(); }254~ScopedErrorReportLock() SANITIZER_RELEASE(mutex_) { Unlock(); }255256static void Lock() SANITIZER_ACQUIRE(mutex_);257static void Unlock() SANITIZER_RELEASE(mutex_);258static void CheckLocked() SANITIZER_CHECK_LOCKED(mutex_);259260private:261static atomic_uintptr_t reporting_thread_;262static StaticSpinMutex mutex_;263};264265extern uptr stoptheworld_tracer_pid;266extern uptr stoptheworld_tracer_ppid;267268bool IsAccessibleMemoryRange(uptr beg, uptr size);269270// Error report formatting.271const char *StripPathPrefix(const char *filepath,272const char *strip_file_prefix);273// Strip the directories from the module name.274const char *StripModuleName(const char *module);275276// OS277uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);278uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);279uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len);280uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);281const char *GetProcessName();282void UpdateProcessName();283void CacheBinaryName();284void DisableCoreDumperIfNecessary();285void DumpProcessMap();286const char *GetEnv(const char *name);287bool SetEnv(const char *name, const char *value);288289u32 GetUid();290void ReExec();291void CheckASLR();292void CheckMPROTECT();293char **GetArgv();294char **GetEnviron();295void PrintCmdline();296bool StackSizeIsUnlimited();297void SetStackSizeLimitInBytes(uptr limit);298bool AddressSpaceIsUnlimited();299void SetAddressSpaceUnlimited();300void AdjustStackSize(void *attr);301void PlatformPrepareForSandboxing(void *args);302void SetSandboxingCallback(void (*f)());303304void InitializeCoverage(bool enabled, const char *coverage_dir);305306void InitTlsSize();307uptr GetTlsSize();308309// Other310void WaitForDebugger(unsigned seconds, const char *label);311void SleepForSeconds(unsigned seconds);312void SleepForMillis(unsigned millis);313u64 NanoTime();314u64 MonotonicNanoTime();315int Atexit(void (*function)(void));316bool TemplateMatch(const char *templ, const char *str);317318// Exit319void NORETURN Abort();320void NORETURN Die();321void NORETURN322CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);323void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,324const char *mmap_type, error_t err,325bool raw_report = false);326void NORETURN ReportMunmapFailureAndDie(void *ptr, uptr size, error_t err,327bool raw_report = false);328329// Returns true if the platform-specific error reported is an OOM error.330bool ErrorIsOOM(error_t err);331332// This reports an error in the form:333//334// `ERROR: {{SanitizerToolName}}: out of memory: {{err_msg}}`335//336// Downstream tools that read sanitizer output will know that errors starting337// in this format are specifically OOM errors.338#define ERROR_OOM(err_msg, ...) \339Report("ERROR: %s: out of memory: " err_msg, SanitizerToolName, __VA_ARGS__)340341// Specific tools may override behavior of "Die" function to do tool-specific342// job.343typedef void (*DieCallbackType)(void);344345// It's possible to add several callbacks that would be run when "Die" is346// called. The callbacks will be run in the opposite order. The tools are347// strongly recommended to setup all callbacks during initialization, when there348// is only a single thread.349bool AddDieCallback(DieCallbackType callback);350bool RemoveDieCallback(DieCallbackType callback);351352void SetUserDieCallback(DieCallbackType callback);353354void SetCheckUnwindCallback(void (*callback)());355356// Functions related to signal handling.357typedef void (*SignalHandlerType)(int, void *, void *);358HandleSignalMode GetHandleSignalMode(int signum);359void InstallDeadlySignalHandlers(SignalHandlerType handler);360361// Signal reporting.362// Each sanitizer uses slightly different implementation of stack unwinding.363typedef void (*UnwindSignalStackCallbackType)(const SignalContext &sig,364const void *callback_context,365BufferedStackTrace *stack);366// Print deadly signal report and die.367void HandleDeadlySignal(void *siginfo, void *context, u32 tid,368UnwindSignalStackCallbackType unwind,369const void *unwind_context);370371// Part of HandleDeadlySignal, exposed for asan.372void StartReportDeadlySignal();373// Part of HandleDeadlySignal, exposed for asan.374void ReportDeadlySignal(const SignalContext &sig, u32 tid,375UnwindSignalStackCallbackType unwind,376const void *unwind_context);377378// Alternative signal stack (POSIX-only).379void SetAlternateSignalStack();380void UnsetAlternateSignalStack();381382// Construct a one-line string:383// SUMMARY: SanitizerToolName: error_message384// and pass it to __sanitizer_report_error_summary.385// If alt_tool_name is provided, it's used in place of SanitizerToolName.386void ReportErrorSummary(const char *error_message,387const char *alt_tool_name = nullptr);388// Same as above, but construct error_message as:389// error_type file:line[:column][ function]390void ReportErrorSummary(const char *error_type, const AddressInfo &info,391const char *alt_tool_name = nullptr);392// Same as above, but obtains AddressInfo by symbolizing top stack trace frame.393void ReportErrorSummary(const char *error_type, const StackTrace *trace,394const char *alt_tool_name = nullptr);395// Skips frames which we consider internal and not usefull to the users.396const SymbolizedStack *SkipInternalFrames(const SymbolizedStack *frames);397398void ReportMmapWriteExec(int prot, int mflags);399400// Math401#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)402extern "C" {403unsigned char _BitScanForward(unsigned long *index, unsigned long mask);404unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);405#if defined(_WIN64)406unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);407unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);408#endif409}410#endif411412inline uptr MostSignificantSetBitIndex(uptr x) {413CHECK_NE(x, 0U);414unsigned long up;415#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)416# ifdef _WIN64417up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);418# else419up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);420# endif421#elif defined(_WIN64)422_BitScanReverse64(&up, x);423#else424_BitScanReverse(&up, x);425#endif426return up;427}428429inline uptr LeastSignificantSetBitIndex(uptr x) {430CHECK_NE(x, 0U);431unsigned long up;432#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)433# ifdef _WIN64434up = __builtin_ctzll(x);435# else436up = __builtin_ctzl(x);437# endif438#elif defined(_WIN64)439_BitScanForward64(&up, x);440#else441_BitScanForward(&up, x);442#endif443return up;444}445446inline constexpr bool IsPowerOfTwo(uptr x) { return (x & (x - 1)) == 0; }447448inline uptr RoundUpToPowerOfTwo(uptr size) {449CHECK(size);450if (IsPowerOfTwo(size)) return size;451452uptr up = MostSignificantSetBitIndex(size);453CHECK_LT(size, (1ULL << (up + 1)));454CHECK_GT(size, (1ULL << up));455return 1ULL << (up + 1);456}457458inline constexpr uptr RoundUpTo(uptr size, uptr boundary) {459RAW_CHECK(IsPowerOfTwo(boundary));460return (size + boundary - 1) & ~(boundary - 1);461}462463inline constexpr uptr RoundDownTo(uptr x, uptr boundary) {464return x & ~(boundary - 1);465}466467inline constexpr bool IsAligned(uptr a, uptr alignment) {468return (a & (alignment - 1)) == 0;469}470471inline uptr Log2(uptr x) {472CHECK(IsPowerOfTwo(x));473return LeastSignificantSetBitIndex(x);474}475476// Don't use std::min, std::max or std::swap, to minimize dependency477// on libstdc++.478template <class T>479constexpr T Min(T a, T b) {480return a < b ? a : b;481}482template <class T>483constexpr T Max(T a, T b) {484return a > b ? a : b;485}486template <class T>487constexpr T Abs(T a) {488return a < 0 ? -a : a;489}490template<class T> void Swap(T& a, T& b) {491T tmp = a;492a = b;493b = tmp;494}495496// Char handling497inline bool IsSpace(int c) {498return (c == ' ') || (c == '\n') || (c == '\t') ||499(c == '\f') || (c == '\r') || (c == '\v');500}501inline bool IsDigit(int c) {502return (c >= '0') && (c <= '9');503}504inline int ToLower(int c) {505return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;506}507508// A low-level vector based on mmap. May incur a significant memory overhead for509// small vectors.510// WARNING: The current implementation supports only POD types.511template <typename T, bool raw_report = false>512class InternalMmapVectorNoCtor {513public:514using value_type = T;515void Initialize(uptr initial_capacity) {516capacity_bytes_ = 0;517size_ = 0;518data_ = 0;519reserve(initial_capacity);520}521void Destroy() { UnmapOrDie(data_, capacity_bytes_, raw_report); }522T &operator[](uptr i) {523CHECK_LT(i, size_);524return data_[i];525}526const T &operator[](uptr i) const {527CHECK_LT(i, size_);528return data_[i];529}530void push_back(const T &element) {531if (UNLIKELY(size_ >= capacity())) {532CHECK_EQ(size_, capacity());533uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);534Realloc(new_capacity);535}536internal_memcpy(&data_[size_++], &element, sizeof(T));537}538T &back() {539CHECK_GT(size_, 0);540return data_[size_ - 1];541}542void pop_back() {543CHECK_GT(size_, 0);544size_--;545}546uptr size() const {547return size_;548}549const T *data() const {550return data_;551}552T *data() {553return data_;554}555uptr capacity() const { return capacity_bytes_ / sizeof(T); }556void reserve(uptr new_size) {557// Never downsize internal buffer.558if (new_size > capacity())559Realloc(new_size);560}561void resize(uptr new_size) {562if (new_size > size_) {563reserve(new_size);564internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_));565}566size_ = new_size;567}568569void clear() { size_ = 0; }570bool empty() const { return size() == 0; }571572const T *begin() const {573return data();574}575T *begin() {576return data();577}578const T *end() const {579return data() + size();580}581T *end() {582return data() + size();583}584585void swap(InternalMmapVectorNoCtor &other) {586Swap(data_, other.data_);587Swap(capacity_bytes_, other.capacity_bytes_);588Swap(size_, other.size_);589}590591private:592NOINLINE void Realloc(uptr new_capacity) {593CHECK_GT(new_capacity, 0);594CHECK_LE(size_, new_capacity);595uptr new_capacity_bytes =596RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached());597T *new_data =598(T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector", raw_report);599internal_memcpy(new_data, data_, size_ * sizeof(T));600UnmapOrDie(data_, capacity_bytes_, raw_report);601data_ = new_data;602capacity_bytes_ = new_capacity_bytes;603}604605T *data_;606uptr capacity_bytes_;607uptr size_;608};609610template <typename T>611bool operator==(const InternalMmapVectorNoCtor<T> &lhs,612const InternalMmapVectorNoCtor<T> &rhs) {613if (lhs.size() != rhs.size()) return false;614return internal_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;615}616617template <typename T>618bool operator!=(const InternalMmapVectorNoCtor<T> &lhs,619const InternalMmapVectorNoCtor<T> &rhs) {620return !(lhs == rhs);621}622623template<typename T>624class InternalMmapVector : public InternalMmapVectorNoCtor<T> {625public:626InternalMmapVector() { InternalMmapVectorNoCtor<T>::Initialize(0); }627explicit InternalMmapVector(uptr cnt) {628InternalMmapVectorNoCtor<T>::Initialize(cnt);629this->resize(cnt);630}631~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }632// Disallow copies and moves.633InternalMmapVector(const InternalMmapVector &) = delete;634InternalMmapVector &operator=(const InternalMmapVector &) = delete;635InternalMmapVector(InternalMmapVector &&) = delete;636InternalMmapVector &operator=(InternalMmapVector &&) = delete;637};638639class InternalScopedString {640public:641InternalScopedString() : buffer_(1) { buffer_[0] = '\0'; }642643uptr length() const { return buffer_.size() - 1; }644void clear() {645buffer_.resize(1);646buffer_[0] = '\0';647}648void Append(const char *str);649void AppendF(const char *format, ...) FORMAT(2, 3);650const char *data() const { return buffer_.data(); }651char *data() { return buffer_.data(); }652653private:654InternalMmapVector<char> buffer_;655};656657template <class T>658struct CompareLess {659bool operator()(const T &a, const T &b) const { return a < b; }660};661662// HeapSort for arrays and InternalMmapVector.663template <class T, class Compare = CompareLess<T>>664void Sort(T *v, uptr size, Compare comp = {}) {665if (size < 2)666return;667// Stage 1: insert elements to the heap.668for (uptr i = 1; i < size; i++) {669uptr j, p;670for (j = i; j > 0; j = p) {671p = (j - 1) / 2;672if (comp(v[p], v[j]))673Swap(v[j], v[p]);674else675break;676}677}678// Stage 2: swap largest element with the last one,679// and sink the new top.680for (uptr i = size - 1; i > 0; i--) {681Swap(v[0], v[i]);682uptr j, max_ind;683for (j = 0; j < i; j = max_ind) {684uptr left = 2 * j + 1;685uptr right = 2 * j + 2;686max_ind = j;687if (left < i && comp(v[max_ind], v[left]))688max_ind = left;689if (right < i && comp(v[max_ind], v[right]))690max_ind = right;691if (max_ind != j)692Swap(v[j], v[max_ind]);693else694break;695}696}697}698699// Works like std::lower_bound: finds the first element that is not less700// than the val.701template <class Container, class T,702class Compare = CompareLess<typename Container::value_type>>703uptr InternalLowerBound(const Container &v, const T &val, Compare comp = {}) {704uptr first = 0;705uptr last = v.size();706while (last > first) {707uptr mid = (first + last) / 2;708if (comp(v[mid], val))709first = mid + 1;710else711last = mid;712}713return first;714}715716enum ModuleArch {717kModuleArchUnknown,718kModuleArchI386,719kModuleArchX86_64,720kModuleArchX86_64H,721kModuleArchARMV6,722kModuleArchARMV7,723kModuleArchARMV7S,724kModuleArchARMV7K,725kModuleArchARM64,726kModuleArchLoongArch64,727kModuleArchRISCV64,728kModuleArchHexagon729};730731// Sorts and removes duplicates from the container.732template <class Container,733class Compare = CompareLess<typename Container::value_type>>734void SortAndDedup(Container &v, Compare comp = {}) {735Sort(v.data(), v.size(), comp);736uptr size = v.size();737if (size < 2)738return;739uptr last = 0;740for (uptr i = 1; i < size; ++i) {741if (comp(v[last], v[i])) {742++last;743if (last != i)744v[last] = v[i];745} else {746CHECK(!comp(v[i], v[last]));747}748}749v.resize(last + 1);750}751752constexpr uptr kDefaultFileMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 28);753754// Opens the file 'file_name" and reads up to 'max_len' bytes.755// The resulting buffer is mmaped and stored in '*buff'.756// Returns true if file was successfully opened and read.757bool ReadFileToVector(const char *file_name,758InternalMmapVectorNoCtor<char> *buff,759uptr max_len = kDefaultFileMaxSize,760error_t *errno_p = nullptr);761762// Opens the file 'file_name" and reads up to 'max_len' bytes.763// This function is less I/O efficient than ReadFileToVector as it may reread764// file multiple times to avoid mmap during read attempts. It's used to read765// procmap, so short reads with mmap in between can produce inconsistent result.766// The resulting buffer is mmaped and stored in '*buff'.767// The size of the mmaped region is stored in '*buff_size'.768// The total number of read bytes is stored in '*read_len'.769// Returns true if file was successfully opened and read.770bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,771uptr *read_len, uptr max_len = kDefaultFileMaxSize,772error_t *errno_p = nullptr);773774int GetModuleAndOffsetForPc(uptr pc, char *module_name, uptr module_name_len,775uptr *pc_offset);776777// When adding a new architecture, don't forget to also update778// script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cpp.779inline const char *ModuleArchToString(ModuleArch arch) {780switch (arch) {781case kModuleArchUnknown:782return "";783case kModuleArchI386:784return "i386";785case kModuleArchX86_64:786return "x86_64";787case kModuleArchX86_64H:788return "x86_64h";789case kModuleArchARMV6:790return "armv6";791case kModuleArchARMV7:792return "armv7";793case kModuleArchARMV7S:794return "armv7s";795case kModuleArchARMV7K:796return "armv7k";797case kModuleArchARM64:798return "arm64";799case kModuleArchLoongArch64:800return "loongarch64";801case kModuleArchRISCV64:802return "riscv64";803case kModuleArchHexagon:804return "hexagon";805}806CHECK(0 && "Invalid module arch");807return "";808}809810#if SANITIZER_APPLE811const uptr kModuleUUIDSize = 16;812#else813const uptr kModuleUUIDSize = 32;814#endif815const uptr kMaxSegName = 16;816817// Represents a binary loaded into virtual memory (e.g. this can be an818// executable or a shared object).819class LoadedModule {820public:821LoadedModule()822: full_name_(nullptr),823base_address_(0),824max_address_(0),825arch_(kModuleArchUnknown),826uuid_size_(0),827instrumented_(false) {828internal_memset(uuid_, 0, kModuleUUIDSize);829ranges_.clear();830}831void set(const char *module_name, uptr base_address);832void set(const char *module_name, uptr base_address, ModuleArch arch,833u8 uuid[kModuleUUIDSize], bool instrumented);834void setUuid(const char *uuid, uptr size);835void clear();836void addAddressRange(uptr beg, uptr end, bool executable, bool writable,837const char *name = nullptr);838bool containsAddress(uptr address) const;839840const char *full_name() const { return full_name_; }841uptr base_address() const { return base_address_; }842uptr max_address() const { return max_address_; }843ModuleArch arch() const { return arch_; }844const u8 *uuid() const { return uuid_; }845uptr uuid_size() const { return uuid_size_; }846bool instrumented() const { return instrumented_; }847848struct AddressRange {849AddressRange *next;850uptr beg;851uptr end;852bool executable;853bool writable;854char name[kMaxSegName];855856AddressRange(uptr beg, uptr end, bool executable, bool writable,857const char *name)858: next(nullptr),859beg(beg),860end(end),861executable(executable),862writable(writable) {863internal_strncpy(this->name, (name ? name : ""), ARRAY_SIZE(this->name));864}865};866867const IntrusiveList<AddressRange> &ranges() const { return ranges_; }868869private:870char *full_name_; // Owned.871uptr base_address_;872uptr max_address_;873ModuleArch arch_;874uptr uuid_size_;875u8 uuid_[kModuleUUIDSize];876bool instrumented_;877IntrusiveList<AddressRange> ranges_;878};879880// List of LoadedModules. OS-dependent implementation is responsible for881// filling this information.882class ListOfModules {883public:884ListOfModules() : initialized(false) {}885~ListOfModules() { clear(); }886void init();887void fallbackInit(); // Uses fallback init if available, otherwise clears888const LoadedModule *begin() const { return modules_.begin(); }889LoadedModule *begin() { return modules_.begin(); }890const LoadedModule *end() const { return modules_.end(); }891LoadedModule *end() { return modules_.end(); }892uptr size() const { return modules_.size(); }893const LoadedModule &operator[](uptr i) const {894CHECK_LT(i, modules_.size());895return modules_[i];896}897898private:899void clear() {900for (auto &module : modules_) module.clear();901modules_.clear();902}903void clearOrInit() {904initialized ? clear() : modules_.Initialize(kInitialCapacity);905initialized = true;906}907908InternalMmapVectorNoCtor<LoadedModule> modules_;909// We rarely have more than 16K loaded modules.910static const uptr kInitialCapacity = 1 << 14;911bool initialized;912};913914// Callback type for iterating over a set of memory ranges.915typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);916917enum AndroidApiLevel {918ANDROID_NOT_ANDROID = 0,919ANDROID_KITKAT = 19,920ANDROID_LOLLIPOP_MR1 = 22,921ANDROID_POST_LOLLIPOP = 23922};923924void WriteToSyslog(const char *buffer);925926#if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__)927#define SANITIZER_WIN_TRACE 1928#else929#define SANITIZER_WIN_TRACE 0930#endif931932#if SANITIZER_APPLE || SANITIZER_WIN_TRACE933void LogFullErrorReport(const char *buffer);934#else935inline void LogFullErrorReport(const char *buffer) {}936#endif937938#if SANITIZER_LINUX || SANITIZER_APPLE939void WriteOneLineToSyslog(const char *s);940void LogMessageOnPrintf(const char *str);941#else942inline void WriteOneLineToSyslog(const char *s) {}943inline void LogMessageOnPrintf(const char *str) {}944#endif945946#if SANITIZER_LINUX || SANITIZER_WIN_TRACE947// Initialize Android logging. Any writes before this are silently lost.948void AndroidLogInit();949void SetAbortMessage(const char *);950#else951inline void AndroidLogInit() {}952// FIXME: MacOS implementation could use CRSetCrashLogMessage.953inline void SetAbortMessage(const char *) {}954#endif955956#if SANITIZER_ANDROID957void SanitizerInitializeUnwinder();958AndroidApiLevel AndroidGetApiLevel();959#else960inline void AndroidLogWrite(const char *buffer_unused) {}961inline void SanitizerInitializeUnwinder() {}962inline AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; }963#endif964965inline uptr GetPthreadDestructorIterations() {966#if SANITIZER_ANDROID967return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;968#elif SANITIZER_POSIX969return 4;970#else971// Unused on Windows.972return 0;973#endif974}975976void *internal_start_thread(void *(*func)(void*), void *arg);977void internal_join_thread(void *th);978void MaybeStartBackgroudThread();979980// Make the compiler think that something is going on there.981// Use this inside a loop that looks like memset/memcpy/etc to prevent the982// compiler from recognising it and turning it into an actual call to983// memset/memcpy/etc.984static inline void SanitizerBreakOptimization(void *arg) {985#if defined(_MSC_VER) && !defined(__clang__)986_ReadWriteBarrier();987#else988__asm__ __volatile__("" : : "r" (arg) : "memory");989#endif990}991992struct SignalContext {993void *siginfo;994void *context;995uptr addr;996uptr pc;997uptr sp;998uptr bp;999bool is_memory_access;1000enum WriteFlag { Unknown, Read, Write } write_flag;10011002// In some cases the kernel cannot provide the true faulting address; `addr`1003// will be zero then. This field allows to distinguish between these cases1004// and dereferences of null.1005bool is_true_faulting_addr;10061007// VS2013 doesn't implement unrestricted unions, so we need a trivial default1008// constructor1009SignalContext() = default;10101011// Creates signal context in a platform-specific manner.1012// SignalContext is going to keep pointers to siginfo and context without1013// owning them.1014SignalContext(void *siginfo, void *context)1015: siginfo(siginfo),1016context(context),1017addr(GetAddress()),1018is_memory_access(IsMemoryAccess()),1019write_flag(GetWriteFlag()),1020is_true_faulting_addr(IsTrueFaultingAddress()) {1021InitPcSpBp();1022}10231024static void DumpAllRegisters(void *context);10251026// Type of signal e.g. SIGSEGV or EXCEPTION_ACCESS_VIOLATION.1027int GetType() const;10281029// String description of the signal.1030const char *Describe() const;10311032// Returns true if signal is stack overflow.1033bool IsStackOverflow() const;10341035private:1036// Platform specific initialization.1037void InitPcSpBp();1038uptr GetAddress() const;1039WriteFlag GetWriteFlag() const;1040bool IsMemoryAccess() const;1041bool IsTrueFaultingAddress() const;1042};10431044void InitializePlatformEarly();10451046template <typename Fn>1047class RunOnDestruction {1048public:1049explicit RunOnDestruction(Fn fn) : fn_(fn) {}1050~RunOnDestruction() { fn_(); }10511052private:1053Fn fn_;1054};10551056// A simple scope guard. Usage:1057// auto cleanup = at_scope_exit([]{ do_cleanup; });1058template <typename Fn>1059RunOnDestruction<Fn> at_scope_exit(Fn fn) {1060return RunOnDestruction<Fn>(fn);1061}10621063// Linux on 64-bit s390 had a nasty bug that crashes the whole machine1064// if a process uses virtual memory over 4TB (as many sanitizers like1065// to do). This function will abort the process if running on a kernel1066// that looks vulnerable.1067#if SANITIZER_LINUX && SANITIZER_S390_641068void AvoidCVE_2016_2143();1069#else1070inline void AvoidCVE_2016_2143() {}1071#endif10721073struct StackDepotStats {1074uptr n_uniq_ids;1075uptr allocated;1076};10771078// The default value for allocator_release_to_os_interval_ms common flag to1079// indicate that sanitizer allocator should not attempt to release memory to OS.1080const s32 kReleaseToOSIntervalNever = -1;10811082void CheckNoDeepBind(const char *filename, int flag);10831084// Returns the requested amount of random data (up to 256 bytes) that can then1085// be used to seed a PRNG. Defaults to blocking like the underlying syscall.1086bool GetRandom(void *buffer, uptr length, bool blocking = true);10871088// Returns the number of logical processors on the system.1089u32 GetNumberOfCPUs();1090extern u32 NumberOfCPUsCached;1091inline u32 GetNumberOfCPUsCached() {1092if (!NumberOfCPUsCached)1093NumberOfCPUsCached = GetNumberOfCPUs();1094return NumberOfCPUsCached;1095}10961097} // namespace __sanitizer10981099inline void *operator new(__sanitizer::usize size,1100__sanitizer::LowLevelAllocator &alloc) {1101return alloc.Allocate(size);1102}11031104#endif // SANITIZER_COMMON_H110511061107