#include <mono/metadata/cil-coff.h>
#include <mono/metadata/endian.h>
#include <mono/metadata/typeattr.h>
+#include <mono/metadata/fieldattr.h>
+#include <mono/metadata/eltype.h>
+#include "util.h"
FILE *output;
}
}
-typedef struct {
- int code;
- char *str;
-} map_t;
-
-static const char *
-map (int code, map_t *table)
-{
- int i;
-
- for (i = 0; table [i].str != NULL; i++)
- if (table [i].code == code)
- return table [i].str;
- g_assert_not_reached ();
- return "";
-}
-
static map_t visibility_map [] = {
{ TYPE_ATTRIBUTE_NOT_PUBLIC, "not-public " },
{ TYPE_ATTRIBUTE_PUBLIC, "public " },
return buffer;
}
-static void
-dis_fields (metadata_t *m, guint32 idx)
+static map_t 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 , "System.Void" },
+ { ELEMENT_TYPE_BOOLEAN , "System.Bool" },
+ { ELEMENT_TYPE_CHAR , "System.Char" },
+ { ELEMENT_TYPE_I1 , "System.SByte" },
+ { ELEMENT_TYPE_U1 , "System.Byte" },
+ { ELEMENT_TYPE_I2 , "System.Int16" },
+ { ELEMENT_TYPE_U2 , "System.UInt16" },
+ { ELEMENT_TYPE_I4 , "System.Int32" },
+ { ELEMENT_TYPE_U4 , "System.UInt32" },
+ { ELEMENT_TYPE_I8 , "System.Int64" },
+ { ELEMENT_TYPE_U8 , "System.UInt64" },
+ { ELEMENT_TYPE_R4 , "System.Single" },
+ { ELEMENT_TYPE_R8 , "System.Double" },
+ { ELEMENT_TYPE_STRING , "System.String" },
+ { ELEMENT_TYPE_TYPEDBYREF , "TypedByRef" },
+ { ELEMENT_TYPE_I , "System.Int32" },
+ { ELEMENT_TYPE_U , "System.UPtr" },
+ { ELEMENT_TYPE_OBJECT , "System.Object" },
+ { 0, NULL }
+};
+
+/**
+ * field_flags:
+ *
+ * Returns a stringified version of a Field's flags
+ */
+static char *
+field_flags (guint32 f)
{
- fprintf (output, "FIELD_LIST: %d\n", idx);
+ static char buffer [1024];
+ int access = f & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
+
+ buffer [0] = 0;
+
+ strcat (buffer, map (access, access_map));
+ strcat (buffer, flags (f, field_flags_map));
+ return g_strdup (buffer);
}
-static void
-dis_methods (metadata_t *m, guint32 idx)
+/**
+ * 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;
+}
+
+/**
+ * get_custom_mod:
+ *
+ * Decodes a CustomMod (22.2.7)
+ *
+ * Returns: updated pointer location
+ */
+static const char *
+get_custom_mod (const char *ptr, char **return_value)
+{
+ if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
+ (*ptr == ELEMENT_TYPE_CMOD_REQD)){
+ fprintf (stderr, "FIXME: still do not support CustomMods (22.2.7)");
+ exit (1);
+ }
+ *return_value = NULL;
+ return ptr;
+}
+
+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 [9];
+
+/* g_assert (idx <= m->tables [META_TABLE_MODULE].rows); */
+
+/* return g_strdup_printf ("IDX=0x%x", idx); */
+ expand (&m->tables [META_TABLE_ASSEMBLYREF], 0, 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] >> 3;
+ table = cols [0] & 7;
+ printf ("------------ %d %d --------\n", rs_idx, table);
+
+ switch (table){
+ case 0: /* Module */
+ x = get_module (m, rs_idx);
+ ret = g_strdup_printf ("[%08x:%s] %s.%s", cols [0], x, s, t);
+ g_free (x);
+ break;
+
+ case 1: /* ModuleRef */
+ ret = g_strdup_printf ("TypeRef: ModuleRef (%s.%s)", s, t);
+
+ case 3: /* AssemblyRef */
+ ret = g_strdup_printf ("TypeRef: AssemblyRef (%s.%s)", s, t);
+
+ case 4: /* TypeRef */
+ ret = g_strdup_printf ("TypeRef: TYPEREF! (%s.%s)", s, t);
+
+ default:
+ ret = g_strdup ("ERROR");
+ }
+
+ return ret;
+}
+
+static char *
+typedef_or_ref (metadata_t *m, guint32 dor_token)
+{
+ int table = dor_token & 0x03;
+ int idx = dor_token >> 2;
+ char *s, *temp = NULL;
+
+ 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 ("/* 0x%08x */ %s", dor_token, temp);
+ break;
+
+ case 2: /* TypeSpec */
+ s = g_strdup_printf ("TypeSpec: 0x%08x", dor_token);
+ break;
+
+ }
+
+ 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 = 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_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.
+ *
+ * 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_ARRAY:
+ *result = g_strdup ("ARRAY:TODO");
+ break;
+
+ case ELEMENT_TYPE_SZARRAY:
+ *result = g_strdup ("SZARRAY: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;
+ int len;
+ static char buffer [8192];
+
+ 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 (ptr, &allocated_modifier_string);
+ ptr = get_type (m, ptr, &allocated_type_string);
+
+ sprintf (buffer, "LEN=%d:::: ", len);
+ strcat (buffer, allocated_type_string);
+
+ if (allocated_modifier_string)
+ g_free (allocated_modifier_string);
+ if (allocated_type_string)
+ g_free (allocated_modifier_string);
+
+ return g_strdup (buffer);
}
+/**
+ * decode_literal:
+ * @m: metadata context
+ * @token: token to decode
+ *
+ * decodes the literal indexed by @token.
+ */
static char *
-typedef_or_ref (guint32 index)
+decode_literal (metadata_t *m, guint32 token)
{
- return "";
+ return g_strdup ("LITERAL_VALUE");
}
-
+
+/**
+ * dis_field_list:
+ * @m: metadata context
+ * @start: starting index into the Field Table.
+ * @end: ending index into Field table.
+ *
+ * This routine displays all the decoded fields from @start to @end
+ */
static void
-dis_type (metadata_t *m, metadata_tableinfo_t *t, int n)
+dis_field_list (metadata_t *m, guint32 start, guint32 end)
{
+ metadata_tableinfo_t *t = &m->tables [META_TABLE_FIELD];
+ guint32 cols [3];
+ int i;
+
+ if (end > t->rows + 1){
+ fprintf (output, "ERROR index out of range in fields");
+ exit (1);
+ }
+
+ for (i = start; i < end; i++){
+ char *sig, *flags;
+
+ expand (t, i, cols, CSIZE (cols));
+ sig = field_signature (m, cols [2]);
+ flags = field_flags (cols [0]);
+
+ if (cols [0] & FIELD_ATTRIBUTE_LITERAL){
+ char *lit = decode_literal (m, cols [2]);
+
+ fprintf (output, " .field %s %s %s = ",
+ flags, sig,
+ mono_metadata_string_heap (m, cols [1]));
+ fprintf (output, "%s\n", lit);
+ g_free (lit);
+ } else
+ fprintf (output, " .field %s %s %s\n",
+ flags, sig,
+ mono_metadata_string_heap (m, cols [1]));
+ g_free (flags);
+ g_free (sig);
+ }
+}
+
+/**
+ * dis_field_list:
+ * @m: metadata context
+ * @start: starting index into the Method Table.
+ * @end: ending index into Method table.
+ *
+ * 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_type:
+ * @m: metadata context
+ * @n: index of type to disassemble
+ *
+ * Disassembles the type whose index in the TypeDef table is @n.
+ */
+static void
+dis_type (metadata_t *m, int n)
+{
+ metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
guint32 cols [6];
+ guint32 cols_next [6];
const char *name;
char *tn;
expand (t, n, cols, CSIZE (cols));
+ expand (t, n + 1, cols_next, CSIZE (cols_next));
name = mono_metadata_string_heap (m, cols [1]);
tn = "interface";
fprintf (output, " .%s %s%s\n", tn, typedef_flags (cols [0]), name);
- fprintf (output, " \textends %s\n", typedef_or_ref (cols [3]));
+ fprintf (output, " \textends %s\n", typedef_or_ref (m, cols [3]));
fprintf (output, " {\n");
- dis_fields (m, cols [4]);
- dis_methods (m, cols [5]);
+
+ /*
+ * The value in the table is always valid, we know we have fields
+ * if the value stored is different than the next record.
+ */
+ if (cols [4] != cols_next [4])
+ dis_field_list (m, cols [4] - 1, cols_next [4] - 1);
+ if (cols [4] != cols_next [5])
+ dis_method_list (m, cols [5], cols_next [5]);
+
fprintf (output, " }\n");
}
+/**
+ * dis_types:
+ * @m: metadata context
+ *
+ * disassembles all types in the @m context
+ */
static void
dis_types (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
int i;
- for (i = 0; i < t->rows; i++){
- dis_type (m, t, i);
- }
+ for (i = 0; i < t->rows; i++)
+ dis_type (m, i);
}
+/**
+ * disassemble_file:
+ * @file: file containing CIL code.
+ *
+ * Disassembles the @file file.
+ */
static void
disassemble_file (const char *file)
{