-
Notifications
You must be signed in to change notification settings - Fork 5k
[wasm] Webcil-in-WebAssembly #85932
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
Merged
Merged
[wasm] Webcil-in-WebAssembly #85932
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
310aa3e
Add option to emit webcil inside a wasm module wrapper
lambdageek 2f2459d
[mono][loader] implement a webcil-in-wasm reader
lambdageek 7be51f8
reword WebcilWasmWrapper summary comment
lambdageek 2e58062
fix whitespace
lambdageek 056b9ac
fix typos
lambdageek 897df89
visit_section should bump the ptr after traversal
lambdageek 15a1894
remove extra bytes from wasm webcil prefix
lambdageek 1688dec
don't forget to include number of segments in the data section
lambdageek d8638f7
update the Webcil spec to include the WebAssembly wrapper module
lambdageek e8f52bb
fix typos and whitespace
lambdageek f06938f
advance endp past the data segment payload
lambdageek 0f5e02f
Adjust RVA map offsets to account for wasm prefix
lambdageek 4271d8f
Add a note about the rva mapping to the spec
lambdageek 2c90fb5
Serve webcil-in-wasm as .wasm
lambdageek 307ae9a
fix wbt
lambdageek 930cfeb
remove old .webcil support from Sdk Pack Tasks
lambdageek 7670b3c
Set SelfContained=true for browser-wasm runtimes (#86102)
lewing d17b8dd
Implement support for webcil in wasm in the managed WebcilReader
lambdageek 61afae7
why fail?
lambdageek 8a42b70
did we load the same asm twice??
lambdageek ccd074e
Merge remote-tracking branch 'origin/main' into webcil-wasm-wrapper
lambdageek 6166a67
checkpoint. things are broken. but I adjusted MonoImage:raw_data
lambdageek eedf447
align webcil payload to a 4-byte boundary within the wasm module
lambdageek d9b396e
remove WIP tracing
lambdageek 89ef589
assert that webcil raw data is 4-byte aligned
lambdageek d9a3fea
revert unrelated build change
lambdageek 6de7dee
revert unrelated change
lambdageek 88f956e
revert whitespace
lambdageek 0542c51
revert WBT debugging output changes
lambdageek 7c0643d
add 4-byte alignment requirement to the webcil spec
lambdageek e187b00
Don't modify MonoImageStorage:raw_data
lambdageek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
148 changes: 148 additions & 0 deletions
148
src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WasmModuleReader.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Collections.Immutable; | ||
using System.IO; | ||
using System.Reflection; | ||
using System.Runtime.InteropServices; | ||
using System.Text; | ||
|
||
namespace Microsoft.NET.WebAssembly.Webcil; | ||
|
||
internal class WasmModuleReader : IDisposable | ||
{ | ||
public enum Section : byte | ||
{ | ||
// order matters: enum values must match the WebAssembly spec | ||
Custom, | ||
Type, | ||
Import, | ||
Function, | ||
Table, | ||
Memory, | ||
Global, | ||
Export, | ||
Start, | ||
Element, | ||
Code, | ||
Data, | ||
DataCount, | ||
} | ||
|
||
private readonly BinaryReader _reader; | ||
|
||
private readonly Lazy<bool> _isWasmModule; | ||
|
||
public bool IsWasmModule => _isWasmModule.Value; | ||
|
||
public WasmModuleReader(Stream stream) | ||
{ | ||
_reader = new BinaryReader(stream, Encoding.UTF8, leaveOpen: true); | ||
_isWasmModule = new Lazy<bool>(this.GetIsWasmModule); | ||
} | ||
|
||
|
||
public void Dispose() | ||
{ | ||
Dispose(true); | ||
} | ||
|
||
|
||
protected virtual void Dispose(bool disposing) | ||
{ | ||
if (disposing) | ||
{ | ||
_reader.Dispose(); | ||
} | ||
} | ||
|
||
protected virtual bool VisitSection (Section sec, out bool shouldStop) | ||
{ | ||
shouldStop = false; | ||
return true; | ||
} | ||
|
||
private const uint WASM_MAGIC = 0x6d736100u; // "\0asm" | ||
|
||
private bool GetIsWasmModule() | ||
{ | ||
_reader.BaseStream.Seek(0, SeekOrigin.Begin); | ||
try | ||
{ | ||
uint magic = _reader.ReadUInt32(); | ||
if (magic == WASM_MAGIC) | ||
return true; | ||
} catch (EndOfStreamException) {} | ||
return false; | ||
} | ||
|
||
public bool Visit() | ||
{ | ||
if (!IsWasmModule) | ||
return false; | ||
_reader.BaseStream.Seek(4L, SeekOrigin.Begin); // skip magic | ||
|
||
uint version = _reader.ReadUInt32(); | ||
if (version != 1) | ||
return false; | ||
|
||
bool success = true; | ||
while (success) { | ||
success = DoVisitSection (out bool shouldStop); | ||
if (shouldStop) | ||
break; | ||
} | ||
return success; | ||
} | ||
|
||
private bool DoVisitSection(out bool shouldStop) | ||
{ | ||
shouldStop = false; | ||
byte code = _reader.ReadByte(); | ||
Section section = (Section)code; | ||
if (!Enum.IsDefined(typeof(Section), section)) | ||
return false; | ||
uint sectionSize = ReadULEB128(); | ||
|
||
long savedPos = _reader.BaseStream.Position; | ||
try | ||
{ | ||
return VisitSection(section, out shouldStop); | ||
} | ||
finally | ||
{ | ||
_reader.BaseStream.Seek(savedPos + (long)sectionSize, SeekOrigin.Begin); | ||
} | ||
} | ||
|
||
protected uint ReadULEB128() | ||
{ | ||
uint val = 0; | ||
int shift = 0; | ||
while (true) | ||
{ | ||
byte b = _reader.ReadByte(); | ||
val |= (b & 0x7fu) << shift; | ||
if ((b & 0x80u) == 0) break; | ||
shift += 7; | ||
if (shift >= 35) | ||
throw new OverflowException(); | ||
} | ||
return val; | ||
} | ||
|
||
protected bool TryReadPassiveDataSegment (out long segmentLength, out long segmentStart) | ||
{ | ||
segmentLength = 0; | ||
segmentStart = 0; | ||
byte code = _reader.ReadByte(); | ||
if (code != 1) | ||
return false; // not passive | ||
segmentLength = ReadULEB128(); | ||
segmentStart = _reader.BaseStream.Position; | ||
// skip over the data | ||
_reader.BaseStream.Seek (segmentLength, SeekOrigin.Current); | ||
return true; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.