Initial revision
authorMiguel de Icaza <miguel@gnome.org>
Tue, 19 Jun 2001 03:37:46 +0000 (03:37 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Tue, 19 Jun 2001 03:37:46 +0000 (03:37 -0000)
svn path=/trunk/mono/; revision=9

19 files changed:
AUTHORS [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
config.h.in [new file with mode: 0644]
configure.in [new file with mode: 0644]
mono/Makefile.am [new file with mode: 0644]
mono/dis/Makefile.am [new file with mode: 0644]
mono/dis/main.c [new file with mode: 0644]
mono/metadata/Makefile.am [new file with mode: 0644]
mono/metadata/assembly.c [new file with mode: 0644]
mono/metadata/assembly.h [new file with mode: 0644]
mono/metadata/cil-coff.h [new file with mode: 0644]
mono/metadata/metadata.c [new file with mode: 0644]
mono/metadata/metadata.h [new file with mode: 0644]
mono/metadata/pedump.c [new file with mode: 0644]
mono/metadata/rawbuffer.c [new file with mode: 0644]
mono/metadata/rawbuffer.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..25e66d4
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Miguel de Icaza (miguel@ximian.com)
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..1a76f44
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+2001-05-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * NEWS: 
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..7a0d4a4
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = mono
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..37b3c85
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,3 @@
+2001-05-30  Miguel de Icaza  <miguel@ximian.com>
+
+       Project started
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..27f2ef4
--- /dev/null
+++ b/README
@@ -0,0 +1,3 @@
+This is MonoNet.
+
+Ximian's portable implementation of .NET 
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..f871c4e
--- /dev/null
@@ -0,0 +1,11 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..b146447
--- /dev/null
@@ -0,0 +1,34 @@
+AC_INIT(README)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(mononet, 0.1)
+AM_MAINTAINER_MODE
+
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_PROG_INSTALL
+
+# Set STDC_HEADERS
+AC_HEADER_STDC
+AM_PROG_LIBTOOL
+
+dnl ***************************
+dnl *** Checks for glib 1.2 ***
+dnl ***************************
+AM_PATH_GLIB(1.2.0,,
+             AC_MSG_ERROR([Cannot find GLIB: Is glib-config in path?]))
+
+GLIB_CFLAGS=`glib-config --cflags glib`
+GLIB_LIBS=`glib-config --libs glib`
+
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+CFLAGS='-g -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations'
+AC_SUBST(CFLAGS)
+
+AC_OUTPUT([
+Makefile
+mono/Makefile
+mono/metadata/Makefile
+mono/dis/Makefile
+])
\ No newline at end of file
diff --git a/mono/Makefile.am b/mono/Makefile.am
new file mode 100644 (file)
index 0000000..89d68d8
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = metadata dis
\ No newline at end of file
diff --git a/mono/dis/Makefile.am b/mono/dis/Makefile.am
new file mode 100644 (file)
index 0000000..fdb8662
--- /dev/null
@@ -0,0 +1,10 @@
+INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
+
+bin_PROGRAMS = monodis
+
+monodis_SOURCES =      \
+       main.c
+
+monodis_LDADD =                        \
+       ../metadata/libmetadata.a       \
+       $(GLIB_LIBS) 
diff --git a/mono/dis/main.c b/mono/dis/main.c
new file mode 100644 (file)
index 0000000..49f9027
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * dis.c: Sample disassembler
+ *
+ * Author:
+ *   Miguel de Icaza (miguel@ximian.com)
+ *
+ * (C) 2001 Ximian, Inc.
+ */
+#include <config.h>
+#include <stdio.h>
+#include <glib.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/cil-coff.h>
+
+FILE *output;
+
+/* True if you want to get a dump of the header data */
+gboolean dump_header_data_p = FALSE;
+
+static void
+dump_header_data (MonoAssembly *ass)
+{
+       if (!dump_header_data_p)
+               return;
+
+       fprintf (output,
+                "// Ximian's CIL disassembler, version 1.0\n"
+                "// Copyright (C) 2001 Ximian, Inc.\n\n");
+}
+
+static void
+disassemble_file (const char *file)
+{
+       enum MonoAssemblyOpenStatus status;
+       MonoAssembly *ass;
+
+       ass = mono_assembly_open (file, &status);
+       if (ass == NULL){
+               fprintf (stderr, "Error while trying to process %s\n", file);
+               
+       }
+
+       dump_header_data (ass);
+
+       mono_assembly_close (ass);
+}
+
+static void
+usage (void)
+{
+       fprintf (stderr, "Usage is: monodis file1 ..\n");
+       exit (1);
+}
+
+int
+main (int argc, char *argv [])
+{
+       GList *input_files = NULL, *l;
+       int i;
+
+       output = stdout;
+       for (i = 1; i < argc; i++){
+               if (argv [i][0] == '-'){
+                       if (argv [i][1] == 'h')
+                               usage ();
+                       else if (argv [i][1] == 'd')
+                               dump_header_data_p = TRUE;
+               } else
+                       input_files = g_list_append (input_files, argv [i]);
+       }
+
+       if (input_files == NULL)
+               usage ();
+       
+       for (l = input_files; l; l = l->next)
+               disassemble_file (l->data);
+}
diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am
new file mode 100644 (file)
index 0000000..505141d
--- /dev/null
@@ -0,0 +1,19 @@
+noinst_PROGRAMS = pedump
+
+lib_LIBRARIES = libmetadata.a
+
+INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
+
+libmetadata_a_SOURCES = \
+       assembly.h      \
+       assembly.c      \
+       cil-coff.h      \
+       metadata.c      \
+       metadata.h      \
+       rawbuffer.c     \
+       rawbuffer.h
+
+pedump_SOURCES =               \
+       pedump.c $(libmetadata_a_SOURCES)
+
+pedump_LDADD = $(GLIB_LIBS) 
diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c
new file mode 100644 (file)
index 0000000..6d6b260
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * assembly.c: Routines for manipulating and assembly stored in an
+ * extended PE/COFF file.
+ * 
+ * Author:
+ *   Miguel de Icaza (miguel@ximian.com)
+ *
+ * (C) 2001 Ximian, Inc.  http://www.ximian.com
+ *
+ * TODO:
+ *   Do byteswaps for big-endian systems on the various headers.
+ */
+#include <config.h>
+#include <stdio.h>
+#include <glib.h>
+#include <errno.h>
+#include <string.h>
+#include "assembly.h"
+#include "cil-coff.h"
+#include "rawbuffer.h"
+
+#define INVALID_ADDRESS 0xffffffff
+
+/* FIXME: implement big endian versions */
+#define le64_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+#define le16_to_cpu(x) (x)
+#define read32(x) le32_to_cpu (*((guint32 *) (x)))
+#define read16(x) le16_to_cpu (*((guint16 *) (x)))
+#define read64(x) le64_to_cpu (*((guint64 *) (x)))
+
+static guint32
+coff_map (dotnet_image_info_t *iinfo, guint32 addr)
+{
+       const int top = iinfo->dn_section_count;
+       section_table_t *tables = iinfo->dn_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;
+}
+
+static int
+load_section_tables (MonoAssembly *assembly, dotnet_image_info_t *iinfo)
+{
+       const int top = iinfo->dn_header.coff.coff_sections;
+       int i;
+
+       iinfo->dn_section_count = top;
+       iinfo->dn_section_tables = g_new (section_table_t, top);
+
+       for (i = 0; i < top; i++){
+               section_table_t *t = &iinfo->dn_section_tables [i];
+               
+               if (fread (t, sizeof (section_table_t), 1, assembly->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);
+       }
+
+       return TRUE;
+}
+
+static gboolean
+load_cli_header (MonoAssembly *assembly, dotnet_image_info_t *iinfo)
+{
+       guint32 offset;
+       int n;
+       
+       offset = coff_map (iinfo, iinfo->dn_header.datadir.pe_cli_header.rva);
+       if (offset == INVALID_ADDRESS)
+               return FALSE;
+
+       if (fseek (assembly->f, offset, 0) != 0)
+               return FALSE;
+       
+       if ((n = fread (&iinfo->dn_cli_header, sizeof (cli_header_t), 1, assembly->f)) != 1)
+               return FALSE;
+
+       /* Catch new uses of the fields that are supposed to be zero */
+
+       if ((iinfo->dn_cli_header.ch_eeinfo_table.rva != 0) ||
+           (iinfo->dn_cli_header.ch_helper_table.rva != 0) ||
+           (iinfo->dn_cli_header.ch_dynamic_info.rva != 0) ||
+           (iinfo->dn_cli_header.ch_delay_load_info.rva != 0) ||
+           (iinfo->dn_cli_header.ch_module_image.rva != 0) ||
+           (iinfo->dn_cli_header.ch_external_fixups.rva != 0) ||
+           (iinfo->dn_cli_header.ch_ridmap.rva != 0) ||
+           (iinfo->dn_cli_header.ch_debug_map.rva != 0) ||
+           (iinfo->dn_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 (MonoAssembly *assembly, dotnet_image_info_t *iinfo)
+{
+       metadata_t *metadata = &iinfo->dn_metadata;
+       guint32 offset, size;
+       guint16 records;
+       int i;
+       char *ptr;
+       
+       offset = coff_map (iinfo, iinfo->dn_cli_header.ch_metadata.rva);
+       size = iinfo->dn_cli_header.ch_metadata.size;
+       
+       metadata->raw_metadata = raw_buffer_load (fileno (assembly->f), FALSE, offset, size);
+       if (metadata->raw_metadata == NULL)
+               return FALSE;
+
+       ptr = metadata->raw_metadata;
+
+       /*
+        * Handle Beta 1 and ECMA versions of the metadata root
+        */
+       if (strncmp (ptr, "COM+", 4) == 0){
+               ptr += 10;
+       } else if (strncmp (ptr, "BSJB", 4) == 0){
+               guint32 version_string_len;
+
+               ptr += 8;
+               version_string_len = read32 (ptr);
+               ptr += version_string_len;
+               if (((guint32) ptr) % 4)
+                       ptr += 4 - (((guint32) ptr) %4);
+       }
+
+       records = read16 (ptr);
+       ptr += 2;
+
+       for (i = 0; i < records; 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;
+}
+
+static gboolean
+load_tables (MonoAssembly *assembly, metadata_t *meta)
+{
+       char *heap_tables = meta->raw_metadata + meta->heap_tables.sh_offset;
+       guint32 *rows;
+       guint64 valid_mask;
+       int valid = 0, table;
+       
+       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->rows [table] = 0;
+                       continue;
+               }
+               meta->rows [table] = *rows;
+               rows++;
+               valid++;
+       }
+
+       return TRUE;
+}
+
+static gboolean
+load_metadata (MonoAssembly *assembly, dotnet_image_info_t *iinfo)
+{
+       if (!load_metadata_ptrs (assembly, iinfo))
+               return FALSE;
+
+       return load_tables (assembly, &iinfo->dn_metadata);
+}
+
+MonoAssembly *
+mono_assembly_open (const char *fname, enum MonoAssemblyOpenStatus *status)
+{
+       dotnet_image_info_t *iinfo;
+       dotnet_header_t *header;
+       msdos_header_t msdos;
+       MonoAssembly *assembly;
+       int n;
+
+       assembly = g_new (MonoAssembly, 1);
+       assembly->f = fopen (fname, "r");
+       iinfo = g_new (dotnet_image_info_t, 1);
+       assembly->image_info = iinfo;
+
+       header = &iinfo->dn_header;
+               
+       if (assembly->f == NULL){
+               if (status)
+                       *status = MONO_ASSEMBLY_ERROR_ERRNO;
+               mono_assembly_close (assembly);
+               return NULL;
+       }
+
+       if (status)
+               *status = MONO_ASSEMBLY_IMAGE_INVALID;
+       
+       if (fread (&msdos, sizeof (msdos), 1, assembly->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, assembly->f)) != 1)
+               goto invalid_image;
+
+       /*
+        * FIXME: byte swap all addresses here for header.
+        */
+       
+       if (!load_section_tables (assembly, iinfo))
+               goto invalid_image;
+       
+       /* Load the CLI header */
+       if (!load_cli_header (assembly, iinfo))
+               goto invalid_image;
+
+       if (!load_metadata (assembly, iinfo))
+               goto invalid_image;
+       
+       if (status)
+               *status = MONO_ASSEMBLY_OK;
+
+       return assembly;
+
+invalid_image:
+       mono_assembly_close (assembly);
+               return NULL;
+}
+
+void
+mono_assembly_close (MonoAssembly *assembly)
+{
+       g_return_if_fail (assembly != NULL);
+
+       if (assembly->f)
+               fclose (assembly->f);
+
+       if (assembly->image_info){
+               dotnet_image_info_t *ii = assembly->image_info;
+
+               if (ii->dn_metadata.raw_metadata != NULL)
+                       raw_buffer_free (ii->dn_metadata.raw_metadata);
+       
+               if (ii->dn_section_tables)
+                       g_free (ii->dn_section_tables);
+
+               g_free (assembly->image_info);
+       }
+       
+       g_free (assembly);
+}
+
+const char *
+mono_assembly_strerror (enum MonoAssemblyOpenStatus status)
+{
+       switch (status){
+       case MONO_ASSEMBLY_OK:
+               return "succes";
+       case MONO_ASSEMBLY_ERROR_ERRNO:
+               return strerror (errno);
+       case MONO_ASSEMBLY_IMAGE_INVALID:
+               return "File does not contain a valid CIL image";
+       }
+       return "Internal error";
+}
diff --git a/mono/metadata/assembly.h b/mono/metadata/assembly.h
new file mode 100644 (file)
index 0000000..dcec354
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _MONONET_METADATA_ASSEMBLY_H_ 
+#define _MONONET_METADATA_ASSEMBLY_H_
+
+typedef struct {
+       FILE *f;
+       void *image_info;
+} MonoAssembly;
+
+enum MonoAssemblyOpenStatus {
+       MONO_ASSEMBLY_OK,
+       MONO_ASSEMBLY_ERROR_ERRNO,
+       MONO_ASSEMBLY_IMAGE_INVALID
+};
+
+MonoAssembly *mono_assembly_open   (const char *fname, enum MonoAssemblyOpenStatus *status);
+void          mono_assembly_close  (MonoAssembly *assembly);
+
+const char   *mono_assembly_strerror (enum MonoAssemblyOpenStatus status);
+       
+#endif
diff --git a/mono/metadata/cil-coff.h b/mono/metadata/cil-coff.h
new file mode 100644 (file)
index 0000000..ee4f001
--- /dev/null
@@ -0,0 +1,156 @@
+#include <mono/metadata/metadata.h>
+
+/* A metadata token */
+typedef guint32 mtoken_t;
+
+typedef struct {
+       char msdos_header [128];
+} msdos_header_t;
+
+typedef struct {
+       guint16  coff_machine;
+       guint16  coff_sections;
+       guint32  coff_time;
+       guint32  coff_symptr;
+       guint32  coff_symcount;
+       guint16  coff_opt_header_size;
+       guint16  coff_attributes;
+} coff_header_t;
+
+#define COFF_ATTRIBUTE_EXECUTABLE_IMAGE 0x0002
+#define COFF_ATTRIBUTE_LIBRARY_IMAGE    0x2000
+
+typedef struct {
+       guint16 pe_magic;
+       guchar  pe_major;
+       guchar  pe_minor;
+       guint32 pe_code_size;
+       guint32 pe_data_size;
+       guint32 pe_uninit_data_size;
+       guint32 pe_rva_entry_point;
+       guint32 pe_rva_code_base;
+       guint32 pe_rva_data_base;
+} pe_header_t;
+
+typedef struct {
+       guint32 pe_image_base;          /* must be 0x400000 */
+       guint32 pe_section_align;       /* must be 8192 */
+       guint32 pe_file_alignment;      /* must be 512 or 4096 */
+       guint16 pe_os_major;            /* must be 4 */
+       guint16 pe_os_minor;            /* must be 0 */
+       guint16 pe_user_major;
+       guint16 pe_user_minor;
+       guint16 pe_subsys_major;
+       guint16 pe_subsys_minor;
+       guint32 pe_reserved_1;
+       guint32 pe_image_size;
+       guint32 pe_header_size;
+       guint32 pe_checksum;
+       guint16 pe_subsys_required;
+       guint16 pe_dll_flags;
+       guint32 pe_stack_reserve;
+       guint32 pe_stack_commit;
+       guint32 pe_heap_reserve;
+       guint32 pe_heap_commit;
+       guint32 pe_loader_flags;
+       guint32 pe_data_dir_count;
+} pe_header_nt_t;
+
+typedef struct {
+       guint32 rva;
+       guint32 size;
+} pe_dir_entry_t;
+
+typedef struct {
+       pe_dir_entry_t pe_export_table;
+       pe_dir_entry_t pe_import_table;
+       pe_dir_entry_t pe_resource_table;
+       pe_dir_entry_t pe_exception_table;
+       pe_dir_entry_t pe_certificate_table;
+       pe_dir_entry_t pe_reloc_table;
+       pe_dir_entry_t pe_debug;
+       pe_dir_entry_t pe_copyright;
+       pe_dir_entry_t pe_global_ptr;
+       pe_dir_entry_t pe_tls_table;
+       pe_dir_entry_t pe_load_config_table;
+       pe_dir_entry_t pe_bound_import;
+       pe_dir_entry_t pe_iat;
+       pe_dir_entry_t pe_delay_import_desc;
+       pe_dir_entry_t pe_cli_header;
+       pe_dir_entry_t pe_reserved;
+} pe_datadir_t;
+
+typedef struct {
+       char            pesig [4];
+       coff_header_t   coff;
+       pe_header_t     pe;
+       pe_header_nt_t  nt;
+       pe_datadir_t    datadir;
+} dotnet_header_t;
+
+typedef struct {
+       char    st_name [8];
+       guint32 st_virtual_size;
+       guint32 st_virtual_address;
+       guint32 st_raw_data_size;
+       guint32 st_raw_data_ptr;
+       guint32 st_reloc_ptr;
+       guint32 st_lineno_ptr;
+       guint16 st_reloc_count;
+       guint16 st_line_count;
+
+#define SECT_FLAGS_HAS_CODE               0x20
+#define SECT_FLAGS_HAS_INITIALIZED_DATA   0x40
+#define SECT_FLAGS_HAS_UNINITIALIZED_DATA 0x80
+#define SECT_FLAGS_MEM_DISCARDABLE        0x02000000
+#define SECT_FLAGS_MEM_NOT_CACHED         0x04000000
+#define SECT_FLAGS_MEM_NOT_PAGED          0x08000000
+#define SECT_FLAGS_MEM_SHARED             0x10000000
+#define SECT_FLAGS_MEM_EXECUTE            0x20000000
+#define SECT_FLAGS_MEM_READ               0x40000000
+#define SECT_FLAGS_MEM_WRITE              0x80000000
+       guint32 st_flags;
+} section_table_t;
+
+typedef struct {
+       guint32        ch_size;
+       guint16        ch_runtime_major;
+       guint16        ch_runtime_minor;
+       pe_dir_entry_t ch_metadata;
+
+#define CLI_FLAGS_ILONLY         0x01
+#define CLI_FLAGS_32BITREQUIRED  0x02
+#define CLI_FLAGS_TRACKDEBUGDATA 0x00010000
+       guint32        ch_flags;
+
+       mtoken_t       ch_entry_point;
+       pe_dir_entry_t ch_resources;
+       pe_dir_entry_t ch_strong_name;
+       pe_dir_entry_t ch_code_manager_table;
+       pe_dir_entry_t ch_vtable_fixups;
+       pe_dir_entry_t ch_export_address_table_jumps;
+
+       /* The following are zero in the current docs */
+       pe_dir_entry_t ch_eeinfo_table;
+       pe_dir_entry_t ch_helper_table;
+       pe_dir_entry_t ch_dynamic_info;
+       pe_dir_entry_t ch_delay_load_info;
+       pe_dir_entry_t ch_module_image;
+       pe_dir_entry_t ch_external_fixups;
+       pe_dir_entry_t ch_ridmap;
+       pe_dir_entry_t ch_debug_map;
+       pe_dir_entry_t ch_ip_map;
+} cli_header_t;
+
+/* This is not an on-disk structure */
+typedef struct {
+       dotnet_header_t   dn_header;
+       int               dn_section_count;
+       section_table_t  *dn_section_tables;
+       cli_header_t      dn_cli_header;
+
+       metadata_t        dn_metadata;
+} dotnet_image_info_t;
+
+
+
diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c
new file mode 100644 (file)
index 0000000..02db6e5
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * metadata.c: Routines for accessing the metadata
+ *
+ * Author:
+ *   Miguel de Icaza (miguel@ximian.com)
+ *
+ * (C) 2001 Ximian, Inc.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include "metadata.h"
+
diff --git a/mono/metadata/metadata.h b/mono/metadata/metadata.h
new file mode 100644 (file)
index 0000000..6e34877
--- /dev/null
@@ -0,0 +1,18 @@
+
+typedef struct {
+       guint32 sh_offset;
+       guint32 sh_size;
+} stream_header_t;
+
+typedef struct {
+       char             *raw_metadata;
+
+       stream_header_t   heap_strings;
+       stream_header_t   heap_us;
+       stream_header_t   heap_blob;
+       stream_header_t   heap_guid;
+       stream_header_t   heap_tables;
+
+       guint32           rows [64];
+} metadata_t;
+
diff --git a/mono/metadata/pedump.c b/mono/metadata/pedump.c
new file mode 100644 (file)
index 0000000..7a716cf
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * pedump.c: Dumps the contents of an extended PE/COFF file
+ *
+ * Author:
+ *   Miguel de Icaza (miguel@ximian.com)
+ *
+ * (C) 2001 Ximian, Inc.
+ */
+#include <config.h>
+#include <stdio.h>
+#include "assembly.h"
+#include <glib.h>
+#include "cil-coff.h"
+
+static void
+hex_dump (char *buffer, int base, int count)
+{
+       int i;
+       
+       for (i = 0; i < count; i++){
+               if ((i % 16) == 0)
+                       printf ("\n0x%08x: ", (unsigned char) base + i);
+
+               printf ("%02x ", (unsigned char) (buffer [i]));
+       }
+}
+
+static void
+hex8 (char *label, unsigned char x)
+{
+       printf ("\t%s: 0x%02x\n", label, (unsigned char) x);
+}
+
+static void
+hex16 (char *label, guint16 x)
+{
+       printf ("\t%s: 0x%04x\n", label, x);
+}
+
+static void
+hex32 (char *label, guint32 x)
+{
+       printf ("\t%s: 0x%08x\n", label, x);
+}
+
+static void
+dump_coff_header (coff_header_t *coff)
+{
+       printf ("\nCOFF Header:\n");
+       hex16 ("                Machine", coff->coff_machine);
+       hex16 ("               Sections", coff->coff_sections);
+       hex32 ("             Time stamp", coff->coff_time);
+       hex32 ("Pointer to Symbol Table", coff->coff_symptr);
+       hex32 ("           Symbol Count", coff->coff_symcount);
+       hex16 ("   Optional Header Size", coff->coff_opt_header_size);
+       hex16 ("        Characteristics", coff->coff_attributes);
+
+}
+
+static void
+dump_pe_header (pe_header_t *pe)
+{
+       printf ("\nPE Header:\n");
+       hex16 ("         Magic (0x010b)", pe->pe_magic);
+       hex8  ("             LMajor (6)", pe->pe_major);
+       hex8  ("             LMinor (0)", pe->pe_minor);
+       hex32 ("              Code Size", pe->pe_code_size);
+       hex32 ("  Initialized Data Size", pe->pe_data_size);
+       hex32 ("Uninitialized Data Size", pe->pe_uninit_data_size);
+       hex32 ("        Entry Point RVA", pe->pe_rva_entry_point);
+       hex32 ("          Code Base RVA", pe->pe_rva_code_base);
+       hex32 ("          Data Base RVA", pe->pe_rva_data_base);
+       printf ("\n");
+}
+
+static void
+dump_nt_header (pe_header_nt_t *nt)
+{
+       printf ("\nNT Header:\n");
+
+       hex32 ("   Image Base (0x400000)", nt->pe_image_base);
+       hex32 ("Section Alignment (8192)", nt->pe_section_align);
+       hex32 ("   File Align (512/4096)", nt->pe_file_alignment);
+       hex16 ("            OS Major (4)", nt->pe_os_major);
+       hex16 ("            OS Minor (0)", nt->pe_os_minor);
+       hex16 ("          User Major (0)", nt->pe_user_major);
+       hex16 ("          User Minor (0)", nt->pe_user_minor);
+       hex16 ("        Subsys major (4)", nt->pe_subsys_major);
+       hex16 ("        Subsys minor (0)", nt->pe_subsys_minor);
+       hex32 ("               Reserverd", nt->pe_reserved_1);
+       hex32 ("              Image Size", nt->pe_image_size);
+       hex32 ("             Header Size", nt->pe_header_size);
+       hex32 ("            Checksum (0)", nt->pe_checksum);
+       hex16 ("               Subsystem", nt->pe_subsys_required);
+       hex16 ("           DLL Flags (0)", nt->pe_dll_flags);
+       hex32 (" Stack Reserve Size (1M)", nt->pe_stack_reserve);
+       hex32 ("Stack commit Size (4096)", nt->pe_stack_commit);
+       hex32 ("  Heap Reserve Size (1M)", nt->pe_heap_reserve);
+       hex32 (" Heap Commit Size (4096)", nt->pe_heap_commit);
+       hex32 ("      Loader flags (0x1)", nt->pe_loader_flags);
+       hex32 ("   Data Directories (16)", nt->pe_data_dir_count);
+}
+
+static void
+dent (const char *label, pe_dir_entry_t de)
+{
+       printf ("\t%s: 0x%08x [0x%08x]\n", label, de.rva, de.size);
+}
+
+static void
+dump_datadir (pe_datadir_t *dd)
+{
+       printf ("\nData directories:\n");
+       dent ("     Export Table", dd->pe_export_table);
+       dent ("     Import Table", dd->pe_import_table);
+       dent ("   Resource Table", dd->pe_resource_table);
+       dent ("  Exception Table", dd->pe_exception_table);
+       dent ("Certificate Table", dd->pe_certificate_table);
+       dent ("      Reloc Table", dd->pe_reloc_table);
+       dent ("            Debug", dd->pe_debug);
+       dent ("        Copyright", dd->pe_copyright);
+       dent ("       Global Ptr", dd->pe_global_ptr);
+       dent ("        TLS Table", dd->pe_tls_table);
+       dent ("Load Config Table", dd->pe_load_config_table);
+       dent ("     Bound Import", dd->pe_bound_import);
+       dent ("              IAT", dd->pe_iat);
+       dent ("Delay Import Desc", dd->pe_delay_import_desc);
+       dent ("       CLI Header", dd->pe_cli_header);
+}
+
+static void
+dump_dotnet_header (dotnet_header_t *header)
+{
+       dump_coff_header (&header->coff);
+       dump_pe_header (&header->pe);
+       dump_nt_header (&header->nt);
+       dump_datadir (&header->datadir);
+}
+
+static void
+dump_section_table (section_table_t *st)
+{
+       guint32 flags = st->st_flags;
+               
+       printf ("\n\tName: %s\n", st->st_name);
+       hex32 ("   Virtual Size", st->st_virtual_size);
+       hex32 ("Virtual Address", st->st_virtual_address);
+       hex32 ("  Raw Data Size", st->st_raw_data_size);
+       hex32 ("   Raw Data Ptr", st->st_raw_data_ptr);
+       hex32 ("      Reloc Ptr", st->st_reloc_ptr);
+       hex32 ("     LineNo Ptr", st->st_lineno_ptr);
+       hex16 ("    Reloc Count", st->st_reloc_count);
+       hex16 ("     Line Count", st->st_line_count);
+
+       printf ("\tFlags: %s%s%s%s%s%s%s%s%s%s\n",
+               (flags & SECT_FLAGS_HAS_CODE) ? "code, " : "",
+               (flags & SECT_FLAGS_HAS_INITIALIZED_DATA) ? "data, " : "",
+               (flags & SECT_FLAGS_HAS_UNINITIALIZED_DATA) ? "bss, " : "",
+               (flags & SECT_FLAGS_MEM_DISCARDABLE) ? "discard, " : "",
+               (flags & SECT_FLAGS_MEM_NOT_CACHED) ? "nocache, " : "",
+               (flags & SECT_FLAGS_MEM_NOT_PAGED) ? "nopage, " : "",
+               (flags & SECT_FLAGS_MEM_SHARED) ? "shared, " : "",
+               (flags & SECT_FLAGS_MEM_EXECUTE) ? "exec, " : "",
+               (flags & SECT_FLAGS_MEM_READ) ? "read, " : "",
+               (flags & SECT_FLAGS_MEM_WRITE) ? "write" : "");
+}
+
+static void
+dump_sections (dotnet_image_info_t *iinfo)
+{
+       const int top = iinfo->dn_header.coff.coff_sections;
+       int i;
+       
+       for (i = 0; i < top; i++)
+               dump_section_table (&iinfo->dn_section_tables [i]);
+}
+
+static void
+dump_cli_header (cli_header_t *ch)
+{
+       printf ("\n");
+       printf ("          CLI header size: %d\n", ch->ch_size);
+       printf ("         Runtime required: %d.%d\n", ch->ch_runtime_major, ch->ch_runtime_minor);
+       printf ("                    Flags: %s, %s, %s\n",
+               (ch->ch_flags & CLI_FLAGS_ILONLY ? "ilonly" : "contains native"),
+               (ch->ch_flags & CLI_FLAGS_32BITREQUIRED ? "32bits" : "32/64"),
+               (ch->ch_flags & CLI_FLAGS_ILONLY ? "trackdebug" : "no-trackdebug"));
+       dent   ("         Metadata", ch->ch_metadata);
+       hex32  ("Entry Point Token", ch->ch_entry_point);
+       dent   ("     Resources at", ch->ch_resources);
+       dent   ("   Strong Name at", ch->ch_strong_name);
+       dent   ("  Code Manager at", ch->ch_code_manager_table);
+       dent   ("  VTableFixups at", ch->ch_vtable_fixups);
+       dent   ("     EAT jumps at", ch->ch_export_address_table_jumps);
+}      
+
+static void
+dsh (char *label, dotnet_image_info_t *iinfo, stream_header_t *sh)
+{
+       printf ("%s: 0x%08x - 0x%08x [%d == 0x%08x]\n",
+               label,
+               sh->sh_offset, sh->sh_offset + sh->sh_size,
+               sh->sh_size, sh->sh_size);
+}
+
+static void
+dump_metadata_ptrs (dotnet_image_info_t *iinfo)
+{
+       metadata_t *meta = &iinfo->dn_metadata;
+       
+       printf ("\nMetadata pointers:\n");
+       dsh ("\tTables (#~)", iinfo, &meta->heap_tables);
+       dsh ("\t    Strings", iinfo, &meta->heap_strings);
+       dsh ("\t       Blob", iinfo, &meta->heap_blob);
+       dsh ("\tUser string", iinfo, &meta->heap_us);
+       dsh ("\t       GUID", iinfo, &meta->heap_guid);
+}
+
+static const char *
+table_to_string (int table)
+{
+       char *map_table_to_string [] = {
+               /* 0 */  "Module",       "TypeRef",       "TypeDef",     "FieldPtr",
+               /* 4 */  "FieldDef",     "MethodPtr",     "MethodDef",   "ParamPtr",
+               /* 8 */  "ParamDef",     "InterfaceImpl", "MemberRef",   "FieldInit",
+               /* 12 */ "CustomAttr",   "MarshalDef",    "Permission",  "LayoutDef",
+               /* 16 */ "FieldOffset",  "Signature",     "EventAssoc",  "EventPtr",
+               /* 20 */ "Event",        "PropertyAssoc", "PropertyPtr", "Property",
+               /* 24 */ "MethodAssoc",  "MethodImpl",    "ModuleRef",   "TypeSpec",
+               /* 28 */ "PInvoke",      "Data",          "EncLog",      "EncAssoc",
+               /* 32 */ "Assembly",     "ProcessorDef",  "OSDef",       "AssemblyRef",
+               /* 36 */ "ProcessorRef", "OSRef",         "File",        "ComType",
+               /* 40 */ "ManifestResource", "ExeLocation", "42",        "43",
+               /* 44 */ "44",           "45",            "NestedClass", "47"
+               /* 48 */ "48",           "49",            "50",          "51",
+               /* 52 */ "52",           "53",            "54",          "55"
+               /* 56 */ "56",           "57",            "58",          "59"
+               /* 60 */ "60",           "61",            "62",          "63"
+       };
+       
+       if (table < 0 || table > 63)
+               return "Unknown table name";
+       
+       return map_table_to_string [table];
+}
+
+static void
+dump_metadata (dotnet_image_info_t *iinfo)
+{
+       metadata_t *meta = &iinfo->dn_metadata;
+       int table;
+       
+       dump_metadata_ptrs (iinfo);
+
+       printf ("Rows:\n");
+       for (table = 0; table < 64; table++){
+               if (meta->rows [table] == 0)
+                       continue;
+               printf ("Table %s (%d): %d rows\n", table_to_string (table), table, meta->rows [table]);
+       }
+}
+
+static void
+dump_dotnet_iinfo (dotnet_image_info_t *iinfo)
+{
+       dump_dotnet_header (&iinfo->dn_header);
+       dump_sections (iinfo);
+       dump_cli_header (&iinfo->dn_cli_header);
+       dump_metadata (iinfo);
+}
+
+static void
+usage (void)
+{
+       printf ("Usage is: pedump [-m] file.exe\n");
+       exit (1);
+}
+
+int
+main (int argc, char *argv [])
+{
+       dotnet_image_info_t *iinfo;
+       MonoAssembly *assembly;
+       char *file = NULL;
+       int i;
+       
+       for (i = 1; i < argc; i++){
+               if (argv [i][0] != '-'){
+                       file = argv [1];
+                       continue;
+               }
+
+               if (argv [i][1] == 'h')
+                       usage ();
+       }
+       
+       if (!file)
+               usage ();
+
+       assembly = mono_assembly_open (file, NULL);
+       iinfo = assembly->image_info;
+
+       dump_dotnet_iinfo (iinfo);
+
+       mono_assembly_close (assembly);
+       
+       return 0;
+}
+
diff --git a/mono/metadata/rawbuffer.c b/mono/metadata/rawbuffer.c
new file mode 100644 (file)
index 0000000..a72705a
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * rawbuffer.c: Manages buffers that might have been mmapped or malloced
+ *
+ * Author:
+ *   Miguel de Icaza (miguel@ximian.com)
+ *
+ * (C) 2001 Ximian, Inc.
+ */
+#include <config.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <glib.h>
+#include "rawbuffer.h"
+
+#define PAGESIZE 8192
+
+GHashTable *malloc_map;
+
+void *
+raw_buffer_load (int fd, int is_writable, guint32 base, size_t size)
+{
+       size_t start, end;
+       int prot = PROT_READ;
+       int flags = 0;
+       void *ptr, *mmap_ptr;
+       
+       if (is_writable){
+               prot |= PROT_WRITE;
+       }
+       flags = MAP_PRIVATE;
+
+       start = base & ~(PAGESIZE - 1);
+       end = (base + size + PAGESIZE - 1) & ~(PAGESIZE - 1);
+       
+       mmap_ptr = mmap (0, end - start, prot, flags, fd, start);
+       if (mmap_ptr == (void *) -1){
+               ptr = g_malloc (size);
+               if (ptr == NULL)
+                       return NULL;
+               if (lseek (fd, base, 0) == (off_t) -1)
+                       return NULL;
+               read (fd, ptr, size);
+               return ptr;
+       }
+       if (malloc_map == NULL)
+               malloc_map = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+       g_hash_table_insert (malloc_map, mmap_ptr, GINT_TO_POINTER (size));
+
+       return ((char *)mmap_ptr) + (base - start);
+}
+
+void
+raw_buffer_free (void *buffer)
+{
+       int size, diff;
+       char *base;
+       
+       if (!malloc_map){
+               g_free (buffer);
+               return;
+       }
+
+       diff = ((unsigned int) buffer) & (PAGESIZE - 1);
+       base = ((char *)buffer) - diff;
+       
+       size = GPOINTER_TO_INT (g_hash_table_lookup (malloc_map, base));
+       munmap (base, size);
+}
diff --git a/mono/metadata/rawbuffer.h b/mono/metadata/rawbuffer.h
new file mode 100644 (file)
index 0000000..4091fc4
--- /dev/null
@@ -0,0 +1,3 @@
+
+void *raw_buffer_load (int fd, int writable, guint32 base, size_t size);
+void raw_buffer_free  (void *buffer);