#include <config.h>
#include <glib.h>
#include <stdio.h>
+#include <math.h>
#ifdef HAVE_WCHAR_H
#include <wchar.h>
#endif
#include "dump.h"
#include "dis-cil.h"
#include "mono/metadata/opcodes.h"
+#include "mono/metadata/class-internals.h"
+#include "mono/utils/mono-compiler.h"
-/*
- * Strings on the US heap are encoded using UTF-16. Poor man's
- * UTF-16 to UTF-8. I know its broken, use libunicode later.
- */
-static char *
-get_encoded_user_string (const char *ptr)
+#ifndef HAVE_ISINF
+
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+int isinf (double);
+int
+isinf (double num)
{
- GString *res = g_string_new ("");
- char *result;
- int len, i;
+ fpclass_t klass;
- len = mono_metadata_decode_blob_size (ptr, &ptr);
+ klass = fpclass (num);
+ if (klass == FP_NINF)
+ return -1;
- for (i = 0; i < len; i += 2) {
- switch (ptr [i]) {
- case '\a': g_string_append (res, "\\a"); break;
- case '\b': g_string_append (res, "\\b"); break;
- case '\f': g_string_append (res, "\\f"); break;
- case '\n': g_string_append (res, "\\n"); break;
- case '\r': g_string_append (res, "\\r"); break;
- case '\t': g_string_append (res, "\\t"); break;
- case '\v': g_string_append (res, "\\v"); break;
- case '\"': g_string_append (res, "\\\""); break;
- case '\'': g_string_append (res, "\\'"); break;
- case '\\': g_string_append (res, "\\\\"); break;
- default: g_string_append_c (res, ptr [i]); break;
- }
- }
+ if (klass == FP_PINF)
+ return 1;
- result = res->str;
- g_string_free (res, FALSE);
-
- return result;
+ return 0;
}
+#else
+#error "Don't know how to implement isinf for this platform."
+#endif
+
+#endif
#define CODE_INDENT g_assert (indent_level < 512); \
indent[indent_level*2] = ' '; \
indent[indent_level*2] = 0;
void
-dissasemble_cil (MonoImage *m, MonoMethodHeader *mh)
+disassemble_cil (MonoImage *m, MonoMethodHeader *mh, MonoGenericContainer *container)
{
const unsigned char *start = mh->code;
int size = mh->code_size;
const unsigned char *ptr = start;
const MonoOpcode *entry;
char indent[1024];
- int i, indent_level = 0;
+ int i, j, indent_level = 0;
gboolean in_fault = 0;
const char *clause_names[] = {"catch", "filter", "finally", "", "fault"};
gboolean *trys = NULL;
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 jcl mh->clauses [j]
#define cl mh->clauses [i]
- if (pcl.try_offset != cl.try_offset || pcl.try_len != cl.try_len)
- trys [i] = 1;
-#undef pcl
+ trys [i] = 1;
+ for (j = 0; j < i; j++) {
+ if (cl.try_offset == jcl.try_offset && cl.try_len == jcl.try_len) {
+ trys [i] = 0;
+ break;
+ }
+ }
+#undef jcl
#undef cl
}
}
fprintf (output, "\t%s} { // %d\n", indent, i);
} else {
char * klass = mh->clauses[i].flags ? g_strdup ("") :
- dis_stringify_token (m, mh->clauses[i].token_or_filter);
+ 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);
if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
in_fault = 1;
}
- if (mh->clauses[i].flags == 1 && ptr == start + mh->clauses[i].token_or_filter) {
+ 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;
}
if (in_fault && entry->opval == 0xDC)
fprintf (output, " %s", "endfault");
else
- fprintf (output, " %s ", mono_opcode_names [i]);
+ 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, container);
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, container);
fprintf (output, "%s", s);
g_free (s);
ptr += 4;
case MonoInlineR: {
double r;
+ int inf;
readr8 (ptr, &r);
- fprintf (output, "%g", r);
+ inf = isinf (r);
+ if (inf == -1)
+ fprintf (output, "(00 00 00 00 00 00 f0 ff)"); /* negative infinity */
+ else if (inf == 1)
+ fprintf (output, "(00 00 00 00 00 00 f0 7f)"); /* positive infinity */
+ else if (isnan (r))
+ fprintf (output, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
+ else {
+ char *str = stringify_double (r);
+ fprintf (output, str);
+ g_free (str);
+ }
ptr += 8;
break;
}
case MonoInlineString: {
guint32 token = read32 (ptr);
-
- char *s = get_encoded_user_string (
- mono_metadata_user_string (m, token & 0xffffff));
+ const char *us_ptr = mono_metadata_user_string (m, token & 0xffffff);
+ int len = mono_metadata_decode_blob_size (us_ptr, (const char**)&us_ptr);
+
+ char *s = get_encoded_user_string_or_bytearray ((const guchar*)us_ptr, len);
/*
* See section 23.1.4 on the encoding of the #US heap
*/
- fprintf (output, "\"%s\"", s);
+ fprintf (output, "%s", s);
g_free (s);
ptr += 4;
break;
ptr += 4;
endswitch = ptr + sizeof (guint32) * count;
- fprintf (output, "(\n");
+ fprintf (output, count > 0 ? "(\n" : "( )");
CODE_INDENT;
for (n = 0; n < count; n++){
fprintf (output, "\t%sIL_%04x%s", indent,
- endswitch-start+read32 (ptr),
- n == count - 1 ? ")" : ",\n");
+ (int)(endswitch-start+read32 (ptr)),
+ n == count - 1 ? ")" : ",\n");
ptr += 4;
}
CODE_UNINDENT;
guint32 token = read32 (ptr);
char *s;
- s = get_token (m, token);
+ s = get_token (m, token, container);
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, container);
fprintf (output, "%s", s);
g_free (s);
ptr += 4;
case MonoShortInlineBrTarget: {
signed char x = *ptr;
- fprintf (output, "IL_%04x\n", ptr - start + 1 + x);
+ fprintf (output, "IL_%04x\n", (int)(ptr - start + 1 + x));
ptr++;
break;
}
case MonoShortInlineR: {
float f;
+ int inf;
+
readr4 (ptr, &f);
- fprintf (output, "%g", (double) f);
+ inf = isinf (f);
+ if (inf == -1)
+ fprintf (output, "(00 00 80 ff)"); /* negative infinity */
+ else if (inf == 1)
+ fprintf (output, "(00 00 80 7f)"); /* positive infinity */
+ else if (isnan (f))
+ fprintf (output, "(00 00 c0 ff)"); /* NaN */
+ else {
+ char *str = stringify_double ((double) f);
+ fprintf (output, str);
+ g_free (str);
+ }
ptr += 4;
break;
}