Renamed MonoAssembly to MonoImage to reflect better reality
authorMiguel de Icaza <miguel@gnome.org>
Wed, 18 Jul 2001 04:33:51 +0000 (04:33 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Wed, 18 Jul 2001 04:33:51 +0000 (04:33 -0000)
svn path=/trunk/mono/; revision=220

12 files changed:
configure.in
doc/faq
mono/dis/Makefile.am
mono/dis/main.c
mono/dis/meta.h
mono/metadata/ChangeLog
mono/metadata/Makefile.am
mono/metadata/image.c [new file with mode: 0644]
mono/metadata/image.h [new file with mode: 0644]
mono/metadata/metadata.c
mono/metadata/pedump.c
web/faq

index fcfe6492389e9f15ec6b0e5426ba798a7286eb91..7e40f106d4f86d06cc575fdc2a85e64d499c81c9 100644 (file)
@@ -32,6 +32,7 @@ mono/Makefile
 mono/metadata/Makefile
 mono/dis/Makefile
 mono/cil/Makefile
+mono/cli/Makefile
 mono/interpreter/Makefile
 doc/Makefile
 ])
diff --git a/doc/faq b/doc/faq
index b26b206886d11b8cc373929a01e580d5fb1371cc..d992ecd440e06d2389fe82c559aca6172127fa16 100644 (file)
--- a/doc/faq
+++ b/doc/faq
@@ -575,7 +575,7 @@ A: The JIT engine and runtime engine will be able to execute CIL
 
 Q: Is Mono part of the GNU project?
 
-A: Mono is a Ximian project, that is also part of the GNU project.
+A: Mono is a Ximian project.  It is also part of the GNU project.
 
 ** Mono and Portability
 
index 9cb1baad6ad2fba407a7a67a20caa9abdd865d61..479cc7c68524f5f8c290590beea0a7f9e1b6772c 100644 (file)
@@ -2,20 +2,25 @@ INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
 
 bin_PROGRAMS = monodis
 
-monodis_SOURCES =      \
+lib_LIBRARIES = libmonodis.a
+
+libmonodis_a_SOURCES = \
        get.c           \
        get.h           \
        dis-cil.c       \
        dis-cil.h       \
+       util.c          \
+       util.h
+
+monodis_SOURCES =      \
        dump.c          \
        dump.h          \
        main.c          \
-       meta.h          \
-       util.c          \
-       util.h
+       meta.h
 
 monodis_LDADD =                        \
        ../metadata/libmetadata.a       \
+       libmonodis.a                    \
        $(GLIB_LIBS) 
 
 man_MANS = monodis.1
index 6004135259451fbdc3aacc87fea959b8b852bcc2..f7c790c6b7e2b6a08b95153f267a317b9da322cc 100644 (file)
@@ -30,7 +30,7 @@ gboolean dump_header_data_p = FALSE;
 int dump_table = -1;
 
 static void
-dump_header_data (MonoAssembly *ass)
+dump_header_data (MonoImage *img)
 {
        if (!dump_header_data_p)
                return;
@@ -600,50 +600,50 @@ struct {
 static void
 disassemble_file (const char *file)
 {
-       enum MonoAssemblyOpenStatus status;
-       MonoAssembly *ass;
+       enum MonoImageOpenStatus status;
+       MonoImage *img;
        cli_image_info_t *ii;
        metadata_t *m;
 
        fprintf (output, "// Disassembling %s\n", file);
 
-       ass = mono_assembly_open (file, &status);
-       if (ass == NULL){
+       img = mono_image_open (file, &status);
+       if (img == NULL){
                fprintf (stderr, "Error while trying to process %s\n", file);
                return;
        }
 
-       ii = ass->image_info;
+       ii = img->image_info;
        m = &ii->cli_metadata;
        
        if (dump_table != -1){
                (*table_list [dump_table].dumper) (m);
        } else {
-               dump_header_data (ass);
+               dump_header_data (img);
                
                dis_directive_assemblyref (m);
                dis_directive_assembly (m);
                dis_types (m, ii);
        }
        
-       mono_assembly_close (ass);
+       mono_image_close (img);
 }
 
 static void
 usage (void)
 {
-       GString *args = g_string_new ("");
+       GString *args = g_string_new ("[--help]");
        int i;
        
        for (i = 0; table_list [i].name != NULL; i++){
                g_string_append (args, "[");
                g_string_append (args, table_list [i].name);
                g_string_append (args, "] ");
-               if ((i % 4) == 0)
+               if (((i-2) % 5) == 0)
                        g_string_append_c (args, '\n');
        }
        fprintf (stderr,
-                "Usage is: monodis %s file ..\n", args);
+                "Usage is: monodis %s file ..\n", args->str);
        exit (1);
 }
 
index 8d8629d921d12c6e272171b49c4fe6e2dbd8b21a..f8d9c971f98ae2559c7c322b841e50cf16a50ba3 100644 (file)
@@ -1,4 +1,4 @@
-#include <mono/metadata/assembly.h>
+#include <mono/metadata/image.h>
 #include <mono/metadata/cil-coff.h>
 #include <mono/metadata/endian.h>
 #include <mono/metadata/typeattr.h>
index 5933a3b67b9275f81849ff45f3ef5e21e5177c8b..600d1853e490cfc649e8287fff8ca72b06b647d4 100644 (file)
@@ -1,5 +1,8 @@
 2001-07-17  Miguel de Icaza  <miguel@ximian.com>
 
+       * assembly.c (mono_assembly_open): Keep track of the file name in
+       case the assembly has no ASSEMBLY table.
+
        * metadata.h: Fixed Paolo's quick hack.  Put the documnentation
        from get.c here.
 
index 2966a60a0b06b8dcd8d4a4cb521c5bbba8b75b17..bce7cef182755d37270ea172d7bd3db36c7f2d71 100644 (file)
@@ -5,19 +5,19 @@ lib_LIBRARIES = libmetadata.a
 INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
 
 libmetadata_a_SOURCES = \
-       assembly.c      \
+       image.c         \
        metadata.c      \
        rawbuffer.c
 
 libmetadataincludedir = $(includedir)/mono/metadata
 
 libmetadatainclude_HEADERS = \
-       assembly.h      \
        blobsig.h       \
        cil-coff.h      \
        eltype.h        \
        endian.h        \
        fieldattr.h     \
+       image.h         \
        metadata.h      \
        methodattr.h    \
        methodheader.h  \
diff --git a/mono/metadata/image.c b/mono/metadata/image.c
new file mode 100644 (file)
index 0000000..4863495
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * image.c: Routines for manipulating an image stored in an
+ * extended PE/COFF file.
+ * 
+ * Author:
+ *   Miguel de Icaza (miguel@ximian.com)
+ *
+ * (C) 2001 Ximian, Inc.  http://www.ximian.com
+ *
+ * TODO:
+ *   Implement big-endian versions of the reading routines.
+ */
+#include <config.h>
+#include <stdio.h>
+#include <glib.h>
+#include <errno.h>
+#include <string.h>
+#include "image.h"
+#include "cil-coff.h"
+#include "rawbuffer.h"
+#include "endian.h"
+
+#define INVALID_ADDRESS 0xffffffff
+
+guint32
+cli_rva_image_map (cli_image_info_t *iinfo, guint32 addr)
+{
+       const int top = iinfo->cli_section_count;
+       section_table_t *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)){
+                       return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
+               }
+               tables++;
+       }
+       return INVALID_ADDRESS;
+}
+
+char *
+cli_rva_map (cli_image_info_t *iinfo, guint32 addr)
+{
+       const int top = iinfo->cli_section_count;
+       section_table_t *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)){
+                       return iinfo->cli_sections [i] +
+                               (addr - tables->st_virtual_address);
+               }
+               tables++;
+       }
+       return NULL;
+}
+
+/**
+ * mono_image_ensure_section_idx:
+ * @image: The image we are operating on
+ * @section: section number that we will load/map into memory
+ *
+ * This routine makes sure that we have an in-memory copy of
+ * an image section (.text, .rsrc, .data).
+ *
+ * Returns: TRUE on success
+ */
+int
+mono_image_ensure_section_idx (MonoImage *image, int section)
+{
+       cli_image_info_t *iinfo = image->image_info;
+       section_table_t *sect;
+       gboolean writable;
+       
+       g_return_val_if_fail (section < iinfo->cli_section_count, FALSE);
+
+       if (iinfo->cli_sections [section] != NULL)
+               return TRUE;
+
+       sect = &iinfo->cli_section_tables [section];
+       
+       writable = sect->st_flags & SECT_FLAGS_MEM_WRITE;
+
+       iinfo->cli_sections [section] = raw_buffer_load (
+               fileno (image->f), writable,
+               sect->st_raw_data_ptr, sect->st_raw_data_size);
+
+       if (iinfo->cli_sections [section] == NULL)
+               return FALSE;
+
+       return TRUE;
+}
+
+/**
+ * mono_image_ensure_section:
+ * @image: The image we are operating on
+ * @section: section name that we will load/map into memory
+ *
+ * This routine makes sure that we have an in-memory copy of
+ * an image section (.text, .rsrc, .data).
+ *
+ * Returns: TRUE on success
+ */
+int
+mono_image_ensure_section (MonoImage *image, const char *section)
+{
+       cli_image_info_t *ii = image->image_info;
+       int i;
+       
+       for (i = 0; i < ii->cli_section_count; i++){
+               if (strncmp (ii->cli_section_tables [i].st_name, section, 8) != 0)
+                       continue;
+               
+               return mono_image_ensure_section_idx (image, i);
+       }
+       return FALSE;
+}
+
+static int
+load_section_tables (MonoImage *image, cli_image_info_t *iinfo)
+{
+       const int top = iinfo->cli_header.coff.coff_sections;
+       int i;
+
+       iinfo->cli_section_count = top;
+       iinfo->cli_section_tables = g_new0 (section_table_t, top);
+       iinfo->cli_sections = g_new0 (void *, top);
+       
+       for (i = 0; i < top; i++){
+               section_table_t *t = &iinfo->cli_section_tables [i];
+               
+               if (fread (t, sizeof (section_table_t), 1, image->f) != 1)
+                       return FALSE;
+
+               t->st_virtual_size = le32_to_cpu (t->st_virtual_size);
+               t->st_virtual_address = le32_to_cpu (t->st_virtual_address);
+               t->st_raw_data_size = le32_to_cpu (t->st_raw_data_size);
+               t->st_raw_data_ptr = le32_to_cpu (t->st_raw_data_ptr);
+               t->st_reloc_ptr = le32_to_cpu (t->st_reloc_ptr);
+               t->st_lineno_ptr = le32_to_cpu (t->st_lineno_ptr);
+               t->st_reloc_count = le16_to_cpu (t->st_reloc_count);
+               t->st_line_count = le16_to_cpu (t->st_line_count);
+       }
+
+       for (i = 0; i < top; i++)
+               if (!mono_image_ensure_section_idx (image, i))
+                       return FALSE;
+       
+       return TRUE;
+}
+
+static gboolean
+load_cli_header (MonoImage *image, cli_image_info_t *iinfo)
+{
+       guint32 offset;
+       int n;
+       
+       offset = cli_rva_image_map (iinfo, iinfo->cli_header.datadir.pe_cli_header.rva);
+       if (offset == INVALID_ADDRESS)
+               return FALSE;
+
+       if (fseek (image->f, offset, 0) != 0)
+               return FALSE;
+       
+       if ((n = fread (&iinfo->cli_cli_header, sizeof (cli_header_t), 1, image->f)) != 1)
+               return FALSE;
+
+       /* Catch new uses of the fields that are supposed to be zero */
+
+       if ((iinfo->cli_cli_header.ch_eeinfo_table.rva != 0) ||
+           (iinfo->cli_cli_header.ch_helper_table.rva != 0) ||
+           (iinfo->cli_cli_header.ch_dynamic_info.rva != 0) ||
+           (iinfo->cli_cli_header.ch_delay_load_info.rva != 0) ||
+           (iinfo->cli_cli_header.ch_module_image.rva != 0) ||
+           (iinfo->cli_cli_header.ch_external_fixups.rva != 0) ||
+           (iinfo->cli_cli_header.ch_ridmap.rva != 0) ||
+           (iinfo->cli_cli_header.ch_debug_map.rva != 0) ||
+           (iinfo->cli_cli_header.ch_ip_map.rva != 0)){
+               g_message ("Some fields in the CLI header which should have been zero are not zero");
+       }
+           
+       return TRUE;
+}
+
+static gboolean
+load_metadata_ptrs (MonoImage *image, cli_image_info_t *iinfo)
+{
+       metadata_t *metadata = &iinfo->cli_metadata;
+       guint32 offset, size;
+       guint16 streams;
+       int i;
+       char *ptr;
+       
+       offset = cli_rva_image_map (iinfo, iinfo->cli_cli_header.ch_metadata.rva);
+       size = iinfo->cli_cli_header.ch_metadata.size;
+       
+       metadata->raw_metadata = raw_buffer_load (fileno (image->f), FALSE, offset, size);
+       if (metadata->raw_metadata == NULL)
+               return FALSE;
+
+       ptr = metadata->raw_metadata;
+
+       if (strncmp (ptr, "BSJB", 4) == 0){
+               guint32 version_string_len;
+
+               ptr += 12;
+               version_string_len = read32 (ptr);
+               ptr += 4;
+               ptr += version_string_len;
+               if (((guint32) ptr) % 4)
+                       ptr += 4 - (((guint32) ptr) %4);
+       } else
+               return FALSE;
+
+       /* skip over flags */
+       ptr += 2;
+       
+       streams = read16 (ptr);
+       ptr += 2;
+
+       for (i = 0; i < streams; i++){
+               if (strncmp (ptr + 8, "#~", 3) == 0){
+                       metadata->heap_tables.sh_offset = read32 (ptr);
+                       metadata->heap_tables.sh_size = read32 (ptr + 4);
+                       ptr += 8 + 3;
+               } else if (strncmp (ptr + 8, "#Strings", 9) == 0){
+                       metadata->heap_strings.sh_offset = read32 (ptr);
+                       metadata->heap_strings.sh_size = read32 (ptr + 4);
+                       ptr += 8 + 9;
+               } else if (strncmp (ptr + 8, "#US", 4) == 0){
+                       metadata->heap_us.sh_offset = read32 (ptr);
+                       metadata->heap_us.sh_size = read32 (ptr + 4);
+                       ptr += 8 + 4;
+               } else if (strncmp (ptr + 8, "#Blob", 6) == 0){
+                       metadata->heap_blob.sh_offset = read32 (ptr);
+                       metadata->heap_blob.sh_size = read32 (ptr + 4);
+                       ptr += 8 + 6;
+               } else if (strncmp (ptr + 8, "#GUID", 6) == 0){
+                       metadata->heap_guid.sh_offset = read32 (ptr);
+                       metadata->heap_guid.sh_size = read32 (ptr + 4);
+                       ptr += 8 + 6;
+               } else
+                       g_message ("Unknown heap type: %s\n", ptr + 8);
+               if (((guint32)ptr) % 4){
+                       ptr += 4 - (((guint32)ptr) % 4);
+               }
+       }
+       return TRUE;
+}
+
+/*
+ * Load representation of logical metadata tables, from the "#~" stream
+ */
+static gboolean
+load_tables (MonoImage *image, metadata_t *meta)
+{
+       char *heap_tables = meta->raw_metadata + meta->heap_tables.sh_offset;
+       guint32 *rows;
+       guint64 valid_mask;
+       int valid = 0, table;
+       int heap_sizes;
+       
+       heap_sizes = heap_tables [6];
+       meta->idx_string_wide = ((heap_sizes & 0x01) == 1);
+       meta->idx_guid_wide   = ((heap_sizes & 0x02) == 2);
+       meta->idx_blob_wide   = ((heap_sizes & 0x04) == 4);
+       
+       valid_mask = read64 (heap_tables + 8);
+       rows = (guint32 *) (heap_tables + 24);
+       
+       for (table = 0; table < 64; table++){
+               if ((valid_mask & ((guint64) 1 << table)) == 0){
+                       meta->tables [table].rows = 0;
+                       continue;
+               }
+               if (table > 0x2b) {
+                       g_warning("bits in valid must be zero above 0x2b (II - 23.1.6)");
+               }
+               meta->tables [table].rows = read32 (rows);
+               rows++;
+               valid++;
+       }
+
+       meta->tables_base = (heap_tables + 24) + (4 * valid);
+
+       /* They must be the same */
+       g_assert ((void *) meta->tables_base == (void *) rows);
+
+       mono_metadata_compute_table_bases (meta);
+       return TRUE;
+}
+
+static gboolean
+load_metadata (MonoImage *image, cli_image_info_t *iinfo)
+{
+       if (!load_metadata_ptrs (image, iinfo))
+               return FALSE;
+
+       return load_tables (image, &iinfo->cli_metadata);
+}
+
+/**
+ * mono_image_open:
+ * @fname: filename that points to the module we want to open
+ * @status: An error condition is returned in this field
+ *
+ * Retuns: An open image of type %MonoImage or NULL on error.
+ * if NULL, then check the value of @status for details on the error
+ */
+MonoImage *
+mono_image_open (const char *fname, enum MonoImageOpenStatus *status)
+{
+       cli_image_info_t *iinfo;
+       dotnet_header_t *header;
+       msdos_header_t msdos;
+       MonoImage *image;
+       int n;
+
+       image = g_new0 (MonoImage, 1);
+       image->f = fopen (fname, "r");
+       image->name = g_strdup (fname);
+       iinfo = g_new0 (cli_image_info_t, 1);
+       image->image_info = iinfo;
+
+       header = &iinfo->cli_header;
+               
+       if (image->f == NULL){
+               if (status)
+                       *status = MONO_IMAGE_ERROR_ERRNO;
+               mono_image_close (image);
+               return NULL;
+       }
+
+       if (status)
+               *status = MONO_IMAGE_IMAGE_INVALID;
+       
+       if (fread (&msdos, sizeof (msdos), 1, image->f) != 1)
+               goto invalid_image;
+       
+       if (!(msdos.msdos_header [0] == 0x4d && msdos.msdos_header [1] == 0x5a))
+               goto invalid_image;
+       
+       if ((n = fread (header, sizeof (dotnet_header_t), 1, image->f)) != 1)
+               goto invalid_image;
+
+       /*
+        * FIXME: byte swap all addresses here for header.
+        */
+       
+       if (!load_section_tables (image, iinfo))
+               goto invalid_image;
+       
+       /* Load the CLI header */
+       if (!load_cli_header (image, iinfo))
+               goto invalid_image;
+
+       if (!load_metadata (image, iinfo))
+               goto invalid_image;
+       
+       if (status)
+               *status = MONO_IMAGE_OK;
+
+       return image;
+
+invalid_image:
+       mono_image_close (image);
+               return NULL;
+}
+
+/**
+ * mono_image_close:
+ * @image: The image file we wish to close
+ *
+ * Closes an image file, deallocates all memory consumed and
+ * unmaps all possible sections of the file
+ */
+void
+mono_image_close (MonoImage *image)
+{
+       g_return_if_fail (image != NULL);
+
+       if (image->f)
+               fclose (image->f);
+
+       g_free (image->name);
+       
+       if (image->image_info){
+               cli_image_info_t *ii = image->image_info;
+               int i;
+
+               if (ii->cli_metadata.raw_metadata != NULL)
+                       raw_buffer_free (ii->cli_metadata.raw_metadata);
+       
+               for (i = 0; i < ii->cli_section_count; i++){
+                       if (!ii->cli_sections [i])
+                               continue;
+                       raw_buffer_free (ii->cli_sections [i]);
+               }
+               if (ii->cli_section_tables)
+                       g_free (ii->cli_section_tables);
+               if (ii->cli_sections)
+                       g_free (ii->cli_sections);
+               g_free (image->image_info);
+       }
+       
+       g_free (image);
+}
+
+/** 
+ * mono_image_strerror:
+ * @status: an code indicating the result from a recent operation
+ *
+ * Returns: a string describing the error
+ */
+const char *
+mono_image_strerror (enum MonoImageOpenStatus status)
+{
+       switch (status){
+       case MONO_IMAGE_OK:
+               return "success";
+       case MONO_IMAGE_ERROR_ERRNO:
+               return strerror (errno);
+       case MONO_IMAGE_IMAGE_INVALID:
+               return "File does not contain a valid CIL image";
+       }
+       return "Internal error";
+}
+
diff --git a/mono/metadata/image.h b/mono/metadata/image.h
new file mode 100644 (file)
index 0000000..578793a
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _MONONET_METADATA_IMAGE_H_ 
+#define _MONONET_METADATA_IMAGE_H_
+
+typedef struct {
+       FILE *f;
+       char *name;
+       void *image_info;
+
+       /*
+        * user_info is a public field and is not touched by the
+        * metadata engine
+        */
+       void *user_info;
+} MonoImage;
+
+enum MonoImageOpenStatus {
+       MONO_IMAGE_OK,
+       MONO_IMAGE_ERROR_ERRNO,
+       MONO_IMAGE_IMAGE_INVALID
+};
+
+MonoImage    *mono_image_open     (const char *fname,
+                                  enum MonoImageOpenStatus *status);
+void          mono_image_close    (MonoImage *image);
+const char   *mono_image_strerror (enum MonoImageOpenStatus status);
+
+
+int           mono_image_ensure_section     (MonoImage *image,
+                                            const char *section);
+int           mono_image_ensure_section_idx (MonoImage *image,
+                                            int section);
+       
+#endif
index f194d97272b60fb1ac9309650e43631315e6f281..496e24112c7ef754b802603f85437d30c7332454 100644 (file)
@@ -891,6 +891,7 @@ mono_metadata_parse_typedef_or_ref (metadata_t *m, const char *ptr, const char *
        guint32 token;
        guint table;
        ptr = mono_metadata_decode_value (ptr, &token);
+
        switch (table & 0x03) {
        case 0: table = META_TABLE_TYPEDEF; break;
        case 1: table = META_TABLE_TYPEREF; break;
index 3415dee70397ee2a995462c74161cb1fba010d18..cfd60622c34ae9f81fce4a9c55eccc5a318191f0 100644 (file)
@@ -9,7 +9,7 @@
 #include <config.h>
 #include <stdio.h>
 #include <string.h>
-#include "assembly.h"
+#include "image.h"
 #include <glib.h>
 #include "cil-coff.h"
 
@@ -281,7 +281,7 @@ int
 main (int argc, char *argv [])
 {
        cli_image_info_t *iinfo;
-       MonoAssembly *assembly;
+       MonoImage *image;
        char *file = NULL;
        int i;
        
@@ -300,17 +300,17 @@ main (int argc, char *argv [])
        if (!file)
                usage ();
 
-       assembly = mono_assembly_open (file, NULL);
-       if (!assembly){
-               fprintf (stderr, "Can not open assembly %s\n", file);
+       image = mono_image_open (file, NULL);
+       if (!image){
+               fprintf (stderr, "Can not open image %s\n", file);
                exit (1);
        }
-       iinfo = assembly->image_info;
+       iinfo = image->image_info;
 
        if (dump_data)
                dump_dotnet_iinfo (iinfo);
        
-       mono_assembly_close (assembly);
+       mono_image_close (image);
        
        return 0;
 }
diff --git a/web/faq b/web/faq
index b26b206886d11b8cc373929a01e580d5fb1371cc..d992ecd440e06d2389fe82c559aca6172127fa16 100644 (file)
--- a/web/faq
+++ b/web/faq
@@ -575,7 +575,7 @@ A: The JIT engine and runtime engine will be able to execute CIL
 
 Q: Is Mono part of the GNU project?
 
-A: Mono is a Ximian project, that is also part of the GNU project.
+A: Mono is a Ximian project.  It is also part of the GNU project.
 
 ** Mono and Portability