#include <config.h>
#include <glib.h>
#include <stdio.h>
+#ifdef HAVE_WCHAR_H
#include <wchar.h>
+#endif
#include "meta.h"
#include "get.h"
#include "dump.h"
static char *
get_encoded_user_string (const char *ptr)
{
- char *res;
+ char *res, *result;
int len, i, j;
len = mono_metadata_decode_blob_size (ptr, &ptr);
res [j] = ptr [i];
res [j] = 0;
-
- return res;
+
+ result = g_strescape (res, NULL);
+ g_free (res);
+
+ return result;
}
#define CODE_INDENT g_assert (indent_level < 512); \
indent[indent_level*2] = 0;
void
-dissasemble_cil (MonoMetadata *m, MonoMethodHeader *mh)
+dissasemble_cil (MonoImage *m, MonoMethodHeader *mh, MonoGenericContext *context)
{
const unsigned char *start = mh->code;
int size = mh->code_size;
const MonoOpcode *entry;
char indent[1024];
int i, indent_level = 0;
- char *clause_names[] = {"catch", "filter", "finally", "fault"};
-
+ gboolean in_fault = 0;
+ const char *clause_names[] = {"catch", "filter", "finally", "", "fault"};
+ gboolean *trys = NULL;
indent [0] = 0;
+#ifdef DEBUG
+ for (i = 0; i < mh->num_clauses; ++i) {
+#define clause mh->clauses [i]
+ g_print ("/* out clause %d: from %d len=%d, handler at %d, %d */\n",
+ clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);
+#undef clause
+ }
+#endif
+
+ if (mh->num_clauses) {
+ trys = g_malloc0 (sizeof (gboolean) * mh->num_clauses);
+ trys [0] = 1;
+ for (i=1; i < mh->num_clauses; ++i) {
+#define pcl mh->clauses [i-1]
+#define cl mh->clauses [i]
+ if (pcl.try_offset != cl.try_offset || pcl.try_len != cl.try_len)
+ trys [i] = 1;
+#undef pcl
+#undef cl
+ }
+ }
+
while (ptr < end){
for (i = mh->num_clauses - 1; i >= 0 ; --i) {
- if ((mh->clauses[i].flags == 0 || mh->clauses[i].flags == 2) && ptr == start + mh->clauses[i].try_offset) {
+ if (ptr == start + mh->clauses[i].try_offset && trys [i]) {
fprintf (output, "\t%s.try { // %d\n", indent, i);
CODE_INDENT;
}
+
if (ptr == start + mh->clauses[i].handler_offset) {
- char * klass = mh->clauses[i].flags ? g_strdup ("") : dis_stringify_token (m, mh->clauses[i].token_or_filter);
- fprintf (output, "\t%s%s %s { // %d\n", indent, clause_names [mh->clauses[i].flags], klass, i);
+ if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+ CODE_UNINDENT;
+ fprintf (output, "\t%s} { // %d\n", indent, i);
+ } else {
+ char * klass = mh->clauses[i].flags ? g_strdup ("") :
+ dis_stringify_object_with_class (m, mh->clauses[i].data.catch_class,
+ FALSE, FALSE);
+ fprintf (output, "\t%s%s %s { // %d\n", indent,
+ clause_names [mh->clauses[i].flags], klass, i);
+ g_free (klass);
+ }
CODE_INDENT;
- g_free (klass);
- }
+ if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
+ in_fault = 1;
+ }
+ if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER && ptr == start + mh->clauses[i].data.filter_offset) {
+ fprintf (output, "\t%s%s {\n", indent, clause_names[1]);
+ CODE_INDENT;
+ }
}
fprintf (output, "\t%sIL_%04x: ", indent, (int) (ptr - start));
i = *ptr;
}
entry = &mono_opcodes [i];
- fprintf (output, "%s ", mono_opcode_names [i]);
+ if (in_fault && entry->opval == 0xDC)
+ fprintf (output, " %s", "endfault");
+ else
+ fprintf (output, " %s ", mono_opcode_name (i));
ptr++;
switch (entry->argument){
case MonoInlineBrTarget: {
guint32 token = read32 (ptr);
char *s;
- s = get_field (m, token);
+ s = get_field (m, token, context);
fprintf (output, "%s", s);
g_free (s);
ptr += 4;
guint32 token = read32 (ptr);
char *s;
- s = get_method (m, token);
+ s = get_method (m, token, context);
fprintf (output, "%s", s);
g_free (s);
ptr += 4;
break;
case MonoInlineR: {
- double r = *(double *) ptr;
+ double r;
+ readr8 (ptr, &r);
fprintf (output, "%g", r);
ptr += 8;
break;
case MonoInlineSwitch: {
guint32 count = read32 (ptr);
const unsigned char *endswitch;
- guint32 i;
+ guint32 n;
ptr += 4;
endswitch = ptr + sizeof (guint32) * count;
- fprintf (output, "(\n");
+ fprintf (output, count > 0 ? "(\n" : "( )");
CODE_INDENT;
- for (i = 0; i < count; i++){
+ for (n = 0; n < count; n++){
fprintf (output, "\t%sIL_%04x%s", indent,
endswitch-start+read32 (ptr),
- i == count - 1 ? ")" : ",\n");
+ n == count - 1 ? ")" : ",\n");
ptr += 4;
}
CODE_UNINDENT;
guint32 token = read32 (ptr);
char *s;
- s = get_token (m, token);
+ s = get_token (m, token, context);
fprintf (output, "%s", s);
g_free (s);
case MonoInlineType: {
guint32 token = read32 (ptr);
- char *s = get_token_type (m, token);
+ char *s = get_token_type (m, token, context);
fprintf (output, "%s", s);
g_free (s);
ptr += 4;
}
case MonoInlineVar: {
- gint16 var_idx = read16 (ptr);
+ guint16 var_idx = read16 (ptr);
- fprintf (output, "variable-%d\n", var_idx);
+ fprintf (output, "%d\n", var_idx);
ptr += 2;
break;
}
}
case MonoShortInlineR: {
- float f = *(float *) ptr;
+ float f;
+ readr4 (ptr, &f);
fprintf (output, "%g", (double) f);
ptr += 4;
}
case MonoShortInlineVar: {
- signed char x = *ptr;
+ unsigned char x = *ptr;
fprintf (output, "%d", (int) x);
ptr++;
fprintf (output, "\n");
for (i = 0; i < mh->num_clauses; ++i) {
- if ((mh->clauses[i].flags == 0 || mh->clauses[i].flags == 2) && ptr == start + mh->clauses[i].try_offset + mh->clauses[i].try_len) {
+ if (ptr == start + mh->clauses[i].try_offset + mh->clauses[i].try_len && trys [i]) {
CODE_UNINDENT;
fprintf (output, "\t%s} // end .try %d\n", indent, i);
}
if (ptr == start + mh->clauses[i].handler_offset + mh->clauses[i].handler_len) {
CODE_UNINDENT;
fprintf (output, "\t%s} // end handler %d\n", indent, i);
+ if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
+ in_fault = 0;
}
}
}
+ if (trys)
+ g_free (trys);
}