linker: align allocated blocks to 16 bytes

C/C++ requires the result of malloc/new to be
aligned for any primitive type.

Change-Id: I715b7679e738f34b3b409993fb3ef242e1321b7f
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index fc9a75b..23298a4 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -22,9 +22,14 @@
 
 #include "private/bionic_prctl.h"
 
+// the multiplier should be power of 2
+static constexpr size_t round_up(size_t size, size_t multiplier) {
+  return (size + (multiplier - 1)) & ~(multiplier-1);
+}
+
 struct LinkerBlockAllocatorPage {
   LinkerBlockAllocatorPage* next;
-  uint8_t bytes[PAGE_SIZE-sizeof(LinkerBlockAllocatorPage*)];
+  uint8_t bytes[PAGE_SIZE - 16] __attribute__((aligned(16)));
 };
 
 struct FreeBlockInfo {
@@ -33,7 +38,8 @@
 };
 
 LinkerBlockAllocator::LinkerBlockAllocator(size_t block_size)
-  : block_size_(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size),
+  : block_size_(
+      round_up(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size, 16)),
     page_list_(nullptr),
     free_block_list_(nullptr)
 {}
@@ -95,6 +101,9 @@
 }
 
 void LinkerBlockAllocator::create_new_page() {
+  static_assert(sizeof(LinkerBlockAllocatorPage) == PAGE_SIZE,
+                "Invalid sizeof(LinkerBlockAllocatorPage)");
+
   LinkerBlockAllocatorPage* page = reinterpret_cast<LinkerBlockAllocatorPage*>(
       mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0));