#include <mono/metadata/object.h>
#include <mono/metadata/verify.h>
+#include <mono/metadata/opcodes.h>
#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/reflection.h>
#include <mono/metadata/mono-endian.h>
#include <string.h>
#include <signal.h>
(list) = g_slist_prepend ((list), vinfo); \
} while (0)
-static const char*
+static const char* const
valid_cultures[] = {
"ar-SA", "ar-IQ", "ar-EG", "ar-LY",
"ar-DZ", "ar-MA", "ar-TN", "ar-OM",
}
static int
-is_valid_blob (MonoImage *image, guint32 index, int notnull)
+is_valid_blob (MonoImage *image, guint32 blob_index, int notnull)
{
guint32 size;
- const char *p, *send;
+ const char *p, *blob_end;
- if (index >= image->heap_blob.size)
+ if (blob_index >= image->heap_blob.size)
return 0;
- p = mono_metadata_blob_heap (image, index);
- size = mono_metadata_decode_blob_size (p, &send);
- if (index + size + (send-p) > image->heap_blob.size)
+ p = mono_metadata_blob_heap (image, blob_index);
+ size = mono_metadata_decode_blob_size (p, &blob_end);
+ if (blob_index + size + (blob_end-p) > image->heap_blob.size)
return 0;
if (notnull && !size)
return 0;
}
static const char*
-is_valid_string (MonoImage *image, guint32 index, int notnull)
+is_valid_string (MonoImage *image, guint32 str_index, int notnull)
{
- const char *p, *send, *res;
+ const char *p, *blob_end, *res;
- if (index >= image->heap_strings.size)
+ if (str_index >= image->heap_strings.size)
return NULL;
- res = p = mono_metadata_string_heap (image, index);
- send = mono_metadata_string_heap (image, image->heap_strings.size - 1);
+ res = p = mono_metadata_string_heap (image, str_index);
+ blob_end = mono_metadata_string_heap (image, image->heap_strings.size - 1);
if (notnull && !*p)
return 0;
/*
* FIXME: should check it's a valid utf8 string, too.
*/
- while (p <= send) {
+ while (p <= blob_end) {
if (!*p)
return res;
++p;
while (ip < end) {
ip_offset = ip - header->code;
- g_print ("IL_%04x: %02x\n", ip_offset, *ip);
+ g_print ("IL_%04x: %02x %s\n", ip_offset, *ip, mono_opcode_names [*ip]);
if (start || !(code [ip_offset].flags & CODE_SEEN)) {
if (start) {
code [ip_offset].stack_count = 0;
g_free (code);
return list;
}
+
+typedef struct {
+ const char *name;
+ guint64 offset;
+} FieldDesc;
+
+typedef struct {
+ const char *name;
+ const FieldDesc *fields;
+} ClassDesc;
+
+static const FieldDesc
+typebuilder_fields[] = {
+ {"tname", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, name)},
+ {"nspace", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, nspace)},
+ {"parent", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, parent)},
+ {"interfaces", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, interfaces)},
+ {"methods", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, methods)},
+ {"properties", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, properties)},
+ {"fields", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, fields)},
+ {"attrs", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, attrs)},
+ {"table_idx", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, table_idx)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+modulebuilder_fields[] = {
+ {"types", G_STRUCT_OFFSET (MonoReflectionModuleBuilder, types)},
+ {"table_idx", G_STRUCT_OFFSET (MonoReflectionModuleBuilder, table_idx)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+assemblybuilder_fields[] = {
+ {"entry_point", G_STRUCT_OFFSET (MonoReflectionAssemblyBuilder, entry_point)},
+ {"modules", G_STRUCT_OFFSET (MonoReflectionAssemblyBuilder, modules)},
+ {"name", G_STRUCT_OFFSET (MonoReflectionAssemblyBuilder, name)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+ctorbuilder_fields[] = {
+ {"ilgen", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, ilgen)},
+ {"parameters", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, parameters)},
+ {"attrs", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, attrs)},
+ {"iattrs", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, iattrs)},
+ {"table_idx", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, table_idx)},
+ {"call_conv", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, call_conv)},
+ {"type", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, type)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+methodbuilder_fields[] = {
+ {"mhandle", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, mhandle)},
+ {"rtype", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, rtype)},
+ {"parameters", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, parameters)},
+ {"attrs", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, attrs)},
+ {"iattrs", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, iattrs)},
+ {"name", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, name)},
+ {"table_idx", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, table_idx)},
+ {"code", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, code)},
+ {"ilgen", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, ilgen)},
+ {"type", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, type)},
+ {"pinfo", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, pinfo)},
+ {"pi_dll", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, dll)},
+ {"pi_entry", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, dllentry)},
+ {"ncharset", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, charset)},
+ {"native_cc", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, native_cc)},
+ {"call_conv", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, call_conv)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+fieldbuilder_fields[] = {
+ {"attrs", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, attrs)},
+ {"type", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, type)},
+ {"name", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, name)},
+ {"def_value", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, def_value)},
+ {"offset", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, offset)},
+ {"table_idx", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, table_idx)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+propertybuilder_fields[] = {
+ {"attrs", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, attrs)},
+ {"name", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, name)},
+ {"type", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, type)},
+ {"parameters", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, parameters)},
+ {"def_value", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, def_value)},
+ {"set_method", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, set_method)},
+ {"get_method", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, get_method)},
+ {"table_idx", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, table_idx)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+ilgenerator_fields[] = {
+ {"code", G_STRUCT_OFFSET (MonoReflectionILGen, code)},
+ {"mbuilder", G_STRUCT_OFFSET (MonoReflectionILGen, mbuilder)},
+ {"code_len", G_STRUCT_OFFSET (MonoReflectionILGen, code_len)},
+ {"max_stack", G_STRUCT_OFFSET (MonoReflectionILGen, max_stack)},
+ {"cur_stack", G_STRUCT_OFFSET (MonoReflectionILGen, cur_stack)},
+ {"locals", G_STRUCT_OFFSET (MonoReflectionILGen, locals)},
+ {"ex_handlers", G_STRUCT_OFFSET (MonoReflectionILGen, ex_handlers)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+ilexinfo_fields[] = {
+ {"handlers", G_STRUCT_OFFSET (MonoILExceptionInfo, handlers)},
+ {"start", G_STRUCT_OFFSET (MonoILExceptionInfo, start)},
+ {"len", G_STRUCT_OFFSET (MonoILExceptionInfo, len)},
+ {"end", G_STRUCT_OFFSET (MonoILExceptionInfo, label)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+ilexblock_fields[] = {
+ {"extype", G_STRUCT_OFFSET (MonoILExceptionBlock, extype)},
+ {"type", G_STRUCT_OFFSET (MonoILExceptionBlock, type)},
+ {"start", G_STRUCT_OFFSET (MonoILExceptionBlock, start)},
+ {"len", G_STRUCT_OFFSET (MonoILExceptionBlock, len)},
+ {"filter_offset", G_STRUCT_OFFSET (MonoILExceptionBlock, filter_offset)},
+ {NULL, 0}
+};
+
+static const ClassDesc
+emit_classes_to_check [] = {
+ {"TypeBuilder", typebuilder_fields},
+ {"ModuleBuilder", modulebuilder_fields},
+ {"AssemblyBuilder", assemblybuilder_fields},
+ {"ConstructorBuilder", ctorbuilder_fields},
+ {"MethodBuilder", methodbuilder_fields},
+ {"FieldBuilder", fieldbuilder_fields},
+ {"PropertyBuilder", propertybuilder_fields},
+ {"ILGenerator", ilgenerator_fields},
+ {"ILExceptionBlock", ilexblock_fields},
+ {"ILExceptionInfo", ilexinfo_fields},
+ {NULL, NULL}
+};
+
+static const FieldDesc
+monoevent_fields[] = {
+ {"klass", G_STRUCT_OFFSET (MonoReflectionEvent, klass)},
+ {"handle", G_STRUCT_OFFSET (MonoReflectionEvent, event)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+monoproperty_fields[] = {
+ {"klass", G_STRUCT_OFFSET (MonoReflectionProperty, klass)},
+ {"prop", G_STRUCT_OFFSET (MonoReflectionProperty, property)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+monofield_fields[] = {
+ {"klass", G_STRUCT_OFFSET (MonoReflectionField, klass)},
+ {"fhandle", G_STRUCT_OFFSET (MonoReflectionField, field)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+monomethodinfo_fields[] = {
+ {"parent", G_STRUCT_OFFSET (MonoMethodInfo, parent)},
+ {"ret", G_STRUCT_OFFSET (MonoMethodInfo, ret)},
+ {"name", G_STRUCT_OFFSET (MonoMethodInfo, name)},
+ {"attrs", G_STRUCT_OFFSET (MonoMethodInfo, attrs)},
+ {"iattrs", G_STRUCT_OFFSET (MonoMethodInfo, implattrs)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+monopropertyinfo_fields[] = {
+ {"parent", G_STRUCT_OFFSET (MonoPropertyInfo, parent)},
+ {"name", G_STRUCT_OFFSET (MonoPropertyInfo, name)},
+ {"get_method", G_STRUCT_OFFSET (MonoPropertyInfo, get)},
+ {"set_method", G_STRUCT_OFFSET (MonoPropertyInfo, set)},
+ {"attrs", G_STRUCT_OFFSET (MonoPropertyInfo, attrs)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+monofieldinfo_fields[] = {
+ {"parent", G_STRUCT_OFFSET (MonoFieldInfo, parent)},
+ {"type", G_STRUCT_OFFSET (MonoFieldInfo, type)},
+ {"name", G_STRUCT_OFFSET (MonoFieldInfo, name)},
+ {"attrs", G_STRUCT_OFFSET (MonoFieldInfo, attrs)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+monomethod_fields[] = {
+ {"mhandle", G_STRUCT_OFFSET (MonoReflectionMethod, method)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+monocmethod_fields[] = {
+ {"mhandle", G_STRUCT_OFFSET (MonoReflectionMethod, method)},
+ {NULL, 0}
+};
+
+static const FieldDesc
+pinfo_fields[] = {
+ {"ClassImpl", G_STRUCT_OFFSET (MonoReflectionParameter, ClassImpl)},
+ {"DefaultValueImpl", G_STRUCT_OFFSET (MonoReflectionParameter, DefaultValueImpl)},
+ {"MemberImpl", G_STRUCT_OFFSET (MonoReflectionParameter, MemberImpl)},
+ {"NameImpl", G_STRUCT_OFFSET (MonoReflectionParameter, NameImpl)},
+ {"PositionImpl", G_STRUCT_OFFSET (MonoReflectionParameter, PositionImpl)},
+ {"AttrsImpl", G_STRUCT_OFFSET (MonoReflectionParameter, AttrsImpl)},
+ {NULL, 0}
+};
+
+static const ClassDesc
+reflection_classes_to_check [] = {
+ {"MonoEvent", monoevent_fields},
+ {"MonoProperty", monoproperty_fields},
+ {"MonoField", monofield_fields},
+ {"MonoMethodInfo", monomethodinfo_fields},
+ {"MonoPropertyInfo", monopropertyinfo_fields},
+ {"MonoFieldInfo", monofieldinfo_fields},
+ {"MonoMethod", monomethod_fields},
+ {"MonoCMethod", monocmethod_fields},
+ {"ParameterInfo", pinfo_fields},
+ {NULL, NULL}
+};
+
+static FieldDesc
+enuminfo_fields[] = {
+ {"utype", G_STRUCT_OFFSET (MonoEnumInfo, utype)},
+ {"values", G_STRUCT_OFFSET (MonoEnumInfo, values)},
+ {"names", G_STRUCT_OFFSET (MonoEnumInfo, names)},
+ {NULL, 0}
+};
+
+static FieldDesc
+delegate_fields[] = {
+ {"target_type", G_STRUCT_OFFSET (MonoDelegate, target_type)},
+ {"m_target", G_STRUCT_OFFSET (MonoDelegate, target)},
+ {"method_name", G_STRUCT_OFFSET (MonoDelegate, method_name)},
+ {"method_ptr", G_STRUCT_OFFSET (MonoDelegate, method_ptr)},
+ {"delegate_trampoline", G_STRUCT_OFFSET (MonoDelegate, delegate_trampoline)},
+ {"method_info", G_STRUCT_OFFSET (MonoDelegate, method_info)},
+ {NULL, 0}
+};
+
+static FieldDesc
+multicast_delegate_fields[] = {
+ {"prev", G_STRUCT_OFFSET (MonoMulticastDelegate, prev)},
+ {NULL, 0}
+};
+
+static FieldDesc
+async_result_fields[] = {
+ {"async_state", G_STRUCT_OFFSET (MonoAsyncResult, async_state)},
+ {"handle", G_STRUCT_OFFSET (MonoAsyncResult, handle)},
+ {"async_delegate", G_STRUCT_OFFSET (MonoAsyncResult, async_delegate)},
+ {"data", G_STRUCT_OFFSET (MonoAsyncResult, data)},
+ {"sync_completed", G_STRUCT_OFFSET (MonoAsyncResult, sync_completed)},
+ {"completed", G_STRUCT_OFFSET (MonoAsyncResult, completed)},
+ {"endinvoke_called", G_STRUCT_OFFSET (MonoAsyncResult, endinvoke_called)},
+ {NULL, 0}
+};
+
+static const ClassDesc
+system_classes_to_check [] = {
+ {"MonoEnumInfo", enuminfo_fields},
+ {"Delegate", delegate_fields},
+ {"MulticastDelegate", multicast_delegate_fields},
+ {NULL, NULL}
+};
+
+static FieldDesc
+mono_method_message_fields[] = {
+ {"method", G_STRUCT_OFFSET (MonoMethodMessage, method)},
+ {"args", G_STRUCT_OFFSET (MonoMethodMessage, args)},
+ {"names", G_STRUCT_OFFSET (MonoMethodMessage, names)},
+ {"arg_types", G_STRUCT_OFFSET (MonoMethodMessage, arg_types)},
+ {"ctx", G_STRUCT_OFFSET (MonoMethodMessage, ctx)},
+ {"rval", G_STRUCT_OFFSET (MonoMethodMessage, rval)},
+ {"exc", G_STRUCT_OFFSET (MonoMethodMessage, exc)},
+ {NULL, 0}
+};
+
+static const ClassDesc
+messaging_classes_to_check [] = {
+ {"AsyncResult", async_result_fields},
+ {"MonoMethodMessage", mono_method_message_fields},
+ {NULL, NULL}
+};
+
+static FieldDesc
+transparent_proxy_fields[] = {
+ {"_rp", G_STRUCT_OFFSET (MonoTransparentProxy, rp)},
+ {NULL, 0}
+};
+
+static FieldDesc
+real_proxy_fields[] = {
+ {"class_to_proxy", G_STRUCT_OFFSET (MonoRealProxy, class_to_proxy)},
+ {NULL, 0}
+};
+
+static const ClassDesc
+proxy_classes_to_check [] = {
+ {"TransparentProxy", transparent_proxy_fields},
+ {"RealProxy", real_proxy_fields},
+ {NULL, NULL}
+};
+
+static FieldDesc
+wait_handle_fields[] = {
+ {"os_handle", G_STRUCT_OFFSET (MonoWaitHandle, handle)},
+ {"disposed", G_STRUCT_OFFSET (MonoWaitHandle, disposed)},
+ {NULL, 0}
+};
+
+static const ClassDesc
+threading_classes_to_check [] = {
+ {"WaitHandle", wait_handle_fields},
+ {NULL, NULL}
+};
+
+typedef struct {
+ const char *name;
+ const ClassDesc *types;
+} NameSpaceDesc;
+
+static const NameSpaceDesc
+namespaces_to_check[] = {
+ {"System.Runtime.Remoting.Proxies", proxy_classes_to_check},
+ {"System.Runtime.Remoting.Messaging", messaging_classes_to_check},
+ {"System.Reflection.Emit", emit_classes_to_check},
+ {"System.Reflection", reflection_classes_to_check},
+ {"System.Threading", threading_classes_to_check},
+ {"System", system_classes_to_check},
+ {NULL, NULL}
+};
+
+static char*
+check_corlib (MonoImage *corlib)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+ const FieldDesc *fdesc;
+ const ClassDesc *cdesc;
+ const NameSpaceDesc *ndesc;
+ gint struct_offset;
+
+ for (ndesc = namespaces_to_check; ndesc->name; ++ndesc) {
+ for (cdesc = ndesc->types; cdesc->name; ++cdesc) {
+ klass = mono_class_from_name (corlib, ndesc->name, cdesc->name);
+ if (!klass)
+ return g_strdup_printf ("Cannot find class %s", cdesc->name);
+ mono_class_init (klass);
+ /*
+ * FIXME: we should also check the size of valuetypes, or
+ * we're going to have trouble when we access them in arrays.
+ */
+ if (klass->valuetype)
+ struct_offset = 8;
+ else
+ struct_offset = 0;
+ for (fdesc = cdesc->fields; fdesc->name; ++fdesc) {
+ field = mono_class_get_field_from_name (klass, fdesc->name);
+ if (!field || (field->offset != (fdesc->offset + struct_offset)))
+ return g_strdup_printf ("field `%s' mismatch in class %s (%ld != %ld)", fdesc->name, cdesc->name, (long) fdesc->offset, (long) (field?field->offset:-1));
+ }
+ }
+ }
+ return NULL;
+}
+
+char*
+mono_verify_corlib () {
+ return check_corlib (mono_defaults.corlib);
+}
+