Skip to content

Custom section generation under wasm32-unknown-unknown is inconsistent and unintuitive #56639

Open
@koute

Description

@koute

Assume we have a crate named dependency with the following content:

pub fn trigger() {
    submodule::call();
}
pub mod submodule {
    pub fn call() {
        #[link_section = "some-custom-section"]
        static SNIPPET: [u8; 3] = [b'X', b'Y', b'Z'];

        extern "C" {
            fn require_XYZ();
        }

        unsafe {
            require_XYZ();
        }
    }
}

And we have another crate which uses the dependency:

extern crate dependency;

#[no_mangle]
pub fn main() {
    dependency::trigger();
}

If I compile this crate like this:

$ cargo build --target=wasm32-unknown-unknown --release

and dump it with wasm-objdump then the "some-custom-section" custom section will be missing. However, if I change the dependency crate to look like this (I've moved the call function from the submodule to the crate root and even made it private):

pub fn trigger() {
    call();
}
fn call() {
    #[link_section = "some-custom-section"]
    static SNIPPET: [u8; 3] = [b'X', b'Y', b'Z'];

    extern "C" {
        fn require_XYZ();
    }

    unsafe {
        require_XYZ();
    }
}

and build the main crate again then the custom section is generated. Calling dependency::submodule::call directly instead of dependency::trigger also results in the custom section being generated.

Based on my experiments the custom section generation currently works like this:

In which crate is the custom section defined? Where is the function containing the section? How is the function containing the custom section called? Is it generated?
External crate Submodule Not called No
External crate Submodule Indirectly No
External crate Submodule Directly Yes
External crate In root Not called No
External crate In root Indirectly Yes
External crate In root Directly Yes
Main crate Any Any Yes

I have an example crate here which reproduces the issue:

$ git clone https://github.com/koute/rust-custom-section-issue
$ cd rust-custom-section-issue

# This will not generate a custom section:
$ cargo build --target=wasm32-unknown-unknown --release --features broken
$ wasm-objdump -s target/wasm32-unknown-unknown/release/rust_custom_section_issue.wasm

# This will:
$ cargo build --target=wasm32-unknown-unknown --release --features working
$ wasm-objdump -s target/wasm32-unknown-unknown/release/rust_custom_section_issue.wasm

I'm using the most recent nightly: rustc 1.32.0-nightly (4a45578bc 2018-12-07)

Could we make this somewhat consistent?

Some background: as a first step towards wasm-bindgen compatibility I'm converting stdweb's js! macro to use custom sections, however to make it not break existing downstream users I need to have either a) every custom section in the whole crate graph be generated, or b) always generated if the custom section is defined inside of a potentially reachable (at runtime) function. Otherwise I end up generating an import for a snippet for which the corresponding custom section entry doesn't exist.

cc @alexcrichton

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binariesO-wasmTarget: WASM (WebAssembly), http://webassembly.org/

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions