• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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