Skip to content
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

[mono] Implement AssemblyExtensions.TryGetRawMetadata. #111642

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

teo-tsirpanis
Copy link
Contributor

No description provided.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jan 20, 2025
@teo-tsirpanis teo-tsirpanis marked this pull request as ready for review January 20, 2025 23:12
Comment on lines 4747 to 4760
ves_icall_System_Reflection_RuntimeAssembly_InternalTryGetRawMetadata (MonoQCallAssemblyHandle assembly_h, gpointer_ref blob, gint32_ref length, MonoError *error)
{
MonoAssembly *assembly = assembly_h.assembly;
MonoImage *image = assembly->image;

if (image_is_dynamic (image)) {
return FALSE;
}

*blob = image->raw_metadata;
*((guint32*)length) = image->raw_metadata_len;

return TRUE;
}
Copy link
Member

Choose a reason for hiding this comment

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

Are you sure that this handles the hot reload case? I think this would give back the metadata for the unedited image with Mono's hot reload implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have no idea. What does CoreCLR do in hot-reloaded assemblies?

Copy link
Member

Choose a reason for hiding this comment

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

For CoreCLR, we have an editable metadata system, so RefEmit and Hot Reload go down the same path (no metadata blob available to pass up to callers).

For Mono, their RefEmit solution is a completely separate lookup system, so Hot Reload uses a separate mechanism that works via "layers".

Copy link
Member

Choose a reason for hiding this comment

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

So for Mono, you need to check the has_updates bit on the MonoImage. If that's true, this function needs to return false.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Member

Choose a reason for hiding this comment

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

For CoreCLR, we have an editable metadata system, so RefEmit and Hot Reload go down the same path (no metadata blob available to pass up to callers).

If I am reading the correctly, CoreCLR returns the original metadata blob for hot reload assemblies from this API.

you need to check the has_updates bit on the MonoImage.

I think it is unnecessary difference from the CoreCLR behavior. I do not see a block like this in the CoreCLR implementation.

Copy link
Member

Choose a reason for hiding this comment

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

@jkotas, you're right. I was thinking of a different internal API that the implementation in CoreCLR doesn't use. The actual function it calls doesn't care about Hot Reload and just returns the original image.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated code to remove checks and rely on the metadata pointer not being null. This now matches the CoreCLR implementation.

extern "C" BOOL QCALLTYPE AssemblyNative_InternalTryGetRawMetadata(
QCall::AssemblyHandle assembly,
UINT8 **blobRef,
INT32 *lengthRef)
{
QCALL_CONTRACT;
PTR_CVOID metadata = nullptr;
BEGIN_QCALL;
_ASSERTE(assembly != nullptr);
_ASSERTE(blobRef != nullptr);
_ASSERTE(lengthRef != nullptr);
static_assert_no_msg(sizeof(*lengthRef) == sizeof(COUNT_T));
metadata = assembly->GetPEAssembly()->GetLoadedMetadata(reinterpret_cast<COUNT_T *>(lengthRef));
*blobRef = reinterpret_cast<UINT8 *>(const_cast<PTR_VOID>(metadata));
_ASSERTE(*lengthRef >= 0);
END_QCALL;
return metadata != nullptr;
}

And return if the metadata blob pointer is not null, matching CoreCLR implementation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-VM-meta-mono community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants