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
Original file line number Diff line number Diff line change
Expand Up @@ -1559,7 +1559,9 @@ private void EnsureImportSectionsImpl()
for (int i = 0; i < entryCount; i++)
{
int entryOffset = sectionOffset - startOffset;
long section = ImageReader.ReadInt64(ref sectionOffset);
long section = entrySize == 4
? ImageReader.ReadInt32(ref sectionOffset)
: ImageReader.ReadInt64(ref sectionOffset);
Comment thread
davidwrighton marked this conversation as resolved.
uint sigRva = ImageReader.ReadUInt32(ref signatureOffset);
int sigOffset = GetOffset((int)sigRva);
ReadyToRunSignature signature = MetadataNameFormatter.FormatSignature(_assemblyResolver, this, sigOffset);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/tools/r2rdump/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ public int Run()
// parse the ReadyToRun image
ReadyToRunReader r2r = new(model, filename);
r2r.ValidateDebugInfo = Get(_command.ValidateDebugInfo);
if (disasm)
if (disasm && !(r2r.CompositeReader is WebcilImageReader))
{
Comment thread
davidwrighton marked this conversation as resolved.
disassembler = new Disassembler(r2r, model);
}
Expand Down
11 changes: 10 additions & 1 deletion src/coreclr/tools/r2rdump/TextDumper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,19 @@ private void DumpWasmDisasm(RuntimeFunction rtf)
}

_writer.WriteLine();
var disasm = new WasmDisassembler(info.Image, info.InstructionOffset, info.InstructionLength);
var disasm = new WasmDisassembler(info.Image, info.InstructionOffset, info.InstructionLength, TryGetImportName);
_writer.Write(disasm.Disassemble());
}

private string TryGetImportName(int rva)
{
if (_r2r.ImportSignatures.TryGetValue(rva, out ReadyToRunSignature signature))
{
return signature.ToString(_model.SignatureFormattingOptions);
}
return null;
}

private static IEnumerable<string> FormatValTypes(IReadOnlyList<byte> types)
{
foreach (byte t in types)
Expand Down
60 changes: 52 additions & 8 deletions src/coreclr/tools/r2rdump/WasmDisassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,21 @@ internal sealed class WasmDisassembler
private int _offset;
private readonly int _baseOffset;
private readonly int _endOffset;
private readonly Func<int, string> _rvaToName;

public WasmDisassembler(ImmutableArray<byte> code, int offset, int length)
/// <summary>
/// Tracks whether the previous instruction was a global.get of the imageBase global (index 1).
/// When true, the next i32.const or memory load offset should be treated as an RVA.
/// </summary>
private bool _prevWasImageBaseGet;

public WasmDisassembler(ImmutableArray<byte> code, int offset, int length, Func<int, string> rvaToName = null)
{
_code = code;
_baseOffset = offset;
_offset = offset;
_endOffset = offset + length;
_rvaToName = rvaToName;
}

/// <summary>
Expand All @@ -40,23 +48,37 @@ public string Disassemble()
while (_offset < _endOffset)
{
int instrOffset = _offset - _baseOffset;
string instr = DecodeInstruction(ref indent, out int postAdjust);
string instr = DecodeInstruction(ref indent, out int postAdjust, out bool isImageBaseGet, out int rva);

string annotation = null;
if (rva >= 0 && _prevWasImageBaseGet && _rvaToName is not null)
{
annotation = _rvaToName(rva);
}
_prevWasImageBaseGet = isImageBaseGet;

sb.Append($" {instrOffset:X4}: ");
if (indent > 0)
{
sb.Append(' ', indent * 2);
}
sb.AppendLine(instr);
sb.Append(instr);
if (annotation is not null)
{
sb.Append($" // {annotation}");
}
sb.AppendLine();
indent += postAdjust;
}

return sb.ToString();
}

private string DecodeInstruction(ref int indent, out int postAdjust)
private string DecodeInstruction(ref int indent, out int postAdjust, out bool isImageBaseGet, out int rva)
{
postAdjust = 0;
isImageBaseGet = false;
rva = -1;
byte opcode = ReadByte();

switch (opcode)
Expand Down Expand Up @@ -185,15 +207,26 @@ private string DecodeInstruction(ref int indent, out int postAdjust)
case 0x20: return $"local.get {ReadU32()}";
case 0x21: return $"local.set {ReadU32()}";
case 0x22: return $"local.tee {ReadU32()}";
case 0x23: return $"global.get {ReadU32()}";
case 0x23:
{
uint globalIdx = ReadU32();
isImageBaseGet = globalIdx == 1;
return $"global.get {globalIdx}";
}
case 0x24: return $"global.set {ReadU32()}";

// Table instructions
case 0x25: return $"table.get {ReadU32()}";
case 0x26: return $"table.set {ReadU32()}";

// Memory instructions
case 0x28: return $"i32.load {ReadMemArg()}";
case 0x28:
{
string memArg = ReadMemArg(out uint offset);
if (offset != 0)
rva = (int)offset;
return $"i32.load {memArg}";
}
case 0x29: return $"i64.load {ReadMemArg()}";
case 0x2A: return $"f32.load {ReadMemArg()}";
case 0x2B: return $"f64.load {ReadMemArg()}";
Expand Down Expand Up @@ -228,7 +261,13 @@ private string DecodeInstruction(ref int indent, out int postAdjust)
}

// Numeric instructions - constants
case 0x41: return $"i32.const {ReadI32()}";
case 0x41:
{
int val = ReadI32();
if (val >= 0)
rva = val;
return $"i32.const {val}";
}
case 0x42: return $"i64.const {ReadI64()}";
case 0x43: return $"f32.const {ReadF32()}";
case 0x44: return $"f64.const {ReadF64()}";
Expand Down Expand Up @@ -939,6 +978,11 @@ private double ReadF64()
}

private string ReadMemArg()
{
return ReadMemArg(out _);
}

private string ReadMemArg(out uint offset)
{
uint align = ReadU32();
// Bit 6 indicates multi-memory (memory index follows)
Expand All @@ -948,7 +992,7 @@ private string ReadMemArg()
align &= ~0x40u;
memIdx = ReadU32();
}
uint offset = ReadU32();
offset = ReadU32();
if (memIdx != 0)
return $"align={1u << (int)align} offset={offset} mem={memIdx}";
if (offset != 0)
Expand Down
Loading