2001-06-27 Miguel de Icaza <miguel@ximian.com>

* main.c: Split code.

svn path=/trunk/mono/; revision=40


Commit migrated from f10919de96
This commit is contained in:
Miguel de Icaza 2001-06-27 17:29:01 +00:00
parent 781642bf71
commit be71b0fcf3
9 changed files with 747 additions and 608 deletions

View File

@ -3,7 +3,13 @@ INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
bin_PROGRAMS = monodis
monodis_SOURCES = \
get.c \
get.h \
dis.h \
dump.c \
dump.h \
main.c \
meta.h \
util.c \
util.h

90
src/mono/mono/dis/dump.c Normal file
View File

@ -0,0 +1,90 @@
/*
* dump.c: Dumping routines for the disassembler.
*
* Author:
* Miguel de Icaza (miguel@ximian.com)
*
* (C) 2001 Ximian, Inc.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include "meta.h"
#include "util.h"
#include "dump.h"
#include "get.h"
void
dump_table_typeref (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEREF];
int i;
fprintf (output, "Typeref Table\n");
for (i = 1; i <= t->rows; i++){
char *s = get_typeref (m, i);
fprintf (output, "%d: %s\n", i, s);
g_free (s);
}
fprintf (output, "\n");
}
void
dump_table_typedef (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
int i;
fprintf (output, "Typedef Table\n");
for (i = 1; i <= t->rows; i++){
char *s = get_typedef (m, i);
fprintf (output, "%d: %s\n", i, s);
g_free (s);
}
fprintf (output, "\n");
}
void
dump_table_assemblyref (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_ASSEMBLYREF];
int i;
fprintf (output, "AssemblyRef Table\n");
for (i = 0; i < t->rows; i++){
guint32 cols [9];
expand (t, i, cols, CSIZE (cols));
fprintf (output, "%d: %d.%d.%d.%d %s\n", i,
cols [0], cols [1], cols [2], cols [3],
mono_metadata_string_heap (m, cols [6]));
}
fprintf (output, "\n");
}
void
dump_table_param (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_PARAM];
int i;
fprintf (output, "Param Table\n");
for (i = 0; i < t->rows; i++){
guint32 cols [3];
expand (t, i, cols, CSIZE (cols));
fprintf (output, "%d: 0x%04x %d %s\n",
i,
cols [0], cols [1],
mono_metadata_string_heap (m, cols [2]));
}
fprintf (output, "\n");
}

6
src/mono/mono/dis/dump.h Normal file
View File

@ -0,0 +1,6 @@
extern FILE *output;
void dump_table_typeref (metadata_t *m);
void dump_table_typedef (metadata_t *m);
void dump_table_assemblyref (metadata_t *m);
void dump_table_param (metadata_t *m);

569
src/mono/mono/dis/get.c Normal file
View File

@ -0,0 +1,569 @@
/*
* get.c: Functions to get stringified values from the metadata tables.
*
* Author:
* Miguel de Icaza (miguel@ximian.com)
*
* (C) 2001 Ximian, Inc.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include "meta.h"
#include "util.h"
#include "get.h"
/**
* expand:
* @t: table to extract information from.
* @idx: index in table.
* @res: array of @res_size cols to store the results in
*
* This decompresses the metadata element @idx in table @t
* into the guint32 @res array that has res_size elements
*/
void
expand (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size)
{
guint32 bitfield = t->size_bitfield;
int i, count = meta_table_count (bitfield);
char *data = t->base + idx * t->row_size;
g_assert (res_size == count);
for (i = 0; i < count; i++){
int n = meta_table_size (bitfield, i);
switch (n){
case 1:
res [i] = *data; break;
case 2:
res [i] = read16 (data); break;
case 4:
res [i] = read32 (data); break;
default:
g_assert_not_reached ();
}
data += n;
}
}
/**
* get_encoded_value:
* @ptr: pointer to decode from
* @len: result value is stored here.
*
* This routine decompresses 32-bit values as specified in the "Blob and
* Signature" section (22.2)
*
* Returns: updated pointer location
*/
const char *
get_encoded_value (const char *_ptr, guint32 *len)
{
const unsigned char *ptr = (unsigned char *) _ptr;
unsigned char b = *ptr;
if ((b & 0x80) == 0){
*len = b;
return ptr+1;
} else if ((b & 0x40) == 0){
*len = ((b & 0x3f) << 8 | ptr [1]);
return ptr + 2;
}
*len = ((b & 0x1f) << 24) |
(ptr [1] << 16) |
(ptr [2] << 8) |
ptr [3];
return ptr + 4;
}
char *
get_typedef (metadata_t *m, int idx)
{
guint32 cols [6];
expand (&m->tables [META_TABLE_TYPEDEF], idx - 1, cols, CSIZE (cols));
return g_strdup_printf (
"%s.%s",
mono_metadata_string_heap (m, cols [2]),
mono_metadata_string_heap (m, cols [1]));
}
char *
get_module (metadata_t *m, int idx)
{
guint32 cols [5];
/*
* There MUST BE only one module in the Module table
*/
g_assert (idx == 1);
expand (&m->tables [META_TABLE_MODULEREF], idx - 1, cols, CSIZE (cols));
return g_strdup (mono_metadata_string_heap (m, cols [6]));
}
char *
get_assemblyref (metadata_t *m, int idx)
{
guint32 cols [9];
expand (&m->tables [META_TABLE_ASSEMBLYREF], idx - 1, cols, CSIZE (cols));
return g_strdup (mono_metadata_string_heap (m, cols [6]));
}
char *
get_typeref (metadata_t *m, int idx)
{
guint32 cols [3];
const char *s, *t;
char *x, *ret;
guint32 rs_idx, table;
expand (&m->tables [META_TABLE_TYPEREF], idx - 1, cols, CSIZE (cols));
t = mono_metadata_string_heap (m, cols [1]);
s = mono_metadata_string_heap (m, cols [2]);
rs_idx = cols [0] >> 2;
/*
* Two bits in Beta2.
* ECMA spec claims 3 bits
*/
table = cols [0] & 3;
switch (table){
case 0: /* Module */
x = get_module (m, rs_idx);
ret = g_strdup_printf ("TODO:TypeRef-Module [%s] %s.%s", x, s, t);
g_free (x);
break;
case 1: /* ModuleRef */
ret = g_strdup_printf ("TODO:TypeRef-ModuleRef (%s.%s)", s, t);
break;
case 2: /*
* AssemblyRef (ECMA docs claim it is 3, but it looks to
* me like it is 2 (tokens are prefixed with 0x23)
*/
x = get_assemblyref (m, rs_idx);
ret = g_strdup_printf ("[%s] %s.%s", x, s, t);
g_free (x);
break;
case 4: /* TypeRef */
ret = g_strdup_printf ("TODO:TypeRef-TypeRef: TYPEREF! (%s.%s)", s, t);
break;
default:
ret = g_strdup_printf ("Unknown table in TypeRef %d", table);
}
return ret;
}
/**
* get_typedef_or_ref:
* @m: metadata context
* @dor_token: def or ref encoded index
*
* Low two bits contain table to lookup from
* high bits contain the index into the def or ref table
*
* Returns: a stringified version of the MethodDef or MethodRef
* at (dor_token >> 2)
*/
char *
get_typedef_or_ref (metadata_t *m, guint32 dor_token)
{
char *temp = NULL, *s;
int table, idx;
/*
* low 2 bits contain encoding
*/
table = dor_token & 0x03;
idx = dor_token >> 2;
switch (table){
case 0: /* TypeDef */
temp = get_typedef (m, idx);
s = g_strdup_printf ("%s", temp);
break;
case 1: /* TypeRef */
temp = get_typeref (m, idx);
s = g_strdup_printf ("%s", temp);
break;
case 2: /* TypeSpec */
s = g_strdup_printf ("TODO-TypeSpec: 0x%08x", idx);
break;
default:
g_error ("Unhandled encoding for typedef-or-ref coded index");
}
if (temp)
g_free (temp);
return s;
}
/**
* get_encoded_typedef_or_ref:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* result will point to a g_malloc()ed string.
*
* Returns: the new ptr to continue decoding
*/
const char *
get_encoded_typedef_or_ref (metadata_t *m, const char *ptr, char **result)
{
guint32 token;
ptr = get_encoded_value (ptr, &token);
*result = get_typedef_or_ref (m, token);
return ptr;
}
/**
* get_custom_mod:
*
* Decodes a CustomMod (22.2.7)
*
* Returns: updated pointer location
*/
const char *
get_custom_mod (metadata_t *m, const char *ptr, char **return_value)
{
char *s;
if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
(*ptr == ELEMENT_TYPE_CMOD_REQD)){
ptr++;
ptr = get_encoded_typedef_or_ref (m, ptr, &s);
*return_value = g_strconcat ("CMOD ", s, NULL);
g_free (s);
} else
*return_value = NULL;
return ptr;
}
/**
* methoddefref_signature:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* This routine decodes into a string a MethodDef or a MethodRef.
*
* result will point to a g_malloc()ed string.
*
* Returns: the new ptr to continue decoding
*/
static const char *
methoddefref_signature (metadata_t *m, const char *ptr, char **result)
{
*result = g_strdup ("method-def-or-ref");
return ptr;
}
static map_t element_type_map [] = {
{ ELEMENT_TYPE_END , "end" },
{ ELEMENT_TYPE_VOID , "void" },
{ ELEMENT_TYPE_BOOLEAN , "bool" },
{ ELEMENT_TYPE_CHAR , "char" },
{ ELEMENT_TYPE_I1 , "sbyte" },
{ ELEMENT_TYPE_U1 , "byte" },
{ ELEMENT_TYPE_I2 , "int16" },
{ ELEMENT_TYPE_U2 , "uint16" },
{ ELEMENT_TYPE_I4 , "int32" },
{ ELEMENT_TYPE_U4 , "uint32" },
{ ELEMENT_TYPE_I8 , "int64" },
{ ELEMENT_TYPE_U8 , "uint64" },
{ ELEMENT_TYPE_R4 , "float32" },
{ ELEMENT_TYPE_R8 , "float64" },
{ ELEMENT_TYPE_STRING , "string" },
{ ELEMENT_TYPE_TYPEDBYREF , "TypedByRef" },
{ ELEMENT_TYPE_I , "native int" },
{ ELEMENT_TYPE_U , "native unsigned int" },
{ ELEMENT_TYPE_OBJECT , "object" },
{ 0, NULL }
};
/**
* get_type:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* This routine returs in @result the stringified type pointed by @ptr.
* (22.2.12)
*
* Returns: the new ptr to continue decoding
*/
const char *
get_type (metadata_t *m, const char *ptr, char **result)
{
char c;
c = *ptr++;
switch (c){
case ELEMENT_TYPE_BOOLEAN:
case ELEMENT_TYPE_CHAR:
case ELEMENT_TYPE_I1:
case ELEMENT_TYPE_U1:
case ELEMENT_TYPE_I2:
case ELEMENT_TYPE_U2:
case ELEMENT_TYPE_I4:
case ELEMENT_TYPE_U4:
case ELEMENT_TYPE_I8:
case ELEMENT_TYPE_U8:
case ELEMENT_TYPE_R4:
case ELEMENT_TYPE_R8:
case ELEMENT_TYPE_I:
case ELEMENT_TYPE_STRING:
case ELEMENT_TYPE_OBJECT:
*result = g_strdup (map (c, element_type_map));
break;
case ELEMENT_TYPE_VALUETYPE:
case ELEMENT_TYPE_CLASS:
ptr = get_encoded_typedef_or_ref (m, ptr, result);
break;
case ELEMENT_TYPE_FNPTR:
ptr = methoddefref_signature (m, ptr, result);
break;
case ELEMENT_TYPE_SZARRAY: {
char *child_type;
ptr = get_type (m, ptr, &child_type);
*result = g_strdup_printf ("%s[]", child_type);
g_free (child_type);
break;
}
case ELEMENT_TYPE_ARRAY:
*result = g_strdup ("ARRAY:TODO");
}
return ptr;
}
/**
*
* Returns a stringified representation of a FieldSig (22.2.4)
*/
char *
get_field_signature (metadata_t *m, guint32 blob_signature)
{
char *allocated_modifier_string, *allocated_type_string;
const char *ptr = mono_metadata_blob_heap (m, blob_signature);
const char *base;
char *res;
int len;
ptr = get_encoded_value (ptr, &len);
base = ptr;
/* FIELD is 0x06 */
g_assert (*ptr == 0x06);
/* hex_dump (ptr, 0, len); */
ptr++; len--;
ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
ptr = get_type (m, ptr, &allocated_type_string);
res = g_strdup_printf (
"%s %s",
allocated_modifier_string ? allocated_modifier_string : "",
allocated_type_string);
if (allocated_modifier_string)
g_free (allocated_modifier_string);
if (allocated_type_string)
g_free (allocated_modifier_string);
return res;
}
/**
* decode_literal:
* @m: metadata context
* @token: token to decode
*
* decodes the literal indexed by @token.
*/
char *
decode_literal (metadata_t *m, guint32 token)
{
return g_strdup ("LITERAL_VALUE");
}
/**
* get_ret_type:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* This routine returns in @result the stringified RetType (22.2.11)
*
* Returns: the new ptr to continue decoding.
*/
const char *
get_ret_type (metadata_t *m, const char *ptr, char **ret_type)
{
GString *str = g_string_new ("");
char *mod = NULL;
char *allocated_type_string;
ptr = get_custom_mod (m, ptr, &mod);
if (mod){
g_string_append (str, mod);
g_string_append_c (str, ' ');
g_free (mod);
}
if (*ptr == ELEMENT_TYPE_TYPEDBYREF){
/* TODO: what does `typedbyref' mean? */
g_string_append (str, "/* FIXME: What does this mean? */ typedbyref ");
ptr++;
} else if (*ptr == ELEMENT_TYPE_VOID){
g_string_append (str, "void");
ptr++;
} else {
if (*ptr == ELEMENT_TYPE_BYREF){
g_string_append (str, "[out] ");
ptr++;
}
ptr = get_type (m, ptr, &allocated_type_string);
g_string_append (str, allocated_type_string);
g_free (allocated_type_string);
}
*ret_type = str->str;
g_string_free (str, FALSE);
return ptr;
}
/**
* get_param:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* This routine returns in @result the stringified Param (22.2.10)
*
* Returns: the new ptr to continue decoding.
*/
const char *
get_param (metadata_t *m, const char *ptr, char **retval)
{
GString *str = g_string_new ("");
char *allocated_mod_string, *allocated_type_string;
ptr = get_custom_mod (m, ptr, &allocated_mod_string);
if (allocated_mod_string){
g_string_append (str, allocated_mod_string);
g_string_append_c (str, ' ');
g_free (allocated_mod_string);
}
if (*ptr == ELEMENT_TYPE_TYPEDBYREF){
g_string_append (str, "/*FIXME: what does typedbyref mean? */ typedbyref ");
ptr++;
} else {
if (*ptr == ELEMENT_TYPE_BYREF){
g_string_append (str, "[out] ");
ptr++;
}
ptr = get_type (m, ptr, &allocated_type_string);
g_string_append (str, allocated_type_string);
g_free (allocated_type_string);
}
*retval = str->str;
g_string_free (str, FALSE);
return ptr;
}
static map_t param_map [] = {
{ PARAM_ATTRIBUTE_IN, "[in] " },
{ PARAM_ATTRIBUTE_OUT, "[out] " },
{ PARAM_ATTRIBUTE_OPTIONAL, "optional " },
{ PARAM_ATTRIBUTE_HAS_DEFAULT, "hasdefault " },
{ PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL, "fieldmarshal " },
{ 0, NULL }
};
char *
param_flags (guint32 f)
{
return g_strdup (flags (f, param_map));
}
static map_t field_access_map [] = {
{ FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
{ FIELD_ATTRIBUTE_PRIVATE, "private " },
{ FIELD_ATTRIBUTE_FAM_AND_ASSEM, "famandassem " },
{ FIELD_ATTRIBUTE_ASSEMBLY, "assembly " },
{ FIELD_ATTRIBUTE_FAMILY, "family " },
{ FIELD_ATTRIBUTE_FAM_OR_ASSEM, "famorassem " },
{ FIELD_ATTRIBUTE_PUBLIC, "public " },
{ 0, NULL }
};
static map_t field_flags_map [] = {
{ FIELD_ATTRIBUTE_STATIC, "static " },
{ FIELD_ATTRIBUTE_INIT_ONLY, "initonly " },
{ FIELD_ATTRIBUTE_LITERAL, "literal " },
{ FIELD_ATTRIBUTE_NOT_SERIALIZED, "notserialized " },
{ FIELD_ATTRIBUTE_SPECIAL_NAME, "specialname " },
{ FIELD_ATTRIBUTE_PINVOKE_IMPL, "FIXME:pinvokeimpl " },
{ 0, NULL }
};
/**
* field_flags:
*
* Returns a stringified version of a Field's flags
*/
char *
field_flags (guint32 f)
{
static char buffer [1024];
int access = f & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
buffer [0] = 0;
strcat (buffer, map (access, field_access_map));
strcat (buffer, flags (f, field_flags_map));
return g_strdup (buffer);
}

37
src/mono/mono/dis/get.h Normal file
View File

@ -0,0 +1,37 @@
/*
* These return allocated strings
*/
char *get_typedef (metadata_t *m, int idx);
char *get_module (metadata_t *m, int idx);
char *get_assemblyref (metadata_t *m, int idx);
char *get_typeref (metadata_t *m, int idx);
char *get_typedef_or_ref (metadata_t *m, guint32 dor_token);
char *get_field_signature (metadata_t *m, guint32 blob_signature);
char *decode_literal (metadata_t *m, guint32 token);
char *param_flags (guint32 f);
char *field_flags (guint32 f);
/*
* These functions are used during the decoding of streams in the
* metadata heaps (a simple parsing).
*
* They return the `next' location to continue parsing from (ptr is
* the starting location).
*
* Results are returning in the pointer argument.
*/
const char *get_encoded_typedef_or_ref (metadata_t *m, const char *ptr,
char **result);
const char *get_encoded_value (const char *_ptr,
guint32 *len);
const char *get_custom_mod (metadata_t *m, const char *ptr,
char **return_value);
const char *get_type (metadata_t *m, const char *ptr,
char **result);
const char *get_ret_type (metadata_t *m, const char *ptr,
char **ret_type);
const char *get_param (metadata_t *m, const char *ptr,
char **retval);
void expand (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size);

View File

@ -16,16 +16,10 @@
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/cil-coff.h>
#include <mono/metadata/endian.h>
#include <mono/metadata/typeattr.h>
#include <mono/metadata/fieldattr.h>
#include <mono/metadata/methodattr.h>
#include <mono/metadata/eltype.h>
#include <mono/metadata/blobsig.h>
#include <mono/metadata/paramattr.h>
#include "meta.h"
#include "util.h"
#include "dump.h"
#include "get.h"
FILE *output;
@ -45,35 +39,6 @@ dump_header_data (MonoAssembly *ass)
"// Copyright (C) 2001 Ximian, Inc.\n\n");
}
#define CSIZE(x) (sizeof (x) / 4)
static void
expand (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size)
{
guint32 bitfield = t->size_bitfield;
int i, count = meta_table_count (bitfield);
char *data = t->base + idx * t->row_size;
g_assert (res_size == count);
for (i = 0; i < count; i++){
int n = meta_table_size (bitfield, i);
switch (n){
case 1:
res [i] = *data; break;
case 2:
res [i] = read16 (data); break;
case 4:
res [i] = read32 (data); break;
default:
g_assert_not_reached ();
}
data += n;
}
}
static void
dis_directive_assembly (metadata_t *m)
{
@ -183,405 +148,6 @@ typedef_flags (guint32 flags)
return buffer;
}
static map_t field_access_map [] = {
{ FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
{ FIELD_ATTRIBUTE_PRIVATE, "private " },
{ FIELD_ATTRIBUTE_FAM_AND_ASSEM, "famandassem " },
{ FIELD_ATTRIBUTE_ASSEMBLY, "assembly " },
{ FIELD_ATTRIBUTE_FAMILY, "family " },
{ FIELD_ATTRIBUTE_FAM_OR_ASSEM, "famorassem " },
{ FIELD_ATTRIBUTE_PUBLIC, "public " },
{ 0, NULL }
};
static map_t field_flags_map [] = {
{ FIELD_ATTRIBUTE_STATIC, "static " },
{ FIELD_ATTRIBUTE_INIT_ONLY, "initonly " },
{ FIELD_ATTRIBUTE_LITERAL, "literal " },
{ FIELD_ATTRIBUTE_NOT_SERIALIZED, "notserialized " },
{ FIELD_ATTRIBUTE_SPECIAL_NAME, "specialname " },
{ FIELD_ATTRIBUTE_PINVOKE_IMPL, "FIXME:pinvokeimpl " },
{ 0, NULL }
};
static map_t element_type_map [] = {
{ ELEMENT_TYPE_END , "end" },
{ ELEMENT_TYPE_VOID , "void" },
{ ELEMENT_TYPE_BOOLEAN , "bool" },
{ ELEMENT_TYPE_CHAR , "char" },
{ ELEMENT_TYPE_I1 , "sbyte" },
{ ELEMENT_TYPE_U1 , "byte" },
{ ELEMENT_TYPE_I2 , "int16" },
{ ELEMENT_TYPE_U2 , "uint16" },
{ ELEMENT_TYPE_I4 , "int32" },
{ ELEMENT_TYPE_U4 , "uint32" },
{ ELEMENT_TYPE_I8 , "int64" },
{ ELEMENT_TYPE_U8 , "uint64" },
{ ELEMENT_TYPE_R4 , "float32" },
{ ELEMENT_TYPE_R8 , "float64" },
{ ELEMENT_TYPE_STRING , "string" },
{ ELEMENT_TYPE_TYPEDBYREF , "TypedByRef" },
{ ELEMENT_TYPE_I , "native int" },
{ ELEMENT_TYPE_U , "native unsigned int" },
{ ELEMENT_TYPE_OBJECT , "object" },
{ 0, NULL }
};
/**
* field_flags:
*
* Returns a stringified version of a Field's flags
*/
static char *
field_flags (guint32 f)
{
static char buffer [1024];
int access = f & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
buffer [0] = 0;
strcat (buffer, map (access, field_access_map));
strcat (buffer, flags (f, field_flags_map));
return g_strdup (buffer);
}
/**
* get_encoded_value:
* @ptr: pointer to decode from
* @len: result value is stored here.
*
* This routine decompresses 32-bit values as specified in the "Blob and
* Signature" section (22.2)
*
* Returns: updated pointer location
*/
static const char *
get_encoded_value (const char *_ptr, guint32 *len)
{
const unsigned char *ptr = (unsigned char *) _ptr;
unsigned char b = *ptr;
if ((b & 0x80) == 0){
*len = b;
return ptr+1;
} else if ((b & 0x40) == 0){
*len = ((b & 0x3f) << 8 | ptr [1]);
return ptr + 2;
}
*len = ((b & 0x1f) << 24) |
(ptr [1] << 16) |
(ptr [2] << 8) |
ptr [3];
return ptr + 4;
}
static char *
get_typedef (metadata_t *m, int idx)
{
guint32 cols [6];
expand (&m->tables [META_TABLE_TYPEDEF], idx - 1, cols, CSIZE (cols));
return g_strdup_printf (
"%s.%s",
mono_metadata_string_heap (m, cols [2]),
mono_metadata_string_heap (m, cols [1]));
}
static char *
get_module (metadata_t *m, int idx)
{
guint32 cols [5];
/*
* There MUST BE only one module in the Module table
*/
g_assert (idx == 1);
expand (&m->tables [META_TABLE_MODULEREF], idx - 1, cols, CSIZE (cols));
return g_strdup (mono_metadata_string_heap (m, cols [6]));
}
static char *
get_assemblyref (metadata_t *m, int idx)
{
guint32 cols [9];
expand (&m->tables [META_TABLE_ASSEMBLYREF], idx - 1, cols, CSIZE (cols));
return g_strdup (mono_metadata_string_heap (m, cols [6]));
}
static char *
get_typeref (metadata_t *m, int idx)
{
guint32 cols [3];
const char *s, *t;
char *x, *ret;
guint32 rs_idx, table;
expand (&m->tables [META_TABLE_TYPEREF], idx - 1, cols, CSIZE (cols));
t = mono_metadata_string_heap (m, cols [1]);
s = mono_metadata_string_heap (m, cols [2]);
rs_idx = cols [0] >> 2;
/*
* Two bits in Beta2.
* ECMA spec claims 3 bits
*/
table = cols [0] & 3;
switch (table){
case 0: /* Module */
x = get_module (m, rs_idx);
ret = g_strdup_printf ("TODO:TypeRef-Module [%s] %s.%s", x, s, t);
g_free (x);
break;
case 1: /* ModuleRef */
ret = g_strdup_printf ("TODO:TypeRef-ModuleRef (%s.%s)", s, t);
break;
case 2: /*
* AssemblyRef (ECMA docs claim it is 3, but it looks to
* me like it is 2 (tokens are prefixed with 0x23)
*/
x = get_assemblyref (m, rs_idx);
ret = g_strdup_printf ("[%s] %s.%s", x, s, t);
g_free (x);
break;
case 4: /* TypeRef */
ret = g_strdup_printf ("TODO:TypeRef-TypeRef: TYPEREF! (%s.%s)", s, t);
break;
default:
ret = g_strdup_printf ("Unknown table in TypeRef %d", table);
}
return ret;
}
static char *
get_typedef_or_ref (metadata_t *m, guint32 dor_token)
{
char *temp = NULL, *s;
int table, idx;
/*
* low 2 bits contain encoding
*/
table = dor_token & 0x03;
idx = dor_token >> 2;
switch (table){
case 0: /* TypeDef */
temp = get_typedef (m, idx);
s = g_strdup_printf ("%s", temp);
break;
case 1: /* TypeRef */
temp = get_typeref (m, idx);
s = g_strdup_printf ("%s", temp);
break;
case 2: /* TypeSpec */
s = g_strdup_printf ("TODO-TypeSpec: 0x%08x", idx);
break;
default:
g_error ("Unhandled encoding for typedef-or-ref coded index");
}
if (temp)
g_free (temp);
return s;
}
/**
* get_encoded_typedef_or_ref:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* result will point to a g_malloc()ed string.
*
* Returns: the new ptr to continue decoding
*/
static const char *
get_encoded_typedef_or_ref (metadata_t *m, const char *ptr, char **result)
{
guint32 token;
ptr = get_encoded_value (ptr, &token);
*result = get_typedef_or_ref (m, token);
return ptr;
}
/**
* methoddefref_signature:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* This routine decodes into a string a MethodDef or a MethodRef.
*
* result will point to a g_malloc()ed string.
*
* Returns: the new ptr to continue decoding
*/
static const char *
methoddefref_signature (metadata_t *m, const char *ptr, char **result)
{
*result = g_strdup ("method-def-or-ref");
return ptr;
}
/**
* get_custom_mod:
*
* Decodes a CustomMod (22.2.7)
*
* Returns: updated pointer location
*/
static const char *
get_custom_mod (metadata_t *m, const char *ptr, char **return_value)
{
char *s;
if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
(*ptr == ELEMENT_TYPE_CMOD_REQD)){
ptr++;
ptr = get_encoded_typedef_or_ref (m, ptr, &s);
*return_value = g_strconcat ("CMOD ", s, NULL);
g_free (s);
} else
*return_value = NULL;
return ptr;
}
/**
* get_type:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* This routine returs in @result the stringified type pointed by @ptr.
* (22.2.12)
*
* Returns: the new ptr to continue decoding
*/
static const char *
get_type (metadata_t *m, const char *ptr, char **result)
{
char c;
c = *ptr++;
switch (c){
case ELEMENT_TYPE_BOOLEAN:
case ELEMENT_TYPE_CHAR:
case ELEMENT_TYPE_I1:
case ELEMENT_TYPE_U1:
case ELEMENT_TYPE_I2:
case ELEMENT_TYPE_U2:
case ELEMENT_TYPE_I4:
case ELEMENT_TYPE_U4:
case ELEMENT_TYPE_I8:
case ELEMENT_TYPE_U8:
case ELEMENT_TYPE_R4:
case ELEMENT_TYPE_R8:
case ELEMENT_TYPE_I:
case ELEMENT_TYPE_STRING:
case ELEMENT_TYPE_OBJECT:
*result = g_strdup (map (c, element_type_map));
break;
case ELEMENT_TYPE_VALUETYPE:
case ELEMENT_TYPE_CLASS:
ptr = get_encoded_typedef_or_ref (m, ptr, result);
break;
case ELEMENT_TYPE_FNPTR:
ptr = methoddefref_signature (m, ptr, result);
break;
case ELEMENT_TYPE_SZARRAY: {
char *child_type;
ptr = get_type (m, ptr, &child_type);
*result = g_strdup_printf ("%s[]", child_type);
g_free (child_type);
break;
}
case ELEMENT_TYPE_ARRAY:
*result = g_strdup ("ARRAY:TODO");
}
return ptr;
}
/**
*
* Returns a stringified representation of a FieldSig (22.2.4)
*/
static char *
field_signature (metadata_t *m, guint32 blob_signature)
{
char *allocated_modifier_string, *allocated_type_string;
const char *ptr = mono_metadata_blob_heap (m, blob_signature);
const char *base;
char *res;
int len;
ptr = get_encoded_value (ptr, &len);
base = ptr;
/* FIELD is 0x06 */
g_assert (*ptr == 0x06);
/* hex_dump (ptr, 0, len); */
ptr++; len--;
ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
ptr = get_type (m, ptr, &allocated_type_string);
res = g_strdup_printf (
"%s %s",
allocated_modifier_string ? allocated_modifier_string : "",
allocated_type_string);
if (allocated_modifier_string)
g_free (allocated_modifier_string);
if (allocated_type_string)
g_free (allocated_modifier_string);
return res;
}
/**
* decode_literal:
* @m: metadata context
* @token: token to decode
*
* decodes the literal indexed by @token.
*/
static char *
decode_literal (metadata_t *m, guint32 token)
{
return g_strdup ("LITERAL_VALUE");
}
/**
* dis_field_list:
* @m: metadata context
@ -606,7 +172,7 @@ dis_field_list (metadata_t *m, guint32 start, guint32 end)
char *sig, *flags;
expand (t, i, cols, CSIZE (cols));
sig = field_signature (m, cols [2]);
sig = get_field_signature (m, cols [2]);
flags = field_flags (cols [0]);
if (cols [0] & FIELD_ATTRIBUTE_LITERAL){
@ -714,83 +280,15 @@ method_impl_flags (guint32 f)
return s;
}
/**
* get_ret_type:
* @m: metadata context
* @ptr: location to decode from.
* @result: pointer to string where resulting decoded string is stored
*
* This routine returns in @result the stringified RetType (22.2.11)
*
* Returns: the new ptr to continue decoding.
*/
static const char *
get_ret_type (metadata_t *m, const char *ptr, char **ret_type)
static void
dis_code (metadata_t *m, cli_image_info_t *ii, guint32 rva)
{
GString *str = g_string_new ("");
char *mod = NULL;
char *allocated_type_string;
const char *ptr = cli_rva_map (ii, rva);
if (rva == 0)
return;
ptr = get_custom_mod (m, ptr, &mod);
if (mod){
g_string_append (str, mod);
g_string_append_c (str, ' ');
g_free (mod);
}
if (*ptr == ELEMENT_TYPE_TYPEDBYREF){
/* TODO: what does `typedbyref' mean? */
g_string_append (str, "/* FIXME: What does this mean? */ typedbyref ");
ptr++;
} else if (*ptr == ELEMENT_TYPE_VOID){
g_string_append (str, "void");
ptr++;
} else {
if (*ptr == ELEMENT_TYPE_BYREF){
g_string_append (str, "[out] ");
ptr++;
}
ptr = get_type (m, ptr, &allocated_type_string);
g_string_append (str, allocated_type_string);
g_free (allocated_type_string);
}
*ret_type = str->str;
g_string_free (str, FALSE);
return ptr;
}
static const char *
get_param (metadata_t *m, const char *ptr, char **retval)
{
GString *str = g_string_new ("");
char *allocated_mod_string, *allocated_type_string;
ptr = get_custom_mod (m, ptr, &allocated_mod_string);
if (allocated_mod_string){
g_string_append (str, allocated_mod_string);
g_string_append_c (str, ' ');
g_free (allocated_mod_string);
}
if (*ptr == ELEMENT_TYPE_TYPEDBYREF){
g_string_append (str, "/*FIXME: what does typedbyref mean? */ typedbyref ");
ptr++;
} else {
if (*ptr == ELEMENT_TYPE_BYREF){
g_string_append (str, "[out] ");
ptr++;
}
ptr = get_type (m, ptr, &allocated_type_string);
g_string_append (str, allocated_type_string);
g_free (allocated_type_string);
}
*retval = str->str;
g_string_free (str, FALSE);
return ptr;
hex_dump (ptr, 0, 64);
}
typedef struct {
@ -800,6 +298,16 @@ typedef struct {
char **param;
} MethodSignature;
/**
* parse_method_signature:
* @m: metadata context
* @blob_signature: pointer to the signature in the Blob heap
*
* 22.2.1: MethodDefSig.
*
* Returns the parsed information in the MethodSignature structure
* needs to be deallocated with free_method_signature().
*/
static MethodSignature *
parse_method_signature (metadata_t *m, guint32 blob_signature)
{
@ -840,21 +348,6 @@ free_method_signature (MethodSignature *ms)
g_free (ms);
}
static map_t param_map [] = {
{ PARAM_ATTRIBUTE_IN, "[in] " },
{ PARAM_ATTRIBUTE_OUT, "[out] " },
{ PARAM_ATTRIBUTE_OPTIONAL, "optional " },
{ PARAM_ATTRIBUTE_HAS_DEFAULT, "hasdefault " },
{ PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL, "fieldmarshal " },
{ 0, NULL }
};
static char *
param_flags (guint32 f)
{
return g_strdup (map (f, param_map));
}
/**
* dis_field_list:
* @m: metadata context
@ -864,7 +357,7 @@ param_flags (guint32 f)
* This routine displays the methods in the Method Table from @start to @end
*/
static void
dis_method_list (metadata_t *m, guint32 start, guint32 end)
dis_method_list (metadata_t *m, cli_image_info_t *ii, guint32 start, guint32 end)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_METHOD];
metadata_tableinfo_t *p = &m->tables [META_TABLE_PARAM];
@ -921,7 +414,7 @@ dis_method_list (metadata_t *m, guint32 start, guint32 end)
fprintf (output, " {\n");
fprintf (output, " // Method begins at RVA 0x%x\n", cols [0]);
fprintf (output, " // Param: %d %d (%d)\n", cols [5], cols_next [5], ms->param_count);
dis_code (m, ii, cols [0]);
fprintf (output, " }\n\n");
free_method_signature (ms);
}
@ -935,7 +428,7 @@ dis_method_list (metadata_t *m, guint32 start, guint32 end)
* Disassembles the type whose index in the TypeDef table is @n.
*/
static void
dis_type (metadata_t *m, int n)
dis_type (metadata_t *m, cli_image_info_t *ii, int n)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
guint32 cols [6];
@ -966,84 +459,11 @@ dis_type (metadata_t *m, int n)
dis_field_list (m, cols [4] - 1, cols_next [4] - 1);
fprintf (output, "\n");
if (cols [4] != cols_next [5])
dis_method_list (m, cols [5] - 1, cols_next [5] - 1);
dis_method_list (m, ii, cols [5] - 1, cols_next [5] - 1);
fprintf (output, " }\n}\n\n");
}
static void
dump_table_typeref (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEREF];
int i;
fprintf (output, "Typeref Table\n");
for (i = 1; i <= t->rows; i++){
char *s = get_typeref (m, i);
fprintf (output, "%d: %s\n", i, s);
g_free (s);
}
fprintf (output, "\n");
}
static void
dump_table_typedef (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
int i;
fprintf (output, "Typedef Table\n");
for (i = 1; i <= t->rows; i++){
char *s = get_typedef (m, i);
fprintf (output, "%d: %s\n", i, s);
g_free (s);
}
fprintf (output, "\n");
}
static void
dump_table_assemblyref (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_ASSEMBLYREF];
int i;
fprintf (output, "AssemblyRef Table\n");
for (i = 0; i < t->rows; i++){
guint32 cols [9];
expand (t, i, cols, CSIZE (cols));
fprintf (output, "%d: %d.%d.%d.%d %s\n", i,
cols [0], cols [1], cols [2], cols [3],
mono_metadata_string_heap (m, cols [6]));
}
fprintf (output, "\n");
}
static void
dump_table_param (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_PARAM];
int i;
fprintf (output, "Param Table\n");
for (i = 0; i < t->rows; i++){
guint32 cols [3];
expand (t, i, cols, CSIZE (cols));
fprintf (output, "%d: 0x%04x %d %s\n",
i,
cols [0], cols [1],
mono_metadata_string_heap (m, cols [2]));
}
fprintf (output, "\n");
}
/**
* dis_types:
* @m: metadata context
@ -1051,13 +471,13 @@ dump_table_param (metadata_t *m)
* disassembles all types in the @m context
*/
static void
dis_types (metadata_t *m)
dis_types (metadata_t *m, cli_image_info_t *ii)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
int i;
for (i = 0; i < t->rows; i++)
dis_type (m, i);
dis_type (m, ii, i);
}
/**
@ -1106,7 +526,7 @@ disassemble_file (const char *file)
dis_directive_assemblyref (m);
dis_directive_assembly (m);
dis_types (m);
dis_types (m, ii);
}
mono_assembly_close (ass);

9
src/mono/mono/dis/meta.h Normal file
View File

@ -0,0 +1,9 @@
#include <mono/metadata/assembly.h>
#include <mono/metadata/cil-coff.h>
#include <mono/metadata/endian.h>
#include <mono/metadata/typeattr.h>
#include <mono/metadata/fieldattr.h>
#include <mono/metadata/methodattr.h>
#include <mono/metadata/eltype.h>
#include <mono/metadata/blobsig.h>
#include <mono/metadata/paramattr.h>

View File

@ -79,3 +79,4 @@ hex_dump (const char *buffer, int base, int count)
}
fflush (stdout);
}

View File

@ -8,3 +8,4 @@ const char *map (guint32 code, map_t *table);
const char *flags (guint32 code, map_t *table);
void hex_dump (const char *buffer, int base, int count);
#define CSIZE(x) (sizeof (x) / 4)