Skip to content

Commit 8371df9

Browse files
committed
Use SNMALLOC_API macro for non-template API functions
Introduce SNMALLOC_API macro for public API functions (dealloc, debug_teardown, libc::malloc, etc.) that need standalone definitions when compiled into a static library. Defaults to SNMALLOC_FAST_PATH_INLINE (normal header-only usage). testlib.cc defines SNMALLOC_API as NOINLINE on MSVC before including snmalloc.h, producing strong definitions that ARM64EC exit-thunks can reference. On GCC/Clang, __attribute__((used)) via the existing SNMALLOC_USED_FUNCTION annotation suffices.
1 parent 5f23bc4 commit 8371df9

File tree

4 files changed

+39
-56
lines changed

4 files changed

+39
-56
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ install(DIRECTORY src/snmalloc/ds_aal DESTINATION include/snmalloc)
801801
install(DIRECTORY src/snmalloc/ds_core DESTINATION include/snmalloc)
802802
install(DIRECTORY src/snmalloc/global DESTINATION include/snmalloc)
803803
install(DIRECTORY src/snmalloc/mem DESTINATION include/snmalloc)
804+
install(DIRECTORY src/snmalloc/mitigations DESTINATION include/snmalloc)
804805
install(DIRECTORY src/snmalloc/override DESTINATION include/snmalloc)
805806
install(DIRECTORY src/snmalloc/pal DESTINATION include/snmalloc)
806807
install(DIRECTORY src/snmalloc/stl DESTINATION include/snmalloc)

src/snmalloc/global/globalalloc.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
#include "../mem/mem.h"
44
#include "threadalloc.h"
55

6+
// Non-template API functions use SNMALLOC_API for their linkage specifier.
7+
// Normally inline; can be overridden to NOINLINE (via SNMALLOC_API_NOINLINE)
8+
// to produce strong definitions in a standalone compilation unit.
9+
#ifndef SNMALLOC_API
10+
# define SNMALLOC_API SNMALLOC_FAST_PATH_INLINE
11+
# define SNMALLOC_API_SLOW inline
12+
#endif
13+
614
namespace snmalloc
715
{
816
template<SNMALLOC_CONCEPT(IsConfig) Config_ = Config>
@@ -363,12 +371,12 @@ namespace snmalloc
363371
aligned_size(align, size));
364372
}
365373

366-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void dealloc(void* p)
374+
SNMALLOC_USED_FUNCTION SNMALLOC_API void dealloc(void* p)
367375
{
368376
ThreadAlloc::get().dealloc<ThreadAlloc::CheckInit>(p);
369377
}
370378

371-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void
379+
SNMALLOC_USED_FUNCTION SNMALLOC_API void
372380
dealloc(void* p, size_t size)
373381
{
374382
check_size(p, size);
@@ -382,15 +390,15 @@ namespace snmalloc
382390
ThreadAlloc::get().dealloc<ThreadAlloc::CheckInit>(p);
383391
}
384392

385-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void
393+
SNMALLOC_USED_FUNCTION SNMALLOC_API void
386394
dealloc(void* p, size_t size, size_t align)
387395
{
388396
auto rsize = aligned_size(align, size);
389397
check_size(p, rsize);
390398
ThreadAlloc::get().dealloc<ThreadAlloc::CheckInit>(p);
391399
}
392400

393-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void debug_teardown()
401+
SNMALLOC_USED_FUNCTION SNMALLOC_API void debug_teardown()
394402
{
395403
return ThreadAlloc::teardown();
396404
}

src/snmalloc/global/libc.h

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@ namespace snmalloc::libc
1919
return err;
2020
}
2121

22-
SNMALLOC_USED_FUNCTION inline void* __malloc_end_pointer(void* ptr)
22+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW void* __malloc_end_pointer(void* ptr)
2323
{
2424
return snmalloc::external_pointer<OnePastEnd>(ptr);
2525
}
2626

