Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dlmalloc: require __heap_end #394

Merged
merged 7 commits into from
Jul 11, 2023
Merged

Conversation

yamt
Copy link
Contributor

@yamt yamt commented Feb 17, 2023

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 #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.

dlmalloc/src/malloc.c Outdated Show resolved Hide resolved
@@ -9,7 +9,7 @@ jobs:
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, 15.0.7]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't we want to update the min version here? I think the idea is to test with the oldest supported version and also with a current/newer version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even before this PR, we were not testing app link for 10.0.0.

@yamt yamt force-pushed the require-heap-end branch 2 times, most recently from b24446a to c385fdb Compare February 17, 2023 05:02
@yamt
Copy link
Contributor Author

yamt commented Feb 17, 2023

i couldn't find any llvm >=15 releases which have assets for both of x86-64 ubuntu and x86-64 darwin.
what to do?

@yamt yamt marked this pull request as draft February 17, 2023 05:05
@sbc100
Copy link
Member

sbc100 commented Feb 17, 2023

i couldn't find any llvm >=15 releases which have assets for both of x86-64 ubuntu and x86-64 darwin. what to do?

15.0.0 looks like it has those binaries: https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.0

And 15.0.2: https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.2

Strange that some of the others don't those. Might be worth opening an issue on the llvm tracker?

@yamt
Copy link
Contributor Author

yamt commented Feb 17, 2023

i couldn't find any llvm >=15 releases which have assets for both of x86-64 ubuntu and x86-64 darwin. what to do?

15.0.0 looks like it has those binaries: https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.0

And 15.0.2: https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.2

which assets are you talking about? can you give me the exact urls of assets?
i only see powerpc for ubuntu.

Strange that some of the others don't those. Might be worth opening an issue on the llvm tracker?

while i'm not familiar with llvm release process, i guess it's like volunteers building and uploading each binaries.
eg. https://discourse.llvm.org/t/llvm-15-0-5-has-been-tagged/66615

@sbc100
Copy link
Member

sbc100 commented Feb 17, 2023

@yamt
Copy link
Contributor Author

yamt commented Feb 17, 2023

i couldn't find any llvm >=15 releases which have assets for both of x86-64 ubuntu and x86-64 darwin. what to do?

15.0.0 looks like it has those binaries: https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.0

https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.0/clang+llvm-15.0.0-x86_64-apple-darwin.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.0/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4.tar.xz

the rhel assert worked on ubuntu.
but it reminded me we actually need >=15.0.7.

@yamt
Copy link
Contributor Author

yamt commented Feb 17, 2023

a. wait for llvm 16 and hope it will have necessary assets
b. use clang from wasi-sdk. feeling a bit chicken-and-egg
c. bulid clang on our ci

@TerrorJack
Copy link
Contributor

d. use https://apt.llvm.org/ on linux

yamt added 3 commits March 22, 2023 09:03
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.
@yamt yamt force-pushed the require-heap-end branch from ba4a797 to 1cc8c8f Compare March 22, 2023 00:30
@yamt yamt marked this pull request as ready for review March 22, 2023 02:11
@yamt
Copy link
Contributor Author

yamt commented Mar 22, 2023

as a compromise, i made the ci to use different versions of llvm among platforms.

@yamt
Copy link
Contributor Author

yamt commented Apr 14, 2023

i still want to merge this. any concerns?

//
// Note: This is a linker bug: https://github.com/llvm/llvm-project/issues/60829
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should just remove this block and assume end is non-NULL.

llvm/llvm-project#60829 has been closed (and its really inconceivable to me that somebody would provide a weak definition of this (internal) symbol). If you want to keep some kind of check then perhaps just assert(end); with note referring to the bug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its really inconceivable to me that somebody would provide a weak definition of this (internal) symbol

i actually have seen such a code. dump these values for diagnostic purposes.

If you want to keep some kind of check then perhaps just assert(end); with note referring to the bug.

it's rare for users to use wasi-libc w/o NDEBUG.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its really inconceivable to me that somebody would provide a weak definition of this (internal) symbol

i actually have seen such a code. dump these values for diagnostic purposes.

But I don't think we want to support that configuration, right? Why would somebody weakly define a linker-internal symbol? Can you point to the place where you have seen this? Maybe just if (!end) abort() in that case, with a TODO to remove once we can depend on the llvm that contains that fix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its really inconceivable to me that somebody would provide a weak definition of this (internal) symbol

i actually have seen such a code. dump these values for diagnostic purposes.

But I don't think we want to support that configuration, right? Why would somebody weakly define a linker-internal symbol?

diagnostic purposes.
it just dumps something potentially useful for later trouble shooting.

Can you point to the place where you have seen this?

not open source.
but it's something similar to https://github.com/yamt/garbage/blob/03f9a1a1ee142194905818380f7f0e34287f9c64/wasm/hello/hello.c#L48

Maybe just if (!end) abort() in that case, with a TODO to remove once we can depend on the llvm that contains that fix?

i feel it's too early to assume https://reviews.llvm.org/D144747
given that even the latest wasi-sdk doesn't have the fix yet.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This (1) case is not true anymore I think. Older versions of llvm will simply cause link failure, not result in a zero-addressed version of __heap_end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know you fixed the linker bug. (thank you)
but how does it fix old llvm?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to worry that much about it, since it will only effect people that are both (a) using the old linker and (b) are weakly referencing __heap_end elsewhere in their program. I think this is highly unlikely isn't it?

Maybe at least leave a TODO to completely remove this check once we drop support for older wasm-ld?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, is https://reviews.llvm.org/D144747 actually required in order to guarantee that this symbol will be non-NULL? Or is it simply enough to have 15.0.7? IIUC if you have 15.0.7 then this can never be null, so this check is only in support of < 15.0.7?

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`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"provide a weak reference to" -> "includes a weak reference to".

Can you add:

"and (3) the weak reference is found by the linker before this strong reference."

@yamt
Copy link
Contributor Author

yamt commented Apr 19, 2023

@sbc100 after thinking a bit, i changed my mind and turned it to a trap. the whole purpose of this PR is to force users to use newer linker. in that sense, it's better to make it fail loudly even if it's on runtime.

@sbc100
Copy link
Member

sbc100 commented Jun 28, 2023

Is this change good to land now?

@sbc100 sbc100 requested a review from sunfishcode June 28, 2023 16:52
@yamt
Copy link
Contributor Author

yamt commented Jun 29, 2023

Is this change good to land now?

yes.
i'm not aware of any open issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants