Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
267a765
[cdac] Add degenerate WasmContext for CoreCLR/wasm
lewing Jul 14, 2026
58bfd23
[cdac] Fix flags computation in stub contract descriptor
lewing Jul 14, 2026
b307a9c
[cdac] Add context-free interpreter stack walk (GetInterpretedFrames)
lewing Jul 14, 2026
e66dd72
[cdac] Make WasmContext.Size consistent with serialized bytes
lewing Jul 14, 2026
eeceae1
[cdac] Add WASM ReadyToRun frame unwinder
lewing Jul 14, 2026
2cf1ca0
Revert "[cdac] Add context-free interpreter stack walk (GetInterprete…
lewing Jul 14, 2026
cd8cc1f
[cdac] Emit + read WASM R2R virtual-IP function-table-index ranges
lewing Jul 14, 2026
5dc2b51
[cdac] Wire WasmContext.Unwind to the R2R virtual unwind
lewing Jul 14, 2026
57d5b59
[cdac] Add WasmFrameHandler to seed the WASM stack walk context
lewing Jul 17, 2026
2186578
[cdac] Mirror native wasm CONTEXT layout and add interpreter-transiti…
lewing Jul 17, 2026
f727c39
[cdac] Test WASM interpreter virtual unwind through WasmContext
lewing Jul 17, 2026
c475adf
[cdac] Verify WASM virtual-IP to MethodDesc R2R resolution
lewing Jul 17, 2026
b70bff9
[cdac] Make Module.MethodDefToILCodeVersioningStateMap optional for WASM
lewing Jul 17, 2026
64e2b88
[cdac] Expose PEImage flat layout so WASM webcil metadata resolves
lewing Jul 17, 2026
011689e
[cdac] Read metadata from WASM webcil images
lewing Jul 17, 2026
abb83be
[cdac] Address PR review feedback for WASM support
lewing Jul 17, 2026
758ffb6
[cdac] Address second PR review pass for WASM support
lewing Jul 17, 2026
219f6c5
[cdac] Add WasmR2RInfo unit tests covering the range-list global deref
lewing Jul 17, 2026
ce3e528
Address review: internal visibility, remove unused API, check TrySetR…
lewing Jul 17, 2026
2027f39
Address review: little-endian magic + ImageDataDirectory for COR20 me…
lewing Jul 20, 2026
d06f276
Merge remote-tracking branch 'origin/main' into lewing-cdac-wasm-support
lewing Jul 20, 2026
9f9b36e
Fix CI: add PEAssembly.MDImport to flat-layout test mock
lewing Jul 20, 2026
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
6 changes: 6 additions & 0 deletions docs/design/datacontracts/EcmaMetadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ TargetSpan GetReadOnlyMetadataAddress(ModuleHandle handle)
return default;
}

// Webcil (flat) images -- e.g. a ReadyToRun corelib on WASM -- are a stripped/rewrapped PE that
// cannot be parsed as a standard PE. They begin with the magic 'WbIL'. For those, the webcil
// header's PeCliHeaderRva locates the CLI (COR20) header, whose metadata directory (RVA + size at
// offset 8) locates the ECMA-335 metadata. RVAs are resolved via the loader's webcil-aware
// GetILAddr. For non-webcil images, read the CLI header from the PE headers as below.

// Read CLR header per https://learn.microsoft.com/windows/win32/debug/pe-format
ulong clrHeaderRVA = ...

