diff --git a/src/mem/chunkmap.h b/src/mem/chunkmap.h index cd37822..fd6b163 100644 --- a/src/mem/chunkmap.h +++ b/src/mem/chunkmap.h @@ -83,81 +83,14 @@ namespace snmalloc FlatPagemap, Pagemap>; - /** - * Mixin used by `ChunkMap` to directly access the pagemap via a global - * variable. This should be used from within the library or program that - * owns the pagemap. - * - * This class makes the global pagemap a static field so that its name - * includes the type mangling. If two compilation units try to instantiate - * two different types of pagemap then they will see two distinct pagemaps. - * This will prevent allocating with one and freeing with the other (because - * the memory will show up as not owned by any allocator in the other - * compilation unit) but will prevent the same memory being interpreted as - * having two different types. - */ - template - class GlobalPagemapTemplate - { - /** - * The global pagemap variable. The name of this symbol will include the - * type of `T`. - */ - inline static T global_pagemap; - - public: - /** - * Returns the pagemap. - */ - static ChunkmapPagemap& pagemap() - { - return global_pagemap; - } - }; - - using GlobalPagemap = GlobalPagemapTemplate; + using GlobalChunkmap = GlobalPagemapTemplate; /** - * Optionally exported function that accesses the global pagemap provided by - * a shared library. + * Optionally exported function that accesses the global chunkmap pagemap + * provided by a shared library. */ - extern "C" void* snmalloc_pagemap_global_get(snmalloc::PagemapConfig const**); - - /** - * Mixin used by `ChunkMap` to access the global pagemap via a - * type-checked C interface. This should be used when another library (e.g. - * your C standard library) uses snmalloc and you wish to use a different - * configuration in your program or library, but wish to share a pagemap so - * that either version can deallocate memory. - */ - class ExternalGlobalPagemap - { - /** - * A pointer to the pagemap. - */ - inline static ChunkmapPagemap* external_pagemap; - - public: - /** - * Returns the exported pagemap. - * Accesses the pagemap via the C ABI accessor and casts it to - * the expected type, failing in cases of ABI mismatch. - */ - static ChunkmapPagemap& pagemap() - { - if (external_pagemap == nullptr) - { - const snmalloc::PagemapConfig* c = nullptr; - void* raw_pagemap = snmalloc_pagemap_global_get(&c); - external_pagemap = ChunkmapPagemap::cast_to_pagemap(raw_pagemap, c); - if (!external_pagemap) - { - Pal::error("Incorrect ABI of global pagemap."); - } - } - return *external_pagemap; - } - }; + extern "C" void* + snmalloc_chunkmap_global_get(snmalloc::PagemapConfig const**); /** * Class that defines an interface to the pagemap. This is provided to @@ -165,7 +98,7 @@ namespace snmalloc * implementation (for example, to move pagemap updates to a different * protection domain). */ - template + template struct DefaultChunkMap { /** diff --git a/src/mem/pagemap.h b/src/mem/pagemap.h index 798c1c9..f549553 100644 --- a/src/mem/pagemap.h +++ b/src/mem/pagemap.h @@ -409,4 +409,74 @@ namespace snmalloc reinterpret_cast(&top[p >> SHIFT]) & ~(OS_PAGE_SIZE - 1)); } }; + + /** + * Mixin used by `ChunkMap` and other `PageMap` consumers to directly access + * the pagemap via a global variable. This should be used from within the + * library or program that owns the pagemap. + * + * This class makes the global pagemap a static field so that its name + * includes the type mangling. If two compilation units try to instantiate + * two different types of pagemap then they will see two distinct pagemaps. + * This will prevent allocating with one and freeing with the other (because + * the memory will show up as not owned by any allocator in the other + * compilation unit) but will prevent the same memory being interpreted as + * having two different types. + */ + template + class GlobalPagemapTemplate + { + /** + * The global pagemap variable. The name of this symbol will include the + * type of `T`. + */ + inline static T global_pagemap; + + public: + /** + * Returns the pagemap. + */ + static T& pagemap() + { + return global_pagemap; + } + }; + + /** + * Mixin used by `ChunkMap` and other `PageMap` consumers to access the global + * pagemap via a type-checked C interface. This should be used when another + * library (e.g. your C standard library) uses snmalloc and you wish to use a + * different configuration in your program or library, but wish to share a + * pagemap so that either version can deallocate memory. + */ + template + class ExternalGlobalPagemapTemplate + { + /** + * A pointer to the pagemap. + */ + inline static T* external_pagemap; + + public: + /** + * Returns the exported pagemap. + * Accesses the pagemap via the C ABI accessor and casts it to + * the expected type, failing in cases of ABI mismatch. + */ + static T& pagemap() + { + if (external_pagemap == nullptr) + { + const snmalloc::PagemapConfig* c = nullptr; + void* raw_pagemap = raw_get(&c); + external_pagemap = T::cast_to_pagemap(raw_pagemap, c); + if (!external_pagemap) + { + Pal::error("Incorrect ABI of global pagemap."); + } + } + return *external_pagemap; + } + }; + } // namespace snmalloc diff --git a/src/override/malloc.cc b/src/override/malloc.cc index dc9f7a4..0c57029 100644 --- a/src/override/malloc.cc +++ b/src/override/malloc.cc @@ -221,10 +221,10 @@ extern "C" * this function to the correct type. This allows us to preserve some * semblance of ABI safety via a pure C API. */ - SNMALLOC_EXPORT void* SNMALLOC_NAME_MANGLE(snmalloc_pagemap_global_get)( + SNMALLOC_EXPORT void* SNMALLOC_NAME_MANGLE(snmalloc_chunkmap_global_get)( PagemapConfig const** config) { - auto& pm = GlobalPagemap::pagemap(); + auto& pm = GlobalChunkmap::pagemap(); if (config) { *config = &ChunkmapPagemap::config; diff --git a/src/test/func/external_pagemap/external_pagemap.cc b/src/test/func/external_pagemap/external_pagemap.cc index 2e56be2..75dc197 100644 --- a/src/test/func/external_pagemap/external_pagemap.cc +++ b/src/test/func/external_pagemap/external_pagemap.cc @@ -10,10 +10,13 @@ int main() # define SNMALLOC_EXPOSE_PAGEMAP 1 # include +using ExternalChunkmap = + ExternalGlobalPagemapTemplate; + int main() { - auto& p = ExternalGlobalPagemap::pagemap(); - auto& global = GlobalPagemap::pagemap(); + auto& p = ExternalChunkmap::pagemap(); + auto& global = GlobalChunkmap::pagemap(); SNMALLOC_CHECK(&p == &global); // Get a valid heap address uintptr_t addr = reinterpret_cast(malloc(42)); diff --git a/src/test/func/two_alloc_types/main.cc b/src/test/func/two_alloc_types/main.cc index 4ce2154..6996f3d 100644 --- a/src/test/func/two_alloc_types/main.cc +++ b/src/test/func/two_alloc_types/main.cc @@ -24,9 +24,9 @@ extern "C" void* enclave_malloc(size_t); extern "C" void enclave_free(void*); extern "C" void* -enclave_snmalloc_pagemap_global_get(snmalloc::PagemapConfig const**); +enclave_snmalloc_chunkmap_global_get(snmalloc::PagemapConfig const**); extern "C" void* -host_snmalloc_pagemap_global_get(snmalloc::PagemapConfig const**); +host_snmalloc_chunkmap_global_get(snmalloc::PagemapConfig const**); using namespace snmalloc; int main() @@ -47,8 +47,8 @@ int main() // Call these functions to trigger asserts if the cast-to-self doesn't work. const PagemapConfig* c; - enclave_snmalloc_pagemap_global_get(&c); - host_snmalloc_pagemap_global_get(&c); + enclave_snmalloc_chunkmap_global_get(&c); + host_snmalloc_chunkmap_global_get(&c); auto a = host_malloc(128); auto b = enclave_malloc(128);