19edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//===-- sanitizer_common.h --------------------------------------*- C++ -*-===//
29edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//
39edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//                     The LLVM Compiler Infrastructure
49edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//
59edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov// This file is distributed under the University of Illinois Open Source
69edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov// License. See LICENSE.TXT for details.
79edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//
89edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//===----------------------------------------------------------------------===//
99edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//
1086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This file is shared between run-time libraries of sanitizers.
1186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
12230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// It declares common functions and classes that are used in both runtimes.
139edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov// Implementation of some functions are provided in sanitizer_common, while
149edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov// others must be defined by run-time library itself.
159edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov//===----------------------------------------------------------------------===//
169edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov#ifndef SANITIZER_COMMON_H
179edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov#define SANITIZER_COMMON_H
189edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov
1986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_flags.h"
2086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_interface_internal.h"
219edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov#include "sanitizer_internal_defs.h"
22b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany#include "sanitizer_libc.h"
2386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_list.h"
247ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov#include "sanitizer_mutex.h"
259edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov
26c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if defined(_MSC_VER) && !defined(__clang__)
27799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarextern "C" void _ReadWriteBarrier();
28799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#pragma intrinsic(_ReadWriteBarrier)
29799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
30799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
319edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonovnamespace __sanitizer {
322673fd8406197c42f16cede6d287f72169298c2eKostya Serebryanystruct StackTrace;
337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstruct AddressInfo;
349edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov
35230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov// Constants.
365af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryanyconst uptr kWordSize = SANITIZER_WORDSIZE / 8;
37230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovconst uptr kWordSizeInBits = 8 * kWordSize;
38e89f1846d58550f919a0ef9081b11d4b0405019dKostya Serebryany
396a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if defined(__powerpc__) || defined(__powerpc64__)
406a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const uptr kCacheLineSize = 128;
416a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
426a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const uptr kCacheLineSize = 64;
436a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
44230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesconst uptr kMaxPathLength = 4096;
46d64bcf43935c9ceeb7376ca4185662811ae907eaAlexey Samsonov
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesconst uptr kMaxThreadStackSize = 1 << 30;  // 1Gb
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
49799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic const uptr kErrorMessageBufferSize = 1 << 16;
50799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
51799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Denotes fake PC values that come from JIT/JAVA/etc.
52799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// For such PC values __tsan_symbolize_external() will be called.
53799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarconst u64 kExternalPCBit = 1ULL << 60;
54799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
55859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryanyextern const char *SanitizerToolName;  // Can be changed by the tool.
56859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany
5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesextern atomic_uint32_t current_verbosity;
5886277eb844c4983c81de62d7c050e92fe7155788Stephen HinesINLINE void SetVerbosity(int verbosity) {
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_store(&current_verbosity, verbosity, memory_order_relaxed);
6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
6186277eb844c4983c81de62d7c050e92fe7155788Stephen HinesINLINE int Verbosity() {
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return atomic_load(&current_verbosity, memory_order_relaxed);
6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
65f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetPageSize();
66c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern uptr PageSizeCached;
67c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarINLINE uptr GetPageSizeCached() {
68c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (!PageSizeCached)
69c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    PageSizeCached = GetPageSize();
70c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return PageSizeCached;
71c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
72f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetMmapGranularity();
73bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66Timur Iskhodzhanovuptr GetMaxVirtualAddress();
74e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// Threads
75e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid();
76fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovuptr GetThreadSelf();
77ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
78e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov                                uptr *stack_bottom);
7924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
8024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev                          uptr *tls_addr, uptr *tls_size);
81a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov
82a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov// Memory management
83799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
84799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarINLINE void *MmapOrDieQuietly(uptr size, const char *mem_type) {
85799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return MmapOrDie(size, mem_type, /*raw_report*/ true);
86799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
87230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovvoid UnmapOrDie(void *addr, uptr size);
88cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarvoid *MmapFixedNoReserve(uptr fixed_addr, uptr size,
89cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         const char *name = nullptr);
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *MmapNoReserveOrDie(uptr size, const char *mem_type);
919bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryanyvoid *MmapFixedOrDie(uptr fixed_addr, uptr size);
92c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);
93c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid *MmapNoAccess(uptr size);
94cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryany// Map aligned chunk of address space; size and alignment are powers of two.
95cc7525951f401d61e2467f1ebc1b133205516a6cKostya Serebryanyvoid *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
96c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Disallow access to a memory range.  Use MmapFixedNoAccess to allocate an
97259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// unaccessible memory.
98259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool MprotectNoAccess(uptr addr, uptr size);
99c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool MprotectReadOnly(uptr addr, uptr size);
100259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
101dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// Used to check if we can map shadow memory to a fixed location.
102dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonovbool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
103a54aec8ca2e372b1a841d605d53cab5e336aeb03Kostya Serebryanyvoid FlushUnneededShadowMemory(uptr addr, uptr size);
1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid IncreaseTotalMmap(uptr size);
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DecreaseTotalMmap(uptr size);
10686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr GetRSS();
10786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid NoHugePagesInRegion(uptr addr, uptr length);
10886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid DontDumpShadowMemory(uptr addr, uptr length);
109799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Check if the built VMA size matches the runtime one.
110799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid CheckVMASize();
111c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid RunMallocHooks(const void *ptr, uptr size);
112c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid RunFreeHooks(const void *ptr);
113f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov
1146611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov// InternalScopedBuffer can be used instead of large stack arrays to
1156611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov// keep frame size low.
1164fa111ccf225648a3de447a7a1ed6420b3c4b3afKostya Serebryany// FIXME: use InternalAlloc instead of MmapOrDie once
1174fa111ccf225648a3de447a7a1ed6420b3c4b3afKostya Serebryany// InternalAlloc is made libc-free.
1186611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonovtemplate<typename T>
1196611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonovclass InternalScopedBuffer {
1206611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov public:
1216611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  explicit InternalScopedBuffer(uptr cnt) {
1226611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    cnt_ = cnt;
1234fa111ccf225648a3de447a7a1ed6420b3c4b3afKostya Serebryany    ptr_ = (T*)MmapOrDie(cnt * sizeof(T), "InternalScopedBuffer");
1246611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
1256611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  ~InternalScopedBuffer() {
1264fa111ccf225648a3de447a7a1ed6420b3c4b3afKostya Serebryany    UnmapOrDie(ptr_, cnt_ * sizeof(T));
1276611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
1286611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  T &operator[](uptr i) { return ptr_[i]; }
1296611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  T *data() { return ptr_; }
1306611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  uptr size() { return cnt_ * sizeof(T); }
1316611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov
1326611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov private:
1336611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  T *ptr_;
1346611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  uptr cnt_;
1356611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  // Disallow evil constructors.
1366611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  InternalScopedBuffer(const InternalScopedBuffer&);
1376611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  void operator=(const InternalScopedBuffer&);
1386611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov};
1396611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov
140bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonovclass InternalScopedString : public InternalScopedBuffer<char> {
141bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov public:
142bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov  explicit InternalScopedString(uptr max_length)
143bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov      : InternalScopedBuffer<char>(max_length), length_(0) {
144bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov    (*this)[0] = '\0';
145bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov  }
146bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov  uptr length() { return length_; }
147bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov  void clear() {
148bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov    (*this)[0] = '\0';
149bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov    length_ = 0;
150bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov  }
151bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov  void append(const char *format, ...);
152bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov
153bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov private:
154bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov  uptr length_;
155bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov};
156bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov
157d883c8007ea8b5ffad10d82a66b1bb262e109705Alexey Samsonov// Simple low-level (mmap-based) allocator for internal use. Doesn't have
158d883c8007ea8b5ffad10d82a66b1bb262e109705Alexey Samsonov// constructor, so all instances of LowLevelAllocator should be
159d883c8007ea8b5ffad10d82a66b1bb262e109705Alexey Samsonov// linker initialized.
16070e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonovclass LowLevelAllocator {
16170e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov public:
162d883c8007ea8b5ffad10d82a66b1bb262e109705Alexey Samsonov  // Requires an external lock.
16370e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov  void *Allocate(uptr size);
16470e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov private:
16570e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov  char *allocated_end_;
16670e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov  char *allocated_current_;
16770e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov};
16870e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonovtypedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
16970e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov// Allows to register tool-specific callbacks for LowLevelAllocator.
17070e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov// Passing NULL removes the callback.
17170e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonovvoid SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
17270e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov
173f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov// IO
174e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonovvoid RawWrite(const char *buffer);
1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool ColorizeReports();
176799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid RemoveANSIEscapeSequencesFromString(char *buffer);
1777fdcdf5a3a7090ec86d426a815bb42f3d35adf13Alexey Samsonovvoid Printf(const char *format, ...);
1787fdcdf5a3a7090ec86d426a815bb42f3d35adf13Alexey Samsonovvoid Report(const char *format, ...);
179283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryanyvoid SetPrintfAndReportCallback(void (*callback)(const char *));
1802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define VReport(level, ...)                                              \
1812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  do {                                                                   \
18286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \
1832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } while (0)
1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define VPrintf(level, ...)                                              \
1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  do {                                                                   \
18686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \
1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } while (0)
188bb4697fe8cbe79c517e6f85713f2de6bd804209dAlexey Samsonov
1897ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov// Can be used to prevent mixing error reports from different sanitizers.
1907ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonovextern StaticSpinMutex CommonSanitizerReportMutex;
19186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
19286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ReportFile {
19386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void Write(const char *buffer, uptr length);
194259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  bool SupportsColors();
19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void SetReportPath(const char *path);
19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
19786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Don't use fields directly. They are only declared public to allow
19886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // aggregate initialization.
19986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
20086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Protects fields below.
20186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  StaticSpinMutex *mu;
20286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Opened file descriptor. Defaults to stderr. It may be equal to
20386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // kInvalidFd, in which case new file will be opened when necessary.
20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  fd_t fd;
20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Path prefix of report file, set via __sanitizer_set_report_path.
20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char path_prefix[kMaxPathLength];
20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Full path to report, obtained as <path_prefix>.PID
20886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char full_path[kMaxPathLength];
20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // PID of the process that opened fd. If a fork() occurs,
21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // the PID of child will be different from fd_pid.
21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr fd_pid;
21286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines private:
21486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void ReopenIfNecessary();
21586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
21686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesextern ReportFile report_file;
21786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern uptr stoptheworld_tracer_pid;
2192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern uptr stoptheworld_tracer_ppid;
220e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov
2217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarenum FileAccessMode {
2227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  RdOnly,
2237c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  WrOnly,
2247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  RdWr
2257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar};
2267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
227259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// Returns kInvalidFd on error.
228259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarfd_t OpenFile(const char *filename, FileAccessMode mode,
229259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar              error_t *errno_p = nullptr);
230259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarvoid CloseFile(fd_t);
231259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
232259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// Return true on success, false on error.
233259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool ReadFromFile(fd_t fd, void *buff, uptr buff_size,
234259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar                  uptr *bytes_read = nullptr, error_t *error_p = nullptr);
235259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool WriteToFile(fd_t fd, const void *buff, uptr buff_size,
236259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar                 uptr *bytes_written = nullptr, error_t *error_p = nullptr);
237259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
238259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool RenameFile(const char *oldpath, const char *newpath,
239259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar                error_t *error_p = nullptr);
240259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
241799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Scoped file handle closer.
242799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstruct FileCloser {
243799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  explicit FileCloser(fd_t fd) : fd(fd) {}
244799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ~FileCloser() { CloseFile(fd); }
245799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  fd_t fd;
246799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar};
247799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
248259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool SupportsColoredOutput(fd_t fd);
249259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
250cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov// Opens the file 'file_name" and reads up to 'max_len' bytes.
251cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov// The resulting buffer is mmaped and stored in '*buff'.
252799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// The size of the mmaped region is stored in '*buff_size'.
253799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// The total number of read bytes is stored in '*read_len'.
254799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Returns true if file was successfully opened and read.
255799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarbool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
256799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                      uptr *read_len, uptr max_len = 1 << 26,
257799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                      error_t *errno_p = nullptr);
258a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov// Maps given file to virtual memory, and returns pointer to it
259259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar// (or NULL if mapping fails). Stores the size of mmaped region
260a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov// in '*buff_size'.
261a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonovvoid *MapFileToMemory(const char *file_name, uptr *buff_size);
262799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset);
263a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov
2646d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool IsAccessibleMemoryRange(uptr beg, uptr size);
2656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
26690b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov// Error report formatting.
26790b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonovconst char *StripPathPrefix(const char *filepath,
26890b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov                            const char *strip_file_prefix);
2696d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// Strip the directories from the module name.
2706d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesconst char *StripModuleName(const char *module);
27190b0f1e3ba126bb2e92ab51ef379c98782c23d90Alexey Samsonov
272d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov// OS
273cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainaruptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
274799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainaruptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);
275799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainaruptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);
276799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarconst char *GetProcessName();
277799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid UpdateProcessName();
278cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarvoid CacheBinaryName();
2796d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid DisableCoreDumperIfNecessary();
280d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid DumpProcessMap();
28193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename);
2823dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name);
283ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonovbool SetEnv(const char *name, const char *value);
2840969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovconst char *GetPwd();
2851dcd1d9d1c86ab9b728386d261fbebe00b32e097Alexey Samsonovchar *FindPathToBinary(const char *name);
2867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool IsPathSeparator(const char c);
2877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool IsAbsolutePath(const char *path);
288c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Starts a subprocess and returs its pid.
289c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// If *_fd parameters are not kInvalidFd their corresponding input/output
290c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// streams will be redirect to the file. The files will always be closed
291c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// in parent process even in case of an error.
292c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// The child process will close all fds after STDERR_FILENO
293c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// before passing control to a program.
294c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarpid_t StartSubprocess(const char *filename, const char *const argv[],
295c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                      fd_t stdin_fd = kInvalidFd, fd_t stdout_fd = kInvalidFd,
296c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                      fd_t stderr_fd = kInvalidFd);
297c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Checks if specified process is still running
298c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool IsProcessRunning(pid_t pid);
299c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Waits for the process to finish and returns its exit code.
300c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Returns -1 in case of an error.
301c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarint WaitForProcess(pid_t pid);
3027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
3030fa691b7ec97d8c3948a637d6263822ed4e738f7Alexey Samsonovu32 GetUid();
304d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec();
305c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarchar **GetArgv();
306c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid PrintCmdline();
307d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovbool StackSizeIsUnlimited();
308c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainaruptr GetStackSizeLimitInBytes();
309d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid SetStackSizeLimitInBytes(uptr limit);
3106d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool AddressSpaceIsUnlimited();
3116d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid SetAddressSpaceUnlimited();
3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AdjustStackSize(void *attr);
3132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid PrepareForSandboxing(__sanitizer_sandbox_arguments *args);
3142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
3152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid SetSandboxingCallback(void (*f)());
3162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
31786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid CoverageUpdateMapping();
3186a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid CovBeforeFork();
3196a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid CovAfterFork(int child_pid);
320cffe2f5c30c27234260d004b54152916ff0c45c6Alexey Samsonov
32186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid InitializeCoverage(bool enabled, const char *coverage_dir);
32286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid ReInitializeCoverage(bool enabled, const char *coverage_dir);
32386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
324b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize();
325b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize();
326b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
327be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov// Other
328fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid SleepForSeconds(int seconds);
3290969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovvoid SleepForMillis(int millis);
3304bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime();
331fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovint Atexit(void (*function)(void));
3324c49666e611f06241bb8462cea7674d877241492Alexey Samsonovvoid SortArray(uptr *array, uptr size);
33386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool TemplateMatch(const char *templ, const char *str);
334be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov
335591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov// Exit
336591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN Abort();
337591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid NORETURN Die();
3383c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovvoid NORETURN
339591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey SamsonovCheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
340799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
341799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                                      const char *mmap_type, error_t err,
342799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                                      bool raw_report = false);
343591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov
344dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany// Set the name of the current thread to 'name', return true on succees.
345dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany// The name may be truncated to a system-dependent limit.
346dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerSetThreadName(const char *name);
347dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany// Get the name of the current thread (no more than max_len bytes),
348dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany// return true on succees. name should have space for at least max_len+1 bytes.
349dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerGetThreadName(char *name, int max_len);
350dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany
351591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov// Specific tools may override behavior of "Die" and "CheckFailed" functions
352591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov// to do tool-specific job.
35390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevtypedef void (*DieCallbackType)(void);
354799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
355799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// It's possible to add several callbacks that would be run when "Die" is
356799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// called. The callbacks will be run in the opposite order. The tools are
357799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// strongly recommended to setup all callbacks during initialization, when there
358799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// is only a single thread.
359799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarbool AddDieCallback(DieCallbackType callback);
360799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarbool RemoveDieCallback(DieCallbackType callback);
361799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
362799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid SetUserDieCallback(DieCallbackType callback);
363799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
364591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovtypedef void (*CheckFailedCallbackType)(const char *, int, const char *,
365591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov                                       u64, u64);
366591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid SetCheckFailedCallback(CheckFailedCallbackType callback);
367591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov
36886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Callback will be called if soft_rss_limit_mb is given and the limit is
36986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// exceeded (exceeded==true) or if rss went down below the limit
37086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// (exceeded==false).
37186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// The callback should be registered once at the tool init time.
37286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded));
37386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
3742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Functions related to signal handling.
3752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef void (*SignalHandlerType)(int, void *, void *);
376c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool IsHandledDeadlySignal(int signum);
3772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid InstallDeadlySignalHandlers(SignalHandlerType handler);
3782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Alternative signal stack (POSIX-only).
3792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid SetAlternateSignalStack();
3802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid UnsetAlternateSignalStack();
3812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
3822fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov// We don't want a summary too long.
3832fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonovconst int kMaxSummaryLength = 1024;
3842fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov// Construct a one-line string:
3852fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov//   SUMMARY: SanitizerToolName: error_message
3862fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov// and pass it to __sanitizer_report_error_summary.
3872fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonovvoid ReportErrorSummary(const char *error_message);
3882fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonov// Same as above, but construct error_message as:
3897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar//   error_type file:line[:column][ function]
3907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid ReportErrorSummary(const char *error_type, const AddressInfo &info);
3917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
3922fb08720b11b4c339e191b90d85477c6a2dd74dbAlexey Samsonovvoid ReportErrorSummary(const char *error_type, StackTrace *trace);
3932673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany
3944c49666e611f06241bb8462cea7674d877241492Alexey Samsonov// Math
395c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukov#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
396400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanovextern "C" {
397400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanovunsigned char _BitScanForward(unsigned long *index, unsigned long mask);  // NOLINT
398400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanovunsigned char _BitScanReverse(unsigned long *index, unsigned long mask);  // NOLINT
399400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov#if defined(_WIN64)
400400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanovunsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);  // NOLINT
401400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanovunsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);  // NOLINT
402400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov#endif
403400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov}
404400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov#endif
405400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
406400a946f7300de3db5c50585e3b0aff2ac3c6509Timur IskhodzhanovINLINE uptr MostSignificantSetBitIndex(uptr x) {
407f155fccd1f26f771c9f7f265a4c30faebdfb214fKostya Serebryany  CHECK_NE(x, 0U);
408400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  unsigned long up;  // NOLINT
409c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukov#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
410799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# ifdef _WIN64
411799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
412799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# else
413400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
414799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# endif
415400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov#elif defined(_WIN64)
416400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  _BitScanReverse64(&up, x);
417400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov#else
418400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  _BitScanReverse(&up, x);
419400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov#endif
420400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  return up;
421400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov}
422400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
4232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINLINE uptr LeastSignificantSetBitIndex(uptr x) {
4242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK_NE(x, 0U);
4252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  unsigned long up;  // NOLINT
4262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
427799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# ifdef _WIN64
428799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  up = __builtin_ctzll(x);
429799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# else
4302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  up = __builtin_ctzl(x);
431799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# endif
4322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif defined(_WIN64)
4332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  _BitScanForward64(&up, x);
4342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  _BitScanForward(&up, x);
4362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return up;
4382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
440b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry VyukovINLINE bool IsPowerOfTwo(uptr x) {
441230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  return (x & (x - 1)) == 0;
442230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
443400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
444400a946f7300de3db5c50585e3b0aff2ac3c6509Timur IskhodzhanovINLINE uptr RoundUpToPowerOfTwo(uptr size) {
445400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  CHECK(size);
446400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  if (IsPowerOfTwo(size)) return size;
447400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
448400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  uptr up = MostSignificantSetBitIndex(size);
449400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  CHECK(size < (1ULL << (up + 1)));
450400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  CHECK(size > (1ULL << up));
451799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return 1ULL << (up + 1);
452400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov}
453400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
454b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry VyukovINLINE uptr RoundUpTo(uptr size, uptr boundary) {
455799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  RAW_CHECK(IsPowerOfTwo(boundary));
456230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  return (size + boundary - 1) & ~(boundary - 1);
457230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
458400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
459bc9940eedb51dd43d844a4c46e17bc89f872781fKostya SerebryanyINLINE uptr RoundDownTo(uptr x, uptr boundary) {
460bc9940eedb51dd43d844a4c46e17bc89f872781fKostya Serebryany  return x & ~(boundary - 1);
461bc9940eedb51dd43d844a4c46e17bc89f872781fKostya Serebryany}
462400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
46384a996fc1057ffea9213608c47a54c3d3d3aed02Kostya SerebryanyINLINE bool IsAligned(uptr a, uptr alignment) {
46484a996fc1057ffea9213608c47a54c3d3d3aed02Kostya Serebryany  return (a & (alignment - 1)) == 0;
46584a996fc1057ffea9213608c47a54c3d3d3aed02Kostya Serebryany}
466400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
467400a946f7300de3db5c50585e3b0aff2ac3c6509Timur IskhodzhanovINLINE uptr Log2(uptr x) {
468400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov  CHECK(IsPowerOfTwo(x));
469799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return LeastSignificantSetBitIndex(x);
470400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov}
471400a946f7300de3db5c50585e3b0aff2ac3c6509Timur Iskhodzhanov
4720dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// Don't use std::min, std::max or std::swap, to minimize dependency
4730dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov// on libstdc++.
4744c49666e611f06241bb8462cea7674d877241492Alexey Samsonovtemplate<class T> T Min(T a, T b) { return a < b ? a : b; }
4754c49666e611f06241bb8462cea7674d877241492Alexey Samsonovtemplate<class T> T Max(T a, T b) { return a > b ? a : b; }
4760dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonovtemplate<class T> void Swap(T& a, T& b) {
4770dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov  T tmp = a;
4780dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov  a = b;
4790dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov  b = tmp;
4800dc3177d6c54fafb9577254a93b2f3c4169129d7Alexey Samsonov}
4819edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov
482c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov// Char handling
483b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry VyukovINLINE bool IsSpace(int c) {
484c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return (c == ' ') || (c == '\n') || (c == '\t') ||
485c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov         (c == '\f') || (c == '\r') || (c == '\v');
486c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov}
487b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry VyukovINLINE bool IsDigit(int c) {
488c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return (c >= '0') && (c <= '9');
489c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov}
490b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry VyukovINLINE int ToLower(int c) {
491c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
492c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov}
493c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
494b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany// A low-level vector based on mmap. May incur a significant memory overhead for
495b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany// small vectors.
496b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany// WARNING: The current implementation supports only POD types.
497b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryanytemplate<typename T>
49886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesclass InternalMmapVectorNoCtor {
499b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany public:
50086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void Initialize(uptr initial_capacity) {
5012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    capacity_ = Max(initial_capacity, (uptr)1);
502b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    size_ = 0;
50386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVectorNoCtor");
504b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  }
50586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void Destroy() {
506b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    UnmapOrDie(data_, capacity_ * sizeof(T));
507b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  }
508b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  T &operator[](uptr i) {
50996950030d58582acbd13939916dc2e507304b7e2Alexey Samsonov    CHECK_LT(i, size_);
510ca280f2809eea49ac90860a5827c81dd09c65cdbAlexey Samsonov    return data_[i];
511ca280f2809eea49ac90860a5827c81dd09c65cdbAlexey Samsonov  }
512ca280f2809eea49ac90860a5827c81dd09c65cdbAlexey Samsonov  const T &operator[](uptr i) const {
51396950030d58582acbd13939916dc2e507304b7e2Alexey Samsonov    CHECK_LT(i, size_);
514b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    return data_[i];
515b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  }
516b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  void push_back(const T &element) {
517b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    CHECK_LE(size_, capacity_);
518b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    if (size_ == capacity_) {
519b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany      uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
520b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany      Resize(new_capacity);
521b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    }
522c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    internal_memcpy(&data_[size_++], &element, sizeof(T));
523b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  }
524352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov  T &back() {
525352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov    CHECK_GT(size_, 0);
526352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov    return data_[size_ - 1];
527352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov  }
528352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov  void pop_back() {
529352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov    CHECK_GT(size_, 0);
530352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov    size_--;
531352b245d32c6022a6eb5f5dec7f1d341c4ab88a3Alexey Samsonov  }
532ca280f2809eea49ac90860a5827c81dd09c65cdbAlexey Samsonov  uptr size() const {
533b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    return size_;
534b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  }
535e5b398f7aba39c4ac04d1e8a0d08cdede3b14b59Alexander Potapenko  const T *data() const {
536e5b398f7aba39c4ac04d1e8a0d08cdede3b14b59Alexander Potapenko    return data_;
537e5b398f7aba39c4ac04d1e8a0d08cdede3b14b59Alexander Potapenko  }
5387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  T *data() {
5397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return data_;
5407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
541e5b398f7aba39c4ac04d1e8a0d08cdede3b14b59Alexander Potapenko  uptr capacity() const {
542e5b398f7aba39c4ac04d1e8a0d08cdede3b14b59Alexander Potapenko    return capacity_;
543e5b398f7aba39c4ac04d1e8a0d08cdede3b14b59Alexander Potapenko  }
544b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany
545dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson  void clear() { size_ = 0; }
5467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool empty() const { return size() == 0; }
547dbd69cc9ccda50efd0305cd0ce9bad50defe4b42Bob Wilson
548c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const T *begin() const {
549c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return data();
550c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
551c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  T *begin() {
552c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return data();
553c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
554c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const T *end() const {
555c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return data() + size();
556c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
557c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  T *end() {
558c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return data() + size();
559c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
560c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
561b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany private:
562b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  void Resize(uptr new_capacity) {
563b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    CHECK_GT(new_capacity, 0);
564b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    CHECK_LE(size_, new_capacity);
565b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T),
566a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonov                                 "InternalMmapVector");
567b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    internal_memcpy(new_data, data_, size_ * sizeof(T));
568b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    T *old_data = data_;
569b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    data_ = new_data;
570b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    UnmapOrDie(old_data, capacity_ * sizeof(T));
571b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany    capacity_ = new_capacity;
572b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  }
573b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany
574b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  T *data_;
575b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  uptr capacity_;
576b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany  uptr size_;
577b5f952134cad10f8416ebeccf375da771e4b9ca9Kostya Serebryany};
57815bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev
57986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestemplate<typename T>
58086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesclass InternalMmapVector : public InternalMmapVectorNoCtor<T> {
58186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines public:
58286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  explicit InternalMmapVector(uptr initial_capacity) {
58386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    InternalMmapVectorNoCtor<T>::Initialize(initial_capacity);
58486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
58586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }
58686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Disallow evil constructors.
58786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  InternalMmapVector(const InternalMmapVector&);
58886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void operator=(const InternalMmapVector&);
58986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
59086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
591a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonov// HeapSort for arrays and InternalMmapVector.
59215bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevtemplate<class Container, class Compare>
59315bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveevvoid InternalSort(Container *v, uptr size, Compare comp) {
59415bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  if (size < 2)
59515bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    return;
59615bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  // Stage 1: insert elements to the heap.
59715bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  for (uptr i = 1; i < size; i++) {
59815bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    uptr j, p;
59915bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    for (j = i; j > 0; j = p) {
60015bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      p = (j - 1) / 2;
60115bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      if (comp((*v)[p], (*v)[j]))
60215bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev        Swap((*v)[j], (*v)[p]);
60315bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      else
60415bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev        break;
60515bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    }
60615bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  }
60715bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  // Stage 2: swap largest element with the last one,
60815bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  // and sink the new top.
60915bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  for (uptr i = size - 1; i > 0; i--) {
61015bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    Swap((*v)[0], (*v)[i]);
61115bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    uptr j, max_ind;
61215bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    for (j = 0; j < i; j = max_ind) {
61315bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      uptr left = 2 * j + 1;
61415bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      uptr right = 2 * j + 2;
61515bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      max_ind = j;
61615bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      if (left < i && comp((*v)[max_ind], (*v)[left]))
61715bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev        max_ind = left;
61815bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      if (right < i && comp((*v)[max_ind], (*v)[right]))
61915bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev        max_ind = right;
62015bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      if (max_ind != j)
62115bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev        Swap((*v)[j], (*v)[max_ind]);
62215bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev      else
62315bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev        break;
62415bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev    }
62515bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev  }
62615bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev}
62715bb32b9e1342030a6c4742625f3c3356de42a2aSergey Matveev
628384a448fbe081352f7b3bb927093412ad1725cffSergey Matveevtemplate<class Container, class Value, class Compare>
629384a448fbe081352f7b3bb927093412ad1725cffSergey Matveevuptr InternalBinarySearch(const Container &v, uptr first, uptr last,
630384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev                          const Value &val, Compare comp) {
631384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev  uptr not_found = last + 1;
632384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev  while (last >= first) {
633384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev    uptr mid = (first + last) / 2;
634384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev    if (comp(v[mid], val))
635384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev      first = mid + 1;
636384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev    else if (comp(val, v[mid]))
637384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev      last = mid - 1;
638384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev    else
639384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev      return mid;
640384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev  }
641384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev  return not_found;
642384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev}
643384a448fbe081352f7b3bb927093412ad1725cffSergey Matveev
6447847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov// Represents a binary loaded into virtual memory (e.g. this can be an
6457847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov// executable or a shared object).
6467847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovclass LoadedModule {
6477847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov public:
648259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  LoadedModule() : full_name_(nullptr), base_address_(0) { ranges_.clear(); }
649259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  void set(const char *module_name, uptr base_address);
65086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void clear();
6516a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  void addAddressRange(uptr beg, uptr end, bool executable);
6527847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  bool containsAddress(uptr address) const;
6537847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
6547847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  const char *full_name() const { return full_name_; }
6557847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  uptr base_address() const { return base_address_; }
6567847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
6577847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  struct AddressRange {
65886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AddressRange *next;
6597847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    uptr beg;
6607847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    uptr end;
66186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    bool executable;
66286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
66386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AddressRange(uptr beg, uptr end, bool executable)
66486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        : next(nullptr), beg(beg), end(end), executable(executable) {}
6657847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  };
66686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
667c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const IntrusiveList<AddressRange> &ranges() const { return ranges_; }
66886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
66986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines private:
67086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char *full_name_;  // Owned.
6717847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  uptr base_address_;
67286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  IntrusiveList<AddressRange> ranges_;
6737847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov};
6747847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
675c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// List of LoadedModules. OS-dependent implementation is responsible for
676c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// filling this information.
677c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarclass ListOfModules {
678c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar public:
679c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ListOfModules() : modules_(kInitialCapacity) {}
680c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ~ListOfModules() { clear(); }
681c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  void init();
682c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const LoadedModule *begin() const { return modules_.begin(); }
683c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  LoadedModule *begin() { return modules_.begin(); }
684c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const LoadedModule *end() const { return modules_.end(); }
685c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  LoadedModule *end() { return modules_.end(); }
686c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr size() const { return modules_.size(); }
687c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const LoadedModule &operator[](uptr i) const {
688c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    CHECK_LT(i, modules_.size());
689c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return modules_[i];
690c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
691c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
692c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar private:
693c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  void clear() {
694c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    for (auto &module : modules_) module.clear();
695c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    modules_.clear();
696c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
697c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
698c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  InternalMmapVector<LoadedModule> modules_;
699c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // We rarely have more than 16K loaded modules.
700c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  static const uptr kInitialCapacity = 1 << 14;
701c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar};
7027847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
703799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Callback type for iterating over a set of memory ranges.
704799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainartypedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
705799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
706799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarenum AndroidApiLevel {
707799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ANDROID_NOT_ANDROID = 0,
708799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ANDROID_KITKAT = 19,
709799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ANDROID_LOLLIPOP_MR1 = 22,
710799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ANDROID_POST_LOLLIPOP = 23
711799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar};
712799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
713799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid WriteToSyslog(const char *buffer);
714799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
715799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_MAC
716799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid LogFullErrorReport(const char *buffer);
71770db33e143303752c7fe8800d15b5b31066b1e0dSergey Matveev#else
718799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarINLINE void LogFullErrorReport(const char *buffer) {}
71970db33e143303752c7fe8800d15b5b31066b1e0dSergey Matveev#endif
720c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev
721799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_LINUX || SANITIZER_MAC
722799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid WriteOneLineToSyslog(const char *s);
723c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid LogMessageOnPrintf(const char *str);
724799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else
725799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarINLINE void WriteOneLineToSyslog(const char *s) {}
726c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarINLINE void LogMessageOnPrintf(const char *str) {}
727799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
7282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
729799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_LINUX
730aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov// Initialize Android logging. Any writes before this are silently lost.
731aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanovvoid AndroidLogInit();
7322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
733aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy StepanovINLINE void AndroidLogInit() {}
734799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
735799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
736799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_ANDROID
737799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid SanitizerInitializeUnwinder();
738799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarAndroidApiLevel AndroidGetApiLevel();
739799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else
7402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINLINE void AndroidLogWrite(const char *buffer_unused) {}
7412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINLINE void SanitizerInitializeUnwinder() {}
742799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarINLINE AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; }
743799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
744799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
745799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarINLINE uptr GetPthreadDestructorIterations() {
746799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_ANDROID
747799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;
748799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#elif SANITIZER_POSIX
749799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return 4;
750799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else
751799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Unused on Windows.
752799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return 0;
7532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
754799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
75586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
75686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void(*func)(void*), void *arg);
75786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th);
75886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid MaybeStartBackgroudThread();
75986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
76086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Make the compiler think that something is going on there.
76186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Use this inside a loop that looks like memset/memcpy/etc to prevent the
76286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// compiler from recognising it and turning it into an actual call to
76386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// memset/memcpy/etc.
76486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic inline void SanitizerBreakOptimization(void *arg) {
765c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if defined(_MSC_VER) && !defined(__clang__)
766799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  _ReadWriteBarrier();
76786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else
76886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asm__ __volatile__("" : : "r" (arg) : "memory");
76986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
77086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
77186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
7727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstruct SignalContext {
7737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  void *context;
7747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr addr;
7757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr pc;
7767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr sp;
7777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr bp;
778c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  bool is_memory_access;
7797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
780c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
781c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
782c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp,
783c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                bool is_memory_access, WriteFlag write_flag)
784c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      : context(context),
785c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        addr(addr),
786c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        pc(pc),
787c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        sp(sp),
788c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        bp(bp),
789c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        is_memory_access(is_memory_access),
790c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        write_flag(write_flag) {}
7917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
7927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // Creates signal context in a platform-specific manner.
7937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  static SignalContext Create(void *siginfo, void *context);
794c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
795c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Returns true if the "context" indicates a memory write.
796c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  static WriteFlag GetWriteFlag(void *context);
7977c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar};
7987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
7997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
8007c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
801799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid MaybeReexec();
802799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
803c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainartemplate <typename Fn>
804c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarclass RunOnDestruction {
805c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar public:
806c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  explicit RunOnDestruction(Fn fn) : fn_(fn) {}
807c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ~RunOnDestruction() { fn_(); }
808c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
809c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar private:
810c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Fn fn_;
811c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar};
812c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
813c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// A simple scope guard. Usage:
814c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// auto cleanup = at_scope_exit([]{ do_cleanup; });
815c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainartemplate <typename Fn>
816c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarRunOnDestruction<Fn> at_scope_exit(Fn fn) {
817c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return RunOnDestruction<Fn>(fn);
818c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
819c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
820c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Linux on 64-bit s390 had a nasty bug that crashes the whole machine
821c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// if a process uses virtual memory over 4TB (as many sanitizers like
822c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// to do).  This function will abort the process if running on a kernel
823c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// that looks vulnerable.
824c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if SANITIZER_LINUX && SANITIZER_S390_64
825c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid AvoidCVE_2016_2143();
826c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
827c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarINLINE void AvoidCVE_2016_2143() {}
828c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
829c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
8309edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov}  // namespace __sanitizer
8319edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov
83253177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourneinline void *operator new(__sanitizer::operator_new_size_type size,
83353177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne                          __sanitizer::LowLevelAllocator &alloc) {
83453177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne  return alloc.Allocate(size);
83553177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne}
83653177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne
8372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct StackDepotStats {
8382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr n_uniq_ids;
8392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr allocated;
8402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
8412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8429edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov#endif  // SANITIZER_COMMON_H
843