Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: base/allocator/allocator_shim_unittest.cc

Issue 2499373003: [NOT FOR REVIEW] Basic allocator shim for macOS. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/allocator/allocator_shim_override_mac_symbols.h ('k') | build/config/allocator.gni » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/allocator/allocator_shim.h" 5 #include "base/allocator/allocator_shim.h"
6 6
7 #include <malloc.h>
8 #include <stdlib.h> 7 #include <stdlib.h>
9 #include <string.h> 8 #include <string.h>
10 9
11 #include <memory> 10 #include <memory>
12 #include <new> 11 #include <new>
13 #include <vector> 12 #include <vector>
14 13
15 #include "base/atomicops.h" 14 #include "base/atomicops.h"
16 #include "base/process/process_metrics.h" 15 #include "base/process/process_metrics.h"
17 #include "base/synchronization/waitable_event.h" 16 #include "base/synchronization/waitable_event.h"
18 #include "base/threading/platform_thread.h" 17 #include "base/threading/platform_thread.h"
19 #include "base/threading/thread_local.h" 18 #include "base/threading/thread_local.h"
19 #include "build/build_config.h"
20 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
22 22
23 #if defined(OS_MACOSX)
24 #include <malloc/malloc.h>
25 #else
26 #include <malloc.h>
27 #endif
28
23 #if !defined(OS_WIN) 29 #if !defined(OS_WIN)
24 #include <unistd.h> 30 #include <unistd.h>
25 #endif 31 #endif
26 32
27 // Some new Android NDKs (64 bit) does not expose (p)valloc anymore. These 33 // Some new Android NDKs (64 bit) does not expose (p)valloc anymore. These
28 // functions are implemented at the shim-layer level. 34 // functions are implemented at the shim-layer level.
29 #if defined(OS_ANDROID) 35 #if defined(OS_ANDROID)
30 extern "C" { 36 extern "C" {
31 void* valloc(size_t size); 37 void* valloc(size_t size);
32 void* pvalloc(size_t size); 38 void* pvalloc(size_t size);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 return self->next->realloc_function(self->next, address, size); 105 return self->next->realloc_function(self->next, address, size);
100 } 106 }
101 107
102 static void MockFree(const AllocatorDispatch* self, void* address) { 108 static void MockFree(const AllocatorDispatch* self, void* address) {
103 if (instance_) { 109 if (instance_) {
104 ++instance_->frees_intercepted_by_addr[Hash(address)]; 110 ++instance_->frees_intercepted_by_addr[Hash(address)];
105 } 111 }
106 self->next->free_function(self->next, address); 112 self->next->free_function(self->next, address);
107 } 113 }
108 114
115 static size_t MockGetSizeEstimate(const AllocatorDispatch* self,
116 void* address) {
117 return self->next->get_size_estimate_function(self->next, address);
118 }
119
109 static void NewHandler() { 120 static void NewHandler() {
110 if (!instance_) 121 if (!instance_)
111 return; 122 return;
112 subtle::Barrier_AtomicIncrement(&instance_->num_new_handler_calls, 1); 123 subtle::Barrier_AtomicIncrement(&instance_->num_new_handler_calls, 1);
113 } 124 }
114 125
115 int32_t GetNumberOfNewHandlerCalls() { 126 int32_t GetNumberOfNewHandlerCalls() {
116 return subtle::Acquire_Load(&instance_->num_new_handler_calls); 127 return subtle::Acquire_Load(&instance_->num_new_handler_calls);
117 } 128 }
118 129
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 }; 182 };
172 183
173 AllocatorShimTest* AllocatorShimTest::instance_ = nullptr; 184 AllocatorShimTest* AllocatorShimTest::instance_ = nullptr;
174 185
175 AllocatorDispatch g_mock_dispatch = { 186 AllocatorDispatch g_mock_dispatch = {
176 &AllocatorShimTest::MockAlloc, /* alloc_function */ 187 &AllocatorShimTest::MockAlloc, /* alloc_function */
177 &AllocatorShimTest::MockAllocZeroInit, /* alloc_zero_initialized_function */ 188 &AllocatorShimTest::MockAllocZeroInit, /* alloc_zero_initialized_function */
178 &AllocatorShimTest::MockAllocAligned, /* alloc_aligned_function */ 189 &AllocatorShimTest::MockAllocAligned, /* alloc_aligned_function */
179 &AllocatorShimTest::MockRealloc, /* realloc_function */ 190 &AllocatorShimTest::MockRealloc, /* realloc_function */
180 &AllocatorShimTest::MockFree, /* free_function */ 191 &AllocatorShimTest::MockFree, /* free_function */
192 &AllocatorShimTest::MockGetSizeEstimate,/* get_size_estimate_function */
181 nullptr, /* next */ 193 nullptr, /* next */
182 }; 194 };
183 195
184 TEST_F(AllocatorShimTest, InterceptLibcSymbols) { 196 TEST_F(AllocatorShimTest, InterceptLibcSymbols) {
197 realloc(nullptr, 9);
198
185 InsertAllocatorDispatch(&g_mock_dispatch); 199 InsertAllocatorDispatch(&g_mock_dispatch);
186 200
187 void* alloc_ptr = malloc(19); 201 void* alloc_ptr = malloc(19);
188 ASSERT_NE(nullptr, alloc_ptr); 202 ASSERT_NE(nullptr, alloc_ptr);
189 ASSERT_GE(allocs_intercepted_by_size[19], 1u); 203 ASSERT_GE(allocs_intercepted_by_size[19], 1u);
190 204
191 void* zero_alloc_ptr = calloc(2, 23); 205 void* zero_alloc_ptr = calloc(2, 23);
192 ASSERT_NE(nullptr, zero_alloc_ptr); 206 ASSERT_NE(nullptr, zero_alloc_ptr);
193 ASSERT_GE(zero_allocs_intercepted_by_size[2 * 23], 1u); 207 ASSERT_GE(zero_allocs_intercepted_by_size[2 * 23], 1u);
194 208
195 #if !defined(OS_WIN) 209 #if !defined(OS_WIN) && !defined(OS_MACOSX)
196 void* memalign_ptr = memalign(128, 53); 210 void* memalign_ptr = memalign(128, 53);
197 ASSERT_NE(nullptr, memalign_ptr); 211 ASSERT_NE(nullptr, memalign_ptr);
198 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(memalign_ptr) % 128); 212 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(memalign_ptr) % 128);
199 ASSERT_GE(aligned_allocs_intercepted_by_alignment[128], 1u); 213 ASSERT_GE(aligned_allocs_intercepted_by_alignment[128], 1u);
200 ASSERT_GE(aligned_allocs_intercepted_by_size[53], 1u); 214 ASSERT_GE(aligned_allocs_intercepted_by_size[53], 1u);
201 215
216 void* pvalloc_ptr = pvalloc(67);
217 ASSERT_NE(nullptr, pvalloc_ptr);
218 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(pvalloc_ptr) % kPageSize);
219 ASSERT_GE(aligned_allocs_intercepted_by_alignment[kPageSize], 1u);
220 // pvalloc rounds the size up to the next page.
221 ASSERT_GE(aligned_allocs_intercepted_by_size[kPageSize], 1u);
222 #endif // !OS_WIN && !OS_MACOSX
223
224 #if !defined(OS_WIN)
202 void* posix_memalign_ptr = nullptr; 225 void* posix_memalign_ptr = nullptr;
203 int res = posix_memalign(&posix_memalign_ptr, 256, 59); 226 int res = posix_memalign(&posix_memalign_ptr, 256, 59);
204 ASSERT_EQ(0, res); 227 ASSERT_EQ(0, res);
205 ASSERT_NE(nullptr, posix_memalign_ptr); 228 ASSERT_NE(nullptr, posix_memalign_ptr);
206 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(posix_memalign_ptr) % 256); 229 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(posix_memalign_ptr) % 256);
207 ASSERT_GE(aligned_allocs_intercepted_by_alignment[256], 1u); 230 ASSERT_GE(aligned_allocs_intercepted_by_alignment[256], 1u);
208 ASSERT_GE(aligned_allocs_intercepted_by_size[59], 1u); 231 ASSERT_GE(aligned_allocs_intercepted_by_size[59], 1u);
209 232
210 void* valloc_ptr = valloc(61); 233 void* valloc_ptr = valloc(61);
211 ASSERT_NE(nullptr, valloc_ptr); 234 ASSERT_NE(nullptr, valloc_ptr);
212 const size_t kPageSize = base::GetPageSize(); 235 const size_t kPageSize = base::GetPageSize();
213 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(valloc_ptr) % kPageSize); 236 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(valloc_ptr) % kPageSize);
214 ASSERT_GE(aligned_allocs_intercepted_by_alignment[kPageSize], 1u); 237 ASSERT_GE(aligned_allocs_intercepted_by_alignment[kPageSize], 1u);
215 ASSERT_GE(aligned_allocs_intercepted_by_size[61], 1u); 238 ASSERT_GE(aligned_allocs_intercepted_by_size[61], 1u);
239 #endif // !OS_WIN
216 240
217 void* pvalloc_ptr = pvalloc(67); 241 char* realloc_ptr = static_cast<char*>(malloc(10));
218 ASSERT_NE(nullptr, pvalloc_ptr);
219 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(pvalloc_ptr) % kPageSize);
220 ASSERT_GE(aligned_allocs_intercepted_by_alignment[kPageSize], 1u);
221 // pvalloc rounds the size up to the next page.
222 ASSERT_GE(aligned_allocs_intercepted_by_size[kPageSize], 1u);
223 #endif // OS_WIN
224
225 char* realloc_ptr = static_cast<char*>(realloc(nullptr, 71));
226 ASSERT_NE(nullptr, realloc_ptr);
227 ASSERT_GE(reallocs_intercepted_by_size[71], 1u);
228 ASSERT_GE(reallocs_intercepted_by_addr[Hash(nullptr)], 1u);
229 strcpy(realloc_ptr, "foobar"); 242 strcpy(realloc_ptr, "foobar");
230 void* old_realloc_ptr = realloc_ptr; 243 void* old_realloc_ptr = realloc_ptr;
231 realloc_ptr = static_cast<char*>(realloc(realloc_ptr, 73)); 244 realloc_ptr = static_cast<char*>(realloc(realloc_ptr, 73));
232 ASSERT_GE(reallocs_intercepted_by_size[73], 1u); 245 ASSERT_GE(reallocs_intercepted_by_size[73], 1u);
233 ASSERT_GE(reallocs_intercepted_by_addr[Hash(old_realloc_ptr)], 1u); 246 ASSERT_GE(reallocs_intercepted_by_addr[Hash(old_realloc_ptr)], 1u);
234 ASSERT_EQ(0, strcmp(realloc_ptr, "foobar")); 247 ASSERT_EQ(0, strcmp(realloc_ptr, "foobar"));
235 248
236 free(alloc_ptr); 249 free(alloc_ptr);
237 ASSERT_GE(frees_intercepted_by_addr[Hash(alloc_ptr)], 1u); 250 ASSERT_GE(frees_intercepted_by_addr[Hash(alloc_ptr)], 1u);
238 251
239 free(zero_alloc_ptr); 252 free(zero_alloc_ptr);
240 ASSERT_GE(frees_intercepted_by_addr[Hash(zero_alloc_ptr)], 1u); 253 ASSERT_GE(frees_intercepted_by_addr[Hash(zero_alloc_ptr)], 1u);
241 254
242 #if !defined(OS_WIN) 255 #if !defined(OS_WIN) && !defined(OS_MACOSX)
243 free(memalign_ptr); 256 free(memalign_ptr);
244 ASSERT_GE(frees_intercepted_by_addr[Hash(memalign_ptr)], 1u); 257 ASSERT_GE(frees_intercepted_by_addr[Hash(memalign_ptr)], 1u);
245 258
259 free(pvalloc_ptr);
260 ASSERT_GE(frees_intercepted_by_addr[Hash(pvalloc_ptr)], 1u);
261 #endif // !OS_WIN && !OS_MACOSX
262
263 #if !defined(OS_WIN)
246 free(posix_memalign_ptr); 264 free(posix_memalign_ptr);
247 ASSERT_GE(frees_intercepted_by_addr[Hash(posix_memalign_ptr)], 1u); 265 ASSERT_GE(frees_intercepted_by_addr[Hash(posix_memalign_ptr)], 1u);
248 266
249 free(valloc_ptr); 267 free(valloc_ptr);
250 ASSERT_GE(frees_intercepted_by_addr[Hash(valloc_ptr)], 1u); 268 ASSERT_GE(frees_intercepted_by_addr[Hash(valloc_ptr)], 1u);
251 269 #endif // !OS_WIN
252 free(pvalloc_ptr);
253 ASSERT_GE(frees_intercepted_by_addr[Hash(pvalloc_ptr)], 1u);
254 #endif // OS_WIN
255 270
256 free(realloc_ptr); 271 free(realloc_ptr);
257 ASSERT_GE(frees_intercepted_by_addr[Hash(realloc_ptr)], 1u); 272 ASSERT_GE(frees_intercepted_by_addr[Hash(realloc_ptr)], 1u);
258 273
259 RemoveAllocatorDispatchForTesting(&g_mock_dispatch); 274 RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
260 275
261 void* non_hooked_ptr = malloc(4095); 276 void* non_hooked_ptr = malloc(4095);
262 ASSERT_NE(nullptr, non_hooked_ptr); 277 ASSERT_NE(nullptr, non_hooked_ptr);
263 ASSERT_EQ(0u, allocs_intercepted_by_size[4095]); 278 ASSERT_EQ(0u, allocs_intercepted_by_size[4095]);
264 free(non_hooked_ptr); 279 free(non_hooked_ptr);
(...skipping 26 matching lines...) Expand all
291 306
292 delete new_nt_ptr; 307 delete new_nt_ptr;
293 ASSERT_GE(frees_intercepted_by_addr[Hash(new_nt_ptr)], 1u); 308 ASSERT_GE(frees_intercepted_by_addr[Hash(new_nt_ptr)], 1u);
294 309
295 delete[] new_array_nt_ptr; 310 delete[] new_array_nt_ptr;
296 ASSERT_GE(frees_intercepted_by_addr[Hash(new_array_nt_ptr)], 1u); 311 ASSERT_GE(frees_intercepted_by_addr[Hash(new_array_nt_ptr)], 1u);
297 312
298 RemoveAllocatorDispatchForTesting(&g_mock_dispatch); 313 RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
299 } 314 }
300 315
316 #if !defined(OS_MACOSX)
317
318 /*
319 realloc() on macOS tries to find zone from ptr and asserts when that fails on
320 bogus value 0x420 we're using:
321
322 base_unittests(54335,0x70000da6e000) malloc: *** error for object 0x420: point er being realloc'd was not allocated
323
324 See realloc() implementation in libSystem.
325 */
326
301 // This test exercises the case of concurrent OOM failure, which would end up 327 // This test exercises the case of concurrent OOM failure, which would end up
302 // invoking std::new_handler concurrently. This is to cover the CallNewHandler() 328 // invoking std::new_handler concurrently. This is to cover the CallNewHandler()
303 // paths of allocator_shim.cc and smoke-test its thread safey. 329 // paths of allocator_shim.cc and smoke-test its thread safey.
304 // The test creates kNumThreads threads. Each of them does just a 330 // The test creates kNumThreads threads. Each of them does just a
305 // realloc(0x420). 331 // realloc(0x420).
306 // The shim intercepts such realloc and makes it fail only once on each thread. 332 // The shim intercepts such realloc and makes it fail only once on each thread.
307 // We expect to see excactly kNumThreads invocations of the new_handler. 333 // We expect to see excactly kNumThreads invocations of the new_handler.
308 TEST_F(AllocatorShimTest, NewHandlerConcurrency) { 334 TEST_F(AllocatorShimTest, NewHandlerConcurrency) {
309 const int kNumThreads = 32; 335 const int kNumThreads = 32;
310 PlatformThreadHandle threads[kNumThreads]; 336 PlatformThreadHandle threads[kNumThreads];
(...skipping 11 matching lines...) Expand all
322 std::set_new_handler(&AllocatorShimTest::NewHandler); 348 std::set_new_handler(&AllocatorShimTest::NewHandler);
323 SetCallNewHandlerOnMallocFailure(true); // It's going to fail on realloc(). 349 SetCallNewHandlerOnMallocFailure(true); // It's going to fail on realloc().
324 InsertAllocatorDispatch(&g_mock_dispatch); 350 InsertAllocatorDispatch(&g_mock_dispatch);
325 event.Signal(); 351 event.Signal();
326 for (int i = 0; i < kNumThreads; ++i) 352 for (int i = 0; i < kNumThreads; ++i)
327 PlatformThread::Join(threads[i]); 353 PlatformThread::Join(threads[i]);
328 RemoveAllocatorDispatchForTesting(&g_mock_dispatch); 354 RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
329 ASSERT_EQ(kNumThreads, GetNumberOfNewHandlerCalls()); 355 ASSERT_EQ(kNumThreads, GetNumberOfNewHandlerCalls());
330 } 356 }
331 357
358 #endif
359
332 } // namespace 360 } // namespace
333 } // namespace allocator 361 } // namespace allocator
334 } // namespace base 362 } // namespace base
OLDNEW
« no previous file with comments | « base/allocator/allocator_shim_override_mac_symbols.h ('k') | build/config/allocator.gni » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698