10b57cec5SDimitry Andric //===-- sanitizer_common.h --------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file is shared between run-time libraries of sanitizers.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // It declares common functions and classes that are used in both runtimes.
120b57cec5SDimitry Andric // Implementation of some functions are provided in sanitizer_common, while
130b57cec5SDimitry Andric // others must be defined by run-time library itself.
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric #ifndef SANITIZER_COMMON_H
160b57cec5SDimitry Andric #define SANITIZER_COMMON_H
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric #include "sanitizer_flags.h"
190b57cec5SDimitry Andric #include "sanitizer_internal_defs.h"
200b57cec5SDimitry Andric #include "sanitizer_libc.h"
210b57cec5SDimitry Andric #include "sanitizer_list.h"
220b57cec5SDimitry Andric #include "sanitizer_mutex.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric #if defined(_MSC_VER) && !defined(__clang__)
250b57cec5SDimitry Andric extern "C" void _ReadWriteBarrier();
260b57cec5SDimitry Andric #pragma intrinsic(_ReadWriteBarrier)
270b57cec5SDimitry Andric #endif
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric namespace __sanitizer {
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric struct AddressInfo;
320b57cec5SDimitry Andric struct BufferedStackTrace;
330b57cec5SDimitry Andric struct SignalContext;
340b57cec5SDimitry Andric struct StackTrace;
351db9f3b2SDimitry Andric struct SymbolizedStack;
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric // Constants.
380b57cec5SDimitry Andric const uptr kWordSize = SANITIZER_WORDSIZE / 8;
390b57cec5SDimitry Andric const uptr kWordSizeInBits = 8 * kWordSize;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric const uptr kCacheLineSize = SANITIZER_CACHE_LINE_SIZE;
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric const uptr kMaxPathLength = 4096;
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
460b57cec5SDimitry Andric
47fe6060f1SDimitry Andric const uptr kErrorMessageBufferSize = 1 << 16;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric // Denotes fake PC values that come from JIT/JAVA/etc.
500b57cec5SDimitry Andric // For such PC values __tsan_symbolize_external_ex() will be called.
510b57cec5SDimitry Andric const u64 kExternalPCBit = 1ULL << 60;
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric extern const char *SanitizerToolName; // Can be changed by the tool.
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric extern atomic_uint32_t current_verbosity;
SetVerbosity(int verbosity)56e8d8bef9SDimitry Andric inline void SetVerbosity(int verbosity) {
570b57cec5SDimitry Andric atomic_store(¤t_verbosity, verbosity, memory_order_relaxed);
580b57cec5SDimitry Andric }
Verbosity()59e8d8bef9SDimitry Andric inline int Verbosity() {
600b57cec5SDimitry Andric return atomic_load(¤t_verbosity, memory_order_relaxed);
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
63*0fca6ea1SDimitry Andric #if SANITIZER_ANDROID && !defined(__aarch64__)
64*0fca6ea1SDimitry Andric // 32-bit Android only has 4k pages.
GetPageSize()65*0fca6ea1SDimitry Andric inline uptr GetPageSize() { return 4096; }
GetPageSizeCached()66*0fca6ea1SDimitry Andric inline uptr GetPageSizeCached() { return 4096; }
670b57cec5SDimitry Andric #else
680b57cec5SDimitry Andric uptr GetPageSize();
690b57cec5SDimitry Andric extern uptr PageSizeCached;
GetPageSizeCached()70e8d8bef9SDimitry Andric inline uptr GetPageSizeCached() {
710b57cec5SDimitry Andric if (!PageSizeCached)
720b57cec5SDimitry Andric PageSizeCached = GetPageSize();
730b57cec5SDimitry Andric return PageSizeCached;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric #endif
76*0fca6ea1SDimitry Andric
770b57cec5SDimitry Andric uptr GetMmapGranularity();
780b57cec5SDimitry Andric uptr GetMaxVirtualAddress();
790b57cec5SDimitry Andric uptr GetMaxUserVirtualAddress();
800b57cec5SDimitry Andric // Threads
810b57cec5SDimitry Andric tid_t GetTid();
820b57cec5SDimitry Andric int TgKill(pid_t pid, tid_t tid, int sig);
830b57cec5SDimitry Andric uptr GetThreadSelf();
840b57cec5SDimitry Andric void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
850b57cec5SDimitry Andric uptr *stack_bottom);
860b57cec5SDimitry Andric void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
870b57cec5SDimitry Andric uptr *tls_addr, uptr *tls_size);
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric // Memory management
900b57cec5SDimitry Andric void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
91*0fca6ea1SDimitry Andric
MmapOrDieQuietly(uptr size,const char * mem_type)92e8d8bef9SDimitry Andric inline void *MmapOrDieQuietly(uptr size, const char *mem_type) {
930b57cec5SDimitry Andric return MmapOrDie(size, mem_type, /*raw_report*/ true);
940b57cec5SDimitry Andric }
95*0fca6ea1SDimitry Andric void UnmapOrDie(void *addr, uptr size, bool raw_report = false);
960b57cec5SDimitry Andric // Behaves just like MmapOrDie, but tolerates out of memory condition, in that
970b57cec5SDimitry Andric // case returns nullptr.
980b57cec5SDimitry Andric void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
990b57cec5SDimitry Andric bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
1000b57cec5SDimitry Andric WARN_UNUSED_RESULT;
10168d75effSDimitry Andric bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size,
10268d75effSDimitry Andric const char *name = nullptr) WARN_UNUSED_RESULT;
1030b57cec5SDimitry Andric void *MmapNoReserveOrDie(uptr size, const char *mem_type);
1040b57cec5SDimitry Andric void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
1050b57cec5SDimitry Andric // Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
1060b57cec5SDimitry Andric // that case returns nullptr.
1070b57cec5SDimitry Andric void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size,
1080b57cec5SDimitry Andric const char *name = nullptr);
1090b57cec5SDimitry Andric void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);
1100b57cec5SDimitry Andric void *MmapNoAccess(uptr size);
1110b57cec5SDimitry Andric // Map aligned chunk of address space; size and alignment are powers of two.
1120b57cec5SDimitry Andric // Dies on all but out of memory errors, in the latter case returns nullptr.
1130b57cec5SDimitry Andric void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
1140b57cec5SDimitry Andric const char *mem_type);
1150b57cec5SDimitry Andric // Disallow access to a memory range. Use MmapFixedNoAccess to allocate an
1160b57cec5SDimitry Andric // unaccessible memory.
1170b57cec5SDimitry Andric bool MprotectNoAccess(uptr addr, uptr size);
1180b57cec5SDimitry Andric bool MprotectReadOnly(uptr addr, uptr size);
11906c3fb27SDimitry Andric bool MprotectReadWrite(uptr addr, uptr size);
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric void MprotectMallocZones(void *addr, int prot);
1220b57cec5SDimitry Andric
123972a253aSDimitry Andric #if SANITIZER_WINDOWS
124972a253aSDimitry Andric // Zero previously mmap'd memory. Currently used only on Windows.
125972a253aSDimitry Andric bool ZeroMmapFixedRegion(uptr fixed_addr, uptr size) WARN_UNUSED_RESULT;
126972a253aSDimitry Andric #endif
127972a253aSDimitry Andric
128e8d8bef9SDimitry Andric #if SANITIZER_LINUX
129e8d8bef9SDimitry Andric // Unmap memory. Currently only used on Linux.
130e8d8bef9SDimitry Andric void UnmapFromTo(uptr from, uptr to);
131e8d8bef9SDimitry Andric #endif
132e8d8bef9SDimitry Andric
133e8d8bef9SDimitry Andric // Maps shadow_size_bytes of shadow memory and returns shadow address. It will
134e8d8bef9SDimitry Andric // be aligned to the mmap granularity * 2^shadow_scale, or to
135e8d8bef9SDimitry Andric // 2^min_shadow_base_alignment if that is larger. The returned address will
136e8d8bef9SDimitry Andric // have max(2^min_shadow_base_alignment, mmap granularity) on the left, and
137e8d8bef9SDimitry Andric // shadow_size_bytes bytes on the right, which on linux is mapped no access.
138e8d8bef9SDimitry Andric // The high_mem_end may be updated if the original shadow size doesn't fit.
139e8d8bef9SDimitry Andric uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
140*0fca6ea1SDimitry Andric uptr min_shadow_base_alignment, uptr &high_mem_end,
141*0fca6ea1SDimitry Andric uptr granularity);
142e8d8bef9SDimitry Andric
143fe6060f1SDimitry Andric // Let S = max(shadow_size, num_aliases * alias_size, ring_buffer_size).
144fe6060f1SDimitry Andric // Reserves 2*S bytes of address space to the right of the returned address and
145fe6060f1SDimitry Andric // ring_buffer_size bytes to the left. The returned address is aligned to 2*S.
146fe6060f1SDimitry Andric // Also creates num_aliases regions of accessible memory starting at offset S
147fe6060f1SDimitry Andric // from the returned address. Each region has size alias_size and is backed by
148fe6060f1SDimitry Andric // the same physical memory.
149fe6060f1SDimitry Andric uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
150fe6060f1SDimitry Andric uptr num_aliases, uptr ring_buffer_size);
151fe6060f1SDimitry Andric
152e8d8bef9SDimitry Andric // Reserve memory range [beg, end]. If madvise_shadow is true then apply
153e8d8bef9SDimitry Andric // madvise (e.g. hugepages, core dumping) requested by options.
154e8d8bef9SDimitry Andric void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,
155e8d8bef9SDimitry Andric bool madvise_shadow = true);
156e8d8bef9SDimitry Andric
157e8d8bef9SDimitry Andric // Protect size bytes of memory starting at addr. Also try to protect
158e8d8bef9SDimitry Andric // several pages at the start of the address space as specified by
159e8d8bef9SDimitry Andric // zero_base_shadow_start, at most up to the size or zero_base_max_shadow_start.
160e8d8bef9SDimitry Andric void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start,
161e8d8bef9SDimitry Andric uptr zero_base_max_shadow_start);
162e8d8bef9SDimitry Andric
1630b57cec5SDimitry Andric // Find an available address space.
1640b57cec5SDimitry Andric uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
1650b57cec5SDimitry Andric uptr *largest_gap_found, uptr *max_occupied_addr);
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric // Used to check if we can map shadow memory to a fixed location.
1680b57cec5SDimitry Andric bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
1690b57cec5SDimitry Andric // Releases memory pages entirely within the [beg, end] address range. Noop if
1700b57cec5SDimitry Andric // the provided range does not contain at least one entire page.
1710b57cec5SDimitry Andric void ReleaseMemoryPagesToOS(uptr beg, uptr end);
1720b57cec5SDimitry Andric void IncreaseTotalMmap(uptr size);
1730b57cec5SDimitry Andric void DecreaseTotalMmap(uptr size);
1740b57cec5SDimitry Andric uptr GetRSS();
17568d75effSDimitry Andric void SetShadowRegionHugePageMode(uptr addr, uptr length);
1760b57cec5SDimitry Andric bool DontDumpShadowMemory(uptr addr, uptr length);
1770b57cec5SDimitry Andric // Check if the built VMA size matches the runtime one.
1780b57cec5SDimitry Andric void CheckVMASize();
17981ad6265SDimitry Andric void RunMallocHooks(void *ptr, uptr size);
180*0fca6ea1SDimitry Andric int RunFreeHooks(void *ptr);
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric class ReservedAddressRange {
1830b57cec5SDimitry Andric public:
1840b57cec5SDimitry Andric uptr Init(uptr size, const char *name = nullptr, uptr fixed_addr = 0);
1855ffd83dbSDimitry Andric uptr InitAligned(uptr size, uptr align, const char *name = nullptr);
1860b57cec5SDimitry Andric uptr Map(uptr fixed_addr, uptr size, const char *name = nullptr);
1870b57cec5SDimitry Andric uptr MapOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
1880b57cec5SDimitry Andric void Unmap(uptr addr, uptr size);
base()1890b57cec5SDimitry Andric void *base() const { return base_; }
size()1900b57cec5SDimitry Andric uptr size() const { return size_; }
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric private:
1930b57cec5SDimitry Andric void* base_;
1940b57cec5SDimitry Andric uptr size_;
1950b57cec5SDimitry Andric const char* name_;
1960b57cec5SDimitry Andric uptr os_handle_;
1970b57cec5SDimitry Andric };
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andric typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
200349cc55cSDimitry Andric /*out*/ uptr *stats);
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric // Parse the contents of /proc/self/smaps and generate a memory profile.
203349cc55cSDimitry Andric // |cb| is a tool-specific callback that fills the |stats| array.
204349cc55cSDimitry Andric void GetMemoryProfile(fill_profile_f cb, uptr *stats);
205349cc55cSDimitry Andric void ParseUnixMemoryProfile(fill_profile_f cb, uptr *stats, char *smaps,
206349cc55cSDimitry Andric uptr smaps_len);
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric // Simple low-level (mmap-based) allocator for internal use. Doesn't have
2090b57cec5SDimitry Andric // constructor, so all instances of LowLevelAllocator should be
2100b57cec5SDimitry Andric // linker initialized.
2115f757f3fSDimitry Andric //
2125f757f3fSDimitry Andric // NOTE: Users should instead use the singleton provided via
2135f757f3fSDimitry Andric // `GetGlobalLowLevelAllocator()` rather than create a new one. This way, the
2145f757f3fSDimitry Andric // number of mmap fragments can be reduced and use the same contiguous mmap
2155f757f3fSDimitry Andric // provided by this singleton.
2160b57cec5SDimitry Andric class LowLevelAllocator {
2170b57cec5SDimitry Andric public:
2180b57cec5SDimitry Andric // Requires an external lock.
2190b57cec5SDimitry Andric void *Allocate(uptr size);
22006c3fb27SDimitry Andric
2210b57cec5SDimitry Andric private:
2220b57cec5SDimitry Andric char *allocated_end_;
2230b57cec5SDimitry Andric char *allocated_current_;
2240b57cec5SDimitry Andric };
2250b57cec5SDimitry Andric // Set the min alignment of LowLevelAllocator to at least alignment.
2260b57cec5SDimitry Andric void SetLowLevelAllocateMinAlignment(uptr alignment);
2270b57cec5SDimitry Andric typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
2280b57cec5SDimitry Andric // Allows to register tool-specific callbacks for LowLevelAllocator.
2290b57cec5SDimitry Andric // Passing NULL removes the callback.
2300b57cec5SDimitry Andric void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
2310b57cec5SDimitry Andric
2325f757f3fSDimitry Andric LowLevelAllocator &GetGlobalLowLevelAllocator();
2335f757f3fSDimitry Andric
2340b57cec5SDimitry Andric // IO
2350b57cec5SDimitry Andric void CatastrophicErrorWrite(const char *buffer, uptr length);
2360b57cec5SDimitry Andric void RawWrite(const char *buffer);
2370b57cec5SDimitry Andric bool ColorizeReports();
2380b57cec5SDimitry Andric void RemoveANSIEscapeSequencesFromString(char *buffer);
239349cc55cSDimitry Andric void Printf(const char *format, ...) FORMAT(1, 2);
240349cc55cSDimitry Andric void Report(const char *format, ...) FORMAT(1, 2);
2410b57cec5SDimitry Andric void SetPrintfAndReportCallback(void (*callback)(const char *));
2420b57cec5SDimitry Andric #define VReport(level, ...) \
2430b57cec5SDimitry Andric do { \
2440b57cec5SDimitry Andric if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \
2450b57cec5SDimitry Andric } while (0)
2460b57cec5SDimitry Andric #define VPrintf(level, ...) \
2470b57cec5SDimitry Andric do { \
2480b57cec5SDimitry Andric if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \
2490b57cec5SDimitry Andric } while (0)
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric // Lock sanitizer error reporting and protects against nested errors.
2520b57cec5SDimitry Andric class ScopedErrorReportLock {
2530b57cec5SDimitry Andric public:
ScopedErrorReportLock()25404eeddc0SDimitry Andric ScopedErrorReportLock() SANITIZER_ACQUIRE(mutex_) { Lock(); }
SANITIZER_RELEASE(mutex_)25504eeddc0SDimitry Andric ~ScopedErrorReportLock() SANITIZER_RELEASE(mutex_) { Unlock(); }
2560b57cec5SDimitry Andric
25704eeddc0SDimitry Andric static void Lock() SANITIZER_ACQUIRE(mutex_);
25804eeddc0SDimitry Andric static void Unlock() SANITIZER_RELEASE(mutex_);
25904eeddc0SDimitry Andric static void CheckLocked() SANITIZER_CHECK_LOCKED(mutex_);
260fe6060f1SDimitry Andric
261fe6060f1SDimitry Andric private:
262fe6060f1SDimitry Andric static atomic_uintptr_t reporting_thread_;
263fe6060f1SDimitry Andric static StaticSpinMutex mutex_;
2640b57cec5SDimitry Andric };
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric extern uptr stoptheworld_tracer_pid;
2670b57cec5SDimitry Andric extern uptr stoptheworld_tracer_ppid;
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric bool IsAccessibleMemoryRange(uptr beg, uptr size);
2700b57cec5SDimitry Andric
2710b57cec5SDimitry Andric // Error report formatting.
2720b57cec5SDimitry Andric const char *StripPathPrefix(const char *filepath,
2730b57cec5SDimitry Andric const char *strip_file_prefix);
2740b57cec5SDimitry Andric // Strip the directories from the module name.
2750b57cec5SDimitry Andric const char *StripModuleName(const char *module);
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric // OS
2780b57cec5SDimitry Andric uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
2790b57cec5SDimitry Andric uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);
280fe6060f1SDimitry Andric uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len);
2810b57cec5SDimitry Andric uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);
2820b57cec5SDimitry Andric const char *GetProcessName();
2830b57cec5SDimitry Andric void UpdateProcessName();
2840b57cec5SDimitry Andric void CacheBinaryName();
2850b57cec5SDimitry Andric void DisableCoreDumperIfNecessary();
2860b57cec5SDimitry Andric void DumpProcessMap();
2870b57cec5SDimitry Andric const char *GetEnv(const char *name);
2880b57cec5SDimitry Andric bool SetEnv(const char *name, const char *value);
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric u32 GetUid();
2910b57cec5SDimitry Andric void ReExec();
2920b57cec5SDimitry Andric void CheckASLR();
2930b57cec5SDimitry Andric void CheckMPROTECT();
2940b57cec5SDimitry Andric char **GetArgv();
2950b57cec5SDimitry Andric char **GetEnviron();
2960b57cec5SDimitry Andric void PrintCmdline();
2970b57cec5SDimitry Andric bool StackSizeIsUnlimited();
2980b57cec5SDimitry Andric void SetStackSizeLimitInBytes(uptr limit);
2990b57cec5SDimitry Andric bool AddressSpaceIsUnlimited();
3000b57cec5SDimitry Andric void SetAddressSpaceUnlimited();
3010b57cec5SDimitry Andric void AdjustStackSize(void *attr);
30281ad6265SDimitry Andric void PlatformPrepareForSandboxing(void *args);
3030b57cec5SDimitry Andric void SetSandboxingCallback(void (*f)());
3040b57cec5SDimitry Andric
3050b57cec5SDimitry Andric void InitializeCoverage(bool enabled, const char *coverage_dir);
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric void InitTlsSize();
3080b57cec5SDimitry Andric uptr GetTlsSize();
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric // Other
31181ad6265SDimitry Andric void WaitForDebugger(unsigned seconds, const char *label);
312fe6060f1SDimitry Andric void SleepForSeconds(unsigned seconds);
313fe6060f1SDimitry Andric void SleepForMillis(unsigned millis);
3140b57cec5SDimitry Andric u64 NanoTime();
3150b57cec5SDimitry Andric u64 MonotonicNanoTime();
3160b57cec5SDimitry Andric int Atexit(void (*function)(void));
3170b57cec5SDimitry Andric bool TemplateMatch(const char *templ, const char *str);
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andric // Exit
3200b57cec5SDimitry Andric void NORETURN Abort();
3210b57cec5SDimitry Andric void NORETURN Die();
3220b57cec5SDimitry Andric void NORETURN
3230b57cec5SDimitry Andric CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
3240b57cec5SDimitry Andric void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
3250b57cec5SDimitry Andric const char *mmap_type, error_t err,
3260b57cec5SDimitry Andric bool raw_report = false);
32706c3fb27SDimitry Andric void NORETURN ReportMunmapFailureAndDie(void *ptr, uptr size, error_t err,
32806c3fb27SDimitry Andric bool raw_report = false);
3290b57cec5SDimitry Andric
33081ad6265SDimitry Andric // Returns true if the platform-specific error reported is an OOM error.
33181ad6265SDimitry Andric bool ErrorIsOOM(error_t err);
33281ad6265SDimitry Andric
33381ad6265SDimitry Andric // This reports an error in the form:
33481ad6265SDimitry Andric //
33581ad6265SDimitry Andric // `ERROR: {{SanitizerToolName}}: out of memory: {{err_msg}}`
33681ad6265SDimitry Andric //
33781ad6265SDimitry Andric // Downstream tools that read sanitizer output will know that errors starting
33881ad6265SDimitry Andric // in this format are specifically OOM errors.
33981ad6265SDimitry Andric #define ERROR_OOM(err_msg, ...) \
34081ad6265SDimitry Andric Report("ERROR: %s: out of memory: " err_msg, SanitizerToolName, __VA_ARGS__)
34181ad6265SDimitry Andric
342fe6060f1SDimitry Andric // Specific tools may override behavior of "Die" function to do tool-specific
343fe6060f1SDimitry Andric // job.
3440b57cec5SDimitry Andric typedef void (*DieCallbackType)(void);
3450b57cec5SDimitry Andric
3460b57cec5SDimitry Andric // It's possible to add several callbacks that would be run when "Die" is
3470b57cec5SDimitry Andric // called. The callbacks will be run in the opposite order. The tools are
3480b57cec5SDimitry Andric // strongly recommended to setup all callbacks during initialization, when there
3490b57cec5SDimitry Andric // is only a single thread.
3500b57cec5SDimitry Andric bool AddDieCallback(DieCallbackType callback);
3510b57cec5SDimitry Andric bool RemoveDieCallback(DieCallbackType callback);
3520b57cec5SDimitry Andric
3530b57cec5SDimitry Andric void SetUserDieCallback(DieCallbackType callback);
3540b57cec5SDimitry Andric
355fe6060f1SDimitry Andric void SetCheckUnwindCallback(void (*callback)());
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric // Functions related to signal handling.
3580b57cec5SDimitry Andric typedef void (*SignalHandlerType)(int, void *, void *);
3590b57cec5SDimitry Andric HandleSignalMode GetHandleSignalMode(int signum);
3600b57cec5SDimitry Andric void InstallDeadlySignalHandlers(SignalHandlerType handler);
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric // Signal reporting.
3630b57cec5SDimitry Andric // Each sanitizer uses slightly different implementation of stack unwinding.
3640b57cec5SDimitry Andric typedef void (*UnwindSignalStackCallbackType)(const SignalContext &sig,
3650b57cec5SDimitry Andric const void *callback_context,
3660b57cec5SDimitry Andric BufferedStackTrace *stack);
3670b57cec5SDimitry Andric // Print deadly signal report and die.
3680b57cec5SDimitry Andric void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
3690b57cec5SDimitry Andric UnwindSignalStackCallbackType unwind,
3700b57cec5SDimitry Andric const void *unwind_context);
3710b57cec5SDimitry Andric
3720b57cec5SDimitry Andric // Part of HandleDeadlySignal, exposed for asan.
3730b57cec5SDimitry Andric void StartReportDeadlySignal();
3740b57cec5SDimitry Andric // Part of HandleDeadlySignal, exposed for asan.
3750b57cec5SDimitry Andric void ReportDeadlySignal(const SignalContext &sig, u32 tid,
3760b57cec5SDimitry Andric UnwindSignalStackCallbackType unwind,
3770b57cec5SDimitry Andric const void *unwind_context);
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andric // Alternative signal stack (POSIX-only).
3800b57cec5SDimitry Andric void SetAlternateSignalStack();
3810b57cec5SDimitry Andric void UnsetAlternateSignalStack();
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric // Construct a one-line string:
3840b57cec5SDimitry Andric // SUMMARY: SanitizerToolName: error_message
3850b57cec5SDimitry Andric // and pass it to __sanitizer_report_error_summary.
3860b57cec5SDimitry Andric // If alt_tool_name is provided, it's used in place of SanitizerToolName.
3870b57cec5SDimitry Andric void ReportErrorSummary(const char *error_message,
3880b57cec5SDimitry Andric const char *alt_tool_name = nullptr);
3890b57cec5SDimitry Andric // Same as above, but construct error_message as:
3900b57cec5SDimitry Andric // error_type file:line[:column][ function]
3910b57cec5SDimitry Andric void ReportErrorSummary(const char *error_type, const AddressInfo &info,
3920b57cec5SDimitry Andric const char *alt_tool_name = nullptr);
3930b57cec5SDimitry Andric // Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
3940b57cec5SDimitry Andric void ReportErrorSummary(const char *error_type, const StackTrace *trace,
3950b57cec5SDimitry Andric const char *alt_tool_name = nullptr);
3961db9f3b2SDimitry Andric // Skips frames which we consider internal and not usefull to the users.
3971db9f3b2SDimitry Andric const SymbolizedStack *SkipInternalFrames(const SymbolizedStack *frames);
3980b57cec5SDimitry Andric
399349cc55cSDimitry Andric void ReportMmapWriteExec(int prot, int mflags);
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric // Math
4020b57cec5SDimitry Andric #if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
4030b57cec5SDimitry Andric extern "C" {
40468d75effSDimitry Andric unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
40568d75effSDimitry Andric unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
4060b57cec5SDimitry Andric #if defined(_WIN64)
40768d75effSDimitry Andric unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);
40868d75effSDimitry Andric unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
4090b57cec5SDimitry Andric #endif
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric #endif
4120b57cec5SDimitry Andric
MostSignificantSetBitIndex(uptr x)413e8d8bef9SDimitry Andric inline uptr MostSignificantSetBitIndex(uptr x) {
4140b57cec5SDimitry Andric CHECK_NE(x, 0U);
41568d75effSDimitry Andric unsigned long up;
4160b57cec5SDimitry Andric #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
4170b57cec5SDimitry Andric # ifdef _WIN64
4180b57cec5SDimitry Andric up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
4190b57cec5SDimitry Andric # else
4200b57cec5SDimitry Andric up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
4210b57cec5SDimitry Andric # endif
4220b57cec5SDimitry Andric #elif defined(_WIN64)
4230b57cec5SDimitry Andric _BitScanReverse64(&up, x);
4240b57cec5SDimitry Andric #else
4250b57cec5SDimitry Andric _BitScanReverse(&up, x);
4260b57cec5SDimitry Andric #endif
4270b57cec5SDimitry Andric return up;
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric
LeastSignificantSetBitIndex(uptr x)430e8d8bef9SDimitry Andric inline uptr LeastSignificantSetBitIndex(uptr x) {
4310b57cec5SDimitry Andric CHECK_NE(x, 0U);
43268d75effSDimitry Andric unsigned long up;
4330b57cec5SDimitry Andric #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
4340b57cec5SDimitry Andric # ifdef _WIN64
4350b57cec5SDimitry Andric up = __builtin_ctzll(x);
4360b57cec5SDimitry Andric # else
4370b57cec5SDimitry Andric up = __builtin_ctzl(x);
4380b57cec5SDimitry Andric # endif
4390b57cec5SDimitry Andric #elif defined(_WIN64)
4400b57cec5SDimitry Andric _BitScanForward64(&up, x);
4410b57cec5SDimitry Andric #else
4420b57cec5SDimitry Andric _BitScanForward(&up, x);
4430b57cec5SDimitry Andric #endif
4440b57cec5SDimitry Andric return up;
4450b57cec5SDimitry Andric }
4460b57cec5SDimitry Andric
IsPowerOfTwo(uptr x)447349cc55cSDimitry Andric inline constexpr bool IsPowerOfTwo(uptr x) { return (x & (x - 1)) == 0; }
4480b57cec5SDimitry Andric
RoundUpToPowerOfTwo(uptr size)449e8d8bef9SDimitry Andric inline uptr RoundUpToPowerOfTwo(uptr size) {
4500b57cec5SDimitry Andric CHECK(size);
4510b57cec5SDimitry Andric if (IsPowerOfTwo(size)) return size;
4520b57cec5SDimitry Andric
4530b57cec5SDimitry Andric uptr up = MostSignificantSetBitIndex(size);
4540b57cec5SDimitry Andric CHECK_LT(size, (1ULL << (up + 1)));
4550b57cec5SDimitry Andric CHECK_GT(size, (1ULL << up));
4560b57cec5SDimitry Andric return 1ULL << (up + 1);
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric
RoundUpTo(uptr size,uptr boundary)459349cc55cSDimitry Andric inline constexpr uptr RoundUpTo(uptr size, uptr boundary) {
4600b57cec5SDimitry Andric RAW_CHECK(IsPowerOfTwo(boundary));
4610b57cec5SDimitry Andric return (size + boundary - 1) & ~(boundary - 1);
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric
RoundDownTo(uptr x,uptr boundary)464349cc55cSDimitry Andric inline constexpr uptr RoundDownTo(uptr x, uptr boundary) {
4650b57cec5SDimitry Andric return x & ~(boundary - 1);
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric
IsAligned(uptr a,uptr alignment)468349cc55cSDimitry Andric inline constexpr bool IsAligned(uptr a, uptr alignment) {
4690b57cec5SDimitry Andric return (a & (alignment - 1)) == 0;
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric
Log2(uptr x)472e8d8bef9SDimitry Andric inline uptr Log2(uptr x) {
4730b57cec5SDimitry Andric CHECK(IsPowerOfTwo(x));
4740b57cec5SDimitry Andric return LeastSignificantSetBitIndex(x);
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric
4770b57cec5SDimitry Andric // Don't use std::min, std::max or std::swap, to minimize dependency
4780b57cec5SDimitry Andric // on libstdc++.
479fe6060f1SDimitry Andric template <class T>
Min(T a,T b)480fe6060f1SDimitry Andric constexpr T Min(T a, T b) {
481fe6060f1SDimitry Andric return a < b ? a : b;
482fe6060f1SDimitry Andric }
483fe6060f1SDimitry Andric template <class T>
Max(T a,T b)484fe6060f1SDimitry Andric constexpr T Max(T a, T b) {
485fe6060f1SDimitry Andric return a > b ? a : b;
486fe6060f1SDimitry Andric }
4874824e7fdSDimitry Andric template <class T>
Abs(T a)4884824e7fdSDimitry Andric constexpr T Abs(T a) {
4894824e7fdSDimitry Andric return a < 0 ? -a : a;
4904824e7fdSDimitry Andric }
Swap(T & a,T & b)4910b57cec5SDimitry Andric template<class T> void Swap(T& a, T& b) {
4920b57cec5SDimitry Andric T tmp = a;
4930b57cec5SDimitry Andric a = b;
4940b57cec5SDimitry Andric b = tmp;
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric
4970b57cec5SDimitry Andric // Char handling
IsSpace(int c)498e8d8bef9SDimitry Andric inline bool IsSpace(int c) {
4990b57cec5SDimitry Andric return (c == ' ') || (c == '\n') || (c == '\t') ||
5000b57cec5SDimitry Andric (c == '\f') || (c == '\r') || (c == '\v');
5010b57cec5SDimitry Andric }
IsDigit(int c)502e8d8bef9SDimitry Andric inline bool IsDigit(int c) {
5030b57cec5SDimitry Andric return (c >= '0') && (c <= '9');
5040b57cec5SDimitry Andric }
ToLower(int c)505e8d8bef9SDimitry Andric inline int ToLower(int c) {
5060b57cec5SDimitry Andric return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric // A low-level vector based on mmap. May incur a significant memory overhead for
5100b57cec5SDimitry Andric // small vectors.
5110b57cec5SDimitry Andric // WARNING: The current implementation supports only POD types.
512*0fca6ea1SDimitry Andric template <typename T, bool raw_report = false>
5130b57cec5SDimitry Andric class InternalMmapVectorNoCtor {
5140b57cec5SDimitry Andric public:
515e8d8bef9SDimitry Andric using value_type = T;
Initialize(uptr initial_capacity)5160b57cec5SDimitry Andric void Initialize(uptr initial_capacity) {
5170b57cec5SDimitry Andric capacity_bytes_ = 0;
5180b57cec5SDimitry Andric size_ = 0;
5190b57cec5SDimitry Andric data_ = 0;
5200b57cec5SDimitry Andric reserve(initial_capacity);
5210b57cec5SDimitry Andric }
Destroy()522*0fca6ea1SDimitry Andric void Destroy() { UnmapOrDie(data_, capacity_bytes_, raw_report); }
5230b57cec5SDimitry Andric T &operator[](uptr i) {
5240b57cec5SDimitry Andric CHECK_LT(i, size_);
5250b57cec5SDimitry Andric return data_[i];
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric const T &operator[](uptr i) const {
5280b57cec5SDimitry Andric CHECK_LT(i, size_);
5290b57cec5SDimitry Andric return data_[i];
5300b57cec5SDimitry Andric }
push_back(const T & element)5310b57cec5SDimitry Andric void push_back(const T &element) {
53206c3fb27SDimitry Andric if (UNLIKELY(size_ >= capacity())) {
53306c3fb27SDimitry Andric CHECK_EQ(size_, capacity());
5340b57cec5SDimitry Andric uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
5350b57cec5SDimitry Andric Realloc(new_capacity);
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric internal_memcpy(&data_[size_++], &element, sizeof(T));
5380b57cec5SDimitry Andric }
back()5390b57cec5SDimitry Andric T &back() {
5400b57cec5SDimitry Andric CHECK_GT(size_, 0);
5410b57cec5SDimitry Andric return data_[size_ - 1];
5420b57cec5SDimitry Andric }
pop_back()5430b57cec5SDimitry Andric void pop_back() {
5440b57cec5SDimitry Andric CHECK_GT(size_, 0);
5450b57cec5SDimitry Andric size_--;
5460b57cec5SDimitry Andric }
size()5470b57cec5SDimitry Andric uptr size() const {
5480b57cec5SDimitry Andric return size_;
5490b57cec5SDimitry Andric }
data()5500b57cec5SDimitry Andric const T *data() const {
5510b57cec5SDimitry Andric return data_;
5520b57cec5SDimitry Andric }
data()5530b57cec5SDimitry Andric T *data() {
5540b57cec5SDimitry Andric return data_;
5550b57cec5SDimitry Andric }
capacity()5560b57cec5SDimitry Andric uptr capacity() const { return capacity_bytes_ / sizeof(T); }
reserve(uptr new_size)5570b57cec5SDimitry Andric void reserve(uptr new_size) {
5580b57cec5SDimitry Andric // Never downsize internal buffer.
5590b57cec5SDimitry Andric if (new_size > capacity())
5600b57cec5SDimitry Andric Realloc(new_size);
5610b57cec5SDimitry Andric }
resize(uptr new_size)5620b57cec5SDimitry Andric void resize(uptr new_size) {
5630b57cec5SDimitry Andric if (new_size > size_) {
5640b57cec5SDimitry Andric reserve(new_size);
5650b57cec5SDimitry Andric internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_));
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric size_ = new_size;
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric
clear()5700b57cec5SDimitry Andric void clear() { size_ = 0; }
empty()5710b57cec5SDimitry Andric bool empty() const { return size() == 0; }
5720b57cec5SDimitry Andric
begin()5730b57cec5SDimitry Andric const T *begin() const {
5740b57cec5SDimitry Andric return data();
5750b57cec5SDimitry Andric }
begin()5760b57cec5SDimitry Andric T *begin() {
5770b57cec5SDimitry Andric return data();
5780b57cec5SDimitry Andric }
end()5790b57cec5SDimitry Andric const T *end() const {
5800b57cec5SDimitry Andric return data() + size();
5810b57cec5SDimitry Andric }
end()5820b57cec5SDimitry Andric T *end() {
5830b57cec5SDimitry Andric return data() + size();
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric
swap(InternalMmapVectorNoCtor & other)5860b57cec5SDimitry Andric void swap(InternalMmapVectorNoCtor &other) {
5870b57cec5SDimitry Andric Swap(data_, other.data_);
5880b57cec5SDimitry Andric Swap(capacity_bytes_, other.capacity_bytes_);
5890b57cec5SDimitry Andric Swap(size_, other.size_);
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric private:
Realloc(uptr new_capacity)59306c3fb27SDimitry Andric NOINLINE void Realloc(uptr new_capacity) {
5940b57cec5SDimitry Andric CHECK_GT(new_capacity, 0);
5950b57cec5SDimitry Andric CHECK_LE(size_, new_capacity);
5960b57cec5SDimitry Andric uptr new_capacity_bytes =
5970b57cec5SDimitry Andric RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached());
598*0fca6ea1SDimitry Andric T *new_data =
599*0fca6ea1SDimitry Andric (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector", raw_report);
6000b57cec5SDimitry Andric internal_memcpy(new_data, data_, size_ * sizeof(T));
601*0fca6ea1SDimitry Andric UnmapOrDie(data_, capacity_bytes_, raw_report);
6020b57cec5SDimitry Andric data_ = new_data;
6030b57cec5SDimitry Andric capacity_bytes_ = new_capacity_bytes;
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric T *data_;
6070b57cec5SDimitry Andric uptr capacity_bytes_;
6080b57cec5SDimitry Andric uptr size_;
6090b57cec5SDimitry Andric };
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andric template <typename T>
6120b57cec5SDimitry Andric bool operator==(const InternalMmapVectorNoCtor<T> &lhs,
6130b57cec5SDimitry Andric const InternalMmapVectorNoCtor<T> &rhs) {
6140b57cec5SDimitry Andric if (lhs.size() != rhs.size()) return false;
6150b57cec5SDimitry Andric return internal_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
6160b57cec5SDimitry Andric }
6170b57cec5SDimitry Andric
6180b57cec5SDimitry Andric template <typename T>
6190b57cec5SDimitry Andric bool operator!=(const InternalMmapVectorNoCtor<T> &lhs,
6200b57cec5SDimitry Andric const InternalMmapVectorNoCtor<T> &rhs) {
6210b57cec5SDimitry Andric return !(lhs == rhs);
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric
6240b57cec5SDimitry Andric template<typename T>
6250b57cec5SDimitry Andric class InternalMmapVector : public InternalMmapVectorNoCtor<T> {
6260b57cec5SDimitry Andric public:
InternalMmapVector()627480093f4SDimitry Andric InternalMmapVector() { InternalMmapVectorNoCtor<T>::Initialize(0); }
InternalMmapVector(uptr cnt)6280b57cec5SDimitry Andric explicit InternalMmapVector(uptr cnt) {
6290b57cec5SDimitry Andric InternalMmapVectorNoCtor<T>::Initialize(cnt);
6300b57cec5SDimitry Andric this->resize(cnt);
6310b57cec5SDimitry Andric }
~InternalMmapVector()6320b57cec5SDimitry Andric ~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }
6330b57cec5SDimitry Andric // Disallow copies and moves.
6340b57cec5SDimitry Andric InternalMmapVector(const InternalMmapVector &) = delete;
6350b57cec5SDimitry Andric InternalMmapVector &operator=(const InternalMmapVector &) = delete;
6360b57cec5SDimitry Andric InternalMmapVector(InternalMmapVector &&) = delete;
6370b57cec5SDimitry Andric InternalMmapVector &operator=(InternalMmapVector &&) = delete;
6380b57cec5SDimitry Andric };
6390b57cec5SDimitry Andric
640fe6060f1SDimitry Andric class InternalScopedString {
6410b57cec5SDimitry Andric public:
InternalScopedString()642fe6060f1SDimitry Andric InternalScopedString() : buffer_(1) { buffer_[0] = '\0'; }
643fe6060f1SDimitry Andric
length()644fe6060f1SDimitry Andric uptr length() const { return buffer_.size() - 1; }
clear()6450b57cec5SDimitry Andric void clear() {
646fe6060f1SDimitry Andric buffer_.resize(1);
647fe6060f1SDimitry Andric buffer_[0] = '\0';
6480b57cec5SDimitry Andric }
6495f757f3fSDimitry Andric void Append(const char *str);
6505f757f3fSDimitry Andric void AppendF(const char *format, ...) FORMAT(2, 3);
data()651fe6060f1SDimitry Andric const char *data() const { return buffer_.data(); }
data()652fe6060f1SDimitry Andric char *data() { return buffer_.data(); }
6530b57cec5SDimitry Andric
6540b57cec5SDimitry Andric private:
655fe6060f1SDimitry Andric InternalMmapVector<char> buffer_;
6560b57cec5SDimitry Andric };
6570b57cec5SDimitry Andric
6580b57cec5SDimitry Andric template <class T>
6590b57cec5SDimitry Andric struct CompareLess {
operatorCompareLess6600b57cec5SDimitry Andric bool operator()(const T &a, const T &b) const { return a < b; }
6610b57cec5SDimitry Andric };
6620b57cec5SDimitry Andric
6630b57cec5SDimitry Andric // HeapSort for arrays and InternalMmapVector.
6640b57cec5SDimitry Andric template <class T, class Compare = CompareLess<T>>
6650b57cec5SDimitry Andric void Sort(T *v, uptr size, Compare comp = {}) {
6660b57cec5SDimitry Andric if (size < 2)
6670b57cec5SDimitry Andric return;
6680b57cec5SDimitry Andric // Stage 1: insert elements to the heap.
6690b57cec5SDimitry Andric for (uptr i = 1; i < size; i++) {
6700b57cec5SDimitry Andric uptr j, p;
6710b57cec5SDimitry Andric for (j = i; j > 0; j = p) {
6720b57cec5SDimitry Andric p = (j - 1) / 2;
6730b57cec5SDimitry Andric if (comp(v[p], v[j]))
6740b57cec5SDimitry Andric Swap(v[j], v[p]);
6750b57cec5SDimitry Andric else
6760b57cec5SDimitry Andric break;
6770b57cec5SDimitry Andric }
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric // Stage 2: swap largest element with the last one,
6800b57cec5SDimitry Andric // and sink the new top.
6810b57cec5SDimitry Andric for (uptr i = size - 1; i > 0; i--) {
6820b57cec5SDimitry Andric Swap(v[0], v[i]);
6830b57cec5SDimitry Andric uptr j, max_ind;
6840b57cec5SDimitry Andric for (j = 0; j < i; j = max_ind) {
6850b57cec5SDimitry Andric uptr left = 2 * j + 1;
6860b57cec5SDimitry Andric uptr right = 2 * j + 2;
6870b57cec5SDimitry Andric max_ind = j;
6880b57cec5SDimitry Andric if (left < i && comp(v[max_ind], v[left]))
6890b57cec5SDimitry Andric max_ind = left;
6900b57cec5SDimitry Andric if (right < i && comp(v[max_ind], v[right]))
6910b57cec5SDimitry Andric max_ind = right;
6920b57cec5SDimitry Andric if (max_ind != j)
6930b57cec5SDimitry Andric Swap(v[j], v[max_ind]);
6940b57cec5SDimitry Andric else
6950b57cec5SDimitry Andric break;
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andric // Works like std::lower_bound: finds the first element that is not less
7010b57cec5SDimitry Andric // than the val.
7020eae32dcSDimitry Andric template <class Container, class T,
703e8d8bef9SDimitry Andric class Compare = CompareLess<typename Container::value_type>>
7040eae32dcSDimitry Andric uptr InternalLowerBound(const Container &v, const T &val, Compare comp = {}) {
705e8d8bef9SDimitry Andric uptr first = 0;
706e8d8bef9SDimitry Andric uptr last = v.size();
7070b57cec5SDimitry Andric while (last > first) {
7080b57cec5SDimitry Andric uptr mid = (first + last) / 2;
7090b57cec5SDimitry Andric if (comp(v[mid], val))
7100b57cec5SDimitry Andric first = mid + 1;
7110b57cec5SDimitry Andric else
7120b57cec5SDimitry Andric last = mid;
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric return first;
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric enum ModuleArch {
7180b57cec5SDimitry Andric kModuleArchUnknown,
7190b57cec5SDimitry Andric kModuleArchI386,
7200b57cec5SDimitry Andric kModuleArchX86_64,
7210b57cec5SDimitry Andric kModuleArchX86_64H,
7220b57cec5SDimitry Andric kModuleArchARMV6,
7230b57cec5SDimitry Andric kModuleArchARMV7,
7240b57cec5SDimitry Andric kModuleArchARMV7S,
7250b57cec5SDimitry Andric kModuleArchARMV7K,
726e8d8bef9SDimitry Andric kModuleArchARM64,
727bdd1243dSDimitry Andric kModuleArchLoongArch64,
728349cc55cSDimitry Andric kModuleArchRISCV64,
729349cc55cSDimitry Andric kModuleArchHexagon
7300b57cec5SDimitry Andric };
7310b57cec5SDimitry Andric
732e8d8bef9SDimitry Andric // Sorts and removes duplicates from the container.
733e8d8bef9SDimitry Andric template <class Container,
734e8d8bef9SDimitry Andric class Compare = CompareLess<typename Container::value_type>>
735e8d8bef9SDimitry Andric void SortAndDedup(Container &v, Compare comp = {}) {
736e8d8bef9SDimitry Andric Sort(v.data(), v.size(), comp);
737e8d8bef9SDimitry Andric uptr size = v.size();
738e8d8bef9SDimitry Andric if (size < 2)
739e8d8bef9SDimitry Andric return;
740e8d8bef9SDimitry Andric uptr last = 0;
741e8d8bef9SDimitry Andric for (uptr i = 1; i < size; ++i) {
742e8d8bef9SDimitry Andric if (comp(v[last], v[i])) {
743e8d8bef9SDimitry Andric ++last;
744e8d8bef9SDimitry Andric if (last != i)
745e8d8bef9SDimitry Andric v[last] = v[i];
746e8d8bef9SDimitry Andric } else {
747e8d8bef9SDimitry Andric CHECK(!comp(v[i], v[last]));
748e8d8bef9SDimitry Andric }
749e8d8bef9SDimitry Andric }
750e8d8bef9SDimitry Andric v.resize(last + 1);
751e8d8bef9SDimitry Andric }
752e8d8bef9SDimitry Andric
753349cc55cSDimitry Andric constexpr uptr kDefaultFileMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 28);
754349cc55cSDimitry Andric
7550b57cec5SDimitry Andric // Opens the file 'file_name" and reads up to 'max_len' bytes.
7560b57cec5SDimitry Andric // The resulting buffer is mmaped and stored in '*buff'.
7570b57cec5SDimitry Andric // Returns true if file was successfully opened and read.
7580b57cec5SDimitry Andric bool ReadFileToVector(const char *file_name,
7590b57cec5SDimitry Andric InternalMmapVectorNoCtor<char> *buff,
760349cc55cSDimitry Andric uptr max_len = kDefaultFileMaxSize,
761349cc55cSDimitry Andric error_t *errno_p = nullptr);
7620b57cec5SDimitry Andric
7630b57cec5SDimitry Andric // Opens the file 'file_name" and reads up to 'max_len' bytes.
7640b57cec5SDimitry Andric // This function is less I/O efficient than ReadFileToVector as it may reread
7650b57cec5SDimitry Andric // file multiple times to avoid mmap during read attempts. It's used to read
7660b57cec5SDimitry Andric // procmap, so short reads with mmap in between can produce inconsistent result.
7670b57cec5SDimitry Andric // The resulting buffer is mmaped and stored in '*buff'.
7680b57cec5SDimitry Andric // The size of the mmaped region is stored in '*buff_size'.
7690b57cec5SDimitry Andric // The total number of read bytes is stored in '*read_len'.
7700b57cec5SDimitry Andric // Returns true if file was successfully opened and read.
7710b57cec5SDimitry Andric bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
772349cc55cSDimitry Andric uptr *read_len, uptr max_len = kDefaultFileMaxSize,
7730b57cec5SDimitry Andric error_t *errno_p = nullptr);
7740b57cec5SDimitry Andric
77581ad6265SDimitry Andric int GetModuleAndOffsetForPc(uptr pc, char *module_name, uptr module_name_len,
77681ad6265SDimitry Andric uptr *pc_offset);
77781ad6265SDimitry Andric
7780b57cec5SDimitry Andric // When adding a new architecture, don't forget to also update
77968d75effSDimitry Andric // script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cpp.
ModuleArchToString(ModuleArch arch)7800b57cec5SDimitry Andric inline const char *ModuleArchToString(ModuleArch arch) {
7810b57cec5SDimitry Andric switch (arch) {
7820b57cec5SDimitry Andric case kModuleArchUnknown:
7830b57cec5SDimitry Andric return "";
7840b57cec5SDimitry Andric case kModuleArchI386:
7850b57cec5SDimitry Andric return "i386";
7860b57cec5SDimitry Andric case kModuleArchX86_64:
7870b57cec5SDimitry Andric return "x86_64";
7880b57cec5SDimitry Andric case kModuleArchX86_64H:
7890b57cec5SDimitry Andric return "x86_64h";
7900b57cec5SDimitry Andric case kModuleArchARMV6:
7910b57cec5SDimitry Andric return "armv6";
7920b57cec5SDimitry Andric case kModuleArchARMV7:
7930b57cec5SDimitry Andric return "armv7";
7940b57cec5SDimitry Andric case kModuleArchARMV7S:
7950b57cec5SDimitry Andric return "armv7s";
7960b57cec5SDimitry Andric case kModuleArchARMV7K:
7970b57cec5SDimitry Andric return "armv7k";
7980b57cec5SDimitry Andric case kModuleArchARM64:
7990b57cec5SDimitry Andric return "arm64";
800bdd1243dSDimitry Andric case kModuleArchLoongArch64:
801bdd1243dSDimitry Andric return "loongarch64";
802e8d8bef9SDimitry Andric case kModuleArchRISCV64:
803e8d8bef9SDimitry Andric return "riscv64";
804349cc55cSDimitry Andric case kModuleArchHexagon:
805349cc55cSDimitry Andric return "hexagon";
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric CHECK(0 && "Invalid module arch");
8080b57cec5SDimitry Andric return "";
8090b57cec5SDimitry Andric }
8100b57cec5SDimitry Andric
81106c3fb27SDimitry Andric #if SANITIZER_APPLE
81206c3fb27SDimitry Andric const uptr kModuleUUIDSize = 16;
81306c3fb27SDimitry Andric #else
8140eae32dcSDimitry Andric const uptr kModuleUUIDSize = 32;
81506c3fb27SDimitry Andric #endif
8160b57cec5SDimitry Andric const uptr kMaxSegName = 16;
8170b57cec5SDimitry Andric
8180b57cec5SDimitry Andric // Represents a binary loaded into virtual memory (e.g. this can be an
8190b57cec5SDimitry Andric // executable or a shared object).
8200b57cec5SDimitry Andric class LoadedModule {
8210b57cec5SDimitry Andric public:
LoadedModule()8220b57cec5SDimitry Andric LoadedModule()
8230b57cec5SDimitry Andric : full_name_(nullptr),
8240b57cec5SDimitry Andric base_address_(0),
82581ad6265SDimitry Andric max_address_(0),
8260b57cec5SDimitry Andric arch_(kModuleArchUnknown),
8270eae32dcSDimitry Andric uuid_size_(0),
8280b57cec5SDimitry Andric instrumented_(false) {
8290b57cec5SDimitry Andric internal_memset(uuid_, 0, kModuleUUIDSize);
8300b57cec5SDimitry Andric ranges_.clear();
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric void set(const char *module_name, uptr base_address);
8330b57cec5SDimitry Andric void set(const char *module_name, uptr base_address, ModuleArch arch,
8340b57cec5SDimitry Andric u8 uuid[kModuleUUIDSize], bool instrumented);
8350eae32dcSDimitry Andric void setUuid(const char *uuid, uptr size);
8360b57cec5SDimitry Andric void clear();
8370b57cec5SDimitry Andric void addAddressRange(uptr beg, uptr end, bool executable, bool writable,
8380b57cec5SDimitry Andric const char *name = nullptr);
8390b57cec5SDimitry Andric bool containsAddress(uptr address) const;
8400b57cec5SDimitry Andric
full_name()8410b57cec5SDimitry Andric const char *full_name() const { return full_name_; }
base_address()8420b57cec5SDimitry Andric uptr base_address() const { return base_address_; }
max_address()84381ad6265SDimitry Andric uptr max_address() const { return max_address_; }
arch()8440b57cec5SDimitry Andric ModuleArch arch() const { return arch_; }
uuid()8450b57cec5SDimitry Andric const u8 *uuid() const { return uuid_; }
uuid_size()8460eae32dcSDimitry Andric uptr uuid_size() const { return uuid_size_; }
instrumented()8470b57cec5SDimitry Andric bool instrumented() const { return instrumented_; }
8480b57cec5SDimitry Andric
8490b57cec5SDimitry Andric struct AddressRange {
8500b57cec5SDimitry Andric AddressRange *next;
8510b57cec5SDimitry Andric uptr beg;
8520b57cec5SDimitry Andric uptr end;
8530b57cec5SDimitry Andric bool executable;
8540b57cec5SDimitry Andric bool writable;
8550b57cec5SDimitry Andric char name[kMaxSegName];
8560b57cec5SDimitry Andric
AddressRangeAddressRange8570b57cec5SDimitry Andric AddressRange(uptr beg, uptr end, bool executable, bool writable,
8580b57cec5SDimitry Andric const char *name)
8590b57cec5SDimitry Andric : next(nullptr),
8600b57cec5SDimitry Andric beg(beg),
8610b57cec5SDimitry Andric end(end),
8620b57cec5SDimitry Andric executable(executable),
8630b57cec5SDimitry Andric writable(writable) {
8640b57cec5SDimitry Andric internal_strncpy(this->name, (name ? name : ""), ARRAY_SIZE(this->name));
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric };
8670b57cec5SDimitry Andric
ranges()8680b57cec5SDimitry Andric const IntrusiveList<AddressRange> &ranges() const { return ranges_; }
8690b57cec5SDimitry Andric
8700b57cec5SDimitry Andric private:
8710b57cec5SDimitry Andric char *full_name_; // Owned.
8720b57cec5SDimitry Andric uptr base_address_;
87381ad6265SDimitry Andric uptr max_address_;
8740b57cec5SDimitry Andric ModuleArch arch_;
8750eae32dcSDimitry Andric uptr uuid_size_;
8760b57cec5SDimitry Andric u8 uuid_[kModuleUUIDSize];
8770b57cec5SDimitry Andric bool instrumented_;
8780b57cec5SDimitry Andric IntrusiveList<AddressRange> ranges_;
8790b57cec5SDimitry Andric };
8800b57cec5SDimitry Andric
8810b57cec5SDimitry Andric // List of LoadedModules. OS-dependent implementation is responsible for
8820b57cec5SDimitry Andric // filling this information.
8830b57cec5SDimitry Andric class ListOfModules {
8840b57cec5SDimitry Andric public:
ListOfModules()8850b57cec5SDimitry Andric ListOfModules() : initialized(false) {}
~ListOfModules()8860b57cec5SDimitry Andric ~ListOfModules() { clear(); }
8870b57cec5SDimitry Andric void init();
8880b57cec5SDimitry Andric void fallbackInit(); // Uses fallback init if available, otherwise clears
begin()8890b57cec5SDimitry Andric const LoadedModule *begin() const { return modules_.begin(); }
begin()8900b57cec5SDimitry Andric LoadedModule *begin() { return modules_.begin(); }
end()8910b57cec5SDimitry Andric const LoadedModule *end() const { return modules_.end(); }
end()8920b57cec5SDimitry Andric LoadedModule *end() { return modules_.end(); }
size()8930b57cec5SDimitry Andric uptr size() const { return modules_.size(); }
8940b57cec5SDimitry Andric const LoadedModule &operator[](uptr i) const {
8950b57cec5SDimitry Andric CHECK_LT(i, modules_.size());
8960b57cec5SDimitry Andric return modules_[i];
8970b57cec5SDimitry Andric }
8980b57cec5SDimitry Andric
8990b57cec5SDimitry Andric private:
clear()9000b57cec5SDimitry Andric void clear() {
9010b57cec5SDimitry Andric for (auto &module : modules_) module.clear();
9020b57cec5SDimitry Andric modules_.clear();
9030b57cec5SDimitry Andric }
clearOrInit()9040b57cec5SDimitry Andric void clearOrInit() {
9050b57cec5SDimitry Andric initialized ? clear() : modules_.Initialize(kInitialCapacity);
9060b57cec5SDimitry Andric initialized = true;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric
9090b57cec5SDimitry Andric InternalMmapVectorNoCtor<LoadedModule> modules_;
9100b57cec5SDimitry Andric // We rarely have more than 16K loaded modules.
9110b57cec5SDimitry Andric static const uptr kInitialCapacity = 1 << 14;
9120b57cec5SDimitry Andric bool initialized;
9130b57cec5SDimitry Andric };
9140b57cec5SDimitry Andric
9150b57cec5SDimitry Andric // Callback type for iterating over a set of memory ranges.
9160b57cec5SDimitry Andric typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
9170b57cec5SDimitry Andric
9180b57cec5SDimitry Andric enum AndroidApiLevel {
9190b57cec5SDimitry Andric ANDROID_NOT_ANDROID = 0,
9200b57cec5SDimitry Andric ANDROID_KITKAT = 19,
9210b57cec5SDimitry Andric ANDROID_LOLLIPOP_MR1 = 22,
9220b57cec5SDimitry Andric ANDROID_POST_LOLLIPOP = 23
9230b57cec5SDimitry Andric };
9240b57cec5SDimitry Andric
9250b57cec5SDimitry Andric void WriteToSyslog(const char *buffer);
9260b57cec5SDimitry Andric
9270b57cec5SDimitry Andric #if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__)
9280b57cec5SDimitry Andric #define SANITIZER_WIN_TRACE 1
9290b57cec5SDimitry Andric #else
9300b57cec5SDimitry Andric #define SANITIZER_WIN_TRACE 0
9310b57cec5SDimitry Andric #endif
9320b57cec5SDimitry Andric
93381ad6265SDimitry Andric #if SANITIZER_APPLE || SANITIZER_WIN_TRACE
9340b57cec5SDimitry Andric void LogFullErrorReport(const char *buffer);
9350b57cec5SDimitry Andric #else
LogFullErrorReport(const char * buffer)936e8d8bef9SDimitry Andric inline void LogFullErrorReport(const char *buffer) {}
9370b57cec5SDimitry Andric #endif
9380b57cec5SDimitry Andric
93981ad6265SDimitry Andric #if SANITIZER_LINUX || SANITIZER_APPLE
9400b57cec5SDimitry Andric void WriteOneLineToSyslog(const char *s);
9410b57cec5SDimitry Andric void LogMessageOnPrintf(const char *str);
9420b57cec5SDimitry Andric #else
WriteOneLineToSyslog(const char * s)943e8d8bef9SDimitry Andric inline void WriteOneLineToSyslog(const char *s) {}
LogMessageOnPrintf(const char * str)944e8d8bef9SDimitry Andric inline void LogMessageOnPrintf(const char *str) {}
9450b57cec5SDimitry Andric #endif
9460b57cec5SDimitry Andric
9470b57cec5SDimitry Andric #if SANITIZER_LINUX || SANITIZER_WIN_TRACE
9480b57cec5SDimitry Andric // Initialize Android logging. Any writes before this are silently lost.
9490b57cec5SDimitry Andric void AndroidLogInit();
9500b57cec5SDimitry Andric void SetAbortMessage(const char *);
9510b57cec5SDimitry Andric #else
AndroidLogInit()952e8d8bef9SDimitry Andric inline void AndroidLogInit() {}
9530b57cec5SDimitry Andric // FIXME: MacOS implementation could use CRSetCrashLogMessage.
SetAbortMessage(const char *)954e8d8bef9SDimitry Andric inline void SetAbortMessage(const char *) {}
9550b57cec5SDimitry Andric #endif
9560b57cec5SDimitry Andric
9570b57cec5SDimitry Andric #if SANITIZER_ANDROID
9580b57cec5SDimitry Andric void SanitizerInitializeUnwinder();
9590b57cec5SDimitry Andric AndroidApiLevel AndroidGetApiLevel();
9600b57cec5SDimitry Andric #else
AndroidLogWrite(const char * buffer_unused)961e8d8bef9SDimitry Andric inline void AndroidLogWrite(const char *buffer_unused) {}
SanitizerInitializeUnwinder()962e8d8bef9SDimitry Andric inline void SanitizerInitializeUnwinder() {}
AndroidGetApiLevel()963e8d8bef9SDimitry Andric inline AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; }
9640b57cec5SDimitry Andric #endif
9650b57cec5SDimitry Andric
GetPthreadDestructorIterations()966e8d8bef9SDimitry Andric inline uptr GetPthreadDestructorIterations() {
9670b57cec5SDimitry Andric #if SANITIZER_ANDROID
9680b57cec5SDimitry Andric return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;
9690b57cec5SDimitry Andric #elif SANITIZER_POSIX
9700b57cec5SDimitry Andric return 4;
9710b57cec5SDimitry Andric #else
9720b57cec5SDimitry Andric // Unused on Windows.
9730b57cec5SDimitry Andric return 0;
9740b57cec5SDimitry Andric #endif
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric
9775ffd83dbSDimitry Andric void *internal_start_thread(void *(*func)(void*), void *arg);
9780b57cec5SDimitry Andric void internal_join_thread(void *th);
9790b57cec5SDimitry Andric void MaybeStartBackgroudThread();
9800b57cec5SDimitry Andric
9810b57cec5SDimitry Andric // Make the compiler think that something is going on there.
9820b57cec5SDimitry Andric // Use this inside a loop that looks like memset/memcpy/etc to prevent the
9830b57cec5SDimitry Andric // compiler from recognising it and turning it into an actual call to
9840b57cec5SDimitry Andric // memset/memcpy/etc.
SanitizerBreakOptimization(void * arg)9850b57cec5SDimitry Andric static inline void SanitizerBreakOptimization(void *arg) {
9860b57cec5SDimitry Andric #if defined(_MSC_VER) && !defined(__clang__)
9870b57cec5SDimitry Andric _ReadWriteBarrier();
9880b57cec5SDimitry Andric #else
9890b57cec5SDimitry Andric __asm__ __volatile__("" : : "r" (arg) : "memory");
9900b57cec5SDimitry Andric #endif
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric
9930b57cec5SDimitry Andric struct SignalContext {
9940b57cec5SDimitry Andric void *siginfo;
9950b57cec5SDimitry Andric void *context;
9960b57cec5SDimitry Andric uptr addr;
9970b57cec5SDimitry Andric uptr pc;
9980b57cec5SDimitry Andric uptr sp;
9990b57cec5SDimitry Andric uptr bp;
10000b57cec5SDimitry Andric bool is_memory_access;
1001d56accc7SDimitry Andric enum WriteFlag { Unknown, Read, Write } write_flag;
10020b57cec5SDimitry Andric
100368d75effSDimitry Andric // In some cases the kernel cannot provide the true faulting address; `addr`
100468d75effSDimitry Andric // will be zero then. This field allows to distinguish between these cases
100568d75effSDimitry Andric // and dereferences of null.
100668d75effSDimitry Andric bool is_true_faulting_addr;
100768d75effSDimitry Andric
10080b57cec5SDimitry Andric // VS2013 doesn't implement unrestricted unions, so we need a trivial default
10090b57cec5SDimitry Andric // constructor
10100b57cec5SDimitry Andric SignalContext() = default;
10110b57cec5SDimitry Andric
10120b57cec5SDimitry Andric // Creates signal context in a platform-specific manner.
10130b57cec5SDimitry Andric // SignalContext is going to keep pointers to siginfo and context without
10140b57cec5SDimitry Andric // owning them.
SignalContextSignalContext10150b57cec5SDimitry Andric SignalContext(void *siginfo, void *context)
10160b57cec5SDimitry Andric : siginfo(siginfo),
10170b57cec5SDimitry Andric context(context),
10180b57cec5SDimitry Andric addr(GetAddress()),
10190b57cec5SDimitry Andric is_memory_access(IsMemoryAccess()),
102068d75effSDimitry Andric write_flag(GetWriteFlag()),
102168d75effSDimitry Andric is_true_faulting_addr(IsTrueFaultingAddress()) {
10220b57cec5SDimitry Andric InitPcSpBp();
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric
10250b57cec5SDimitry Andric static void DumpAllRegisters(void *context);
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andric // Type of signal e.g. SIGSEGV or EXCEPTION_ACCESS_VIOLATION.
10280b57cec5SDimitry Andric int GetType() const;
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric // String description of the signal.
10310b57cec5SDimitry Andric const char *Describe() const;
10320b57cec5SDimitry Andric
10330b57cec5SDimitry Andric // Returns true if signal is stack overflow.
10340b57cec5SDimitry Andric bool IsStackOverflow() const;
10350b57cec5SDimitry Andric
10360b57cec5SDimitry Andric private:
10370b57cec5SDimitry Andric // Platform specific initialization.
10380b57cec5SDimitry Andric void InitPcSpBp();
10390b57cec5SDimitry Andric uptr GetAddress() const;
10400b57cec5SDimitry Andric WriteFlag GetWriteFlag() const;
10410b57cec5SDimitry Andric bool IsMemoryAccess() const;
104268d75effSDimitry Andric bool IsTrueFaultingAddress() const;
10430b57cec5SDimitry Andric };
10440b57cec5SDimitry Andric
10450b57cec5SDimitry Andric void InitializePlatformEarly();
10460b57cec5SDimitry Andric
10470b57cec5SDimitry Andric template <typename Fn>
10480b57cec5SDimitry Andric class RunOnDestruction {
10490b57cec5SDimitry Andric public:
RunOnDestruction(Fn fn)10500b57cec5SDimitry Andric explicit RunOnDestruction(Fn fn) : fn_(fn) {}
~RunOnDestruction()10510b57cec5SDimitry Andric ~RunOnDestruction() { fn_(); }
10520b57cec5SDimitry Andric
10530b57cec5SDimitry Andric private:
10540b57cec5SDimitry Andric Fn fn_;
10550b57cec5SDimitry Andric };
10560b57cec5SDimitry Andric
10570b57cec5SDimitry Andric // A simple scope guard. Usage:
10580b57cec5SDimitry Andric // auto cleanup = at_scope_exit([]{ do_cleanup; });
10590b57cec5SDimitry Andric template <typename Fn>
at_scope_exit(Fn fn)10600b57cec5SDimitry Andric RunOnDestruction<Fn> at_scope_exit(Fn fn) {
10610b57cec5SDimitry Andric return RunOnDestruction<Fn>(fn);
10620b57cec5SDimitry Andric }
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andric // Linux on 64-bit s390 had a nasty bug that crashes the whole machine
10650b57cec5SDimitry Andric // if a process uses virtual memory over 4TB (as many sanitizers like
10660b57cec5SDimitry Andric // to do). This function will abort the process if running on a kernel
10670b57cec5SDimitry Andric // that looks vulnerable.
10680b57cec5SDimitry Andric #if SANITIZER_LINUX && SANITIZER_S390_64
10690b57cec5SDimitry Andric void AvoidCVE_2016_2143();
10700b57cec5SDimitry Andric #else
AvoidCVE_2016_2143()1071e8d8bef9SDimitry Andric inline void AvoidCVE_2016_2143() {}
10720b57cec5SDimitry Andric #endif
10730b57cec5SDimitry Andric
10740b57cec5SDimitry Andric struct StackDepotStats {
10750b57cec5SDimitry Andric uptr n_uniq_ids;
10760b57cec5SDimitry Andric uptr allocated;
10770b57cec5SDimitry Andric };
10780b57cec5SDimitry Andric
10790b57cec5SDimitry Andric // The default value for allocator_release_to_os_interval_ms common flag to
10800b57cec5SDimitry Andric // indicate that sanitizer allocator should not attempt to release memory to OS.
10810b57cec5SDimitry Andric const s32 kReleaseToOSIntervalNever = -1;
10820b57cec5SDimitry Andric
10830b57cec5SDimitry Andric void CheckNoDeepBind(const char *filename, int flag);
10840b57cec5SDimitry Andric
10850b57cec5SDimitry Andric // Returns the requested amount of random data (up to 256 bytes) that can then
10860b57cec5SDimitry Andric // be used to seed a PRNG. Defaults to blocking like the underlying syscall.
10870b57cec5SDimitry Andric bool GetRandom(void *buffer, uptr length, bool blocking = true);
10880b57cec5SDimitry Andric
10890b57cec5SDimitry Andric // Returns the number of logical processors on the system.
10900b57cec5SDimitry Andric u32 GetNumberOfCPUs();
10910b57cec5SDimitry Andric extern u32 NumberOfCPUsCached;
GetNumberOfCPUsCached()1092e8d8bef9SDimitry Andric inline u32 GetNumberOfCPUsCached() {
10930b57cec5SDimitry Andric if (!NumberOfCPUsCached)
10940b57cec5SDimitry Andric NumberOfCPUsCached = GetNumberOfCPUs();
10950b57cec5SDimitry Andric return NumberOfCPUsCached;
10960b57cec5SDimitry Andric }
10970b57cec5SDimitry Andric
10980b57cec5SDimitry Andric } // namespace __sanitizer
10990b57cec5SDimitry Andric
new(__sanitizer::usize size,__sanitizer::LowLevelAllocator & alloc)1100*0fca6ea1SDimitry Andric inline void *operator new(__sanitizer::usize size,
1101349cc55cSDimitry Andric __sanitizer::LowLevelAllocator &alloc) {
11020b57cec5SDimitry Andric return alloc.Allocate(size);
11030b57cec5SDimitry Andric }
11040b57cec5SDimitry Andric
11050b57cec5SDimitry Andric #endif // SANITIZER_COMMON_H
1106