[Mono-bugs] [Bug 70429][Maj] New - find_method failed in assembly loaded using mono_image_open_from_data from preload_hook

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Fri, 10 Dec 2004 11:41:18 -0500 (EST)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by ymeng@bloomberg.net.

http://bugzilla.ximian.com/show_bug.cgi?id=70429

--- shadow/70429	2004-12-10 11:41:18.000000000 -0500
+++ shadow/70429.tmp.4602	2004-12-10 11:41:18.000000000 -0500
@@ -0,0 +1,285 @@
+Bug#: 70429
+Product: Mono: Runtime
+Version: 1.1
+OS: 
+OS Details: Window XP
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Major
+Component: misc
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: ymeng@bloomberg.net               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: find_method failed in assembly loaded using mono_image_open_from_data from preload_hook
+
+Our project requires selectively loading assemblies from memory. This was
+achieved with mono_image_open_from_data() in an assembly preload hook. Most
+of the time it works. However, in assemblies loaded in such a manner, Mono
+seems to have trouble resolving method or class references. In certain
+assemblies, the find_method call fails repeatedly in loader.cs line 355. If
+we load the same assemblies from disk using mono_image_open() instead of
+from memory, the problem disappears.
+
+I noticed that mono_image_open_from_data() does not look up the
+loaded_image_hash before loading the image, neither does it insert the
+image to the hash after a successful load. This seem to be a major
+difference between ..._open_from_data() and ..._open(). I added an
+additional function mono_image_open_from_data_with_name(), which adds the
+hash look-up and insertion before and after loading. When I used this
+function in my preload hook, the problem was fixed.
+
+MonoImage *                                                               
+                                                                          
+              
+mono_image_open_from_data_with_name(const char *name, char *data, guint32
+data_len, gboolean need_copy, MonoImageOpenStatus *status)                
+               
+{                                                                         
+                                                                          
+              
+    MonoCLIImageInfo *iinfo;                                              
+                                                                          
+              
+    MonoImage *image, *image2;                                            
+                                                                          
+              
+    char *datac;                                                          
+                                                                          
+              
+    char *imgName;                                                        
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    g_return_val_if_fail (name != NULL, NULL);                            
+                                                                          
+              
+                                                                          
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    /*                                                                    
+                                                                          
+              
+     * The easiest solution would be to do all the loading inside the
+mutex,                                                                    
+                   
+     * but that would lead to scalability problems. So we let the loading 
+                                                                          
+              
+     * happen outside the mutex, and if multiple threads happen to load   
+                                                                          
+              
+     * the same image, we discard all but the first copy.                 
+                                                                          
+              
+     */                                                                   
+                                                                          
+              
+    imgName = g_strdup(name);                                             
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    EnterCriticalSection (&images_mutex);                                 
+                                                                          
+              
+    image = g_hash_table_lookup (loaded_images_hash, imgName);            
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    if (image){                                                           
+                                                                          
+              
+        image->ref_count++;                                               
+                                                                          
+              
+        LeaveCriticalSection (&images_mutex);                             
+                                                                          
+              
+        return image;                                                     
+                                                                          
+              
+    }                                                                     
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    LeaveCriticalSection (&images_mutex);                                 
+                                                                          
+              
+                                                                          
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    if (!data || !data_len) {                                             
+                                                                          
+              
+        if (status)                                                       
+                                                                          
+              
+            *status = MONO_IMAGE_IMAGE_INVALID;                           
+                                                                          
+              
+        return NULL;                                                      
+                                                                          
+              
+    }                                                                     
+                                                                          
+              
+    datac = data;                                                         
+                                                                          
+              
+    if (need_copy) {                                                      
+                                                                          
+              
+        datac = g_try_malloc (data_len);                                  
+                                                                          
+              
+        if (!datac) {                                                     
+                                                                          
+              
+            if (status)                                                   
+                                                                          
+              
+                *status = MONO_IMAGE_ERROR_ERRNO;                         
+                                                                          
+              
+            return NULL;                                                  
+                                                                          
+              
+        }                                                                 
+                                                                          
+              
+        memcpy (datac, data, data_len);                                   
+                                                                          
+              
+    }                                                                     
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    image = g_new0 (MonoImage, 1);                                        
+                                                                          
+              
+    image->ref_count = 1;                                                 
+                                                                          
+              
+    image->raw_data = datac;                                              
+                                                                          
+              
+    image->raw_data_len = data_len;                                       
+                                                                          
+              
+    image->raw_data_allocated = need_copy;                                
+                                                                          
+              
+    image->name = imgName;                                                
+                                                                          
+              
+    iinfo = g_new0 (MonoCLIImageInfo, 1);                                 
+                                                                          
+              
+    image->image_info = iinfo;                                            
+                                                                          
+              
+                                                                          
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    image = do_mono_image_load(image, status);                            
+                                                                          
+              
+                                                                          
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    if (image == NULL)                                                    
+                                                                          
+              
+        return NULL;                                                      
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    EnterCriticalSection (&images_mutex);                                 
+                                                                          
+              
+    image2 = g_hash_table_lookup (loaded_images_hash, image->name);       
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    if (image2) {                                                         
+                                                                          
+              
+        /* Somebody else beat us to it */                                 
+                                                                          
+              
+        image2->ref_count ++;                                             
+                                                                          
+              
+        LeaveCriticalSection (&images_mutex);                             
+                                                                          
+              
+        mono_image_close (image);                                         
+                                                                          
+              
+        return image2;                                                    
+                                                                          
+              
+    }                                                                     
+                                                                          
+              
+    g_hash_table_insert (loaded_images_hash, image->name, image);         
+                                                                          
+              
+    if (image->assembly_name && (g_hash_table_lookup (loaded_images_hash,
+image->assembly_name) == NULL))                                           
+               
+        g_hash_table_insert (loaded_images_hash, (char *)
+image->assembly_name, image);                                             
+                               
+    g_hash_table_insert (loaded_images_guid_hash, image->guid, image);    
+                                                                          
+              
+    LeaveCriticalSection (&images_mutex);                                 
+                                                                          
+              
+                                                                          
+                                                                          
+              
+    return image;                                                         
+                                                                          
+              
+                                                                          
+                                                                          
+              
+                                                                          
+                                                                          
+              
+}
+
+
+Please consider adding such a function or fix the existing
+image_open_from_data such that it behaves the same as the file based   open