1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares LargeBlockHeap, a heap that directly grabs pages of memory from the
16 : // OS and redzones blocks with entire pages. This is only intended for use with
17 : // sufficiently large allocations (hence the name) where the redzone overhead
18 : // can be amortized.
19 : //
20 : // SyzyAsan overhead is roughly 45% overall, with 25% coming from memory
21 : // allocation overhead (20 + 16 = 36 bytes of overhead for average allocation
22 : // sizes of 144 bytes in Chrome). If we wish to maintain a similar overhead
23 : // then allocations being fed into the large block heap should be at least
24 : // 32KB in size. Ideally the large allocation heap should not be leaned on too
25 : // heavily as it can cause significant memory fragmentation.
26 :
27 : #ifndef SYZYGY_AGENT_ASAN_HEAPS_LARGE_BLOCK_HEAP_H_
28 : #define SYZYGY_AGENT_ASAN_HEAPS_LARGE_BLOCK_HEAP_H_
29 :
30 : #include <unordered_set>
31 :
32 : #include "syzygy/agent/asan/allocators.h"
33 : #include "syzygy/agent/asan/heap.h"
34 : #include "syzygy/agent/asan/memory_notifier.h"
35 : #include "syzygy/common/recursive_lock.h"
36 :
37 : namespace agent {
38 : namespace asan {
39 : namespace heaps {
40 :
41 : class LargeBlockHeap : public BlockHeapInterface {
42 : public:
43 : // Constructor.
44 : // @param internal_heap The heap to use for making internal allocations.
45 : explicit LargeBlockHeap(HeapInterface* internal_heap);
46 :
47 : // Virtual destructor.
48 : virtual ~LargeBlockHeap();
49 :
50 : // @name HeapInterface implementation.
51 : // @{
52 : virtual HeapType GetHeapType() const;
53 : virtual uint32 GetHeapFeatures() const;
54 : virtual void* Allocate(size_t bytes);
55 : virtual bool Free(void* alloc);
56 : virtual bool IsAllocated(const void* alloc);
57 : virtual size_t GetAllocationSize(const void* alloc);
58 : virtual void Lock();
59 : virtual void Unlock();
60 : virtual bool TryLock();
61 : // @}
62 :
63 : // @name BlockHeapInterface implementation.
64 : // @{
65 : virtual void* AllocateBlock(size_t size,
66 : size_t min_left_redzone_size,
67 : size_t min_right_redzone_size,
68 : BlockLayout* layout);
69 : virtual bool FreeBlock(const BlockInfo& block_info);
70 : // @}
71 :
72 : // @returns the number of active allocations in this heap.
73 E : size_t size() const { return allocs_.size(); }
74 :
75 : protected:
76 : // Information about an allocation made by this allocator.
77 : struct Allocation {
78 : const void* address;
79 : size_t size;
80 : };
81 :
82 : // Calculates a hash of an Allocation object by forwarding to the STL
83 : // hash for the allocation address.
84 : struct AllocationHash {
85 E : size_t operator()(const Allocation& allocation) const {
86 : std::hash<const void*> hash;
87 E : return hash(allocation.address);
88 E : }
89 : };
90 :
91 : // Functor for determining if 2 allocation objects are identical. This only
92 : // uses the allocation address as a key.
93 : struct AllocationEqualTo {
94 E : bool operator()(const Allocation& a1, const Allocation& a2) const {
95 E : return a1.address == a2.address;
96 E : }
97 : };
98 :
99 : // The collection of allocations that has been made through this allocator.
100 : // It is expected that a small number of allocations will be made, so keeping
101 : // track of these explicitly is fine for now.
102 : typedef std::unordered_set<
103 : Allocation,
104 : AllocationHash,
105 : AllocationEqualTo,
106 : HeapAllocator<Allocation>> AllocationSet;
107 : AllocationSet allocs_; // Under lock_.
108 :
109 : // The global lock for this allocator.
110 : ::common::RecursiveLock lock_;
111 :
112 : private:
113 : DISALLOW_COPY_AND_ASSIGN(LargeBlockHeap);
114 : };
115 :
116 : } // namespace heaps
117 : } // namespace asan
118 : } // namespace agent
119 :
120 : #endif // SYZYGY_AGENT_ASAN_HEAPS_LARGE_BLOCK_HEAP_H_
|