diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | config.h.in | 11 | ||||
-rw-r--r-- | configure.in | 34 | ||||
-rw-r--r-- | mono/Makefile.am | 1 | ||||
-rw-r--r-- | mono/dis/Makefile.am | 10 | ||||
-rw-r--r-- | mono/dis/main.c | 77 | ||||
-rw-r--r-- | mono/metadata/Makefile.am | 19 | ||||
-rw-r--r-- | mono/metadata/assembly.c | 303 | ||||
-rw-r--r-- | mono/metadata/assembly.h | 20 | ||||
-rw-r--r-- | mono/metadata/cil-coff.h | 156 | ||||
-rw-r--r-- | mono/metadata/metadata.c | 13 | ||||
-rw-r--r-- | mono/metadata/metadata.h | 18 | ||||
-rw-r--r-- | mono/metadata/pedump.c | 309 | ||||
-rw-r--r-- | mono/metadata/rawbuffer.c | 70 | ||||
-rw-r--r-- | mono/metadata/rawbuffer.h | 3 |
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 @@ -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); |