1 // Copyright 2019 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ 6 #define BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ 7 8 #include <atomic> 9 #include <vector> 10 11 #include "base/base_export.h" 12 #include "base/memory/raw_ptr_exclusion.h" 13 #include "base/no_destructor.h" 14 15 namespace base { 16 17 namespace android { 18 19 // ReachedAddressesBitset is a set that stores addresses for the 20 // ReachedCodeProfiler in compact form. Its main features are lock-free 21 // thread-safety and fast adding of elements. 22 // 23 // The addresses are kept with |kBytesGranularity| to save the storage space. 24 // 25 // Once insterted, elements cannot be erased from the set. 26 // 27 // All methods can be called from any thread. 28 class BASE_EXPORT ReachedAddressesBitset { 29 public: 30 // Returns an instance of ReachedAddressesBitset having enough storage space 31 // to keep all addresses from the .text section. 32 // Returns nullptr if SUPPORTS_CODE_ORDERING isn't defined. 33 // This instance is stored in the .bss section of the binary, meaning that it 34 // doesn't incur the binary size overhead and it doesn't increase the resident 35 // memory footprint when not used. 36 static ReachedAddressesBitset* GetTextBitset(); 37 38 // Inserts |address| into the bitset iff |address| lies in the range between 39 // |start_address_| and |end_address_|. 40 void RecordAddress(uintptr_t address); 41 42 // Returns a list of recorded addresses in the form of offsets from 43 // |start_address_|. 44 std::vector<uint32_t> GetReachedOffsets() const; 45 46 private: 47 friend class ReachedAddressesBitsetTest; 48 friend class NoDestructor<ReachedAddressesBitset>; 49 50 // Represents the number of bytes that are mapped into the same bit in the 51 // bitset. 52 static constexpr size_t kBytesGranularity = 4; 53 54 // Constructs a ReachedAddressesBitset on top of an external storage of 55 // |storage_size| pointed by |storage_ptr|. This external storage must outlive 56 // the constructed bitset instance. The size of storage must be large enough 57 // to fit all addresses in the range between |start_address| and 58 // |end_address|. 59 ReachedAddressesBitset(uintptr_t start_address, 60 uintptr_t end_address, 61 std::atomic<uint32_t>* storage_ptr, 62 size_t storage_size); 63 64 size_t NumberOfReachableElements() const; 65 66 uintptr_t start_address_; 67 uintptr_t end_address_; 68 // This field is not a raw_ptr<> because the rewriter couldn't handle the 69 // global variable in a build configuration specific code. 70 RAW_PTR_EXCLUSION std::atomic<uint32_t>* reached_; 71 }; 72 73 } // namespace android 74 } // namespace base 75 76 #endif // BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ 77