Skip to content

Instantly share code, notes, and snippets.

@binji
Last active April 18, 2022 07:26
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save binji/d1cfff7faaebb2aa4f8b1c995234e5a0 to your computer and use it in GitHub Desktop.
Save binji/d1cfff7faaebb2aa4f8b1c995234e5a0 to your computer and use it in GitHub Desktop.
CustomSectionTextFormat.md

Custom sections in the text format

This page describes a proposal for representing custom sections in the text format.

Rationale

Currently it is impossible to round-trip a WebAssembly module between the binary and text formats without loss of information because there is no way to specify custom sections in the text format.

Custom sections are defined by using section id 0 and a name, followed by any binary data. See custom sections.

Currently, all known sections have a fixed order and may occur at most once. See binary module. Custom sections may occur anywhere in the module after the header:

  module ::= magic
             version
             customsec*
             functype*: typesec
             customsec*
             import*: importsec
             customsec*
             typeidx^n: funcsec
             customsec*
             ...

The text format is more free-form, so items from different sections may be interspersed. The only constraint is that imports must occur before any other non-import definitions. For example:

(module
  (import "mod" "name" (func $import0))

  (global $global0 i32 (i32.const 1))

  (func $func0 ...)

  (global $global1 i32 (i32.const -1))

  (memory $mem0 1)
)

Proposal

As described above, custom sections need to specify three things: their name, their contents, and their location in the module.

The location of the custom section is specified in reference to a given known section.

Example

  ...
  (@custom "name" (after function) "contents")
  ...

In this example, the section name is "name", its contents are "contents", and its location is after the function section.

The location can also be omitted, in which case the custom section will after all known sections:

  (@custom "stuff" "at the end")

Specification

A custom section is specified as follows:

custom ::= '(' '@custom' n:name l:custom_loc b*:datastring ')' => { name n, loc l, data b* }

custom_loc ::= '(' 'before' known_section_name:n ')'  => n - 1
            |  '(' 'after' known_section_nane:n ')'   => n
            |  ϵ      => 12
            
known_section_name ::= 'type'     => 1
                     | 'import'   => 2
                     | 'function' => 3
                     | 'table'    => 4
                     | 'memory'   => 5
                     | 'global'   => 6
                     | 'export'   => 7
                     | 'start'    => 8
                     | 'elem'     => 9
                     | 'code'     => 10
                     | 'data'     => 11

modulefield_I ::= ...
               | c:custom  => {custom c}

The custom section follows the section with id specified by its loc field. If there are multiple sections that have the same loc value, they are inserted in the order they appear in the source text.

The @custom syntax is an instance of the more general annotation syntax, which does not yet have a concrete proposal.

@sbc100
Copy link

sbc100 commented Dec 19, 2017

Since most custom sections will want to be at the end, and in the order in which they appear, could we make loc optional?

@rossberg
Copy link

For the reasons mentioned elsewhere, identifying locations by section numbers is future-hostile, because it would become ambiguous (and/or change meaning) as soon as we add new sections to the binary format. This needs to be something more abstract, like the before/after clauses you suggested earlier.

@rossberg
Copy link

It's also worth adding a note that this is assuming (@id ...) will be a generic annotation syntax, which this is just an instance of.

@binji
Copy link
Author

binji commented Jan 9, 2018

Sorry, didn't notice the comments on this gist till now.

@sbc100: Yes, I intended that to be the behavior. Added a comment to make it clearer.

@rossberg: I switched to before/after clauses, and added a comment about the generic annotation syntax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment