1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <stdlib.h> 30 #include <string.h> 31 #include <sys/mman.h> 32 33 #include <gtest/gtest.h> 34 35 #include "linker_block_allocator.h" 36 37 #include <unistd.h> 38 39 namespace { 40 41 struct test_struct_nominal { 42 void* pointer; 43 ssize_t value; 44 }; 45 46 /* 47 * this one has size below allocator cap which is 2*sizeof(void*) 48 */ 49 struct test_struct_small { 50 char dummy_str[5]; 51 }; 52 53 /* 54 * 1009 byte struct (1009 is prime) 55 */ 56 struct test_struct_larger { 57 char dummy_str[1009]; 58 }; 59 60 static size_t kPageSize = sysconf(_SC_PAGE_SIZE); 61 }; 62 63 TEST(linker_allocator, test_nominal) { 64 LinkerTypeAllocator<test_struct_nominal> allocator; 65 66 test_struct_nominal* ptr1 = allocator.alloc(); 67 ASSERT_TRUE(ptr1 != nullptr); 68 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16); 69 test_struct_nominal* ptr2 = allocator.alloc(); 70 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16); 71 ASSERT_TRUE(ptr2 != nullptr); 72 // they should be next to each other. 73 ASSERT_EQ(reinterpret_cast<uint8_t*>(ptr1)+16, reinterpret_cast<uint8_t*>(ptr2)); 74 75 ptr1->value = 42; 76 77 allocator.free(ptr1); 78 allocator.free(ptr2); 79 } 80 81 TEST(linker_allocator, test_small) { 82 LinkerTypeAllocator<test_struct_small> allocator; 83 84 char* ptr1 = reinterpret_cast<char*>(allocator.alloc()); 85 char* ptr2 = reinterpret_cast<char*>(allocator.alloc()); 86 87 ASSERT_TRUE(ptr1 != nullptr); 88 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16); 89 ASSERT_TRUE(ptr2 != nullptr); 90 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16); 91 ASSERT_EQ(ptr1+16, ptr2); // aligned to 16 92 } 93 94 TEST(linker_allocator, test_larger) { 95 LinkerTypeAllocator<test_struct_larger> allocator; 96 97 test_struct_larger* ptr1 = allocator.alloc(); 98 test_struct_larger* ptr2 = allocator.alloc(); 99 100 ASSERT_TRUE(ptr1 != nullptr); 101 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16); 102 ASSERT_TRUE(ptr2 != nullptr); 103 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16); 104 105 ASSERT_EQ(reinterpret_cast<uint8_t*>(ptr1) + 1024, reinterpret_cast<uint8_t*>(ptr2)); 106 107 // lets allocate until we reach next page. 108 size_t n = kPageSize/sizeof(test_struct_larger) + 1 - 2; 109 110 for (size_t i=0; i<n; ++i) { 111 ASSERT_TRUE(allocator.alloc() != nullptr); 112 } 113 114 test_struct_larger* ptr_to_free = allocator.alloc(); 115 ASSERT_TRUE(ptr_to_free != nullptr); 116 allocator.free(ptr1); 117 } 118 119 static void protect_all() { 120 LinkerTypeAllocator<test_struct_larger> allocator; 121 122 // number of allocs to reach the end of first page 123 size_t n = kPageSize/sizeof(test_struct_larger) - 1; 124 test_struct_larger* page1_ptr = allocator.alloc(); 125 126 for (size_t i=0; i<n; ++i) { 127 allocator.alloc(); 128 } 129 130 test_struct_larger* page2_ptr = allocator.alloc(); 131 allocator.protect_all(PROT_READ); 132 allocator.protect_all(PROT_READ | PROT_WRITE); 133 // check access 134 page2_ptr->dummy_str[23] = 27; 135 page1_ptr->dummy_str[13] = 11; 136 137 allocator.protect_all(PROT_READ); 138 fprintf(stderr, "trying to access protected page"); 139 140 // this should result in segmentation fault 141 page1_ptr->dummy_str[11] = 7; 142 } 143 144 TEST(linker_allocator, test_protect) { 145 testing::FLAGS_gtest_death_test_style = "threadsafe"; 146 ASSERT_EXIT(protect_all(), testing::KilledBySignal(SIGSEGV), "trying to access protected page"); 147 } 148