Expand Down
6 changes: 6 additions & 0 deletions docs/design/datacontracts/ExecutionManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ Data descriptors used:
| `ReadyToRunInfo` | `LoadedImageBase` | Base address of the loaded R2R image |
| `ReadyToRunInfo` | `Composite` | Pointer to the `ReadyToRunCoreInfo` used for section lookup |
| `ReadyToRunInfo` | `ExceptionInfoSection` | Pointer to the `ImageDataDirectory` for R2R exception info section |
| `ReadyToRunInfo` | `MinVirtualIP` | (WASM only) Base virtual IP for the module's ReadyToRun functions; a function-table index is mapped to a virtual IP relative to this base |
| `ReadyToRunHeader` | `MajorVersion` | ReadyToRun major version |
| `ReadyToRunHeader` | `MinorVersion` | ReadyToRun minor version |
| `ImageDataDirectory` | `VirtualAddress` | Virtual address of the image data directory |
Expand Down Expand Up @@ -239,6 +240,10 @@ Data descriptors used:
| `ReadyToRunSection` | `Section` | `IMAGE_DATA_DIRECTORY` for the section data |
| `ExceptionLookupTableEntry` | `MethodStartRVA` | RVA of the method start |
| `ExceptionLookupTableEntry` | `ExceptionInfoRVA` | RVA of the exception clause data |
| `FunctionTableIndexRangeSection` | `MinFunctionTableIndex` | (WASM only) Lowest ReadyToRun function-table index covered by this range |
| `FunctionTableIndexRangeSection` | `NumRuntimeFunctions` | (WASM only) Number of runtime functions in the range |
| `FunctionTableIndexRangeSection` | `R2RModule` | (WASM only) Pointer to the owning ReadyToRun module |
| `FunctionTableIndexRangeSection` | `Next` | (WASM only) Pointer to the next `FunctionTableIndexRangeSection` in the list |

Global variables used:
| Global Name | Type | Purpose |
Expand All @@ -253,6 +258,7 @@ Global variables used:
| `FeatureOnStackReplacement` | uint8 | 1 if FEATURE_ON_STACK_REPLACEMENT is enabled, 0 otherwise |
| `FeaturePortableEntrypoints` | uint8 | 1 if FEATURE_PORTABLE_ENTRYPOINTS is enabled, 0 otherwise |
| `ObjectMethodTable` | TargetPointer | Pointer to the `System.Object` MethodTable, used for catch-all handler detection |
| `FunctionTableIndexRangeList` | TargetPointer | (WASM only) Head of the linked list of `FunctionTableIndexRangeSection`, mapping ReadyToRun function-table indices to their owning module for virtual-IP stack walking |

Contract constants used:
| Name | Type | Purpose | Value |
Expand Down
25 changes: 22 additions & 3 deletions docs/design/datacontracts/Loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ enum ClrModifiableAssemblies : uint
| `PEAssembly` | `AssemblyBinder` | Pointer to the PEAssembly's binder |
| `AssemblyBinder` | `AssemblyLoadContext` | Pointer to the AssemblyBinder's AssemblyLoadContext |
| `PEImage` | `LoadedImageLayout` | Pointer to the PEImage's loaded PEImageLayout |
| `PEImage` | `FlatImageLayout` | Pointer to the PEImage's flat PEImageLayout (used when there is no loaded layout, e.g. webcil images) |
| `PEImage` | `ProbeExtensionResult` | PEImage's ProbeExtensionResult |
| `ProbeExtensionResult` | `Type` | Type of ProbeExtensionResult |
| `PEImageLayout` | `Base` | Base address of the image layout |
Expand Down Expand Up @@ -436,6 +437,14 @@ bool TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer baseAddres
// try to get loaded PE image (peImage), if not loaded return false

TargetPointer peImageLayout = target.ReadPointer(peImage + /* PEImage::LoadedImageLayout offset */);
if (peImageLayout == TargetPointer.Null)
{
// Images that are never mapped/loaded (e.g. a webcil ReadyToRun image on WASM) have no
// loaded layout; their metadata lives in the flat layout (m_pLayouts[IMAGE_FLAT]).
peImageLayout = target.ReadPointer(peImage + /* PEImage::FlatImageLayout offset */);
if (peImageLayout == TargetPointer.Null)
return false;
}

