Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@gnome.org>2001-06-19 07:37:46 +0400
committerMiguel de Icaza <miguel@gnome.org>2001-06-19 07:37:46 +0400
commit0fae05ddc83ee034344d50a6d4d618cfb10ee491 (patch)
treee940f3430e38c4b03cbc5f0755a6f437cfb4480f
parent0273a2dd786ade874dfc4684646a8dcab74090f7 (diff)
Initial revision
svn path=/trunk/mono/; revision=9
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog4
-rw-r--r--Makefile.am1
-rw-r--r--NEWS3
-rw-r--r--README3
-rw-r--r--config.h.in11
-rw-r--r--configure.in34
-rw-r--r--mono/Makefile.am1
-rw-r--r--mono/dis/Makefile.am10
-rw-r--r--mono/dis/main.c77
-rw-r--r--mono/metadata/Makefile.am19
-rw-r--r--mono/metadata/assembly.c303
-rw-r--r--mono/metadata/assembly.h20
-rw-r--r--mono/metadata/cil-coff.h156
-rw-r--r--mono/metadata/metadata.c13
-rw-r--r--mono/metadata/metadata.h18
-rw-r--r--mono/metadata/pedump.c309
-rw-r--r--mono/metadata/rawbuffer.c70
-rw-r--r--mono/metadata/rawbuffer.h3
19 files changed, 1056 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 00000000000..25e66d4943c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Miguel de Icaza (miguel@ximian.com)
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 00000000000..1a76f446632
--- /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
index 00000000000..7a0d4a47da8
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = mono
diff --git a/NEWS b/NEWS
new file mode 100644
index 00000000000..37b3c8595b0
--- /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
index 00000000000..27f2ef4c497
--- /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
index 00000000000..f871c4edf55
--- /dev/null
+++ b/config.h.in
@@ -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
index 00000000000..b146447d4d7
--- /dev/null
+++ b/configure.in
@@ -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
index 00000000000..89d68d86d83
--- /dev/null
+++ b/mono/Makefile.am
@@ -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
index 00000000000..fdb8662c28c
--- /dev/null
+++ b/mono/dis/Makefile.am
@@ -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
index 00000000000..49f9027c1e2
--- /dev/null
+++ b/mono/dis/main.c
@@ -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
index 00000000000..505141d5abc
--- /dev/null
+++ b/mono/metadata/Makefile.am
@@ -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
index 00000000000..6d6b2602d7f
--- /dev/null
+++ b/mono/metadata/assembly.c
@@ -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
index 00000000000..dcec354f007
--- /dev/null
+++ b/mono/metadata/assembly.h
@@ -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
index 00000000000..ee4f001e2b0
--- /dev/null
+++ b/mono/metadata/cil-coff.h
@@ -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
index 00000000000..02db6e5c04b
--- /dev/null
+++ b/mono/metadata/metadata.c
@@ -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
index 00000000000..6e34877013f
--- /dev/null
+++ b/mono/metadata/metadata.h
@@ -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
index 00000000000..7a716cf3ea7
--- /dev/null
+++ b/mono/metadata/pedump.c
@@ -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
index 00000000000..a72705af35e
--- /dev/null
+++ b/mono/metadata/rawbuffer.c
@@ -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
index 00000000000..4091fc434c2
--- /dev/null
+++ b/mono/metadata/rawbuffer.h
@@ -0,0 +1,3 @@
+
+void *raw_buffer_load (int fd, int writable, guint32 base, size_t size);
+void raw_buffer_free (void *buffer);