Skip to content

Commit

Permalink
[mbr] Fix encmap boundary and method RVA lookup. (#50254)
Browse files Browse the repository at this point in the history
Two separate issues:

1. When we process the EnC map, any tables after the last one that has an
update gets an "enc_recs" pointer that's one past the last row of the
table.  (the enc_recs pointer is used to speed up relative address lookup).  So
at lookup time if enc_recs says to look past the end of the EnC map table, we
know there won't be any updates - return -1.

2. When looking for the updated RVA of a method, we need to go through every
delta and find the latest one that has an update for the given method.  The
problem is that if a later generation doesn't have an update, we would take the
NULL return value at face value and it would look like the method had no
updates to its body - we would go back to using the original version from
before any updates were applied.  Instead now ignore lookup table misses and
remember the last successful lookup.  Fixes
#50190
  • Loading branch information
lambdageek committed Mar 30, 2021
1 parent 58cf4f2 commit f513229
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
14 changes: 12 additions & 2 deletions src/mono/mono/metadata/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -2000,16 +2000,26 @@ get_method_update_rva (MonoImage *image_base, uint32_t idx)
{
gpointer loc = NULL;
uint32_t cur = mono_metadata_update_get_thread_generation ();
int generation = -1;
GList *ptr = image_base->delta_image;
/* Go through all the updates that the current thread can see and see
* if they updated the method. Keep the latest visible update */
for (; ptr != NULL; ptr = ptr->next) {
MonoImage *image_delta = (MonoImage*) ptr->data;
if (image_delta->generation > cur)
break;
if (image_delta->method_table_update)
loc = g_hash_table_lookup (image_delta->method_table_update, GUINT_TO_POINTER (idx));
if (image_delta->method_table_update) {
gpointer result = g_hash_table_lookup (image_delta->method_table_update, GUINT_TO_POINTER (idx));
/* if it's not in the table of a later generation, the
* later generation didn't modify the method
*/
if (result != NULL) {
loc = result;
generation = image_delta->generation;
}
}
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "method lookup idx=0x%08x returned gen=%d il=%p", idx, generation, loc);
return loc;
}
#endif
Expand Down
10 changes: 9 additions & 1 deletion src/mono/mono/metadata/metadata-update.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,11 +635,18 @@ mono_image_relative_delta_index (MonoImage *image_dmeta, int token)
g_assert (delta_info);

int index_map = delta_info->enc_recs [table];
int encmap_rows = encmap->rows;

/* if the table didn't have any updates in this generation and the
* table index is bigger than the last table that got updates,
* enc_recs will point past the last row */
if (index_map - 1 == encmap_rows)
return -1;
guint32 cols[MONO_ENCMAP_SIZE];
mono_metadata_decode_row (encmap, index_map - 1, cols, MONO_ENCMAP_SIZE);
int map_entry = cols [MONO_ENCMAP_TOKEN];

while (mono_metadata_token_table (map_entry) == table && mono_metadata_token_index (map_entry) < index && index_map < encmap->rows) {
while (mono_metadata_token_table (map_entry) == table && mono_metadata_token_index (map_entry) < index && index_map < encmap_rows) {
mono_metadata_decode_row (encmap, ++index_map - 1, cols, MONO_ENCMAP_SIZE);
map_entry = cols [MONO_ENCMAP_TOKEN];
}
Expand Down Expand Up @@ -847,6 +854,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, gconstpointer
static void
set_update_method (MonoImage *image_base, uint32_t generation, MonoImage *image_dmeta, uint32_t token_index, const char* il_address)
{
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "setting method 0x%08x in g=%d IL=%p", token_index, generation, (void*)il_address);
/* FIXME: this is a race if other threads are doing a lookup. */
g_hash_table_insert (image_base->method_table_update, GUINT_TO_POINTER (token_index), GUINT_TO_POINTER (generation));
g_hash_table_insert (image_dmeta->method_table_update, GUINT_TO_POINTER (token_index), (gpointer) il_address);
Expand Down

0 comments on commit f513229

Please sign in to comment.