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

[mbr] Add support for editing property getters/setters #51011

Merged
4 commits merged into from
Apr 14, 2021
Merged
Changes from 3 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
86 changes: 77 additions & 9 deletions src/mono/mono/metadata/metadata-update.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,11 +814,58 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, gconstpointer
int token_table = mono_metadata_token_table (log_token);
int token_index = mono_metadata_token_index (log_token);

if (token_table == MONO_TABLE_ASSEMBLYREF) {
switch (token_table) {
case MONO_TABLE_ASSEMBLYREF:
/* okay, supported */
} else if (token_table == MONO_TABLE_METHOD) {
break;
case MONO_TABLE_METHOD:
/* handled above */
} else {
break;
case MONO_TABLE_PROPERTY:
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
if (token_index <= table_info_get_rows (&image_base->tables [token_table])) {
/* modifying a property */
break;
} else {
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x we do not support adding new properties.", i, log_token);
mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support adding new properties. token=0x%08x", log_token);
unsupported_edits = TRUE;
continue;
}
case MONO_TABLE_METHODSEMANTICS: {
if (token_index > table_info_get_rows (&image_base->tables [token_table])) {
/* new rows are fine, as long as they point at existing methods */
guint32 sema_cols [MONO_METHOD_SEMA_SIZE];
int mapped_token = mono_image_relative_delta_index (image_dmeta, mono_metadata_make_token (token_table, token_index));
g_assert (mapped_token != -1);
mono_metadata_decode_row (&image_dmeta->tables [MONO_TABLE_METHODSEMANTICS], mapped_token - 1, sema_cols, MONO_METHOD_SEMA_SIZE);

switch (sema_cols [MONO_METHOD_SEMA_SEMANTICS]) {
case METHOD_SEMANTIC_GETTER:
case METHOD_SEMANTIC_SETTER: {
int prop_method_index = sema_cols [MONO_METHOD_SEMA_METHOD];
/* ok, if it's pointing to an existing getter/setter */
if (prop_method_index < table_info_get_rows (&image_base->tables [MONO_TABLE_METHOD]))
break;
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x adding new getter/setter method 0x%08x to a property is not supported", i, log_token, prop_method_index);
mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support adding a new getter or setter to a property, token=0x%08x", log_token);
unsupported_edits = TRUE;
continue;
}
default:
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x adding new non-getter/setter property or event methods is not supported.", i, log_token);
mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support adding new non-getter/setter property or event methods. token=0x%08x", log_token);
unsupported_edits = TRUE;
continue;
}
} else {
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x we do not support patching of existing table cols.", i, log_token);
mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support patching of existing table cols. token=0x%08x", log_token);
unsupported_edits = TRUE;
continue;
}
}
default:
/* FIXME: this bounds check is wrong for cumulative updates - need to look at the DeltaInfo:count.prev_gen_rows */
if (token_index <= table_info_get_rows (&image_base->tables [token_table])) {
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x we do not support patching of existing table cols.", i, log_token);
mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support patching of existing table cols. token=0x%08x", log_token);
Expand Down Expand Up @@ -884,7 +931,8 @@ apply_enclog_pass2 (MonoImage *image_base, uint32_t generation, MonoImage *image
break;
}

if (token_table == MONO_TABLE_ASSEMBLYREF) {
switch (token_table) {
case MONO_TABLE_ASSEMBLYREF: {
g_assert (token_index > table_info_get_rows (&image_base->tables [token_table]));

if (assemblyref_updated)
Expand Down Expand Up @@ -916,7 +964,9 @@ apply_enclog_pass2 (MonoImage *image_base, uint32_t generation, MonoImage *image
mono_image_unlock (image_base);

g_free (old_array);
} else if (token_table == MONO_TABLE_METHOD) {
break;
}
case MONO_TABLE_METHOD: {
if (token_index > table_info_get_rows (&image_base->tables [token_table])) {
g_error ("EnC: new method added, should be caught by pass1");
}
Expand All @@ -935,17 +985,29 @@ apply_enclog_pass2 (MonoImage *image_base, uint32_t generation, MonoImage *image
/* rva points probably into image_base IL stream. can this ever happen? */
g_print ("TODO: this case is still a bit contrived. token=0x%08x with rva=0x%04x\n", log_token, rva);
}
} else if (token_table == MONO_TABLE_TYPEDEF) {
break;
}
case MONO_TABLE_TYPEDEF: {
/* TODO: throw? */
/* TODO: happens changing the class (adding field or method). we ignore it, but dragons are here */

/* existing entries are supposed to be patched */
g_assert (token_index <= table_info_get_rows (&image_base->tables [token_table]));
} else {
break;
}
case MONO_TABLE_PROPERTY: {
/* allow updates to existing properties. */
/* FIXME: use DeltaInfo:prev_gen_rows instead of image_base */
g_assert (token_index <= table_info_get_rows (&image_base->tables [token_table]));
/* assuming that property attributes and type haven't changed. */
break;
}
default: {
g_assert (token_index > table_info_get_rows (&image_base->tables [token_table]));
if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE))
g_print ("todo: do something about this table index: 0x%02x\n", token_table);
}
}
}
return TRUE;
}
Expand Down Expand Up @@ -1016,6 +1078,14 @@ mono_image_load_enc_delta (MonoImage *image_base, gconstpointer dmeta_bytes, uin
return;
}

/* Process EnCMap and compute number of added/modified rows from this
* delta. This enables computing row indexes relative to the delta.
* We use it in pass1 to bail out early if the EnCLog has unsupported
* edits.
*/
delta_info_init (image_dmeta, image_base);


if (!apply_enclog_pass1 (image_base, image_dmeta, dil_bytes, dil_length, error)) {
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "Error on sanity-checking delta image to base=%s, due to: %s", basename, mono_error_get_message (error));
mono_metadata_update_cancel (generation);
Expand All @@ -1026,8 +1096,6 @@ mono_image_load_enc_delta (MonoImage *image_base, gconstpointer dmeta_bytes, uin
if (table_info_get_rows (table_enclog))
table_to_image_add (image_base);

delta_info_init (image_dmeta, image_base);

mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "base guid: %s", image_base->guid);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "dmeta guid: %s", image_dmeta->guid);

Expand Down