baseAddress = target.ReadPointer(peImageLayout + /* PEImageLayout::Base offset */);
size = target.Read<uint>(peImageLayout + /* PEImageLayout::Size offset */);
Expand Down Expand Up @@ -472,7 +481,13 @@ private TargetPointer GetRvaData(TargetPointer peAssemblyPtr, int rva, bool isNu

TargetPointer peImageLayout = target.ReadPointer(peImage + /* PEImage::LoadedImageLayout offset */);
if(peImageLayout == TargetPointer.Null)
throw new InvalidOperationException("PEImage does not have a LoadedImageLayout associated with it.");
{
// Images that are never mapped/loaded (e.g. a webcil ReadyToRun image on WASM) have no
// loaded layout; fall back to the flat layout (m_pLayouts[IMAGE_FLAT]).
peImageLayout = target.ReadPointer(peImage + /* PEImage::FlatImageLayout offset */);
if(peImageLayout == TargetPointer.Null)
throw new InvalidOperationException("PEImage does not have a usable image layout associated with it.");
}

// Get base address and flags from PEImageLayout
TargetPointer baseAddress = target.ReadPointer(peImageLayout + /* PEImageLayout::Base offset */);
Expand Down Expand Up @@ -700,8 +715,12 @@ ModuleLookupTables GetLookupTables(ModuleHandle handle)
MethodDefToDescMap: target.ReadPointer(handle.Address + /* Module::MethodDefToDescMap */),
TypeDefToMethodTableMap: target.ReadPointer(handle.Address + /* Module::TypeDefToMethodTableMap */),
TypeRefToMethodTableMap: target.ReadPointer(handle.Address + /* Module::TypeRefToMethodTableMap */),
MethodDefToILCodeVersioningState: target.ReadPointer(handle.Address + /*
Module::MethodDefToILCodeVersioningState */),
// Module::MethodDefToILCodeVersioningState is only present when the target was built
// with code versioning (FEATURE_CODE_VERSIONING). When absent (e.g. on WASM) it is
// treated as a null (empty) table.
MethodDefToILCodeVersioningState: HasField(Module::MethodDefToILCodeVersioningState)
? target.ReadPointer(handle.Address + /* Module::MethodDefToILCodeVersioningState */)
: TargetPointer.Null,
TableDataOffset: tableDataOffset);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ DLLEXPORT struct ContractDescriptor CONTRACT_NAME;

