Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 50 additions & 28 deletions docs/design/mono/webcil.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Version

This is version 0.0 of the Webcil payload format.
This is version 1.0 of the Webcil payload format.
This is version 0 of the WebAssembly module Webcil wrapper.

## Motivation
Expand Down Expand Up @@ -111,27 +111,27 @@ The Webcil headers consist of a Webcil header followed by a sequence of section

``` c
struct WebcilHeader {
uint8_t id[4]; // 'W' 'b' 'I' 'L'
// 4 bytes
uint16_t version_major; // 0
uint16_t version_minor; // 0
// 8 bytes
uint16_t coff_sections;
uint16_t reserved0; // 0
// 12 bytes

uint32_t pe_cli_header_rva;
uint32_t pe_cli_header_size;
// 20 bytes

uint32_t pe_debug_rva;
uint32_t pe_debug_size;
// 28 bytes
uint8_t id[4]; // 'W' 'b' 'I' 'L'
// 4 bytes
uint16_t version_major; // 1
uint16_t version_minor; // 0
// 8 bytes
uint16_t coff_sections;
uint16_t reserved0; // 0
// 12 bytes

uint32_t pe_cli_header_rva;
uint32_t pe_cli_header_size;
// 20 bytes

uint32_t pe_debug_rva;
uint32_t pe_debug_size;
// 28 bytes
};
```

The Webcil header starts with the magic characters 'W' 'b' 'I' 'L' followed by the version in major
minor format (must be 0 and 0). Then a count of the section headers and two reserved bytes.
minor format (must be 1 and 0). Then a count of the section headers and two reserved bytes.

The next pairs of integers are a subset of the PE Header data directory specifying the RVA and size
of the CLI header, as well as the directory entry for the PE debug directory.
Expand All @@ -140,25 +140,47 @@ of the CLI header, as well as the directory entry for the PE debug directory.
#### Section header table

Immediately following the Webcil header is a sequence (whose length is given by `coff_sections`
above) of section headers giving their virtual address and virtual size, as well as the offset in
the Webcil payload and the size in the file. This is a subset of the PE section header that includes
enough information to correctly interpret the RVAs from the webcil header and from the .NET
metadata. Other information (such as the section names) are not included.
above) of PE/COFF `IMAGE_SECTION_HEADER` structures (40 bytes each). Each header contains the
section name, virtual address and size, file offset and size, and other PE section attributes.
Unused fields (such as `PointerToRelocations`, `NumberOfRelocations`, `PointerToLinenumbers`,
`NumberOfLinenumbers`, and `Characteristics`) are set to zero. The `Name` field is copied from
the original PE section header.

Using the standard `IMAGE_SECTION_HEADER` layout allows runtimes to reference the section headers
directly from the loaded file image without converting from a compact representation at load time.

``` c
// IMAGE_SECTION_HEADER — 40 bytes, same layout as PE/COFF
struct SectionHeader {
uint32_t st_virtual_size;
uint32_t st_virtual_address;
uint32_t st_raw_data_size;
uint32_t st_raw_data_ptr;
char Name[8];
uint32_t VirtualSize;
uint32_t VirtualAddress;
uint32_t SizeOfRawData;
uint32_t PointerToRawData;
uint32_t PointerToRelocations; // 0
uint32_t PointerToLinenumbers; // 0
uint16_t NumberOfRelocations; // 0
uint16_t NumberOfLinenumbers; // 0
uint32_t Characteristics; // 0
};
```

(**Note**: the `st_raw_data_ptr` member is an offset from the beginning of the Webcil payload, not from the beginning of the WebAssembly wrapper module.)
(**Note**: the `PointerToRawData` member is an offset from the beginning of the Webcil payload, not from the beginning of the WebAssembly wrapper module.)

#### Sections

Immediately following the section table are the sections. These are copied verbatim from the PE file.
The section data starts at the first 16-byte-aligned offset after the end of the
section header table. Any gap between the last section header and the first section's
raw data is filled with zero-valued padding bytes. Each subsequent section likewise
begins at a 16-byte-aligned offset. This alignment guarantees that RVA static fields
(such as those backing `ReadOnlySpan<T>` over types up to `Vector128<T>`) retain
their natural alignment when the payload is loaded into memory at a 16-byte-aligned
base address.

Because PE `SizeOfRawData` is normally a multiple of the PE `FileAlignment` (≥ 512),
the inter-section padding is almost always zero bytes. In the worst case a single
assembly may gain up to ~30 bytes of padding total (header-to-first-section plus
one boundary per additional section).

### Rationale

Expand Down
3 changes: 1 addition & 2 deletions eng/testing/tests.browser.targets
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@
<WasmTestLogExitCode>true</WasmTestLogExitCode>
</PropertyGroup>

<!-- TODO-WASM https://github.com/dotnet/runtime/issues/120248 (CoreCLR on wasm defaults) -->
<!-- TODO-WASM github.com/dotnet/runtime/issues/120226 (CoreCLR on wasm defaults) -->
<PropertyGroup Condition="'$(RuntimeFlavor)' == 'CoreCLR'">
<InvariantGlobalization Condition="'$(InvariantGlobalization)' == ''">false</InvariantGlobalization>
<WasmEnableWebcil>false</WasmEnableWebcil>
</PropertyGroup>

<ItemGroup>
Expand Down
20 changes: 19 additions & 1 deletion src/coreclr/inc/pedecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION;

typedef DPTR(IMAGE_COR20_HEADER) PTR_IMAGE_COR20_HEADER;

#ifdef TARGET_BROWSER
#include "webcil.h"
#endif // TARGET_BROWSER

// --------------------------------------------------------------------------------
// Forward declared types
// --------------------------------------------------------------------------------
Expand Down Expand Up @@ -167,6 +171,17 @@ class PEDecoder
BOOL HasNTHeaders() const;
CHECK CheckNTHeaders() const;

#ifdef TARGET_BROWSER
BOOL HasWebcilHeaders() const;
CHECK CheckWebcilHeaders() const;
inline BOOL HasHeaders() const { return HasWebcilHeaders() || HasNTHeaders(); }
#else
inline BOOL HasWebcilHeaders() const { return FALSE; }
inline BOOL HasHeaders() const { return HasNTHeaders(); }
#endif

CHECK CheckHeaders() const;

IMAGE_NT_HEADERS32 *GetNTHeaders32() const;
IMAGE_NT_HEADERS64 *GetNTHeaders64() const;
BOOL Has32BitNTHeaders() const;
Expand All @@ -189,7 +204,6 @@ class PEDecoder
SIZE_T GetSizeOfHeapCommit() const;
UINT32 GetLoaderFlags() const;
UINT32 GetWin32VersionValue() const;
COUNT_T GetNumberOfRvaAndSizes() const;
COUNT_T GetNumberOfSections() const;
PTR_IMAGE_SECTION_HEADER FindFirstSection() const;
IMAGE_SECTION_HEADER *FindSection(LPCSTR sectionName) const;
Expand Down Expand Up @@ -365,6 +379,8 @@ class PEDecoder

IMAGE_DATA_DIRECTORY *GetMetaDataHelper(METADATA_SECTION_TYPE type) const;

COUNT_T GetNumberOfRvaAndSizes() const;

static PTR_IMAGE_SECTION_HEADER FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders);

IMAGE_COR20_HEADER *FindCorHeader() const;
Expand Down Expand Up @@ -399,6 +415,8 @@ class PEDecoder
FLAG_NATIVE_CHECKED = 0x80,

FLAG_HAS_NO_READYTORUN_HEADER = 0x100,
FLAG_WEBCIL = 0x200,
FLAG_WEBCIL_CHECKED = 0x400,
};

TADDR m_base;
Expand Down
Loading
Loading