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
19 changes: 17 additions & 2 deletions src/coreclr/hosts/corerun/wasm/libCorerun.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,15 @@ function libCoreRunFactory() {
} catch (e) {
return false;
}
const wasmModule = new WebAssembly.Module(wasmBytes);
let wasmModule;
try {
wasmModule = new WebAssembly.Module(wasmBytes);
} catch (e) {
const errormessage = e instanceof Error ? e.message : String(e);
console.error("Failed to compile WebAssembly module for Webcil image:", {wasmPath, errormessage});
Comment on lines +185 to +186
return false;
}

const tableStartIndex = wasmTable.length;

var payloadSize = 0;
Expand All @@ -195,7 +203,14 @@ function libCoreRunFactory() {
console.error("Webcil payload size is 0; cannot load image");
return false;
}
wasmTable.grow(tableSize);

try {
wasmTable.grow(tableSize);
} catch (e) {
const errormessage = e instanceof Error ? e.message : String(e);
console.error("Failed to grow WebAssembly table for Webcil image:", {wasmPath, errormessage});
return false;
}

var payloadPtr = 0;
var wasmInstance;
Expand Down
27 changes: 20 additions & 7 deletions src/coreclr/inc/webcildecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,26 @@ class WebcilDecoder
void *GetNativeEntryPoint() const { return NULL; }

// ------------------------------------------------------------
// R2R — not supported for Webcil
// R2R
// ------------------------------------------------------------

BOOL HasReadyToRunHeader() const { return FALSE; }
BOOL HasReadyToRunHeader() const;
BOOL IsComponentAssembly() const { return FALSE; }
READYTORUN_HEADER *GetReadyToRunHeader() const { return NULL; }
BOOL IsNativeMachineFormat() const { return FALSE; }
PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL) const;
READYTORUN_HEADER *GetReadyToRunHeader() const;
BOOL IsNativeMachineFormat() const { return TRUE; }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TRUE only when you found R2R ?

PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize) const;

CHECK CheckDirectory(IMAGE_DATA_DIRECTORY *pDir, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const;
TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const;
SSIZE_T GetTableBaseOffset() const
{
if (m_pHeader == NULL)
return 0;
return m_pHeader->VersionMajor >= WEBCIL_VERSION_MAJOR_1 ? ((const WebcilHeader_1 *)m_pHeader)->TableBase : 0;
}
private:
READYTORUN_HEADER *FindReadyToRunHeader() const;
public:
// ------------------------------------------------------------
// RVA operations (remaining private)
// ------------------------------------------------------------
Expand Down Expand Up @@ -274,12 +285,14 @@ class WebcilDecoder
// Instance members
TADDR m_base;
COUNT_T m_size;
BOOL m_hasContents;
BOOL m_relocated = FALSE;
bool m_relocated = FALSE;
bool m_hasContents;
mutable bool m_hasNoReadyToRunHeader;
const WebcilHeader *m_pHeader;
const WebcilSectionHeader *m_sections;

mutable IMAGE_COR20_HEADER *m_pCorHeader;
mutable PTR_READYTORUN_HEADER m_pReadyToRunHeader;
};

#endif // FEATURE_WEBCIL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,19 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
symbol = method;
}

runtimeFunctionsBuilder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ADDR32NB, delta: frameInfo.StartOffset + _nodeFactory.Target.CodeDelta);
if (!relocsOnly && _nodeFactory.Target.Architecture == TargetArchitecture.X64)
if (_nodeFactory.Target.Architecture == TargetArchitecture.Wasm32)
{
// On Amd64, the 2nd word contains the EndOffset of the runtime function
Debug.Assert(frameInfo.StartOffset != frameInfo.EndOffset);
runtimeFunctionsBuilder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ADDR32NB, delta: frameInfo.EndOffset);
runtimeFunctionsBuilder.EmitReloc(symbol, RelocType.WASM_TABLE_INDEX_I32, frameIndex);
}
else
{
runtimeFunctionsBuilder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ADDR32NB, delta: frameInfo.StartOffset + _nodeFactory.Target.CodeDelta);
if (!relocsOnly && _nodeFactory.Target.Architecture == TargetArchitecture.X64)
{
// On Amd64, the 2nd word contains the EndOffset of the runtime function
Debug.Assert(frameInfo.StartOffset != frameInfo.EndOffset);
runtimeFunctionsBuilder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ADDR32NB, delta: frameInfo.EndOffset);
}
}
Comment on lines +127 to 140
runtimeFunctionsBuilder.EmitReloc(factory.RuntimeFunctionsGCInfo, RelocType.IMAGE_REL_BASED_ADDR32NB, funcletOffsets[frameIndex]);
runtimeFunctionIndex++;
Expand Down
172 changes: 160 additions & 12 deletions src/coreclr/utilcode/webcildecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ bool WebcilDecoder::DetectWebcilFormat(const void* data, COUNT_T size)
WebcilDecoder::WebcilDecoder()
: m_base(0),
m_size(0),
m_hasContents(FALSE),
m_hasContents(false),
m_hasNoReadyToRunHeader(false),
m_pHeader(NULL),
m_sections(NULL),
m_pCorHeader(NULL)
m_pCorHeader(NULL),
m_pReadyToRunHeader(NULL)
{
LIMITED_METHOD_CONTRACT;
}
Expand Down Expand Up @@ -82,7 +84,7 @@ void WebcilDecoder::Reset()
LIMITED_METHOD_CONTRACT;
m_base = 0;
m_size = 0;
m_hasContents = FALSE;
m_hasContents = false;
m_pHeader = NULL;
m_sections = NULL;
m_pCorHeader = NULL;
Expand Down Expand Up @@ -470,14 +472,6 @@ ULONG WebcilDecoder::GetEntryPointToken() const
// R2R / native manifest metadata
// ------------------------------------------------------------

