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 : #include "syzygy/agent/asan/heaps/ctmalloc_heap.h"
16 :
17 : namespace agent {
18 : namespace asan {
19 : namespace heaps {
20 :
21 : namespace {
22 :
23 : // Callback that CtMalloc will invoke when memory is reserved.
24 : void CtMallocMemoryReservedCallback(
25 E : void* user_data, void* addr, size_t length) {
26 E : DCHECK_NE(static_cast<void*>(NULL), user_data);
27 E : DCHECK_NE(static_cast<void*>(NULL), addr);
28 E : DCHECK_LT(0u, length);
29 :
30 : MemoryNotifierInterface* memory_notifier =
31 E : reinterpret_cast<MemoryNotifierInterface*>(user_data);
32 E : memory_notifier->NotifyFutureHeapUse(addr, length);
33 E : }
34 :
35 : // Callback that CtMalloc will invoke when memory is released.
36 : void CtMallocMemoryReleasedCallback(
37 E : void* user_data, void* addr, size_t length) {
38 E : DCHECK_NE(static_cast<void*>(NULL), user_data);
39 E : DCHECK_NE(static_cast<void*>(NULL), addr);
40 E : DCHECK_LT(0u, length);
41 :
42 : MemoryNotifierInterface* memory_notifier =
43 E : reinterpret_cast<MemoryNotifierInterface*>(user_data);
44 E : memory_notifier->NotifyReturnedToOS(addr, length);
45 E : }
46 :
47 : } // namespace
48 :
49 : CtMallocHeap::CtMallocHeap(MemoryNotifierInterface* memory_notifier)
50 E : : memory_notifier_(memory_notifier) {
51 E : DCHECK_NE(static_cast<MemoryNotifierInterface*>(NULL), memory_notifier);
52 :
53 E : ::memset(&allocator_, 0, sizeof(allocator_));
54 :
55 : // Wire the memory notifier up to the underlying CtMalloc implementation via
56 : // the callbacks we added.
57 E : allocator_.root()->callbacks.user_data = memory_notifier;
58 : allocator_.root()->callbacks.reserved_callback =
59 E : &CtMallocMemoryReservedCallback;
60 : allocator_.root()->callbacks.released_callback =
61 E : &CtMallocMemoryReleasedCallback;
62 :
63 : // Initialize the CtMalloc heap.
64 E : allocator_.init();
65 E : }
66 :
67 E : CtMallocHeap::~CtMallocHeap() {
68 : // Shutdown the CtMalloc heap.
69 E : allocator_.shutdown();
70 E : }
71 :
72 E : HeapType CtMallocHeap::GetHeapType() const {
73 E : return kCtMallocHeap;
74 E : }
75 :
76 E : uint32 CtMallocHeap::GetHeapFeatures() const {
77 : return kHeapReportsReservations | kHeapSupportsIsAllocated |
78 E : kHeapSupportsGetAllocationSize | kHeapGetAllocationSizeIsUpperBound;
79 E : }
80 :
81 E : void* CtMallocHeap::Allocate(size_t bytes) {
82 E : ::common::AutoRecursiveLock lock(lock_);
83 E : void* alloc = WTF::partitionAllocGeneric(allocator_.root(), bytes);
84 E : return alloc;
85 E : }
86 :
87 E : bool CtMallocHeap::Free(void* alloc) {
88 E : ::common::AutoRecursiveLock lock(lock_);
89 E : WTF::partitionFreeGeneric(allocator_.root(), alloc);
90 E : return true;
91 E : }
92 :
93 E : bool CtMallocHeap::IsAllocated(const void* alloc) {
94 : if (!WTF::partitionIsAllocatedGeneric(allocator_.root(),
95 E : const_cast<void*>(alloc), -1, NULL))
96 E : return false;
97 E : return true;
98 E : }
99 :
100 E : size_t CtMallocHeap::GetAllocationSize(const void* alloc) {
101 E : if (alloc == NULL)
102 i : return kUnknownSize;
103 :
104 E : size_t allocation_size = 0;
105 : if (!WTF::partitionIsAllocatedGeneric(allocator_.root(),
106 : const_cast<void*>(alloc), -1,
107 E : &allocation_size)) {
108 i : return kUnknownSize;
109 : }
110 E : return allocation_size;
111 E : }
112 :
113 E : void CtMallocHeap::Lock() {
114 E : lock_.Acquire();
115 E : }
116 :
117 E : void CtMallocHeap::Unlock() {
118 E : lock_.Release();
119 E : }
120 :
121 E : bool CtMallocHeap::TryLock() {
122 E : return lock_.Try();
123 E : }
124 :
125 : } // namespace heaps
126 : } // namespace asan
127 : } // namespace agent
|