#include "private.h"
#include "tabledefs.h"
#include "tokentype.h"
+#include "metadata-internals.h"
#include <mono/io-layer/io-layer.h>
#define INVALID_ADDRESS 0xffffffff
}
char *
-mono_cli_rva_map (MonoCLIImageInfo *iinfo, guint32 addr)
+mono_image_rva_map (MonoImage *image, guint32 addr)
{
+ MonoCLIImageInfo *iinfo = image->image_info;
const int top = iinfo->cli_section_count;
MonoSectionTable *tables = iinfo->cli_section_tables;
int i;
for (i = 0; i < top; i++){
if ((addr >= tables->st_virtual_address) &&
(addr < tables->st_virtual_address + tables->st_raw_data_size)){
+ if (!iinfo->cli_sections [i]) {
+ if (!mono_image_ensure_section_idx (image, i))
+ return NULL;
+ }
return (char*)iinfo->cli_sections [i] +
(addr - tables->st_virtual_address);
}
return NULL;
}
+static gchar *
+canonicalize_path (const char *path)
+{
+ gchar *abspath, *pos, *lastpos, *dest;
+ int backc;
+
+ if (g_path_is_absolute (path)) {
+ abspath = g_strdup (path);
+ } else {
+ gchar *tmpdir = g_get_current_dir ();
+ abspath = g_build_filename (tmpdir, path, NULL);
+ g_free (tmpdir);
+ }
+
+ abspath = g_strreverse (abspath);
+
+ backc = 0;
+ dest = lastpos = abspath;
+ pos = strchr (lastpos, G_DIR_SEPARATOR);
+
+ while (pos != NULL) {
+ int len = pos - lastpos;
+ if (len == 1 && lastpos [0] == '.') {
+ // nop
+ } else if (len == 2 && lastpos [0] == '.' && lastpos [1] == '.') {
+ backc++;
+ } else if (len > 0) {
+ if (backc > 0) {
+ backc--;
+ } else {
+ if (dest != lastpos) strncpy (dest, lastpos, len + 1);
+ dest += len + 1;
+ }
+ }
+ lastpos = pos + 1;
+ pos = strchr (lastpos, G_DIR_SEPARATOR);
+ }
+
+ if (dest != lastpos) strcpy (dest, lastpos);
+ return g_strreverse (abspath);
+}
+
/**
* mono_images_init:
*
/* consistency checks here */
}
- for (i = 0; i < top; i++)
- if (!mono_image_ensure_section_idx (image, i))
- return FALSE;
-
return TRUE;
}
return FALSE;
} else {
g_message ("Unknown heap type: %s\n", ptr + 8);
- ptr += 8 + strlen (ptr) + 1;
+ ptr += 8 + strlen (ptr + 8) + 1;
}
pad = ptr - image->raw_metadata;
if (pad % 4)
t = &image->tables [MONO_TABLE_MODULEREF];
image->modules = g_new0 (MonoImage *, t->rows);
+ image->module_count = t->rows;
base_dir = g_path_get_dirname (image->name);
for (i = 0; i < t->rows; i++){
char *module_ref;
module_ref = g_build_filename (base_dir, name, NULL);
image->modules [i] = mono_image_open (module_ref, status);
if (image->modules [i]) {
- //g_print ("loaded module %s from %s (%p)\n", module_ref, image->name, image->assembly);
+ /* g_print ("loaded module %s from %s (%p)\n", module_ref, image->name, image->assembly); */
}
/*
* FIXME: what do we do here? it could be a native dll...
image->delegate_invoke_cache =
g_hash_table_new ((GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
-
- image->runtime_invoke_cache = g_hash_table_new (NULL, NULL);
+ image->runtime_invoke_cache =
+ g_hash_table_new ((GHashFunc)mono_signature_hash,
+ (GCompareFunc)mono_metadata_signature_equal);
+
image->managed_wrapper_cache = g_hash_table_new (NULL, NULL);
image->native_wrapper_cache = g_hash_table_new (NULL, NULL);
image->remoting_invoke_cache = g_hash_table_new (NULL, NULL);
image->synchronized_cache = g_hash_table_new (NULL, NULL);
+ image->unbox_wrapper_cache = g_hash_table_new (NULL, NULL);
- image->generics_cache = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GEqualFunc)mono_metadata_type_equal);
image->typespec_cache = g_hash_table_new (NULL, NULL);
+ image->memberref_signatures = g_hash_table_new (NULL, NULL);
+ image->helper_signatures = g_hash_table_new (g_str_hash, g_str_equal);
}
static MonoImage *
image = g_new0 (MonoImage, 1);
image->ref_count = 1;
image->f = filed;
- image->name = g_strdup (fname);
iinfo = g_new0 (MonoCLIImageInfo, 1);
image->image_info = iinfo;
+ image->name = canonicalize_path (fname);
return do_mono_image_load (image, status);
}
{
MonoImage *res;
- if (strcmp (name, "corlib") == 0)
- name = "mscorlib";
-
EnterCriticalSection (&images_mutex);
res = g_hash_table_lookup (loaded_images_hash, name);
LeaveCriticalSection (&images_mutex);
mono_image_open (const char *fname, MonoImageOpenStatus *status)
{
MonoImage *image, *image2;
+ char *absfname;
g_return_val_if_fail (fname != NULL, NULL);
+
+ absfname = canonicalize_path (fname);
/*
* The easiest solution would be to do all the loading inside the mutex,
* the same image, we discard all but the first copy.
*/
EnterCriticalSection (&images_mutex);
- image = g_hash_table_lookup (loaded_images_hash, fname);
+ image = g_hash_table_lookup (loaded_images_hash, absfname);
+ g_free (absfname);
+
if (image){
image->ref_count++;
LeaveCriticalSection (&images_mutex);
return NULL;
EnterCriticalSection (&images_mutex);
- image2 = g_hash_table_lookup (loaded_images_hash, fname);
+ 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)
+ 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);
g_hash_table_destroy ((GHashTable*)val);
}
+static void
+free_mr_signatures (gpointer key, gpointer val, gpointer user_data)
+{
+ mono_metadata_free_method_signature ((MonoMethodSignature*)val);
+}
+
+static void
+free_remoting_wrappers (gpointer key, gpointer val, gpointer user_data)
+{
+ g_free (val);
+}
+
/**
- * mono_image_close:
+ * mono_image_addref:
* @image: The image file we wish to add a reference to
*
* Increases the reference count of an image.
if (image == image2) {
/* This is not true if we are called from mono_image_open () */
g_hash_table_remove (loaded_images_hash, image->name);
- if (image->assembly_name)
- g_hash_table_remove (loaded_images_hash, (char *) image->assembly_name);
g_hash_table_remove (loaded_images_guid_hash, image->guid);
/* Multiple images might have the same guid */
build_guid_table ();
- }
+ }
+ if (image->assembly_name && (g_hash_table_lookup (loaded_images_hash, image->assembly_name) == image))
+ g_hash_table_remove (loaded_images_hash, (char *) image->assembly_name);
LeaveCriticalSection (&images_mutex);
if (image->f)
fclose (image->f);
- if (image->raw_data_allocated)
- g_free (image->raw_data);
+ if (image->raw_data_allocated) {
+ /* image->raw_metadata and cli_sections might lie inside image->raw_data */
+ MonoCLIImageInfo *ii = image->image_info;
+ int i;
+
+ if ((image->raw_metadata > image->raw_data) &&
+ (image->raw_metadata <= (image->raw_data + image->raw_data_len)))
+ image->raw_metadata = NULL;
+
+ for (i = 0; i < ii->cli_section_count; i++)
+ if (((char*)(ii->cli_sections [i]) > image->raw_data) &&
+ ((char*)(ii->cli_sections [i]) <= ((char*)image->raw_data + image->raw_data_len)))
+ ii->cli_sections [i] = NULL;
+ g_free (image->raw_data);
+ }
g_free (image->name);
+ g_free (image->guid);
g_free (image->files);
g_hash_table_destroy (image->method_cache);
g_hash_table_destroy (image->delegate_begin_invoke_cache);
g_hash_table_destroy (image->delegate_end_invoke_cache);
g_hash_table_destroy (image->delegate_invoke_cache);
+ g_hash_table_foreach (image->remoting_invoke_cache, free_remoting_wrappers, NULL);
g_hash_table_destroy (image->remoting_invoke_cache);
g_hash_table_destroy (image->runtime_invoke_cache);
+ g_hash_table_destroy (image->synchronized_cache);
+ g_hash_table_destroy (image->unbox_wrapper_cache);
+ g_hash_table_destroy (image->typespec_cache);
+ g_hash_table_foreach (image->memberref_signatures, free_mr_signatures, NULL);
+ g_hash_table_destroy (image->memberref_signatures);
+ g_hash_table_foreach (image->helper_signatures, free_mr_signatures, NULL);
+ g_hash_table_destroy (image->helper_signatures);
if (image->raw_metadata != NULL)
mono_raw_buffer_free (image->raw_metadata);
g_free (image->image_info);
}
- g_free (image);
+ if (!image->dynamic)
+ /* Dynamic images are GC_MALLOCed */
+ g_free (image);
}
/**
return(NULL);
}
- resource_dir=(MonoPEResourceDir *)mono_cli_rva_map (info, rsrc->rva);
+ resource_dir=(MonoPEResourceDir *)mono_image_rva_map (image, rsrc->rva);
if(resource_dir==NULL) {
return(NULL);
}
if (!ch->ch_resources.rva || offset + 4 > ch->ch_resources.size)
return NULL;
- data = mono_cli_rva_map (iinfo, ch->ch_resources.rva);
+ data = mono_image_rva_map (image, ch->ch_resources.rva);
if (!data)
return NULL;
data += offset;
res = mono_image_open (name, NULL);
if (res) {
int i;
- t = &res->tables [MONO_TABLE_MODULEREF];
- //g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly);
+ /* g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly); */
res->assembly = image->assembly;
- for (i = 0; i < t->rows; ++i) {
+ for (i = 0; i < res->module_count; ++i) {
if (res->modules [i] && !res->modules [i]->assembly)
res->modules [i]->assembly = image->assembly;
}
if (!de->size || !de->rva)
return NULL;
- data = mono_cli_rva_map (iinfo, de->rva);
+ data = mono_image_rva_map (image, de->rva);
if (!data)
return NULL;
if (size)
return pubkey;
}
+const char*
+mono_image_get_name (MonoImage *image)
+{
+ return image->assembly_name;
+}
+
+const char*
+mono_image_get_filename (MonoImage *image)
+{
+ return image->name;
+}
+
+const MonoTableInfo*
+mono_image_get_table_info (MonoImage *image, int table_id)
+{
+ if (table_id < 0 || table_id >= 64)
+ return NULL;
+ return &image->tables [table_id];
+}
+
+int
+mono_image_get_table_rows (MonoImage *image, int table_id)
+{
+ if (table_id < 0 || table_id >= 64)
+ return 0;
+ return image->tables [table_id].rows;
+}
+
+int
+mono_table_info_get_rows (const MonoTableInfo *table)
+{
+ return table->rows;
+}
+
+MonoAssembly*
+mono_image_get_assembly (MonoImage *image)
+{
+ return image->assembly;
+}
+
+gboolean
+mono_image_is_dynamic (MonoImage *image)
+{
+ return image->dynamic;
+}
+
+gboolean
+mono_image_has_authenticode_entry (MonoImage *image)
+{
+ MonoCLIImageInfo *iinfo = image->image_info;
+ MonoDotNetHeader *header = &iinfo->cli_header;
+ MonoPEDirEntry *de = &header->datadir.pe_certificate_table;
+ // the Authenticode "pre" (non ASN.1) header is 8 bytes long
+ return ((de->rva != 0) && (de->size > 8));
+}