Skip to content

Commit

Permalink
dlmalloc: require __heap_end
Browse files Browse the repository at this point in the history
This commit effectively drops the support of older wasm-ld. (LLVM <15.0.7)

We have two relevant use cases:

* `memory.grow` use outside of malloc
  (eg. used by polyfill preview1 binaries)

* `--init-memory` to somehow preallocate heap
  (eg. avoid dynamic allocations, especially on small environments)

While WebAssembly#377
fixed the former, it broke the latter if you are using
an older LLVM, which doesn't provide the `__heap_end` symbol,
to link your module.

As we couldn't come up with a solution which satisfies all parties,
this commit simply makes it require new enough LLVM which provides
`__heap_end`. After all, a link-time failure is more friendly to users
than failing later in a subtle way.
  • Loading branch information
yamt committed Feb 17, 2023
1 parent 8daaba3 commit 9e7a106
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 17 deletions.
25 changes: 8 additions & 17 deletions dlmalloc/src/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5215,7 +5215,7 @@ static void internal_inspect_all(mstate m,

/* Symbol marking the end of data, bss and explicit stack, provided by wasm-ld. */
extern char __heap_base;
extern char __heap_end __attribute__((__weak__));
extern char __heap_end;

/* Initialize the initial state of dlmalloc to be able to use free memory between __heap_base and initial. */
static void try_init_allocator(void) {
Expand All @@ -5227,23 +5227,14 @@ static void try_init_allocator(void) {

char *base = &__heap_base;
// Try to use the linker pseudo-symbol `__heap_end` for the initial size of
// the heap, but if that's not defined due to LLVM being too old perhaps then
// round up `base` to the nearest `PAGESIZE`. The initial size of linear
// memory will be at least the heap base to this page boundary, and it's then
// assumed that the initial linear memory image was truncated at that point.
// While this reflects the default behavior of `wasm-ld` it is also possible
// for users to craft larger linear memories by passing options to extend
// beyond this threshold. In this situation the memory will not be used for
// dlmalloc.
//
// Note that `sbrk(0)`, or in dlmalloc-ese `CALL_MORECORE(0)`, is specifically
// not used here. That captures the current size of the heap but is only
// correct if the we're the first to try to grow the heap. If the heap has
// grown elsewhere, such as a different allocator in place, then this would
// incorrectly claim such memroy as our own.
// the heap.
char *end = &__heap_end;
if (end == NULL)
end = (char*) page_align((size_t) base);
if (end == NULL) {
// This can happen when 1. you are using an old wasm-ld which doesn't
// provide `__heap_end` and 2. something (other libraries or maybe
// your app?) provide a weak reference to `__heap_end`.
return;
}
size_t initial_heap_size = end - base;

/* Check that initial heap is long enough to serve a minimal allocation request. */
Expand Down
1 change: 1 addition & 0 deletions expected/wasm32-wasi-threads/undefined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ __getf2
__global_base
__gttf2
__heap_base
__heap_end
__imported_wasi_snapshot_preview1_args_get
__imported_wasi_snapshot_preview1_args_sizes_get
__imported_wasi_snapshot_preview1_clock_res_get
Expand Down
1 change: 1 addition & 0 deletions expected/wasm32-wasi/undefined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ __floatunsitf
__getf2
__gttf2
__heap_base
__heap_end
__imported_wasi_snapshot_preview1_args_get
__imported_wasi_snapshot_preview1_args_sizes_get
__imported_wasi_snapshot_preview1_clock_res_get
Expand Down

0 comments on commit 9e7a106

Please sign in to comment.