2 * dis.c: Sample disassembler
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
10 * Investigate how interface inheritance works and how it should be dumped.
11 * Structs are not being labeled as `valuetype' classes
19 #include <mono/metadata/assembly.h>
20 #include <mono/metadata/cil-coff.h>
21 #include <mono/metadata/endian.h>
22 #include <mono/metadata/typeattr.h>
23 #include <mono/metadata/fieldattr.h>
24 #include <mono/metadata/methodattr.h>
25 #include <mono/metadata/eltype.h>
26 #include <mono/metadata/blobsig.h>
27 #include <mono/metadata/paramattr.h>
32 /* True if you want to get a dump of the header data */
33 gboolean dump_header_data_p = FALSE;
38 dump_header_data (MonoAssembly *ass)
40 if (!dump_header_data_p)
44 "// Ximian's CIL disassembler, version 1.0\n"
45 "// Copyright (C) 2001 Ximian, Inc.\n\n");
48 #define CSIZE(x) (sizeof (x) / 4)
50 expand (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size)
52 guint32 bitfield = t->size_bitfield;
53 int i, count = meta_table_count (bitfield);
54 char *data = t->base + idx * t->row_size;
56 g_assert (res_size == count);
58 for (i = 0; i < count; i++){
59 int n = meta_table_size (bitfield, i);
63 res [i] = *data; break;
65 res [i] = read16 (data); break;
68 res [i] = read32 (data); break;
71 g_assert_not_reached ();
78 dis_directive_assembly (metadata_t *m)
80 metadata_tableinfo_t *t = &m->tables [META_TABLE_ASSEMBLY];
86 expand (t, 0, cols, CSIZE (cols));
91 " .hash algorithm 0x%08x\n"
97 mono_metadata_string_heap (m, cols [7]),
99 cols [1], cols [2], cols [3], cols [4],
100 cols [8] ? "\n .locale" : "",
101 cols [8] ? mono_metadata_string_heap (m, cols [8]) : "",
102 cols [6] ? "\n .publickey" : ""
107 dis_directive_assemblyref (metadata_t *m)
109 metadata_tableinfo_t *t = &m->tables [META_TABLE_ASSEMBLYREF];
116 for (i = 0; i < t->rows; i++){
117 expand (t, i, cols, CSIZE (cols));
120 ".assembly extern %s\n"
122 " .ver %d.%d.%d.%d\n"
124 mono_metadata_string_heap (m, cols [6]),
125 cols [0], cols [1], cols [2], cols [3]
130 static map_t visibility_map [] = {
131 { TYPE_ATTRIBUTE_NOT_PUBLIC, "private " },
132 { TYPE_ATTRIBUTE_PUBLIC, "public " },
133 { TYPE_ATTRIBUTE_NESTED_PUBLIC, "nested-public " },
134 { TYPE_ATTRIBUTE_NESTED_PRIVATE, "nested-private " },
135 { TYPE_ATTRIBUTE_NESTED_FAMILY, "family " },
136 { TYPE_ATTRIBUTE_NESTED_ASSEMBLY, "nested-assembly" },
137 { TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM, "nested-fam-and-assembly" },
138 { TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM, "nested-fam-or-assembly" },
142 static map_t layout_map [] = {
143 { TYPE_ATTRIBUTE_AUTO_LAYOUT, "auto " },
144 { TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT, "sequential " },
145 { TYPE_ATTRIBUTE_EXPLICIT_LAYOUT, "explicit " },
149 static map_t format_map [] = {
150 { TYPE_ATTRIBUTE_ANSI_CLASS, "ansi " },
151 { TYPE_ATTRIBUTE_UNICODE_CLASS, "unicode " },
152 { TYPE_ATTRIBUTE_AUTO_CLASS, "auto " },
157 typedef_flags (guint32 flags)
159 static char buffer [1024];
160 int visibility = flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
161 int layout = flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
162 int format = flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK;
166 strcat (buffer, map (visibility, visibility_map));
167 strcat (buffer, map (layout, layout_map));
168 strcat (buffer, map (format, format_map));
170 if (flags & TYPE_ATTRIBUTE_ABSTRACT)
171 strcat (buffer, "abstract ");
172 if (flags & TYPE_ATTRIBUTE_SEALED)
173 strcat (buffer, "sealed ");
174 if (flags & TYPE_ATTRIBUTE_SPECIAL_NAME)
175 strcat (buffer, "special-name ");
176 if (flags & TYPE_ATTRIBUTE_IMPORT)
177 strcat (buffer, "import ");
178 if (flags & TYPE_ATTRIBUTE_SERIALIZABLE)
179 strcat (buffer, "serializable ");
180 if (flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)
181 strcat (buffer, "beforefieldinit ");
186 static map_t field_access_map [] = {
187 { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
188 { FIELD_ATTRIBUTE_PRIVATE, "private " },
189 { FIELD_ATTRIBUTE_FAM_AND_ASSEM, "famandassem " },
190 { FIELD_ATTRIBUTE_ASSEMBLY, "assembly " },
191 { FIELD_ATTRIBUTE_FAMILY, "family " },
192 { FIELD_ATTRIBUTE_FAM_OR_ASSEM, "famorassem " },
193 { FIELD_ATTRIBUTE_PUBLIC, "public " },
197 static map_t field_flags_map [] = {
198 { FIELD_ATTRIBUTE_STATIC, "static " },
199 { FIELD_ATTRIBUTE_INIT_ONLY, "initonly " },
200 { FIELD_ATTRIBUTE_LITERAL, "literal " },
201 { FIELD_ATTRIBUTE_NOT_SERIALIZED, "notserialized " },
202 { FIELD_ATTRIBUTE_SPECIAL_NAME, "specialname " },
203 { FIELD_ATTRIBUTE_PINVOKE_IMPL, "FIXME:pinvokeimpl " },
207 static map_t element_type_map [] = {
208 { ELEMENT_TYPE_END , "end" },
209 { ELEMENT_TYPE_VOID , "void" },
210 { ELEMENT_TYPE_BOOLEAN , "bool" },
211 { ELEMENT_TYPE_CHAR , "char" },
212 { ELEMENT_TYPE_I1 , "sbyte" },
213 { ELEMENT_TYPE_U1 , "byte" },
214 { ELEMENT_TYPE_I2 , "int16" },
215 { ELEMENT_TYPE_U2 , "uint16" },
216 { ELEMENT_TYPE_I4 , "int32" },
217 { ELEMENT_TYPE_U4 , "uint32" },
218 { ELEMENT_TYPE_I8 , "int64" },
219 { ELEMENT_TYPE_U8 , "uint64" },
220 { ELEMENT_TYPE_R4 , "float32" },
221 { ELEMENT_TYPE_R8 , "float64" },
222 { ELEMENT_TYPE_STRING , "string" },
223 { ELEMENT_TYPE_TYPEDBYREF , "TypedByRef" },
224 { ELEMENT_TYPE_I , "native int" },
225 { ELEMENT_TYPE_U , "native unsigned int" },
226 { ELEMENT_TYPE_OBJECT , "object" },
233 * Returns a stringified version of a Field's flags
236 field_flags (guint32 f)
238 static char buffer [1024];
239 int access = f & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
243 strcat (buffer, map (access, field_access_map));
244 strcat (buffer, flags (f, field_flags_map));
245 return g_strdup (buffer);
250 * @ptr: pointer to decode from
251 * @len: result value is stored here.
253 * This routine decompresses 32-bit values as specified in the "Blob and
254 * Signature" section (22.2)
256 * Returns: updated pointer location
259 get_encoded_value (const char *_ptr, guint32 *len)
261 const unsigned char *ptr = (unsigned char *) _ptr;
262 unsigned char b = *ptr;
264 if ((b & 0x80) == 0){
267 } else if ((b & 0x40) == 0){
268 *len = ((b & 0x3f) << 8 | ptr [1]);
271 *len = ((b & 0x1f) << 24) |
280 get_typedef (metadata_t *m, int idx)
284 expand (&m->tables [META_TABLE_TYPEDEF], idx - 1, cols, CSIZE (cols));
286 return g_strdup_printf (
288 mono_metadata_string_heap (m, cols [2]),
289 mono_metadata_string_heap (m, cols [1]));
293 get_module (metadata_t *m, int idx)
298 * There MUST BE only one module in the Module table
302 expand (&m->tables [META_TABLE_MODULEREF], idx - 1, cols, CSIZE (cols));
304 return g_strdup (mono_metadata_string_heap (m, cols [6]));
308 get_assemblyref (metadata_t *m, int idx)
312 expand (&m->tables [META_TABLE_ASSEMBLYREF], idx - 1, cols, CSIZE (cols));
314 return g_strdup (mono_metadata_string_heap (m, cols [6]));
318 get_typeref (metadata_t *m, int idx)
323 guint32 rs_idx, table;
325 expand (&m->tables [META_TABLE_TYPEREF], idx - 1, cols, CSIZE (cols));
327 t = mono_metadata_string_heap (m, cols [1]);
328 s = mono_metadata_string_heap (m, cols [2]);
330 rs_idx = cols [0] >> 2;
333 * ECMA spec claims 3 bits
335 table = cols [0] & 3;
339 x = get_module (m, rs_idx);
340 ret = g_strdup_printf ("TODO:TypeRef-Module [%s] %s.%s", x, s, t);
344 case 1: /* ModuleRef */
345 ret = g_strdup_printf ("TODO:TypeRef-ModuleRef (%s.%s)", s, t);
349 * AssemblyRef (ECMA docs claim it is 3, but it looks to
350 * me like it is 2 (tokens are prefixed with 0x23)
352 x = get_assemblyref (m, rs_idx);
353 ret = g_strdup_printf ("[%s] %s.%s", x, s, t);
357 case 4: /* TypeRef */
358 ret = g_strdup_printf ("TODO:TypeRef-TypeRef: TYPEREF! (%s.%s)", s, t);
362 ret = g_strdup_printf ("Unknown table in TypeRef %d", table);
369 get_typedef_or_ref (metadata_t *m, guint32 dor_token)
371 char *temp = NULL, *s;
375 * low 2 bits contain encoding
377 table = dor_token & 0x03;
378 idx = dor_token >> 2;
381 case 0: /* TypeDef */
382 temp = get_typedef (m, idx);
383 s = g_strdup_printf ("%s", temp);
386 case 1: /* TypeRef */
387 temp = get_typeref (m, idx);
388 s = g_strdup_printf ("%s", temp);
391 case 2: /* TypeSpec */
392 s = g_strdup_printf ("TODO-TypeSpec: 0x%08x", idx);
396 g_error ("Unhandled encoding for typedef-or-ref coded index");
407 * get_encoded_typedef_or_ref:
408 * @m: metadata context
409 * @ptr: location to decode from.
410 * @result: pointer to string where resulting decoded string is stored
412 * result will point to a g_malloc()ed string.
414 * Returns: the new ptr to continue decoding
417 get_encoded_typedef_or_ref (metadata_t *m, const char *ptr, char **result)
421 ptr = get_encoded_value (ptr, &token);
423 *result = get_typedef_or_ref (m, token);
429 * methoddefref_signature:
430 * @m: metadata context
431 * @ptr: location to decode from.
432 * @result: pointer to string where resulting decoded string is stored
434 * This routine decodes into a string a MethodDef or a MethodRef.
436 * result will point to a g_malloc()ed string.
438 * Returns: the new ptr to continue decoding
441 methoddefref_signature (metadata_t *m, const char *ptr, char **result)
443 *result = g_strdup ("method-def-or-ref");
451 * Decodes a CustomMod (22.2.7)
453 * Returns: updated pointer location
456 get_custom_mod (metadata_t *m, const char *ptr, char **return_value)
460 if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
461 (*ptr == ELEMENT_TYPE_CMOD_REQD)){
463 ptr = get_encoded_typedef_or_ref (m, ptr, &s);
465 *return_value = g_strconcat ("CMOD ", s, NULL);
468 *return_value = NULL;
475 * @m: metadata context
476 * @ptr: location to decode from.
477 * @result: pointer to string where resulting decoded string is stored
479 * This routine returs in @result the stringified type pointed by @ptr.
482 * Returns: the new ptr to continue decoding
485 get_type (metadata_t *m, const char *ptr, char **result)
492 case ELEMENT_TYPE_BOOLEAN:
493 case ELEMENT_TYPE_CHAR:
494 case ELEMENT_TYPE_I1:
495 case ELEMENT_TYPE_U1:
496 case ELEMENT_TYPE_I2:
497 case ELEMENT_TYPE_U2:
498 case ELEMENT_TYPE_I4:
499 case ELEMENT_TYPE_U4:
500 case ELEMENT_TYPE_I8:
501 case ELEMENT_TYPE_U8:
502 case ELEMENT_TYPE_R4:
503 case ELEMENT_TYPE_R8:
505 case ELEMENT_TYPE_STRING:
506 case ELEMENT_TYPE_OBJECT:
507 *result = g_strdup (map (c, element_type_map));
510 case ELEMENT_TYPE_VALUETYPE:
511 case ELEMENT_TYPE_CLASS:
512 ptr = get_encoded_typedef_or_ref (m, ptr, result);
515 case ELEMENT_TYPE_FNPTR:
516 ptr = methoddefref_signature (m, ptr, result);
519 case ELEMENT_TYPE_SZARRAY: {
522 ptr = get_type (m, ptr, &child_type);
523 *result = g_strdup_printf ("%s[]", child_type);
528 case ELEMENT_TYPE_ARRAY:
530 *result = g_strdup ("ARRAY:TODO");
538 * Returns a stringified representation of a FieldSig (22.2.4)
541 field_signature (metadata_t *m, guint32 blob_signature)
543 char *allocated_modifier_string, *allocated_type_string;
544 const char *ptr = mono_metadata_blob_heap (m, blob_signature);
549 ptr = get_encoded_value (ptr, &len);
552 g_assert (*ptr == 0x06);
553 /* hex_dump (ptr, 0, len); */
556 ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
557 ptr = get_type (m, ptr, &allocated_type_string);
559 res = g_strdup_printf (
561 allocated_modifier_string ? allocated_modifier_string : "",
562 allocated_type_string);
564 if (allocated_modifier_string)
565 g_free (allocated_modifier_string);
566 if (allocated_type_string)
567 g_free (allocated_modifier_string);
574 * @m: metadata context
575 * @token: token to decode
577 * decodes the literal indexed by @token.
580 decode_literal (metadata_t *m, guint32 token)
582 return g_strdup ("LITERAL_VALUE");
587 * @m: metadata context
588 * @start: starting index into the Field Table.
589 * @end: ending index into Field table.
591 * This routine displays all the decoded fields from @start to @end
594 dis_field_list (metadata_t *m, guint32 start, guint32 end)
596 metadata_tableinfo_t *t = &m->tables [META_TABLE_FIELD];
600 if (end > t->rows + 1){
601 fprintf (output, "ERROR index out of range in fields");
605 for (i = start; i < end; i++){
608 expand (t, i, cols, CSIZE (cols));
609 sig = field_signature (m, cols [2]);
610 flags = field_flags (cols [0]);
612 if (cols [0] & FIELD_ATTRIBUTE_LITERAL){
613 char *lit = decode_literal (m, cols [2]);
615 fprintf (output, " .field %s %s %s = ",
617 mono_metadata_string_heap (m, cols [1]));
618 fprintf (output, "%s\n", lit);
621 fprintf (output, " .field %s %s %s\n",
623 mono_metadata_string_heap (m, cols [1]));
629 static map_t method_access_map [] = {
630 { METHOD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
631 { METHOD_ATTRIBUTE_PRIVATE, "private" },
632 { METHOD_ATTRIBUTE_FAM_AND_ASSEM, "famandassem" },
633 { METHOD_ATTRIBUTE_ASSEM, "assembly " },
634 { METHOD_ATTRIBUTE_FAMILY, "family " },
635 { METHOD_ATTRIBUTE_FAM_OR_ASSEM, "famorassem " },
636 { METHOD_ATTRIBUTE_PUBLIC, "public " },
640 static map_t method_flags_map [] = {
641 { METHOD_ATTRIBUTE_STATIC, "static " },
642 { METHOD_ATTRIBUTE_FINAL, "final " },
643 { METHOD_ATTRIBUTE_VIRTUAL, "virtual " },
644 { METHOD_ATTRIBUTE_HIDE_BY_SIG, "hidebysig " },
645 { METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK, "newslot " },
646 { METHOD_ATTRIBUTE_ABSTRACT, "abstract " },
647 { METHOD_ATTRIBUTE_SPECIAL_NAME, "specialname " },
648 { METHOD_ATTRIBUTE_RT_SPECIAL_NAME, "rtspecialname " },
649 { METHOD_ATTRIBUTE_PINVOKE_IMPL, "pinvokeimpl " },
650 { METHOD_ATTRIBUTE_UNMANAGED_EXPORT, "export " },
651 { METHOD_ATTRIBUTE_HAS_SECURITY, "hassecurity" },
652 { METHOD_ATTRIBUTE_REQUIRE_SEC_OBJECT, "requiresecobj" },
659 * Returns a stringified version of the Method's flags
662 method_flags (guint32 f)
664 GString *str = g_string_new ("");
665 int access = f & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
668 g_string_append (str, map (access, method_access_map));
669 g_string_append (str, flags (f, method_flags_map));
672 g_string_free (str, FALSE);
677 static map_t method_impl_map [] = {
678 { METHOD_IMPL_ATTRIBUTE_IL, "cil " },
679 { METHOD_IMPL_ATTRIBUTE_NATIVE, "native " },
680 { METHOD_IMPL_ATTRIBUTE_OPTIL, "optil " },
681 { METHOD_IMPL_ATTRIBUTE_RUNTIME, "runtime " },
685 static map_t managed_type_map [] = {
686 { METHOD_IMPL_ATTRIBUTE_UNMANAGED, "unmanaged " },
687 { METHOD_IMPL_ATTRIBUTE_MANAGED, "managed " },
691 static map_t managed_impl_flags [] = {
692 { METHOD_IMPL_ATTRIBUTE_FORWARD_REF, "fwdref " },
693 { METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG, "preservesig " },
694 { METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL, "internalcall " },
695 { METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED, "synchronized " },
696 { METHOD_IMPL_ATTRIBUTE_NOINLINING, "noinline " },
701 method_impl_flags (guint32 f)
703 GString *str = g_string_new ("");
705 int code_type = f & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
706 int managed_type = f & METHOD_IMPL_ATTRIBUTE_MANAGED_MASK;
708 g_string_append (str, map (code_type, method_impl_map));
709 g_string_append (str, map (managed_type, managed_type_map));
710 g_string_append (str, flags (f, managed_impl_flags));
713 g_string_free (str, FALSE);
719 * @m: metadata context
720 * @ptr: location to decode from.
721 * @result: pointer to string where resulting decoded string is stored
723 * This routine returns in @result the stringified RetType (22.2.11)
725 * Returns: the new ptr to continue decoding.
728 get_ret_type (metadata_t *m, const char *ptr, char **ret_type)
730 GString *str = g_string_new ("");
732 char *allocated_type_string;
734 ptr = get_custom_mod (m, ptr, &mod);
736 g_string_append (str, mod);
737 g_string_append_c (str, ' ');
741 if (*ptr == ELEMENT_TYPE_TYPEDBYREF){
742 /* TODO: what does `typedbyref' mean? */
743 g_string_append (str, "/* FIXME: What does this mean? */ typedbyref ");
745 } else if (*ptr == ELEMENT_TYPE_VOID){
746 g_string_append (str, "void");
749 if (*ptr == ELEMENT_TYPE_BYREF){
750 g_string_append (str, "[out] ");
754 ptr = get_type (m, ptr, &allocated_type_string);
755 g_string_append (str, allocated_type_string);
756 g_free (allocated_type_string);
759 *ret_type = str->str;
760 g_string_free (str, FALSE);
766 get_param (metadata_t *m, const char *ptr, char **retval)
768 GString *str = g_string_new ("");
769 char *allocated_mod_string, *allocated_type_string;
771 ptr = get_custom_mod (m, ptr, &allocated_mod_string);
772 if (allocated_mod_string){
773 g_string_append (str, allocated_mod_string);
774 g_string_append_c (str, ' ');
775 g_free (allocated_mod_string);
778 if (*ptr == ELEMENT_TYPE_TYPEDBYREF){
779 g_string_append (str, "/*FIXME: what does typedbyref mean? */ typedbyref ");
782 if (*ptr == ELEMENT_TYPE_BYREF){
783 g_string_append (str, "[out] ");
786 ptr = get_type (m, ptr, &allocated_type_string);
787 g_string_append (str, allocated_type_string);
788 g_free (allocated_type_string);
792 g_string_free (str, FALSE);
803 static MethodSignature *
804 parse_method_signature (metadata_t *m, guint32 blob_signature)
806 GString *res = g_string_new ("");
807 const char *ptr = mono_metadata_blob_heap (m, blob_signature);
808 MethodSignature *ms = g_new0 (MethodSignature, 1);
812 ptr = get_encoded_value (ptr, &len);
813 fprintf (output, " // SIG: ");
814 hex_dump (ptr, 0, -len);
815 fprintf (output, "\n");
819 ptr = get_encoded_value (ptr, &ms->param_count);
820 ptr = get_ret_type (m, ptr, &ms->ret_type);
821 ms->param = g_new (char *, ms->param_count);
823 for (i = 0; i < ms->param_count; i++)
824 ptr = get_param (m, ptr, &(ms->param [i]));
827 g_string_free (res, FALSE);
832 free_method_signature (MethodSignature *ms)
836 for (i = 0; i < ms->param_count; i++)
837 g_free (ms->param [i]);
839 g_free (ms->ret_type);
843 static map_t param_map [] = {
844 { PARAM_ATTRIBUTE_IN, "[in] " },
845 { PARAM_ATTRIBUTE_OUT, "[out] " },
846 { PARAM_ATTRIBUTE_OPTIONAL, "optional " },
847 { PARAM_ATTRIBUTE_HAS_DEFAULT, "hasdefault " },
848 { PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL, "fieldmarshal " },
853 param_flags (guint32 f)
855 return g_strdup (map (f, param_map));
860 * @m: metadata context
861 * @start: starting index into the Method Table.
862 * @end: ending index into Method table.
864 * This routine displays the methods in the Method Table from @start to @end
867 dis_method_list (metadata_t *m, guint32 start, guint32 end)
869 metadata_tableinfo_t *t = &m->tables [META_TABLE_METHOD];
870 metadata_tableinfo_t *p = &m->tables [META_TABLE_PARAM];
872 guint32 cols_next [6];
873 guint32 param_cols [3];
876 if (end > t->rows + 1){
877 fprintf (output, "ERROR index out of range in methods");
881 for (i = start; i < end; i++){
883 char *flags, *impl_flags;
885 expand (t, i, cols, CSIZE (cols));
886 expand (t, i + 1, cols_next, CSIZE (cols_next));
888 flags = method_flags (cols [2]);
889 impl_flags = method_impl_flags (cols [1]);
891 ms = parse_method_signature (m, cols [4]);
899 mono_metadata_string_heap (m, cols [3]));
900 if (ms->param_count > 0){
903 fprintf (output, "(\n");
904 for (i = 0; i < ms->param_count; i++){
907 expand (p, i, param_cols, CSIZE (param_cols));
908 pf = param_flags (param_cols [0]);
910 output, "\t\t%s %s %s%s", pf, ms->param [i],
911 mono_metadata_string_heap (m, param_cols [2]),
912 (i+1 == ms->param_count) ? ")" : ",\n");
918 fprintf (output, " %s\n", impl_flags);
922 fprintf (output, " {\n");
923 fprintf (output, " // Method begins at RVA 0x%x\n", cols [0]);
924 fprintf (output, " // Param: %d %d (%d)\n", cols [5], cols_next [5], ms->param_count);
925 fprintf (output, " }\n\n");
926 free_method_signature (ms);
932 * @m: metadata context
933 * @n: index of type to disassemble
935 * Disassembles the type whose index in the TypeDef table is @n.
938 dis_type (metadata_t *m, int n)
940 metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
942 guint32 cols_next [6];
945 expand (t, n, cols, CSIZE (cols));
946 expand (t, n + 1, cols_next, CSIZE (cols_next));
948 fprintf (output, ".namespace %s\n{\n", mono_metadata_string_heap (m, cols [2]));
949 name = mono_metadata_string_heap (m, cols [1]);
951 if ((cols [0] & TYPE_ATTRIBUTE_CLASS_SEMANTIC_MASK) == TYPE_ATTRIBUTE_CLASS){
952 char *base = get_typedef_or_ref (m, cols [3]);
953 fprintf (output, " .class %s%s\n", typedef_flags (cols [0]), name);
954 fprintf (output, " \textends %s\n", base);
957 fprintf (output, " .class interface %s%s\n", typedef_flags (cols [0]), name);
959 fprintf (output, " {\n");
962 * The value in the table is always valid, we know we have fields
963 * if the value stored is different than the next record.
965 if (cols [4] != cols_next [4])
966 dis_field_list (m, cols [4] - 1, cols_next [4] - 1);
967 fprintf (output, "\n");
968 if (cols [4] != cols_next [5])
969 dis_method_list (m, cols [5] - 1, cols_next [5] - 1);
971 fprintf (output, " }\n}\n\n");
975 dump_table_typeref (metadata_t *m)
977 metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEREF];
980 fprintf (output, "Typeref Table\n");
982 for (i = 1; i <= t->rows; i++){
983 char *s = get_typeref (m, i);
985 fprintf (output, "%d: %s\n", i, s);
988 fprintf (output, "\n");
992 dump_table_typedef (metadata_t *m)
994 metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
997 fprintf (output, "Typedef Table\n");
999 for (i = 1; i <= t->rows; i++){
1000 char *s = get_typedef (m, i);
1002 fprintf (output, "%d: %s\n", i, s);
1005 fprintf (output, "\n");
1009 dump_table_assemblyref (metadata_t *m)
1011 metadata_tableinfo_t *t = &m->tables [META_TABLE_ASSEMBLYREF];
1014 fprintf (output, "AssemblyRef Table\n");
1016 for (i = 0; i < t->rows; i++){
1019 expand (t, i, cols, CSIZE (cols));
1020 fprintf (output, "%d: %d.%d.%d.%d %s\n", i,
1021 cols [0], cols [1], cols [2], cols [3],
1022 mono_metadata_string_heap (m, cols [6]));
1024 fprintf (output, "\n");
1028 dump_table_param (metadata_t *m)
1030 metadata_tableinfo_t *t = &m->tables [META_TABLE_PARAM];
1033 fprintf (output, "Param Table\n");
1035 for (i = 0; i < t->rows; i++){
1038 expand (t, i, cols, CSIZE (cols));
1039 fprintf (output, "%d: 0x%04x %d %s\n",
1042 mono_metadata_string_heap (m, cols [2]));
1044 fprintf (output, "\n");
1049 * @m: metadata context
1051 * disassembles all types in the @m context
1054 dis_types (metadata_t *m)
1056 metadata_tableinfo_t *t = &m->tables [META_TABLE_TYPEDEF];
1059 for (i = 0; i < t->rows; i++)
1065 * @file: file containing CIL code.
1067 * Disassembles the @file file.
1070 disassemble_file (const char *file)
1072 enum MonoAssemblyOpenStatus status;
1074 cli_image_info_t *ii;
1078 ass = mono_assembly_open (file, &status);
1080 fprintf (stderr, "Error while trying to process %s\n", file);
1084 ii = ass->image_info;
1085 m = &ii->cli_metadata;
1087 if (dump_table != -1){
1088 switch (dump_table){
1089 case META_TABLE_TYPEDEF:
1090 dump_table_typedef (m);
1092 case META_TABLE_TYPEREF:
1093 dump_table_typeref (m);
1095 case META_TABLE_ASSEMBLYREF:
1096 dump_table_assemblyref (m);
1098 case META_TABLE_PARAM:
1099 dump_table_param (m);
1102 g_error ("Internal error");
1105 dump_header_data (ass);
1107 dis_directive_assemblyref (m);
1108 dis_directive_assembly (m);
1112 mono_assembly_close (ass);
1118 fprintf (stderr, "Usage is: monodis [--typeref][--typedef][--assemblyref] file ..\n");
1123 main (int argc, char *argv [])
1125 GList *input_files = NULL, *l;
1129 for (i = 1; i < argc; i++){
1130 if (argv [i][0] == '-'){
1131 if (argv [i][1] == 'h')
1133 else if (argv [i][1] == 'd')
1134 dump_header_data_p = TRUE;
1135 else if (strcmp (argv [i], "--help") == 0)
1137 else if (strcmp (argv [i], "--typeref") == 0)
1138 dump_table = META_TABLE_TYPEREF;
1139 else if (strcmp (argv [i], "--typedef") == 0)
1140 dump_table = META_TABLE_TYPEDEF;
1141 else if (strcmp (argv [i], "--assemblyref") == 0)
1142 dump_table = META_TABLE_ASSEMBLYREF;
1143 else if (strcmp (argv [i], "--param") == 0)
1144 dump_table = META_TABLE_PARAM;
1146 input_files = g_list_append (input_files, argv [i]);
1149 if (input_files == NULL)
1152 for (l = input_files; l; l = l->next)
1153 disassemble_file (l->data);