Move the linker allocator into libc
Rename LinkerMemoryAllocator -> BionicAllocator
Rename LinkerSmallObjectAllocator -> BionicSmallObjectAllocator
libc and the linker need to share an instance of the allocator for
allocating and freeing dynamic ELF TLS memory (DTVs and segments). The
linker also continues to use this allocator.
Bug: http://b/78026329
Test: /data/nativetest/bionic-unit-tests-static
Test: /data/nativetest64/bionic-unit-tests-static
Test: /data/nativetest/linker-unit-tests/linker-unit-tests32
Test: /data/nativetest64/linker-unit-tests/linker-unit-tests64
Change-Id: I2da037006ddf8041a75f3eba2071a8fcdcc223ce
diff --git a/libc/Android.bp b/libc/Android.bp
index 6f2e347..226a81f 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1014,6 +1014,7 @@
"bionic/arpa_inet.cpp",
"bionic/assert.cpp",
"bionic/atof.cpp",
+ "bionic/bionic_allocator.cpp",
"bionic/bionic_arc4random.cpp",
"bionic/bionic_futex.cpp",
"bionic/bionic_netlink.cpp",
diff --git a/linker/linker_allocator.cpp b/libc/bionic/bionic_allocator.cpp
similarity index 87%
rename from linker/linker_allocator.cpp
rename to libc/bionic/bionic_allocator.cpp
index df7c999..a933212 100644
--- a/linker/linker_allocator.cpp
+++ b/libc/bionic/bionic_allocator.cpp
@@ -26,7 +26,7 @@
* SUCH DAMAGE.
*/
-#include "linker_allocator.h"
+#include "private/bionic_allocator.h"
#include <stdlib.h>
#include <string.h>
@@ -41,9 +41,8 @@
#include "private/bionic_page.h"
//
-// LinkerMemeoryAllocator is general purpose allocator
-// designed to provide the same functionality as the malloc/free/realloc
-// libc functions.
+// BionicAllocator is a general purpose allocator designed to provide the same
+// functionality as the malloc/free/realloc libc functions.
//
// On alloc:
// If size is >= 1k allocator proxies malloc call directly to mmap
@@ -93,7 +92,7 @@
return result;
}
-LinkerSmallObjectAllocator::LinkerSmallObjectAllocator(uint32_t type,
+BionicSmallObjectAllocator::BionicSmallObjectAllocator(uint32_t type,
size_t block_size)
: type_(type),
block_size_(block_size),
@@ -102,7 +101,7 @@
free_pages_cnt_(0),
page_list_(nullptr) {}
-void* LinkerSmallObjectAllocator::alloc() {
+void* BionicSmallObjectAllocator::alloc() {
CHECK(block_size_ != 0);
if (page_list_ == nullptr) {
@@ -144,7 +143,7 @@
return block_record;
}
-void LinkerSmallObjectAllocator::free_page(small_object_page_info* page) {
+void BionicSmallObjectAllocator::free_page(small_object_page_info* page) {
CHECK(page->free_blocks_cnt == blocks_per_page_);
if (page->prev_page) {
page->prev_page->next_page = page->next_page;
@@ -159,7 +158,7 @@
free_pages_cnt_--;
}
-void LinkerSmallObjectAllocator::free(void* ptr) {
+void BionicSmallObjectAllocator::free(void* ptr) {
small_object_page_info* const page =
reinterpret_cast<small_object_page_info*>(
PAGE_START(reinterpret_cast<uintptr_t>(ptr)));
@@ -189,7 +188,7 @@
}
}
-void LinkerSmallObjectAllocator::alloc_page() {
+void BionicSmallObjectAllocator::alloc_page() {
void* const map_ptr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (map_ptr == MAP_FAILED) {
@@ -197,7 +196,7 @@
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE,
- "linker_alloc_small_objects");
+ "bionic_alloc_small_objects");
small_object_page_info* const page =
reinterpret_cast<small_object_page_info*>(map_ptr);
@@ -223,7 +222,7 @@
free_pages_cnt_++;
}
-void LinkerSmallObjectAllocator::add_to_page_list(small_object_page_info* page) {
+void BionicSmallObjectAllocator::add_to_page_list(small_object_page_info* page) {
page->next_page = page_list_;
page->prev_page = nullptr;
if (page_list_) {
@@ -232,7 +231,7 @@
page_list_ = page;
}
-void LinkerSmallObjectAllocator::remove_from_page_list(
+void BionicSmallObjectAllocator::remove_from_page_list(
small_object_page_info* page) {
if (page->prev_page) {
page->prev_page->next_page = page->next_page;
@@ -247,23 +246,23 @@
page->next_page = nullptr;
}
-void LinkerMemoryAllocator::initialize_allocators() {
+void BionicAllocator::initialize_allocators() {
if (allocators_ != nullptr) {
return;
}
- LinkerSmallObjectAllocator* allocators =
- reinterpret_cast<LinkerSmallObjectAllocator*>(allocators_buf_);
+ BionicSmallObjectAllocator* allocators =
+ reinterpret_cast<BionicSmallObjectAllocator*>(allocators_buf_);
for (size_t i = 0; i < kSmallObjectAllocatorsCount; ++i) {
uint32_t type = i + kSmallObjectMinSizeLog2;
- new (allocators + i) LinkerSmallObjectAllocator(type, 1 << type);
+ new (allocators + i) BionicSmallObjectAllocator(type, 1 << type);
}
allocators_ = allocators;
}
-void* LinkerMemoryAllocator::alloc_mmap(size_t size) {
+void* BionicAllocator::alloc_mmap(size_t size) {
size_t allocated_size = PAGE_END(size + kPageInfoSize);
void* map_ptr = mmap(nullptr, allocated_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
@@ -272,7 +271,7 @@
async_safe_fatal("mmap failed: %s", strerror(errno));
}
- prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob");
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "bionic_alloc_lob");
page_info* info = reinterpret_cast<page_info*>(map_ptr);
memcpy(info->signature, kSignature, sizeof(kSignature));
@@ -283,7 +282,7 @@
kPageInfoSize);
}
-void* LinkerMemoryAllocator::alloc(size_t size) {
+void* BionicAllocator::alloc(size_t size) {
// treat alloc(0) as alloc(1)
if (size == 0) {
size = 1;
@@ -302,7 +301,7 @@
return get_small_object_allocator(log2_size)->alloc();
}
-page_info* LinkerMemoryAllocator::get_page_info(void* ptr) {
+page_info* BionicAllocator::get_page_info(void* ptr) {
page_info* info = reinterpret_cast<page_info*>(PAGE_START(reinterpret_cast<size_t>(ptr)));
if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) {
async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
@@ -311,7 +310,7 @@
return info;
}
-void* LinkerMemoryAllocator::realloc(void* ptr, size_t size) {
+void* BionicAllocator::realloc(void* ptr, size_t size) {
if (ptr == nullptr) {
return alloc(size);
}
@@ -328,7 +327,7 @@
if (info->type == kLargeObject) {
old_size = info->allocated_size - kPageInfoSize;
} else {
- LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
+ BionicSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
if (allocator != info->allocator_addr) {
async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
}
@@ -346,7 +345,7 @@
return ptr;
}
-void LinkerMemoryAllocator::free(void* ptr) {
+void BionicAllocator::free(void* ptr) {
if (ptr == nullptr) {
return;
}
@@ -356,7 +355,7 @@
if (info->type == kLargeObject) {
munmap(info, info->allocated_size);
} else {
- LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
+ BionicSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
if (allocator != info->allocator_addr) {
async_safe_fatal("invalid pointer %p (invalid allocator address for the page)", ptr);
}
@@ -365,7 +364,7 @@
}
}
-LinkerSmallObjectAllocator* LinkerMemoryAllocator::get_small_object_allocator(uint32_t type) {
+BionicSmallObjectAllocator* BionicAllocator::get_small_object_allocator(uint32_t type) {
if (type < kSmallObjectMinSizeLog2 || type > kSmallObjectMaxSizeLog2) {
async_safe_fatal("invalid type: %u", type);
}
diff --git a/linker/linker_allocator.h b/libc/private/bionic_allocator.h
similarity index 85%
rename from linker/linker_allocator.h
rename to libc/private/bionic_allocator.h
index d2b8551..75cbd9d 100644
--- a/linker/linker_allocator.h
+++ b/libc/private/bionic_allocator.h
@@ -40,7 +40,7 @@
const uint32_t kSmallObjectMinSizeLog2 = 4;
const uint32_t kSmallObjectAllocatorsCount = kSmallObjectMaxSizeLog2 - kSmallObjectMinSizeLog2 + 1;
-class LinkerSmallObjectAllocator;
+class BionicSmallObjectAllocator;
// This structure is placed at the beginning of each addressable page
// and has all information we need to find the corresponding memory allocator.
@@ -51,7 +51,7 @@
// we use allocated_size for large objects allocator
size_t allocated_size;
// and allocator_addr for small ones.
- LinkerSmallObjectAllocator* allocator_addr;
+ BionicSmallObjectAllocator* allocator_addr;
};
};
@@ -61,14 +61,14 @@
};
// This structure is placed at the beginning of each page managed by
-// LinkerSmallObjectAllocator. Note that a page_info struct is expected at the
+// BionicSmallObjectAllocator. Note that a page_info struct is expected at the
// beginning of each page as well, and therefore this structure contains a
// page_info as its *first* field.
struct small_object_page_info {
page_info info; // Must be the first field.
// Doubly linked list for traversing all pages allocated by a
- // LinkerSmallObjectAllocator.
+ // BionicSmallObjectAllocator.
small_object_page_info* next_page;
small_object_page_info* prev_page;
@@ -79,9 +79,9 @@
size_t free_blocks_cnt;
};
-class LinkerSmallObjectAllocator {
+class BionicSmallObjectAllocator {
public:
- LinkerSmallObjectAllocator(uint32_t type, size_t block_size);
+ BionicSmallObjectAllocator(uint32_t type, size_t block_size);
void* alloc();
void free(void* ptr);
@@ -101,9 +101,9 @@
small_object_page_info* page_list_;
};
-class LinkerMemoryAllocator {
+class BionicAllocator {
public:
- constexpr LinkerMemoryAllocator() : allocators_(nullptr), allocators_buf_() {}
+ constexpr BionicAllocator() : allocators_(nullptr), allocators_buf_() {}
void* alloc(size_t size);
// Note that this implementation of realloc never shrinks allocation
@@ -112,9 +112,9 @@
private:
void* alloc_mmap(size_t size);
page_info* get_page_info(void* ptr);
- LinkerSmallObjectAllocator* get_small_object_allocator(uint32_t type);
+ BionicSmallObjectAllocator* get_small_object_allocator(uint32_t type);
void initialize_allocators();
- LinkerSmallObjectAllocator* allocators_;
- uint8_t allocators_buf_[sizeof(LinkerSmallObjectAllocator)*kSmallObjectAllocatorsCount];
+ BionicSmallObjectAllocator* allocators_;
+ uint8_t allocators_buf_[sizeof(BionicSmallObjectAllocator)*kSmallObjectAllocatorsCount];
};
diff --git a/linker/Android.bp b/linker/Android.bp
index 4991935..5ae09ba 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -4,7 +4,6 @@
recovery_available: true,
srcs: [
- "linker_allocator.cpp",
"linker_memory.cpp",
],
cflags: [
diff --git a/linker/linker_block_allocator.h b/linker/linker_block_allocator.h
index 85e6bd9..458d092 100644
--- a/linker/linker_block_allocator.h
+++ b/linker/linker_block_allocator.h
@@ -68,18 +68,18 @@
* of a single fixed-size type. Allocations are backed by page-sized private
* anonymous mmaps.
*
- * The differences between this allocator and LinkerMemoryAllocator are:
- * 1. This allocator manages space more efficiently. LinkerMemoryAllocator
- * operates in power-of-two sized blocks up to 1k, when this implementation
- * splits the page to aligned size of structure; For example for structures
- * with size 513 this allocator will use 516 (520 for lp64) bytes of data
- * where generalized implementation is going to use 1024 sized blocks.
+ * The differences between this allocator and BionicAllocator are:
+ * 1. This allocator manages space more efficiently. BionicAllocator operates in
+ * power-of-two sized blocks up to 1k, when this implementation splits the
+ * page to aligned size of structure; For example for structures with size
+ * 513 this allocator will use 516 (520 for lp64) bytes of data where
+ * generalized implementation is going to use 1024 sized blocks.
*
* 2. Unless all allocated memory is freed, this allocator does not munmap
- * allocated memory, where LinkerMemoryAllocator does.
+ * allocated memory, where BionicAllocator does.
*
- * 3. This allocator provides mprotect services to the user, where LinkerMemoryAllocator
- * always treats it's memory as READ|WRITE.
+ * 3. This allocator provides mprotect services to the user, where BionicAllocator
+ * always treats its memory as READ|WRITE.
*/
template<typename T>
class LinkerTypeAllocator {
diff --git a/linker/linker_memory.cpp b/linker/linker_memory.cpp
index f2cce01..ce29997 100644
--- a/linker/linker_memory.cpp
+++ b/linker/linker_memory.cpp
@@ -26,7 +26,7 @@
* SUCH DAMAGE.
*/
-#include "linker_allocator.h"
+#include "private/bionic_allocator.h"
#include <stdlib.h>
#include <sys/cdefs.h>
@@ -36,7 +36,7 @@
#include <async_safe/log.h>
-static LinkerMemoryAllocator g_linker_allocator;
+static BionicAllocator g_bionic_allocator;
static std::atomic<pid_t> fallback_tid(0);
// Used by libdebuggerd_handler to switch allocators during a crash dump, in
@@ -56,16 +56,16 @@
}
}
-static LinkerMemoryAllocator& get_fallback_allocator() {
- static LinkerMemoryAllocator fallback_allocator;
+static BionicAllocator& get_fallback_allocator() {
+ static BionicAllocator fallback_allocator;
return fallback_allocator;
}
-static LinkerMemoryAllocator& get_allocator() {
+static BionicAllocator& get_allocator() {
if (__predict_false(fallback_tid) && __predict_false(gettid() == fallback_tid)) {
return get_fallback_allocator();
}
- return g_linker_allocator;
+ return g_bionic_allocator;
}
void* malloc(size_t byte_count) {
diff --git a/linker/tests/Android.mk b/linker/tests/Android.mk
index 9268e31..63e0555 100644
--- a/linker/tests/Android.mk
+++ b/linker/tests/Android.mk
@@ -43,10 +43,8 @@
linker_config_test.cpp \
linker_globals.cpp \
linked_list_test.cpp \
- linker_memory_allocator_test.cpp \
linker_sleb128_test.cpp \
linker_utils_test.cpp \
- ../linker_allocator.cpp \
../linker_block_allocator.cpp \
../linker_config.cpp \
../linker_utils.cpp \
diff --git a/tests/Android.bp b/tests/Android.bp
index 8ac0531..e123f9e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -661,6 +661,13 @@
"gtest_preinit_debuggerd.cpp",
"gtest_globals.cpp",
"gtest_main.cpp",
+
+ // The Bionic allocator has its own C++ API. It isn't packaged into its
+ // own library, so it can only be tested when it's part of libc.a.
+ "bionic_allocator_test.cpp",
+ ],
+ include_dirs: [
+ "bionic/libc",
],
whole_static_libs: [
"libBionicTests",
diff --git a/linker/tests/linker_memory_allocator_test.cpp b/tests/bionic_allocator_test.cpp
similarity index 92%
rename from linker/tests/linker_memory_allocator_test.cpp
rename to tests/bionic_allocator_test.cpp
index c284eaa..d0ca8ec 100644
--- a/linker/tests/linker_memory_allocator_test.cpp
+++ b/tests/bionic_allocator_test.cpp
@@ -32,7 +32,7 @@
#include <gtest/gtest.h>
-#include "../linker_allocator.h"
+#include "private/bionic_allocator.h"
#include <unistd.h>
@@ -61,20 +61,20 @@
static size_t kPageSize = sysconf(_SC_PAGE_SIZE);
-TEST(linker_memory, test_alloc_0) {
- LinkerMemoryAllocator allocator;
+TEST(bionic_allocator, test_alloc_0) {
+ BionicAllocator allocator;
void* ptr = allocator.alloc(0);
ASSERT_TRUE(ptr != nullptr);
allocator.free(ptr);
}
-TEST(linker_memory, test_free_nullptr) {
- LinkerMemoryAllocator allocator;
+TEST(bionic_allocator, test_free_nullptr) {
+ BionicAllocator allocator;
allocator.free(nullptr);
}
-TEST(linker_memory, test_realloc) {
- LinkerMemoryAllocator allocator;
+TEST(bionic_allocator, test_realloc) {
+ BionicAllocator allocator;
uint32_t* array = reinterpret_cast<uint32_t*>(allocator.alloc(512));
const size_t array_size = 512 / sizeof(uint32_t);
@@ -127,8 +127,8 @@
ASSERT_EQ(nullptr, allocator.realloc(reallocated_ptr, 0));
}
-TEST(linker_memory, test_small_smoke) {
- LinkerMemoryAllocator allocator;
+TEST(bionic_allocator, test_small_smoke) {
+ BionicAllocator allocator;
uint8_t zeros[16];
memset(zeros, 0, sizeof(zeros));
@@ -150,8 +150,8 @@
allocator.free(ptr2);
}
-TEST(linker_memory, test_huge_smoke) {
- LinkerMemoryAllocator allocator;
+TEST(bionic_allocator, test_huge_smoke) {
+ BionicAllocator allocator;
// this should trigger proxy-to-mmap
test_struct_huge* ptr1 =
@@ -170,8 +170,8 @@
allocator.free(ptr1);
}
-TEST(linker_memory, test_large) {
- LinkerMemoryAllocator allocator;
+TEST(bionic_allocator, test_large) {
+ BionicAllocator allocator;
test_struct_large* ptr1 =
reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large)));