diff options
author | Miguel de Icaza <miguel@gnome.org> | 2001-07-02 08:19:12 +0400 |
---|---|---|
committer | Miguel de Icaza <miguel@gnome.org> | 2001-07-02 08:19:12 +0400 |
commit | 3c8a3d1b0698f57ba31ff2b74473f1a619a93382 (patch) | |
tree | f933481a93f6417df486e8b7cd63a39aa0c3252d | |
parent | e04016adacbb074a8492c5e807a62dbaa91cf0f2 (diff) |
Implement code disassembler.
svn path=/trunk/mono/; revision=45
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | mono/cil/.cvsignore | 3 | ||||
-rw-r--r-- | mono/dis/.cvsignore | 1 | ||||
-rw-r--r-- | mono/dis/ChangeLog | 4 | ||||
-rw-r--r-- | mono/dis/Makefile.am | 3 | ||||
-rw-r--r-- | mono/dis/dis-cil.c | 211 | ||||
-rw-r--r-- | mono/dis/dis-cil.h | 1 | ||||
-rw-r--r-- | mono/dis/main.c | 16 | ||||
-rw-r--r-- | mono/dis/push-pop.h | 265 | ||||
-rw-r--r-- | mono/metadata/ChangeLog | 5 | ||||
-rw-r--r-- | mono/metadata/TODO | 5 | ||||
-rw-r--r-- | mono/metadata/metadata.c | 8 | ||||
-rw-r--r-- | mono/metadata/metadata.h | 1 | ||||
-rw-r--r-- | notes/cil | 6 |
14 files changed, 523 insertions, 7 deletions
diff --git a/configure.in b/configure.in index c0bde9b200b..865f09b2d2c 100644 --- a/configure.in +++ b/configure.in @@ -31,4 +31,5 @@ Makefile mono/Makefile mono/metadata/Makefile mono/dis/Makefile +mono/cil/Makefile ])
\ No newline at end of file diff --git a/mono/cil/.cvsignore b/mono/cil/.cvsignore new file mode 100644 index 00000000000..10dae49ad16 --- /dev/null +++ b/mono/cil/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in +opcode.def diff --git a/mono/dis/.cvsignore b/mono/dis/.cvsignore index e9407c9414e..8521f30085c 100644 --- a/mono/dis/.cvsignore +++ b/mono/dis/.cvsignore @@ -2,3 +2,4 @@ Makefile Makefile.in .libs .deps +monodirs diff --git a/mono/dis/ChangeLog b/mono/dis/ChangeLog index 15b16ceab79..b2af66214ed 100644 --- a/mono/dis/ChangeLog +++ b/mono/dis/ChangeLog @@ -1,3 +1,7 @@ +2001-07-01 Miguel de Icaza <miguel@ximian.com> + + * dis-cil.c: New file. CIL opcode dissasembler. + 2001-06-27 Miguel de Icaza <miguel@ximian.com> * main.c: Split code. diff --git a/mono/dis/Makefile.am b/mono/dis/Makefile.am index 01ed731d940..9cb1baad6ad 100644 --- a/mono/dis/Makefile.am +++ b/mono/dis/Makefile.am @@ -5,7 +5,8 @@ bin_PROGRAMS = monodis monodis_SOURCES = \ get.c \ get.h \ - dis.h \ + dis-cil.c \ + dis-cil.h \ dump.c \ dump.h \ main.c \ diff --git a/mono/dis/dis-cil.c b/mono/dis/dis-cil.c new file mode 100644 index 00000000000..eede4e7300b --- /dev/null +++ b/mono/dis/dis-cil.c @@ -0,0 +1,211 @@ +/* + * dis-cil.c: Disassembles CIL byte codes + * + * Author: + * Miguel de Icaza (miguel@ximian.com) + * + * (C) 2001 Ximian, Inc. + */ +#include <config.h> +#include <glib.h> +#include <stdio.h> +#include <wchar.h> +#include "meta.h" +#include "dump.h" +#include "dis-cil.h" + +enum { + InlineBrTarget, + InlineField, + InlineI, + InlineI8, + InlineMethod, + InlineNone, + InlineR, + InlineSig, + InlineString, + InlineSwitch, + InlineTok, + InlineType, + InlineVar, + ShortInlineBrTarget, + ShortInlineI, + ShortInlineR, + ShortInlineVar +}; + +#define OPDEF(a,b,c,d,e,f,g,h,i,j) \ + { b, e, g, h, i }, + +typedef struct { + char *name; + int argument; + + /* + * we are not really using any of the following: + */ + int bytes; + unsigned char o1, o2; +} opcode_t; + +static opcode_t opcodes [300] = { +#include "mono/cil/opcode.def" +}; + +void +dissasemble_cil (metadata_t *m, const unsigned char *start, int size) +{ + const unsigned char *end = start + size; + const unsigned char *ptr = start; + opcode_t *entry; + + while (ptr < end){ + if (*ptr == 0xfe){ + ptr++; + entry = &opcodes [*ptr + 256]; + } else + entry = &opcodes [*ptr]; + + fprintf (output, "\tIL_%04x: %s ", (int) (ptr - start), entry->name); + ptr++; + switch (entry->argument){ + case InlineBrTarget: { + gint target = *(gint32 *) ptr; + fprintf (output, "IL_%04x", ((int) (ptr - start)) + 4 + target); + ptr += 4; + break; + } + + case InlineField: { + guint32 token = *(guint32 *) ptr; + fprintf (output, "fieldref-0x%08x", token); + ptr += 4; + break; + } + + case InlineI: { + int value = *(int *) ptr; + + fprintf (output, "%d", value); + ptr += 4; + break; + } + + case InlineI8: { + gint64 top = *(guint64 *) ptr; + + fprintf (output, "%lld", (long long) top); + ptr += 8; + break; + } + + case InlineMethod: { + guint32 token = *(guint32 *) ptr; + fprintf (output, "method-0x%08x", token); + ptr += 4; + break; + } + + case InlineNone: + break; + + case InlineR: { + double r = *(double *) ptr; + fprintf (output, "%g", r); + ptr += 8; + break; + } + + case InlineSig: { + guint32 token = *(guint32 *) ptr; + fprintf (output, "signature-0x%08x", token); + ptr += 4; + break; + } + + case InlineString: { + guint32 token = *(guint32 *) ptr; + + /* + * See section 23.1.4 on the encoding of the #US heap + */ + fprintf (output, "string-0x%08x", token); + ptr += 4; + break; + } + + case InlineSwitch: { + guint32 count = *(guint32 *) ptr; + guint32 i; + + ptr += 4; + fprintf (output, "(\n\t\t\t"); + for (i = 0; i < count; i++){ + fprintf (output, "IL_%x", *(guint32 *) ptr); + ptr += 4; + } + fprintf (output, "\t\t\t)"); + break; + } + + case InlineTok: { + guint32 token = *(guint32 *) ptr; + + fprintf (output, "TOKEN_%08x", token); + ptr += 4; + break; + } + + case InlineType: { + guint32 token = *(guint32 *) ptr; + + fprintf (output, "Type-%08x", token); + ptr += 4; + break; + } + + case InlineVar: { + gint16 var_idx = *(gint16 *) ptr; + + fprintf (output, "variable-%d\n", var_idx); + ptr += 2; + break; + } + + case ShortInlineBrTarget: { + signed char x = *ptr; + + fprintf (output, "IL_%04x", ptr - start + 1 + x); + ptr++; + break; + } + + case ShortInlineI: { + char x = *ptr; + + fprintf (output, "0x%02x", x); + ptr++; + break; + } + + case ShortInlineR: { + float f = *(float *) ptr; + + fprintf (output, "%g", (double) f); + ptr += 4; + break; + } + + case ShortInlineVar: { + signed char x = *ptr; + + fprintf (output, "Varidx-%d", (int) x); + ptr++; + break; + } + + } + + fprintf (output, "\n"); + } +} diff --git a/mono/dis/dis-cil.h b/mono/dis/dis-cil.h new file mode 100644 index 00000000000..7874d4e7ff1 --- /dev/null +++ b/mono/dis/dis-cil.h @@ -0,0 +1 @@ +void dissasemble_cil (metadata_t *m, const unsigned char *ptr, int size); diff --git a/mono/dis/main.c b/mono/dis/main.c index b18cf3a0b87..09126a1d0f1 100644 --- a/mono/dis/main.c +++ b/mono/dis/main.c @@ -1,5 +1,5 @@ /* - * dis.c: Sample disassembler + * main.c: Sample disassembler * * Author: * Miguel de Icaza (miguel@ximian.com) @@ -290,11 +290,15 @@ dis_code (metadata_t *m, cli_image_info_t *ii, guint32 rva) mh = mono_metadata_parse_mh (ptr); fprintf (output, "\t.maxstack %d\n", mh->max_stack); fprintf (output, "\t// Code size=%d (0x%x)\n", mh->code_size, mh->code_size); - printf ("Values Code Size=%d/0x%x\nMaxStack=%d\nLocalTok=%x", - mh->code_size, mh->code_size, mh->max_stack, mh->local_var_sig_tok); - hex_dump (mh->code, 0, mh->code_size); - printf ("\nAfter the code\n"); - hex_dump (mh->code + mh->code_size, 0, 64); + printf ("\t// Values Code Size=%d/0x%x\n\t// LocalTok=%x\n\n", + mh->code_size, mh->code_size, mh->local_var_sig_tok); + dissasemble_cil (m, mh->code, mh->code_size); + +/* + hex_dump (mh->code, 0, mh->code_size); + printf ("\nAfter the code\n"); + hex_dump (mh->code + mh->code_size, 0, 64); +*/ mono_metadata_free_mh (mh); } diff --git a/mono/dis/push-pop.h b/mono/dis/push-pop.h new file mode 100644 index 00000000000..f74252e4327 --- /dev/null +++ b/mono/dis/push-pop.h @@ -0,0 +1,265 @@ +/* Poping */ +/* 1 bit */ +#define Pop0 1 +/* 2 bits */ +#define Pop1 2 +/* 3 bits */ +#define PopI 8 +/* 1 bit */ +#define PopI8 64 +/* 1 bit */ +#define Pop8 128 +/* 1 bit */ +#define PopR4 256 +/* 1 bit */ +#define PopR8 512 +/* 1 bit */ +#define PopRef 1024 +/* 1 bit */ +#define VarPop 2048 + +/* Pushing */ +#define Push0 1 +#define PushI 2 +#define PushI8 4 +#define PushR4 8 +#define PushR8 16 +#define PushRef 32 +#define VarPush 64 +#define Push1 128 + +/* + * dis-cil.c: Disassembles CIL byte codes + * + * Author: + * Miguel de Icaza (miguel@ximian.com) + * + * (C) 2001 Ximian, Inc. + */ +#include <config.h> +#include <glib.h> +#include <stdio.h> +#include "meta.h" +#include "dump.h" +#include "dis-cil.h" + +/* Poping */ +/* 1 bit */ +#define Pop0 1 +/* 2 bits */ +#define Pop1 2 +/* 3 bits */ +#define PopI 8 +/* 1 bit */ +#define PopI8 64 +/* 1 bit */ +#define Pop8 128 +/* 1 bit */ +#define PopR4 256 +/* 1 bit */ +#define PopR8 512 +/* 1 bit */ +#define PopRef 1024 +/* 1 bit */ +#define VarPop 2048 + +/* Pushing */ +#define Push0 1 +#define PushI 2 +#define PushI8 4 +#define PushR4 8 +#define PushR8 16 +#define PushRef 32 +#define VarPush 64 +#define Push1 128 + +enum { + InlineBrTarget, + InlineField, + InlineI, + InlineI8, + InlineMethod, + InlineNone, + InlineR, + InlineSig, + InlineString, + InlineSwitch, + InlineTok, + InlineType, + InlineVar, + ShortInlineBrTarget, + ShortInlineI, + ShortInlineR, + ShortInlineVar +}; + +#define OPDEF(a,b,c,d,e,f,g,h,i,j) \ + { b, c, d, e, g, h, i }, + +typedef struct { + char *name; + int pop, push; + int argument; + int bytes; + unsigned char o1, o2; +} opcode_t; + +static opcode_t opcodes [300] = { +#include "mono/cil/opcode.def" +}; + +void +dissasemble_cil (metadata_t *m, const unsigned char *start, int size) +{ + const unsigned char *end = start + size; + const unsigned char *ptr = start; + opcode_t *entry; + + while (ptr < end){ + if (*ptr == 0xfe){ + ptr++; + entry = &opcodes [*ptr + 256]; + } else + entry = &opcodes [*ptr]; + + ptr++; + + fprintf (output, "\tIL_%04x: %s ", ptr - start, entry->name); + switch (entry->argument){ + case InlineBrTarget: { + gint target = *(gint32 *) ptr; + fprintf (output, "IL_%04x", ptr + 4 + target); + ptr += 4; + break; + } + + case InlineField: { + token = *(guint32 *) ptr; + fprintf (output, "fieldref-0x%08x", token); + ptr += 4; + break; + } + + case InlineI: { + int value = *(int *) ptr; + + fprintf (output, "%d", value); + ptr += 4; + break; + } + + case InlineI8: { + gint64 top = *(guint64 *) value; + + fprintf (output, "%ld", top); + ptr += 8; + break; + } + + case InlineMethod: { + token = *(guint32 *) ptr; + fprintf (output, "method-0x%08x", token); + ptr += 4; + break; + } + + case InlineNone: + break; + + case InlineR: { + double r = *(double *) ptr; + fprintf (output, "%g", r); + ptr += 8; + break; + } + + case InlineSig: { + guint32 token = *(guint32 *) ptr; + fprintf (output, "signature-0x%08x", token); + ptr += 4; + break; + } + + case InlineString: { + guint32 token = *(guint32 *) ptr; + + fprintf (output, "string-%0x08x", token); + ptr += 4; + break; + } + + case InlineSwitch: { + guint32 count = *(guint32 *) ptr; + guint32 i; + + ptr += 4; + fprintf (output, "(\n\t\t\t"); + for (i = 0; i < count; i++){ + fprintf (output, "IL_%x", *(guint32 *) ptr); + ptr += 4; + } + fprintf (output, "\t\t\t)"); + break; + } + + case InlineTok: { + guint32 token = *(guint32 *) ptr; + + fprintf (output, "TOKEN_%08x", token); + ptr += 4; + break; + } + + case InlineType: { + guint32 token = *(guint32 *) ptr; + + fprintf (output, "Type-%08x", token); + ptr += 4; + break; + } + + case InlineVar: { + gint16 var_idx = *(gint16 *) ptr; + + fprintf (output, "variable-%d\n", var_idx); + ptr += 2; + break; + } + + case ShortInlineBrTarget: { + signed char x = *ptr; + + fprintf (output, "IL_%04x", ptr - start + 1 + x); + ptr++: + break; + } + + case ShortInlineI: { + char x = *ptr; + + fprintf (output, "0x%02x", x); + ptr++; + break; + } + + case ShortInlineR: { + float f = *(float *) ptr; + + fprintf (output, "%g", (double) f); + ptr += 4; + break; + } + + case ShortInlineVar: { + signed char x = *ptr; + + fprintf (output, "Varidx-%d", (int) x); + ptr++; + break; + }m + + } + + fprintf (output, "\n"); + } +} diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index ec8657a4d9e..2a339d6c8c1 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,8 @@ +2001-07-01 Miguel de Icaza <miguel@ximian.com> + + * metadata.c (mono_metadata_user_string): New function, provides + access to the UserString heap. + 2001-06-27 Miguel de Icaza <miguel@ximian.com> * metadata.c: Add inline documentation. diff --git a/mono/metadata/TODO b/mono/metadata/TODO new file mode 100644 index 00000000000..7c7da2c7aef --- /dev/null +++ b/mono/metadata/TODO @@ -0,0 +1,5 @@ + +* Rename assembly.c to module.c + + * Rename all symbols called `assembly' to module, because that is + what they actually are.
\ No newline at end of file diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index cfaba846190..ea3a9727493 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -643,6 +643,12 @@ mono_metadata_string_heap (metadata_t *meta, guint32 index) return meta->raw_metadata + meta->heap_strings.sh_offset + index; } +const char * +mono_metadata_user_string (metadata_t *meta, guint32 index) +{ + return meta->raw_metadata + meta->heap_us.sh_offset + index; +} + /** * mono_metadata_blob_heap: * @meta: metadata context @@ -699,6 +705,7 @@ parse_exception_handler (const char *ptr, gboolean is_fat) static void parse_section_data (MonoMetaMethodHeader *mh, const char *ptr) { +#if 0 while ((*ptr) & METHOD_HEADER_SECTION_MORE_SECTS){ /* align on 32-bit boundary */ /* FIXME: not 64-bit clean code */ @@ -723,6 +730,7 @@ parse_section_data (MonoMetaMethodHeader *mh, const char *ptr) ptr = dword_align (ptr); } +#endif } MonoMetaMethodHeader * diff --git a/mono/metadata/metadata.h b/mono/metadata/metadata.h index bd285ed162d..c2d8af6c336 100644 --- a/mono/metadata/metadata.h +++ b/mono/metadata/metadata.h @@ -172,6 +172,7 @@ char *mono_metadata_locate_token (metadata_t *meta, guint32 token); const char *mono_metadata_string_heap (metadata_t *meta, guint32 index); const char *mono_metadata_blob_heap (metadata_t *meta, guint32 index); +const char *mono_metadata_user_string (metadata_t *meta, guint32 index); typedef enum { MONO_META_EXCEPTION_CLAUSE_NONE, diff --git a/notes/cil b/notes/cil new file mode 100644 index 00000000000..eaf550b9fe2 --- /dev/null +++ b/notes/cil @@ -0,0 +1,6 @@ +Random collection of notes + + * What is the point of having the InlineVar argument to + opcodes be a signed integer instead of unsigned? + + |