DLLEXPORT struct ContractDescriptor CONTRACT_NAME = {
.magic = 0x0043414443434e44ull, // "DNCCDAC\0"
.flags = 0x1u & (sizeof(void*) == 4 ? 0x02u : 0x00u),
.flags = 0x1u | (sizeof(void*) == 4 ? 0x02u : 0x00u),
Comment thread
lewing marked this conversation as resolved.
.descriptor_size = sizeof(STUB_DESCRIPTOR),
.descriptor = STUB_DESCRIPTOR,
.pointer_data_count = 1,
Expand Down
14 changes: 14 additions & 0 deletions src/coreclr/vm/codeman.h
Original file line number Diff line number Diff line change
Expand Up @@ -2728,7 +2728,21 @@ struct cdac_data<ExecutionManager>
{
static constexpr void* const CodeRangeMapAddress = (void*)&ExecutionManager::g_codeRangeMap.Data[0];
static constexpr PTR_EEJitManager* EEJitManagerAddress = &ExecutionManager::m_pEEJitManager;
#ifdef TARGET_WASM
static constexpr FunctionTableIndexRangeSection** FunctionTableIndexRangeListAddress = &ExecutionManager::s_pFunctionTableIndexRangeList;
#endif // TARGET_WASM
};

#ifdef TARGET_WASM
template<>
struct cdac_data<FunctionTableIndexRangeSection>
{
static constexpr size_t MinFunctionTableIndex = offsetof(FunctionTableIndexRangeSection, minFunctionTableIndex);
static constexpr size_t NumRuntimeFunctions = offsetof(FunctionTableIndexRangeSection, numRuntimeFunctions);
static constexpr size_t R2RModule = offsetof(FunctionTableIndexRangeSection, pR2RModule);
static constexpr size_t Next = offsetof(FunctionTableIndexRangeSection, pNext);
};
#endif // TARGET_WASM
#endif

inline CodeHeader * EEJitManager::GetCodeHeader(const METHODTOKEN& MethodToken)
Expand Down
17 changes: 17 additions & 0 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ CDAC_TYPE_END(AssemblyBinder)

CDAC_TYPE_BEGIN(PEImage)
CDAC_TYPE_INDETERMINATE(PEImage)
CDAC_TYPE_FIELD(PEImage, T_POINTER, FlatImageLayout, cdac_data<PEImage>::FlatImageLayout)
CDAC_TYPE_FIELD(PEImage, T_POINTER, LoadedImageLayout, cdac_data<PEImage>::LoadedImageLayout)
CDAC_TYPE_FIELD(PEImage, TYPE(ProbeExtensionResult), ProbeExtensionResult, cdac_data<PEImage>::ProbeExtensionResult)
CDAC_TYPE_END(PEImage)
Expand Down Expand Up @@ -887,8 +888,21 @@ CDAC_TYPE_FIELD(ReadyToRunInfo, T_UINT32, NumImportSections, cdac_data<ReadyToRu
CDAC_TYPE_FIELD(ReadyToRunInfo, TYPE(HashMap), EntryPointToMethodDescMap, cdac_data<ReadyToRunInfo>::EntryPointToMethodDescMap)
CDAC_TYPE_FIELD(ReadyToRunInfo, T_POINTER, LoadedImageBase, cdac_data<ReadyToRunInfo>::LoadedImageBase)
CDAC_TYPE_FIELD(ReadyToRunInfo, T_POINTER, Composite, cdac_data<ReadyToRunInfo>::Composite)
#ifdef TARGET_WASM
CDAC_TYPE_FIELD(ReadyToRunInfo, T_POINTER, MinVirtualIP, cdac_data<ReadyToRunInfo>::MinVirtualIP)
#endif // TARGET_WASM
CDAC_TYPE_END(ReadyToRunInfo)

#ifdef TARGET_WASM
CDAC_TYPE_BEGIN(FunctionTableIndexRangeSection)
CDAC_TYPE_INDETERMINATE(FunctionTableIndexRangeSection)
CDAC_TYPE_FIELD(FunctionTableIndexRangeSection, T_UINT32, MinFunctionTableIndex, cdac_data<FunctionTableIndexRangeSection>::MinFunctionTableIndex)
CDAC_TYPE_FIELD(FunctionTableIndexRangeSection, T_UINT32, NumRuntimeFunctions, cdac_data<FunctionTableIndexRangeSection>::NumRuntimeFunctions)
CDAC_TYPE_FIELD(FunctionTableIndexRangeSection, T_POINTER, R2RModule, cdac_data<FunctionTableIndexRangeSection>::R2RModule)
CDAC_TYPE_FIELD(FunctionTableIndexRangeSection, T_POINTER, Next, cdac_data<FunctionTableIndexRangeSection>::Next)
CDAC_TYPE_END(FunctionTableIndexRangeSection)
Comment thread
lewing marked this conversation as resolved.
#endif // TARGET_WASM

CDAC_TYPE_BEGIN(ReadyToRunHeader)
CDAC_TYPE_INDETERMINATE(ReadyToRunHeader)
CDAC_TYPE_FIELD(ReadyToRunHeader, T_UINT16, MajorVersion, offsetof(READYTORUN_HEADER, MajorVersion))
Expand Down Expand Up @@ -1716,6 +1730,9 @@ CDAC_GLOBAL(StressLogEnabled, T_UINT8, 0)
#endif
CDAC_GLOBAL_POINTER(ExecutionManagerCodeRangeMapAddress, cdac_data<ExecutionManager>::CodeRangeMapAddress)
CDAC_GLOBAL_POINTER(EEJitManagerAddress, cdac_data<ExecutionManager>::EEJitManagerAddress)
#ifdef TARGET_WASM
CDAC_GLOBAL_POINTER(FunctionTableIndexRangeList, cdac_data<ExecutionManager>::FunctionTableIndexRangeListAddress)
#endif // TARGET_WASM
CDAC_GLOBAL_POINTER(PlatformMetadata, &::g_cdacPlatformMetadata)
#ifdef PROFILING_SUPPORTED
CDAC_GLOBAL_POINTER(ProfilerControlBlock, &::g_profControlBlock)
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/vm/peimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ class PEImage final
template<>
struct cdac_data<PEImage>
{
// The loaded PEImageLayout is m_pLayouts[IMAGE_LOADED]
// Layouts are stored in m_pLayouts[], indexed by IMAGE_FLAT (0) and IMAGE_LOADED (1).
static constexpr size_t FlatImageLayout = offsetof(PEImage, m_pLayouts);
static constexpr size_t LoadedImageLayout = offsetof(PEImage, m_pLayouts) + sizeof(PTR_PEImageLayout);
static constexpr size_t ProbeExtensionResult = offsetof(PEImage, m_probeExtensionResult);
};
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/readytoruninfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,9 @@ struct cdac_data<ReadyToRunInfo>
static constexpr size_t EntryPointToMethodDescMap = offsetof(ReadyToRunInfo, m_entryPointToMethodDescMap);
static constexpr size_t LoadedImageBase = offsetof(ReadyToRunInfo, m_pLoadedImageBase);
static constexpr size_t Composite = offsetof(ReadyToRunInfo, m_pComposite);
#ifdef TARGET_WASM
static constexpr size_t MinVirtualIP = offsetof(ReadyToRunInfo, m_minVirtualIP);
#endif // TARGET_WASM
};

class DynamicHelpers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public static class Globals
public const string SystemDomain = nameof(SystemDomain);
public const string ThreadStore = nameof(ThreadStore);
public const string FinalizerThread = nameof(FinalizerThread);
public const string FunctionTableIndexRangeList = nameof(FunctionTableIndexRangeList);
public const string GCThread = nameof(GCThread);
public const string Debugger = nameof(Debugger);
public const string MaxHijackFunctions = nameof(MaxHijackFunctions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,58 @@ public TargetSpan GetReadOnlyMetadataAddress(ModuleHandle handle)
{
throw new InvalidOperationException("Module is not loaded.");
}
bool isMapped = (imageFlags & 0x1) != 0; // FLAG_MAPPED = 0x1
PEStreamOptions isLoaded = isMapped ? PEStreamOptions.IsLoadedImage : PEStreamOptions.Default;

TargetStream stream = new(target, baseAddress, size);
using PEReader peReader = new PEReader(stream, isLoaded);
TargetSpan result;
if (IsWebcilImage(baseAddress))
{
// Webcil (flat) images -- e.g. ReadyToRun corelib on WASM -- are a stripped/rewrapped PE
// that System.Reflection.Metadata's PEReader cannot parse. Locate the metadata via the
// webcil header instead.
result = GetWebcilReadOnlyMetadataAddress(handle, baseAddress);
}
else
{
bool isMapped = (imageFlags & 0x1) != 0; // FLAG_MAPPED = 0x1
PEStreamOptions isLoaded = isMapped ? PEStreamOptions.IsLoadedImage : PEStreamOptions.Default;

TargetStream stream = new(target, baseAddress, size);
using PEReader peReader = new PEReader(stream, isLoaded);

int metadataStartOffset = peReader.PEHeaders.MetadataStartOffset;
int metadataSize = peReader.PEHeaders.MetadataSize;
int metadataStartOffset = peReader.PEHeaders.MetadataStartOffset;
int metadataSize = peReader.PEHeaders.MetadataSize;

result = new TargetSpan(baseAddress + (ulong)metadataStartOffset, (ulong)metadataSize);
}

TargetSpan result = new TargetSpan(baseAddress + (ulong)metadataStartOffset, (ulong)metadataSize);
_readOnlyMetadataAddress[handle] = result;
return result;
}

// 'W','b','I','L' little-endian -- the magic at the start of a webcil header (see docs/design/mono/webcil.md).
private const uint WebcilMagic = 0x4C49_6257;

private bool IsWebcilImage(TargetPointer baseAddress)
=> target.ReadLittleEndian<uint>(baseAddress) == WebcilMagic;

private TargetSpan GetWebcilReadOnlyMetadataAddress(ModuleHandle handle, TargetPointer webcilBase)
{
// The webcil header points to the PE CLI (COR20) header; the metadata directory (RVA + size
// at offset 8 in the COR20 header) locates the ECMA-335 metadata blob. RVAs are resolved
// through the loader, which understands the webcil section layout.
Data.WebcilHeader header = target.ProcessedData.GetOrAdd<Data.WebcilHeader>(webcilBase);
Data.Module module = target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
ILoader loader = target.Contracts.Loader;

TargetPointer cliHeader = loader.GetILAddr(module.PEAssembly, checked((int)header.PeCliHeaderRva));

// IMAGE_COR20_HEADER: cb (4) + MajorRuntimeVersion (2) + MinorRuntimeVersion (2) then the
// MetaData IMAGE_DATA_DIRECTORY (RVA @ 8, Size @ 12).
Data.ImageDataDirectory metadataDirectory = target.ProcessedData.GetOrAdd<Data.ImageDataDirectory>(cliHeader + 8);

TargetPointer metadataAddress = loader.GetILAddr(module.PEAssembly, checked((int)metadataDirectory.VirtualAddress));
return new TargetSpan(metadataAddress, metadataDirectory.Size);
}

public MetadataReader? GetMetadata(ModuleHandle handle)
{
if (_metadata.TryGetValue(handle, out MetadataReaderProvider? result))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,26 @@ private bool TryGetPEImage(ModuleHandle handle, [NotNullWhen(true)] out Data.PEI
return true;
}

// Resolves the PEImageLayout used to read a module's image contents. Prefers the mapped/loaded
// layout; when that is absent (e.g. a webcil ReadyToRun image on WASM is only ever flat) falls
// back to the flat layout, whose section data still backs the image's RVAs and metadata.
private bool TryGetUsableImageLayout(Data.PEImage peImage, [NotNullWhen(true)] out Data.PEImageLayout? imageLayout)
{
imageLayout = null;

TargetPointer imageLayoutPtr = peImage.LoadedImageLayout;
if (imageLayoutPtr == TargetPointer.Null)
{
if (peImage.FlatImageLayout is not TargetPointer flatLayoutPtr || flatLayoutPtr == TargetPointer.Null)
return false;

imageLayoutPtr = flatLayoutPtr;
}

imageLayout = _target.ProcessedData.GetOrAdd<Data.PEImageLayout>(imageLayoutPtr);
return true;
}

bool ILoader.TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer baseAddress, out uint size, out uint imageFlags)
{
baseAddress = TargetPointer.Null;
Expand All @@ -204,10 +224,8 @@ bool ILoader.TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer ba
if (!TryGetPEImage(handle, out Data.PEImage? peImage))
return false; // no PE image

if (peImage.LoadedImageLayout == TargetPointer.Null)
return false; // no loaded image layout

Data.PEImageLayout peImageLayout = _target.ProcessedData.GetOrAdd<Data.PEImageLayout>(peImage.LoadedImageLayout);
if (!TryGetUsableImageLayout(peImage, out Data.PEImageLayout? peImageLayout))
return false; // no usable image layout

baseAddress = peImageLayout.Base;
size = peImageLayout.Size;
Expand Down Expand Up @@ -319,9 +337,8 @@ private TargetPointer GetRvaData(TargetPointer peAssemblyPtr, int rva, bool isNu
if (assembly.PEImage == TargetPointer.Null)
throw new InvalidOperationException("PEAssembly does not have a PEImage associated with it.");
Data.PEImage peImage = _target.ProcessedData.GetOrAdd<Data.PEImage>(assembly.PEImage);
if (peImage.LoadedImageLayout == TargetPointer.Null)
throw new InvalidOperationException("PEImage does not have a LoadedImageLayout associated with it.");
Data.PEImageLayout peImageLayout = _target.ProcessedData.GetOrAdd<Data.PEImageLayout>(peImage.LoadedImageLayout);
if (!TryGetUsableImageLayout(peImage, out Data.PEImageLayout? peImageLayout))
throw new InvalidOperationException("PEImage does not have a usable image layout associated with it.");
uint offset;
if (IsMapped(peImageLayout))
offset = (uint)rva;
Expand Down Expand Up @@ -533,7 +550,8 @@ ModuleLookupTables ILoader.GetLookupTables(ModuleHandle handle)
module.MethodDefToDescMap,
module.TypeDefToMethodTableMap,
module.TypeRefToMethodTableMap,
module.MethodDefToILCodeVersioningStateMap,
// Absent on builds without code versioning (e.g. WASM); treat as an empty table.
module.MethodDefToILCodeVersioningStateMap ?? TargetPointer.Null,
tableDataOffset);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static IPlatformAgnosticContext GetContextForPlatform(Target target)
RuntimeInfoArchitecture.Arm64 => new ContextHolder<ARM64Context>(),
RuntimeInfoArchitecture.LoongArch64 => new ContextHolder<LoongArch64Context>(),
RuntimeInfoArchitecture.RiscV64 => new ContextHolder<RISCV64Context>(),
RuntimeInfoArchitecture.Wasm => new ContextHolder<WasmContext>(),
RuntimeInfoArchitecture.Unknown => throw new InvalidOperationException($"Processor architecture is required for creating a platform specific context and is not provided by the target"),
_ => throw new InvalidOperationException($"Unsupported architecture {runtimeInfo.GetTargetArchitecture()}"),
};
Expand Down
Loading
Loading