PTR_CVOID WebcilDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const
{
LIMITED_METHOD_CONTRACT;
if (pSize != NULL)
*pSize = 0;
return NULL;
}

// ------------------------------------------------------------
// RVA operations
// ------------------------------------------------------------
Expand Down Expand Up @@ -864,7 +858,7 @@ TADDR WebcilDecoder::GetDirectoryEntryData(int entry, COUNT_T *pSize) const
return (TADDR)0;
}

const WebcilSectionHeader *sections = (const WebcilSectionHeader *)(m_base + sizeof(WebcilHeader));
const WebcilSectionHeader *sections = m_sections;
const WebcilSectionHeader *relocSection = &sections[sectionIndex];

if (pSize != NULL)
Expand Down Expand Up @@ -916,6 +910,160 @@ CHECK WebcilDecoder::CheckILMethod(RVA rva)
return CorDecoderHelpers::CheckILMethod(*this, rva);
}

BOOL WebcilDecoder::HasReadyToRunHeader() const
{
CONTRACTL
{
INSTANCE_CHECK;
NOTHROW;
GC_NOTRIGGER;
CANNOT_TAKE_LOCK;
SUPPORTS_DAC;
}
CONTRACTL_END;

if (m_hasNoReadyToRunHeader)
return FALSE;

if (m_pReadyToRunHeader != NULL)
return TRUE;

return FindReadyToRunHeader() != NULL;
}

READYTORUN_HEADER * WebcilDecoder::GetReadyToRunHeader() const
{
CONTRACT(READYTORUN_HEADER *)
{
INSTANCE_CHECK;
PRECONDITION(CheckNTHeaders());
PRECONDITION(HasCorHeader());
PRECONDITION(HasReadyToRunHeader());
NOTHROW;
GC_NOTRIGGER;
Comment on lines +934 to +943
POSTCONDITION(CheckPointer(RETVAL));
SUPPORTS_DAC;
CANNOT_TAKE_LOCK;
}
CONTRACT_END;

if (m_pReadyToRunHeader != NULL)
RETURN m_pReadyToRunHeader;

RETURN FindReadyToRunHeader();
}

PTR_CVOID WebcilDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const
{
CONTRACT(PTR_CVOID)
{
INSTANCE_CHECK;
PRECONDITION(HasReadyToRunHeader());
POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); // TBD - may not store metadata for IJW
NOTHROW;
GC_NOTRIGGER;
}
CONTRACT_END;

IMAGE_DATA_DIRECTORY *pDir = NULL;
{
READYTORUN_HEADER * pHeader = GetReadyToRunHeader();

PTR_READYTORUN_SECTION pSections = dac_cast<PTR_READYTORUN_SECTION>(dac_cast<TADDR>(pHeader) + sizeof(READYTORUN_HEADER));
for (DWORD i = 0; i < pHeader->CoreHeader.NumberOfSections; i++)
{
// Verify that section types are sorted
_ASSERTE(i == 0 || (pSections[i - 1].Type < pSections[i].Type));

READYTORUN_SECTION * pSection = pSections + i;
if (pSection->Type == ReadyToRunSectionType::ManifestMetadata)
{
// Set pDir to the address of the manifest metadata section
pDir = &pSection->Section;
break;
}
}

// ReadyToRun file without large version bubble support doesn't have the ManifestMetadata
if (pDir == NULL)
{
if (pSize != NULL)
{
*pSize = 0;
}

RETURN NULL;
}
}

if (pSize != NULL)
*pSize = VAL32(pDir->Size);

RETURN dac_cast<PTR_VOID>(GetDirectoryData(pDir));
}

READYTORUN_HEADER * WebcilDecoder::FindReadyToRunHeader() const
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
SUPPORTS_DAC;
}
CONTRACTL_END;

IMAGE_DATA_DIRECTORY *pDir = &GetCorHeader()->ManagedNativeHeader;

