From: monojenkins Date: Fri, 18 Sep 2020 13:45:30 +0000 (-0400) Subject: [metadata] Assorted enhancements for some CIL image formats (#42398) X-Git-Tag: submit/tizen/20210909.063632~5431 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6f72257061fbec6c972b94fd7c8da15903f1e112;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [metadata] Assorted enhancements for some CIL image formats (#42398) Some cherrypicked changes from a work in progress * Try to set MonoImage guid from modules table for metadata_only images If the image has a modules table, and a guid heap, set MonoImage:guid when loading the image, even if it is metadata_only. In minimal delta images this is true. * Minimal delta files have 4 byte indices, always * Don't populate MonoImage:module_name for minimal deltas * Always store precise string heap size in MonoImage:heap_strings In minimal delta images, the String heap is appended to the heap of the base image. But in the physical base image, the String heap is zero-padded to a size that's a multiple of 4 bytes. Compute the precise String heap size at base image load time. Co-authored-by: lambdageek --- diff --git a/src/mono/mono/metadata/image.c b/src/mono/mono/metadata/image.c index 0b61757..ba93004 100644 --- a/src/mono/mono/metadata/image.c +++ b/src/mono/mono/metadata/image.c @@ -449,6 +449,21 @@ mono_image_load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo) return TRUE; } +/** + * mono_metadata_module_mvid: + * + * Return the module mvid GUID or NULL if the image doesn't have a module table. + */ +static const guint8 * +mono_metadata_module_mvid (MonoImage *image) +{ + if (!image->tables [MONO_TABLE_MODULE].base) + return NULL; + guint32 module_cols [MONO_MODULE_SIZE]; + mono_metadata_decode_row (&image->tables [MONO_TABLE_MODULE], 0, module_cols, MONO_MODULE_SIZE); + return (const guint8*) mono_metadata_guid_heap (image, module_cols [MONO_MODULE_MVID]); +} + static gboolean load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo) { @@ -543,6 +558,21 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo) ptr += 4 - (pad % 4); } + { + /* Compute the precise size of the string heap by walking back over the trailing nul padding. + * + * ENC minimal delta images require the precise size of the base image string heap to be known. + */ + const char *p; + p = image->heap_strings.data + image->heap_strings.size - 1; + pad = 0; + while (p [0] == '\0' && p [-1] == '\0') { + p--; + pad++; + } + image->heap_strings.size -= pad; + } + i = ((MonoImageLoader*)image->loader)->load_tables (image); if (!image->metadata_only) { @@ -551,12 +581,17 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo) image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data); } else { - /* PPDB files have no guid */ - guint8 empty_guid [16]; + const guint8 *guid = mono_metadata_module_mvid (image); + if (guid) + image->guid = mono_guid_to_string (guid); + else { + /* PPDB files have no guid */ + guint8 empty_guid [16]; - memset (empty_guid, 0, sizeof (empty_guid)); + memset (empty_guid, 0, sizeof (empty_guid)); - image->guid = mono_guid_to_string (empty_guid); + image->guid = mono_guid_to_string (empty_guid); + } } return i; @@ -1174,7 +1209,10 @@ mono_image_load_names (MonoImage *image) } /* Portable pdb images don't have a MODULE row */ - if (image->tables [MONO_TABLE_MODULE].rows) { + /* Minimal ENC delta images index the combined string heap of the base and delta image, + * so the module index is out of bounds here. + */ + if (image->tables [MONO_TABLE_MODULE].rows && !image->minimal_delta) { image->module_name = mono_metadata_string_heap (image, mono_metadata_decode_row_col (&image->tables [MONO_TABLE_MODULE], 0, MONO_MODULE_NAME)); diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index de7c1d0..ca88806 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -564,11 +564,22 @@ finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical ro inverse of this mapping. */ -#define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4)) +static int +rtsize (MonoImage *meta, int sz, int bits) +{ + if (G_UNLIKELY (meta->minimal_delta)) + return 4; + if (sz < (1 << bits)) + return 2; + else + return 4; +} static int idx_size (MonoImage *meta, int idx) { + if (G_UNLIKELY (meta->minimal_delta)) + return 4; if (meta->referenced_tables && (meta->referenced_tables & ((guint64)1 << idx))) return meta->referenced_table_rows [idx] < 65536 ? 2 : 4; else