return INVALID_ADDRESS;
}
+/**
+ * mono_images_rva_map:
+ * @image: a MonoImage
+ * @addr: relative virtual address (RVA)
+ *
+ * This is a low-level routine used by the runtime to map relative
+ * virtual address (RVA) into their location in memory.
+ *
+ * Returns: the address in memory for the given RVA, or NULL if the
+ * RVA is not valid for this image.
+ */
char *
mono_image_rva_map (MonoImage *image, guint32 addr)
{
image->heap_guid.size = read32 (ptr + 4);
ptr += 8 + 6;
} else if (strncmp (ptr + 8, "#-", 3) == 0) {
- g_print ("Assembly '%s' has the non-standard metadata heap #-.\nRecompile it correctly (without the /incremental switch or in Release mode).", image->name);
- return FALSE;
+ image->heap_tables.data = image->raw_metadata + read32 (ptr);
+ image->heap_tables.size = read32 (ptr + 4);
+ ptr += 8 + 3;
+ image->uncompressed_metadata = TRUE;
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly '%s' has the non-standard metadata heap #-.\nRecompile it correctly (without the /incremental switch or in Release mode).\n", image->name);
} else {
g_message ("Unknown heap type: %s\n", ptr + 8);
ptr += 8 + strlen (ptr + 8) + 1;
return load_tables (image);
}
+void
+mono_image_check_for_module_cctor (MonoImage *image)
+{
+ MonoTableInfo *t, *mt;
+ t = &image->tables [MONO_TABLE_TYPEDEF];
+ mt = &image->tables [MONO_TABLE_METHOD];
+ if (mono_get_runtime_info ()->framework_version [0] == '1') {
+ image->checked_module_cctor = TRUE;
+ return;
+ }
+ if (t->rows >= 1) {
+ guint32 nameidx = mono_metadata_decode_row_col (t, 0, MONO_TYPEDEF_NAME);
+ const char *name = mono_metadata_string_heap (image, nameidx);
+ if (strcmp (name, "<Module>") == 0) {
+ guint32 first_method = mono_metadata_decode_row_col (t, 0, MONO_TYPEDEF_METHOD_LIST) - 1;
+ guint32 last_method;
+ if (t->rows > 1)
+ last_method = mono_metadata_decode_row_col (t, 1, MONO_TYPEDEF_METHOD_LIST) - 1;
+ else
+ last_method = mt->rows;
+ for (; first_method < last_method; first_method++) {
+ nameidx = mono_metadata_decode_row_col (mt, first_method, MONO_METHOD_NAME);
+ name = mono_metadata_string_heap (image, nameidx);
+ if (strcmp (name, ".cctor") == 0) {
+ image->has_module_cctor = TRUE;
+ image->checked_module_cctor = TRUE;
+ return;
+ }
+ }
+ }
+ }
+ image->has_module_cctor = FALSE;
+ image->checked_module_cctor = TRUE;
+}
+
static void
-load_modules (MonoImage *image, MonoImageOpenStatus *status)
+load_modules (MonoImage *image)
+{
+ MonoTableInfo *t;
+
+ if (image->modules)
+ return;
+
+ t = &image->tables [MONO_TABLE_MODULEREF];
+ image->modules = g_new0 (MonoImage *, t->rows);
+ image->modules_loaded = g_new0 (gboolean, t->rows);
+ image->module_count = t->rows;
+}
+
+/**
+ * mono_image_load_module:
+ *
+ * Load the module with the one-based index IDX from IMAGE and return it. Return NULL if
+ * it cannot be loaded.
+ */
+MonoImage*
+mono_image_load_module (MonoImage *image, int idx)
{
MonoTableInfo *t;
MonoTableInfo *file_table;
char *base_dir;
gboolean refonly = image->ref_only;
GList *list_iter, *valid_modules = NULL;
+ MonoImageOpenStatus status;
- if (image->modules)
- return;
+ g_assert (idx <= image->module_count);
+ if (image->modules_loaded [idx - 1])
+ return image->modules [idx - 1];
file_table = &image->tables [MONO_TABLE_FILE];
for (i = 0; i < file_table->rows; i++) {
}
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;
const char *name;
guint32 cols [MONO_MODULEREF_SIZE];
- int valid = 0;
+ /* if there is no file table, we try to load the module... */
+ int valid = file_table->rows == 0;
- mono_metadata_decode_row (t, i, cols, MONO_MODULEREF_SIZE);
+ mono_metadata_decode_row (t, idx - 1, cols, MONO_MODULEREF_SIZE);
name = mono_metadata_string_heap (image, cols [MONO_MODULEREF_NAME]);
for (list_iter = valid_modules; list_iter; list_iter = list_iter->next) {
/* be safe with string dups, but we could just compare string indexes */
break;
}
}
- if (!valid)
- continue;
- module_ref = g_build_filename (base_dir, name, NULL);
- image->modules [i] = mono_image_open_full (module_ref, status, refonly);
- if (image->modules [i]) {
- mono_image_addref (image->modules [i]);
- /* g_print ("loaded module %s from %s (%p)\n", module_ref, image->name, image->assembly); */
+ if (valid) {
+ module_ref = g_build_filename (base_dir, name, NULL);
+ image->modules [idx - 1] = mono_image_open_full (module_ref, &status, refonly);
+ if (image->modules [idx - 1]) {
+ mono_image_addref (image->modules [idx - 1]);
+ image->modules [idx - 1]->assembly = image->assembly;
+ /* g_print ("loaded module %s from %s (%p)\n", module_ref, image->name, image->assembly); */
+ }
+ g_free (module_ref);
}
- /*
- * FIXME: We should probably do lazy-loading of modules.
- */
- if (status)
- *status = MONO_IMAGE_OK;
- g_free (module_ref);
}
+ image->modules_loaded [idx - 1] = TRUE;
+
g_free (base_dir);
g_list_free (valid_modules);
+
+ return image->modules [idx - 1];
}
static void
mono_metadata_decode_row_col (&image->tables [MONO_TABLE_MODULE],
0, MONO_MODULE_NAME));
- load_modules (image, status);
+ load_modules (image);
done:
if (status)
return res;
}
+/**
+ * mono_image_loaded:
+ * @name: name of the image to load
+ *
+ * This routine ensures that the given image is loaded.
+ *
+ * Returns: the loaded MonoImage, or NULL on failure.
+ */
MonoImage *
mono_image_loaded (const char *name)
{
MonoPEResourceDirEntry *entry,
MonoPEResourceDir *root, guint32 level)
{
- gboolean is_string=entry->name_is_string;
+ gboolean is_string, is_dir;
+ guint32 name_offset, dir_offset;
/* Level 0 holds a directory entry for each type of resource
* (identified by ID or name).
* Level 2 holds a directory entry for each language pointing to
* the actual data.
*/
+ name_offset = GUINT32_FROM_LE (entry->name_offset) & 0x7fffffff;
+ dir_offset = GUINT32_FROM_LE (entry->dir_offset) & 0x7fffffff;
+
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ is_string = (GUINT32_FROM_LE (entry->name_offset) & 0x80000000) != 0;
+ is_dir = (GUINT32_FROM_LE (entry->dir_offset) & 0x80000000) != 0;
+#else
+ is_string = entry->name_is_string;
+ is_dir = entry->is_dir;
+#endif
if(level==0) {
- if((is_string==FALSE && entry->name_offset!=res_id) ||
+ if((is_string==FALSE && name_offset!=res_id) ||
(is_string==TRUE)) {
return(NULL);
}
} else if (level==1) {
#if 0
if(name!=NULL &&
- is_string==TRUE && name!=lookup (entry->name_offset)) {
+ is_string==TRUE && name!=lookup (name_offset)) {
return(NULL);
}
#endif
} else if (level==2) {
if ((is_string == FALSE &&
- entry->name_offset != lang_id &&
+ name_offset != lang_id &&
lang_id != 0) ||
(is_string == TRUE)) {
return(NULL);
g_assert_not_reached ();
}
- if(entry->is_dir==TRUE) {
- MonoPEResourceDir *res_dir=(MonoPEResourceDir *)(((char *)root)+entry->dir_offset);
+ if(is_dir==TRUE) {
+ MonoPEResourceDir *res_dir=(MonoPEResourceDir *)(((char *)root)+dir_offset);
MonoPEResourceDirEntry *sub_entries=(MonoPEResourceDirEntry *)(res_dir+1);
guint32 entries, i;
-
- entries=res_dir->res_named_entries + res_dir->res_id_entries;
+
+ entries = GUINT16_FROM_LE (res_dir->res_named_entries) + GUINT16_FROM_LE (res_dir->res_id_entries);
for(i=0; i<entries; i++) {
MonoPEResourceDirEntry *sub_entry=&sub_entries[i];
return(NULL);
} else {
- MonoPEResourceDataEntry *data_entry=(MonoPEResourceDataEntry *)((char *)(root)+entry->dir_offset);
-
- return(data_entry);
+ MonoPEResourceDataEntry *data_entry=(MonoPEResourceDataEntry *)((char *)(root)+dir_offset);
+ MonoPEResourceDataEntry *res;
+
+ res = g_new0 (MonoPEResourceDataEntry, 1);
+
+ res->rde_data_offset = GUINT32_TO_LE (data_entry->rde_data_offset);
+ res->rde_size = GUINT32_TO_LE (data_entry->rde_size);
+ res->rde_codepage = GUINT32_TO_LE (data_entry->rde_codepage);
+ res->rde_reserved = GUINT32_TO_LE (data_entry->rde_reserved);
+
+ return (res);
}
}
* @name: the resource name to lookup.
*
* Returns: NULL if not found, otherwise a pointer to the in-memory representation
- * of the given resource.
+ * of the given resource. The caller should free it using g_free () when no longer
+ * needed.
*/
gpointer
mono_image_lookup_resource (MonoImage *image, guint32 res_id, guint32 lang_id, gunichar2 *name)
if(resource_dir==NULL) {
return(NULL);
}
-
- entries=resource_dir->res_named_entries + resource_dir->res_id_entries;
+
+ entries = GUINT16_FROM_LE (resource_dir->res_named_entries) + GUINT16_FROM_LE (resource_dir->res_id_entries);
res_entries=(MonoPEResourceDirEntry *)(resource_dir+1);
for(i=0; i<entries; i++) {
return res;
}
+/**
+ * mono_image_get_strong_name:
+ * @image: a MonoImage
+ * @size: a guint32 pointer, or NULL.
+ *
+ * If the image has a strong name, and @size is not NULL, the value
+ * pointed to by size will have the size of the strong name.
+ *
+ * Returns: NULL if the image does not have a strong name, or a
+ * pointer to the public key.
+ */
const char*
mono_image_get_strong_name (MonoImage *image, guint32 *size)
{
return data;
}
+/**
+ * mono_image_strong_name_position:
+ * @image: a MonoImage
+ * @size: a guint32 pointer, or NULL.
+ *
+ * If the image has a strong name, and @size is not NULL, the value
+ * pointed to by size will have the size of the strong name.
+ *
+ * Returns: the position within the image file where the strong name
+ * is stored.
+ */
guint32
mono_image_strong_name_position (MonoImage *image, guint32 *size)
{
return 0;
}
+/**
+ * mono_image_get_public_key:
+ * @image: a MonoImage
+ * @size: a guint32 pointer, or NULL.
+ *
+ * This is used to obtain the public key in the @image.
+ *
+ * If the image has a public key, and @size is not NULL, the value
+ * pointed to by size will have the size of the public key.
+ *
+ * Returns: NULL if the image does not have a public key, or a pointer
+ * to the public key.
+ */
const char*
mono_image_get_public_key (MonoImage *image, guint32 *size)
{
return pubkey;
}
+/**
+ * mono_image_get_name:
+ * @name: a MonoImage
+ *
+ * Returns: the name of the assembly.
+ */
const char*
mono_image_get_name (MonoImage *image)
{
return image->assembly_name;
}
+/**
+ * mono_image_get_filename:
+ * @image: a MonoImage
+ *
+ * Used to get the filename that hold the actual MonoImage
+ *
+ * Returns: the filename.
+ */
const char*
mono_image_get_filename (MonoImage *image)
{
return table->rows;
}
+/**
+ * mono_image_get_assembly:
+ * @image: the MonoImage.
+ *
+ * Use this routine to get the assembly that owns this image.
+ *
+ * Returns: the assembly that holds this image.
+ */
MonoAssembly*
mono_image_get_assembly (MonoImage *image)
{
return image->assembly;
}
+/**
+ * mono_image_is_dynamic:
+ * @image: the MonoImage
+ *
+ * Determines if the given image was created dynamically through the
+ * System.Reflection.Emit API
+ *
+ * Returns: TRUE if the image was created dynamically, FALSE if not.
+ */
gboolean
mono_image_is_dynamic (MonoImage *image)
{
return image->dynamic;
}
+/**
+ * mono_image_has_authenticode_entry:
+ * @image: the MonoImage
+ *
+ * Use this routine to determine if the image has a Authenticode
+ * Certificate Table.
+ *
+ * Returns: TRUE if the image contains an authenticode entry in the PE
+ * directory.
+ */
gboolean
mono_image_has_authenticode_entry (MonoImage *image)
{