if (VAL32(pDir->Size) >= sizeof(READYTORUN_HEADER) && CheckDirectory(pDir))
{
PTR_READYTORUN_HEADER pHeader = PTR_READYTORUN_HEADER((TADDR)GetDirectoryData(pDir));
if (pHeader->Signature == READYTORUN_SIGNATURE)
{
m_pReadyToRunHeader = pHeader;
return pHeader;
}
}

m_hasNoReadyToRunHeader = true;
return NULL;
}

TADDR WebcilDecoder::GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const
{
CONTRACT(TADDR)
{
INSTANCE_CHECK;
PRECONDITION(CheckNTHeaders());
PRECONDITION(CheckDirectory(pDir, 0, NULL_OK));
NOTHROW;
GC_NOTRIGGER;
SUPPORTS_DAC;
POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK));
CANNOT_TAKE_LOCK;
}
CONTRACT_END;

RETURN GetRvaData(VAL32(pDir->VirtualAddress));
}

CHECK WebcilDecoder::CheckDirectory(IMAGE_DATA_DIRECTORY *pDir, int forbiddenFlags, IsNullOK ok) const
{
CONTRACT_CHECK
{
INSTANCE_CHECK;
PRECONDITION(CheckNTHeaders());
PRECONDITION(CheckPointer(pDir));
NOTHROW;
Comment on lines +1031 to +1056
GC_NOTRIGGER;
SUPPORTS_DAC;
}
CONTRACT_CHECK_END;

CHECK(CheckRva(VAL32(pDir->VirtualAddress), VAL32(pDir->Size), forbiddenFlags, ok));

CHECK_OK;
}

// ------------------------------------------------------------
// DAC support
// ------------------------------------------------------------
Expand Down
20 changes: 18 additions & 2 deletions src/coreclr/vm/peimagelayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ void PEImageLayout::InitDecoders(void* data, COUNT_T size)
{
m_format = FORMAT_WEBCIL;
m_webcilDecoder.Init(data, size);
if (HasBaseRelocations())
ApplyBaseRelocations(true);
m_peDecoder.Init(data, size); // Initialize base/size/flags for cDAC
}
else
Expand Down Expand Up @@ -245,7 +247,7 @@ void PEImageLayout::ApplyBaseRelocations(bool relocationMustWriteCopy)
SSIZE_T delta = (SIZE_T) GetBase() - (SIZE_T) GetPreferredBase();

#ifdef FEATURE_WEBCIL
SSIZE_T tableBaseDelta = m_tableBaseOffset;
SSIZE_T tableBaseDelta = GetTableBaseOffset();
#endif // FEATURE_WEBCIL

// Nothing to do - image is loaded at preferred base and no table base offset
Expand Down Expand Up @@ -275,12 +277,26 @@ void PEImageLayout::ApplyBaseRelocations(bool relocationMustWriteCopy)
const SIZE_T cbPageSize = 4096;

COUNT_T dirPos = 0;
#ifdef TARGET_WASM
// WASM will padd out the reloc size to the next 16 byte boundary, so we need to validate we can safely read the IMAGE_BASE_RELOCATION struct before processing each entry.
while (dirPos < (dirSize - sizeof(IMAGE_BASE_RELOCATION)))
#else
while (dirPos < dirSize)
#endif
Comment on lines 279 to +285
{
PIMAGE_BASE_RELOCATION r = (PIMAGE_BASE_RELOCATION)(dir + dirPos);

COUNT_T fixupsSize = VAL32(r->SizeOfBlock);

#ifdef TARGET_WASM
if (fixupsSize == 0)
{
// Since WASM will pad the reloc block to the next 16 byte boundary with 0's we need to allow for a SizeOfBlock being zero.
// This can only happen for the last block in the relocation list, so we can break here instead of continue.
break;
}
#endif

USHORT *fixups = (USHORT *) (r + 1);

_ASSERTE(fixupsSize > sizeof(IMAGE_BASE_RELOCATION));
Expand Down Expand Up @@ -415,7 +431,7 @@ void PEImageLayout::ApplyBaseRelocations(bool relocationMustWriteCopy)

dirPos += fixupsSize;
}
_ASSERTE(dirSize == dirPos);
_ASSERTE(dirSize == dirPos || !IsPEFormat());

if (dwOldProtection != 0)
{
Expand Down
4 changes: 1 addition & 3 deletions src/coreclr/vm/peimagelayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ class PEImageLayout
void ApplyBaseRelocations(bool relocationMustWriteCopy);

#ifdef FEATURE_WEBCIL
// TODO-WASM: These can be removed very soon, and we can fetch this from the webcil header itself
void SetTableBaseOffset(SSIZE_T tableBaseOffset) { m_tableBaseOffset = tableBaseOffset; }
SSIZE_T GetTableBaseOffset() const { return m_tableBaseOffset; }
SSIZE_T GetTableBaseOffset() const;
#endif

// ------------------------------------------------------------
Expand Down
Loading
Loading