[metadata] Assorted enhancements for some CIL image formats (#42398)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Fri, 18 Sep 2020 13:45:30 +0000 (09:45 -0400)
committerGitHub <noreply@github.com>
Fri, 18 Sep 2020 13:45:30 +0000 (09:45 -0400)
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 <lambdageek@users.noreply.github.com>
src/mono/mono/metadata/image.c
src/mono/mono/metadata/metadata.c

index 0b61757..ba93004 100644 (file)
@@ -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));
index de7c1d0..ca88806 100644 (file)
@@ -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