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(¤t_verbosity, verbosity, memory_order_relaxed); 6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 6186277eb844c4983c81de62d7c050e92fe7155788Stephen HinesINLINE int Verbosity() { 6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return atomic_load(¤t_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