Browse Source

dlmalloc: require __heap_end (#394)

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 https://github.com/WebAssembly/wasi-libc/pull/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.
sunfishcode/dso-main
YAMAMOTO Takashi 1 year ago
committed by GitHub
parent
commit
d8abbaac1b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      .github/workflows/main.yml
  2. 29
      dlmalloc/src/malloc.c
  3. 1
      expected/wasm32-wasi-threads/undefined-symbols.txt
  4. 1
      expected/wasm32-wasi/undefined-symbols.txt

34
.github/workflows/main.yml

@ -8,8 +8,26 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# oldest and newest supported LLVM version
clang_version: [10.0.0, 14.0.0]
clang_version: [10.0.0]
# use different LLVM versions among oses because of the lack of
# official assets on github.
include:
- os: ubuntu-latest
clang_version: 10.0.0
llvm_asset_suffix: x86_64-linux-gnu-ubuntu-18.04
- os: macos-latest
clang_version: 10.0.0
llvm_asset_suffix: x86_64-apple-darwin
- os: windows-latest
clang_version: 10.0.0
- os: ubuntu-latest
clang_version: 16.0.0
llvm_asset_suffix: x86_64-linux-gnu-ubuntu-18.04
- os: macos-latest
clang_version: 15.0.7
llvm_asset_suffix: x86_64-apple-darwin21.0
- os: windows-latest
clang_version: 16.0.0
steps:
- uses: actions/checkout@v1
with:
@ -44,8 +62,8 @@ jobs:
- name: Install LLVM tools (MacOS)
shell: bash
run: |
curl -sSfL https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.clang_version }}/clang+llvm-${{ matrix.clang_version }}-x86_64-apple-darwin.tar.xz | tar xJf -
export CLANG_DIR=`pwd`/clang+llvm-${{ matrix.clang_version }}-x86_64-apple-darwin/bin
curl -sSfL https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.clang_version }}/clang+llvm-${{ matrix.clang_version }}-${{ matrix.llvm_asset_suffix }}.tar.xz | tar xJf -
export CLANG_DIR=`pwd`/clang+llvm-${{ matrix.clang_version }}-${{ matrix.llvm_asset_suffix }}/bin
echo "$CLANG_DIR" >> $GITHUB_PATH
echo "CC=$CLANG_DIR/clang" >> $GITHUB_ENV
echo "AR=$CLANG_DIR/llvm-ar" >> $GITHUB_ENV
@ -55,8 +73,8 @@ jobs:
- name: Install LLVM tools (Linux)
shell: bash
run: |
curl -sSfL https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.clang_version }}/clang+llvm-${{ matrix.clang_version }}-x86_64-linux-gnu-ubuntu-18.04.tar.xz | tar xJf -
export CLANG_DIR=`pwd`/clang+llvm-${{ matrix.clang_version }}-x86_64-linux-gnu-ubuntu-18.04/bin
curl -sSfL https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.clang_version }}/clang+llvm-${{ matrix.clang_version }}-${{ matrix.llvm_asset_suffix }}.tar.xz | tar xJf -
export CLANG_DIR=`pwd`/clang+llvm-${{ matrix.clang_version }}-${{ matrix.llvm_asset_suffix }}/bin
echo "$CLANG_DIR" >> $GITHUB_PATH
echo "CLANG_DIR=$CLANG_DIR" >> $GITHUB_ENV
echo "CC=$CLANG_DIR/clang" >> $GITHUB_ENV
@ -76,12 +94,14 @@ jobs:
run: |
cd test
make download
export WASI_DIR=$(realpath $CLANG_DIR/../lib/clang/${{ matrix.clang_version }}/lib/wasi/)
export WASI_DIR=$(realpath $($CLANG_DIR/clang -print-resource-dir)/lib/wasi/)
mkdir -p $WASI_DIR
cp download/lib/wasi/libclang_rt.builtins-wasm32.a $WASI_DIR
make test
# The older version of Clang does not provide the expected symbol for the
# test entrypoints: `undefined symbol: __main_argc_argv`.
# The older (<15.0.7) version of wasm-ld does not provide `__heap_end`,
# which is required by our malloc implementation.
if: matrix.os == 'ubuntu-latest' && matrix.clang_version != '10.0.0'
- uses: actions/upload-artifact@v1

29
dlmalloc/src/malloc.c

@ -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) {
@ -5227,23 +5227,18 @@ 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 < base) {
// "end" can be NULL when 1. you are using an old wasm-ld which doesn't
// provide `__heap_end` (< 15.0.7) and 2. something (other libraries
// or maybe your app?) includes a weak reference to `__heap_end` and
// 3. the weak reference is found by the linker before this strong
// reference.
//
// Note: This is a linker bug: https://github.com/llvm/llvm-project/issues/60829
__builtin_trap();
}
size_t initial_heap_size = end - base;
/* Check that initial heap is long enough to serve a minimal allocation request. */

1
expected/wasm32-wasi-threads/undefined-symbols.txt

@ -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

1
expected/wasm32-wasi/undefined-symbols.txt

@ -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

Loading…
Cancel
Save