27-
SNMALLOC_USED_FUNCTION inline void* __malloc_start_pointer(void* ptr)
27+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW void* __malloc_start_pointer(void* ptr)
2828
{
2929
return snmalloc::external_pointer<Start>(ptr);
3030
}
3131

32-
SNMALLOC_USED_FUNCTION inline void* __malloc_last_byte_pointer(void* ptr)
32+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW void* __malloc_last_byte_pointer(void* ptr)
3333
{
3434
return snmalloc::external_pointer<End>(ptr);
3535
}
3636

37-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void* malloc(size_t size)
37+
SNMALLOC_USED_FUNCTION SNMALLOC_API void* malloc(size_t size)
3838
{
3939
return snmalloc::alloc(size);
4040
}
@@ -43,7 +43,7 @@ namespace snmalloc::libc
4343
* Allocate for a pre-computed small sizeclass.
4444
* Use is_small_sizeclass() + size_to_sizeclass_const() to get the class.
4545
*/
46-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void*
46+
SNMALLOC_USED_FUNCTION SNMALLOC_API void*
4747
malloc_small(smallsizeclass_t sizeclass)
4848
{
4949
return snmalloc::alloc(sizeclass);
@@ -52,30 +52,30 @@ namespace snmalloc::libc
5252
/**
5353
* Allocate zeroed memory for a pre-computed small sizeclass.
5454
*/
55-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void*
55+
SNMALLOC_USED_FUNCTION SNMALLOC_API void*
5656
malloc_small_zero(smallsizeclass_t sizeclass)
5757
{
5858
return snmalloc::alloc<Zero>(sizeclass);
5959
}
6060

61-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void free(void* ptr)
61+
SNMALLOC_USED_FUNCTION SNMALLOC_API void free(void* ptr)
6262
{
6363
dealloc(ptr);
6464
}
6565

66-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void
66+
SNMALLOC_USED_FUNCTION SNMALLOC_API void
6767
free_sized(void* ptr, size_t size)
6868
{
6969
dealloc(ptr, size);
7070
}
7171

72-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void
72+
SNMALLOC_USED_FUNCTION SNMALLOC_API void
7373
free_aligned_sized(void* ptr, size_t alignment, size_t size)
7474
{
7575
dealloc(ptr, size, alignment);
7676
}
7777

78-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void*
78+
SNMALLOC_USED_FUNCTION SNMALLOC_API void*
7979
calloc(size_t nmemb, size_t size)
8080
{
8181
bool overflow = false;
@@ -87,7 +87,7 @@ namespace snmalloc::libc
8787
return alloc<Zero>(sz);
8888
}
8989

90-
SNMALLOC_USED_FUNCTION SNMALLOC_FAST_PATH_INLINE void*
90+
SNMALLOC_USED_FUNCTION SNMALLOC_API void*
9191
realloc(void* ptr, size_t size)
9292
{
9393
// Glibc treats
@@ -137,12 +137,12 @@ namespace snmalloc::libc
137137
return p;
138138
}
139139

140-
SNMALLOC_USED_FUNCTION inline size_t malloc_usable_size(const void* ptr)
140+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW size_t malloc_usable_size(const void* ptr)
141141
{
142142
return alloc_size(ptr);
143143
}
144144

145-
SNMALLOC_USED_FUNCTION inline void*
145+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW void*
146146
reallocarray(void* ptr, size_t nmemb, size_t size)
147147
{
148148
bool overflow = false;
@@ -154,7 +154,7 @@ namespace snmalloc::libc
154154
return realloc(ptr, sz);
155155
}
156156

157-
SNMALLOC_USED_FUNCTION inline int
157+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW int
158158
reallocarr(void* ptr_, size_t nmemb, size_t size)
159159
{
160160
int err = errno;
@@ -190,7 +190,7 @@ namespace snmalloc::libc
190190
return 0;
191191
}
192192

193-
SNMALLOC_USED_FUNCTION inline void*
193+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW void*
194194
memalign(size_t alignment, size_t size)
195195
{
196196
if (SNMALLOC_UNLIKELY(alignment == 0 || !bits::is_pow2(alignment)))
@@ -201,13 +201,13 @@ namespace snmalloc::libc
201201
return alloc_aligned(alignment, size);
202202
}
203203

204-
SNMALLOC_USED_FUNCTION inline void*
204+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW void*
205205
aligned_alloc(size_t alignment, size_t size)
206206
{
207207
return memalign(alignment, size);
208208
}
209209

210-
SNMALLOC_USED_FUNCTION inline int
210+
SNMALLOC_USED_FUNCTION SNMALLOC_API_SLOW int
211211
posix_memalign(void** memptr, size_t alignment, size_t size)
212212
{
213213
if (SNMALLOC_UNLIKELY(

src/test/snmalloc_testlib.cc

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
* ODR-conflicting with the templates).
2323
*/
2424

25+
// On MSVC (where SNMALLOC_USED_FUNCTION is empty), override the testlib
26+
// inline macros to produce strong (non-inline) definitions so the linker
27+
// can resolve ARM64EC exit-thunks. On GCC/Clang, __attribute__((used))
28+
// already handles this.
29+
#ifdef _MSC_VER
30+
# define SNMALLOC_API NOINLINE
31+
# define SNMALLOC_API_SLOW NOINLINE
32+
#endif
33+
2534
#include <snmalloc/snmalloc.h>
2635

2736
namespace snmalloc
@@ -167,41 +176,6 @@ namespace snmalloc
167176
{
168177
Aal::pause();
169178
}
170-
171-
// -- Force emission of inline functions for MSVC (where USED_FUNCTION is
172-
// empty). Taking the address of each inline function forces the compiler to
173-
// emit a definition in this TU, making it available to testlib consumers.
174-
175-
SNMALLOC_USED_FUNCTION static const volatile void* force_emit_global[] = {
176-
reinterpret_cast<volatile void*>(
177-
static_cast<void (*)(void*)>(&dealloc)),
178-
reinterpret_cast<volatile void*>(
179-
static_cast<void (*)(void*, size_t)>(&dealloc)),
180-
reinterpret_cast<volatile void*>(
181-
static_cast<void (*)(void*, size_t, size_t)>(&dealloc)),
182-
reinterpret_cast<volatile void*>(&debug_teardown),
183-
};
184-
185-
namespace libc
186-
{
187-
SNMALLOC_USED_FUNCTION static const volatile void* force_emit_libc[] = {
188-
reinterpret_cast<volatile void*>(&__malloc_start_pointer),
189-
reinterpret_cast<volatile void*>(&__malloc_last_byte_pointer),
190-
reinterpret_cast<volatile void*>(&__malloc_end_pointer),
191-
reinterpret_cast<volatile void*>(&malloc),
192-
reinterpret_cast<volatile void*>(&free),
193-
reinterpret_cast<volatile void*>(
194-
static_cast<void* (*)(size_t, size_t)>(&calloc)),
195-
reinterpret_cast<volatile void*>(
196-
static_cast<void* (*)(void*, size_t)>(&realloc)),
197-
reinterpret_cast<volatile void*>(&malloc_usable_size),
198-
reinterpret_cast<volatile void*>(&memalign),
199-
reinterpret_cast<volatile void*>(&aligned_alloc),
200-
reinterpret_cast<volatile void*>(&posix_memalign),
201-
reinterpret_cast<volatile void*>(&malloc_small),
202-
reinterpret_cast<volatile void*>(&malloc_small_zero),
203-
};
204-
} // namespace libc
205179
} // namespace snmalloc
206180

207181
// -- override/malloc.cc symbols with testlib_ prefix -----------------------

0 commit comments

Comments
 (0)