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