/*
- * reflection.c: Routines for creating an image at runtime.
+ * reflection.c: System.Type icalls and related reflection queries.
*
* Author:
* Paolo Molaro (lupus@ximian.com)
* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
* Copyright 2011 Rodrigo Kumpera
+ * Copyright 2016 Microsoft
*
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
-#include "mono/utils/mono-digest.h"
#include "mono/utils/mono-membar.h"
#include "mono/metadata/reflection-internals.h"
#include "mono/metadata/tabledefs.h"
#include <mono/metadata/profiler-private.h>
#include "mono/metadata/class-internals.h"
#include "mono/metadata/gc-internals.h"
-#include "mono/metadata/tokentype.h"
#include "mono/metadata/domain-internals.h"
#include "mono/metadata/opcodes.h"
#include "mono/metadata/assembly.h"
#include <mono/metadata/exception.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/security-manager.h>
+#include <mono/metadata/reflection-cache.h>
+#include <mono/metadata/sre-internals.h>
#include <stdio.h>
#include <glib.h>
#include <errno.h>
#include <mono/utils/mono-string.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/checked-build.h>
+#include <mono/utils/mono-counters.h>
-static gboolean is_usertype (MonoReflectionType *ref);
-static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
-
-typedef struct {
- char *p;
- char *buf;
- char *end;
-} SigBuffer;
-
-#define TEXT_OFFSET 512
-#define CLI_H_SIZE 136
-#define FILE_ALIGN 512
-#define VIRT_ALIGN 8192
-#define START_TEXT_RVA 0x00002000
-
-typedef struct {
- MonoReflectionILGen *ilgen;
- MonoReflectionType *rtype;
- MonoArray *parameters;
- MonoArray *generic_params;
- MonoGenericContainer *generic_container;
- MonoArray *pinfo;
- MonoArray *opt_types;
- guint32 attrs;
- guint32 iattrs;
- guint32 call_conv;
- guint32 *table_idx; /* note: it's a pointer */
- MonoArray *code;
- MonoObject *type;
- MonoString *name;
- MonoBoolean init_locals;
- MonoBoolean skip_visibility;
- MonoArray *return_modreq;
- MonoArray *return_modopt;
- MonoArray *param_modreq;
- MonoArray *param_modopt;
- MonoArray *permissions;
- MonoMethod *mhandle;
- guint32 nrefs;
- gpointer *refs;
- /* for PInvoke */
- int charset, extra_flags, native_cc;
- MonoString *dll, *dllentry;
-} ReflectionMethodBuilder;
-
-typedef struct {
- guint32 owner;
- MonoReflectionGenericParam *gparam;
-} GenericParamTableEntry;
-
-const unsigned char table_sizes [MONO_TABLE_NUM] = {
- MONO_MODULE_SIZE,
- MONO_TYPEREF_SIZE,
- MONO_TYPEDEF_SIZE,
- 0,
- MONO_FIELD_SIZE,
- 0,
- MONO_METHOD_SIZE,
- 0,
- MONO_PARAM_SIZE,
- MONO_INTERFACEIMPL_SIZE,
- MONO_MEMBERREF_SIZE, /* 0x0A */
- MONO_CONSTANT_SIZE,
- MONO_CUSTOM_ATTR_SIZE,
- MONO_FIELD_MARSHAL_SIZE,
- MONO_DECL_SECURITY_SIZE,
- MONO_CLASS_LAYOUT_SIZE,
- MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
- MONO_STAND_ALONE_SIGNATURE_SIZE,
- MONO_EVENT_MAP_SIZE,
- 0,
- MONO_EVENT_SIZE,
- MONO_PROPERTY_MAP_SIZE,
- 0,
- MONO_PROPERTY_SIZE,
- MONO_METHOD_SEMA_SIZE,
- MONO_METHODIMPL_SIZE,
- MONO_MODULEREF_SIZE, /* 0x1A */
- MONO_TYPESPEC_SIZE,
- MONO_IMPLMAP_SIZE,
- MONO_FIELD_RVA_SIZE,
- 0,
- 0,
- MONO_ASSEMBLY_SIZE, /* 0x20 */
- MONO_ASSEMBLY_PROCESSOR_SIZE,
- MONO_ASSEMBLYOS_SIZE,
- MONO_ASSEMBLYREF_SIZE,
- MONO_ASSEMBLYREFPROC_SIZE,
- MONO_ASSEMBLYREFOS_SIZE,
- MONO_FILE_SIZE,
- MONO_EXP_TYPE_SIZE,
- MONO_MANIFEST_SIZE,
- MONO_NESTED_CLASS_SIZE,
-
- MONO_GENERICPARAM_SIZE, /* 0x2A */
- MONO_METHODSPEC_SIZE,
- MONO_GENPARCONSTRAINT_SIZE
-
-};
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
-static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
-static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
-static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
-static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
-static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
-static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
-static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
-static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
-static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
-static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
-static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
-#endif
-
-static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
-static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
-static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
-static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
-static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
-static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
-static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
-static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
-static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
-static gboolean is_sre_array (MonoClass *klass);
-static gboolean is_sre_byref (MonoClass *klass);
-static gboolean is_sre_pointer (MonoClass *klass);
-static gboolean is_sre_type_builder (MonoClass *klass);
-static gboolean is_sre_method_builder (MonoClass *klass);
-static gboolean is_sre_ctor_builder (MonoClass *klass);
-static gboolean is_sre_field_builder (MonoClass *klass);
-static gboolean is_sr_mono_method (MonoClass *klass);
-static gboolean is_sr_mono_cmethod (MonoClass *klass);
-static gboolean is_sr_mono_generic_method (MonoClass *klass);
-static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
-static gboolean is_sr_mono_field (MonoClass *klass);
-static gboolean is_sr_mono_property (MonoClass *klass);
-static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
-static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
-
-static gboolean type_is_reference (MonoType *type);
-
-static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
-static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
-static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
-
-static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
-static void init_type_builder_generics (MonoObject *type, MonoError *error);
-
-#define RESOLVE_TYPE(type, error) do { \
- type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
-} while (0)
-#define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
- MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
- __type = mono_reflection_type_resolve_user_types (__type, error); \
- if (mono_error_ok (error)) \
- mono_array_set (arr, MonoReflectionType*, index, __type); \
-} while (0)
-
-#define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
-
-#define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
-#define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
-
-#if SIZEOF_VOID_P == 4
-#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
-#else
-#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
-#endif
-
-#define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
-#define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
/* Class lazy loading functions */
static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
-static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
-static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
-static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
-static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
-static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
-// The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
-static GPtrArray *dynamic_images;
-static mono_mutex_t dynamic_images_mutex;
-
-static inline void
-dynamic_images_lock (void)
-{
- mono_os_mutex_lock (&dynamic_images_mutex);
-}
-
-static inline void
-dynamic_images_unlock (void)
-{
- mono_os_mutex_unlock (&dynamic_images_mutex);
-}
-
-/**
- * mono_find_dynamic_image_owner:
- *
- * Find the dynamic image, if any, which a given pointer is located in the memory of.
- */
-MonoImage *
-mono_find_dynamic_image_owner (void *ptr)
-{
- MonoImage *owner = NULL;
- int i;
-
- dynamic_images_lock ();
-
- if (dynamic_images)
- {
- for (i = 0; !owner && i < dynamic_images->len; ++i) {
- MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
- if (mono_mempool_contains_addr (image->mempool, ptr))
- owner = image;
- }
- }
-
- dynamic_images_unlock ();
- return owner;
-}
+static int class_ref_info_handle_count;
void
mono_reflection_init (void)
{
- mono_os_mutex_init (&dynamic_images_mutex);
-}
+ mono_reflection_emit_init ();
-static inline void
-dynamic_image_lock (MonoDynamicImage *image)
-{
- MONO_ENTER_GC_SAFE;
- mono_image_lock ((MonoImage*)image);
- MONO_EXIT_GC_SAFE;
-}
+ mono_counters_register ("MonoClass::ref_info_handle count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ref_info_handle_count);
-static inline void
-dynamic_image_unlock (MonoDynamicImage *image)
-{
- mono_image_unlock ((MonoImage*)image);
}
-static void
-register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
+/*
+ * mono_class_get_ref_info:
+ *
+ * Return the type builder/generic param builder corresponding to KLASS, if it exists.
+ */
+gpointer
+mono_class_get_ref_info (MonoClass *klass)
{
MONO_REQ_GC_UNSAFE_MODE;
+ guint32 ref_info_handle = mono_class_get_ref_info_handle (klass);
- dynamic_image_lock (assembly);
- mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
- dynamic_image_unlock (assembly);
+ if (ref_info_handle == 0)
+ return NULL;
+ else
+ return mono_gchandle_get_target (ref_info_handle);
}
-static MonoObject*
-lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
+void
+mono_class_set_ref_info (MonoClass *klass, gpointer obj)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoObject *obj;
-
- dynamic_image_lock (assembly);
- obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
- dynamic_image_unlock (assembly);
+ guint32 candidate = mono_gchandle_new ((MonoObject*)obj, FALSE);
+ guint32 handle = mono_class_set_ref_info_handle (klass, candidate);
+ ++class_ref_info_handle_count;
- return obj;
+ if (handle != candidate)
+ mono_gchandle_free (candidate);
}
-static void
-sigbuffer_init (SigBuffer *buf, int size)
+void
+mono_class_free_ref_info (MonoClass *klass)
{
MONO_REQ_GC_NEUTRAL_MODE;
+ guint32 handle = mono_class_get_ref_info_handle (klass);
- buf->buf = (char *)g_malloc (size);
- buf->p = buf->buf;
- buf->end = buf->buf + size;
+ if (handle) {
+ mono_gchandle_free (handle);
+ mono_class_set_ref_info_handle (klass, 0);
+ }
}
-static void
-sigbuffer_make_room (SigBuffer *buf, int size)
+
+void
+mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
{
MONO_REQ_GC_NEUTRAL_MODE;
- if (buf->end - buf->p < size) {
- int new_size = buf->end - buf->buf + size + 32;
- char *p = (char *)g_realloc (buf->buf, new_size);
- size = buf->p - buf->buf;
- buf->buf = p;
- buf->p = p + size;
- buf->end = buf->buf + new_size;
- }
+ if (ainfo && !ainfo->cached)
+ g_free (ainfo);
}
-static void
-sigbuffer_add_value (SigBuffer *buf, guint32 val)
+
+gboolean
+reflected_equal (gconstpointer a, gconstpointer b)
{
- MONO_REQ_GC_NEUTRAL_MODE;
+ const ReflectedEntry *ea = (const ReflectedEntry *)a;
+ const ReflectedEntry *eb = (const ReflectedEntry *)b;
+
+ return (ea->item == eb->item) && (ea->refclass == eb->refclass);
+}
- sigbuffer_make_room (buf, 6);
- mono_metadata_encode_value (val, buf->p, &buf->p);
+guint
+reflected_hash (gconstpointer a) {
+ const ReflectedEntry *ea = (const ReflectedEntry *)a;
+ return mono_aligned_addr_hash (ea->item);
}
+
static void
-sigbuffer_add_byte (SigBuffer *buf, guint8 val)
+clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
{
- MONO_REQ_GC_NEUTRAL_MODE;
+ mono_domain_lock (domain);
+ if (domain->refobject_hash) {
+ ReflectedEntry pe;
+ gpointer orig_pe, orig_value;
- sigbuffer_make_room (buf, 1);
- buf->p [0] = val;
- buf->p++;
+ pe.item = o;
+ pe.refclass = klass;
+ if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
+ mono_g_hash_table_remove (domain->refobject_hash, &pe);
+ FREE_REFENTRY (orig_pe);
+ }
+ }
+ mono_domain_unlock (domain);
}
+#ifdef REFENTRY_REQUIRES_CLEANUP
static void
-sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
+cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- sigbuffer_make_room (buf, size);
- memcpy (buf->p, p, size);
- buf->p += size;
+ FREE_REFENTRY (key);
}
+#endif
-static void
-sigbuffer_free (SigBuffer *buf)
+void
+mono_reflection_cleanup_domain (MonoDomain *domain)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- g_free (buf->buf);
+ if (domain->refobject_hash) {
+/*let's avoid scanning the whole hashtable if not needed*/
+#ifdef REFENTRY_REQUIRES_CLEANUP
+ mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
+#endif
+ mono_g_hash_table_destroy (domain->refobject_hash);
+ domain->refobject_hash = NULL;
+ }
}
-#ifndef DISABLE_REFLECTION_EMIT
-/**
- * mp_g_alloc:
+
+/*
+ * mono_assembly_get_object:
+ * @domain: an app domain
+ * @assembly: an assembly
*
- * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
- * from the C heap.
+ * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
*/
-static gpointer
-image_g_malloc (MonoImage *image, guint size)
+MonoReflectionAssembly*
+mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (image)
- return mono_image_alloc (image, size);
- else
- return g_malloc (size);
+ HANDLE_FUNCTION_ENTER ();
+ MonoError error;
+ MonoReflectionAssemblyHandle result = mono_assembly_get_object_handle (domain, assembly, &error);
+ mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
+ HANDLE_FUNCTION_RETURN_OBJ (result);
}
-#endif /* !DISABLE_REFLECTION_EMIT */
-/**
- * image_g_alloc0:
- *
- * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
- * from the C heap.
- */
-static gpointer
-image_g_malloc0 (MonoImage *image, guint size)
+static MonoReflectionAssemblyHandle
+assembly_object_construct (MonoDomain *domain, MonoClass *unused_klass, MonoAssembly *assembly, gpointer user_data, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (image)
- return mono_image_alloc0 (image, size);
- else
- return g_malloc0 (size);
+ mono_error_init (error);
+ MonoReflectionAssemblyHandle res = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error));
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE));
+ MONO_HANDLE_SETVAL (res, assembly, MonoAssembly*, assembly);
+ return res;
}
-/**
- * image_g_free:
- * @image: a MonoImage
- * @ptr: pointer
+/*
+ * mono_assembly_get_object_handle:
+ * @domain: an app domain
+ * @assembly: an assembly
*
- * If @image is NULL, free @ptr, otherwise do nothing.
+ * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
*/
-static void
-image_g_free (MonoImage *image, gpointer ptr)
+MonoReflectionAssemblyHandle
+mono_assembly_get_object_handle (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
{
- if (image == NULL)
- g_free (ptr);
+ mono_error_init (error);
+ return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionAssemblyHandle, assembly, NULL, assembly_object_construct, NULL);
}
-#ifndef DISABLE_REFLECTION_EMIT
-static char*
-image_strdup (MonoImage *image, const char *s)
+/*
+ * mono_assembly_get_object_handle:
+ * @domain: an app domain
+ * @assembly: an assembly
+ *
+ * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
+ */
+MonoReflectionAssembly*
+mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (image)
- return mono_image_strdup (image, s);
- else
- return g_strdup (s);
+ HANDLE_FUNCTION_ENTER ();
+ mono_error_init (error);
+ MonoReflectionAssemblyHandle result = mono_assembly_get_object_handle (domain, assembly, error);
+ HANDLE_FUNCTION_RETURN_OBJ (result);
}
-#endif
-
-#define image_g_new(image,struct_type, n_structs) \
- ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-#define image_g_new0(image,struct_type, n_structs) \
- ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
-static void
-alloc_table (MonoDynamicTable *table, guint nrows)
+MonoReflectionModule*
+mono_module_get_object (MonoDomain *domain, MonoImage *image)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- table->rows = nrows;
- g_assert (table->columns);
- if (nrows + 1 >= table->alloc_rows) {
- while (nrows + 1 >= table->alloc_rows) {
- if (table->alloc_rows == 0)
- table->alloc_rows = 16;
- else
- table->alloc_rows *= 2;
- }
-
- table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
- }
+ HANDLE_FUNCTION_ENTER ();
+ MonoError error;
+ MonoReflectionModuleHandle result = mono_module_get_object_handle (domain, image, &error);
+ mono_error_cleanup (&error);
+ HANDLE_FUNCTION_RETURN_OBJ (result);
}
-static void
-make_room_in_stream (MonoDynamicStream *stream, int size)
+static MonoReflectionModuleHandle
+module_object_construct (MonoDomain *domain, MonoClass *unused_klass, MonoImage *image, gpointer user_data, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (size <= stream->alloc_size)
- return;
-
- while (stream->alloc_size <= size) {
- if (stream->alloc_size < 4096)
- stream->alloc_size = 4096;
- else
- stream->alloc_size *= 2;
- }
+ char* basename;
- stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
-}
+ mono_error_init (error);
+ MonoReflectionModuleHandle res = MONO_HANDLE_NEW (MonoReflectionModule, mono_object_new_checked (domain, mono_class_get_mono_module_class (), error));
+ if (!is_ok (error))
+ goto fail;
-static guint32
-string_heap_insert (MonoDynamicStream *sh, const char *str)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ MONO_HANDLE_SETVAL (res, image, MonoImage *, image);
+ MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, image->assembly, error);
+ if (!is_ok (error))
+ goto fail;
+ MONO_HANDLE_SET (res, assembly, assm_obj);
- guint32 idx;
- guint32 len;
- gpointer oldkey, oldval;
+ MONO_HANDLE_SET (res, fqname, mono_string_new_handle (domain, image->name, error));
+ if (!is_ok (error))
+ goto fail;
+ basename = g_path_get_basename (image->name);
+ MONO_HANDLE_SET (res, name, mono_string_new_handle (domain, basename, error));
+ if (!is_ok (error))
+ goto fail;
+ MONO_HANDLE_SET (res, scopename, mono_string_new_handle (domain, image->module_name, error));
+ if (!is_ok (error))
+ goto fail;
- if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
- return GPOINTER_TO_UINT (oldval);
+ g_free (basename);
- len = strlen (str) + 1;
- idx = sh->index;
-
- make_room_in_stream (sh, idx + len);
+ guint32 token = 0;
+ if (image->assembly->image == image) {
+ token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
+ } else {
+ int i;
+ if (image->assembly->image->modules) {
+ for (i = 0; i < image->assembly->image->module_count; i++) {
+ if (image->assembly->image->modules [i] == image)
+ token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
+ }
+ g_assert (token != 0);
+ }
+ }
+ MONO_HANDLE_SETVAL (res, token, guint32, token);
- /*
- * We strdup the string even if we already copy them in sh->data
- * so that the string pointers in the hash remain valid even if
- * we need to realloc sh->data. We may want to avoid that later.
- */
- g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
- memcpy (sh->data + idx, str, len);
- sh->index += len;
- return idx;
+ return res;
+fail:
+ return MONO_HANDLE_CAST (MonoReflectionModule, NULL_HANDLE);
}
-static guint32
-string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
+MonoReflectionModuleHandle
+mono_module_get_object_handle (MonoDomain *domain, MonoImage *image, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
mono_error_init (error);
- char *name = mono_string_to_utf8_checked (str, error);
- return_val_if_nok (error, -1);
- guint32 idx;
- idx = string_heap_insert (sh, name);
- g_free (name);
- return idx;
+ return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionModuleHandle, image, NULL, module_object_construct, NULL);
}
-#ifndef DISABLE_REFLECTION_EMIT
-static void
-string_heap_init (MonoDynamicStream *sh)
+MonoReflectionModule*
+mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- sh->index = 0;
- sh->alloc_size = 4096;
- sh->data = (char *)g_malloc (4096);
- sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- string_heap_insert (sh, "");
+ HANDLE_FUNCTION_ENTER ();
+ MonoError error;
+ MonoReflectionModuleHandle result = mono_module_file_get_object_handle (domain, image, table_index, &error);
+ mono_error_cleanup (&error);
+ HANDLE_FUNCTION_RETURN_OBJ (result);
}
-#endif
-static guint32
-mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
+MonoReflectionModuleHandle
+mono_module_file_get_object_handle (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 idx;
+ MonoTableInfo *table;
+ guint32 cols [MONO_FILE_SIZE];
+ const char *name;
+ guint32 i, name_idx;
+ const char *val;
- make_room_in_stream (stream, stream->index + len);
- memcpy (stream->data + stream->index, data, len);
- idx = stream->index;
- stream->index += len;
- /*
- * align index? Not without adding an additional param that controls it since
- * we may store a blob value in pieces.
- */
- return idx;
-}
+ mono_error_init (error);
-static guint32
-mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ MonoReflectionModuleHandle res = MONO_HANDLE_NEW (MonoReflectionModule, mono_object_new_checked (domain, mono_class_get_mono_module_class (), error));
+ if (!is_ok (error))
+ goto fail;
- guint32 idx;
-
- make_room_in_stream (stream, stream->index + len);
- memset (stream->data + stream->index, 0, len);
- idx = stream->index;
- stream->index += len;
- return idx;
-}
+ table = &image->tables [MONO_TABLE_FILE];
+ g_assert (table_index < table->rows);
+ mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
-static void
-stream_data_align (MonoDynamicStream *stream)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ MONO_HANDLE_SETVAL (res, image, MonoImage*, NULL);
+ MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, image->assembly, error);
+ if (!is_ok (error))
+ goto fail;
+ MONO_HANDLE_SET (res, assembly, assm_obj);
+ name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
+
+ /* Check whenever the row has a corresponding row in the moduleref table */
+ table = &image->tables [MONO_TABLE_MODULEREF];
+ for (i = 0; i < table->rows; ++i) {
+ name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
+ val = mono_metadata_string_heap (image, name_idx);
+ if (strcmp (val, name) == 0)
+ MONO_HANDLE_SETVAL (res, image, MonoImage*, image->modules [i]);
+ }
- char buf [4] = {0};
- guint32 count = stream->index % 4;
+ MONO_HANDLE_SET (res, fqname, mono_string_new_handle (domain, name, error));
+ if (!is_ok (error))
+ goto fail;
+ MONO_HANDLE_SET (res, name, mono_string_new_handle (domain, name, error));
+ if (!is_ok (error))
+ goto fail;
+ MONO_HANDLE_SET (res, scopename, mono_string_new_handle (domain, name, error));
+ if (!is_ok (error))
+ goto fail;
+ MONO_HANDLE_SETVAL (res, is_resource, MonoBoolean, cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA);
+ MONO_HANDLE_SETVAL (res, token, guint32, mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1));
- /* we assume the stream data will be aligned */
- if (count)
- mono_image_add_stream_data (stream, buf, 4 - count);
+ return res;
+fail:
+ return MONO_HANDLE_CAST (MonoReflectionModule, NULL_HANDLE);
}
-#ifndef DISABLE_REFLECTION_EMIT
-static int
-mono_blob_entry_hash (const char* str)
+static MonoType*
+mono_type_normalize (MonoType *type)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint len, h;
- const char *end;
- len = mono_metadata_decode_blob_size (str, &str);
- if (len > 0) {
- end = str + len;
- h = *str;
- for (str += 1; str < end; str++)
- h = (h << 5) - h + *str;
- return h;
- } else {
- return 0;
- }
-}
-
-static gboolean
-mono_blob_entry_equal (const char *str1, const char *str2) {
- MONO_REQ_GC_NEUTRAL_MODE;
-
- int len, len2;
- const char *end1;
- const char *end2;
- len = mono_metadata_decode_blob_size (str1, &end1);
- len2 = mono_metadata_decode_blob_size (str2, &end2);
- if (len != len2)
- return 0;
- return memcmp (end1, end2, len) == 0;
-}
-#endif
-static guint32
-add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 idx;
- char *copy;
- gpointer oldkey, oldval;
-
- copy = (char *)g_malloc (s1+s2);
- memcpy (copy, b1, s1);
- memcpy (copy + s1, b2, s2);
- if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
- g_free (copy);
- idx = GPOINTER_TO_UINT (oldval);
- } else {
- idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
- mono_image_add_stream_data (&assembly->blob, b2, s2);
- g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
- }
- return idx;
-}
+ int i;
+ MonoGenericClass *gclass;
+ MonoGenericInst *ginst;
+ MonoClass *gtd;
+ MonoGenericContainer *gcontainer;
+ MonoType **argv = NULL;
+ gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
-static guint32
-sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ if (type->type != MONO_TYPE_GENERICINST)
+ return type;
- char blob_size [8];
- char *b = blob_size;
- guint32 size = buf->p - buf->buf;
- /* store length */
- g_assert (size <= (buf->end - buf->buf));
- mono_metadata_encode_value (size, b, &b);
- return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
-}
+ gclass = type->data.generic_class;
+ ginst = gclass->context.class_inst;
+ if (!ginst->is_open)
+ return type;
-/*
- * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
- * dest may be misaligned.
- */
-static void
-swap_with_size (char *dest, const char* val, int len, int nelem) {
- MONO_REQ_GC_NEUTRAL_MODE;
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- int elem;
+ gtd = gclass->container_class;
+ gcontainer = mono_class_get_generic_container (gtd);
+ argv = g_newa (MonoType*, ginst->type_argc);
- for (elem = 0; elem < nelem; ++elem) {
- switch (len) {
- case 1:
- *dest = *val;
- break;
- case 2:
- dest [0] = val [1];
- dest [1] = val [0];
- break;
- case 4:
- dest [0] = val [3];
- dest [1] = val [2];
- dest [2] = val [1];
- dest [3] = val [0];
- break;
- case 8:
- dest [0] = val [7];
- dest [1] = val [6];
- dest [2] = val [5];
- dest [3] = val [4];
- dest [4] = val [3];
- dest [5] = val [2];
- dest [6] = val [1];
- dest [7] = val [0];
- break;
- default:
- g_assert_not_reached ();
- }
- dest += len;
- val += len;
+ for (i = 0; i < ginst->type_argc; ++i) {
+ MonoType *t = ginst->type_argv [i], *norm;
+ if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
+ is_denorm_gtd = FALSE;
+ norm = mono_type_normalize (t);
+ argv [i] = norm;
+ if (norm != t)
+ requires_rebind = TRUE;
}
-#else
- memcpy (dest, val, len * nelem);
-#endif
-}
-
-static guint32
-add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- char blob_size [64];
- char *b = blob_size;
- guint32 idx = 0, len;
- len = str->length * 2;
- mono_metadata_encode_value (len, b, &b);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- {
- char *swapped = g_malloc (2 * mono_string_length (str));
- const char *p = (const char*)mono_string_chars (str);
+ if (is_denorm_gtd)
+ return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
- swap_with_size (swapped, p, 2, mono_string_length (str));
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
- g_free (swapped);
+ if (requires_rebind) {
+ MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
+ return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
}
-#else
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
-#endif
- return idx;
-}
-#ifndef DISABLE_REFLECTION_EMIT
-static MonoClass *
-default_class_from_mono_type (MonoType *type)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- switch (type->type) {
- case MONO_TYPE_OBJECT:
- return mono_defaults.object_class;
- case MONO_TYPE_VOID:
- return mono_defaults.void_class;
- case MONO_TYPE_BOOLEAN:
- return mono_defaults.boolean_class;
- case MONO_TYPE_CHAR:
- return mono_defaults.char_class;
- case MONO_TYPE_I1:
- return mono_defaults.sbyte_class;
- case MONO_TYPE_U1:
- return mono_defaults.byte_class;
- case MONO_TYPE_I2:
- return mono_defaults.int16_class;
- case MONO_TYPE_U2:
- return mono_defaults.uint16_class;
- case MONO_TYPE_I4:
- return mono_defaults.int32_class;
- case MONO_TYPE_U4:
- return mono_defaults.uint32_class;
- case MONO_TYPE_I:
- return mono_defaults.int_class;
- case MONO_TYPE_U:
- return mono_defaults.uint_class;
- case MONO_TYPE_I8:
- return mono_defaults.int64_class;
- case MONO_TYPE_U8:
- return mono_defaults.uint64_class;
- case MONO_TYPE_R4:
- return mono_defaults.single_class;
- case MONO_TYPE_R8:
- return mono_defaults.double_class;
- case MONO_TYPE_STRING:
- return mono_defaults.string_class;
- default:
- g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
- g_assert_not_reached ();
- }
-
- return NULL;
+ return type;
}
-#endif
-
/*
- * mono_class_get_ref_info:
+ * mono_type_get_object:
+ * @domain: an app domain
+ * @type: a type
*
- * Return the type builder/generic param builder corresponding to KLASS, if it exists.
+ * Return an System.MonoType object representing the type @type.
*/
-gpointer
-mono_class_get_ref_info (MonoClass *klass)
+MonoReflectionType*
+mono_type_get_object (MonoDomain *domain, MonoType *type)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+ MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
+ mono_error_cleanup (&error);
- if (klass->ref_info_handle == 0)
- return NULL;
- else
- return mono_gchandle_get_target (klass->ref_info_handle);
+ return ret;
}
-void
-mono_class_set_ref_info (MonoClass *klass, gpointer obj)
+MonoReflectionType*
+mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoType *norm_type;
+ MonoReflectionType *res;
+ MonoClass *klass;
- klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
- g_assert (klass->ref_info_handle != 0);
-}
+ mono_error_init (error);
-void
-mono_class_free_ref_info (MonoClass *klass)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ g_assert (type != NULL);
+ klass = mono_class_from_mono_type (type);
+
+ /*we must avoid using @type as it might have come
+ * from a mono_metadata_type_dup and the caller
+ * expects that is can be freed.
+ * Using the right type from
+ */
+ type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
+
+ /* void is very common */
+ if (type->type == MONO_TYPE_VOID && domain->typeof_void)
+ return (MonoReflectionType*)domain->typeof_void;
- if (klass->ref_info_handle) {
- mono_gchandle_free (klass->ref_info_handle);
- klass->ref_info_handle = 0;
+ /*
+ * If the vtable of the given class was already created, we can use
+ * the MonoType from there and avoid all locking and hash table lookups.
+ *
+ * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
+ * that the resulting object is different.
+ */
+ if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
+ MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
+ if (vtable && vtable->type)
+ return (MonoReflectionType *)vtable->type;
}
-}
-static void
-encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
+ mono_domain_lock (domain);
+ if (!domain->type_hash)
+ domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
+ (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
+ if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return res;
+ }
- int i;
- MonoGenericInst *class_inst;
- MonoClass *klass;
+ /*Types must be normalized so a generic instance of the GTD get's the same inner type.
+ * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
+ * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
+ * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
+ * artifact of how generics are encoded and should be transparent to managed code so we
+ * need to weed out this diference when retrieving managed System.Type objects.
+ */
+ norm_type = mono_type_normalize (type);
+ if (norm_type != type) {
+ res = mono_type_get_object_checked (domain, norm_type, error);
+ if (!mono_error_ok (error))
+ return NULL;
+ mono_g_hash_table_insert (domain->type_hash, type, res);
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return res;
+ }
- g_assert (gclass);
+ if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
+ /* This can happen if a TypeBuilder for a generic class K<T,U>
+ * had reflection_create_generic_class) called on it, but not
+ * ves_icall_TypeBuilder_create_runtime_class. This can happen
+ * if the K`2 is refernced from a generic instantiation
+ * (e.g. K<int,string>) that appears as type argument
+ * (e.g. Dict<string,K<int,string>>), field (e.g. K<int,string>
+ * Foo) or method signature, parent class or any of the above
+ * in a nested class of some other TypeBuilder. Such an
+ * occurrence caused mono_reflection_type_get_handle to be
+ * called on the sre generic instance (K<int,string>) which
+ * required the container_class for the generic class K`2 to be
+ * set up, but the remainder of class construction for K`2 has
+ * not been done. */
+ char * full_name = mono_type_get_full_name (klass);
+ /* I would have expected ReflectionTypeLoadException, but evidently .NET throws TLE in this case. */
+ mono_error_set_type_load_class (error, klass, "TypeBuilder.CreateType() not called for generic class %s", full_name);
+ g_free (full_name);
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return NULL;
+ }
- class_inst = gclass->context.class_inst;
+ if (mono_class_get_ref_info (klass) && !klass->wastypebuilder && !type->byref) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return (MonoReflectionType *)mono_class_get_ref_info (klass);
+ }
+ /* This is stored in vtables/JITted code so it has to be pinned */
+ res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
+ if (!mono_error_ok (error))
+ return NULL;
- sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
- klass = gclass->container_class;
- sigbuffer_add_value (buf, klass->byval_arg.type);
- sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
+ res->type = type;
+ mono_g_hash_table_insert (domain->type_hash, type, res);
- sigbuffer_add_value (buf, class_inst->type_argc);
- for (i = 0; i < class_inst->type_argc; ++i)
- encode_type (assembly, class_inst->type_argv [i], buf);
+ if (type->type == MONO_TYPE_VOID)
+ domain->typeof_void = (MonoObject*)res;
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return res;
}
-static void
-encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
+MonoReflectionTypeHandle
+mono_type_get_object_handle (MonoDomain *domain, MonoType *type, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (!type) {
- g_assert_not_reached ();
- return;
- }
-
- if (type->byref)
- sigbuffer_add_value (buf, MONO_TYPE_BYREF);
-
- switch (type->type){
- case MONO_TYPE_VOID:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_STRING:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_TYPEDBYREF:
- sigbuffer_add_value (buf, type->type);
- break;
- case MONO_TYPE_PTR:
- sigbuffer_add_value (buf, type->type);
- encode_type (assembly, type->data.type, buf);
- break;
- case MONO_TYPE_SZARRAY:
- sigbuffer_add_value (buf, type->type);
- encode_type (assembly, &type->data.klass->byval_arg, buf);
- break;
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_CLASS: {
- MonoClass *k = mono_class_from_mono_type (type);
-
- if (k->generic_container) {
- MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
- encode_generic_class (assembly, gclass, buf);
- } else {
- /*
- * Make sure we use the correct type.
- */
- sigbuffer_add_value (buf, k->byval_arg.type);
- /*
- * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
- * otherwise two typerefs could point to the same type, leading to
- * verification errors.
- */
- sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
- }
- break;
- }
- case MONO_TYPE_ARRAY:
- sigbuffer_add_value (buf, type->type);
- encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
- sigbuffer_add_value (buf, type->data.array->rank);
- sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
- sigbuffer_add_value (buf, 0);
- break;
- case MONO_TYPE_GENERICINST:
- encode_generic_class (assembly, type->data.generic_class, buf);
- break;
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- sigbuffer_add_value (buf, type->type);
- sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
- break;
- default:
- g_error ("need to encode type %x", type->type);
- }
+ /* NOTE: We happen to know that mono_type_get_object_checked returns
+ * pinned objects, so we can just wrap its return value in a handle for
+ * uniformity. If it ever starts returning unpinned, objects, this
+ * implementation would need to change!
+ */
+ return MONO_HANDLE_NEW (MonoReflectionType, mono_type_get_object_checked (domain, type, error));
}
-static void
-encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
+/*
+ * mono_method_get_object:
+ * @domain: an app domain
+ * @method: a method
+ * @refclass: the reflected type (can be NULL)
+ *
+ * Return an System.Reflection.MonoMethod object representing the method @method.
+ */
+MonoReflectionMethod*
+mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
-
- if (!type) {
- sigbuffer_add_value (buf, MONO_TYPE_VOID);
- return;
- }
-
- MonoType *t = mono_reflection_type_get_handle (type, error);
- return_if_nok (error);
- encode_type (assembly, t, buf);
+ MonoError error;
+ MonoReflectionMethod *ret = NULL;
+ ret = mono_method_get_object_checked (domain, method, refclass, &error);
+ mono_error_cleanup (&error);
+ return ret;
}
-static void
-encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
+static MonoReflectionMethod*
+method_object_construct (MonoDomain *domain, MonoClass *refclass, MonoMethod *method, gpointer user_data, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- int i;
+ mono_error_init (error);
+ g_assert (refclass != NULL);
+ /*
+ * We use the same C representation for methods and constructors, but the type
+ * name in C# is different.
+ */
+ MonoReflectionType *rt;
+ MonoClass *klass;
+ MonoReflectionMethod *ret;
mono_error_init (error);
- if (modreq) {
- for (i = 0; i < mono_array_length (modreq); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
- return_if_nok (error);
- sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
- sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
- }
+ if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
+ klass = mono_class_get_mono_cmethod_class ();
}
- if (modopt) {
- for (i = 0; i < mono_array_length (modopt); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
- return_if_nok (error);
- sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
- sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
- }
+ else {
+ klass = mono_class_get_mono_method_class ();
}
-}
+ ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
+ if (!mono_error_ok (error))
+ goto leave;
+ ret->method = method;
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
+ if (!mono_error_ok (error))
+ goto leave;
- SigBuffer buf;
- int i;
- guint32 nparams = sig->param_count;
- guint32 idx;
+ MONO_OBJECT_SETREF (ret, reftype, rt);
- if (!assembly->save)
- return 0;
+ return ret;
- sigbuffer_init (&buf, 32);
- /*
- * FIXME: vararg, explicit_this, differenc call_conv values...
- */
- idx = sig->call_convention;
- if (sig->hasthis)
- idx |= 0x20; /* hasthis */
- if (sig->generic_param_count)
- idx |= 0x10; /* generic */
- sigbuffer_add_byte (&buf, idx);
- if (sig->generic_param_count)
- sigbuffer_add_value (&buf, sig->generic_param_count);
- sigbuffer_add_value (&buf, nparams);
- encode_type (assembly, sig->ret, &buf);
- for (i = 0; i < nparams; ++i) {
- if (i == sig->sentinelpos)
- sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
- encode_type (assembly, sig->params [i], &buf);
- }
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
+leave:
+ g_assert (!mono_error_ok (error));
+ return NULL;
}
-#endif
-static guint32
-method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
+/*
+ * mono_method_get_object_checked:
+ * @domain: an app domain
+ * @method: a method
+ * @refclass: the reflected type (can be NULL)
+ * @error: set on error.
+ *
+ * Return an System.Reflection.MonoMethod object representing the method @method.
+ * Returns NULL and sets @error on error.
+ */
+MonoReflectionMethod*
+mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
mono_error_init (error);
+ if (!refclass)
+ refclass = method->klass;
- /*
- * FIXME: reuse code from method_encode_signature().
- */
- SigBuffer buf;
- int i;
- guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
- guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
- guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
- guint32 idx;
-
- sigbuffer_init (&buf, 32);
- /* LAMESPEC: all the call conv spec is foobared */
- idx = mb->call_conv & 0x60; /* has-this, explicit-this */
- if (mb->call_conv & 2)
- idx |= 0x5; /* vararg */
- if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
- idx |= 0x20; /* hasthis */
- if (ngparams)
- idx |= 0x10; /* generic */
- sigbuffer_add_byte (&buf, idx);
- if (ngparams)
- sigbuffer_add_value (&buf, ngparams);
- sigbuffer_add_value (&buf, nparams + notypes);
- encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
- if (!is_ok (error))
- goto leave;
- encode_reflection_type (assembly, mb->rtype, &buf, error);
- if (!is_ok (error))
- goto leave;
- for (i = 0; i < nparams; ++i) {
- MonoArray *modreq = NULL;
- MonoArray *modopt = NULL;
- MonoReflectionType *pt;
-
- if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
- modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
- if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
- modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
- encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
- if (!is_ok (error))
- goto leave;
- pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto leave;
- }
- if (notypes)
- sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
- for (i = 0; i < notypes; ++i) {
- MonoReflectionType *pt;
-
- pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto leave;
- }
-
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
-leave:
- sigbuffer_free (&buf);
- return idx;
+ return CHECK_OR_CONSTRUCT (MonoReflectionMethod*, method, refclass, method_object_construct, NULL);
}
-static guint32
-encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
+/*
+ * mono_method_clear_object:
+ *
+ * Clear the cached reflection objects for the dynamic method METHOD.
+ */
+void
+mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 idx, sig_idx;
- guint nl = mono_array_length (ilgen->locals);
- SigBuffer buf;
- int i;
+ MonoClass *klass;
+ g_assert (method_is_dynamic (method));
- sigbuffer_init (&buf, 32);
- sigbuffer_add_value (&buf, 0x07);
- sigbuffer_add_value (&buf, nl);
- for (i = 0; i < nl; ++i) {
- MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
-
- if (lb->is_pinned)
- sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
-
- encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
+ klass = method->klass;
+ while (klass) {
+ clear_cached_object (domain, method, klass);
+ klass = klass->parent;
+ }
+ /* Added by mono_param_get_objects () */
+ clear_cached_object (domain, &(method->signature), NULL);
+ klass = method->klass;
+ while (klass) {
+ clear_cached_object (domain, &(method->signature), klass);
+ klass = klass->parent;
}
- sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
-
- if (assembly->standalonesig_cache == NULL)
- assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
- if (idx)
- return idx;
-
- table = &assembly->tables [MONO_TABLE_STANDALONESIG];
- idx = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
-
- values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
-
- g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
-
- return idx;
}
-static guint32
-method_count_clauses (MonoReflectionILGen *ilgen)
+/*
+ * mono_field_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @field: a field
+ *
+ * Return an System.Reflection.MonoField object representing the field @field
+ * in class @klass.
+ */
+MonoReflectionField*
+mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- guint32 num_clauses = 0;
- int i;
-
- MonoILExceptionInfo *ex_info;
- for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
- ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
- if (ex_info->handlers)
- num_clauses += mono_array_length (ex_info->handlers);
- else
- num_clauses++;
- }
-
- return num_clauses;
+ MonoError error;
+ MonoReflectionField *result;
+ result = mono_field_get_object_checked (domain, klass, field, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-#ifndef DISABLE_REFLECTION_EMIT
-static MonoExceptionClause*
-method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
+static MonoReflectionField*
+field_object_construct (MonoDomain *domain, MonoClass *klass, MonoClassField *field, gpointer user_data, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoReflectionType *rt;
+ MonoReflectionField *res;
mono_error_init (error);
- MonoExceptionClause *clauses;
- MonoExceptionClause *clause;
- MonoILExceptionInfo *ex_info;
- MonoILExceptionBlock *ex_block;
- guint32 finally_start;
- int i, j, clause_index;;
-
- clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
-
- clause_index = 0;
- for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
- ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
- finally_start = ex_info->start + ex_info->len;
- if (!ex_info->handlers)
- continue;
- for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
- ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
- clause = &(clauses [clause_index]);
-
- clause->flags = ex_block->type;
- clause->try_offset = ex_info->start;
+ res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
+ if (!res)
+ return NULL;
+ res->klass = klass;
+ res->field = field;
+ MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
- clause->try_len = finally_start - ex_info->start;
- else
- clause->try_len = ex_info->len;
- clause->handler_offset = ex_block->start;
- clause->handler_len = ex_block->len;
- if (ex_block->extype) {
- MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
-
- if (!is_ok (error)) {
- image_g_free (image, clauses);
- return NULL;
- }
- clause->data.catch_class = mono_class_from_mono_type (extype);
- } else {
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
- clause->data.filter_offset = ex_block->filter_offset;
- else
- clause->data.filter_offset = 0;
- }
- finally_start = ex_block->start + ex_block->len;
+ if (field->type) {
+ rt = mono_type_get_object_checked (domain, field->type, error);
+ if (!mono_error_ok (error))
+ return NULL;
- clause_index ++;
- }
+ MONO_OBJECT_SETREF (res, type, rt);
}
-
- return clauses;
+ res->attrs = mono_field_get_flags (field);
+ return res;
}
-#endif /* !DISABLE_REFLECTION_EMIT */
-/**
- * method_encode_code:
- *
- * @assembly the assembly
- * @mb the managed MethodBuilder
- * @error set on error
+/*
+ * mono_field_get_object_checked:
+ * @domain: an app domain
+ * @klass: a type
+ * @field: a field
+ * @error: set on error
*
- * Note that the return value is not sensible if @error is set.
+ * Return an System.Reflection.MonoField object representing the field @field
+ * in class @klass. On error, returns NULL and sets @error.
*/
-static guint32
-method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
+MonoReflectionField*
+mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- char flags = 0;
- guint32 idx;
- guint32 code_size;
- gint32 max_stack, i;
- gint32 num_locals = 0;
- gint32 num_exception = 0;
- gint maybe_small;
- guint32 fat_flags;
- char fat_header [12];
- guint32 int_value;
- guint16 short_value;
- guint32 local_sig = 0;
- guint32 header_size = 12;
- MonoArray *code;
-
mono_error_init (error);
-
- if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
- (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
- return 0;
-
- /*if (mb->name)
- g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
- if (mb->ilgen) {
- code = mb->ilgen->code;
- code_size = mb->ilgen->code_len;
- max_stack = mb->ilgen->max_stack;
- num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
- if (mb->ilgen->ex_handlers)
- num_exception = method_count_clauses (mb->ilgen);
- } else {
- code = mb->code;
- if (code == NULL){
- MonoError inner_error;
- char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
- if (!is_ok (&inner_error)) {
- name = g_strdup ("");
- mono_error_cleanup (&inner_error);
- }
- char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
- mono_error_set_argument (error, NULL, "a method does not have any IL associated");
- g_free (str);
- g_free (name);
- return 0;
- }
-
- code_size = mono_array_length (code);
- max_stack = 8; /* we probably need to run a verifier on the code... */
- }
-
- stream_data_align (&assembly->code);
-
- /* check for exceptions, maxstack, locals */
- maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
- if (maybe_small) {
- if (code_size < 64 && !(code_size & 1)) {
- flags = (code_size << 2) | 0x2;
- } else if (code_size < 32 && (code_size & 1)) {
- flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
- } else {
- goto fat_header;
- }
- idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
- /* add to the fixup todo list */
- if (mb->ilgen && mb->ilgen->num_token_fixups)
- mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
- mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
- return assembly->text_rva + idx;
- }
-fat_header:
- if (num_locals) {
- local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
- return_val_if_nok (error, 0);
- }
- /*
- * FIXME: need to set also the header size in fat_flags.
- * (and more sects and init locals flags)
- */
- fat_flags = 0x03;
- if (num_exception)
- fat_flags |= METHOD_HEADER_MORE_SECTS;
- if (mb->init_locals)
- fat_flags |= METHOD_HEADER_INIT_LOCALS;
- fat_header [0] = fat_flags;
- fat_header [1] = (header_size / 4 ) << 4;
- short_value = GUINT16_TO_LE (max_stack);
- memcpy (fat_header + 2, &short_value, 2);
- int_value = GUINT32_TO_LE (code_size);
- memcpy (fat_header + 4, &int_value, 4);
- int_value = GUINT32_TO_LE (local_sig);
- memcpy (fat_header + 8, &int_value, 4);
- idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
- /* add to the fixup todo list */
- if (mb->ilgen && mb->ilgen->num_token_fixups)
- mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
-
- mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
- if (num_exception) {
- unsigned char sheader [4];
- MonoILExceptionInfo * ex_info;
- MonoILExceptionBlock * ex_block;
- int j;
-
- stream_data_align (&assembly->code);
- /* always use fat format for now */
- sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
- num_exception *= 6 * sizeof (guint32);
- num_exception += 4; /* include the size of the header */
- sheader [1] = num_exception & 0xff;
- sheader [2] = (num_exception >> 8) & 0xff;
- sheader [3] = (num_exception >> 16) & 0xff;
- mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
- /* fat header, so we are already aligned */
- /* reverse order */
- for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
- ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
- if (ex_info->handlers) {
- int finally_start = ex_info->start + ex_info->len;
- for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
- guint32 val;
- ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
- /* the flags */
- val = GUINT32_TO_LE (ex_block->type);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* try offset */
- val = GUINT32_TO_LE (ex_info->start);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* need fault, too, probably */
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
- val = GUINT32_TO_LE (finally_start - ex_info->start);
- else
- val = GUINT32_TO_LE (ex_info->len);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* handler offset */
- val = GUINT32_TO_LE (ex_block->start);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /* handler len */
- val = GUINT32_TO_LE (ex_block->len);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- finally_start = ex_block->start + ex_block->len;
- if (ex_block->extype) {
- MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
- return_val_if_nok (error, 0);
-
- val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
- } else {
- if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
- val = ex_block->filter_offset;
- else
- val = 0;
- }
- val = GUINT32_TO_LE (val);
- mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
- /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
- clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
- }
- } else {
- g_error ("No clauses for ex info block %d", i);
- }
- }
- }
- return assembly->text_rva + idx;
-}
-
-static guint32
-find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- int i;
- MonoDynamicTable *table;
- guint32 *values;
-
- table = &assembly->tables [table_idx];
-
- g_assert (col < table->columns);
-
- values = table->values + table->columns;
- for (i = 1; i <= table->rows; ++i) {
- if (values [col] == token)
- return i;
- values += table->columns;
- }
- return 0;
+ return CHECK_OR_CONSTRUCT (MonoReflectionField*, field, klass, field_object_construct, NULL);
}
/*
- * LOCKING: Acquires the loader lock.
+ * mono_property_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @property: a property
+ *
+ * Return an System.Reflection.MonoProperty object representing the property @property
+ * in class @klass.
*/
-static MonoCustomAttrInfo*
-lookup_custom_attr (MonoImage *image, gpointer member)
+MonoReflectionProperty*
+mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
{
- MONO_REQ_GC_NEUTRAL_MODE;
+ MonoError error;
+ MonoReflectionProperty *result;
+ result = mono_property_get_object_checked (domain, klass, property, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
- MonoCustomAttrInfo* res;
+static MonoReflectionProperty*
+property_object_construct (MonoDomain *domain, MonoClass *klass, MonoProperty *property, gpointer user_data, MonoError *error)
+{
+ MonoReflectionProperty *res;
- res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
+ mono_error_init (error);
+ res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
if (!res)
return NULL;
-
- res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
- res->cached = 0;
+ res->klass = klass;
+ res->property = property;
return res;
}
-static gboolean
-custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
+/**
+ * mono_property_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @property: a property
+ * @error: set on error
+ *
+ * Return an System.Reflection.MonoProperty object representing the property @property
+ * in class @klass. On error returns NULL and sets @error.
+ */
+MonoReflectionProperty*
+mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- /* FIXME: Need to do more checks */
- if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
- int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
-
- if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
- return FALSE;
- }
-
- return TRUE;
+ mono_error_init (error);
+ return CHECK_OR_CONSTRUCT (MonoReflectionProperty*, property, klass, property_object_construct, NULL);
}
-static MonoCustomAttrInfo*
-mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
+/*
+ * mono_event_get_object:
+ * @domain: an app domain
+ * @klass: a type
+ * @event: a event
+ *
+ * Return an System.Reflection.MonoEvent object representing the event @event
+ * in class @klass.
+ */
+MonoReflectionEvent*
+mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+ MonoReflectionEvent *result;
+ result = mono_event_get_object_checked (domain, klass, event, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
- int i, index, count, not_visible;
- MonoCustomAttrInfo *ainfo;
- MonoReflectionCustomAttr *cattr;
+static MonoReflectionEvent*
+event_object_construct (MonoDomain *domain, MonoClass *klass, MonoEvent *event, gpointer user_data, MonoError *error)
+{
+ MonoReflectionMonoEvent *mono_event;
- if (!cattrs)
+ mono_error_init (error);
+ mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
+ if (!mono_event)
return NULL;
- /* FIXME: check in assembly the Run flag is set */
-
- count = mono_array_length (cattrs);
-
- /* Skip nonpublic attributes since MS.NET seems to do the same */
- /* FIXME: This needs to be done more globally */
- not_visible = 0;
- for (i = 0; i < count; ++i) {
- cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
- if (!custom_attr_visible (image, cattr))
- not_visible ++;
- }
- count -= not_visible;
-
- ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
-
- ainfo->image = image;
- ainfo->num_attrs = count;
- ainfo->cached = alloc_img != NULL;
- index = 0;
- for (i = 0; i < count; ++i) {
- cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
- if (custom_attr_visible (image, cattr)) {
- unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
- memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
- ainfo->attrs [index].ctor = cattr->ctor->method;
- ainfo->attrs [index].data = saved;
- ainfo->attrs [index].data_size = mono_array_length (cattr->data);
- index ++;
- }
- }
-
- return ainfo;
+ mono_event->klass = klass;
+ mono_event->event = event;
+ return &mono_event->object;
}
-#ifndef DISABLE_REFLECTION_EMIT
-/*
- * LOCKING: Acquires the loader lock.
+/**
+ * mono_event_get_object_checked:
+ * @domain: an app domain
+ * @klass: a type
+ * @event: a event
+ * @error: set on error
+ *
+ * Return an System.Reflection.MonoEvent object representing the event @event
+ * in class @klass. On failure sets @error and returns NULL
*/
-static void
-mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoCustomAttrInfo *ainfo, *tmp;
-
- if (!cattrs || !mono_array_length (cattrs))
- return;
-
- ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
-
- mono_loader_lock ();
- tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
- if (tmp)
- mono_custom_attrs_free (tmp);
- mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
- mono_loader_unlock ();
-
-}
-#endif
-
-void
-mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
+MonoReflectionEvent*
+mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (ainfo && !ainfo->cached)
- g_free (ainfo);
+ mono_error_init (error);
+ return CHECK_OR_CONSTRUCT (MonoReflectionEvent*, event, klass, event_object_construct, NULL);
}
-/*
- * idx is the table index of the object
- * type is one of MONO_CUSTOM_ATTR_*
+/**
+ * mono_get_reflection_missing_object:
+ * @domain: Domain where the object lives
+ *
+ * Returns the System.Reflection.Missing.Value singleton object
+ * (of type System.Reflection.Missing).
+ *
+ * Used as the value for ParameterInfo.DefaultValue when Optional
+ * is present
*/
-static gboolean
-mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
+static MonoObject *
+mono_get_reflection_missing_object (MonoDomain *domain)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- MonoReflectionCustomAttr *cattr;
- guint32 *values;
- guint32 count, i, token;
- char blob_size [6];
- char *p = blob_size;
+ MonoError error;
+ MonoObject *obj;
+ static MonoClassField *missing_value_field = NULL;
- mono_error_init (error);
-
- /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
- if (!cattrs)
- return TRUE;
- count = mono_array_length (cattrs);
- table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
- table->rows += count;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= type;
- for (i = 0; i < count; ++i) {
- cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
- values [MONO_CUSTOM_ATTR_PARENT] = idx;
- token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
- if (!mono_error_ok (error)) goto fail;
- type = mono_metadata_token_index (token);
- type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
- switch (mono_metadata_token_table (token)) {
- case MONO_TABLE_METHOD:
- type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
- /*
- * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
- * method, not the one returned by mono_image_create_token ().
- */
- mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
- break;
- case MONO_TABLE_MEMBERREF:
- type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
- break;
- default:
- g_warning ("got wrong token in custom attr");
- continue;
- }
- values [MONO_CUSTOM_ATTR_TYPE] = type;
- p = blob_size;
- mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
- values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
- mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
- values += MONO_CUSTOM_ATTR_SIZE;
- ++table->next_idx;
- }
-
- return TRUE;
-
-fail:
- return FALSE;
-}
-
-static void
-mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 count, i, idx;
- MonoReflectionPermissionSet *perm;
-
- if (!permissions)
- return;
-
- count = mono_array_length (permissions);
- table = &assembly->tables [MONO_TABLE_DECLSECURITY];
- table->rows += count;
- alloc_table (table, table->rows);
-
- for (i = 0; i < mono_array_length (permissions); ++i) {
- perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
-
- values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
-
- idx = mono_metadata_token_index (parent_token);
- idx <<= MONO_HAS_DECL_SECURITY_BITS;
- switch (mono_metadata_token_table (parent_token)) {
- case MONO_TABLE_TYPEDEF:
- idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
- break;
- case MONO_TABLE_METHOD:
- idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
- break;
- case MONO_TABLE_ASSEMBLY:
- idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
- break;
- default:
- g_assert_not_reached ();
- }
-
- values [MONO_DECL_SECURITY_ACTION] = perm->action;
- values [MONO_DECL_SECURITY_PARENT] = idx;
- values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
-
- ++table->next_idx;
+ if (!missing_value_field) {
+ MonoClass *missing_klass;
+ missing_klass = mono_class_get_missing_class ();
+ mono_class_init (missing_klass);
+ missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
+ g_assert (missing_value_field);
}
+ obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
+ mono_error_assert_ok (&error);
+ return obj;
}
-/*
- * Fill in the MethodDef and ParamDef tables for a method.
- * This is used for both normal methods and constructors.
- */
-static gboolean
-mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
+static MonoObject*
+get_dbnull_object (MonoDomain *domain, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint i, count;
+ MonoObject *obj;
+ static MonoClassField *dbnull_value_field = NULL;
mono_error_init (error);
- /* room in this table is already allocated */
- table = &assembly->tables [MONO_TABLE_METHOD];
- *mb->table_idx = table->next_idx ++;
- g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
- values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
- values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
- return_val_if_nok (error, FALSE);
- values [MONO_METHOD_FLAGS] = mb->attrs;
- values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
- values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
- return_val_if_nok (error, FALSE);
- values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
- return_val_if_nok (error, FALSE);
-
- table = &assembly->tables [MONO_TABLE_PARAM];
- values [MONO_METHOD_PARAMLIST] = table->next_idx;
-
- mono_image_add_decl_security (assembly,
- mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
-
- if (mb->pinfo) {
- MonoDynamicTable *mtable;
- guint32 *mvalues;
-
- mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
- mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
-
- count = 0;
- for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
- if (mono_array_get (mb->pinfo, gpointer, i))
- count++;
- }
- table->rows += count;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_PARAM_SIZE;
- for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
- MonoReflectionParamBuilder *pb;
- if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
- values [MONO_PARAM_FLAGS] = pb->attrs;
- values [MONO_PARAM_SEQUENCE] = i;
- if (pb->name != NULL) {
- values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
- return_val_if_nok (error, FALSE);
- } else {
- values [MONO_PARAM_NAME] = 0;
- }
- values += MONO_PARAM_SIZE;
- if (pb->marshal_info) {
- mtable->rows++;
- alloc_table (mtable, mtable->rows);
- mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
- mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
- mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
- return_val_if_nok (error, FALSE);
- }
- pb->table_idx = table->next_idx++;
- if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
- guint32 field_type = 0;
- mtable = &assembly->tables [MONO_TABLE_CONSTANT];
- mtable->rows ++;
- alloc_table (mtable, mtable->rows);
- mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
- mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
- mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
- mvalues [MONO_CONSTANT_TYPE] = field_type;
- mvalues [MONO_CONSTANT_PADDING] = 0;
- }
- }
- }
+ if (!dbnull_value_field) {
+ MonoClass *dbnull_klass;
+ dbnull_klass = mono_class_get_dbnull_class ();
+ dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
+ g_assert (dbnull_value_field);
}
-
- return TRUE;
+ obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, error);
+ return obj;
}
-#ifndef DISABLE_REFLECTION_EMIT
-static gboolean
-reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
+static MonoObject*
+get_dbnull (MonoDomain *domain, MonoObject **dbnull, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
mono_error_init (error);
- memset (rmb, 0, sizeof (ReflectionMethodBuilder));
-
- rmb->ilgen = mb->ilgen;
- rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
- return_val_if_nok (error, FALSE);
- rmb->parameters = mb->parameters;
- rmb->generic_params = mb->generic_params;
- rmb->generic_container = mb->generic_container;
- rmb->opt_types = NULL;
- rmb->pinfo = mb->pinfo;
- rmb->attrs = mb->attrs;
- rmb->iattrs = mb->iattrs;
- rmb->call_conv = mb->call_conv;
- rmb->code = mb->code;
- rmb->type = mb->type;
- rmb->name = mb->name;
- rmb->table_idx = &mb->table_idx;
- rmb->init_locals = mb->init_locals;
- rmb->skip_visibility = FALSE;
- rmb->return_modreq = mb->return_modreq;
- rmb->return_modopt = mb->return_modopt;
- rmb->param_modreq = mb->param_modreq;
- rmb->param_modopt = mb->param_modopt;
- rmb->permissions = mb->permissions;
- rmb->mhandle = mb->mhandle;
- rmb->nrefs = 0;
- rmb->refs = NULL;
-
- if (mb->dll) {
- rmb->charset = mb->charset;
- rmb->extra_flags = mb->extra_flags;
- rmb->native_cc = mb->native_cc;
- rmb->dllentry = mb->dllentry;
- rmb->dll = mb->dll;
- }
-
- return TRUE;
+ if (!*dbnull)
+ *dbnull = get_dbnull_object (domain, error);
+ return *dbnull;
}
-static gboolean
-reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
+static MonoObject*
+get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
-
- mono_error_init (error);
-
- memset (rmb, 0, sizeof (ReflectionMethodBuilder));
-
- rmb->ilgen = mb->ilgen;
- rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
- return_val_if_nok (error, FALSE);
- rmb->parameters = mb->parameters;
- rmb->generic_params = NULL;
- rmb->generic_container = NULL;
- rmb->opt_types = NULL;
- rmb->pinfo = mb->pinfo;
- rmb->attrs = mb->attrs;
- rmb->iattrs = mb->iattrs;
- rmb->call_conv = mb->call_conv;
- rmb->code = NULL;
- rmb->type = mb->type;
- rmb->name = mono_string_new (mono_domain_get (), name);
- rmb->table_idx = &mb->table_idx;
- rmb->init_locals = mb->init_locals;
- rmb->skip_visibility = FALSE;
- rmb->return_modreq = NULL;
- rmb->return_modopt = NULL;
- rmb->param_modreq = mb->param_modreq;
- rmb->param_modopt = mb->param_modopt;
- rmb->permissions = mb->permissions;
- rmb->mhandle = mb->mhandle;
- rmb->nrefs = 0;
- rmb->refs = NULL;
-
- return TRUE;
+ if (!*reflection_missing)
+ *reflection_missing = mono_get_reflection_missing_object (domain);
+ return *reflection_missing;
}
-static void
-reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
+static MonoArray*
+param_objects_construct (MonoDomain *domain, MonoClass *refclass, MonoMethodSignature **addr_of_sig, gpointer user_data, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- memset (rmb, 0, sizeof (ReflectionMethodBuilder));
-
- rmb->ilgen = mb->ilgen;
- rmb->rtype = mb->rtype;
- rmb->parameters = mb->parameters;
- rmb->generic_params = NULL;
- rmb->generic_container = NULL;
- rmb->opt_types = NULL;
- rmb->pinfo = NULL;
- rmb->attrs = mb->attrs;
- rmb->iattrs = 0;
- rmb->call_conv = mb->call_conv;
- rmb->code = NULL;
- rmb->type = (MonoObject *) mb->owner;
- rmb->name = mb->name;
- rmb->table_idx = NULL;
- rmb->init_locals = mb->init_locals;
- rmb->skip_visibility = mb->skip_visibility;
- rmb->return_modreq = NULL;
- rmb->return_modopt = NULL;
- rmb->param_modreq = NULL;
- rmb->param_modopt = NULL;
- rmb->permissions = NULL;
- rmb->mhandle = mb->mhandle;
- rmb->nrefs = 0;
- rmb->refs = NULL;
-}
-#endif
+ static MonoClass *System_Reflection_ParameterInfo;
+ static MonoClass *System_Reflection_ParameterInfo_array;
-static gboolean
-mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ MonoMethod *method = (MonoMethod*)user_data;
+ MonoMethodSignature *sig = *addr_of_sig; /* see note in mono_param_get_objects_internal */
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
- MonoDynamicTable *table;
- guint32 *values;
- guint32 tok;
- MonoReflectionMethod *m;
+ MonoArray *res = NULL;
+ MonoReflectionMethod *member = NULL;
+ MonoReflectionParameter *param = NULL;
+ char **names = NULL, **blobs = NULL;
+ guint32 *types = NULL;
+ MonoType *type = NULL;
+ MonoObject *dbnull = NULL;
+ MonoObject *missing = NULL;
+ MonoMarshalSpec **mspecs = NULL;
+ MonoVTable *pinfo_vtable;
+ MonoReflectionType *rt;
int i;
mono_error_init (error);
+
+ if (!System_Reflection_ParameterInfo_array) {
+ MonoClass *klass;
+ klass = mono_class_get_mono_parameter_info_class ();
+ System_Reflection_ParameterInfo = klass;
+ klass = mono_array_class_get (klass, 1);
+ System_Reflection_ParameterInfo_array = klass;
+ }
- if (!mb->override_methods)
- return TRUE;
-
- for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
- m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
+ member = mono_method_get_object_checked (domain, method, refclass, error);
+ if (!member)
+ goto leave;
+ names = g_new (char *, sig->param_count);
+ mono_method_get_param_names (method, (const char **) names);
- table = &assembly->tables [MONO_TABLE_METHODIMPL];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_METHODIMPL_SIZE;
- values [MONO_METHODIMPL_CLASS] = tb->table_idx;
- values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+ mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
+ mono_method_get_marshal_info (method, mspecs);
- tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
- return_val_if_nok (error, FALSE);
+ res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
+ if (!res)
+ goto leave;
- switch (mono_metadata_token_table (tok)) {
- case MONO_TABLE_MEMBERREF:
- tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
- break;
- case MONO_TABLE_METHOD:
- tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
- break;
- default:
- g_assert_not_reached ();
- }
- values [MONO_METHODIMPL_DECLARATION] = tok;
- }
+ pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
+ for (i = 0; i < sig->param_count; ++i) {
+ param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
+ if (!param)
+ goto leave;
- return TRUE;
-}
+ rt = mono_type_get_object_checked (domain, sig->params [i], error);
+ if (!rt)
+ goto leave;
-#ifndef DISABLE_REFLECTION_EMIT
-static gboolean
-mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ MONO_OBJECT_SETREF (param, ClassImpl, rt);
- MonoDynamicTable *table;
- guint32 *values;
- ReflectionMethodBuilder rmb;
- int i;
+ MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
- mono_error_init (error);
+ MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
- !mono_image_basic_method (&rmb, assembly, error))
- return FALSE;
+ param->PositionImpl = i;
+ param->AttrsImpl = sig->params [i]->attrs;
- mb->table_idx = *rmb.table_idx;
-
- if (mb->dll) { /* It's a P/Invoke method */
- guint32 moduleref;
- /* map CharSet values to on-disk values */
- int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
- int extra_flags = mb->extra_flags;
- table = &assembly->tables [MONO_TABLE_IMPLMAP];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_IMPLMAP_SIZE;
-
- values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
- values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
- if (mb->dllentry) {
- values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
- return_val_if_nok (error, FALSE);
+ if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
+ if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
+ else
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull, error));
+ if (!is_ok (error))
+ goto leave;
} else {
- values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
- return_val_if_nok (error, FALSE);
- }
- moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
- return_val_if_nok (error, FALSE);
- if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
- table = &assembly->tables [MONO_TABLE_MODULEREF];
- table->rows ++;
- alloc_table (table, table->rows);
- table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
- values [MONO_IMPLMAP_SCOPE] = table->rows;
- }
- }
-
- if (mb->generic_params) {
- table = &assembly->tables [MONO_TABLE_GENERICPARAM];
- table->rows += mono_array_length (mb->generic_params);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
- guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
-
- mono_image_get_generic_param_info (
- (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
- }
- }
- return TRUE;
-}
+ if (!blobs) {
+ blobs = g_new0 (char *, sig->param_count);
+ types = g_new0 (guint32, sig->param_count);
+ get_default_param_value_blobs (method, blobs, types);
+ }
-static gboolean
-mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ /* Build MonoType for the type from the Constant Table */
+ if (!type)
+ type = g_new0 (MonoType, 1);
+ type->type = (MonoTypeEnum)types [i];
+ type->data.klass = NULL;
+ if (types [i] == MONO_TYPE_CLASS)
+ type->data.klass = mono_defaults.object_class;
+ else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
+ /* For enums, types [i] contains the base type */
- ReflectionMethodBuilder rmb;
+ type->type = MONO_TYPE_VALUETYPE;
+ type->data.klass = mono_class_from_mono_type (sig->params [i]);
+ } else
+ type->data.klass = mono_class_from_mono_type (type);
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
- return FALSE;
+ MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
+ if (!is_ok (error))
+ goto leave;
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
- if (!mono_image_basic_method (&rmb, assembly, error))
- return FALSE;
+ /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
+ if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
+ if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
+ else
+ MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull, error));
+ if (!is_ok (error))
+ goto leave;
+ }
+ }
- mb->table_idx = *rmb.table_idx;
+ if (mspecs [i + 1]) {
+ MonoReflectionMarshalAsAttribute* mobj;
+ mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
+ if (!mobj)
+ goto leave;
+ MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
+ }
+
+ mono_array_setref (res, i, param);
+ }
- return TRUE;
-}
-#endif
+leave:
+ g_free (names);
+ g_free (blobs);
+ g_free (types);
+ g_free (type);
-static char*
-type_get_fully_qualified_name (MonoType *type)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
+ if (sig) {
+ for (i = sig->param_count; i >= 0; i--) {
+ if (mspecs [i])
+ mono_metadata_free_marshal_spec (mspecs [i]);
+ }
+ }
+ g_free (mspecs);
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
+ if (!is_ok (error))
+ return NULL;
+
+ return res;
}
-static char*
-type_get_qualified_name (MonoType *type, MonoAssembly *ass)
+/*
+ * mono_param_get_objects:
+ * @domain: an app domain
+ * @method: a method
+ *
+ * Return an System.Reflection.ParameterInfo array object representing the parameters
+ * in the method @method.
+ */
+MonoArray*
+mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ mono_error_init (error);
- MonoClass *klass;
- MonoAssembly *ta;
+ MonoMethodSignature *sig = mono_method_signature_checked (method, error);
+ if (!mono_error_ok (error))
+ goto leave;
- klass = mono_class_from_mono_type (type);
- if (!klass)
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
- ta = klass->image->assembly;
- if (assembly_is_dynamic (ta) || (ta == ass)) {
- if (klass->generic_class || klass->generic_container)
- /* For generic type definitions, we want T, while REFLECTION returns T<K> */
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
- else
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
+ if (!sig->param_count) {
+ MonoArray *res = mono_array_new_checked (domain, mono_class_get_mono_parameter_info_class (), 0, error);
+ if (!res)
+ goto leave;
+
+ return res;
}
- return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
+ /* Note: the cache is based on the address of the signature into the method
+ * since we already cache MethodInfos with the method as keys.
+ */
+ return CHECK_OR_CONSTRUCT (MonoArray*, &method->signature, refclass, param_objects_construct, method);
+leave:
+ return NULL;
}
-#ifndef DISABLE_REFLECTION_EMIT
-/*field_image is the image to which the eventual custom mods have been encoded against*/
-static guint32
-fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
+MonoArray*
+mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- SigBuffer buf;
- guint32 idx, i, token;
+ MonoError error;
+ MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
+ mono_error_assert_ok (&error);
+ return result;
+}
- if (!assembly->save)
- return 0;
+/*
+ * mono_method_body_get_object:
+ * @domain: an app domain
+ * @method: a method
+ *
+ * Return an System.Reflection.MethodBody object representing the method @method.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
+{
+ MonoError error;
+ MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
+ mono_error_cleanup (&error);
+ return result;
+}
- sigbuffer_init (&buf, 32);
-
- sigbuffer_add_value (&buf, 0x06);
- /* encode custom attributes before the type */
- if (type->num_mods) {
- for (i = 0; i < type->num_mods; ++i) {
- if (field_image) {
- MonoError error;
- MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
- g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
-
- token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
- } else {
- token = type->modifiers [i].token;
- }
+static MonoReflectionMethodBody*
+method_body_object_construct (MonoDomain *domain, MonoClass *unused_class, MonoMethod *method, gpointer user_data, MonoError *error)
+{
+ MonoReflectionMethodBody *ret;
+ MonoMethodHeader *header;
+ MonoImage *image;
+ MonoReflectionType *rt;
+ guint32 method_rva, local_var_sig_token;
+ char *ptr;
+ unsigned char format, flags;
+ int i;
- if (type->modifiers [i].required)
- sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
- else
- sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
+ mono_error_init (error);
- sigbuffer_add_value (&buf, token);
- }
+ /* for compatibility with .net */
+ if (method_is_dynamic (method)) {
+ mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
+ return NULL;
}
- encode_type (assembly, type, &buf);
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
-#endif
-static guint32
-field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
+ (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+ (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
+ (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
+ return NULL;
- mono_error_init (error);
+ image = method->klass->image;
+ header = mono_method_get_header_checked (method, error);
+ return_val_if_nok (error, NULL);
- SigBuffer buf;
- guint32 idx;
- guint32 typespec = 0;
- MonoType *type;
- MonoClass *klass;
+ if (!image_is_dynamic (image)) {
+ /* Obtain local vars signature token */
+ method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
+ ptr = mono_image_rva_map (image, method_rva);
+ flags = *(const unsigned char *) ptr;
+ format = flags & METHOD_HEADER_FORMAT_MASK;
+ switch (format){
+ case METHOD_HEADER_TINY_FORMAT:
+ local_var_sig_token = 0;
+ break;
+ case METHOD_HEADER_FAT_FORMAT:
+ ptr += 2;
+ ptr += 2;
+ ptr += 4;
+ local_var_sig_token = read32 (ptr);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ } else
+ local_var_sig_token = 0; //FIXME
- init_type_builder_generics (fb->type, error);
- return_val_if_nok (error, 0);
+ ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
+ if (!is_ok (error))
+ goto fail;
- type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
+ ret->init_locals = header->init_locals;
+ ret->max_stack = header->max_stack;
+ ret->local_var_sig_token = local_var_sig_token;
+ MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
+ if (!is_ok (error))
+ goto fail;
+ MONO_OBJECT_SETREF (ret, il, il_arr);
+ memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
- sigbuffer_init (&buf, 32);
-
- sigbuffer_add_value (&buf, 0x06);
- encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
+ /* Locals */
+ MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
if (!is_ok (error))
goto fail;
- /* encode custom attributes before the type */
+ MONO_OBJECT_SETREF (ret, locals, locals_arr);
+ for (i = 0; i < header->num_locals; ++i) {
+ MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
+ if (!is_ok (error))
+ goto fail;
- if (klass->generic_container)
- typespec = create_typespec (assembly, type);
+ rt = mono_type_get_object_checked (domain, header->locals [i], error);
+ if (!is_ok (error))
+ goto fail;
- if (typespec) {
- MonoGenericClass *gclass;
- gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
- encode_generic_class (assembly, gclass, &buf);
- } else {
- encode_type (assembly, type, &buf);
+ MONO_OBJECT_SETREF (info, local_type, rt);
+
+ info->is_pinned = header->locals [i]->pinned;
+ info->local_index = i;
+ mono_array_setref (ret->locals, i, info);
}
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-fail:
- sigbuffer_free (&buf);
- return 0;
-}
-static guint32
-encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ /* Exceptions */
+ MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
+ if (!is_ok (error))
+ goto fail;
+ MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
+ for (i = 0; i < header->num_clauses; ++i) {
+ MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
+ if (!is_ok (error))
+ goto fail;
+ MonoExceptionClause *clause = &header->clauses [i];
- char blob_size [64];
- char *b = blob_size;
- char *box_val;
- char* buf;
- guint32 idx = 0, len = 0, dummy = 0;
-
- buf = (char *)g_malloc (64);
- if (!val) {
- *ret_type = MONO_TYPE_CLASS;
- len = 4;
- box_val = (char*)&dummy;
- } else {
- box_val = ((char*)val) + sizeof (MonoObject);
- *ret_type = val->vtable->klass->byval_arg.type;
- }
-handle_enum:
- switch (*ret_type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- len = 1;
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- len = 2;
- break;
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4:
- len = 4;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- len = 8;
- break;
- case MONO_TYPE_R8:
- len = 8;
- break;
- case MONO_TYPE_VALUETYPE: {
- MonoClass *klass = val->vtable->klass;
-
- if (klass->enumtype) {
- *ret_type = mono_class_enum_basetype (klass)->type;
- goto handle_enum;
- } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
- len = 8;
- } else
- g_error ("we can't encode valuetypes, we should have never reached this line");
- break;
- }
- case MONO_TYPE_CLASS:
- break;
- case MONO_TYPE_STRING: {
- MonoString *str = (MonoString*)val;
- /* there is no signature */
- len = str->length * 2;
- mono_metadata_encode_value (len, b, &b);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- {
- char *swapped = g_malloc (2 * mono_string_length (str));
- const char *p = (const char*)mono_string_chars (str);
-
- swap_with_size (swapped, p, 2, mono_string_length (str));
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
- g_free (swapped);
+ info->flags = clause->flags;
+ info->try_offset = clause->try_offset;
+ info->try_length = clause->try_len;
+ info->handler_offset = clause->handler_offset;
+ info->handler_length = clause->handler_len;
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
+ info->filter_offset = clause->data.filter_offset;
+ else if (clause->data.catch_class) {
+ rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
+ if (!is_ok (error))
+ goto fail;
+
+ MONO_OBJECT_SETREF (info, catch_type, rt);
}
-#else
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
-#endif
- g_free (buf);
- return idx;
- }
- case MONO_TYPE_GENERICINST:
- *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
- goto handle_enum;
- default:
- g_error ("we don't encode constant type 0x%02x yet", *ret_type);
+ mono_array_setref (ret->clauses, i, info);
}
- /* there is no signature */
- mono_metadata_encode_value (len, b, &b);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- swap_with_size (blob_size, box_val, len, 1);
- mono_image_add_stream_data (&assembly->blob, blob_size, len);
-#else
- idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
-#endif
-
- g_free (buf);
- return idx;
+ mono_metadata_free_mh (header);
+ return ret;
+fail:
+ mono_metadata_free_mh (header);
+ return NULL;
}
-static guint32
-encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
+/**
+ * mono_method_body_get_object_checked:
+ * @domain: an app domain
+ * @method: a method
+ * @error: set on error
+ *
+ * Return an System.Reflection.MethodBody object representing the
+ * method @method. On failure, returns NULL and sets @error.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
mono_error_init (error);
+ return CHECK_OR_CONSTRUCT (MonoReflectionMethodBody *, method, NULL, method_body_object_construct, NULL);
+}
- char *str;
- SigBuffer buf;
- guint32 idx, len;
+/**
+ * mono_get_dbnull_object:
+ * @domain: Domain where the object lives
+ *
+ * Returns the System.DBNull.Value singleton object
+ *
+ * Used as the value for ParameterInfo.DefaultValue
+ */
+MonoObject *
+mono_get_dbnull_object (MonoDomain *domain)
+{
+ MonoError error;
+ MonoObject *obj;
- sigbuffer_init (&buf, 32);
+ obj = get_dbnull_object (domain, &error);
+ mono_error_assert_ok (&error);
+ return obj;
+}
- sigbuffer_add_value (&buf, minfo->type);
+static void
+get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
+{
+ guint32 param_index, i, lastp, crow = 0;
+ guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
+ gint32 idx;
- switch (minfo->type) {
- case MONO_NATIVE_BYVALTSTR:
- case MONO_NATIVE_BYVALARRAY:
- sigbuffer_add_value (&buf, minfo->count);
- break;
- case MONO_NATIVE_LPARRAY:
- if (minfo->eltype || minfo->has_size) {
- sigbuffer_add_value (&buf, minfo->eltype);
- if (minfo->has_size) {
- sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
- sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
+ MonoClass *klass = method->klass;
+ MonoImage *image = klass->image;
+ MonoMethodSignature *methodsig = mono_method_signature (method);
- /* LAMESPEC: ElemMult is undocumented */
- sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
- }
- }
- break;
- case MONO_NATIVE_SAFEARRAY:
- if (minfo->eltype)
- sigbuffer_add_value (&buf, minfo->eltype);
- break;
- case MONO_NATIVE_CUSTOM:
- if (minfo->guid) {
- str = mono_string_to_utf8_checked (minfo->guid, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- len = strlen (str);
- sigbuffer_add_value (&buf, len);
- sigbuffer_add_mem (&buf, str, len);
- g_free (str);
- } else {
- sigbuffer_add_value (&buf, 0);
- }
- /* native type name */
- sigbuffer_add_value (&buf, 0);
- /* custom marshaler type name */
- if (minfo->marshaltype || minfo->marshaltyperef) {
- if (minfo->marshaltyperef) {
- MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- str = type_get_fully_qualified_name (marshaltype);
- } else {
- str = mono_string_to_utf8_checked (minfo->marshaltype, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- }
- len = strlen (str);
- sigbuffer_add_value (&buf, len);
- sigbuffer_add_mem (&buf, str, len);
- g_free (str);
- } else {
- /* FIXME: Actually a bug, since this field is required. Punting for now ... */
- sigbuffer_add_value (&buf, 0);
- }
- if (minfo->mcookie) {
- str = mono_string_to_utf8_checked (minfo->mcookie, error);
- if (!is_ok (error)) {
- sigbuffer_free (&buf);
- return 0;
- }
- len = strlen (str);
- sigbuffer_add_value (&buf, len);
- sigbuffer_add_mem (&buf, str, len);
- g_free (str);
- } else {
- sigbuffer_add_value (&buf, 0);
- }
- break;
- default:
- break;
- }
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
+ MonoTableInfo *constt;
+ MonoTableInfo *methodt;
+ MonoTableInfo *paramt;
-static void
-mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ if (!methodsig->param_count)
+ return;
- mono_error_init (error);
+ mono_class_init (klass);
- MonoDynamicTable *table;
- guint32 *values;
-
- /* maybe this fixup should be done in the C# code */
- if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
- fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
- table = &assembly->tables [MONO_TABLE_FIELD];
- fb->table_idx = table->next_idx ++;
- g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
- values = table->values + fb->table_idx * MONO_FIELD_SIZE;
- values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
- return_if_nok (error);
- values [MONO_FIELD_FLAGS] = fb->attrs;
- values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
- return_if_nok (error);
-
-
- if (fb->offset != -1) {
- table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
- values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
- values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
- }
- if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
- MonoTypeEnum field_type = (MonoTypeEnum)0;
- table = &assembly->tables [MONO_TABLE_CONSTANT];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_CONSTANT_SIZE;
- values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
- values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
- values [MONO_CONSTANT_TYPE] = field_type;
- values [MONO_CONSTANT_PADDING] = 0;
- }
- if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
- guint32 rva_idx;
- table = &assembly->tables [MONO_TABLE_FIELDRVA];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
- values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
- /*
- * We store it in the code section because it's simpler for now.
- */
- if (fb->rva_data) {
- if (mono_array_length (fb->rva_data) >= 10)
- stream_data_align (&assembly->code);
- rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
- } else
- rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
- values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
- }
- if (fb->marshal_info) {
- table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
- values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
- values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
- return_if_nok (error);
+ if (image_is_dynamic (klass->image)) {
+ MonoReflectionMethodAux *aux;
+ if (method->is_inflated)
+ method = ((MonoMethodInflated*)method)->declaring;
+ aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+ if (aux && aux->param_defaults) {
+ memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
+ memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
+ }
+ return;
}
-}
-static guint32
-property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
+ methodt = &klass->image->tables [MONO_TABLE_METHOD];
+ paramt = &klass->image->tables [MONO_TABLE_PARAM];
+ constt = &image->tables [MONO_TABLE_CONSTANT];
- mono_error_init (error);
+ idx = mono_method_get_index (method) - 1;
+ g_assert (idx != -1);
- SigBuffer buf;
- guint32 nparams = 0;
- MonoReflectionMethodBuilder *mb = fb->get_method;
- MonoReflectionMethodBuilder *smb = fb->set_method;
- guint32 idx, i;
-
- if (mb && mb->parameters)
- nparams = mono_array_length (mb->parameters);
- if (!mb && smb && smb->parameters)
- nparams = mono_array_length (smb->parameters) - 1;
- sigbuffer_init (&buf, 32);
- if (fb->call_conv & 0x20)
- sigbuffer_add_byte (&buf, 0x28);
+ param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
+ if (idx + 1 < methodt->rows)
+ lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
else
- sigbuffer_add_byte (&buf, 0x08);
- sigbuffer_add_value (&buf, nparams);
- if (mb) {
- encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
- if (!is_ok (error))
- goto fail;
- for (i = 0; i < nparams; ++i) {
- MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto fail;
- }
- } else if (smb && smb->parameters) {
- /* the property type is the last param */
- encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
- if (!is_ok (error))
- goto fail;
+ lastp = paramt->rows + 1;
- for (i = 0; i < nparams; ++i) {
- MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto fail;
+ for (i = param_index; i < lastp; ++i) {
+ guint32 paramseq;
+
+ mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
+ paramseq = param_cols [MONO_PARAM_SEQUENCE];
+
+ if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
+ continue;
+
+ crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
+ if (!crow) {
+ continue;
}
- } else {
- encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
- if (!is_ok (error))
- goto fail;
+
+ mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
+ blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
+ types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
}
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-fail:
- sigbuffer_free (&buf);
- return 0;
+ return;
}
-static void
-mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
+MonoObject *
+mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ void *retval;
+ MonoClass *klass;
+ MonoObject *object;
+ MonoType *basetype = type;
mono_error_init (error);
- MonoDynamicTable *table;
- guint32 *values;
- guint num_methods = 0;
- guint32 semaidx;
-
- /*
- * we need to set things in the following tables:
- * PROPERTYMAP (info already filled in _get_type_info ())
- * PROPERTY (rows already preallocated in _get_type_info ())
- * METHOD (method info already done with the generic method code)
- * METHODSEMANTICS
- * CONSTANT
- */
- table = &assembly->tables [MONO_TABLE_PROPERTY];
- pb->table_idx = table->next_idx ++;
- values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
- values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
- return_if_nok (error);
- values [MONO_PROPERTY_FLAGS] = pb->attrs;
- values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
- return_if_nok (error);
-
-
- /* FIXME: we still don't handle 'other' methods */
- if (pb->get_method) num_methods ++;
- if (pb->set_method) num_methods ++;
-
- table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
- table->rows += num_methods;
- alloc_table (table, table->rows);
-
- if (pb->get_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
- values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
- }
- if (pb->set_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
- values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
- }
- if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
- MonoTypeEnum field_type = (MonoTypeEnum)0;
- table = &assembly->tables [MONO_TABLE_CONSTANT];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_CONSTANT_SIZE;
- values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
- values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
- values [MONO_CONSTANT_TYPE] = field_type;
- values [MONO_CONSTANT_PADDING] = 0;
+ if (!blob)
+ return NULL;
+
+ klass = mono_class_from_mono_type (type);
+ if (klass->valuetype) {
+ object = mono_object_new_checked (domain, klass, error);
+ return_val_if_nok (error, NULL);
+ retval = ((gchar *) object + sizeof (MonoObject));
+ if (klass->enumtype)
+ basetype = mono_class_enum_basetype (klass);
+ } else {
+ retval = &object;
}
+
+ if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
+ return object;
+ else
+ return NULL;
}
-static void
-mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint num_methods = 0;
- guint32 semaidx;
+static int
+assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
+ int found_sep;
+ char *s;
+ gboolean quoted = FALSE;
- /*
- * we need to set things in the following tables:
- * EVENTMAP (info already filled in _get_type_info ())
- * EVENT (rows already preallocated in _get_type_info ())
- * METHOD (method info already done with the generic method code)
- * METHODSEMANTICS
- */
- table = &assembly->tables [MONO_TABLE_EVENT];
- eb->table_idx = table->next_idx ++;
- values = table->values + eb->table_idx * MONO_EVENT_SIZE;
- values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
- return_if_nok (error);
- values [MONO_EVENT_FLAGS] = eb->attrs;
- MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
- return_if_nok (error);
- values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
+ memset (assembly, 0, sizeof (MonoAssemblyName));
+ assembly->culture = "";
+ memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
- /*
- * FIXME: we still don't handle 'other' methods
- */
- if (eb->add_method) num_methods ++;
- if (eb->remove_method) num_methods ++;
- if (eb->raise_method) num_methods ++;
-
- table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
- table->rows += num_methods;
- alloc_table (table, table->rows);
-
- if (eb->add_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
- values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
- }
- if (eb->remove_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
- values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
+ if (*p == '"') {
+ quoted = TRUE;
+ p++;
}
- if (eb->raise_method) {
- semaidx = table->next_idx ++;
- values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
- values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
- values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
+ assembly->name = p;
+ while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
+ p++;
+ if (quoted) {
+ if (*p != '"')
+ return 1;
+ *p = 0;
+ p++;
}
-}
-
-static void
-encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- mono_error_init (error);
-
- MonoDynamicTable *table;
- guint32 num_constraints, i;
- guint32 *values;
- guint32 table_idx;
-
- table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
- num_constraints = gparam->iface_constraints ?
- mono_array_length (gparam->iface_constraints) : 0;
- table->rows += num_constraints;
- if (gparam->base_type)
- table->rows++;
- alloc_table (table, table->rows);
-
- if (gparam->base_type) {
- table_idx = table->next_idx ++;
- values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
-
- MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
- return_if_nok (error);
- values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
- values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
+ if (*p != ',')
+ return 1;
+ *p = 0;
+ /* Remove trailing whitespace */
+ s = p - 1;
+ while (*s && g_ascii_isspace (*s))
+ *s-- = 0;
+ p ++;
+ while (g_ascii_isspace (*p))
+ p++;
+ while (*p) {
+ if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
+ p += 8;
+ assembly->major = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->minor = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->build = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->revision = strtoul (p, &s, 10);
+ if (s == p)
+ return 1;
+ p = s;
+ } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
+ p += 8;
+ if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
+ assembly->culture = "";
+ p += 7;
+ } else {
+ assembly->culture = p;
+ while (*p && *p != ',') {
+ p++;
+ }
+ }
+ } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
+ p += 15;
+ if (strncmp (p, "null", 4) == 0) {
+ p += 4;
+ } else {
+ int len;
+ gchar *start = p;
+ while (*p && *p != ',') {
+ p++;
+ }
+ len = (p - start + 1);
+ if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
+ len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
+ g_strlcpy ((char*)assembly->public_key_token, start, len);
+ }
+ } else {
+ while (*p && *p != ',')
+ p++;
+ }
+ found_sep = 0;
+ while (g_ascii_isspace (*p) || *p == ',') {
+ *p++ = 0;
+ found_sep = 1;
+ continue;
+ }
+ /* failed */
+ if (!found_sep)
+ return 1;
}
- for (i = 0; i < num_constraints; i++) {
- MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
- gparam->iface_constraints, gpointer, i);
-
- table_idx = table->next_idx ++;
- values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
-
- MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
- return_if_nok (error);
-
- values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
- values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
- }
+ return 0;
}
-static void
-mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
+/*
+ * mono_reflection_parse_type:
+ * @name: type name
+ *
+ * Parse a type name as accepted by the GetType () method and output the info
+ * extracted in the info structure.
+ * the name param will be mangled, so, make a copy before passing it to this function.
+ * The fields in info will be valid until the memory pointed to by name is valid.
+ *
+ * See also mono_type_get_name () below.
+ *
+ * Returns: 0 on parse error.
+ */
+static int
+_mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
+ MonoTypeNameParse *info)
{
- MONO_REQ_GC_UNSAFE_MODE;
+ char *start, *p, *w, *last_point, *startn;
+ int in_modifiers = 0;
+ int isbyref = 0, rank = 0, isptr = 0;
- GenericParamTableEntry *entry;
+ start = p = w = name;
- /*
- * The GenericParam table must be sorted according to the `owner' field.
- * We need to do this sorting prior to writing the GenericParamConstraint
- * table, since we have to use the final GenericParam table indices there
- * and they must also be sorted.
- */
+ //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
+ memset (&info->assembly, 0, sizeof (MonoAssemblyName));
+ info->name = info->name_space = NULL;
+ info->nested = NULL;
+ info->modifiers = NULL;
+ info->type_arguments = NULL;
- entry = g_new0 (GenericParamTableEntry, 1);
- entry->owner = owner;
- /* FIXME: track where gen_params should be freed and remove the GC root as well */
- MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
- entry->gparam = gparam;
-
- g_ptr_array_add (assembly->gen_params, entry);
-}
-
-static gboolean
-write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- MonoGenericParam *param;
- guint32 *values;
- guint32 table_idx;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_GENERICPARAM];
- table_idx = table->next_idx ++;
- values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
-
- MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
- return_val_if_nok (error, FALSE);
-
- param = gparam_type->data.generic_param;
-
- values [MONO_GENERICPARAM_OWNER] = entry->owner;
- values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
- values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
- values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
-
- if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
- return FALSE;
-
- encode_constraints (entry->gparam, table_idx, assembly, error);
- return_val_if_nok (error, FALSE);
-
- return TRUE;
-}
-
-static guint32
-resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 token;
- guint32 *values;
- guint32 cols [MONO_ASSEMBLY_SIZE];
- const char *pubkey;
- guint32 publen;
-
- if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
- return token;
-
- if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
- table = &assembly->tables [MONO_TABLE_MODULEREF];
- token = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + token * MONO_MODULEREF_SIZE;
- values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
-
- token <<= MONO_RESOLUTION_SCOPE_BITS;
- token |= MONO_RESOLUTION_SCOPE_MODULEREF;
- g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
-
- return token;
- }
-
- if (assembly_is_dynamic (image->assembly))
- /* FIXME: */
- memset (cols, 0, sizeof (cols));
- else {
- /* image->assembly->image is the manifest module */
- image = image->assembly->image;
- mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
- }
-
- table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
- token = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + token * MONO_ASSEMBLYREF_SIZE;
- values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
- values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
- values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
- values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
- values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
- values [MONO_ASSEMBLYREF_FLAGS] = 0;
- values [MONO_ASSEMBLYREF_CULTURE] = 0;
- values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
-
- if (strcmp ("", image->assembly->aname.culture)) {
- values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
- image->assembly->aname.culture);
- }
-
- if ((pubkey = mono_image_get_public_key (image, &publen))) {
- guchar pubtoken [9];
- pubtoken [0] = 8;
- mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
- values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
- } else {
- values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
- }
- token <<= MONO_RESOLUTION_SCOPE_BITS;
- token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
- g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
- return token;
-}
-
-static guint32
-create_typespec (MonoDynamicImage *assembly, MonoType *type)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token;
- SigBuffer buf;
-
- if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
- return token;
-
- sigbuffer_init (&buf, 32);
- switch (type->type) {
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_PTR:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- case MONO_TYPE_GENERICINST:
- encode_type (assembly, type, &buf);
- break;
- case MONO_TYPE_CLASS:
- case MONO_TYPE_VALUETYPE: {
- MonoClass *k = mono_class_from_mono_type (type);
- if (!k || !k->generic_container) {
- sigbuffer_free (&buf);
- return 0;
- }
- encode_type (assembly, type, &buf);
- break;
- }
- default:
- sigbuffer_free (&buf);
- return 0;
- }
-
- table = &assembly->tables [MONO_TABLE_TYPESPEC];
- if (assembly->save) {
- token = sigbuffer_add_to_blob_cached (assembly, &buf);
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
- values [MONO_TYPESPEC_SIGNATURE] = token;
- }
- sigbuffer_free (&buf);
-
- token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
- g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
- table->next_idx ++;
- return token;
-}
-
-static guint32
-mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
-{
- MONO_REQ_GC_UNSAFE_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, scope, enclosing;
- MonoClass *klass;
-
- /* if the type requires a typespec, we must try that first*/
- if (try_typespec && (token = create_typespec (assembly, type)))
- return token;
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
- if (token)
- return token;
- klass = mono_class_from_mono_type (type);
- if (!klass)
- klass = mono_class_from_mono_type (type);
-
- /*
- * If it's in the same module and not a generic type parameter:
- */
- if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
- (type->type != MONO_TYPE_MVAR)) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
- register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
- return token;
- }
-
- if (klass->nested_in) {
- enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
- /* get the typeref idx of the enclosing type */
- enclosing >>= MONO_TYPEDEFORREF_BITS;
- scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
- } else {
- scope = resolution_scope_from_image (assembly, klass->image);
- }
- table = &assembly->tables [MONO_TABLE_TYPEREF];
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
- values [MONO_TYPEREF_SCOPE] = scope;
- values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
- values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
- }
- token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
- g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
- table->next_idx ++;
- register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
- return token;
-}
-
-/*
- * Despite the name, we handle also TypeSpec (with the above helper).
- */
-static guint32
-mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
-{
- return mono_image_typedef_or_ref_full (assembly, type, TRUE);
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, pclass;
-
- switch (parent & MONO_TYPEDEFORREF_MASK) {
- case MONO_TYPEDEFORREF_TYPEREF:
- pclass = MONO_MEMBERREF_PARENT_TYPEREF;
- break;
- case MONO_TYPEDEFORREF_TYPESPEC:
- pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
- break;
- case MONO_TYPEDEFORREF_TYPEDEF:
- pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
- break;
- default:
- g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
- return 0;
- }
- /* extract the index */
- parent >>= MONO_TYPEDEFORREF_BITS;
-
- table = &assembly->tables [MONO_TABLE_MEMBERREF];
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_MEMBER_REF | table->next_idx;
- table->next_idx ++;
-
- return token;
-}
-
-/*
- * Insert a memberef row into the metadata: the token that point to the memberref
- * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
- * mono_image_get_fieldref_token()).
- * The sig param is an index to an already built signature.
- */
-static guint32
-mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 parent = mono_image_typedef_or_ref (assembly, type);
- return mono_image_add_memberef_row (assembly, parent, name, sig);
-}
-
-
-static guint32
-mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 token;
- MonoMethodSignature *sig;
-
- create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
-
- if (create_typespec) {
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
- if (token)
- return token;
- }
-
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
- if (token && !create_typespec)
- return token;
-
- g_assert (!method->is_inflated);
- if (!token) {
- /*
- * A methodref signature can't contain an unmanaged calling convention.
- */
- sig = mono_metadata_signature_dup (mono_method_signature (method));
- if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
- sig->call_convention = MONO_CALL_DEFAULT;
- token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
- method->name, method_encode_signature (assembly, sig));
- g_free (sig);
- g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
- }
-
- if (create_typespec) {
- MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
- g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
- token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
-
- if (assembly->save) {
- guint32 *values;
-
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
- values [MONO_METHODSPEC_METHOD] = token;
- values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
- }
-
- token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
- table->next_idx ++;
- /*methodspec and memberef tokens are diferent, */
- g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
- return token;
- }
- return token;
-}
-
-static guint32
-mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
-{
- guint32 token, parent, sig;
- ReflectionMethodBuilder rmb;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
-
- mono_error_init (error);
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
- if (token)
- return token;
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
- return 0;
-
- /*
- * A methodref signature can't contain an unmanaged calling convention.
- * Since some flags are encoded as part of call_conv, we need to check against it.
- */
- if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
- rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
-
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- if (tb->generic_params) {
- parent = create_generic_typespec (assembly, tb, error);
- return_val_if_nok (error, 0);
- } else {
- MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
- return_val_if_nok (error, 0);
-
- parent = mono_image_typedef_or_ref (assembly, t);
- }
-
- char *name = mono_string_to_utf8_checked (method->name, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_add_memberef_row (assembly, parent, name, sig);
- g_free (name);
-
- g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
-
- return token;
-}
-
-static guint32
-mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
- const gchar *name, guint32 sig)
-{
- MonoDynamicTable *table;
- guint32 token;
- guint32 *values;
-
- table = &assembly->tables [MONO_TABLE_MEMBERREF];
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = original;
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_MEMBER_REF | table->next_idx;
- table->next_idx ++;
-
- return token;
-}
-
-static guint32
-encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
-{
- SigBuffer buf;
- int i;
- guint32 nparams = mono_array_length (mb->generic_params);
- guint32 idx;
-
- if (!assembly->save)
- return 0;
-
- sigbuffer_init (&buf, 32);
-
- sigbuffer_add_value (&buf, 0xa);
- sigbuffer_add_value (&buf, nparams);
-
- for (i = 0; i < nparams; i++) {
- sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
- sigbuffer_add_value (&buf, i);
- }
-
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
-
-static guint32
-mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, mtoken = 0;
-
- mono_error_init (error);
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
- if (token)
- return token;
-
- table = &assembly->tables [MONO_TABLE_METHODSPEC];
-
- mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
- if (!mono_error_ok (error))
- return 0;
-
- switch (mono_metadata_token_table (mtoken)) {
- case MONO_TABLE_MEMBERREF:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
- break;
- case MONO_TABLE_METHOD:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
- break;
- default:
- g_assert_not_reached ();
- }
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
- values [MONO_METHODSPEC_METHOD] = mtoken;
- values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
- }
-
- token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
- table->next_idx ++;
-
- mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
-{
- guint32 token;
-
- mono_error_init (error);
-
- if (mb->generic_params && create_methodspec)
- return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
- if (token)
- return token;
-
- token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
- if (!mono_error_ok (error))
- return 0;
- mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
-{
- guint32 token, parent, sig;
- ReflectionMethodBuilder rmb;
- char *name;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
-
- mono_error_init (error);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
- if (token)
- return token;
-
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
- return 0;
-
- if (tb->generic_params) {
- parent = create_generic_typespec (assembly, tb, error);
- return_val_if_nok (error, 0);
- } else {
- MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_val_if_nok (error, 0);
- parent = mono_image_typedef_or_ref (assembly, type);
- }
-
- name = mono_string_to_utf8_checked (rmb.name, error);
- return_val_if_nok (error, 0);
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_add_memberef_row (assembly, parent, name, sig);
-
- g_free (name);
- mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
- return token;
-}
-#endif
-
-static gboolean
-is_field_on_inst (MonoClassField *field)
-{
- return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
-}
-
-/*
- * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
- */
-static MonoType*
-get_field_on_inst_generic_type (MonoClassField *field)
-{
- MonoClass *klass, *gtd;
- MonoDynamicGenericClass *dgclass;
- int field_index;
-
- g_assert (is_field_on_inst (field));
-
- dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
-
- if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
- field_index = field - dgclass->fields;
- return dgclass->field_generic_types [field_index];
- }
-
- klass = field->parent;
- gtd = klass->generic_class->container_class;
-
- if (field >= klass->fields && field - klass->fields < klass->field.count) {
- field_index = field - klass->fields;
- return gtd->fields [field_index].type;
- }
-
- g_assert_not_reached ();
- return 0;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
-{
- MonoType *type;
- guint32 token;
-
- g_assert (field);
- g_assert (field->parent);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
- if (token)
- return token;
-
- if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
- int index = field - field->parent->fields;
- type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
- } else {
- if (is_field_on_inst (field))
- type = get_field_on_inst_generic_type (field);
- else
- type = mono_field_get_type (field);
- }
- token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
- mono_field_get_name (field),
- fieldref_encode_signature (assembly, field->parent->image, type));
- mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
-{
- guint32 token;
- MonoClass *klass;
- MonoGenericClass *gclass;
- MonoType *type;
- char *name;
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
- if (token)
- return token;
- if (is_sre_field_builder (mono_object_class (f->fb))) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
- type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
- gclass = type->data.generic_class;
- g_assert (gclass->is_dynamic);
-
- guint32 sig_token = field_encode_signature (assembly, fb, error);
- return_val_if_nok (error, 0);
- name = mono_string_to_utf8_checked (fb->name, error);
- return_val_if_nok (error, 0);
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
- g_free (name);
- } else if (is_sr_mono_field (mono_object_class (f->fb))) {
- guint32 sig;
- MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
- } else {
- char *name = mono_type_get_full_name (mono_object_class (f->fb));
- g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
- }
-
- mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
- return token;
-}
-
-static guint32
-mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
-{
- guint32 sig, token;
- MonoClass *klass;
- MonoGenericClass *gclass;
- MonoType *type;
-
- mono_error_init (error);
-
- /* A ctor cannot be a generic method, so we can ignore create_methodspec */
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
- if (token)
- return token;
-
- if (is_sre_ctor_builder (mono_object_class (c->cb))) {
- MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
- ReflectionMethodBuilder rmb;
- char *name;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- gclass = type->data.generic_class;
- g_assert (gclass->is_dynamic);
-
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
- return 0;
-
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- name = mono_string_to_utf8_checked (rmb.name, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
- g_free (name);
- } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
- MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- sig = method_encode_signature (assembly, mono_method_signature (mm));
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
- } else {
- char *name = mono_type_get_full_name (mono_object_class (c->cb));
- g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
- }
-
-
- mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
- return token;
-}
-
-static MonoMethod*
-mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
-{
- MonoClass *klass;
- MonoGenericContext tmp_context;
- MonoType **type_argv;
- MonoGenericInst *ginst;
- MonoMethod *method, *inflated;
- int count, i;
-
- mono_error_init (error);
-
- init_type_builder_generics ((MonoObject*)m->inst, error);
- return_val_if_nok (error, NULL);
-
- method = inflate_method (m->inst, (MonoObject*)m->mb, error);
- return_val_if_nok (error, NULL);
-
- klass = method->klass;
-
- if (m->method_args == NULL)
- return method;
-
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- count = mono_array_length (m->method_args);
-
- type_argv = g_new0 (MonoType *, count);
- for (i = 0; i < count; i++) {
- MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
- type_argv [i] = mono_reflection_type_get_handle (garg, error);
- return_val_if_nok (error, NULL);
- }
- ginst = mono_metadata_get_generic_inst (count, type_argv);
- g_free (type_argv);
-
- tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
- tmp_context.method_inst = ginst;
-
- inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
- mono_error_assert_ok (error);
- return inflated;
-}
-
-static guint32
-mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
-{
- guint32 sig, token = 0;
- MonoType *type;
- MonoClass *klass;
-
- mono_error_init (error);
-
- if (m->method_args) {
- MonoMethod *inflated;
-
- inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
- return_val_if_nok (error, 0);
-
- if (create_methodspec)
- token = mono_image_get_methodspec_token (assembly, inflated);
- else
- token = mono_image_get_inflated_method_token (assembly, inflated);
- return token;
- }
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
- if (token)
- return token;
-
- if (is_sre_method_builder (mono_object_class (m->mb))) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
- MonoGenericClass *gclass;
- ReflectionMethodBuilder rmb;
- char *name;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
- gclass = type->data.generic_class;
- g_assert (gclass->is_dynamic);
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
- return 0;
-
- sig = method_builder_encode_signature (assembly, &rmb, error);
- return_val_if_nok (error, 0);
-
- name = mono_string_to_utf8_checked (rmb.name, error);
- return_val_if_nok (error, 0);
-
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
- g_free (name);
- } else if (is_sr_mono_method (mono_object_class (m->mb))) {
- MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
-
- type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, 0);
- klass = mono_class_from_mono_type (type);
-
- sig = method_encode_signature (assembly, mono_method_signature (mm));
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
- } else {
- char *name = mono_type_get_full_name (mono_object_class (m->mb));
- g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
- }
-
- mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
- return token;
-}
-
-static guint32
-encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
-{
- SigBuffer buf;
- int i;
- guint32 nparams = context->method_inst->type_argc;
- guint32 idx;
-
- if (!assembly->save)
- return 0;
-
- sigbuffer_init (&buf, 32);
- /*
- * FIXME: vararg, explicit_this, differenc call_conv values...
- */
- sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
- sigbuffer_add_value (&buf, nparams);
-
- for (i = 0; i < nparams; i++)
- encode_type (assembly, context->method_inst->type_argv [i], &buf);
-
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
- return idx;
-}
-
-static guint32
-method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 token, mtoken = 0, sig;
- MonoMethodInflated *imethod;
- MonoMethod *declaring;
-
- table = &assembly->tables [MONO_TABLE_METHODSPEC];
-
- g_assert (method->is_inflated);
- imethod = (MonoMethodInflated *) method;
- declaring = imethod->declaring;
-
- sig = method_encode_signature (assembly, mono_method_signature (declaring));
- mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
-
- if (!mono_method_signature (declaring)->generic_param_count)
- return mtoken;
-
- switch (mono_metadata_token_table (mtoken)) {
- case MONO_TABLE_MEMBERREF:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
- break;
- case MONO_TABLE_METHOD:
- mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
- break;
- default:
- g_assert_not_reached ();
- }
-
- sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
- values [MONO_METHODSPEC_METHOD] = mtoken;
- values [MONO_METHODSPEC_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
- table->next_idx ++;
-
- return token;
-}
-
-static guint32
-mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
-{
- MonoMethodInflated *imethod;
- guint32 token;
-
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
- if (token)
- return token;
-
- g_assert (method->is_inflated);
- imethod = (MonoMethodInflated *) method;
-
- if (mono_method_signature (imethod->declaring)->generic_param_count) {
- token = method_encode_methodspec (assembly, method);
- } else {
- guint32 sig = method_encode_signature (
- assembly, mono_method_signature (imethod->declaring));
- token = mono_image_get_memberref_token (
- assembly, &method->klass->byval_arg, method->name, sig);
- }
-
- g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
- return token;
-}
-
-static guint32
-mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
-{
- MonoMethodInflated *imethod = (MonoMethodInflated *) m;
- guint32 sig, token;
-
- sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
- token = mono_image_get_memberref_token (
- assembly, &m->klass->byval_arg, m->name, sig);
-
- return token;
-}
-
-static guint32
-create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoClass *klass;
- MonoType *type;
- guint32 *values;
- guint32 token;
- SigBuffer buf;
- int count, i;
-
- /*
- * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
- * ie. what we'd normally use as the generic type in a TypeSpec signature.
- * Because of this, we must not insert it into the `typeref' hash table.
- */
- type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_val_if_nok (error, 0);
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
- if (token)
- return token;
-
- sigbuffer_init (&buf, 32);
-
- g_assert (tb->generic_params);
- klass = mono_class_from_mono_type (type);
-
- if (tb->generic_container) {
- if (!mono_reflection_create_generic_class (tb, error))
- goto fail;
- }
-
- sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
- g_assert (klass->generic_container);
- sigbuffer_add_value (&buf, klass->byval_arg.type);
- sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
-
- count = mono_array_length (tb->generic_params);
- sigbuffer_add_value (&buf, count);
- for (i = 0; i < count; i++) {
- MonoReflectionGenericParam *gparam;
-
- gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
- MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
- if (!is_ok (error))
- goto fail;
-
- encode_type (assembly, gparam_type, &buf);
- }
-
- table = &assembly->tables [MONO_TABLE_TYPESPEC];
-
- if (assembly->save) {
- token = sigbuffer_add_to_blob_cached (assembly, &buf);
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
- values [MONO_TYPESPEC_SIGNATURE] = token;
- }
- sigbuffer_free (&buf);
-
- token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
- g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
- table->next_idx ++;
- return token;
-fail:
- sigbuffer_free (&buf);
- return 0;
-}
-
-/*
- * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
- */
-static MonoType*
-add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
-{
- int i, count, len, pos;
- MonoType *t;
-
- mono_error_init (error);
-
- count = 0;
- if (modreq)
- count += mono_array_length (modreq);
- if (modopt)
- count += mono_array_length (modopt);
-
- if (count == 0)
- return mono_metadata_type_dup (NULL, type);
-
- len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
- t = (MonoType *)g_malloc (len);
- memcpy (t, type, MONO_SIZEOF_TYPE);
-
- t->num_mods = count;
- pos = 0;
- if (modreq) {
- for (i = 0; i < mono_array_length (modreq); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
- if (!is_ok (error))
- goto fail;
- t->modifiers [pos].required = 1;
- t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
- pos ++;
- }
- }
- if (modopt) {
- for (i = 0; i < mono_array_length (modopt); ++i) {
- MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
- if (!is_ok (error))
- goto fail;
- t->modifiers [pos].required = 0;
- t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
- pos ++;
- }
- }
-
- return t;
-fail:
- g_free (t);
- return NULL;
-}
-
-static void
-init_type_builder_generics (MonoObject *type, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb;
-
- mono_error_init (error);
-
- if (!is_sre_type_builder(mono_object_class (type)))
- return;
- tb = (MonoReflectionTypeBuilder *)type;
-
- if (tb && tb->generic_container)
- mono_reflection_create_generic_class (tb, error);
-}
-
-static guint32
-mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoType *custom = NULL, *type;
- guint32 *values;
- guint32 token, pclass, parent, sig;
- gchar *name;
-
- mono_error_init (error);
-
- token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
- if (token)
- return token;
-
- MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
- return_val_if_nok (error, 0);
- /* FIXME: is this call necessary? */
- mono_class_from_mono_type (typeb);
-
- /*FIXME this is one more layer of ugliness due how types are created.*/
- init_type_builder_generics (fb->type, error);
- return_val_if_nok (error, 0);
-
- /* fb->type does not include the custom modifiers */
- /* FIXME: We should do this in one place when a fieldbuilder is created */
- type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_val_if_nok (error, 0);
-
- if (fb->modreq || fb->modopt) {
- type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
- return_val_if_nok (error, 0);
- }
-
- sig = fieldref_encode_signature (assembly, NULL, type);
- g_free (custom);
-
- parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
- return_val_if_nok (error, 0);
- g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
-
- pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
- parent >>= MONO_TYPEDEFORREF_BITS;
-
- table = &assembly->tables [MONO_TABLE_MEMBERREF];
-
- name = mono_string_to_utf8_checked (fb->name, error);
- return_val_if_nok (error, 0);
-
- if (assembly->save) {
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
- }
-
- token = MONO_TOKEN_MEMBER_REF | table->next_idx;
- table->next_idx ++;
- mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
- g_free (name);
- return token;
-}
-
-static guint32
-mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
-{
- SigBuffer buf;
- guint32 nargs;
- guint32 i, idx;
-
- mono_error_init (error);
-
- if (!assembly->save)
- return 0;
-
- /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
- g_assert (helper->type == 2);
-
- if (helper->arguments)
- nargs = mono_array_length (helper->arguments);
- else
- nargs = 0;
-
- sigbuffer_init (&buf, 32);
-
- /* Encode calling convention */
- /* Change Any to Standard */
- if ((helper->call_conv & 0x03) == 0x03)
- helper->call_conv = 0x01;
- /* explicit_this implies has_this */
- if (helper->call_conv & 0x40)
- helper->call_conv &= 0x20;
-
- if (helper->call_conv == 0) { /* Unmanaged */
- idx = helper->unmanaged_call_conv - 1;
- } else {
- /* Managed */
- idx = helper->call_conv & 0x60; /* has_this + explicit_this */
- if (helper->call_conv & 0x02) /* varargs */
- idx += 0x05;
- }
-
- sigbuffer_add_byte (&buf, idx);
- sigbuffer_add_value (&buf, nargs);
- encode_reflection_type (assembly, helper->return_type, &buf, error);
- if (!is_ok (error))
- goto fail;
- for (i = 0; i < nargs; ++i) {
- MonoArray *modreqs = NULL;
- MonoArray *modopts = NULL;
- MonoReflectionType *pt;
-
- if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
- modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
- if (helper->modopts && (i < mono_array_length (helper->modopts)))
- modopts = mono_array_get (helper->modopts, MonoArray*, i);
-
- encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
- if (!is_ok (error))
- goto fail;
- pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
- encode_reflection_type (assembly, pt, &buf, error);
- if (!is_ok (error))
- goto fail;
- }
- idx = sigbuffer_add_to_blob_cached (assembly, &buf);
- sigbuffer_free (&buf);
-
- return idx;
-fail:
- sigbuffer_free (&buf);
- return 0;
-}
-
-static guint32
-mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
-{
- guint32 idx;
- MonoDynamicTable *table;
- guint32 *values;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_STANDALONESIG];
- idx = table->next_idx ++;
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
-
- values [MONO_STAND_ALONE_SIGNATURE] =
- mono_reflection_encode_sighelper (assembly, helper, error);
- return_val_if_nok (error, 0);
-
- return idx;
-}
-
-static int
-reflection_cc_to_file (int call_conv) {
- switch (call_conv & 0x3) {
- case 0:
- case 1: return MONO_CALL_DEFAULT;
- case 2: return MONO_CALL_VARARG;
- default:
- g_assert_not_reached ();
- }
- return 0;
-}
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-typedef struct {
- MonoType *parent;
- MonoMethodSignature *sig;
- char *name;
- guint32 token;
-} ArrayMethod;
-
-#ifndef DISABLE_REFLECTION_EMIT
-static guint32
-mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
-{
- guint32 nparams, i;
- GList *tmp;
- char *name = NULL;
- MonoMethodSignature *sig;
- ArrayMethod *am = NULL;
- MonoType *mtype;
-
- mono_error_init (error);
-
- nparams = mono_array_length (m->parameters);
- sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
- sig->hasthis = 1;
- sig->sentinelpos = -1;
- sig->call_convention = reflection_cc_to_file (m->call_conv);
- sig->param_count = nparams;
- if (m->ret) {
- sig->ret = mono_reflection_type_get_handle (m->ret, error);
- if (!is_ok (error))
- goto fail;
- } else
- sig->ret = &mono_defaults.void_class->byval_arg;
-
- mtype = mono_reflection_type_get_handle (m->parent, error);
- if (!is_ok (error))
- goto fail;
-
- for (i = 0; i < nparams; ++i) {
- sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
- if (!is_ok (error))
- goto fail;
- }
-
- name = mono_string_to_utf8_checked (m->name, error);
- if (!is_ok (error))
- goto fail;
- for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
- am = (ArrayMethod *)tmp->data;
- if (strcmp (name, am->name) == 0 &&
- mono_metadata_type_equal (am->parent, mtype) &&
- mono_metadata_signature_equal (am->sig, sig)) {
- g_free (name);
- g_free (sig);
- m->table_idx = am->token & 0xffffff;
- return am->token;
- }
- }
- am = g_new0 (ArrayMethod, 1);
- am->name = name;
- am->sig = sig;
- am->parent = mtype;
- am->token = mono_image_get_memberref_token (assembly, am->parent, name,
- method_encode_signature (assembly, sig));
- assembly->array_methods = g_list_prepend (assembly->array_methods, am);
- m->table_idx = am->token & 0xffffff;
- return am->token;
-fail:
- g_free (am);
- g_free (name);
- g_free (sig);
- return 0;
-
-}
-
-/*
- * Insert into the metadata tables all the info about the TypeBuilder tb.
- * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
- */
-static gboolean
-mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- guint *values;
- int i, is_object = 0, is_system = 0;
- char *n;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
- values [MONO_TYPEDEF_FLAGS] = tb->attrs;
- n = mono_string_to_utf8_checked (tb->name, error);
- return_val_if_nok (error, FALSE);
- if (strcmp (n, "Object") == 0)
- is_object++;
- values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
- g_free (n);
- n = mono_string_to_utf8_checked (tb->nspace, error);
- return_val_if_nok (error, FALSE);
- if (strcmp (n, "System") == 0)
- is_system++;
- values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
- g_free (n);
- if (tb->parent && !(is_system && is_object) &&
- !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
- MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
- return_val_if_nok (error, FALSE);
- values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
- } else {
- values [MONO_TYPEDEF_EXTENDS] = 0;
- }
- values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
- values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
-
- /*
- * if we have explicitlayout or sequentiallayouts, output data in the
- * ClassLayout table.
- */
- if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
- ((tb->class_size > 0) || (tb->packing_size > 0))) {
- table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
- values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
- values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
- values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
- }
-
- /* handle interfaces */
- if (tb->interfaces) {
- table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
- i = table->rows;
- table->rows += mono_array_length (tb->interfaces);
- alloc_table (table, table->rows);
- values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
- for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
- MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
- MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
- return_val_if_nok (error, FALSE);
- values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
- values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
- values += MONO_INTERFACEIMPL_SIZE;
- }
- }
-
- /* handle fields */
- if (tb->fields) {
- table = &assembly->tables [MONO_TABLE_FIELD];
- table->rows += tb->num_fields;
- alloc_table (table, table->rows);
- for (i = 0; i < tb->num_fields; ++i) {
- mono_image_get_field_info (
- mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
-
- /* handle constructors */
- if (tb->ctors) {
- table = &assembly->tables [MONO_TABLE_METHOD];
- table->rows += mono_array_length (tb->ctors);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (tb->ctors); ++i) {
- if (!mono_image_get_ctor_info (domain,
- mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
- assembly, error))
- return FALSE;
- }
- }
-
- /* handle methods */
- if (tb->methods) {
- table = &assembly->tables [MONO_TABLE_METHOD];
- table->rows += tb->num_methods;
- alloc_table (table, table->rows);
- for (i = 0; i < tb->num_methods; ++i) {
- if (!mono_image_get_method_info (
- mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
- return FALSE;
- }
- }
-
- /* Do the same with properties etc.. */
- if (tb->events && mono_array_length (tb->events)) {
- table = &assembly->tables [MONO_TABLE_EVENT];
- table->rows += mono_array_length (tb->events);
- alloc_table (table, table->rows);
- table = &assembly->tables [MONO_TABLE_EVENTMAP];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
- values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
- values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
- for (i = 0; i < mono_array_length (tb->events); ++i) {
- mono_image_get_event_info (
- mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
- if (tb->properties && mono_array_length (tb->properties)) {
- table = &assembly->tables [MONO_TABLE_PROPERTY];
- table->rows += mono_array_length (tb->properties);
- alloc_table (table, table->rows);
- table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
- values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
- values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
- for (i = 0; i < mono_array_length (tb->properties); ++i) {
- mono_image_get_property_info (
- mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
-
- /* handle generic parameters */
- if (tb->generic_params) {
- table = &assembly->tables [MONO_TABLE_GENERICPARAM];
- table->rows += mono_array_length (tb->generic_params);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
- guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
-
- mono_image_get_generic_param_info (
- mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
- }
- }
-
- mono_image_add_decl_security (assembly,
- mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
-
- if (tb->subtypes) {
- MonoDynamicTable *ntable;
-
- ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
- ntable->rows += mono_array_length (tb->subtypes);
- alloc_table (ntable, ntable->rows);
- values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
-
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
-
- values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
- values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
- /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
- mono_string_to_utf8 (subtype->name), subtype->table_idx,
- mono_string_to_utf8 (tb->name), tb->table_idx,
- ntable->next_idx, ntable->rows);*/
- values += MONO_NESTED_CLASS_SIZE;
- ntable->next_idx++;
- }
- }
-
- return TRUE;
-}
-#endif
-
-static void
-collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
-{
- int i;
-
- mono_ptr_array_append (*types, type);
-
- if (!type->subtypes)
- return;
-
- for (i = 0; i < mono_array_length (type->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
- collect_types (types, subtype);
- }
-}
-
-static gint
-compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
-{
- if ((*type1)->table_idx < (*type2)->table_idx)
- return -1;
- else
- if ((*type1)->table_idx > (*type2)->table_idx)
- return 1;
- else
- return 0;
-}
-
-static gboolean
-params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
- int i;
-
- mono_error_init (error);
- if (!pinfo)
- return TRUE;
- for (i = 0; i < mono_array_length (pinfo); ++i) {
- MonoReflectionParamBuilder *pb;
- pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
- if (!pb)
- continue;
- if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
- int i;
-
- mono_error_init (error);
-
- if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
- return FALSE;
- if (tb->fields) {
- for (i = 0; i < tb->num_fields; ++i) {
- MonoReflectionFieldBuilder* fb;
- fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
- if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
- return FALSE;
- }
- }
- if (tb->events) {
- for (i = 0; i < mono_array_length (tb->events); ++i) {
- MonoReflectionEventBuilder* eb;
- eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
- if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
- return FALSE;
- }
- }
- if (tb->properties) {
- for (i = 0; i < mono_array_length (tb->properties); ++i) {
- MonoReflectionPropertyBuilder* pb;
- pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
- if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
- return FALSE;
- }
- }
- if (tb->ctors) {
- for (i = 0; i < mono_array_length (tb->ctors); ++i) {
- MonoReflectionCtorBuilder* cb;
- cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
- if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
- !params_add_cattrs (assembly, cb->pinfo, error))
- return FALSE;
- }
- }
-
- if (tb->methods) {
- for (i = 0; i < tb->num_methods; ++i) {
- MonoReflectionMethodBuilder* mb;
- mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
- !params_add_cattrs (assembly, mb->pinfo, error))
- return FALSE;
- }
- }
-
- if (tb->subtypes) {
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- int i;
-
- mono_error_init (error);
-
- if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
- return FALSE;
-
- if (moduleb->global_methods) {
- for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
- MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
- if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
- !params_add_cattrs (assembly, mb->pinfo, error))
- return FALSE;
- }
- }
-
- if (moduleb->global_fields) {
- for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
- MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
- if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
- return FALSE;
- }
- }
-
- if (moduleb->types) {
- for (i = 0; i < moduleb->num_types; ++i) {
- if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
- char blob_size [6];
- guchar hash [20];
- char *b = blob_size;
- char *dir, *path;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_FILE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_FILE_SIZE;
- values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
- values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
- if (image_is_dynamic (module->image)) {
- /* This depends on the fact that the main module is emitted last */
- dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
- return_val_if_nok (error, FALSE);
- path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
- } else {
- dir = NULL;
- path = g_strdup (module->image->name);
- }
- mono_sha1_get_digest_from_file (path, hash);
- g_free (dir);
- g_free (path);
- mono_metadata_encode_value (20, b, &b);
- values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
- table->next_idx ++;
- return TRUE;
-}
-
-static void
-mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- int i;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_MODULE];
- mb->table_idx = table->next_idx ++;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
- return_if_nok (error);
- i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
- i /= 16;
- ++i;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
- table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
-}
-
-static guint32
-mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
- guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 visib, res;
-
- visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
- if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
- return 0;
-
- table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
-
- values [MONO_EXP_TYPE_FLAGS] = klass->flags;
- values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
- if (klass->nested_in)
- values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
- else
- values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
- values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
- values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
-
- res = table->next_idx;
-
- table->next_idx ++;
-
- /* Emit nested types */
- if (klass->ext && klass->ext->nested_classes) {
- GList *tmp;
-
- for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
- mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
- }
-
- return res;
-}
-
-static void
-mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
- guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
- MonoError *error)
-{
- MonoClass *klass;
- guint32 idx, i;
-
- mono_error_init (error);
-
- MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_if_nok (error);
-
- klass = mono_class_from_mono_type (t);
-
- klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
-
- idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
- parent_index, assembly);
-
- /*
- * Emit nested types
- * We need to do this ourselves since klass->nested_classes is not set up.
- */
- if (tb->subtypes) {
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
- return_if_nok (error);
- }
- }
-}
-
-static void
-mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
- guint32 module_index, MonoDynamicImage *assembly)
-{
- MonoImage *image = module->image;
- MonoTableInfo *t;
- guint32 i;
-
- t = &image->tables [MONO_TABLE_TYPEDEF];
-
- for (i = 0; i < t->rows; ++i) {
- MonoError error;
- MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
- g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
-
- if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
- mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
- }
-}
-
-static void
-add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 scope, scope_idx, impl, current_idx;
- gboolean forwarder = TRUE;
- gpointer iter = NULL;
- MonoClass *nested;
-
- if (klass->nested_in) {
- impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
- forwarder = FALSE;
- } else {
- scope = resolution_scope_from_image (assembly, klass->image);
- g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
- scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
- impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
- }
-
- table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
-
- table->rows++;
- alloc_table (table, table->rows);
- current_idx = table->next_idx;
- values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
-
- values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
- values [MONO_EXP_TYPE_TYPEDEF] = 0;
- values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
- values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
- values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
-
- table->next_idx++;
-
- while ((nested = mono_class_get_nested_types (klass, &iter)))
- add_exported_type (assemblyb, assembly, nested, current_idx);
-}
-
-static void
-mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
-{
- MonoError error;
- MonoClass *klass;
- int i;
-
- if (!assemblyb->type_forwarders)
- return;
-
- for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
- MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
- MonoType *type;
- if (!t)
- continue;
-
- type = mono_reflection_type_get_handle (t, &error);
- mono_error_assert_ok (&error);
- g_assert (type);
-
- klass = mono_class_from_mono_type (type);
-
- add_exported_type (assemblyb, assembly, klass, 0);
- }
-}
-
-#define align_pointer(base,p)\
- do {\
- guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
- if (__diff & 3)\
- (p) += 4 - (__diff & 3);\
- } while (0)
-
-static int
-compare_constants (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
- return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
-}
-
-static int
-compare_semantics (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
- int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
- if (assoc)
- return assoc;
- return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
-}
-
-static int
-compare_custom_attrs (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
-}
-
-static int
-compare_field_marshal (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
-}
-
-static int
-compare_nested (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
-}
-
-static int
-compare_genericparam (const void *a, const void *b)
-{
- MonoError error;
- const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
- const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
-
- if ((*b_entry)->owner == (*a_entry)->owner) {
- MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
- mono_error_assert_ok (&error);
- MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
- mono_error_assert_ok (&error);
- return
- mono_type_get_generic_param_num (a_type) -
- mono_type_get_generic_param_num (b_type);
- } else
- return (*a_entry)->owner - (*b_entry)->owner;
-}
-
-static int
-compare_declsecurity_attrs (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
-}
-
-static int
-compare_interface_impl (const void *a, const void *b)
-{
- const guint32 *a_values = (const guint32 *)a;
- const guint32 *b_values = (const guint32 *)b;
-
- int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
- if (klass)
- return klass;
-
- return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
-}
-
-static void
-pad_heap (MonoDynamicStream *sh)
-{
- if (sh->index & 3) {
- int sz = 4 - (sh->index & 3);
- memset (sh->data + sh->index, 0, sz);
- sh->index += sz;
- }
-}
-
-struct StreamDesc {
- const char *name;
- MonoDynamicStream *stream;
-};
-
-/*
- * build_compressed_metadata() fills in the blob of data that represents the
- * raw metadata as it will be saved in the PE file. The five streams are output
- * and the metadata tables are comnpressed from the guint32 array representation,
- * to the compressed on-disk format.
- */
-static gboolean
-build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
-{
- MonoDynamicTable *table;
- int i;
- guint64 valid_mask = 0;
- guint64 sorted_mask;
- guint32 heapt_size = 0;
- guint32 meta_size = 256; /* allow for header and other stuff */
- guint32 table_offset;
- guint32 ntables = 0;
- guint64 *int64val;
- guint32 *int32val;
- guint16 *int16val;
- MonoImage *meta;
- unsigned char *p;
- struct StreamDesc stream_desc [5];
-
- mono_error_init (error);
-
- qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
- for (i = 0; i < assembly->gen_params->len; i++) {
- GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
- if (!write_generic_param_entry (assembly, entry, error))
- return FALSE;
- }
-
- stream_desc [0].name = "#~";
- stream_desc [0].stream = &assembly->tstream;
- stream_desc [1].name = "#Strings";
- stream_desc [1].stream = &assembly->sheap;
- stream_desc [2].name = "#US";
- stream_desc [2].stream = &assembly->us;
- stream_desc [3].name = "#Blob";
- stream_desc [3].stream = &assembly->blob;
- stream_desc [4].name = "#GUID";
- stream_desc [4].stream = &assembly->guid;
-
- /* tables that are sorted */
- sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
- | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
- | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
- | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
- | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
- | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
- | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
-
- /* Compute table sizes */
- /* the MonoImage has already been created in mono_image_basic_init() */
- meta = &assembly->image;
-
- /* sizes should be multiple of 4 */
- pad_heap (&assembly->blob);
- pad_heap (&assembly->guid);
- pad_heap (&assembly->sheap);
- pad_heap (&assembly->us);
-
- /* Setup the info used by compute_sizes () */
- meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
- meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
- meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
-
- meta_size += assembly->blob.index;
- meta_size += assembly->guid.index;
- meta_size += assembly->sheap.index;
- meta_size += assembly->us.index;
-
- for (i=0; i < MONO_TABLE_NUM; ++i)
- meta->tables [i].rows = assembly->tables [i].rows;
-
- for (i = 0; i < MONO_TABLE_NUM; i++){
- if (meta->tables [i].rows == 0)
- continue;
- valid_mask |= (guint64)1 << i;
- ntables ++;
- meta->tables [i].row_size = mono_metadata_compute_size (
- meta, i, &meta->tables [i].size_bitfield);
- heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
- }
- heapt_size += 24; /* #~ header size */
- heapt_size += ntables * 4;
- /* make multiple of 4 */
- heapt_size += 3;
- heapt_size &= ~3;
- meta_size += heapt_size;
- meta->raw_metadata = (char *)g_malloc0 (meta_size);
- p = (unsigned char*)meta->raw_metadata;
- /* the metadata signature */
- *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
- /* version numbers and 4 bytes reserved */
- int16val = (guint16*)p;
- *int16val++ = GUINT16_TO_LE (meta->md_version_major);
- *int16val = GUINT16_TO_LE (meta->md_version_minor);
- p += 8;
- /* version string */
- int32val = (guint32*)p;
- *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
- p += 4;
- memcpy (p, meta->version, strlen (meta->version));
- p += GUINT32_FROM_LE (*int32val);
- align_pointer (meta->raw_metadata, p);
- int16val = (guint16*)p;
- *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
- *int16val = GUINT16_TO_LE (5); /* number of streams */
- p += 4;
-
- /*
- * write the stream info.
- */
- table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
- table_offset += 3; table_offset &= ~3;
-
- assembly->tstream.index = heapt_size;
- for (i = 0; i < 5; ++i) {
- int32val = (guint32*)p;
- stream_desc [i].stream->offset = table_offset;
- *int32val++ = GUINT32_TO_LE (table_offset);
- *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
- table_offset += GUINT32_FROM_LE (*int32val);
- table_offset += 3; table_offset &= ~3;
- p += 8;
- strcpy ((char*)p, stream_desc [i].name);
- p += strlen (stream_desc [i].name) + 1;
- align_pointer (meta->raw_metadata, p);
- }
- /*
- * now copy the data, the table stream header and contents goes first.
- */
- g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
- p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
- int32val = (guint32*)p;
- *int32val = GUINT32_TO_LE (0); /* reserved */
- p += 4;
-
- *p++ = 2; /* version */
- *p++ = 0;
-
- if (meta->idx_string_wide)
- *p |= 0x01;
- if (meta->idx_guid_wide)
- *p |= 0x02;
- if (meta->idx_blob_wide)
- *p |= 0x04;
- ++p;
- *p++ = 1; /* reserved */
- int64val = (guint64*)p;
- *int64val++ = GUINT64_TO_LE (valid_mask);
- *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
- p += 16;
- int32val = (guint32*)p;
- for (i = 0; i < MONO_TABLE_NUM; i++){
- if (meta->tables [i].rows == 0)
- continue;
- *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
- }
- p = (unsigned char*)int32val;
-
- /* sort the tables that still need sorting */
- table = &assembly->tables [MONO_TABLE_CONSTANT];
- if (table->rows)
- qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
- table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
- if (table->rows)
- qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
- table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
- if (table->rows)
- qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
- table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
- if (table->rows)
- qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
- table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
- if (table->rows)
- qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
- /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
- table = &assembly->tables [MONO_TABLE_DECLSECURITY];
- if (table->rows)
- qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
- table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
- if (table->rows)
- qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
-
- /* compress the tables */
- for (i = 0; i < MONO_TABLE_NUM; i++){
- int row, col;
- guint32 *values;
- guint32 bitfield = meta->tables [i].size_bitfield;
- if (!meta->tables [i].rows)
- continue;
- if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
- g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
- meta->tables [i].base = (char*)p;
- for (row = 1; row <= meta->tables [i].rows; ++row) {
- values = assembly->tables [i].values + row * assembly->tables [i].columns;
- for (col = 0; col < assembly->tables [i].columns; ++col) {
- switch (mono_metadata_table_size (bitfield, col)) {
- case 1:
- *p++ = values [col];
- break;
- case 2:
- *p++ = values [col] & 0xff;
- *p++ = (values [col] >> 8) & 0xff;
- break;
- case 4:
- *p++ = values [col] & 0xff;
- *p++ = (values [col] >> 8) & 0xff;
- *p++ = (values [col] >> 16) & 0xff;
- *p++ = (values [col] >> 24) & 0xff;
- break;
- default:
- g_assert_not_reached ();
- }
- }
- }
- g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
- }
-
- g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
- memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
- memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
- memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
- memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
-
- assembly->meta_size = assembly->guid.offset + assembly->guid.index;
-
- return TRUE;
-}
-
-/*
- * Some tables in metadata need to be sorted according to some criteria, but
- * when methods and fields are first created with reflection, they may be assigned a token
- * that doesn't correspond to the final token they will get assigned after the sorting.
- * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
- * with the reflection objects that represent them. Once all the tables are set up, the
- * reflection objects will contains the correct table index. fixup_method() will fixup the
- * tokens for the method with ILGenerator @ilgen.
- */
-static void
-fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
-{
- guint32 code_idx = GPOINTER_TO_UINT (value);
- MonoReflectionILTokenInfo *iltoken;
- MonoReflectionFieldBuilder *field;
- MonoReflectionCtorBuilder *ctor;
- MonoReflectionMethodBuilder *method;
- MonoReflectionTypeBuilder *tb;
- MonoReflectionArrayMethod *am;
- guint32 i, idx = 0;
- unsigned char *target;
-
- for (i = 0; i < ilgen->num_token_fixups; ++i) {
- iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
- target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
- switch (target [3]) {
- case MONO_TABLE_FIELD:
- if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
- field = (MonoReflectionFieldBuilder *)iltoken->member;
- idx = field->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
- MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
- } else {
- g_assert_not_reached ();
- }
- break;
- case MONO_TABLE_METHOD:
- if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
- method = (MonoReflectionMethodBuilder *)iltoken->member;
- idx = method->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
- ctor = (MonoReflectionCtorBuilder *)iltoken->member;
- idx = ctor->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
- } else {
- g_assert_not_reached ();
- }
- break;
- case MONO_TABLE_TYPEDEF:
- if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
- g_assert_not_reached ();
- tb = (MonoReflectionTypeBuilder *)iltoken->member;
- idx = tb->table_idx;
- break;
- case MONO_TABLE_MEMBERREF:
- if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
- am = (MonoReflectionArrayMethod*)iltoken->member;
- idx = am->table_idx;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
- !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- g_assert (m->klass->generic_class || m->klass->generic_container);
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
- MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
- g_assert (is_field_on_inst (f));
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
- !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
- continue;
- } else {
- g_assert_not_reached ();
- }
- break;
- case MONO_TABLE_METHODSPEC:
- if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- g_assert (mono_method_signature (m)->generic_param_count);
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
- continue;
- } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
- continue;
- } else {
- g_assert_not_reached ();
- }
- break;
- default:
- g_error ("got unexpected table 0x%02x in fixup", target [3]);
- }
- target [0] = idx & 0xff;
- target [1] = (idx >> 8) & 0xff;
- target [2] = (idx >> 16) & 0xff;
- }
-}
-
-/*
- * fixup_cattrs:
- *
- * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
- * value is not known when the table is emitted.
- */
-static void
-fixup_cattrs (MonoDynamicImage *assembly)
-{
- MonoDynamicTable *table;
- guint32 *values;
- guint32 type, i, idx, token;
- MonoObject *ctor;
-
- table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
-
- for (i = 0; i < table->rows; ++i) {
- values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
-
- type = values [MONO_CUSTOM_ATTR_TYPE];
- if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
- idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
- token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
- ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
- g_assert (ctor);
-
- if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
- MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
- values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
- } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
- MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
- idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
- values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
- }
- }
- }
-}
-
-static gboolean
-assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
-
- mono_error_init (error);
-
- table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
- values [MONO_MANIFEST_OFFSET] = rsrc->offset;
- values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
- values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
- return_val_if_nok (error, FALSE);
- values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
- table->next_idx++;
- return TRUE;
-}
-
-static gboolean
-assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
-{
- MonoDynamicTable *table;
- guint32 *values;
- char blob_size [6];
- guchar hash [20];
- char *b = blob_size;
- char *name, *sname;
- guint32 idx, offset;
-
- mono_error_init (error);
-
- if (rsrc->filename) {
- name = mono_string_to_utf8_checked (rsrc->filename, error);
- return_val_if_nok (error, FALSE);
- sname = g_path_get_basename (name);
-
- table = &assembly->tables [MONO_TABLE_FILE];
- table->rows++;
- alloc_table (table, table->rows);
- values = table->values + table->next_idx * MONO_FILE_SIZE;
- values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
- values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
- g_free (sname);
-
- mono_sha1_get_digest_from_file (name, hash);
- mono_metadata_encode_value (20, b, &b);
- values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
- g_free (name);
- idx = table->next_idx++;
- rsrc->offset = 0;
- idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
- } else {
- char sizebuf [4];
- char *data;
- guint len;
- if (rsrc->data) {
- data = mono_array_addr (rsrc->data, char, 0);
- len = mono_array_length (rsrc->data);
- } else {
- data = NULL;
- len = 0;
- }
- offset = len;
- sizebuf [0] = offset; sizebuf [1] = offset >> 8;
- sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
- rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
- mono_image_add_stream_data (&assembly->resources, data, len);
-
- if (!mb->is_main)
- /*
- * The entry should be emitted into the MANIFESTRESOURCE table of
- * the main module, but that needs to reference the FILE table
- * which isn't emitted yet.
- */
- return TRUE;
- else
- idx = 0;
- }
-
- return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
-}
-
-static gboolean
-set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
-{
- gchar *ver, *p, *str;
- guint32 i;
-
- mono_error_init (error);
-
- values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
- values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
- values [MONO_ASSEMBLY_REV_NUMBER] = 0;
- values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
- if (!version)
- return TRUE;
- ver = str = mono_string_to_utf8_checked (version, error);
- return_val_if_nok (error, FALSE);
- for (i = 0; i < 4; ++i) {
- values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
- switch (*p) {
- case '.':
- p++;
- break;
- case '*':
- /* handle Revision and Build */
- p++;
- break;
- }
- ver = p;
- }
- g_free (str);
- return TRUE;
-}
-
-static guint32
-load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
- gsize len;
- guint32 token = 0;
- char blob_size [6];
- char *b = blob_size;
-
- if (!pkey)
- return token;
-
- len = mono_array_length (pkey);
- mono_metadata_encode_value (len, b, &b);
- token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
- mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
-
- assembly->public_key = (guint8 *)g_malloc (len);
- memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
- assembly->public_key_len = len;
-
- /* Special case: check for ECMA key (16 bytes) */
- if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
- /* In this case we must reserve 128 bytes (1024 bits) for the signature */
- assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
- } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
- /* minimum key size (in 2.0) is 384 bits */
- assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
- } else {
- /* FIXME - verifier */
- g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
- assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
- }
- assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
-
- return token;
-}
-
-static gboolean
-mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoDynamicImage *assembly;
- MonoReflectionAssemblyBuilder *assemblyb;
- MonoDomain *domain;
- guint32 *values;
- int i;
- guint32 module_index;
-
- mono_error_init (error);
-
- assemblyb = moduleb->assemblyb;
- assembly = moduleb->dynamic_image;
- domain = mono_object_domain (assemblyb);
-
- /* Emit ASSEMBLY table */
- table = &assembly->tables [MONO_TABLE_ASSEMBLY];
- alloc_table (table, 1);
- values = table->values + MONO_ASSEMBLY_SIZE;
- values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
- values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
- return_val_if_nok (error, FALSE);
- if (assemblyb->culture) {
- values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
- return_val_if_nok (error, FALSE);
- } else {
- values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
- }
- values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
- values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
- if (!set_version_from_string (assemblyb->version, values, error))
- return FALSE;
-
- /* Emit FILE + EXPORTED_TYPE table */
- module_index = 0;
- for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
- int j;
- MonoReflectionModuleBuilder *file_module =
- mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
- if (file_module != moduleb) {
- if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
- return FALSE;
- module_index ++;
- if (file_module->types) {
- for (j = 0; j < file_module->num_types; ++j) {
- MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
- mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
- return_val_if_nok (error, FALSE);
- }
- }
- }
- }
- if (assemblyb->loaded_modules) {
- for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
- MonoReflectionModule *file_module =
- mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
- if (!mono_image_fill_file_table (domain, file_module, assembly, error))
- return FALSE;
- module_index ++;
- mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
- }
- }
- if (assemblyb->type_forwarders)
- mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
-
- /* Emit MANIFESTRESOURCE table */
- module_index = 0;
- for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
- int j;
- MonoReflectionModuleBuilder *file_module =
- mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
- /* The table for the main module is emitted later */
- if (file_module != moduleb) {
- module_index ++;
- if (file_module->resources) {
- int len = mono_array_length (file_module->resources);
- for (j = 0; j < len; ++j) {
- MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
- if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
- return FALSE;
- }
- }
- }
- }
- return TRUE;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT_SAVE
-
-/*
- * mono_image_build_metadata() will fill the info in all the needed metadata tables
- * for the modulebuilder @moduleb.
- * At the end of the process, method and field tokens are fixed up and the
- * on-disk compressed metadata representation is created.
- * Return TRUE on success, or FALSE on failure and sets @error
- */
-gboolean
-mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- MonoDynamicTable *table;
- MonoDynamicImage *assembly;
- MonoReflectionAssemblyBuilder *assemblyb;
- MonoDomain *domain;
- MonoPtrArray types;
- guint32 *values;
- int i, j;
-
- mono_error_init (error);
-
- assemblyb = moduleb->assemblyb;
- assembly = moduleb->dynamic_image;
- domain = mono_object_domain (assemblyb);
-
- if (assembly->text_rva)
- return TRUE;
-
- assembly->text_rva = START_TEXT_RVA;
-
- if (moduleb->is_main) {
- mono_image_emit_manifest (moduleb, error);
- return_val_if_nok (error, FALSE);
- }
-
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows = 1; /* .<Module> */
- table->next_idx++;
- alloc_table (table, table->rows);
- /*
- * Set the first entry.
- */
- values = table->values + table->columns;
- values [MONO_TYPEDEF_FLAGS] = 0;
- values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
- values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
- values [MONO_TYPEDEF_EXTENDS] = 0;
- values [MONO_TYPEDEF_FIELD_LIST] = 1;
- values [MONO_TYPEDEF_METHOD_LIST] = 1;
-
- /*
- * handle global methods
- * FIXME: test what to do when global methods are defined in multiple modules.
- */
- if (moduleb->global_methods) {
- table = &assembly->tables [MONO_TABLE_METHOD];
- table->rows += mono_array_length (moduleb->global_methods);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
- if (!mono_image_get_method_info (
- mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
- goto leave;
- }
- }
- if (moduleb->global_fields) {
- table = &assembly->tables [MONO_TABLE_FIELD];
- table->rows += mono_array_length (moduleb->global_fields);
- alloc_table (table, table->rows);
- for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
- mono_image_get_field_info (
- mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
- error);
- if (!is_ok (error))
- goto leave;
- }
- }
-
- table = &assembly->tables [MONO_TABLE_MODULE];
- alloc_table (table, 1);
- mono_image_fill_module_table (domain, moduleb, assembly, error);
- if (!is_ok (error))
- goto leave;
-
- /* Collect all types into a list sorted by their table_idx */
- mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
-
- if (moduleb->types)
- for (i = 0; i < moduleb->num_types; ++i) {
- MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
- collect_types (&types, type);
- }
-
- mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows += mono_ptr_array_size (types);
- alloc_table (table, table->rows);
-
- /*
- * Emit type names + namespaces at one place inside the string heap,
- * so load_class_names () needs to touch fewer pages.
- */
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
- if (!is_ok (error))
- goto leave_types;
- }
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- string_heap_insert_mstring (&assembly->sheap, tb->name, error);
- if (!is_ok (error))
- goto leave_types;
- }
-
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- if (!mono_image_get_type_info (domain, type, assembly, error))
- goto leave_types;
- }
-
- /*
- * table->rows is already set above and in mono_image_fill_module_table.
- */
- /* add all the custom attributes at the end, once all the indexes are stable */
- if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
- goto leave_types;
-
- /* CAS assembly permissions */
- if (assemblyb->permissions_minimum)
- mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
- if (assemblyb->permissions_optional)
- mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
- if (assemblyb->permissions_refused)
- mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
-
- if (!module_add_cattrs (assembly, moduleb, error))
- goto leave_types;
-
- /* fixup tokens */
- mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
-
- /* Create the MethodImpl table. We do this after emitting all methods so we already know
- * the final tokens and don't need another fixup pass. */
-
- if (moduleb->global_methods) {
- for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
- MonoReflectionMethodBuilder *mb = mono_array_get (
- moduleb->global_methods, MonoReflectionMethodBuilder*, i);
- if (!mono_image_add_methodimpl (assembly, mb, error))
- goto leave_types;
- }
- }
-
- for (i = 0; i < mono_ptr_array_size (types); ++i) {
- MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
- if (type->methods) {
- for (j = 0; j < type->num_methods; ++j) {
- MonoReflectionMethodBuilder *mb = mono_array_get (
- type->methods, MonoReflectionMethodBuilder*, j);
-
- if (!mono_image_add_methodimpl (assembly, mb, error))
- goto leave_types;
- }
- }
- }
-
- fixup_cattrs (assembly);
-
-leave_types:
- mono_ptr_array_destroy (types);
-leave:
-
- return mono_error_ok (error);
-}
-
-#else /* DISABLE_REFLECTION_EMIT_SAVE */
-
-gboolean
-mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
-}
-
-#endif /* DISABLE_REFLECTION_EMIT_SAVE */
-
-
-typedef struct {
- guint32 import_lookup_table;
- guint32 timestamp;
- guint32 forwarder;
- guint32 name_rva;
- guint32 import_address_table_rva;
-} MonoIDT;
-
-typedef struct {
- guint32 name_rva;
- guint32 flags;
-} MonoILT;
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-/*
- * mono_image_insert_string:
- * @module: module builder object
- * @str: a string
- *
- * Insert @str into the user string stream of @module.
- */
-guint32
-mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
-{
- MonoDynamicImage *assembly;
- guint32 idx;
- char buf [16];
- char *b = buf;
-
- if (!module->dynamic_image)
- mono_image_module_basic_init (module);
-
- assembly = module->dynamic_image;
-
- if (assembly->save) {
- mono_metadata_encode_value (1 | (str->length * 2), b, &b);
- idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- {
- char *swapped = g_malloc (2 * mono_string_length (str));
- const char *p = (const char*)mono_string_chars (str);
-
- swap_with_size (swapped, p, 2, mono_string_length (str));
- mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
- g_free (swapped);
- }
-#else
- mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
-#endif
- mono_image_add_stream_data (&assembly->us, "", 1);
- } else {
- idx = assembly->us.index ++;
- }
-
- register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
-
- return MONO_TOKEN_STRING | idx;
-}
-
-guint32
-mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
-{
- MonoClass *klass;
- guint32 token = 0;
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
- if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
- MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
- MonoMethodSignature *old;
- guint32 sig_token, parent;
- int nargs, i;
-
- g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
-
- nargs = mono_array_length (opt_param_types);
- old = mono_method_signature (method);
- sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
-
- sig->hasthis = old->hasthis;
- sig->explicit_this = old->explicit_this;
- sig->call_convention = old->call_convention;
- sig->generic_param_count = old->generic_param_count;
- sig->param_count = old->param_count + nargs;
- sig->sentinelpos = old->param_count;
- sig->ret = old->ret;
-
- for (i = 0; i < old->param_count; i++)
- sig->params [i] = old->params [i];
-
- for (i = 0; i < nargs; i++) {
- MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
- sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
- if (!is_ok (error)) goto fail;
- }
-
- parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
- g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
- parent >>= MONO_TYPEDEFORREF_BITS;
-
- parent <<= MONO_MEMBERREF_PARENT_BITS;
- parent |= MONO_MEMBERREF_PARENT_TYPEREF;
-
- sig_token = method_encode_signature (assembly, sig);
- token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
- } else if (strcmp (klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
- ReflectionMethodBuilder rmb;
- guint32 parent, sig_token;
- int nopt_args, nparams, ngparams, i;
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
- goto fail;
-
- rmb.opt_types = opt_param_types;
- nopt_args = mono_array_length (opt_param_types);
-
- nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
- ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
- sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
-
- sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
- sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
- sig->call_convention = rmb.call_conv;
- sig->generic_param_count = ngparams;
- sig->param_count = nparams + nopt_args;
- sig->sentinelpos = nparams;
- sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
- if (!is_ok (error)) goto fail;
-
- for (i = 0; i < nparams; i++) {
- MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
- sig->params [i] = mono_reflection_type_get_handle (rt, error);
- if (!is_ok (error)) goto fail;
- }
-
- for (i = 0; i < nopt_args; i++) {
- MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
- sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
- if (!is_ok (error)) goto fail;
- }
-
- sig_token = method_builder_encode_signature (assembly, &rmb, error);
- if (!is_ok (error))
- goto fail;
-
- parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
- if (!mono_error_ok (error))
- goto fail;
- g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
-
- parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
- parent |= MONO_MEMBERREF_PARENT_METHODDEF;
-
- char *name = mono_string_to_utf8_checked (rmb.name, error);
- if (!is_ok (error)) goto fail;
- token = mono_image_get_varargs_method_token (
- assembly, parent, name, sig_token);
- g_free (name);
- } else {
- g_error ("requested method token for %s\n", klass->name);
- }
-
- g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
- register_dyn_token (assembly, token, obj);
- return token;
-fail:
- g_assert (!mono_error_ok (error));
- return 0;
-}
-
-/*
- * mono_image_create_token:
- * @assembly: a dynamic assembly
- * @obj:
- * @register_token: Whenever to register the token in the assembly->tokens hash.
- *
- * Get a token to insert in the IL code stream for the given MemberInfo.
- * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
- * the table_idx-es were recomputed, so registering the token would overwrite an existing
- * entry.
- */
-guint32
-mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
- gboolean create_open_instance, gboolean register_token,
- MonoError *error)
-{
- MonoClass *klass;
- guint32 token = 0;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
-
- /* Check for user defined reflection objects */
- /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
- if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
- mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
- return 0;
- }
-
- if (strcmp (klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
-
- if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- else {
- token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
- if (!mono_error_ok (error))
- return 0;
- }
- /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
- MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
-
- if (tb->module->dynamic_image == assembly && !tb->generic_params)
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- else {
- token = mono_image_get_ctorbuilder_token (assembly, mb, error);
- if (!mono_error_ok (error))
- return 0;
- }
- /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- } else if (strcmp (klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
- if (tb->generic_params) {
- token = mono_image_get_generic_field_token (assembly, fb, error);
- return_val_if_nok (error, 0);
- } else {
- if (tb->module->dynamic_image == assembly) {
- token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
- } else {
- token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
- }
- }
- } else if (strcmp (klass->name, "TypeBuilder") == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
- if (create_open_instance && tb->generic_params) {
- MonoType *type;
- init_type_builder_generics (obj, error);
- return_val_if_nok (error, 0);
- type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
- token = mono_metadata_token_from_dor (token);
- } else if (tb->module->dynamic_image == assembly) {
- token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
- } else {
- MonoType *type;
- type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
- }
- } else if (strcmp (klass->name, "RuntimeType") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- MonoClass *mc = mono_class_from_mono_type (type);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
- } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
- strcmp (klass->name, "MonoMethod") == 0 ||
- strcmp (klass->name, "MonoGenericMethod") == 0 ||
- strcmp (klass->name, "MonoGenericCMethod") == 0) {
- MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
- if (m->method->is_inflated) {
- if (create_open_instance)
- token = mono_image_get_methodspec_token (assembly, m->method);
- else
- token = mono_image_get_inflated_method_token (assembly, m->method);
- } else if ((m->method->klass->image == &assembly->image) &&
- !m->method->klass->generic_class) {
- static guint32 method_table_idx = 0xffffff;
- if (m->method->klass->wastypebuilder) {
- /* we use the same token as the one that was assigned
- * to the Methodbuilder.
- * FIXME: do the equivalent for Fields.
- */
- token = m->method->token;
- } else {
- /*
- * Each token should have a unique index, but the indexes are
- * assigned by managed code, so we don't know about them. An
- * easy solution is to count backwards...
- */
- method_table_idx --;
- token = MONO_TOKEN_METHOD_DEF | method_table_idx;
- }
- } else {
- token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
- }
- /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
- } else if (strcmp (klass->name, "MonoField") == 0) {
- MonoReflectionField *f = (MonoReflectionField *)obj;
- if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
- static guint32 field_table_idx = 0xffffff;
- field_table_idx --;
- token = MONO_TOKEN_FIELD_DEF | field_table_idx;
- } else {
- token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
- }
- /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
- } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
- MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
- token = mono_image_get_array_token (assembly, m, error);
- return_val_if_nok (error, 0);
- } else if (strcmp (klass->name, "SignatureHelper") == 0) {
- MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
- token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
- return_val_if_nok (error, 0);
- } else if (strcmp (klass->name, "EnumBuilder") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
- MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
- token = mono_image_get_field_on_inst_token (assembly, f, error);
- return_val_if_nok (error, 0);
- } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
- MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
- token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
- if (!mono_error_ok (error))
- return 0;
- } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
- MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
- token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
- if (!mono_error_ok (error))
- return 0;
- } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, 0);
- token = mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, type));
- } else {
- g_error ("requested token for %s\n", klass->name);
- }
-
- if (register_token)
- mono_image_register_token (assembly, token, obj);
-
- return token;
-}
-
-/*
- * mono_image_register_token:
- *
- * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
- * the Module.ResolveXXXToken () methods to work.
- */
-void
-mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
-{
- MonoObject *prev;
-
- dynamic_image_lock (assembly);
- prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
- if (prev) {
- /* There could be multiple MethodInfo objects with the same token */
- //g_assert (prev == obj);
- } else {
- mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
- }
- dynamic_image_unlock (assembly);
-}
-
-static MonoDynamicImage*
-create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
-{
- static const guchar entrycode [16] = {0xff, 0x25, 0};
- MonoDynamicImage *image;
- int i;
-
- const char *version;
-
- if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
- version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
- else
- version = mono_get_runtime_info ()->runtime_version;
-
-#if HAVE_BOEHM_GC
- /* The MonoGHashTable's need GC tracking */
- image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
-#else
- image = g_new0 (MonoDynamicImage, 1);
-#endif
-
- mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
-
- /*g_print ("created image %p\n", image);*/
- /* keep in sync with image.c */
- image->image.name = assembly_name;
- image->image.assembly_name = image->image.name; /* they may be different */
- image->image.module_name = module_name;
- image->image.version = g_strdup (version);
- image->image.md_version_major = 1;
- image->image.md_version_minor = 1;
- image->image.dynamic = TRUE;
-
- image->image.references = g_new0 (MonoAssembly*, 1);
- image->image.references [0] = NULL;
-
- mono_image_init (&image->image);
-
- image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
- image->method_to_table_idx = g_hash_table_new (NULL, NULL);
- image->field_to_table_idx = g_hash_table_new (NULL, NULL);
- image->method_aux_hash = g_hash_table_new (NULL, NULL);
- image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
- image->handleref = g_hash_table_new (NULL, NULL);
- image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
- image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
- image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
- image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
- image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
- image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
- image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
- image->gen_params = g_ptr_array_new ();
- image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
-
- /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
- string_heap_init (&image->sheap);
- mono_image_add_stream_data (&image->us, "", 1);
- add_to_blob_cached (image, (char*) "", 1, NULL, 0);
- /* import tables... */
- mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
- image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
- image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
- image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
- mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
- mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
- image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
- stream_data_align (&image->code);
-
- image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
-
- for (i=0; i < MONO_TABLE_NUM; ++i) {
- image->tables [i].next_idx = 1;
- image->tables [i].columns = table_sizes [i];
- }
-
- image->image.assembly = (MonoAssembly*)assembly;
- image->run = assembly->run;
- image->save = assembly->save;
- image->pe_kind = 0x1; /* ILOnly */
- image->machine = 0x14c; /* I386 */
-
- mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
-
- dynamic_images_lock ();
-
- if (!dynamic_images)
- dynamic_images = g_ptr_array_new ();
-
- g_ptr_array_add (dynamic_images, image);
-
- dynamic_images_unlock ();
-
- return image;
-}
-#endif
-
-static void
-free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
-{
- g_free (key);
-}
-
-static void
-release_hashtable (MonoGHashTable **hash)
-{
- if (*hash) {
- mono_g_hash_table_destroy (*hash);
- *hash = NULL;
- }
-}
-
-void
-mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
-{
- release_hashtable (&image->token_fixups);
- release_hashtable (&image->handleref_managed);
- release_hashtable (&image->tokens);
- release_hashtable (&image->remapped_tokens);
- release_hashtable (&image->generic_def_objects);
- release_hashtable (&image->methodspec);
-}
-
-// Free dynamic image pass one: Free resources but not image itself
-void
-mono_dynamic_image_free (MonoDynamicImage *image)
-{
- MonoDynamicImage *di = image;
- GList *list;
- int i;
-
- if (di->methodspec)
- mono_g_hash_table_destroy (di->methodspec);
- if (di->typespec)
- g_hash_table_destroy (di->typespec);
- if (di->typeref)
- g_hash_table_destroy (di->typeref);
- if (di->handleref)
- g_hash_table_destroy (di->handleref);
- if (di->handleref_managed)
- mono_g_hash_table_destroy (di->handleref_managed);
- if (di->tokens)
- mono_g_hash_table_destroy (di->tokens);
- if (di->remapped_tokens)
- mono_g_hash_table_destroy (di->remapped_tokens);
- if (di->generic_def_objects)
- mono_g_hash_table_destroy (di->generic_def_objects);
- if (di->blob_cache) {
- g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
- g_hash_table_destroy (di->blob_cache);
- }
- if (di->standalonesig_cache)
- g_hash_table_destroy (di->standalonesig_cache);
- for (list = di->array_methods; list; list = list->next) {
- ArrayMethod *am = (ArrayMethod *)list->data;
- g_free (am->sig);
- g_free (am->name);
- g_free (am);
- }
- g_list_free (di->array_methods);
- if (di->gen_params) {
- for (i = 0; i < di->gen_params->len; i++) {
- GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
- mono_gc_deregister_root ((char*) &entry->gparam);
- g_free (entry);
- }
- g_ptr_array_free (di->gen_params, TRUE);
- }
- if (di->token_fixups)
- mono_g_hash_table_destroy (di->token_fixups);
- if (di->method_to_table_idx)
- g_hash_table_destroy (di->method_to_table_idx);
- if (di->field_to_table_idx)
- g_hash_table_destroy (di->field_to_table_idx);
- if (di->method_aux_hash)
- g_hash_table_destroy (di->method_aux_hash);
- if (di->vararg_aux_hash)
- g_hash_table_destroy (di->vararg_aux_hash);
- g_free (di->strong_name);
- g_free (di->win32_res);
- if (di->public_key)
- g_free (di->public_key);
-
- /*g_print ("string heap destroy for image %p\n", di);*/
- mono_dynamic_stream_reset (&di->sheap);
- mono_dynamic_stream_reset (&di->code);
- mono_dynamic_stream_reset (&di->resources);
- mono_dynamic_stream_reset (&di->us);
- mono_dynamic_stream_reset (&di->blob);
- mono_dynamic_stream_reset (&di->tstream);
- mono_dynamic_stream_reset (&di->guid);
- for (i = 0; i < MONO_TABLE_NUM; ++i) {
- g_free (di->tables [i].values);
- }
-
- dynamic_images_lock ();
-
- if (dynamic_images)
- g_ptr_array_remove (dynamic_images, di);
-
- dynamic_images_unlock ();
-}
-
-// Free dynamic image pass two: Free image itself (might never get called in some debug modes)
-void
-mono_dynamic_image_free_image (MonoDynamicImage *image)
-{
- /* See create_dynamic_mono_image () */
-#if HAVE_BOEHM_GC
- /* Allocated using GC_MALLOC */
-#else
- g_free (image);
-#endif
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-/*
- * mono_image_basic_init:
- * @assembly: an assembly builder object
- *
- * Create the MonoImage that represents the assembly builder and setup some
- * of the helper hash table and the basic metadata streams.
- */
-void
-mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
-{
- MonoError error;
- MonoDynamicAssembly *assembly;
- MonoDynamicImage *image;
- MonoDomain *domain = mono_object_domain (assemblyb);
-
- if (assemblyb->dynamic_assembly)
- return;
-
-#if HAVE_BOEHM_GC
- /* assembly->assembly.image might be GC allocated */
- assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
-#else
- assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
-#endif
-
- mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
-
- assembly->assembly.ref_count = 1;
- assembly->assembly.dynamic = TRUE;
- assembly->assembly.corlib_internal = assemblyb->corlib_internal;
- assemblyb->assembly.assembly = (MonoAssembly*)assembly;
- assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- if (assemblyb->culture) {
- assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- } else
- assembly->assembly.aname.culture = g_strdup ("");
-
- if (assemblyb->version) {
- char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- char **version = g_strsplit (vstr, ".", 4);
- char **parts = version;
- assembly->assembly.aname.major = atoi (*parts++);
- assembly->assembly.aname.minor = atoi (*parts++);
- assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
- assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
-
- g_strfreev (version);
- g_free (vstr);
- } else {
- assembly->assembly.aname.major = 0;
- assembly->assembly.aname.minor = 0;
- assembly->assembly.aname.build = 0;
- assembly->assembly.aname.revision = 0;
- }
-
- assembly->run = assemblyb->access != 2;
- assembly->save = assemblyb->access != 1;
- assembly->domain = domain;
-
- char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
- if (mono_error_set_pending_exception (&error))
- return;
- image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
- image->initial_image = TRUE;
- assembly->assembly.aname.name = image->image.name;
- assembly->assembly.image = &image->image;
- if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
- /* -1 to correct for the trailing NULL byte */
- if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
- g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
- }
- memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
- }
-
- mono_domain_assemblies_lock (domain);
- domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
- mono_domain_assemblies_unlock (domain);
-
- register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
-
- mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
-
- mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
-}
-
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-#ifndef DISABLE_REFLECTION_EMIT_SAVE
-
-static int
-calc_section_size (MonoDynamicImage *assembly)
-{
- int nsections = 0;
-
- /* alignment constraints */
- mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
- g_assert ((assembly->code.index % 4) == 0);
- assembly->meta_size += 3;
- assembly->meta_size &= ~3;
- mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
- g_assert ((assembly->resources.index % 4) == 0);
-
- assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
- assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
- nsections++;
-
- if (assembly->win32_res) {
- guint32 res_size = (assembly->win32_res_size + 3) & ~3;
-
- assembly->sections [MONO_SECTION_RSRC].size = res_size;
- assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
- nsections++;
- }
-
- assembly->sections [MONO_SECTION_RELOC].size = 12;
- assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
- nsections++;
-
- return nsections;
-}
-
-typedef struct {
- guint32 id;
- guint32 offset;
- GSList *children;
- MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
-} ResTreeNode;
-
-static int
-resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
-{
- ResTreeNode *t1 = (ResTreeNode*)a;
- ResTreeNode *t2 = (ResTreeNode*)b;
-
- return t1->id - t2->id;
-}
-
-/*
- * resource_tree_create:
- *
- * Organize the resources into a resource tree.
- */
-static ResTreeNode *
-resource_tree_create (MonoArray *win32_resources)
-{
- ResTreeNode *tree, *res_node, *type_node, *lang_node;
- GSList *l;
- int i;
-
- tree = g_new0 (ResTreeNode, 1);
-
- for (i = 0; i < mono_array_length (win32_resources); ++i) {
- MonoReflectionWin32Resource *win32_res =
- (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
-
- /* Create node */
-
- /* FIXME: BUG: this stores managed references in unmanaged memory */
- lang_node = g_new0 (ResTreeNode, 1);
- lang_node->id = win32_res->lang_id;
- lang_node->win32_res = win32_res;
-
- /* Create type node if neccesary */
- type_node = NULL;
- for (l = tree->children; l; l = l->next)
- if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
- type_node = (ResTreeNode*)l->data;
- break;
- }
-
- if (!type_node) {
- type_node = g_new0 (ResTreeNode, 1);
- type_node->id = win32_res->res_type;
-
- /*
- * The resource types have to be sorted otherwise
- * Windows Explorer can't display the version information.
- */
- tree->children = g_slist_insert_sorted (tree->children,
- type_node, resource_tree_compare_by_id);
- }
-
- /* Create res node if neccesary */
- res_node = NULL;
- for (l = type_node->children; l; l = l->next)
- if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
- res_node = (ResTreeNode*)l->data;
- break;
- }
-
- if (!res_node) {
- res_node = g_new0 (ResTreeNode, 1);
- res_node->id = win32_res->res_id;
- type_node->children = g_slist_append (type_node->children, res_node);
- }
-
- res_node->children = g_slist_append (res_node->children, lang_node);
- }
-
- return tree;
-}
-
-/*
- * resource_tree_encode:
- *
- * Encode the resource tree into the format used in the PE file.
- */
-static void
-resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
-{
- char *entries;
- MonoPEResourceDir dir;
- MonoPEResourceDirEntry dir_entry;
- MonoPEResourceDataEntry data_entry;
- GSList *l;
- guint32 res_id_entries;
-
- /*
- * For the format of the resource directory, see the article
- * "An In-Depth Look into the Win32 Portable Executable File Format" by
- * Matt Pietrek
- */
-
- memset (&dir, 0, sizeof (dir));
- memset (&dir_entry, 0, sizeof (dir_entry));
- memset (&data_entry, 0, sizeof (data_entry));
-
- g_assert (sizeof (dir) == 16);
- g_assert (sizeof (dir_entry) == 8);
- g_assert (sizeof (data_entry) == 16);
-
- node->offset = p - begin;
-
- /* IMAGE_RESOURCE_DIRECTORY */
- res_id_entries = g_slist_length (node->children);
- dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
-
- memcpy (p, &dir, sizeof (dir));
- p += sizeof (dir);
-
- /* Reserve space for entries */
- entries = p;
- p += sizeof (dir_entry) * res_id_entries;
-
- /* Write children */
- for (l = node->children; l; l = l->next) {
- ResTreeNode *child = (ResTreeNode*)l->data;
-
- if (child->win32_res) {
- guint32 size;
-
- child->offset = p - begin;
-
- /* IMAGE_RESOURCE_DATA_ENTRY */
- data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
- size = mono_array_length (child->win32_res->res_data);
- data_entry.rde_size = GUINT32_TO_LE (size);
-
- memcpy (p, &data_entry, sizeof (data_entry));
- p += sizeof (data_entry);
-
- memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
- p += size;
- } else {
- resource_tree_encode (child, begin, p, &p);
- }
- }
-
- /* IMAGE_RESOURCE_ENTRY */
- for (l = node->children; l; l = l->next) {
- ResTreeNode *child = (ResTreeNode*)l->data;
-
- MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
- MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
-
- memcpy (entries, &dir_entry, sizeof (dir_entry));
- entries += sizeof (dir_entry);
- }
-
- *endbuf = p;
-}
-
-static void
-resource_tree_free (ResTreeNode * node)
-{
- GSList * list;
- for (list = node->children; list; list = list->next)
- resource_tree_free ((ResTreeNode*)list->data);
- g_slist_free(node->children);
- g_free (node);
-}
-
-static void
-assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
-{
- char *buf;
- char *p;
- guint32 size, i;
- MonoReflectionWin32Resource *win32_res;
- ResTreeNode *tree;
-
- if (!assemblyb->win32_resources)
- return;
-
- /*
- * Resources are stored in a three level tree inside the PE file.
- * - level one contains a node for each type of resource
- * - level two contains a node for each resource
- * - level three contains a node for each instance of a resource for a
- * specific language.
- */
-
- tree = resource_tree_create (assemblyb->win32_resources);
-
- /* Estimate the size of the encoded tree */
- size = 0;
- for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
- win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
- size += mono_array_length (win32_res->res_data);
- }
- /* Directory structure */
- size += mono_array_length (assemblyb->win32_resources) * 256;
- p = buf = (char *)g_malloc (size);
-
- resource_tree_encode (tree, p, p, &p);
-
- g_assert (p - buf <= size);
-
- assembly->win32_res = (char *)g_malloc (p - buf);
- assembly->win32_res_size = p - buf;
- memcpy (assembly->win32_res, buf, p - buf);
-
- g_free (buf);
- resource_tree_free (tree);
-}
-
-static void
-fixup_resource_directory (char *res_section, char *p, guint32 rva)
-{
- MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
- int i;
-
- p += sizeof (MonoPEResourceDir);
- for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
- MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
- char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
- if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
- fixup_resource_directory (res_section, child, rva);
- } else {
- MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
- data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
- }
-
- p += sizeof (MonoPEResourceDirEntry);
- }
-}
-
-static void
-checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
-{
- guint32 dummy;
- if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
- g_error ("WriteFile returned %d\n", GetLastError ());
-}
-
-/*
- * mono_image_create_pefile:
- * @mb: a module builder object
- *
- * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
- * assembly->pefile where it can be easily retrieved later in chunks.
- */
-gboolean
-mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
-{
- MonoMSDOSHeader *msdos;
- MonoDotNetHeader *header;
- MonoSectionTable *section;
- MonoCLIHeader *cli_header;
- guint32 size, image_size, virtual_base, text_offset;
- guint32 header_start, section_start, file_offset, virtual_offset;
- MonoDynamicImage *assembly;
- MonoReflectionAssemblyBuilder *assemblyb;
- MonoDynamicStream pefile_stream = {0};
- MonoDynamicStream *pefile = &pefile_stream;
- int i, nsections;
- guint32 *rva, value;
- guchar *p;
- static const unsigned char msheader[] = {
- 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
- 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
- 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
- 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- mono_error_init (error);
-
- assemblyb = mb->assemblyb;
-
- mono_image_basic_init (assemblyb);
- assembly = mb->dynamic_image;
-
- assembly->pe_kind = assemblyb->pe_kind;
- assembly->machine = assemblyb->machine;
- ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
- ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
-
- if (!mono_image_build_metadata (mb, error))
- return FALSE;
-
-
- if (mb->is_main && assemblyb->resources) {
- int len = mono_array_length (assemblyb->resources);
- for (i = 0; i < len; ++i) {
- if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
- return FALSE;
- }
- }
-
- if (mb->resources) {
- int len = mono_array_length (mb->resources);
- for (i = 0; i < len; ++i) {
- if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
- return FALSE;
- }
- }
-
- if (!build_compressed_metadata (assembly, error))
- return FALSE;
-
- if (mb->is_main)
- assembly_add_win32_resources (assembly, assemblyb);
-
- nsections = calc_section_size (assembly);
-
- /* The DOS header and stub */
- g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
- mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
-
- /* the dotnet header */
- header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
-
- /* the section tables */
- section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
-
- file_offset = section_start + sizeof (MonoSectionTable) * nsections;
- virtual_offset = VIRT_ALIGN;
- image_size = 0;
-
- for (i = 0; i < MONO_SECTION_MAX; ++i) {
- if (!assembly->sections [i].size)
- continue;
- /* align offsets */
- file_offset += FILE_ALIGN - 1;
- file_offset &= ~(FILE_ALIGN - 1);
- virtual_offset += VIRT_ALIGN - 1;
- virtual_offset &= ~(VIRT_ALIGN - 1);
-
- assembly->sections [i].offset = file_offset;
- assembly->sections [i].rva = virtual_offset;
-
- file_offset += assembly->sections [i].size;
- virtual_offset += assembly->sections [i].size;
- image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
- }
-
- file_offset += FILE_ALIGN - 1;
- file_offset &= ~(FILE_ALIGN - 1);
-
- image_size += section_start + sizeof (MonoSectionTable) * nsections;
-
- /* back-patch info */
- msdos = (MonoMSDOSHeader*)pefile->data;
- msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
-
- header = (MonoDotNetHeader*)(pefile->data + header_start);
- header->pesig [0] = 'P';
- header->pesig [1] = 'E';
-
- header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
- header->coff.coff_sections = GUINT16_FROM_LE (nsections);
- header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
- header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
- if (assemblyb->pekind == 1) {
- /* it's a dll */
- header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
- } else {
- /* it's an exe */
- header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
- }
-
- virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
-
- header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
- header->pe.pe_major = 6;
- header->pe.pe_minor = 0;
- size = assembly->sections [MONO_SECTION_TEXT].size;
- size += FILE_ALIGN - 1;
- size &= ~(FILE_ALIGN - 1);
- header->pe.pe_code_size = GUINT32_FROM_LE(size);
- size = assembly->sections [MONO_SECTION_RSRC].size;
- size += FILE_ALIGN - 1;
- size &= ~(FILE_ALIGN - 1);
- header->pe.pe_data_size = GUINT32_FROM_LE(size);
- g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
- header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
- header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
- /* pe_rva_entry_point always at the beginning of the text section */
- header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
-
- header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
- header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
- header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
- header->nt.pe_os_major = GUINT16_FROM_LE (4);
- header->nt.pe_os_minor = GUINT16_FROM_LE (0);
- header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
- size = section_start;
- size += FILE_ALIGN - 1;
- size &= ~(FILE_ALIGN - 1);
- header->nt.pe_header_size = GUINT32_FROM_LE (size);
- size = image_size;
- size += VIRT_ALIGN - 1;
- size &= ~(VIRT_ALIGN - 1);
- header->nt.pe_image_size = GUINT32_FROM_LE (size);
-
- /*
- // Translate the PEFileKind value to the value expected by the Windows loader
- */
- {
- short kind;
-
- /*
- // PEFileKinds.Dll == 1
- // PEFileKinds.ConsoleApplication == 2
- // PEFileKinds.WindowApplication == 3
- //
- // need to get:
- // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
- // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
- */
- if (assemblyb->pekind == 3)
- kind = 2;
- else
- kind = 3;
-
- header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
- }
- header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
- header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
- header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
- header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
- header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
- header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
-
- /* fill data directory entries */
-
- header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
- header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
-
- header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
- header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
-
- header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
- header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
- header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
- header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
- /* patch entrypoint name */
- if (assemblyb->pekind == 1)
- memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
- else
- memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
- /* patch imported function RVA name */
- rva = (guint32*)(assembly->code.data + assembly->iat_offset);
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
-
- /* the import table */
- header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
- header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
- /* patch imported dll RVA name and other entries in the dir */
- rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
- rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
- rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
-
- p = (guchar*)(assembly->code.data + assembly->ilt_offset);
- value = (assembly->text_rva + assembly->imp_names_offset);
- *p++ = (value) & 0xff;
- *p++ = (value >> 8) & (0xff);
- *p++ = (value >> 16) & (0xff);
- *p++ = (value >> 24) & (0xff);
-
- /* the CLI header info */
- cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
- cli_header->ch_size = GUINT32_FROM_LE (72);
- cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
- cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
- cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
- if (assemblyb->entry_point) {
- guint32 table_idx = 0;
- if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
- MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
- table_idx = methodb->table_idx;
- } else {
- table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
- }
- cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
- } else {
- cli_header->ch_entry_point = GUINT32_FROM_LE (0);
- }
- /* The embedded managed resources */
- text_offset = assembly->text_rva + assembly->code.index;
- cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
- cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
- text_offset += assembly->resources.index;
- cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
- cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
- text_offset += assembly->meta_size;
- if (assembly->strong_name_size) {
- cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
- cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
- text_offset += assembly->strong_name_size;
- }
-
- /* write the section tables and section content */
- section = (MonoSectionTable*)(pefile->data + section_start);
- for (i = 0; i < MONO_SECTION_MAX; ++i) {
- static const char section_names [][7] = {
- ".text", ".rsrc", ".reloc"
- };
- if (!assembly->sections [i].size)
- continue;
- strcpy (section->st_name, section_names [i]);
- /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
- section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
- section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
- section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
- section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
- section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
- section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
- section ++;
- }
-
- checked_write_file (file, pefile->data, pefile->index);
-
- mono_dynamic_stream_reset (pefile);
-
- for (i = 0; i < MONO_SECTION_MAX; ++i) {
- if (!assembly->sections [i].size)
- continue;
-
- if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- g_error ("SetFilePointer returned %d\n", GetLastError ());
-
- switch (i) {
- case MONO_SECTION_TEXT:
- /* patch entry point */
- p = (guchar*)(assembly->code.data + 2);
- value = (virtual_base + assembly->text_rva + assembly->iat_offset);
- *p++ = (value) & 0xff;
- *p++ = (value >> 8) & 0xff;
- *p++ = (value >> 16) & 0xff;
- *p++ = (value >> 24) & 0xff;
-
- checked_write_file (file, assembly->code.data, assembly->code.index);
- checked_write_file (file, assembly->resources.data, assembly->resources.index);
- checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
- checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
-
-
- g_free (assembly->image.raw_metadata);
- break;
- case MONO_SECTION_RELOC: {
- struct {
- guint32 page_rva;
- guint32 block_size;
- guint16 type_and_offset;
- guint16 term;
- } reloc;
-
- g_assert (sizeof (reloc) == 12);
-
- reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
- reloc.block_size = GUINT32_FROM_LE (12);
-
- /*
- * the entrypoint is always at the start of the text section
- * 3 is IMAGE_REL_BASED_HIGHLOW
- * 2 is patch_size_rva - text_rva
- */
- reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
- reloc.term = 0;
-
- checked_write_file (file, &reloc, sizeof (reloc));
-
- break;
- }
- case MONO_SECTION_RSRC:
- if (assembly->win32_res) {
-
- /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
- fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
- checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
- }
- break;
- default:
- g_assert_not_reached ();
- }
- }
-
- /* check that the file is properly padded */
- if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- g_error ("SetFilePointer returned %d\n", GetLastError ());
- if (! SetEndOfFile (file))
- g_error ("SetEndOfFile returned %d\n", GetLastError ());
-
- mono_dynamic_stream_reset (&assembly->code);
- mono_dynamic_stream_reset (&assembly->us);
- mono_dynamic_stream_reset (&assembly->blob);
- mono_dynamic_stream_reset (&assembly->guid);
- mono_dynamic_stream_reset (&assembly->sheap);
-
- g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
- g_hash_table_destroy (assembly->blob_cache);
- assembly->blob_cache = NULL;
-
- return TRUE;
-}
-
-#else /* DISABLE_REFLECTION_EMIT_SAVE */
-
-gboolean
-mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
-{
- g_assert_not_reached ();
-}
-
-#endif /* DISABLE_REFLECTION_EMIT_SAVE */
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-MonoReflectionModule *
-mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
-{
- char *name;
- MonoImage *image;
- MonoImageOpenStatus status;
- MonoDynamicAssembly *assembly;
- guint32 module_count;
- MonoImage **new_modules;
- gboolean *new_modules_loaded;
-
- mono_error_init (error);
-
- name = mono_string_to_utf8_checked (fileName, error);
- return_val_if_nok (error, NULL);
-
- image = mono_image_open (name, &status);
- if (!image) {
- if (status == MONO_IMAGE_ERROR_ERRNO)
- mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
- else
- mono_error_set_bad_image_name (error, name, NULL);
- g_free (name);
- return NULL;
- }
-
- g_free (name);
-
- assembly = ab->dynamic_assembly;
- image->assembly = (MonoAssembly*)assembly;
-
- module_count = image->assembly->image->module_count;
- new_modules = g_new0 (MonoImage *, module_count + 1);
- new_modules_loaded = g_new0 (gboolean, module_count + 1);
-
- if (image->assembly->image->modules)
- memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
- if (image->assembly->image->modules_loaded)
- memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
- new_modules [module_count] = image;
- new_modules_loaded [module_count] = TRUE;
- mono_image_addref (image);
-
- g_free (image->assembly->image->modules);
- image->assembly->image->modules = new_modules;
- image->assembly->image->modules_loaded = new_modules_loaded;
- image->assembly->image->module_count ++;
-
- mono_assembly_load_references (image, &status);
- if (status) {
- mono_image_close (image);
- mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
- return NULL;
- }
-
- return mono_module_get_object_checked (mono_domain_get (), image, error);
-}
-
-#endif /* DISABLE_REFLECTION_EMIT */
-
-/*
- * We need to return always the same object for MethodInfo, FieldInfo etc..
- * but we need to consider the reflected type.
- * type uses a different hash, since it uses custom hash/equal functions.
- */
-
-typedef struct {
- gpointer item;
- MonoClass *refclass;
-} ReflectedEntry;
-
-static gboolean
-reflected_equal (gconstpointer a, gconstpointer b) {
- const ReflectedEntry *ea = (const ReflectedEntry *)a;
- const ReflectedEntry *eb = (const ReflectedEntry *)b;
-
- return (ea->item == eb->item) && (ea->refclass == eb->refclass);
-}
-
-static guint
-reflected_hash (gconstpointer a) {
- const ReflectedEntry *ea = (const ReflectedEntry *)a;
- return mono_aligned_addr_hash (ea->item);
-}
-
-#define CHECK_OBJECT(t,p,k) \
- do { \
- t _obj; \
- ReflectedEntry e; \
- e.item = (p); \
- e.refclass = (k); \
- mono_domain_lock (domain); \
- if (!domain->refobject_hash) \
- domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
- if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
- mono_domain_unlock (domain); \
- return _obj; \
- } \
- mono_domain_unlock (domain); \
- } while (0)
-
-#ifdef HAVE_BOEHM_GC
-/* ReflectedEntry doesn't need to be GC tracked */
-#define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
-#define FREE_REFENTRY(entry) g_free ((entry))
-#define REFENTRY_REQUIRES_CLEANUP
-#else
-#define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
-/* FIXME: */
-#define FREE_REFENTRY(entry)
-#endif
-
-#define CACHE_OBJECT(t,p,o,k) \
- do { \
- t _obj; \
- ReflectedEntry pe; \
- pe.item = (p); \
- pe.refclass = (k); \
- mono_domain_lock (domain); \
- if (!domain->refobject_hash) \
- domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
- _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
- if (!_obj) { \
- ReflectedEntry *e = ALLOC_REFENTRY; \
- e->item = (p); \
- e->refclass = (k); \
- mono_g_hash_table_insert (domain->refobject_hash, e,o); \
- _obj = o; \
- } \
- mono_domain_unlock (domain); \
- return _obj; \
- } while (0)
-
-static void
-clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
-{
- mono_domain_lock (domain);
- if (domain->refobject_hash) {
- ReflectedEntry pe;
- gpointer orig_pe, orig_value;
-
- pe.item = o;
- pe.refclass = klass;
- if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
- mono_g_hash_table_remove (domain->refobject_hash, &pe);
- FREE_REFENTRY (orig_pe);
- }
- }
- mono_domain_unlock (domain);
-}
-
-#ifdef REFENTRY_REQUIRES_CLEANUP
-static void
-cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
-{
- FREE_REFENTRY (key);
-}
-#endif
-
-void
-mono_reflection_cleanup_domain (MonoDomain *domain)
-{
- if (domain->refobject_hash) {
-/*let's avoid scanning the whole hashtable if not needed*/
-#ifdef REFENTRY_REQUIRES_CLEANUP
- mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
-#endif
- mono_g_hash_table_destroy (domain->refobject_hash);
- domain->refobject_hash = NULL;
- }
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static gpointer
-register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
-{
- CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
-}
-
-static gpointer
-register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
-{
- CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
-}
-
-static gboolean
-image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
-{
- MonoDynamicImage *image = moduleb->dynamic_image;
- MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
- mono_error_init (error);
- if (!image) {
- int module_count;
- MonoImage **new_modules;
- MonoImage *ass;
- char *name, *fqname;
- /*
- * FIXME: we already created an image in mono_image_basic_init (), but
- * we don't know which module it belongs to, since that is only
- * determined at assembly save time.
- */
- /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
- name = mono_string_to_utf8_checked (ab->name, error);
- return_val_if_nok (error, FALSE);
- fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
- if (!is_ok (error)) {
- g_free (name);
- return FALSE;
- }
- image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
-
- moduleb->module.image = &image->image;
- moduleb->dynamic_image = image;
- register_module (mono_object_domain (moduleb), moduleb, image);
-
- /* register the module with the assembly */
- ass = ab->dynamic_assembly->assembly.image;
- module_count = ass->module_count;
- new_modules = g_new0 (MonoImage *, module_count + 1);
-
- if (ass->modules)
- memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
- new_modules [module_count] = &image->image;
- mono_image_addref (&image->image);
-
- g_free (ass->modules);
- ass->modules = new_modules;
- ass->module_count ++;
- }
- return TRUE;
-}
-
-void
-mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
-{
- MonoError error;
- (void) image_module_basic_init (moduleb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-void
-mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
-{
- MonoDynamicImage *image = moduleb->dynamic_image;
-
- g_assert (type->type);
- image->wrappers_type = mono_class_from_mono_type (type->type);
-}
-
-#endif
-
-/*
- * mono_assembly_get_object:
- * @domain: an app domain
- * @assembly: an assembly
- *
- * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
- */
-MonoReflectionAssembly*
-mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
-{
- MonoError error;
- MonoReflectionAssembly *result;
- result = mono_assembly_get_object_checked (domain, assembly, &error);
- mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
- return result;
-}
-/*
- * mono_assembly_get_object_checked:
- * @domain: an app domain
- * @assembly: an assembly
- *
- * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
- */
-MonoReflectionAssembly*
-mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
-{
- MonoReflectionAssembly *res;
-
- mono_error_init (error);
-
- CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
- res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
- if (!res)
- return NULL;
- res->assembly = assembly;
-
- CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
-}
-
-
-
-MonoReflectionModule*
-mono_module_get_object (MonoDomain *domain, MonoImage *image)
-{
- MonoError error;
- MonoReflectionModule *result;
- result = mono_module_get_object_checked (domain, image, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoReflectionModule*
-mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
-{
- MonoReflectionModule *res;
- char* basename;
-
- mono_error_init (error);
- CHECK_OBJECT (MonoReflectionModule *, image, NULL);
- res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
- if (!res)
- return NULL;
-
- res->image = image;
- MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
- if (!assm_obj)
- return NULL;
- MONO_OBJECT_SETREF (res, assembly, assm_obj);
-
- MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
- basename = g_path_get_basename (image->name);
- MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
- MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
-
- g_free (basename);
-
- if (image->assembly->image == image) {
- res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
- } else {
- int i;
- res->token = 0;
- if (image->assembly->image->modules) {
- for (i = 0; i < image->assembly->image->module_count; i++) {
- if (image->assembly->image->modules [i] == image)
- res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
- }
- g_assert (res->token);
- }
- }
-
- CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
-}
-
-MonoReflectionModule*
-mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
-{
- MonoError error;
- MonoReflectionModule *result;
- result = mono_module_file_get_object_checked (domain, image, table_index, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoReflectionModule*
-mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
-{
- MonoReflectionModule *res;
- MonoTableInfo *table;
- guint32 cols [MONO_FILE_SIZE];
- const char *name;
- guint32 i, name_idx;
- const char *val;
-
- mono_error_init (error);
-
- res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
- if (!res)
- return NULL;
-
- table = &image->tables [MONO_TABLE_FILE];
- g_assert (table_index < table->rows);
- mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
-
- res->image = NULL;
- MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
- if (!assm_obj)
- return NULL;
- MONO_OBJECT_SETREF (res, assembly, assm_obj);
- name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
-
- /* Check whenever the row has a corresponding row in the moduleref table */
- table = &image->tables [MONO_TABLE_MODULEREF];
- for (i = 0; i < table->rows; ++i) {
- name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
- val = mono_metadata_string_heap (image, name_idx);
- if (strcmp (val, name) == 0)
- res->image = image->modules [i];
- }
-
- MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
- MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
- MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
- res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
- res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
-
- return res;
-}
-
-static gboolean
-verify_safe_for_managed_space (MonoType *type)
-{
- switch (type->type) {
-#ifdef DEBUG_HARDER
- case MONO_TYPE_ARRAY:
- return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
- case MONO_TYPE_PTR:
- return verify_safe_for_managed_space (type->data.type);
- case MONO_TYPE_SZARRAY:
- return verify_safe_for_managed_space (&type->data.klass->byval_arg);
- case MONO_TYPE_GENERICINST: {
- MonoGenericInst *inst = type->data.generic_class->inst;
- int i;
- if (!inst->is_open)
- break;
- for (i = 0; i < inst->type_argc; ++i)
- if (!verify_safe_for_managed_space (inst->type_argv [i]))
- return FALSE;
- return TRUE;
- }
-#endif
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- return TRUE;
- default:
- return TRUE;
- }
-}
-
-static MonoType*
-mono_type_normalize (MonoType *type)
-{
- int i;
- MonoGenericClass *gclass;
- MonoGenericInst *ginst;
- MonoClass *gtd;
- MonoGenericContainer *gcontainer;
- MonoType **argv = NULL;
- gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
-
- if (type->type != MONO_TYPE_GENERICINST)
- return type;
-
- gclass = type->data.generic_class;
- ginst = gclass->context.class_inst;
- if (!ginst->is_open)
- return type;
-
- gtd = gclass->container_class;
- gcontainer = gtd->generic_container;
- argv = g_newa (MonoType*, ginst->type_argc);
-
- for (i = 0; i < ginst->type_argc; ++i) {
- MonoType *t = ginst->type_argv [i], *norm;
- if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
- is_denorm_gtd = FALSE;
- norm = mono_type_normalize (t);
- argv [i] = norm;
- if (norm != t)
- requires_rebind = TRUE;
- }
-
- if (is_denorm_gtd)
- return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
-
- if (requires_rebind) {
- MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
- return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
- }
-
- return type;
-}
-/*
- * mono_type_get_object:
- * @domain: an app domain
- * @type: a type
- *
- * Return an System.MonoType object representing the type @type.
- */
-MonoReflectionType*
-mono_type_get_object (MonoDomain *domain, MonoType *type)
-{
- MonoError error;
- MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
- mono_error_cleanup (&error);
-
- return ret;
-}
-
-MonoReflectionType*
-mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
-{
- MonoType *norm_type;
- MonoReflectionType *res;
- MonoClass *klass;
-
- mono_error_init (error);
-
- klass = mono_class_from_mono_type (type);
-
- /*we must avoid using @type as it might have come
- * from a mono_metadata_type_dup and the caller
- * expects that is can be freed.
- * Using the right type from
- */
- type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
-
- /* void is very common */
- if (type->type == MONO_TYPE_VOID && domain->typeof_void)
- return (MonoReflectionType*)domain->typeof_void;
-
- /*
- * If the vtable of the given class was already created, we can use
- * the MonoType from there and avoid all locking and hash table lookups.
- *
- * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
- * that the resulting object is different.
- */
- if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
- MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
- if (vtable && vtable->type)
- return (MonoReflectionType *)vtable->type;
- }
-
- mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
- mono_domain_lock (domain);
- if (!domain->type_hash)
- domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
- (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
- if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return res;
- }
-
- /*Types must be normalized so a generic instance of the GTD get's the same inner type.
- * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
- * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
- * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
- * artifact of how generics are encoded and should be transparent to managed code so we
- * need to weed out this diference when retrieving managed System.Type objects.
- */
- norm_type = mono_type_normalize (type);
- if (norm_type != type) {
- res = mono_type_get_object_checked (domain, norm_type, error);
- if (!mono_error_ok (error))
- return NULL;
- mono_g_hash_table_insert (domain->type_hash, type, res);
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return res;
- }
-
- /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
- if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
- g_assert (0);
-
- if (!verify_safe_for_managed_space (type)) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
- return NULL;
- }
-
- if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
- gboolean is_type_done = TRUE;
- /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
- * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
- * We can't simply close the types as this will interfere with other parts of the generics machinery.
- */
- if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
- MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
-
- if (gparam->owner && gparam->owner->is_method) {
- MonoMethod *method = gparam->owner->owner.method;
- if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
- is_type_done = FALSE;
- } else if (gparam->owner && !gparam->owner->is_method) {
- MonoClass *klass = gparam->owner->owner.klass;
- if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
- is_type_done = FALSE;
- }
- }
-
- /* g_assert_not_reached (); */
- /* should this be considered an error condition? */
- if (is_type_done && !type->byref) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return (MonoReflectionType *)mono_class_get_ref_info (klass);
- }
- }
- /* This is stored in vtables/JITted code so it has to be pinned */
- res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
- if (!mono_error_ok (error))
- return NULL;
-
- res->type = type;
- mono_g_hash_table_insert (domain->type_hash, type, res);
-
- if (type->type == MONO_TYPE_VOID)
- domain->typeof_void = (MonoObject*)res;
-
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return res;
-}
-
-/*
- * mono_method_get_object:
- * @domain: an app domain
- * @method: a method
- * @refclass: the reflected type (can be NULL)
- *
- * Return an System.Reflection.MonoMethod object representing the method @method.
- */
-MonoReflectionMethod*
-mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
-{
- MonoError error;
- MonoReflectionMethod *ret = NULL;
- ret = mono_method_get_object_checked (domain, method, refclass, &error);
- mono_error_cleanup (&error);
- return ret;
-}
-
-/*
- * mono_method_get_object_checked:
- * @domain: an app domain
- * @method: a method
- * @refclass: the reflected type (can be NULL)
- * @error: set on error.
- *
- * Return an System.Reflection.MonoMethod object representing the method @method.
- * Returns NULL and sets @error on error.
- */
-MonoReflectionMethod*
-mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
-{
- /*
- * We use the same C representation for methods and constructors, but the type
- * name in C# is different.
- */
- MonoReflectionType *rt;
- MonoClass *klass;
- MonoReflectionMethod *ret;
-
- mono_error_init (error);
-
- if (method->is_inflated) {
- MonoReflectionGenericMethod *gret;
-
- if (!refclass)
- refclass = method->klass;
- CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
- if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
- klass = mono_class_get_mono_generic_cmethod_class ();
- } else {
- klass = mono_class_get_mono_generic_method_class ();
- }
- gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
- if (!mono_error_ok (error))
- goto leave;
- gret->method.method = method;
-
- MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
-
- rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
- if (!mono_error_ok (error))
- goto leave;
-
- MONO_OBJECT_SETREF (gret, method.reftype, rt);
-
- CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
- }
-
- if (!refclass)
- refclass = method->klass;
-
- CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
- if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
- klass = mono_class_get_mono_cmethod_class ();
- }
- else {
- klass = mono_class_get_mono_method_class ();
- }
- ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
- if (!mono_error_ok (error))
- goto leave;
- ret->method = method;
-
- rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
- if (!mono_error_ok (error))
- goto leave;
-
- MONO_OBJECT_SETREF (ret, reftype, rt);
-
- CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
-
-leave:
- g_assert (!mono_error_ok (error));
- return NULL;
-}
-
-/*
- * mono_method_clear_object:
- *
- * Clear the cached reflection objects for the dynamic method METHOD.
- */
-void
-mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
-{
- MonoClass *klass;
- g_assert (method_is_dynamic (method));
-
- klass = method->klass;
- while (klass) {
- clear_cached_object (domain, method, klass);
- klass = klass->parent;
- }
- /* Added by mono_param_get_objects () */
- clear_cached_object (domain, &(method->signature), NULL);
- klass = method->klass;
- while (klass) {
- clear_cached_object (domain, &(method->signature), klass);
- klass = klass->parent;
- }
-}
-
-/*
- * mono_field_get_object:
- * @domain: an app domain
- * @klass: a type
- * @field: a field
- *
- * Return an System.Reflection.MonoField object representing the field @field
- * in class @klass.
- */
-MonoReflectionField*
-mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
-{
- MonoError error;
- MonoReflectionField *result;
- result = mono_field_get_object_checked (domain, klass, field, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/*
- * mono_field_get_object_checked:
- * @domain: an app domain
- * @klass: a type
- * @field: a field
- * @error: set on error
- *
- * Return an System.Reflection.MonoField object representing the field @field
- * in class @klass. On error, returns NULL and sets @error.
- */
-MonoReflectionField*
-mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
-{
- MonoReflectionType *rt;
- MonoReflectionField *res;
-
- mono_error_init (error);
-
- CHECK_OBJECT (MonoReflectionField *, field, klass);
- res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
- if (!res)
- return NULL;
- res->klass = klass;
- res->field = field;
- MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
-
- if (is_field_on_inst (field)) {
- res->attrs = get_field_on_inst_generic_type (field)->attrs;
-
- rt = mono_type_get_object_checked (domain, field->type, error);
- if (!mono_error_ok (error))
- return NULL;
-
- MONO_OBJECT_SETREF (res, type, rt);
- } else {
- if (field->type) {
- rt = mono_type_get_object_checked (domain, field->type, error);
- if (!mono_error_ok (error))
- return NULL;
-
- MONO_OBJECT_SETREF (res, type, rt);
- }
- res->attrs = mono_field_get_flags (field);
- }
- CACHE_OBJECT (MonoReflectionField *, field, res, klass);
-}
-
-/*
- * mono_property_get_object:
- * @domain: an app domain
- * @klass: a type
- * @property: a property
- *
- * Return an System.Reflection.MonoProperty object representing the property @property
- * in class @klass.
- */
-MonoReflectionProperty*
-mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
-{
- MonoError error;
- MonoReflectionProperty *result;
- result = mono_property_get_object_checked (domain, klass, property, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_property_get_object:
- * @domain: an app domain
- * @klass: a type
- * @property: a property
- * @error: set on error
- *
- * Return an System.Reflection.MonoProperty object representing the property @property
- * in class @klass. On error returns NULL and sets @error.
- */
-MonoReflectionProperty*
-mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
-{
- MonoReflectionProperty *res;
-
- mono_error_init (error);
-
- CHECK_OBJECT (MonoReflectionProperty *, property, klass);
- res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
- if (!res)
- return NULL;
- res->klass = klass;
- res->property = property;
- CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
-}
-
-/*
- * mono_event_get_object:
- * @domain: an app domain
- * @klass: a type
- * @event: a event
- *
- * Return an System.Reflection.MonoEvent object representing the event @event
- * in class @klass.
- */
-MonoReflectionEvent*
-mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
-{
- MonoError error;
- MonoReflectionEvent *result;
- result = mono_event_get_object_checked (domain, klass, event, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_event_get_object_checked:
- * @domain: an app domain
- * @klass: a type
- * @event: a event
- * @error: set on error
- *
- * Return an System.Reflection.MonoEvent object representing the event @event
- * in class @klass. On failure sets @error and returns NULL
- */
-MonoReflectionEvent*
-mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
-{
- MonoReflectionEvent *res;
- MonoReflectionMonoEvent *mono_event;
-
- mono_error_init (error);
- CHECK_OBJECT (MonoReflectionEvent *, event, klass);
- mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
- if (!mono_event)
- return NULL;
- mono_event->klass = klass;
- mono_event->event = event;
- res = (MonoReflectionEvent*)mono_event;
- CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
-}
-
-/**
- * mono_get_reflection_missing_object:
- * @domain: Domain where the object lives
- *
- * Returns the System.Reflection.Missing.Value singleton object
- * (of type System.Reflection.Missing).
- *
- * Used as the value for ParameterInfo.DefaultValue when Optional
- * is present
- */
-static MonoObject *
-mono_get_reflection_missing_object (MonoDomain *domain)
-{
- MonoError error;
- MonoObject *obj;
- static MonoClassField *missing_value_field = NULL;
-
- if (!missing_value_field) {
- MonoClass *missing_klass;
- missing_klass = mono_class_get_missing_class ();
- mono_class_init (missing_klass);
- missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
- g_assert (missing_value_field);
- }
- obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
- mono_error_assert_ok (&error);
- return obj;
-}
-
-static MonoObject*
-get_dbnull (MonoDomain *domain, MonoObject **dbnull)
-{
- if (!*dbnull)
- *dbnull = mono_get_dbnull_object (domain);
- return *dbnull;
-}
-
-static MonoObject*
-get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
-{
- if (!*reflection_missing)
- *reflection_missing = mono_get_reflection_missing_object (domain);
- return *reflection_missing;
-}
-
-/*
- * mono_param_get_objects:
- * @domain: an app domain
- * @method: a method
- *
- * Return an System.Reflection.ParameterInfo array object representing the parameters
- * in the method @method.
- */
-MonoArray*
-mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
-{
- static MonoClass *System_Reflection_ParameterInfo;
- static MonoClass *System_Reflection_ParameterInfo_array;
- MonoArray *res = NULL;
- MonoReflectionMethod *member = NULL;
- MonoReflectionParameter *param = NULL;
- char **names = NULL, **blobs = NULL;
- guint32 *types = NULL;
- MonoType *type = NULL;
- MonoObject *dbnull = NULL;
- MonoObject *missing = NULL;
- MonoMarshalSpec **mspecs = NULL;
- MonoMethodSignature *sig = NULL;
- MonoVTable *pinfo_vtable;
- MonoReflectionType *rt;
- int i;
-
- mono_error_init (error);
-
- if (!System_Reflection_ParameterInfo_array) {
- MonoClass *klass;
-
- klass = mono_class_get_mono_parameter_info_class ();
-
- mono_memory_barrier ();
- System_Reflection_ParameterInfo = klass;
-
-
- klass = mono_array_class_get (klass, 1);
- mono_memory_barrier ();
- System_Reflection_ParameterInfo_array = klass;
- }
-
- sig = mono_method_signature_checked (method, error);
- if (!mono_error_ok (error))
- goto leave;
-
- if (!sig->param_count) {
- res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
- if (!res)
- goto leave;
-
- return res;
- }
-
- /* Note: the cache is based on the address of the signature into the method
- * since we already cache MethodInfos with the method as keys.
- */
- CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
-
- member = mono_method_get_object_checked (domain, method, refclass, error);
- if (!member)
- goto leave;
- names = g_new (char *, sig->param_count);
- mono_method_get_param_names (method, (const char **) names);
-
- mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
- mono_method_get_marshal_info (method, mspecs);
-
- res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
- if (!res)
- goto leave;
-
- pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
- for (i = 0; i < sig->param_count; ++i) {
- param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
- if (!param)
- goto leave;
-
- rt = mono_type_get_object_checked (domain, sig->params [i], error);
- if (!rt)
- goto leave;
-
- MONO_OBJECT_SETREF (param, ClassImpl, rt);
-
- MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
-
- MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
-
- param->PositionImpl = i;
- param->AttrsImpl = sig->params [i]->attrs;
-
- if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
- if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
- else
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
- } else {
-
- if (!blobs) {
- blobs = g_new0 (char *, sig->param_count);
- types = g_new0 (guint32, sig->param_count);
- get_default_param_value_blobs (method, blobs, types);
- }
-
- /* Build MonoType for the type from the Constant Table */
- if (!type)
- type = g_new0 (MonoType, 1);
- type->type = (MonoTypeEnum)types [i];
- type->data.klass = NULL;
- if (types [i] == MONO_TYPE_CLASS)
- type->data.klass = mono_defaults.object_class;
- else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
- /* For enums, types [i] contains the base type */
-
- type->type = MONO_TYPE_VALUETYPE;
- type->data.klass = mono_class_from_mono_type (sig->params [i]);
- } else
- type->data.klass = mono_class_from_mono_type (type);
-
- MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
- if (!is_ok (error))
- goto leave;
- MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
-
- /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
- if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
- if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
- else
- MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
- }
-
- }
-
- if (mspecs [i + 1]) {
- MonoReflectionMarshalAsAttribute* mobj;
- mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
- if (!mobj)
- goto leave;
- MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
- }
-
- mono_array_setref (res, i, param);
- }
-
-leave:
- g_free (names);
- g_free (blobs);
- g_free (types);
- g_free (type);
-
- if (sig) {
- for (i = sig->param_count; i >= 0; i--) {
- if (mspecs [i])
- mono_metadata_free_marshal_spec (mspecs [i]);
- }
- }
- g_free (mspecs);
-
- if (!is_ok (error))
- return NULL;
-
- CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
-}
-
-MonoArray*
-mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
-{
- MonoError error;
- MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
- mono_error_assert_ok (&error);
- return result;
-}
-
-/*
- * mono_method_body_get_object:
- * @domain: an app domain
- * @method: a method
- *
- * Return an System.Reflection.MethodBody object representing the method @method.
- */
-MonoReflectionMethodBody*
-mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
-{
- MonoError error;
- MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_method_body_get_object_checked:
- * @domain: an app domain
- * @method: a method
- * @error: set on error
- *
- * Return an System.Reflection.MethodBody object representing the
- * method @method. On failure, returns NULL and sets @error.
- */
-MonoReflectionMethodBody*
-mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
-{
- MonoReflectionMethodBody *ret;
- MonoMethodHeader *header;
- MonoImage *image;
- MonoReflectionType *rt;
- guint32 method_rva, local_var_sig_token;
- char *ptr;
- unsigned char format, flags;
- int i;
-
- mono_error_init (error);
-
- /* for compatibility with .net */
- if (method_is_dynamic (method)) {
- mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
- return NULL;
- }
-
- CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
-
- if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
- (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
- (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
- (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
- (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
- return NULL;
-
- image = method->klass->image;
- header = mono_method_get_header_checked (method, error);
- return_val_if_nok (error, NULL);
-
- if (!image_is_dynamic (image)) {
- /* Obtain local vars signature token */
- method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
- ptr = mono_image_rva_map (image, method_rva);
- flags = *(const unsigned char *) ptr;
- format = flags & METHOD_HEADER_FORMAT_MASK;
- switch (format){
- case METHOD_HEADER_TINY_FORMAT:
- local_var_sig_token = 0;
- break;
- case METHOD_HEADER_FAT_FORMAT:
- ptr += 2;
- ptr += 2;
- ptr += 4;
- local_var_sig_token = read32 (ptr);
- break;
- default:
- g_assert_not_reached ();
- }
- } else
- local_var_sig_token = 0; //FIXME
-
- ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
- if (!is_ok (error))
- goto fail;
-
- ret->init_locals = header->init_locals;
- ret->max_stack = header->max_stack;
- ret->local_var_sig_token = local_var_sig_token;
- MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
- if (!is_ok (error))
- goto fail;
- MONO_OBJECT_SETREF (ret, il, il_arr);
- memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
-
- /* Locals */
- MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
- if (!is_ok (error))
- goto fail;
- MONO_OBJECT_SETREF (ret, locals, locals_arr);
- for (i = 0; i < header->num_locals; ++i) {
- MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
- if (!is_ok (error))
- goto fail;
-
- rt = mono_type_get_object_checked (domain, header->locals [i], error);
- if (!is_ok (error))
- goto fail;
-
- MONO_OBJECT_SETREF (info, local_type, rt);
-
- info->is_pinned = header->locals [i]->pinned;
- info->local_index = i;
- mono_array_setref (ret->locals, i, info);
- }
-
- /* Exceptions */
- MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
- if (!is_ok (error))
- goto fail;
- MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
- for (i = 0; i < header->num_clauses; ++i) {
- MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
- if (!is_ok (error))
- goto fail;
- MonoExceptionClause *clause = &header->clauses [i];
-
- info->flags = clause->flags;
- info->try_offset = clause->try_offset;
- info->try_length = clause->try_len;
- info->handler_offset = clause->handler_offset;
- info->handler_length = clause->handler_len;
- if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
- info->filter_offset = clause->data.filter_offset;
- else if (clause->data.catch_class) {
- rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
- if (!is_ok (error))
- goto fail;
-
- MONO_OBJECT_SETREF (info, catch_type, rt);
- }
-
- mono_array_setref (ret->clauses, i, info);
- }
-
- mono_metadata_free_mh (header);
- CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
- return ret;
-
-fail:
- mono_metadata_free_mh (header);
- return NULL;
-}
-
-/**
- * mono_get_dbnull_object:
- * @domain: Domain where the object lives
- *
- * Returns the System.DBNull.Value singleton object
- *
- * Used as the value for ParameterInfo.DefaultValue
- */
-MonoObject *
-mono_get_dbnull_object (MonoDomain *domain)
-{
- MonoError error;
- MonoObject *obj;
- static MonoClassField *dbnull_value_field = NULL;
-
- if (!dbnull_value_field) {
- MonoClass *dbnull_klass;
- dbnull_klass = mono_class_get_dbnull_class ();
- dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
- g_assert (dbnull_value_field);
- }
- obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
- mono_error_assert_ok (&error);
- return obj;
-}
-
-static void
-get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
-{
- guint32 param_index, i, lastp, crow = 0;
- guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
- gint32 idx;
-
- MonoClass *klass = method->klass;
- MonoImage *image = klass->image;
- MonoMethodSignature *methodsig = mono_method_signature (method);
-
- MonoTableInfo *constt;
- MonoTableInfo *methodt;
- MonoTableInfo *paramt;
-
- if (!methodsig->param_count)
- return;
-
- mono_class_init (klass);
-
- if (image_is_dynamic (klass->image)) {
- MonoReflectionMethodAux *aux;
- if (method->is_inflated)
- method = ((MonoMethodInflated*)method)->declaring;
- aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
- if (aux && aux->param_defaults) {
- memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
- memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
- }
- return;
- }
-
- methodt = &klass->image->tables [MONO_TABLE_METHOD];
- paramt = &klass->image->tables [MONO_TABLE_PARAM];
- constt = &image->tables [MONO_TABLE_CONSTANT];
-
- idx = mono_method_get_index (method) - 1;
- g_assert (idx != -1);
-
- param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
- if (idx + 1 < methodt->rows)
- lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
- else
- lastp = paramt->rows + 1;
-
- for (i = param_index; i < lastp; ++i) {
- guint32 paramseq;
-
- mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
- paramseq = param_cols [MONO_PARAM_SEQUENCE];
-
- if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
- continue;
-
- crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
- if (!crow) {
- continue;
- }
-
- mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
- blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
- types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
- }
-
- return;
-}
-
-MonoObject *
-mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
-{
- void *retval;
- MonoClass *klass;
- MonoObject *object;
- MonoType *basetype = type;
-
- mono_error_init (error);
-
- if (!blob)
- return NULL;
-
- klass = mono_class_from_mono_type (type);
- if (klass->valuetype) {
- object = mono_object_new_checked (domain, klass, error);
- return_val_if_nok (error, NULL);
- retval = ((gchar *) object + sizeof (MonoObject));
- if (klass->enumtype)
- basetype = mono_class_enum_basetype (klass);
- } else {
- retval = &object;
- }
-
- if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
- return object;
- else
- return NULL;
-}
-
-static int
-assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
- int found_sep;
- char *s;
- gboolean quoted = FALSE;
-
- memset (assembly, 0, sizeof (MonoAssemblyName));
- assembly->culture = "";
- memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
-
- if (*p == '"') {
- quoted = TRUE;
- p++;
- }
- assembly->name = p;
- while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
- p++;
- if (quoted) {
- if (*p != '"')
- return 1;
- *p = 0;
- p++;
- }
- if (*p != ',')
- return 1;
- *p = 0;
- /* Remove trailing whitespace */
- s = p - 1;
- while (*s && g_ascii_isspace (*s))
- *s-- = 0;
- p ++;
- while (g_ascii_isspace (*p))
- p++;
- while (*p) {
- if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
- p += 8;
- assembly->major = strtoul (p, &s, 10);
- if (s == p || *s != '.')
- return 1;
- p = ++s;
- assembly->minor = strtoul (p, &s, 10);
- if (s == p || *s != '.')
- return 1;
- p = ++s;
- assembly->build = strtoul (p, &s, 10);
- if (s == p || *s != '.')
- return 1;
- p = ++s;
- assembly->revision = strtoul (p, &s, 10);
- if (s == p)
- return 1;
- p = s;
- } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
- p += 8;
- if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
- assembly->culture = "";
- p += 7;
- } else {
- assembly->culture = p;
- while (*p && *p != ',') {
- p++;
- }
- }
- } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
- p += 15;
- if (strncmp (p, "null", 4) == 0) {
- p += 4;
- } else {
- int len;
- gchar *start = p;
- while (*p && *p != ',') {
- p++;
- }
- len = (p - start + 1);
- if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
- len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
- g_strlcpy ((char*)assembly->public_key_token, start, len);
- }
- } else {
- while (*p && *p != ',')
- p++;
- }
- found_sep = 0;
- while (g_ascii_isspace (*p) || *p == ',') {
- *p++ = 0;
- found_sep = 1;
- continue;
- }
- /* failed */
- if (!found_sep)
- return 1;
- }
-
- return 0;
-}
-
-/*
- * mono_reflection_parse_type:
- * @name: type name
- *
- * Parse a type name as accepted by the GetType () method and output the info
- * extracted in the info structure.
- * the name param will be mangled, so, make a copy before passing it to this function.
- * The fields in info will be valid until the memory pointed to by name is valid.
- *
- * See also mono_type_get_name () below.
- *
- * Returns: 0 on parse error.
- */
-static int
-_mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
- MonoTypeNameParse *info)
-{
- char *start, *p, *w, *last_point, *startn;
- int in_modifiers = 0;
- int isbyref = 0, rank = 0, isptr = 0;
-
- start = p = w = name;
-
- //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
- memset (&info->assembly, 0, sizeof (MonoAssemblyName));
- info->name = info->name_space = NULL;
- info->nested = NULL;
- info->modifiers = NULL;
- info->type_arguments = NULL;
-
- /* last_point separates the namespace from the name */
- last_point = NULL;
- /* Skips spaces */
- while (*p == ' ') p++, start++, w++, name++;
-
- while (*p) {
- switch (*p) {
- case '+':
- *p = 0; /* NULL terminate the name */
- startn = p + 1;
- info->nested = g_list_append (info->nested, startn);
- /* we have parsed the nesting namespace + name */
- if (info->name)
- break;
- if (last_point) {
- info->name_space = start;
- *last_point = 0;
- info->name = last_point + 1;
- } else {
- info->name_space = (char *)"";
- info->name = start;
- }
- break;
- case '.':
- last_point = p;
- break;
- case '\\':
- ++p;
- break;
- case '&':
- case '*':
- case '[':
- case ',':
- case ']':
- in_modifiers = 1;
- break;
- default:
- break;
- }
- if (in_modifiers)
- break;
- // *w++ = *p++;
- p++;
- }
-
- if (!info->name) {
- if (last_point) {
- info->name_space = start;
- *last_point = 0;
- info->name = last_point + 1;
- } else {
- info->name_space = (char *)"";
- info->name = start;
- }
- }
- while (*p) {
- switch (*p) {
- case '&':
- if (isbyref) /* only one level allowed by the spec */
- return 0;
- isbyref = 1;
- isptr = 0;
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
- *p++ = 0;
- break;
- case '*':
- if (isbyref) /* pointer to ref not okay */
- return 0;
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
- isptr = 1;
- *p++ = 0;
- break;
- case '[':
- if (isbyref) /* array of ref and generic ref are not okay */
- return 0;
- //Decide if it's an array of a generic argument list
- *p++ = 0;
-
- if (!*p) //XXX test
- return 0;
- if (*p == ',' || *p == '*' || *p == ']') { //array
- isptr = 0;
- rank = 1;
- while (*p) {
- if (*p == ']')
- break;
- if (*p == ',')
- rank++;
- else if (*p == '*') /* '*' means unknown lower bound */
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
- else
- return 0;
- ++p;
- }
- if (*p++ != ']')
- return 0;
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
- } else {
- if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
- return 0;
- isptr = 0;
- info->type_arguments = g_ptr_array_new ();
- while (*p) {
- MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
- gboolean fqname = FALSE;
-
- g_ptr_array_add (info->type_arguments, subinfo);
-
- while (*p == ' ') p++;
- if (*p == '[') {
- p++;
- fqname = TRUE;
- }
-
- if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
- return 0;
-
- /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
- if (fqname && (*p != ']')) {
- char *aname;
-
- if (*p != ',')
- return 0;
- *p++ = 0;
-
- aname = p;
- while (*p && (*p != ']'))
- p++;
-
- if (*p != ']')
- return 0;
-
- *p++ = 0;
- while (*aname) {
- if (g_ascii_isspace (*aname)) {
- ++aname;
- continue;
- }
- break;
- }
- if (!*aname ||
- !assembly_name_to_aname (&subinfo->assembly, aname))
- return 0;
- } else if (fqname && (*p == ']')) {
- *p++ = 0;
- }
- if (*p == ']') {
- *p++ = 0;
- break;
- } else if (!*p) {
- return 0;
- }
- *p++ = 0;
- }
- }
- break;
- case ']':
- if (is_recursed)
- goto end;
- return 0;
- case ',':
- if (is_recursed)
- goto end;
- *p++ = 0;
- while (*p) {
- if (g_ascii_isspace (*p)) {
- ++p;
- continue;
- }
- break;
- }
- if (!*p)
- return 0; /* missing assembly name */
- if (!assembly_name_to_aname (&info->assembly, p))
- return 0;
- break;
- default:
- return 0;
- }
- if (info->assembly.name)
- break;
- }
- // *w = 0; /* terminate class name */
- end:
- if (!info->name || !*info->name)
- return 0;
- if (endptr)
- *endptr = p;
- /* add other consistency checks */
- return 1;
-}
-
-
-/**
- * mono_identifier_unescape_type_name_chars:
- * @identifier: the display name of a mono type
- *
- * Returns:
- * The name in internal form, that is without escaping backslashes.
- *
- * The string is modified in place!
- */
-char*
-mono_identifier_unescape_type_name_chars(char* identifier)
-{
- char *w, *r;
- if (!identifier)
- return NULL;
- for (w = r = identifier; *r != 0; r++)
- {
- char c = *r;
- if (c == '\\') {
- r++;
- if (*r == 0)
- break;
- c = *r;
- }
- *w = c;
- w++;
- }
- if (w != r)
- *w = 0;
- return identifier;
-}
-
-void
-mono_identifier_unescape_info (MonoTypeNameParse* info);
-
-static void
-unescape_each_type_argument(void* data, void* user_data)
-{
- MonoTypeNameParse* info = (MonoTypeNameParse*)data;
- mono_identifier_unescape_info (info);
-}
-
-static void
-unescape_each_nested_name (void* data, void* user_data)
-{
- char* nested_name = (char*) data;
- mono_identifier_unescape_type_name_chars(nested_name);
-}
-
-/**
- * mono_identifier_unescape_info:
- *
- * @info: a parsed display form of an (optionally assembly qualified) full type name.
- *
- * Returns: nothing.
- *
- * Destructively updates the info by unescaping the identifiers that
- * comprise the type namespace, name, nested types (if any) and
- * generic type arguments (if any).
- *
- * The resulting info has the names in internal form.
- *
- */
-void
-mono_identifier_unescape_info (MonoTypeNameParse *info)
-{
- if (!info)
- return;
- mono_identifier_unescape_type_name_chars(info->name_space);
- mono_identifier_unescape_type_name_chars(info->name);
- // but don't escape info->assembly
- if (info->type_arguments)
- g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
- if (info->nested)
- g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
-}
-
-int
-mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
-{
- int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
- if (ok) {
- mono_identifier_unescape_info (info);
- }
- return ok;
-}
-
-static MonoType*
-_mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
-{
- gboolean type_resolve = FALSE;
- MonoType *type;
- MonoImage *rootimage = image;
-
- mono_error_init (error);
-
- if (info->assembly.name) {
- MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
- if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
- /*
- * This could happen in the AOT compiler case when the search hook is not
- * installed.
- */
- assembly = image->assembly;
- if (!assembly) {
- /* then we must load the assembly ourselve - see #60439 */
- assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
- if (!assembly)
- return NULL;
- }
- image = assembly->image;
- } else if (!image) {
- image = mono_defaults.corlib;
- }
-
- type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
- if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
- /* ignore the error and try again */
- mono_error_cleanup (error);
- mono_error_init (error);
- image = mono_defaults.corlib;
- type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
- }
-
- return type;
-}
-
-/**
- * mono_reflection_get_type_internal:
- *
- * Returns: may return NULL on success, sets error on failure.
- */
-static MonoType*
-mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
-{
- MonoClass *klass;
- GList *mod;
- int modval;
- gboolean bounded = FALSE;
-
- mono_error_init (error);
- if (!image)
- image = mono_defaults.corlib;
-
- if (!rootimage)
- rootimage = mono_defaults.corlib;
-
- if (ignorecase)
- klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
- else
- klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
-
- if (!klass)
- return NULL;
-
- for (mod = info->nested; mod; mod = mod->next) {
- gpointer iter = NULL;
- MonoClass *parent;
-
- parent = klass;
- mono_class_init (parent);
-
- while ((klass = mono_class_get_nested_types (parent, &iter))) {
- char *lastp;
- char *nested_name, *nested_nspace;
- gboolean match = TRUE;
-
- lastp = strrchr ((const char *)mod->data, '.');
- if (lastp) {
- /* Nested classes can have namespaces */
- int nspace_len;
-
- nested_name = g_strdup (lastp + 1);
- nspace_len = lastp - (char*)mod->data;
- nested_nspace = (char *)g_malloc (nspace_len + 1);
- memcpy (nested_nspace, mod->data, nspace_len);
- nested_nspace [nspace_len] = '\0';
-
- } else {
- nested_name = (char *)mod->data;
- nested_nspace = NULL;
- }
-
- if (nested_nspace) {
- if (ignorecase) {
- if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
- match = FALSE;
- } else {
- if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
- match = FALSE;
- }
- }
- if (match) {
- if (ignorecase) {
- if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
- match = FALSE;
- } else {
- if (strcmp (klass->name, nested_name) != 0)
- match = FALSE;
- }
- }
- if (lastp) {
- g_free (nested_name);
- g_free (nested_nspace);
- }
- if (match)
- break;
- }
-
- if (!klass)
- break;
- }
- if (!klass)
- return NULL;
-
- if (info->type_arguments) {
- MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
- MonoReflectionType *the_type;
- MonoType *instance;
- int i;
-
- for (i = 0; i < info->type_arguments->len; i++) {
- MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
-
- type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
- if (!type_args [i]) {
- g_free (type_args);
- return NULL;
- }
- }
-
- the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
- if (!the_type)
- return NULL;
-
- instance = mono_reflection_bind_generic_parameters (
- the_type, info->type_arguments->len, type_args, error);
-
- g_free (type_args);
- if (!instance)
- return NULL;
-
- klass = mono_class_from_mono_type (instance);
- }
-
- for (mod = info->modifiers; mod; mod = mod->next) {
- modval = GPOINTER_TO_UINT (mod->data);
- if (!modval) { /* byref: must be last modifier */
- return &klass->this_arg;
- } else if (modval == -1) {
- klass = mono_ptr_class_get (&klass->byval_arg);
- } else if (modval == -2) {
- bounded = TRUE;
- } else { /* array rank */
- klass = mono_bounded_array_class_get (klass, modval, bounded);
- }
- }
-
- return &klass->byval_arg;
-}
-
-/*
- * mono_reflection_get_type:
- * @image: a metadata context
- * @info: type description structure
- * @ignorecase: flag for case-insensitive string compares
- * @type_resolve: whenever type resolve was already tried
- *
- * Build a MonoType from the type description in @info.
- *
- */
-
-MonoType*
-mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
- MonoError error;
- MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_type_checked:
- * @rootimage: the image of the currently active managed caller
- * @image: a metadata context
- * @info: type description structure
- * @ignorecase: flag for case-insensitive string compares
- * @type_resolve: whenever type resolve was already tried
- * @error: set on error.
- *
- * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
- *
- */
-MonoType*
-mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
- mono_error_init (error);
- return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
-}
-
-
-static MonoType*
-mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
-{
- MonoReflectionAssemblyBuilder *abuilder;
- MonoType *type;
- int i;
-
- mono_error_init (error);
- g_assert (assembly_is_dynamic (assembly));
- abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
- if (!abuilder)
- return NULL;
-
- /* Enumerate all modules */
-
- type = NULL;
- if (abuilder->modules) {
- for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
- MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
- type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
- if (type)
- break;
- if (!mono_error_ok (error))
- return NULL;
- }
- }
-
- if (!type && abuilder->loaded_modules) {
- for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
- MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
- type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
- if (type)
- break;
- if (!mono_error_ok (error))
- return NULL;
- }
- }
-
- return type;
-}
-
-MonoType*
-mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
-{
- MonoType *type;
- MonoReflectionAssembly *assembly;
- GString *fullName;
- GList *mod;
-
- mono_error_init (error);
-
- if (image && image_is_dynamic (image))
- type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
- else {
- type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
- }
- return_val_if_nok (error, NULL);
-
- if (type)
- return type;
- if (!mono_domain_has_type_resolve (mono_domain_get ()))
- return NULL;
-
- if (type_resolve) {
- if (*type_resolve)
- return NULL;
- else
- *type_resolve = TRUE;
- }
-
- /* Reconstruct the type name */
- fullName = g_string_new ("");
- if (info->name_space && (info->name_space [0] != '\0'))
- g_string_printf (fullName, "%s.%s", info->name_space, info->name);
- else
- g_string_printf (fullName, "%s", info->name);
- for (mod = info->nested; mod; mod = mod->next)
- g_string_append_printf (fullName, "+%s", (char*)mod->data);
-
- assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
- if (!is_ok (error)) {
- g_string_free (fullName, TRUE);
- return NULL;
- }
-
- if (assembly) {
- if (assembly_is_dynamic (assembly->assembly))
- type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
- info, ignorecase, error);
- else
- type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
- info, ignorecase, error);
- }
- g_string_free (fullName, TRUE);
- return_val_if_nok (error, NULL);
- return type;
-}
-
-void
-mono_reflection_free_type_info (MonoTypeNameParse *info)
-{
- g_list_free (info->modifiers);
- g_list_free (info->nested);
-
- if (info->type_arguments) {
- int i;
-
- for (i = 0; i < info->type_arguments->len; i++) {
- MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
-
- mono_reflection_free_type_info (subinfo);
- /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
- g_free (subinfo);
- }
-
- g_ptr_array_free (info->type_arguments, TRUE);
- }
-}
-
-/*
- * mono_reflection_type_from_name:
- * @name: type name.
- * @image: a metadata context (can be NULL).
- *
- * Retrieves a MonoType from its @name. If the name is not fully qualified,
- * it defaults to get the type from @image or, if @image is NULL or loading
- * from it fails, uses corlib.
- *
- */
-MonoType*
-mono_reflection_type_from_name (char *name, MonoImage *image)
-{
- MonoError error;
- MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_reflection_type_from_name_checked:
- * @name: type name.
- * @image: a metadata context (can be NULL).
- * @error: set on errror.
- *
- * Retrieves a MonoType from its @name. If the name is not fully qualified,
- * it defaults to get the type from @image or, if @image is NULL or loading
- * from it fails, uses corlib. On failure returns NULL and sets @error.
- *
- */
-MonoType*
-mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
-{
- MonoType *type = NULL;
- MonoTypeNameParse info;
- char *tmp;
-
- mono_error_init (error);
- /* Make a copy since parse_type modifies its argument */
- tmp = g_strdup (name);
-
- /*g_print ("requested type %s\n", str);*/
- if (mono_reflection_parse_type (tmp, &info)) {
- type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
- if (!is_ok (error)) {
- g_free (tmp);
- mono_reflection_free_type_info (&info);
- return NULL;
- }
- }
-
- g_free (tmp);
- mono_reflection_free_type_info (&info);
- return type;
-}
-
-/*
- * mono_reflection_get_token:
- *
- * Return the metadata token of OBJ which should be an object
- * representing a metadata element.
- */
-guint32
-mono_reflection_get_token (MonoObject *obj)
-{
- MonoError error;
- guint32 result = mono_reflection_get_token_checked (obj, &error);
- mono_error_assert_ok (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_token_checked:
- * @obj: the object
- * @error: set on error
- *
- * Return the metadata token of @obj which should be an object
- * representing a metadata element. On failure sets @error.
- */
-guint32
-mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
-{
- MonoClass *klass;
- guint32 token = 0;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
-
- if (strcmp (klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
-
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
- MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
-
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
- } else if (strcmp (klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
-
- token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
- } else if (strcmp (klass->name, "TypeBuilder") == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
- token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
- } else if (strcmp (klass->name, "RuntimeType") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, 0);
- MonoClass *mc = mono_class_from_mono_type (type);
- if (!mono_class_init (mc)) {
- mono_error_set_for_class_failure (error, mc);
- return 0;
- }
-
- token = mc->type_token;
- } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
- strcmp (klass->name, "MonoMethod") == 0 ||
- strcmp (klass->name, "MonoGenericMethod") == 0 ||
- strcmp (klass->name, "MonoGenericCMethod") == 0) {
- MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
- if (m->method->is_inflated) {
- MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
- return inflated->declaring->token;
- } else {
- token = m->method->token;
- }
- } else if (strcmp (klass->name, "MonoField") == 0) {
- MonoReflectionField *f = (MonoReflectionField*)obj;
-
- if (is_field_on_inst (f->field)) {
- MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
-
- if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
- int field_index = f->field - dgclass->fields;
- MonoObject *obj;
-
- g_assert (field_index >= 0 && field_index < dgclass->count_fields);
- obj = dgclass->field_objects [field_index];
- return mono_reflection_get_token_checked (obj, error);
- }
- }
- token = mono_class_get_field_token (f->field);
- } else if (strcmp (klass->name, "MonoProperty") == 0) {
- MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
-
- token = mono_class_get_property_token (p->property);
- } else if (strcmp (klass->name, "MonoEvent") == 0) {
- MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
-
- token = mono_class_get_event_token (p->event);
- } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
- MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
- MonoClass *member_class = mono_object_class (p->MemberImpl);
- g_assert (mono_class_is_reflection_method_or_constructor (member_class));
-
- token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
- } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
- MonoReflectionModule *m = (MonoReflectionModule*)obj;
-
- token = m->token;
- } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
- token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
- } else {
- mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
- klass->name_space, klass->name);
- return 0;
- }
-
- return token;
-}
-
-/*
- * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
- * The @is_enum flag only affects the error message that's displayed on failure.
- */
-static MonoType*
-cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
-{
- MonoError inner_error;
- MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
- if (!t) {
- mono_error_set_type_load_name (error, g_strdup(n), NULL,
- "Could not load %s %s while decoding custom attribute: %s",
- is_enum ? "enum type": "type",
- n,
- mono_error_get_message (&inner_error));
- mono_error_cleanup (&inner_error);
- return NULL;
- }
- return t;
-}
-
-static MonoClass*
-load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
-{
- char *n;
- MonoType *t;
- int slen = mono_metadata_decode_value (p, &p);
-
- mono_error_init (error);
-
- n = (char *)g_memdup (p, slen + 1);
- n [slen] = 0;
- t = cattr_type_from_name (n, image, TRUE, error);
- g_free (n);
- return_val_if_nok (error, NULL);
- p += slen;
- *end = p;
- return mono_class_from_mono_type (t);
-}
-
-static void*
-load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
-{
- int slen, type = t->type;
- MonoClass *tklass = t->data.klass;
-
- mono_error_init (error);
-
-handle_enum:
- switch (type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN: {
- MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
- *bval = *p;
- *end = p + 1;
- return bval;
- }
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2: {
- guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
- *val = read16 (p);
- *end = p + 2;
- return val;
- }
-#if SIZEOF_VOID_P == 4
- case MONO_TYPE_U:
- case MONO_TYPE_I:
-#endif
- case MONO_TYPE_R4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4: {
- guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
- *val = read32 (p);
- *end = p + 4;
- return val;
- }
-#if SIZEOF_VOID_P == 8
- case MONO_TYPE_U: /* error out instead? this should probably not happen */
- case MONO_TYPE_I:
-#endif
- case MONO_TYPE_U8:
- case MONO_TYPE_I8: {
- guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
- *val = read64 (p);
- *end = p + 8;
- return val;
- }
- case MONO_TYPE_R8: {
- double *val = (double *)g_malloc (sizeof (double));
- readr8 (p, val);
- *end = p + 8;
- return val;
- }
- case MONO_TYPE_VALUETYPE:
- if (t->data.klass->enumtype) {
- type = mono_class_enum_basetype (t->data.klass)->type;
- goto handle_enum;
- } else {
- MonoClass *k = t->data.klass;
-
- if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
- guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
- *val = read64 (p);
- *end = p + 8;
- return val;
- }
- }
- g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
- break;
-
- case MONO_TYPE_STRING:
- if (*p == (char)0xFF) {
- *end = p + 1;
- return NULL;
- }
- slen = mono_metadata_decode_value (p, &p);
- *end = p + slen;
- return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
- case MONO_TYPE_CLASS: {
- MonoReflectionType *rt;
- char *n;
- MonoType *t;
- if (*p == (char)0xFF) {
- *end = p + 1;
- return NULL;
- }
-handle_type:
- slen = mono_metadata_decode_value (p, &p);
- n = (char *)g_memdup (p, slen + 1);
- n [slen] = 0;
- t = cattr_type_from_name (n, image, FALSE, error);
- g_free (n);
- return_val_if_nok (error, NULL);
- *end = p + slen;
-
- rt = mono_type_get_object_checked (mono_domain_get (), t, error);
- if (!mono_error_ok (error))
- return NULL;
-
- return rt;
- }
- case MONO_TYPE_OBJECT: {
- char subt = *p++;
- MonoObject *obj;
- MonoClass *subc = NULL;
- void *val;
-
- if (subt == 0x50) {
- goto handle_type;
- } else if (subt == 0x0E) {
- type = MONO_TYPE_STRING;
- goto handle_enum;
- } else if (subt == 0x1D) {
- MonoType simple_type = {{0}};
- int etype = *p;
- p ++;
-
- type = MONO_TYPE_SZARRAY;
- if (etype == 0x50) {
- tklass = mono_defaults.systemtype_class;
- } else if (etype == 0x55) {
- tklass = load_cattr_enum_type (image, p, &p, error);
- if (!mono_error_ok (error))
- return NULL;
- } else {
- if (etype == 0x51)
- /* See Partition II, Appendix B3 */
- etype = MONO_TYPE_OBJECT;
- simple_type.type = (MonoTypeEnum)etype;
- tklass = mono_class_from_mono_type (&simple_type);
- }
- goto handle_enum;
- } else if (subt == 0x55) {
- char *n;
- MonoType *t;
- slen = mono_metadata_decode_value (p, &p);
- n = (char *)g_memdup (p, slen + 1);
- n [slen] = 0;
- t = cattr_type_from_name (n, image, FALSE, error);
- g_free (n);
- return_val_if_nok (error, NULL);
- p += slen;
- subc = mono_class_from_mono_type (t);
- } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
- MonoType simple_type = {{0}};
- simple_type.type = (MonoTypeEnum)subt;
- subc = mono_class_from_mono_type (&simple_type);
- } else {
- g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
- }
- val = load_cattr_value (image, &subc->byval_arg, p, end, error);
- obj = NULL;
- if (mono_error_ok (error)) {
- obj = mono_object_new_checked (mono_domain_get (), subc, error);
- g_assert (!subc->has_references);
- if (mono_error_ok (error))
- mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
- }
-
- g_free (val);
- return obj;
- }
- case MONO_TYPE_SZARRAY: {
- MonoArray *arr;
- guint32 i, alen, basetype;
- alen = read32 (p);
- p += 4;
- if (alen == 0xffffffff) {
- *end = p;
- return NULL;
- }
- arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
- return_val_if_nok (error, NULL);
- basetype = tklass->byval_arg.type;
- if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
- basetype = mono_class_enum_basetype (tklass)->type;
- switch (basetype)
- {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN:
- for (i = 0; i < alen; i++) {
- MonoBoolean val = *p++;
- mono_array_set (arr, MonoBoolean, i, val);
- }
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- for (i = 0; i < alen; i++) {
- guint16 val = read16 (p);
- mono_array_set (arr, guint16, i, val);
- p += 2;
- }
- break;
- case MONO_TYPE_R4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- for (i = 0; i < alen; i++) {
- guint32 val = read32 (p);
- mono_array_set (arr, guint32, i, val);
- p += 4;
- }
- break;
- case MONO_TYPE_R8:
- for (i = 0; i < alen; i++) {
- double val;
- readr8 (p, &val);
- mono_array_set (arr, double, i, val);
- p += 8;
- }
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- for (i = 0; i < alen; i++) {
- guint64 val = read64 (p);
- mono_array_set (arr, guint64, i, val);
- p += 8;
- }
- break;
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_SZARRAY:
- for (i = 0; i < alen; i++) {
- MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
- if (!mono_error_ok (error))
- return NULL;
- mono_array_setref (arr, i, item);
- }
- break;
- default:
- g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
- }
- *end=p;
- return arr;
- }
- default:
- g_error ("Type 0x%02x not handled in custom attr value decoding", type);
- }
- return NULL;
-}
-
-static MonoObject*
-load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
-{
- mono_error_init (error);
-
- gboolean is_ref = type_is_reference (t);
-
- void *val = load_cattr_value (image, t, p, end, error);
- if (!is_ok (error)) {
- if (is_ref)
- g_free (val);
- return NULL;
- }
-
- if (is_ref)
- return (MonoObject*)val;
-
- MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
- g_free (val);
- return boxed;
-}
-
-static MonoObject*
-create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
-{
- static MonoMethod *ctor;
- MonoObject *retval;
- void *params [2], *unboxed;
-
- mono_error_init (error);
-
- if (!ctor)
- ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
-
- params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
- return_val_if_nok (error, NULL);
-
- params [1] = val;
- retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
- return_val_if_nok (error, NULL);
- unboxed = mono_object_unbox (retval);
-
- mono_runtime_invoke_checked (ctor, unboxed, params, error);
- return_val_if_nok (error, NULL);
-
- return retval;
-}
-
-static MonoObject*
-create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
-{
- static MonoMethod *ctor;
- MonoObject *retval;
- void *unboxed, *params [2];
-
- mono_error_init (error);
-
- if (!ctor)
- ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
-
- params [0] = minfo;
- params [1] = typedarg;
- retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
- return_val_if_nok (error, NULL);
-
- unboxed = mono_object_unbox (retval);
-
- mono_runtime_invoke_checked (ctor, unboxed, params, error);
- return_val_if_nok (error, NULL);
-
- return retval;
-}
-
-static gboolean
-type_is_reference (MonoType *type)
-{
- switch (type->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8:
- case MONO_TYPE_R4:
- case MONO_TYPE_VALUETYPE:
- return FALSE;
- default:
- return TRUE;
- }
-}
-
-static void
-free_param_data (MonoMethodSignature *sig, void **params) {
- int i;
- for (i = 0; i < sig->param_count; ++i) {
- if (!type_is_reference (sig->params [i]))
- g_free (params [i]);
- }
-}
-
-/*
- * Find the field index in the metadata FieldDef table.
- */
-static guint32
-find_field_index (MonoClass *klass, MonoClassField *field) {
- int i;
-
- for (i = 0; i < klass->field.count; ++i) {
- if (field == &klass->fields [i])
- return klass->field.first + 1 + i;
- }
- return 0;
-}
-
-/*
- * Find the property index in the metadata Property table.
- */
-static guint32
-find_property_index (MonoClass *klass, MonoProperty *property) {
- int i;
-
- for (i = 0; i < klass->ext->property.count; ++i) {
- if (property == &klass->ext->properties [i])
- return klass->ext->property.first + 1 + i;
- }
- return 0;
-}
-
-/*
- * Find the event index in the metadata Event table.
- */
-static guint32
-find_event_index (MonoClass *klass, MonoEvent *event) {
- int i;
-
- for (i = 0; i < klass->ext->event.count; ++i) {
- if (event == &klass->ext->events [i])
- return klass->ext->event.first + 1 + i;
- }
- return 0;
-}
-
-static MonoObject*
-create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
-{
- const char *p = (const char*)data;
- const char *named;
- guint32 i, j, num_named;
- MonoObject *attr;
- void *params_buf [32];
- void **params = NULL;
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- mono_class_init (method->klass);
-
- if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
- return NULL;
- }
-
- if (len == 0) {
- attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
- if (!mono_error_ok (error)) return NULL;
-
- mono_runtime_invoke_checked (method, attr, NULL, error);
- if (!mono_error_ok (error))
- return NULL;
-
- return attr;
- }
-
- if (len < 2 || read16 (p) != 0x0001) /* Prolog */
- return NULL;
-
- /*g_print ("got attr %s\n", method->klass->name);*/
-
- sig = mono_method_signature (method);
- if (sig->param_count < 32) {
- params = params_buf;
- memset (params, 0, sizeof (void*) * sig->param_count);
- } else {
- /* Allocate using GC so it gets GC tracking */
- params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
- }
-
- /* skip prolog */
- p += 2;
- for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
- params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
- if (!mono_error_ok (error))
- goto fail;
- }
-
- named = p;
- attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
- if (!mono_error_ok (error)) goto fail;
-
- MonoObject *exc = NULL;
- mono_runtime_try_invoke (method, attr, params, &exc, error);
- if (!mono_error_ok (error))
- goto fail;
- if (exc) {
- mono_error_set_exception_instance (error, (MonoException*)exc);
- goto fail;
- }
-
- num_named = read16 (named);
- named += 2;
- for (j = 0; j < num_named; j++) {
- gint name_len;
- char *name, named_type, data_type;
- named_type = *named++;
- data_type = *named++; /* type of data */
- if (data_type == MONO_TYPE_SZARRAY)
- data_type = *named++;
- if (data_type == MONO_TYPE_ENUM) {
- gint type_len;
- char *type_name;
- type_len = mono_metadata_decode_blob_size (named, &named);
- type_name = (char *)g_malloc (type_len + 1);
- memcpy (type_name, named, type_len);
- type_name [type_len] = 0;
- named += type_len;
- /* FIXME: lookup the type and check type consistency */
- g_free (type_name);
- }
- name_len = mono_metadata_decode_blob_size (named, &named);
- name = (char *)g_malloc (name_len + 1);
- memcpy (name, named, name_len);
- name [name_len] = 0;
- named += name_len;
- if (named_type == 0x53) {
- MonoClassField *field;
- void *val;
-
- /* how this fail is a blackbox */
- field = mono_class_get_field_from_name (mono_object_class (attr), name);
- if (!field) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
- g_free (name);
- goto fail;
- }
-
- val = load_cattr_value (image, field->type, named, &named, error);
- if (!mono_error_ok (error)) {
- g_free (name);
- if (!type_is_reference (field->type))
- g_free (val);
- goto fail;
- }
-
- mono_field_set_value (attr, field, val);
- if (!type_is_reference (field->type))
- g_free (val);
- } else if (named_type == 0x54) {
- MonoProperty *prop;
- void *pparams [1];
- MonoType *prop_type;
-
- prop = mono_class_get_property_from_name (mono_object_class (attr), name);
-
- if (!prop) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
- g_free (name);
- goto fail;
- }
-
- if (!prop->set) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
- g_free (name);
- goto fail;
- }
-
- /* can we have more that 1 arg in a custom attr named property? */
- prop_type = prop->get? mono_method_signature (prop->get)->ret :
- mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
-
- pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
- if (!mono_error_ok (error)) {
- g_free (name);
- if (!type_is_reference (prop_type))
- g_free (pparams [0]);
- goto fail;
- }
-
-
- mono_property_set_value_checked (prop, attr, pparams, error);
- if (!type_is_reference (prop_type))
- g_free (pparams [0]);
- if (!is_ok (error)) {
- g_free (name);
- goto fail;
- }
- }
- g_free (name);
- }
-
- free_param_data (method->signature, params);
- if (params != params_buf)
- mono_gc_free_fixed (params);
-
- return attr;
-
-fail:
- free_param_data (method->signature, params);
- if (params != params_buf)
- mono_gc_free_fixed (params);
- return NULL;
-}
-
-/*
- * mono_reflection_create_custom_attr_data_args:
- *
- * Create an array of typed and named arguments from the cattr blob given by DATA.
- * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
- * NAMED_ARG_INFO will contain information about the named arguments.
- */
-void
-mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
-{
- MonoArray *typedargs, *namedargs;
- MonoClass *attrklass;
- MonoDomain *domain;
- const char *p = (const char*)data;
- const char *named;
- guint32 i, j, num_named;
- CattrNamedArg *arginfo = NULL;
-
- *typed_args = NULL;
- *named_args = NULL;
- *named_arg_info = NULL;
-
- mono_error_init (error);
-
- if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
- return;
- }
-
- mono_class_init (method->klass);
-
- domain = mono_domain_get ();
-
- if (len < 2 || read16 (p) != 0x0001) /* Prolog */
- return;
-
- typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
- return_if_nok (error);
-
- /* skip prolog */
- p += 2;
- for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
- MonoObject *obj;
-
- obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
- return_if_nok (error);
- mono_array_setref (typedargs, i, obj);
- }
-
- named = p;
- num_named = read16 (named);
- namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
- return_if_nok (error);
- named += 2;
- attrklass = method->klass;
-
- arginfo = g_new0 (CattrNamedArg, num_named);
- *named_arg_info = arginfo;
-
- for (j = 0; j < num_named; j++) {
- gint name_len;
- char *name, named_type, data_type;
- named_type = *named++;
- data_type = *named++; /* type of data */
- if (data_type == MONO_TYPE_SZARRAY)
- data_type = *named++;
- if (data_type == MONO_TYPE_ENUM) {
- gint type_len;
- char *type_name;
- type_len = mono_metadata_decode_blob_size (named, &named);
- if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
- goto fail;
-
- type_name = (char *)g_malloc (type_len + 1);
- memcpy (type_name, named, type_len);
- type_name [type_len] = 0;
- named += type_len;
- /* FIXME: lookup the type and check type consistency */
- g_free (type_name);
- }
- name_len = mono_metadata_decode_blob_size (named, &named);
- if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
- goto fail;
- name = (char *)g_malloc (name_len + 1);
- memcpy (name, named, name_len);
- name [name_len] = 0;
- named += name_len;
- if (named_type == 0x53) {
- MonoObject *obj;
- MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
-
- if (!field) {
- g_free (name);
- goto fail;
- }
-
- arginfo [j].type = field->type;
- arginfo [j].field = field;
-
- obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
- if (!is_ok (error)) {
- g_free (name);
- return;
- }
- mono_array_setref (namedargs, j, obj);
-
- } else if (named_type == 0x54) {
- MonoObject *obj;
- MonoType *prop_type;
- MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
-
- if (!prop || !prop->set) {
- g_free (name);
- goto fail;
- }
-
- prop_type = prop->get? mono_method_signature (prop->get)->ret :
- mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
-
- arginfo [j].type = prop_type;
- arginfo [j].prop = prop;
-
- obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
- if (!is_ok (error)) {
- g_free (name);
- return;
- }
- mono_array_setref (namedargs, j, obj);
- }
- g_free (name);
- }
-
- *typed_args = typedargs;
- *named_args = namedargs;
- return;
-fail:
- mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
- g_free (arginfo);
- *named_arg_info = NULL;
-}
-
-static gboolean
-reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
-{
- MonoDomain *domain;
- MonoArray *typedargs, *namedargs;
- MonoImage *image;
- MonoMethod *method;
- CattrNamedArg *arginfo = NULL;
- int i;
-
- mono_error_init (error);
-
- *ctor_args = NULL;
- *named_args = NULL;
-
- if (len == 0)
- return TRUE;
-
- image = assembly->assembly->image;
- method = ref_method->method;
- domain = mono_object_domain (ref_method);
-
- if (!mono_class_init (method->klass)) {
- mono_error_set_for_class_failure (error, method->klass);
- goto leave;
- }
-
- mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
- if (!is_ok (error))
- goto leave;
-
- if (!typedargs || !namedargs)
- goto leave;
-
- for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
- MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
- MonoObject *typedarg;
-
- typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
- if (!is_ok (error))
- goto leave;
- mono_array_setref (typedargs, i, typedarg);
- }
-
- for (i = 0; i < mono_array_length (namedargs); ++i) {
- MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
- MonoObject *typedarg, *namedarg, *minfo;
-
- if (arginfo [i].prop) {
- minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
- if (!minfo)
- goto leave;
- } else {
- minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
- if (!is_ok (error))
- goto leave;
- }
-
- typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
- if (!is_ok (error))
- goto leave;
- namedarg = create_cattr_named_arg (minfo, typedarg, error);
- if (!is_ok (error))
- goto leave;
-
- mono_array_setref (namedargs, i, namedarg);
- }
-
- *ctor_args = typedargs;
- *named_args = namedargs;
-
-leave:
- g_free (arginfo);
- return mono_error_ok (error);
-}
-
-void
-ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
-{
- MonoError error;
- (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
- mono_error_set_pending_exception (&error);
-}
-
-static MonoObject*
-create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
-{
- static MonoMethod *ctor;
-
- MonoDomain *domain;
- MonoObject *attr;
- void *params [4];
-
- mono_error_init (error);
-
- g_assert (image->assembly);
-
- if (!ctor)
- ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
-
- domain = mono_domain_get ();
- attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
- return_val_if_nok (error, NULL);
- params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
- return_val_if_nok (error, NULL);
- params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
- return_val_if_nok (error, NULL);
- params [2] = (gpointer)&cattr->data;
- params [3] = &cattr->data_size;
-
- mono_runtime_invoke_checked (ctor, attr, params, error);
- return_val_if_nok (error, NULL);
- return attr;
-}
-
-static MonoArray*
-mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
-{
- MonoArray *result;
- MonoObject *attr;
- int i, n;
-
- mono_error_init (error);
-
- n = 0;
- for (i = 0; i < cinfo->num_attrs; ++i) {
- if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
- n ++;
- }
-
- result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
- return_val_if_nok (error, NULL);
- n = 0;
- for (i = 0; i < cinfo->num_attrs; ++i) {
- if (!cinfo->attrs [i].ctor) {
- /* The cattr type is not finished yet */
- /* We should include the type name but cinfo doesn't contain it */
- mono_error_set_type_load_name (error, NULL, NULL, "");
- return NULL;
- }
- if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
- attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
- if (!mono_error_ok (error))
- return result;
- mono_array_setref (result, n, attr);
- n ++;
- }
- }
- return result;
-}
-
-MonoArray*
-mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
-{
- MonoError error;
- MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
- mono_error_assert_ok (&error); /*FIXME proper error handling*/
-
- return result;
-}
-
-static MonoArray*
-mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
-{
- MonoArray *result;
- MonoObject *attr;
- int i;
-
- mono_error_init (error);
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
- return_val_if_nok (error, NULL);
- for (i = 0; i < cinfo->num_attrs; ++i) {
- attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
- return_val_if_nok (error, NULL);
- mono_array_setref (result, i, attr);
- }
- return result;
-}
-
-/**
- * mono_custom_attrs_from_index:
- *
- * Returns: NULL if no attributes are found or if a loading error occurs.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
- mono_error_cleanup (&error);
- return result;
-}
-/**
- * mono_custom_attrs_from_index_checked:
- *
- * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
-{
- guint32 mtoken, i, len;
- guint32 cols [MONO_CUSTOM_ATTR_SIZE];
- MonoTableInfo *ca;
- MonoCustomAttrInfo *ainfo;
- GList *tmp, *list = NULL;
- const char *data;
- MonoCustomAttrEntry* attr;
-
- mono_error_init (error);
-
- ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
-
- i = mono_metadata_custom_attrs_from_index (image, idx);
- if (!i)
- return NULL;
- i --;
- while (i < ca->rows) {
- if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
- break;
- list = g_list_prepend (list, GUINT_TO_POINTER (i));
- ++i;
- }
- len = g_list_length (list);
- if (!len)
- return NULL;
- ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
- ainfo->num_attrs = len;
- ainfo->image = image;
- for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
- mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
- mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
- switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
- case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
- mtoken |= MONO_TOKEN_METHOD_DEF;
- break;
- case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
- mtoken |= MONO_TOKEN_MEMBER_REF;
- break;
- default:
- g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
- break;
- }
- attr = &ainfo->attrs [i - 1];
- attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
- if (!attr->ctor) {
- g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
- g_list_free (list);
- g_free (ainfo);
- return NULL;
- }
-
- if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
- /*FIXME raising an exception here doesn't make any sense*/
- g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
- g_list_free (list);
- g_free (ainfo);
- return NULL;
- }
- data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
- attr->data_size = mono_metadata_decode_value (data, &data);
- attr->data = (guchar*)data;
- }
- g_list_free (list);
-
- return ainfo;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_method (MonoMethod *method)
-{
- MonoError error;
- MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
- mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
-{
- guint32 idx;
-
- mono_error_init (error);
-
- /*
- * An instantiated method has the same cattrs as the generic method definition.
- *
- * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
- * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
- */
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
- return lookup_custom_attr (method->klass->image, method);
-
- if (!method->token)
- /* Synthetic methods */
- return NULL;
-
- idx = mono_method_get_index (method);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_METHODDEF;
- return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_class (MonoClass *klass)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
-{
- guint32 idx;
-
- mono_error_init (error);
-
- if (klass->generic_class)
- klass = klass->generic_class->container_class;
-
- if (image_is_dynamic (klass->image))
- return lookup_custom_attr (klass->image, klass);
-
- if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
- idx = mono_metadata_token_index (klass->sizes.generic_param_token);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_GENERICPAR;
- } else {
- idx = mono_metadata_token_index (klass->type_token);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_TYPEDEF;
- }
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_assembly (MonoAssembly *assembly)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
-{
- guint32 idx;
-
- mono_error_init (error);
-
- if (image_is_dynamic (assembly->image))
- return lookup_custom_attr (assembly->image, assembly);
- idx = 1; /* there is only one assembly */
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
- return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
-}
-
-static MonoCustomAttrInfo*
-mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
-{
- guint32 idx;
-
- if (image_is_dynamic (image))
- return lookup_custom_attr (image, image);
- idx = 1; /* there is only one module */
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_MODULE;
- return mono_custom_attrs_from_index_checked (image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
-{
- MonoError error;
- MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
-{
- guint32 idx;
-
- if (image_is_dynamic (klass->image)) {
- property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
- return lookup_custom_attr (klass->image, property);
- }
- idx = find_property_index (klass, property);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_PROPERTY;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
-{
- MonoError error;
- MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
-{
- guint32 idx;
-
- if (image_is_dynamic (klass->image)) {
- event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
- return lookup_custom_attr (klass->image, event);
- }
- idx = find_event_index (klass, event);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_EVENT;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
-{
- MonoError error;
- MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-MonoCustomAttrInfo*
-mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
-{
- guint32 idx;
- mono_error_init (error);
-
- if (image_is_dynamic (klass->image)) {
- field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
- return lookup_custom_attr (klass->image, field);
- }
- idx = find_field_index (klass, field);
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_FIELDDEF;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
-}
-
-/**
- * mono_custom_attrs_from_param:
- * @method: handle to the method that we want to retrieve custom parameter information from
- * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
- *
- * The result must be released with mono_custom_attrs_free().
- *
- * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_custom_attrs_from_param_checked:
- * @method: handle to the method that we want to retrieve custom parameter information from
- * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
- * @error: set on error
- *
- * The result must be released with mono_custom_attrs_free().
- *
- * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
- */
-MonoCustomAttrInfo*
-mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
-{
- MonoTableInfo *ca;
- guint32 i, idx, method_index;
- guint32 param_list, param_last, param_pos, found;
- MonoImage *image;
- MonoReflectionMethodAux *aux;
-
- mono_error_init (error);
-
- /*
- * An instantiated method has the same cattrs as the generic method definition.
- *
- * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
- * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
- */
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- if (image_is_dynamic (method->klass->image)) {
- MonoCustomAttrInfo *res, *ainfo;
- int size;
-
- aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
- if (!aux || !aux->param_cattr)
- return NULL;
-
- /* Need to copy since it will be freed later */
- ainfo = aux->param_cattr [param];
- if (!ainfo)
- return NULL;
- size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
- res = (MonoCustomAttrInfo *)g_malloc0 (size);
- memcpy (res, ainfo, size);
- return res;
- }
-
- image = method->klass->image;
- method_index = mono_method_get_index (method);
- if (!method_index)
- return NULL;
- ca = &image->tables [MONO_TABLE_METHOD];
-
- param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
- if (method_index == ca->rows) {
- ca = &image->tables [MONO_TABLE_PARAM];
- param_last = ca->rows + 1;
- } else {
- param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
- ca = &image->tables [MONO_TABLE_PARAM];
- }
- found = FALSE;
- for (i = param_list; i < param_last; ++i) {
- param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
- if (param_pos == param) {
- found = TRUE;
- break;
- }
- }
- if (!found)
- return NULL;
- idx = i;
- idx <<= MONO_CUSTOM_ATTR_BITS;
- idx |= MONO_CUSTOM_ATTR_PARAMDEF;
- return mono_custom_attrs_from_index_checked (image, idx, error);
-}
-
-gboolean
-mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
-{
- int i;
- MonoClass *klass;
- for (i = 0; i < ainfo->num_attrs; ++i) {
- klass = ainfo->attrs [i].ctor->klass;
- if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
- return TRUE;
- }
- return FALSE;
-}
-
-MonoObject*
-mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
-{
- MonoError error;
- MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
- mono_error_assert_ok (&error); /*FIXME proper error handling*/
- return res;
-}
-
-MonoObject*
-mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
-{
- int i, attr_index;
- MonoClass *klass;
- MonoArray *attrs;
-
- mono_error_init (error);
-
- attr_index = -1;
- for (i = 0; i < ainfo->num_attrs; ++i) {
- klass = ainfo->attrs [i].ctor->klass;
- if (mono_class_has_parent (klass, attr_klass)) {
- attr_index = i;
- break;
- }
- }
- if (attr_index == -1)
- return NULL;
-
- attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
- if (!mono_error_ok (error))
- return NULL;
- return mono_array_get (attrs, MonoObject*, attr_index);
-}
-
-/*
- * mono_reflection_get_custom_attrs_info:
- * @obj: a reflection object handle
- *
- * Return the custom attribute info for attributes defined for the
- * reflection handle @obj. The objects.
- *
- * FIXME this function leaks like a sieve for SRE objects.
- */
-MonoCustomAttrInfo*
-mono_reflection_get_custom_attrs_info (MonoObject *obj)
-{
- MonoError error;
- MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
- mono_error_assert_ok (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_custom_attrs_info_checked:
- * @obj: a reflection object handle
- * @error: set on error
- *
- * Return the custom attribute info for attributes defined for the
- * reflection handle @obj. The objects.
- *
- * On failure returns NULL and sets @error.
- *
- * FIXME this function leaks like a sieve for SRE objects.
- */
-MonoCustomAttrInfo*
-mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
-{
- MonoClass *klass;
- MonoCustomAttrInfo *cinfo = NULL;
-
- mono_error_init (error);
-
- klass = obj->vtable->klass;
- if (klass == mono_defaults.runtimetype_class) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
- return_val_if_nok (error, NULL);
- klass = mono_class_from_mono_type (type);
- /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
- cinfo = mono_custom_attrs_from_class_checked (klass, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
- MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
- cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
- MonoReflectionModule *module = (MonoReflectionModule*)obj;
- cinfo = mono_custom_attrs_from_module (module->image, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("MonoProperty", klass->name) == 0) {
- MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
- cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("MonoEvent", klass->name) == 0) {
- MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
- cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("MonoField", klass->name) == 0) {
- MonoReflectionField *rfield = (MonoReflectionField*)obj;
- cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
- return_val_if_nok (error, NULL);
- } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
- MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
- cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
- return_val_if_nok (error, NULL);
- } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
- MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
- cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
- return_val_if_nok (error, NULL);
- } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
- MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
- MonoClass *member_class = mono_object_class (param->MemberImpl);
- if (mono_class_is_reflection_method_or_constructor (member_class)) {
- MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
- cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- } else if (is_sr_mono_property (member_class)) {
- MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
- MonoMethod *method;
- if (!(method = prop->property->get))
- method = prop->property->set;
- g_assert (method);
-
- cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- }
-#ifndef DISABLE_REFLECTION_EMIT
- else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
- MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
- return_val_if_nok (error, NULL);
- cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
- MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
- MonoMethod *method = NULL;
- if (is_sre_ctor_builder (mono_object_class (c->cb)))
- method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
- else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
- method = ((MonoReflectionMethod *)c->cb)->method;
- else
- g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
-
- cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
- return_val_if_nok (error, NULL);
- }
-#endif
- else {
- char *type_name = mono_type_get_full_name (member_class);
- mono_error_set_not_supported (error,
- "Custom attributes on a ParamInfo with member %s are not supported",
- type_name);
- g_free (type_name);
- return NULL;
- }
- } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
- MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
- } else if (strcmp ("TypeBuilder", klass->name) == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
- } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
- MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
- } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
- MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
- } else if (strcmp ("MethodBuilder", klass->name) == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
- } else if (strcmp ("FieldBuilder", klass->name) == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
- cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
- } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
- MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
- cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
- return_val_if_nok (error, NULL);
- } else { /* handle other types here... */
- g_error ("get custom attrs not yet supported for %s", klass->name);
- }
-
- return cinfo;
-}
-
-/*
- * mono_reflection_get_custom_attrs_by_type:
- * @obj: a reflection object handle
- *
- * Return an array with all the custom attributes defined of the
- * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
- * of that type are returned. The objects are fully build. Return NULL if a loading error
- * occurs.
- */
-MonoArray*
-mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
-{
- MonoArray *result;
- MonoCustomAttrInfo *cinfo;
-
- mono_error_init (error);
-
- cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
- return_val_if_nok (error, NULL);
- if (cinfo) {
- result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
- if (!cinfo->cached)
- mono_custom_attrs_free (cinfo);
- if (!result)
- return NULL;
- } else {
- result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
- }
-
- return result;
-}
-
-/*
- * mono_reflection_get_custom_attrs:
- * @obj: a reflection object handle
- *
- * Return an array with all the custom attributes defined of the
- * reflection handle @obj. The objects are fully build. Return NULL if a loading error
- * occurs.
- */
-MonoArray*
-mono_reflection_get_custom_attrs (MonoObject *obj)
-{
- MonoError error;
-
- return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
-}
-
-/*
- * mono_reflection_get_custom_attrs_data:
- * @obj: a reflection obj handle
- *
- * Returns an array of System.Reflection.CustomAttributeData,
- * which include information about attributes reflected on
- * types loaded using the Reflection Only methods
- */
-MonoArray*
-mono_reflection_get_custom_attrs_data (MonoObject *obj)
-{
- MonoError error;
- MonoArray* result;
- result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/*
- * mono_reflection_get_custom_attrs_data_checked:
- * @obj: a reflection obj handle
- * @error: set on error
- *
- * Returns an array of System.Reflection.CustomAttributeData,
- * which include information about attributes reflected on
- * types loaded using the Reflection Only methods
- */
-MonoArray*
-mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
-{
- MonoArray *result;
- MonoCustomAttrInfo *cinfo;
-
- mono_error_init (error);
-
- cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
- return_val_if_nok (error, NULL);
- if (cinfo) {
- result = mono_custom_attrs_data_construct (cinfo, error);
- if (!cinfo->cached)
- mono_custom_attrs_free (cinfo);
- return_val_if_nok (error, NULL);
- } else
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
-
- return result;
-}
-
-static MonoReflectionType*
-mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
-{
- static MonoMethod *method_get_underlying_system_type = NULL;
- MonoReflectionType *rt;
- MonoMethod *usertype_method;
-
- mono_error_init (error);
-
- if (!method_get_underlying_system_type)
- method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
-
- usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
-
- rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
-
- return rt;
-}
-
-
-static gboolean
-is_corlib_type (MonoClass *klass)
-{
- return klass->image == mono_defaults.corlib;
-}
-
-#define check_corlib_type_cached(_class, _namespace, _name) do { \
- static MonoClass *cached_class; \
- if (cached_class) \
- return cached_class == _class; \
- if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
- cached_class = _class; \
- return TRUE; \
- } \
- return FALSE; \
-} while (0) \
-
-
-#ifndef DISABLE_REFLECTION_EMIT
-static gboolean
-is_sre_array (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
-}
-
-static gboolean
-is_sre_byref (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
-}
-
-static gboolean
-is_sre_pointer (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
-}
-
-static gboolean
-is_sre_generic_instance (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
-}
-
-static gboolean
-is_sre_type_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
-}
-
-static gboolean
-is_sre_method_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
-}
-
-static gboolean
-is_sre_ctor_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
-}
-
-static gboolean
-is_sre_field_builder (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
-}
-
-static gboolean
-is_sre_method_on_tb_inst (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
-}
-
-static gboolean
-is_sre_ctor_on_tb_inst (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
-}
-
-MonoType*
-mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
-{
- MonoClass *klass;
- mono_error_init (error);
-
- if (!ref)
- return NULL;
- if (ref->type)
- return ref->type;
-
- if (is_usertype (ref)) {
- ref = mono_reflection_type_get_underlying_system_type (ref, error);
- if (ref == NULL || is_usertype (ref) || !is_ok (error))
- return NULL;
- if (ref->type)
- return ref->type;
- }
-
- klass = mono_object_class (ref);
-
- if (is_sre_array (klass)) {
- MonoType *res;
- MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
- MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
- return_val_if_nok (error, NULL);
- g_assert (base);
- if (sre_array->rank == 0) //single dimentional array
- res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
- else
- res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
- sre_array->type.type = res;
- return res;
- } else if (is_sre_byref (klass)) {
- MonoType *res;
- MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
- MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
- return_val_if_nok (error, NULL);
- g_assert (base);
- res = &mono_class_from_mono_type (base)->this_arg;
- sre_byref->type.type = res;
- return res;
- } else if (is_sre_pointer (klass)) {
- MonoType *res;
- MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
- MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
- return_val_if_nok (error, NULL);
- g_assert (base);
- res = &mono_ptr_class_get (base)->byval_arg;
- sre_pointer->type.type = res;
- return res;
- } else if (is_sre_generic_instance (klass)) {
- MonoType *res, **types;
- MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
- int i, count;
-
- count = mono_array_length (gclass->type_arguments);
- types = g_new0 (MonoType*, count);
- for (i = 0; i < count; ++i) {
- MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
- types [i] = mono_reflection_type_get_handle (t, error);
- if (!types[i] || !is_ok (error)) {
- g_free (types);
- return NULL;
- }
- }
-
- res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
- g_free (types);
- g_assert (res);
- gclass->type.type = res;
- return res;
- }
-
- g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
- return NULL;
-}
-
-void
-mono_reflection_create_unmanaged_type (MonoReflectionType *type)
-{
- MonoError error;
- mono_reflection_type_get_handle (type, &error);
- mono_error_set_pending_exception (&error);
-}
-
-static gboolean
-reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
-{
- MonoDomain *domain = mono_object_domain ((MonoObject*)type);
- MonoClass *klass;
-
- mono_error_init (error);
-
- MonoType *res = mono_reflection_type_get_handle (type, error);
-
- if (!res && is_ok (error)) {
- mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
- }
- return_val_if_nok (error, FALSE);
-
- klass = mono_class_from_mono_type (res);
-
- mono_loader_lock (); /*same locking as mono_type_get_object_checked */
- mono_domain_lock (domain);
-
- if (!image_is_dynamic (klass->image)) {
- mono_class_setup_supertypes (klass);
- } else {
- if (!domain->type_hash)
- domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
- (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
- mono_g_hash_table_insert (domain->type_hash, res, type);
- }
- mono_domain_unlock (domain);
- mono_loader_unlock ();
-
- return TRUE;
-}
-
-void
-mono_reflection_register_with_runtime (MonoReflectionType *type)
-{
- MonoError error;
- (void) reflection_register_with_runtime (type, &error);
- mono_error_set_pending_exception (&error);
-}
-
-/**
- * LOCKING: Assumes the loader lock is held.
- */
-static MonoMethodSignature*
-parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
- MonoMethodSignature *sig;
- int count, i;
-
- mono_error_init (error);
-
- count = parameters? mono_array_length (parameters): 0;
-
- sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
- sig->param_count = count;
- sig->sentinelpos = -1; /* FIXME */
- for (i = 0; i < count; ++i) {
- sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
- if (!is_ok (error)) {
- image_g_free (image, sig);
- return NULL;
- }
- }
- return sig;
-}
-
-/**
- * LOCKING: Assumes the loader lock is held.
- */
-static MonoMethodSignature*
-ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- sig = parameters_to_signature (image, ctor->parameters, error);
- return_val_if_nok (error, NULL);
- sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
- sig->ret = &mono_defaults.void_class->byval_arg;
- return sig;
-}
-
-/**
- * LOCKING: Assumes the loader lock is held.
- */
-static MonoMethodSignature*
-method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- sig = parameters_to_signature (image, method->parameters, error);
- return_val_if_nok (error, NULL);
- sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
- if (method->rtype) {
- sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
- if (!is_ok (error)) {
- image_g_free (image, sig);
- return NULL;
- }
- } else {
- sig->ret = &mono_defaults.void_class->byval_arg;
- }
- sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
- return sig;
-}
-
-static MonoMethodSignature*
-dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- sig = parameters_to_signature (NULL, method->parameters, error);
- return_val_if_nok (error, NULL);
- sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
- if (method->rtype) {
- sig->ret = mono_reflection_type_get_handle (method->rtype, error);
- if (!is_ok (error)) {
- g_free (sig);
- return NULL;
- }
- } else {
- sig->ret = &mono_defaults.void_class->byval_arg;
- }
- sig->generic_param_count = 0;
- return sig;
-}
-
-static void
-get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
-{
- mono_error_init (error);
- MonoClass *klass = mono_object_class (prop);
- if (strcmp (klass->name, "PropertyBuilder") == 0) {
- MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
- *name = mono_string_to_utf8_checked (pb->name, error);
- return_if_nok (error);
- *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
- } else {
- MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
- *name = g_strdup (p->property->name);
- if (p->property->get)
- *type = mono_method_signature (p->property->get)->ret;
- else
- *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
- }
-}
-
-static void
-get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
-{
- mono_error_init (error);
- MonoClass *klass = mono_object_class (field);
- if (strcmp (klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
- *name = mono_string_to_utf8_checked (fb->name, error);
- return_if_nok (error);
- *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- } else {
- MonoReflectionField *f = (MonoReflectionField *)field;
- *name = g_strdup (mono_field_get_name (f->field));
- *type = f->field->type;
- }
-}
-
-#else /* DISABLE_REFLECTION_EMIT */
-
-void
-mono_reflection_register_with_runtime (MonoReflectionType *type)
-{
- /* This is empty */
-}
-
-static gboolean
-is_sre_type_builder (MonoClass *klass)
-{
- return FALSE;
-}
-
-static gboolean
-is_sre_generic_instance (MonoClass *klass)
-{
- return FALSE;
-}
-
-static void
-init_type_builder_generics (MonoObject *type, MonoError *error)
-{
- mono_error_init (error);
-}
-
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-
-static gboolean
-is_sr_mono_field (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoField");
-}
-
-static gboolean
-is_sr_mono_property (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
-}
-
-static gboolean
-is_sr_mono_method (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
-}
-
-static gboolean
-is_sr_mono_cmethod (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
-}
-
-static gboolean
-is_sr_mono_generic_method (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
-}
-
-static gboolean
-is_sr_mono_generic_cmethod (MonoClass *klass)
-{
- check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
-}
-
-gboolean
-mono_class_is_reflection_method_or_constructor (MonoClass *klass)
-{
- return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
-}
-
-static gboolean
-is_usertype (MonoReflectionType *ref)
-{
- MonoClass *klass = mono_object_class (ref);
- return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
-}
-
-static MonoReflectionType*
-mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
-{
- mono_error_init (error);
- if (!type || type->type)
- return type;
-
- if (is_usertype (type)) {
- type = mono_reflection_type_get_underlying_system_type (type, error);
- return_val_if_nok (error, NULL);
- if (is_usertype (type)) {
- mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
- return NULL;
- }
- }
-
- return type;
-}
-/**
- * encode_cattr_value:
- * Encode a value in a custom attribute stream of bytes.
- * The value to encode is either supplied as an object in argument val
- * (valuetypes are boxed), or as a pointer to the data in the
- * argument argval.
- * @type represents the type of the value
- * @buffer is the start of the buffer
- * @p the current position in the buffer
- * @buflen contains the size of the buffer and is used to return the new buffer size
- * if this needs to be realloced.
- * @retbuffer and @retp return the start and the position of the buffer
- * @error set on error.
- */
-static void
-encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
-{
- MonoTypeEnum simple_type;
-
- mono_error_init (error);
- if ((p-buffer) + 10 >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- if (!argval)
- argval = ((char*)arg + sizeof (MonoObject));
- simple_type = type->type;
-handle_enum:
- switch (simple_type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- *p++ = *argval;
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- swap_with_size (p, argval, 2, 1);
- p += 2;
- break;
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4:
- swap_with_size (p, argval, 4, 1);
- p += 4;
- break;
- case MONO_TYPE_R8:
- swap_with_size (p, argval, 8, 1);
- p += 8;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- swap_with_size (p, argval, 8, 1);
- p += 8;
- break;
- case MONO_TYPE_VALUETYPE:
- if (type->data.klass->enumtype) {
- simple_type = mono_class_enum_basetype (type->data.klass)->type;
- goto handle_enum;
- } else {
- g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
- }
- break;
- case MONO_TYPE_STRING: {
- char *str;
- guint32 slen;
- if (!arg) {
- *p++ = 0xFF;
- break;
- }
- str = mono_string_to_utf8_checked ((MonoString*)arg, error);
- return_if_nok (error);
- slen = strlen (str);
- if ((p-buffer) + 10 + slen >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += slen;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- break;
- }
- case MONO_TYPE_CLASS: {
- char *str;
- guint32 slen;
- MonoType *arg_type;
- if (!arg) {
- *p++ = 0xFF;
- break;
- }
-handle_type:
- arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
- return_if_nok (error);
-
- str = type_get_qualified_name (arg_type, NULL);
- slen = strlen (str);
- if ((p-buffer) + 10 + slen >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += slen;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- break;
- }
- case MONO_TYPE_SZARRAY: {
- int len, i;
- MonoClass *eclass, *arg_eclass;
-
- if (!arg) {
- *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
- break;
- }
- len = mono_array_length ((MonoArray*)arg);
- *p++ = len & 0xff;
- *p++ = (len >> 8) & 0xff;
- *p++ = (len >> 16) & 0xff;
- *p++ = (len >> 24) & 0xff;
- *retp = p;
- *retbuffer = buffer;
- eclass = type->data.klass;
- arg_eclass = mono_object_class (arg)->element_class;
-
- if (!eclass) {
- /* Happens when we are called from the MONO_TYPE_OBJECT case below */
- eclass = mono_defaults.object_class;
- }
- if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
- char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
- int elsize = mono_class_array_element_size (arg_eclass);
- for (i = 0; i < len; ++i) {
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
- return_if_nok (error);
- elptr += elsize;
- }
- } else if (eclass->valuetype && arg_eclass->valuetype) {
- char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
- int elsize = mono_class_array_element_size (eclass);
- for (i = 0; i < len; ++i) {
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
- return_if_nok (error);
- elptr += elsize;
- }
- } else {
- for (i = 0; i < len; ++i) {
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
- return_if_nok (error);
- }
- }
- break;
- }
- case MONO_TYPE_OBJECT: {
- MonoClass *klass;
- char *str;
- guint32 slen;
-
- /*
- * The parameter type is 'object' but the type of the actual
- * argument is not. So we have to add type information to the blob
- * too. This is completely undocumented in the spec.
- */
-
- if (arg == NULL) {
- *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
- *p++ = 0xFF;
- break;
- }
-
- klass = mono_object_class (arg);
-
- if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
- *p++ = 0x50;
- goto handle_type;
- } else {
- return_if_nok (error);
- }
-
- if (klass->enumtype) {
- *p++ = 0x55;
- } else if (klass == mono_defaults.string_class) {
- simple_type = MONO_TYPE_STRING;
- *p++ = 0x0E;
- goto handle_enum;
- } else if (klass->rank == 1) {
- *p++ = 0x1D;
- if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
- /* See Partition II, Appendix B3 */
- *p++ = 0x51;
- else
- *p++ = klass->element_class->byval_arg.type;
- encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
- return_if_nok (error);
- break;
- } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
- *p++ = simple_type = klass->byval_arg.type;
- goto handle_enum;
- } else {
- g_error ("unhandled type in custom attr");
- }
- str = type_get_qualified_name (mono_class_get_type(klass), NULL);
- slen = strlen (str);
- if ((p-buffer) + 10 + slen >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += slen;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- simple_type = mono_class_enum_basetype (klass)->type;
- goto handle_enum;
- }
- default:
- g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
- }
- *retp = p;
- *retbuffer = buffer;
-}
-
-static void
-encode_field_or_prop_type (MonoType *type, char *p, char **retp)
-{
- if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
- char *str = type_get_qualified_name (type, NULL);
- int slen = strlen (str);
-
- *p++ = 0x55;
- /*
- * This seems to be optional...
- * *p++ = 0x80;
- */
- mono_metadata_encode_value (slen, p, &p);
- memcpy (p, str, slen);
- p += slen;
- g_free (str);
- } else if (type->type == MONO_TYPE_OBJECT) {
- *p++ = 0x51;
- } else if (type->type == MONO_TYPE_CLASS) {
- /* it should be a type: encode_cattr_value () has the check */
- *p++ = 0x50;
- } else {
- mono_metadata_encode_value (type->type, p, &p);
- if (type->type == MONO_TYPE_SZARRAY)
- /* See the examples in Partition VI, Annex B */
- encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
- }
-
- *retp = p;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static void
-encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
-{
- int len;
-
- mono_error_init (error);
-
- /* Preallocate a large enough buffer */
- if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
- char *str = type_get_qualified_name (type, NULL);
- len = strlen (str);
- g_free (str);
- } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
- char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
- len = strlen (str);
- g_free (str);
- } else {
- len = 0;
- }
- len += strlen (name);
-
- if ((p-buffer) + 20 + len >= *buflen) {
- char *newbuf;
- *buflen *= 2;
- *buflen += len;
- newbuf = (char *)g_realloc (buffer, *buflen);
- p = newbuf + (p-buffer);
- buffer = newbuf;
- }
-
- encode_field_or_prop_type (type, p, &p);
-
- len = strlen (name);
- mono_metadata_encode_value (len, p, &p);
- memcpy (p, name, len);
- p += len;
- encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
- return_if_nok (error);
- *retp = p;
- *retbuffer = buffer;
-}
-
-/**
- * mono_reflection_get_custom_attrs_blob:
- * @ctor: custom attribute constructor
- * @ctorArgs: arguments o the constructor
- * @properties:
- * @propValues:
- * @fields:
- * @fieldValues:
- *
- * Creates the blob of data that needs to be saved in the metadata and that represents
- * the custom attributed described by @ctor, @ctorArgs etc.
- * Returns: a Byte array representing the blob of data.
- */
-MonoArray*
-mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
-{
- MonoError error;
- MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
- mono_error_cleanup (&error);
- return result;
-}
-
-/**
- * mono_reflection_get_custom_attrs_blob_checked:
- * @ctor: custom attribute constructor
- * @ctorArgs: arguments o the constructor
- * @properties:
- * @propValues:
- * @fields:
- * @fieldValues:
- * @error: set on error
- *
- * Creates the blob of data that needs to be saved in the metadata and that represents
- * the custom attributed described by @ctor, @ctorArgs etc.
- * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
- */
-MonoArray*
-mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
-{
- MonoArray *result = NULL;
- MonoMethodSignature *sig;
- MonoObject *arg;
- char *buffer, *p;
- guint32 buflen, i;
-
- mono_error_init (error);
-
- if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
- /* sig is freed later so allocate it in the heap */
- sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
- if (!is_ok (error)) {
- g_free (sig);
- return NULL;
- }
- } else {
- sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
- }
-
- g_assert (mono_array_length (ctorArgs) == sig->param_count);
- buflen = 256;
- p = buffer = (char *)g_malloc (buflen);
- /* write the prolog */
- *p++ = 1;
- *p++ = 0;
- for (i = 0; i < sig->param_count; ++i) {
- arg = mono_array_get (ctorArgs, MonoObject*, i);
- encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
- if (!is_ok (error)) goto leave;
- }
- i = 0;
- if (properties)
- i += mono_array_length (properties);
- if (fields)
- i += mono_array_length (fields);
- *p++ = i & 0xff;
- *p++ = (i >> 8) & 0xff;
- if (properties) {
- MonoObject *prop;
- for (i = 0; i < mono_array_length (properties); ++i) {
- MonoType *ptype;
- char *pname;
-
- prop = (MonoObject *)mono_array_get (properties, gpointer, i);
- get_prop_name_and_type (prop, &pname, &ptype, error);
- if (!is_ok (error)) goto leave;
- *p++ = 0x54; /* PROPERTY signature */
- encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
- g_free (pname);
- if (!is_ok (error)) goto leave;
- }
- }
-
- if (fields) {
- MonoObject *field;
- for (i = 0; i < mono_array_length (fields); ++i) {
- MonoType *ftype;
- char *fname;
-
- field = (MonoObject *)mono_array_get (fields, gpointer, i);
- get_field_name_and_type (field, &fname, &ftype, error);
- if (!is_ok (error)) goto leave;
- *p++ = 0x53; /* FIELD signature */
- encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
- g_free (fname);
- if (!is_ok (error)) goto leave;
- }
- }
-
- g_assert (p - buffer <= buflen);
- buflen = p - buffer;
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
- if (!is_ok (error))
- goto leave;
- p = mono_array_addr (result, char, 0);
- memcpy (p, buffer, buflen);
-leave:
- g_free (buffer);
- if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
- g_free (sig);
- return result;
-}
-
-/**
- * reflection_setup_internal_class:
- * @tb: a TypeBuilder object
- * @error: set on error
- *
- * Creates a MonoClass that represents the TypeBuilder.
- * This is a trick that lets us simplify a lot of reflection code
- * (and will allow us to support Build and Run assemblies easier).
- *
- * Returns TRUE on success. On failure, returns FALSE and sets @error.
- */
-static gboolean
-reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
- MonoClass *klass, *parent;
-
- mono_error_init (error);
- RESOLVE_TYPE (tb->parent, error);
- return_val_if_nok (error, FALSE);
-
- mono_loader_lock ();
-
- if (tb->parent) {
- MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return FALSE;
- }
- /* check so we can compile corlib correctly */
- if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
- /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
- parent = parent_type->data.klass;
- } else {
- parent = mono_class_from_mono_type (parent_type);
- }
- } else {
- parent = NULL;
- }
-
- /* the type has already being created: it means we just have to change the parent */
- if (tb->type.type) {
- klass = mono_class_from_mono_type (tb->type.type);
- klass->parent = NULL;
- /* fool mono_class_setup_parent */
- klass->supertypes = NULL;
- mono_class_setup_parent (klass, parent);
- mono_class_setup_mono_type (klass);
- mono_loader_unlock ();
- return TRUE;
- }
-
- klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
-
- klass->image = &tb->module->dynamic_image->image;
-
- klass->inited = 1; /* we lie to the runtime */
- klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
- if (!is_ok (error))
- goto failure;
- klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
- if (!is_ok (error))
- goto failure;
- klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
- klass->flags = tb->attrs;
-
- mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
-
- klass->element_class = klass;
-
- if (mono_class_get_ref_info (klass) == NULL) {
-
- mono_class_set_ref_info (klass, tb);
-
- /* Put into cache so mono_class_get_checked () will find it.
- Skip nested types as those should not be available on the global scope. */
- if (!tb->nesting_type)
- mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
-
- /*
- We must register all types as we cannot rely on the name_cache hashtable since we find the class
- by performing a mono_class_get which does the full resolution.
-
- Working around this semantics would require us to write a lot of code for no clear advantage.
- */
- mono_image_append_class_to_reflection_info_set (klass);
- } else {
- g_assert (mono_class_get_ref_info (klass) == tb);
- }
-
- register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
-
- if (parent != NULL) {
- mono_class_setup_parent (klass, parent);
- } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
- const char *old_n = klass->name;
- /* trick to get relative numbering right when compiling corlib */
- klass->name = "BuildingObject";
- mono_class_setup_parent (klass, mono_defaults.object_class);
- klass->name = old_n;
- }
-
- if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
- (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
- (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
- klass->instance_size = sizeof (MonoObject);
- klass->size_inited = 1;
- mono_class_setup_vtable_general (klass, NULL, 0, NULL);
- }
-
- mono_class_setup_mono_type (klass);
-
- mono_class_setup_supertypes (klass);
-
- /*
- * FIXME: handle interfaces.
- */
-
- tb->type.type = &klass->byval_arg;
-
- if (tb->nesting_type) {
- g_assert (tb->nesting_type->type);
- MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
- if (!is_ok (error)) goto failure;
- klass->nested_in = mono_class_from_mono_type (nesting_type);
- }
-
- /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
-
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
-
- mono_loader_unlock ();
- return TRUE;
-
-failure:
- mono_loader_unlock ();
- return FALSE;
-}
-
-/**
- * mono_reflection_setup_internal_class:
- * @tb: a TypeBuilder object
- *
- * (icall)
- * Creates a MonoClass that represents the TypeBuilder.
- * This is a trick that lets us simplify a lot of reflection code
- * (and will allow us to support Build and Run assemblies easier).
- *
- */
-void
-mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
-{
- MonoError error;
- (void) reflection_setup_internal_class (tb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-/*
- * mono_reflection_setup_generic_class:
- * @tb: a TypeBuilder object
- *
- * Setup the generic class before adding the first generic parameter.
- */
-void
-mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
-{
-}
-
-/**
- * mono_reflection_create_generic_class:
- * @tb: a TypeBuilder object
- * @error: set on error
- *
- * Creates the generic class after all generic parameters have been added.
- * On success returns TRUE, on failure returns FALSE and sets @error.
- *
- */
-gboolean
-mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
-
- MonoClass *klass;
- int count, i;
-
- mono_error_init (error);
-
- klass = mono_class_from_mono_type (tb->type.type);
-
- count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
-
- if (klass->generic_container || (count == 0))
- return TRUE;
-
- g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
-
- klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
-
- klass->generic_container->owner.klass = klass;
- klass->generic_container->type_argc = count;
- klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
-
- klass->is_generic = 1;
-
- for (i = 0; i < count; i++) {
- MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
- MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
- return_val_if_nok (error, FALSE);
- MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
- klass->generic_container->type_params [i] = *param;
- /*Make sure we are a diferent type instance */
- klass->generic_container->type_params [i].param.owner = klass->generic_container;
- klass->generic_container->type_params [i].info.pklass = NULL;
- klass->generic_container->type_params [i].info.flags = gparam->attrs;
-
- g_assert (klass->generic_container->type_params [i].param.owner);
- }
-
- klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
- return TRUE;
-}
-
-/**
- * reflection_create_internal_class:
- * @tb: a TypeBuilder object
- * @error: set on error
- *
- * Actually create the MonoClass that is associated with the TypeBuilder.
- * On success returns TRUE, on failure returns FALSE and sets @error.
- *
- */
-static gboolean
-reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
-
- MonoClass *klass;
-
- mono_error_init (error);
- klass = mono_class_from_mono_type (tb->type.type);
-
- mono_loader_lock ();
- if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
- MonoReflectionFieldBuilder *fb;
- MonoClass *ec;
- MonoType *enum_basetype;
-
- g_assert (tb->fields != NULL);
- g_assert (mono_array_length (tb->fields) >= 1);
-
- fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
-
- MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return FALSE;
- }
- if (!mono_type_is_valid_enum_basetype (field_type)) {
- mono_loader_unlock ();
- return TRUE;
- }
-
- enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return FALSE;
- }
- klass->element_class = mono_class_from_mono_type (enum_basetype);
- if (!klass->element_class)
- klass->element_class = mono_class_from_mono_type (enum_basetype);
-
- /*
- * get the element_class from the current corlib.
- */
- ec = default_class_from_mono_type (enum_basetype);
- klass->instance_size = ec->instance_size;
- klass->size_inited = 1;
- /*
- * this is almost safe to do with enums and it's needed to be able
- * to create objects of the enum type (for use in SetConstant).
- */
- /* FIXME: Does this mean enums can't have method overrides ? */
- mono_class_setup_vtable_general (klass, NULL, 0, NULL);
- }
- mono_loader_unlock ();
- return TRUE;
-}
-
-/**
- * mono_reflection_create_internal_class:
- * @tb: a TypeBuilder object
- *
- * (icall)
- * Actually create the MonoClass that is associated with the TypeBuilder.
- */
-void
-mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
-{
- MonoError error;
- (void) reflection_create_internal_class (tb, &error);
- mono_error_set_pending_exception (&error);
-}
-
-static MonoMarshalSpec*
-mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
- MonoReflectionMarshal *minfo, MonoError *error)
-{
- MonoMarshalSpec *res;
-
- mono_error_init (error);
-
- res = image_g_new0 (image, MonoMarshalSpec, 1);
- res->native = (MonoMarshalNative)minfo->type;
-
- switch (minfo->type) {
- case MONO_NATIVE_LPARRAY:
- res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
- if (minfo->has_size) {
- res->data.array_data.param_num = minfo->param_num;
- res->data.array_data.num_elem = minfo->count;
- res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
- }
- else {
- res->data.array_data.param_num = -1;
- res->data.array_data.num_elem = -1;
- res->data.array_data.elem_mult = -1;
- }
- break;
-
- case MONO_NATIVE_BYVALTSTR:
- case MONO_NATIVE_BYVALARRAY:
- res->data.array_data.num_elem = minfo->count;
- break;
-
- case MONO_NATIVE_CUSTOM:
- if (minfo->marshaltyperef) {
- MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
- if (!is_ok (error)) {
- image_g_free (image, res);
- return NULL;
- }
- res->data.custom_data.custom_name =
- type_get_fully_qualified_name (marshaltyperef);
- }
- if (minfo->mcookie) {
- res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
- if (!is_ok (error)) {
- image_g_free (image, res);
- return NULL;
- }
- }
- break;
-
- default:
- break;
- }
-
- return res;
-}
-#endif /* !DISABLE_REFLECTION_EMIT */
-
-MonoReflectionMarshalAsAttribute*
-mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
- MonoMarshalSpec *spec, MonoError *error)
-{
- MonoReflectionType *rt;
- MonoReflectionMarshalAsAttribute *minfo;
- MonoType *mtype;
-
- mono_error_init (error);
-
- minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
- if (!minfo)
- return NULL;
- minfo->utype = spec->native;
-
- switch (minfo->utype) {
- case MONO_NATIVE_LPARRAY:
- minfo->array_subtype = spec->data.array_data.elem_type;
- minfo->size_const = spec->data.array_data.num_elem;
- if (spec->data.array_data.param_num != -1)
- minfo->size_param_index = spec->data.array_data.param_num;
- break;
-
- case MONO_NATIVE_BYVALTSTR:
- case MONO_NATIVE_BYVALARRAY:
- minfo->size_const = spec->data.array_data.num_elem;
- break;
-
- case MONO_NATIVE_CUSTOM:
- if (spec->data.custom_data.custom_name) {
- mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
- return_val_if_nok (error, NULL);
-
- if (mtype) {
- rt = mono_type_get_object_checked (domain, mtype, error);
- if (!rt)
- return NULL;
-
- MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
- }
-
- MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
- }
- if (spec->data.custom_data.cookie)
- MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
- break;
-
- default:
- break;
- }
-
- return minfo;
-}
-
-#ifndef DISABLE_REFLECTION_EMIT
-static MonoMethod*
-reflection_methodbuilder_to_mono_method (MonoClass *klass,
- ReflectionMethodBuilder *rmb,
- MonoMethodSignature *sig,
- MonoError *error)
-{
- MonoMethod *m;
- MonoMethodWrapper *wrapperm;
- MonoMarshalSpec **specs;
- MonoReflectionMethodAux *method_aux;
- MonoImage *image;
- gboolean dynamic;
- int i;
-
- mono_error_init (error);
- /*
- * Methods created using a MethodBuilder should have their memory allocated
- * inside the image mempool, while dynamic methods should have their memory
- * malloc'd.
- */
- dynamic = rmb->refs != NULL;
- image = dynamic ? NULL : klass->image;
-
- if (!dynamic)
- g_assert (!klass->generic_class);
-
- mono_loader_lock ();
-
- if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
- (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
- m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
- else
- m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
-
- wrapperm = (MonoMethodWrapper*)m;
-
- m->dynamic = dynamic;
- m->slot = -1;
- m->flags = rmb->attrs;
- m->iflags = rmb->iattrs;
- m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
- m->klass = klass;
- m->signature = sig;
- m->sre_method = TRUE;
- m->skip_visibility = rmb->skip_visibility;
- if (rmb->table_idx)
- m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
-
- if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
- if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
- m->string_ctor = 1;
-
- m->signature->pinvoke = 1;
- } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
- m->signature->pinvoke = 1;
-
- method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
-
- method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
- mono_error_assert_ok (error);
- method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
- mono_error_assert_ok (error);
-
- ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
-
- if (image_is_dynamic (klass->image))
- g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
-
- mono_loader_unlock ();
-
- return m;
- } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
- !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
- MonoMethodHeader *header;
- guint32 code_size;
- gint32 max_stack, i;
- gint32 num_locals = 0;
- gint32 num_clauses = 0;
- guint8 *code;
-
- if (rmb->ilgen) {
- code = mono_array_addr (rmb->ilgen->code, guint8, 0);
- code_size = rmb->ilgen->code_len;
- max_stack = rmb->ilgen->max_stack;
- num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
- if (rmb->ilgen->ex_handlers)
- num_clauses = method_count_clauses (rmb->ilgen);
- } else {
- if (rmb->code) {
- code = mono_array_addr (rmb->code, guint8, 0);
- code_size = mono_array_length (rmb->code);
- /* we probably need to run a verifier on the code... */
- max_stack = 8;
- }
- else {
- code = NULL;
- code_size = 0;
- max_stack = 8;
- }
- }
-
- header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
- header->code_size = code_size;
- header->code = (const unsigned char *)image_g_malloc (image, code_size);
- memcpy ((char*)header->code, code, code_size);
- header->max_stack = max_stack;
- header->init_locals = rmb->init_locals;
- header->num_locals = num_locals;
-
- for (i = 0; i < num_locals; ++i) {
- MonoReflectionLocalBuilder *lb =
- mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
-
- header->locals [i] = image_g_new0 (image, MonoType, 1);
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
- mono_error_assert_ok (error);
- memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
- }
-
- header->num_clauses = num_clauses;
- if (num_clauses) {
- header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
- rmb->ilgen, num_clauses, error);
- mono_error_assert_ok (error);
- }
-
- wrapperm->header = header;
- }
-
- if (rmb->generic_params) {
- int count = mono_array_length (rmb->generic_params);
- MonoGenericContainer *container = rmb->generic_container;
-
- g_assert (container);
-
- container->type_argc = count;
- container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
- container->owner.method = m;
- container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
-
- m->is_generic = TRUE;
- mono_method_set_generic_container (m, container);
-
- for (i = 0; i < count; i++) {
- MonoReflectionGenericParam *gp =
- mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
- MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
- mono_error_assert_ok (error);
- MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
- container->type_params [i] = *param;
- }
-
- /*
- * The method signature might have pointers to generic parameters that belong to other methods.
- * This is a valid SRE case, but the resulting method signature must be encoded using the proper
- * generic parameters.
- */
- for (i = 0; i < m->signature->param_count; ++i) {
- MonoType *t = m->signature->params [i];
- if (t->type == MONO_TYPE_MVAR) {
- MonoGenericParam *gparam = t->data.generic_param;
- if (gparam->num < count) {
- m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
- m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
- }
-
- }
- }
-
- if (klass->generic_container) {
- container->parent = klass->generic_container;
- container->context.class_inst = klass->generic_container->context.class_inst;
- }
- container->context.method_inst = mono_get_shared_generic_inst (container);
- }
-
- if (rmb->refs) {
- MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
- int i;
- void **data;
-
- m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
-
- mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
- data [0] = GUINT_TO_POINTER (rmb->nrefs);
- for (i = 0; i < rmb->nrefs; ++i)
- data [i + 1] = rmb->refs [i];
- }
-
- method_aux = NULL;
-
- /* Parameter info */
- if (rmb->pinfo) {
- if (!method_aux)
- method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
- method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
- for (i = 0; i <= m->signature->param_count; ++i) {
- MonoReflectionParamBuilder *pb;
- if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
- if ((i > 0) && (pb->attrs)) {
- /* Make a copy since it might point to a shared type structure */
- m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
- m->signature->params [i - 1]->attrs = pb->attrs;
- }
-
- if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
- MonoDynamicImage *assembly;
- guint32 idx, len;
- MonoTypeEnum def_type;
- char *p;
- const char *p2;
-
- if (!method_aux->param_defaults) {
- method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
- method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
- }
- assembly = (MonoDynamicImage*)klass->image;
- idx = encode_constant (assembly, pb->def_value, &def_type);
- /* Copy the data from the blob since it might get realloc-ed */
- p = assembly->blob.data + idx;
- len = mono_metadata_decode_blob_size (p, &p2);
- len += p2 - p;
- method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
- method_aux->param_default_types [i] = def_type;
- memcpy ((gpointer)method_aux->param_defaults [i], p, len);
- }
-
- if (pb->name) {
- method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
- mono_error_assert_ok (error);
- }
- if (pb->cattrs) {
- if (!method_aux->param_cattr)
- method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
- method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
- }
- }
- }
- }
-
- /* Parameter marshalling */
- specs = NULL;
- if (rmb->pinfo)
- for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
- MonoReflectionParamBuilder *pb;
- if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
- if (pb->marshal_info) {
- if (specs == NULL)
- specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
- specs [pb->position] =
- mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- image_g_free (image, specs);
- /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
- return NULL;
- }
- }
- }
- }
- if (specs != NULL) {
- if (!method_aux)
- method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
- method_aux->param_marshall = specs;
- }
-
- if (image_is_dynamic (klass->image) && method_aux)
- g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
-
- mono_loader_unlock ();
-
- return m;
-}
-
-static MonoMethod*
-ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
-{
- ReflectionMethodBuilder rmb;
- MonoMethodSignature *sig;
-
- mono_loader_lock ();
- g_assert (klass->image != NULL);
- sig = ctor_builder_to_signature (klass->image, mb, error);
- mono_loader_unlock ();
- return_val_if_nok (error, NULL);
-
- if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
- return NULL;
-
- mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- return_val_if_nok (error, NULL);
- mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
-
- /* If we are in a generic class, we might be called multiple times from inflate_method */
- if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
- /* ilgen is no longer needed */
- mb->ilgen = NULL;
- }
-
- return mb->mhandle;
-}
-
-static MonoMethod*
-methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
-{
- ReflectionMethodBuilder rmb;
- MonoMethodSignature *sig;
-
- mono_error_init (error);
-
- mono_loader_lock ();
- g_assert (klass->image != NULL);
- sig = method_builder_to_signature (klass->image, mb, error);
- mono_loader_unlock ();
- return_val_if_nok (error, NULL);
-
- if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
- return NULL;
-
- mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- return_val_if_nok (error, NULL);
- mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
-
- /* If we are in a generic class, we might be called multiple times from inflate_method */
- if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
- /* ilgen is no longer needed */
- mb->ilgen = NULL;
- }
- return mb->mhandle;
-}
-
-static MonoClassField*
-fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
-{
- MonoClassField *field;
- MonoType *custom;
-
- mono_error_init (error);
-
- field = g_new0 (MonoClassField, 1);
-
- field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
- mono_error_assert_ok (error);
- if (fb->attrs || fb->modreq || fb->modopt) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- g_free (field);
- return NULL;
- }
- field->type = mono_metadata_type_dup (NULL, type);
- field->type->attrs = fb->attrs;
-
- g_assert (image_is_dynamic (klass->image));
- custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
- g_free (field->type);
- if (!is_ok (error)) {
- g_free (field);
- return NULL;
- }
- field->type = mono_metadata_type_dup (klass->image, custom);
- g_free (custom);
- } else {
- field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- if (!is_ok (error)) {
- g_free (field);
- return NULL;
- }
- }
- if (fb->offset != -1)
- field->offset = fb->offset;
- field->parent = klass;
- mono_save_custom_attrs (klass->image, field, fb->cattrs);
-
- // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
-
- return field;
-}
-#endif
-
-/**
- * mono_reflection_bind_generic_parameters:
- * @type: a managed type object (which should be some kind of generic (instance? definition?))
- * @type_args: the number of type arguments to bind
- * @types: array of type arguments
- * @error: set on error
- *
- * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
- * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
- */
-MonoType*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
-{
- MonoClass *klass;
- MonoReflectionTypeBuilder *tb = NULL;
- gboolean is_dynamic = FALSE;
- MonoClass *geninst;
-
- mono_error_init (error);
-
- mono_loader_lock ();
-
- if (is_sre_type_builder (mono_object_class (type))) {
- tb = (MonoReflectionTypeBuilder *) type;
-
- is_dynamic = TRUE;
- } else if (is_sre_generic_instance (mono_object_class (type))) {
- MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
- MonoReflectionType *gtd = rgi->generic_type;
-
- if (is_sre_type_builder (mono_object_class (gtd))) {
- tb = (MonoReflectionTypeBuilder *)gtd;
- is_dynamic = TRUE;
- }
- }
-
- /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
- if (tb && tb->generic_container) {
- if (!mono_reflection_create_generic_class (tb, error)) {
- mono_loader_unlock ();
- return NULL;
- }
- }
-
- MonoType *t = mono_reflection_type_get_handle (type, error);
- if (!is_ok (error)) {
- mono_loader_unlock ();
- return NULL;
- }
-
- klass = mono_class_from_mono_type (t);
- if (!klass->generic_container) {
- mono_loader_unlock ();
- mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
- return NULL;
- }
-
- if (klass->wastypebuilder) {
- tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
-
- is_dynamic = TRUE;
- }
-
- mono_loader_unlock ();
-
- geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
-
- return &geninst->byval_arg;
-}
-
-MonoClass*
-mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
-{
- MonoGenericClass *gclass;
- MonoGenericInst *inst;
-
- g_assert (klass->generic_container);
-
- inst = mono_metadata_get_generic_inst (type_argc, types);
- gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
-
- return mono_generic_class_get_class (gclass);
-}
-
-static MonoReflectionMethod*
-reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
-{
- MonoClass *klass;
- MonoMethod *method, *inflated;
- MonoMethodInflated *imethod;
- MonoGenericContext tmp_context;
- MonoGenericInst *ginst;
- MonoType **type_argv;
- int count, i;
-
- mono_error_init (error);
-
- /*FIXME but this no longer should happen*/
- if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
-#ifndef DISABLE_REFLECTION_EMIT
- MonoReflectionMethodBuilder *mb = NULL;
- MonoType *tb;
- MonoClass *klass;
-
- mb = (MonoReflectionMethodBuilder *) rmethod;
- tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
- return_val_if_nok (error, NULL);
- klass = mono_class_from_mono_type (tb);
-
- method = methodbuilder_to_mono_method (klass, mb, error);
- return_val_if_nok (error, NULL);
-#else
- g_assert_not_reached ();
- method = NULL;
-#endif
- } else {
- method = rmethod->method;
- }
-
- klass = method->klass;
-
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- count = mono_method_signature (method)->generic_param_count;
- if (count != mono_array_length (types))
- return NULL;
-
- type_argv = g_new0 (MonoType *, count);
- for (i = 0; i < count; i++) {
- MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
- type_argv [i] = mono_reflection_type_get_handle (garg, error);
- if (!is_ok (error)) {
- g_free (type_argv);
- return NULL;
- }
- }
- ginst = mono_metadata_get_generic_inst (count, type_argv);
- g_free (type_argv);
-
- tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
- tmp_context.method_inst = ginst;
-
- inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
- mono_error_assert_ok (error);
- imethod = (MonoMethodInflated *) inflated;
-
- /*FIXME but I think this is no longer necessary*/
- if (image_is_dynamic (method->klass->image)) {
- MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
- /*
- * This table maps metadata structures representing inflated methods/fields
- * to the reflection objects representing their generic definitions.
- */
- mono_image_lock ((MonoImage*)image);
- mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
- mono_image_unlock ((MonoImage*)image);
- }
-
- if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
- mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
- return NULL;
- }
-
- MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
- return ret;
-}
-
-MonoReflectionMethod*
-mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
-{
- MonoError error;
- MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
-
-#ifndef DISABLE_REFLECTION_EMIT
-
-static MonoMethod *
-inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
-{
- MonoMethodInflated *imethod;
- MonoGenericContext *context;
- int i;
-
- /*
- * With generic code sharing the klass might not be inflated.
- * This can happen because classes inflated with their own
- * type arguments are "normalized" to the uninflated class.
- */
- if (!klass->generic_class)
- return method;
-
- context = mono_class_get_context (klass);
-
- if (klass->method.count && klass->methods) {
- /* Find the already created inflated method */
- for (i = 0; i < klass->method.count; ++i) {
- g_assert (klass->methods [i]->is_inflated);
- if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
- break;
- }
- g_assert (i < klass->method.count);
- imethod = (MonoMethodInflated*)klass->methods [i];
- } else {
- MonoError error;
- imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
- mono_error_assert_ok (&error);
- }
-
- if (method->is_generic && image_is_dynamic (method->klass->image)) {
- MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
-
- mono_image_lock ((MonoImage*)image);
- mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
- mono_image_unlock ((MonoImage*)image);
- }
- return (MonoMethod *) imethod;
-}
-
-static MonoMethod *
-inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
-{
- MonoMethod *method;
- MonoClass *gklass;
-
- mono_error_init (error);
-
- MonoClass *type_class = mono_object_class (type);
-
- if (is_sre_generic_instance (type_class)) {
- MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
- MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
- return_val_if_nok (error, NULL);
- gklass = mono_class_from_mono_type (generic_type);
- } else if (is_sre_type_builder (type_class)) {
- MonoType *t = mono_reflection_type_get_handle (type, error);
- return_val_if_nok (error, NULL);
- gklass = mono_class_from_mono_type (t);
- } else if (type->type) {
- gklass = mono_class_from_mono_type (type->type);
- gklass = mono_class_get_generic_type_definition (gklass);
- } else {
- g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
- }
-
- if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
- if (((MonoReflectionMethodBuilder*)obj)->mhandle)
- method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
- else {
- method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
- if (!method)
- return NULL;
- }
- else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
- method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
- if (!method)
- return NULL;
- } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
- method = ((MonoReflectionMethod *) obj)->method;
- else {
- method = NULL; /* prevent compiler warning */
- g_error ("can't handle type %s", obj->vtable->klass->name);
- }
-
- MonoType *t = mono_reflection_type_get_handle (type, error);
- return_val_if_nok (error, NULL);
- return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
-}
-
-/*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
-static gboolean
-reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
-{
- MonoGenericClass *gclass;
- MonoDynamicGenericClass *dgclass;
- MonoClass *klass, *gklass;
- MonoType *gtype;
- int i;
-
- mono_error_init (error);
-
- gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
- return_val_if_nok (error, FALSE);
- klass = mono_class_from_mono_type (gtype);
- g_assert (gtype->type == MONO_TYPE_GENERICINST);
- gclass = gtype->data.generic_class;
-
- if (!gclass->is_dynamic)
- return TRUE;
-
- dgclass = (MonoDynamicGenericClass *) gclass;
-
- if (dgclass->initialized)
- return TRUE;
-
- gklass = gclass->container_class;
- mono_class_init (gklass);
-
- dgclass->count_fields = fields ? mono_array_length (fields) : 0;
-
- dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
- dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
- dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
-
- for (i = 0; i < dgclass->count_fields; i++) {
- MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
- MonoClassField *field, *inflated_field = NULL;
-
- if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
- inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
- return_val_if_nok (error, FALSE);
- } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
- field = ((MonoReflectionField *) obj)->field;
- else {
- field = NULL; /* prevent compiler warning */
- g_assert_not_reached ();
- }
-
- dgclass->fields [i] = *field;
- dgclass->fields [i].parent = klass;
- dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
- field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
- mono_error_assert_ok (error); /* FIXME don't swallow the error */
- dgclass->field_generic_types [i] = field->type;
- MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
- dgclass->field_objects [i] = obj;
-
- if (inflated_field) {
- g_free (inflated_field);
- } else {
- dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
- }
- }
-
- dgclass->initialized = TRUE;
- return TRUE;
-}
-
-void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
-{
- MonoError error;
- (void) reflection_generic_class_initialize (type, fields, &error);
- mono_error_set_pending_exception (&error);
-}
-
-void
-mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
-{
- MonoDynamicGenericClass *dgclass;
- int i;
-
- g_assert (gclass->is_dynamic);
-
- dgclass = (MonoDynamicGenericClass *)gclass;
-
- for (i = 0; i < dgclass->count_fields; ++i) {
- MonoClassField *field = dgclass->fields + i;
- mono_metadata_free_type (field->type);
- MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
- }
-}
-
-/**
- * fix_partial_generic_class:
- * @klass: a generic instantiation MonoClass
- * @error: set on error
- *
- * Assumes that the generic container of @klass has its vtable
- * initialized, and updates the parent class, insterfaces, methods and
- * fields of @klass by inflating the types using the generic context.
- *
- * On success returns TRUE, on failure returns FALSE and sets @error.
- *
- */
-static gboolean
-fix_partial_generic_class (MonoClass *klass, MonoError *error)
-{
- MonoClass *gklass = klass->generic_class->container_class;
- MonoDynamicGenericClass *dgclass;
- int i;
-
- mono_error_init (error);
+ /* last_point separates the namespace from the name */
+ last_point = NULL;
+ /* Skips spaces */
+ while (*p == ' ') p++, start++, w++, name++;
- if (klass->wastypebuilder)
- return TRUE;
-
- dgclass = (MonoDynamicGenericClass *) klass->generic_class;
- if (klass->parent != gklass->parent) {
- MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
- if (mono_error_ok (error)) {
- MonoClass *parent = mono_class_from_mono_type (parent_type);
- mono_metadata_free_type (parent_type);
- if (parent != klass->parent) {
- /*fool mono_class_setup_parent*/
- klass->supertypes = NULL;
- mono_class_setup_parent (klass, parent);
+ while (*p) {
+ switch (*p) {
+ case '+':
+ *p = 0; /* NULL terminate the name */
+ startn = p + 1;
+ info->nested = g_list_append (info->nested, startn);
+ /* we have parsed the nesting namespace + name */
+ if (info->name)
+ break;
+ if (last_point) {
+ info->name_space = start;
+ *last_point = 0;
+ info->name = last_point + 1;
+ } else {
+ info->name_space = (char *)"";
+ info->name = start;
}
- } else {
- if (gklass->wastypebuilder)
- klass->wastypebuilder = TRUE;
- return FALSE;
- }
- }
-
- if (!dgclass->initialized)
- return TRUE;
-
- if (klass->method.count != gklass->method.count) {
- klass->method.count = gklass->method.count;
- klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
-
- for (i = 0; i < klass->method.count; i++) {
- klass->methods [i] = mono_class_inflate_generic_method_full_checked (
- gklass->methods [i], klass, mono_class_get_context (klass), error);
- mono_error_assert_ok (error);
- }
- }
-
- if (klass->interface_count && klass->interface_count != gklass->interface_count) {
- klass->interface_count = gklass->interface_count;
- klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
- klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
-
- for (i = 0; i < gklass->interface_count; ++i) {
- MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
- return_val_if_nok (error, FALSE);
-
- klass->interfaces [i] = mono_class_from_mono_type (iface_type);
- mono_metadata_free_type (iface_type);
-
- if (!ensure_runtime_vtable (klass->interfaces [i], error))
- return FALSE;
- }
- klass->interfaces_inited = 1;
- }
-
- if (klass->field.count != gklass->field.count) {
- klass->field.count = gklass->field.count;
- klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
-
- for (i = 0; i < klass->field.count; i++) {
- klass->fields [i] = gklass->fields [i];
- klass->fields [i].parent = klass;
- klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
- return_val_if_nok (error, FALSE);
+ break;
+ case '.':
+ last_point = p;
+ break;
+ case '\\':
+ ++p;
+ break;
+ case '&':
+ case '*':
+ case '[':
+ case ',':
+ case ']':
+ in_modifiers = 1;
+ break;
+ default:
+ break;
}
+ if (in_modifiers)
+ break;
+ // *w++ = *p++;
+ p++;
}
-
- /*We can only finish with this klass once it's parent has as well*/
- if (gklass->wastypebuilder)
- klass->wastypebuilder = TRUE;
- return TRUE;
-}
-
-/**
- * ensure_generic_class_runtime_vtable:
- * @klass a generic class
- * @error set on error
- *
- * Ensures that the generic container of @klass has a vtable and
- * returns TRUE on success. On error returns FALSE and sets @error.
- */
-static gboolean
-ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
-{
- MonoClass *gklass = klass->generic_class->container_class;
-
- mono_error_init (error);
-
- if (!ensure_runtime_vtable (gklass, error))
- return FALSE;
-
- return fix_partial_generic_class (klass, error);
-}
-
-/**
- * ensure_runtime_vtable:
- * @klass the class
- * @error set on error
- *
- * Ensures that @klass has a vtable and returns TRUE on success. On
- * error returns FALSE and sets @error.
- */
-static gboolean
-ensure_runtime_vtable (MonoClass *klass, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- int i, num, j;
-
- mono_error_init (error);
-
- if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
- return TRUE;
- if (klass->parent)
- if (!ensure_runtime_vtable (klass->parent, error))
- return FALSE;
-
- if (tb) {
- num = tb->ctors? mono_array_length (tb->ctors): 0;
- num += tb->num_methods;
- klass->method.count = num;
- klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
- num = tb->ctors? mono_array_length (tb->ctors): 0;
- for (i = 0; i < num; ++i) {
- MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
- if (!ctor)
- return FALSE;
- klass->methods [i] = ctor;
- }
- num = tb->num_methods;
- j = i;
- for (i = 0; i < num; ++i) {
- MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
- if (!meth)
- return FALSE;
- klass->methods [j++] = meth;
- }
- if (tb->interfaces) {
- klass->interface_count = mono_array_length (tb->interfaces);
- klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
- for (i = 0; i < klass->interface_count; ++i) {
- MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
- return_val_if_nok (error, FALSE);
- klass->interfaces [i] = mono_class_from_mono_type (iface);
- if (!ensure_runtime_vtable (klass->interfaces [i], error))
- return FALSE;
- }
- klass->interfaces_inited = 1;
- }
- } else if (klass->generic_class){
- if (!ensure_generic_class_runtime_vtable (klass, error)) {
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- return FALSE;
- }
- }
-
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
- int slot_num = 0;
- for (i = 0; i < klass->method.count; ++i) {
- MonoMethod *im = klass->methods [i];
- if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
- im->slot = slot_num++;
- }
-
- klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
- mono_class_setup_interface_offsets (klass);
- mono_class_setup_interface_id (klass);
- }
-
- /*
- * The generic vtable is needed even if image->run is not set since some
- * runtime code like ves_icall_Type_GetMethodsByName depends on
- * method->slot being defined.
- */
-
- /*
- * tb->methods could not be freed since it is used for determining
- * overrides during dynamic vtable construction.
- */
-
- return TRUE;
-}
-
-static MonoMethod*
-mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
-{
- mono_error_init (error);
- MonoClass *klass = mono_object_class (method);
- if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
- MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
- return sr_method->method;
- }
- if (is_sre_method_builder (klass)) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
- return mb->mhandle;
- }
- if (is_sre_method_on_tb_inst (klass)) {
- MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
- MonoMethod *result;
- /*FIXME move this to a proper method and unify with resolve_object*/
- if (m->method_args) {
- result = mono_reflection_method_on_tb_inst_get_handle (m, error);
+ if (!info->name) {
+ if (last_point) {
+ info->name_space = start;
+ *last_point = 0;
+ info->name = last_point + 1;
} else {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, NULL);
- MonoClass *inflated_klass = mono_class_from_mono_type (type);
- MonoMethod *mono_method;
-
- if (is_sre_method_builder (mono_object_class (m->mb)))
- mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
- else if (is_sr_mono_method (mono_object_class (m->mb)))
- mono_method = ((MonoReflectionMethod *)m->mb)->method;
- else
- g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
-
- result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
- }
- return result;
- }
-
- g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
- return NULL;
-}
-
-void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb;
- int i, j, onum;
- MonoReflectionMethod *m;
-
- mono_error_init (error);
- *overrides = NULL;
- *num_overrides = 0;
-
- g_assert (image_is_dynamic (klass->image));
-
- if (!mono_class_get_ref_info (klass))
- return;
-
- g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
-
- tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
-
- onum = 0;
- if (tb->methods) {
- for (i = 0; i < tb->num_methods; ++i) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (mb->override_methods)
- onum += mono_array_length (mb->override_methods);
+ info->name_space = (char *)"";
+ info->name = start;
}
}
+ while (*p) {
+ switch (*p) {
+ case '&':
+ if (isbyref) /* only one level allowed by the spec */
+ return 0;
+ isbyref = 1;
+ isptr = 0;
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
+ *p++ = 0;
+ break;
+ case '*':
+ if (isbyref) /* pointer to ref not okay */
+ return 0;
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
+ isptr = 1;
+ *p++ = 0;
+ break;
+ case '[':
+ if (isbyref) /* array of ref and generic ref are not okay */
+ return 0;
+ //Decide if it's an array of a generic argument list
+ *p++ = 0;
- if (onum) {
- *overrides = g_new0 (MonoMethod*, onum * 2);
-
- onum = 0;
- for (i = 0; i < tb->num_methods; ++i) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (mb->override_methods) {
- for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
- m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
-
- (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
- return_if_nok (error);
- (*overrides) [onum * 2 + 1] = mb->mhandle;
-
- g_assert (mb->mhandle);
-
- onum ++;
+ if (!*p) //XXX test
+ return 0;
+ if (*p == ',' || *p == '*' || *p == ']') { //array
+ isptr = 0;
+ rank = 1;
+ while (*p) {
+ if (*p == ']')
+ break;
+ if (*p == ',')
+ rank++;
+ else if (*p == '*') /* '*' means unknown lower bound */
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
+ else
+ return 0;
+ ++p;
}
- }
- }
- }
-
- *num_overrides = onum;
-}
-
-static void
-typebuilder_setup_fields (MonoClass *klass, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- MonoReflectionFieldBuilder *fb;
- MonoClassField *field;
- MonoImage *image = klass->image;
- const char *p, *p2;
- int i;
- guint32 len, idx, real_size = 0;
-
- klass->field.count = tb->num_fields;
- klass->field.first = 0;
-
- mono_error_init (error);
-
- if (tb->class_size) {
- if ((tb->packing_size & 0xffffff00) != 0) {
- char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
- return;
- }
- klass->packing_size = tb->packing_size;
- real_size = klass->instance_size + tb->class_size;
- }
-
- if (!klass->field.count) {
- klass->instance_size = MAX (klass->instance_size, real_size);
- return;
- }
-
- klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
- mono_class_alloc_ext (klass);
- klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
- /*
- This is, guess what, a hack.
- The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
- On the static path no field class is resolved, only types are built. This is the right thing to do
- but we suck.
- Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
- */
- klass->size_inited = 1;
-
- for (i = 0; i < klass->field.count; ++i) {
- MonoArray *rva_data;
- fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
- field = &klass->fields [i];
- field->name = mono_string_to_utf8_image (image, fb->name, error);
- if (!mono_error_ok (error))
- return;
- if (fb->attrs) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_if_nok (error);
- field->type = mono_metadata_type_dup (klass->image, type);
- field->type->attrs = fb->attrs;
- } else {
- field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
- return_if_nok (error);
- }
-
- if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
- char *base = mono_array_addr (rva_data, char, 0);
- size_t size = mono_array_length (rva_data);
- char *data = (char *)mono_image_alloc (klass->image, size);
- memcpy (data, base, size);
- klass->ext->field_def_values [i].data = data;
- }
- if (fb->offset != -1)
- field->offset = fb->offset;
- field->parent = klass;
- fb->handle = field;
- mono_save_custom_attrs (klass->image, field, fb->cattrs);
-
- if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
- }
- if (fb->def_value) {
- MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
- field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
- idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
- /* Copy the data from the blob since it might get realloc-ed */
- p = assembly->blob.data + idx;
- len = mono_metadata_decode_blob_size (p, &p2);
- len += p2 - p;
- klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
- memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
- }
- }
-
- klass->instance_size = MAX (klass->instance_size, real_size);
- mono_class_layout_fields (klass, klass->instance_size);
-}
-
-static void
-typebuilder_setup_properties (MonoClass *klass, MonoError *error)
-{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- MonoReflectionPropertyBuilder *pb;
- MonoImage *image = klass->image;
- MonoProperty *properties;
- int i;
+ if (*p++ != ']')
+ return 0;
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
+ } else {
+ if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
+ return 0;
+ isptr = 0;
+ info->type_arguments = g_ptr_array_new ();
+ while (*p) {
+ MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
+ gboolean fqname = FALSE;
- mono_error_init (error);
+ g_ptr_array_add (info->type_arguments, subinfo);
- if (!klass->ext)
- klass->ext = image_g_new0 (image, MonoClassExt, 1);
+ while (*p == ' ') p++;
+ if (*p == '[') {
+ p++;
+ fqname = TRUE;
+ }
- klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
- klass->ext->property.first = 0;
+ if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
+ return 0;
- properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
- klass->ext->properties = properties;
- for (i = 0; i < klass->ext->property.count; ++i) {
- pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
- properties [i].parent = klass;
- properties [i].attrs = pb->attrs;
- properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
- if (!mono_error_ok (error))
- return;
- if (pb->get_method)
- properties [i].get = pb->get_method->mhandle;
- if (pb->set_method)
- properties [i].set = pb->set_method->mhandle;
-
- mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
- if (pb->def_value) {
- guint32 len, idx;
- const char *p, *p2;
- MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
- if (!klass->ext->prop_def_values)
- klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
- properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
- idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
- /* Copy the data from the blob since it might get realloc-ed */
- p = assembly->blob.data + idx;
- len = mono_metadata_decode_blob_size (p, &p2);
- len += p2 - p;
- klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
- memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
- }
- }
-}
+ /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
+ if (fqname && (*p != ']')) {
+ char *aname;
-static MonoReflectionEvent *
-reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
-{
- mono_error_init (error);
+ if (*p != ',')
+ return 0;
+ *p++ = 0;
- MonoEvent *event = g_new0 (MonoEvent, 1);
- MonoClass *klass;
+ aname = p;
+ while (*p && (*p != ']'))
+ p++;
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- if (!is_ok (error)) {
- g_free (event);
- return NULL;
- }
- klass = mono_class_from_mono_type (type);
+ if (*p != ']')
+ return 0;
- event->parent = klass;
- event->attrs = eb->attrs;
- event->name = mono_string_to_utf8_checked (eb->name, error);
- if (!is_ok (error)) {
- g_free (event);
- return NULL;
- }
- if (eb->add_method)
- event->add = eb->add_method->mhandle;
- if (eb->remove_method)
- event->remove = eb->remove_method->mhandle;
- if (eb->raise_method)
- event->raise = eb->raise_method->mhandle;
-
-#ifndef MONO_SMALL_CONFIG
- if (eb->other_methods) {
- int j;
- event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
- for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (eb->other_methods,
- MonoReflectionMethodBuilder*, j);
- event->other [j] = mb->mhandle;
+ *p++ = 0;
+ while (*aname) {
+ if (g_ascii_isspace (*aname)) {
+ ++aname;
+ continue;
+ }
+ break;
+ }
+ if (!*aname ||
+ !assembly_name_to_aname (&subinfo->assembly, aname))
+ return 0;
+ } else if (fqname && (*p == ']')) {
+ *p++ = 0;
+ }
+ if (*p == ']') {
+ *p++ = 0;
+ break;
+ } else if (!*p) {
+ return 0;
+ }
+ *p++ = 0;
+ }
+ }
+ break;
+ case ']':
+ if (is_recursed)
+ goto end;
+ return 0;
+ case ',':
+ if (is_recursed)
+ goto end;
+ *p++ = 0;
+ while (*p) {
+ if (g_ascii_isspace (*p)) {
+ ++p;
+ continue;
+ }
+ break;
+ }
+ if (!*p)
+ return 0; /* missing assembly name */
+ if (!assembly_name_to_aname (&info->assembly, p))
+ return 0;
+ break;
+ default:
+ return 0;
}
+ if (info->assembly.name)
+ break;
}
-#endif
-
- MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
- if (!is_ok (error)) {
-#ifndef MONO_SMALL_CONFIG
- g_free (event->other);
-#endif
- g_free (event);
- return NULL;
- }
- return ev_obj;
+ // *w = 0; /* terminate class name */
+ end:
+ if (!info->name || !*info->name)
+ return 0;
+ if (endptr)
+ *endptr = p;
+ /* add other consistency checks */
+ return 1;
}
-MonoReflectionEvent *
-mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
-{
- MonoError error;
- MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-static void
-typebuilder_setup_events (MonoClass *klass, MonoError *error)
+/**
+ * mono_identifier_unescape_type_name_chars:
+ * @identifier: the display name of a mono type
+ *
+ * Returns:
+ * The name in internal form, that is without escaping backslashes.
+ *
+ * The string is modified in place!
+ */
+char*
+mono_identifier_unescape_type_name_chars(char* identifier)
{
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
- MonoReflectionEventBuilder *eb;
- MonoImage *image = klass->image;
- MonoEvent *events;
- int i;
-
- mono_error_init (error);
-
- if (!klass->ext)
- klass->ext = image_g_new0 (image, MonoClassExt, 1);
-
- klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
- klass->ext->event.first = 0;
-
- events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
- klass->ext->events = events;
- for (i = 0; i < klass->ext->event.count; ++i) {
- eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
- events [i].parent = klass;
- events [i].attrs = eb->attrs;
- events [i].name = mono_string_to_utf8_image (image, eb->name, error);
- if (!mono_error_ok (error))
- return;
- if (eb->add_method)
- events [i].add = eb->add_method->mhandle;
- if (eb->remove_method)
- events [i].remove = eb->remove_method->mhandle;
- if (eb->raise_method)
- events [i].raise = eb->raise_method->mhandle;
-
-#ifndef MONO_SMALL_CONFIG
- if (eb->other_methods) {
- int j;
- events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
- for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
- MonoReflectionMethodBuilder *mb =
- mono_array_get (eb->other_methods,
- MonoReflectionMethodBuilder*, j);
- events [i].other [j] = mb->mhandle;
- }
+ char *w, *r;
+ if (!identifier)
+ return NULL;
+ for (w = r = identifier; *r != 0; r++)
+ {
+ char c = *r;
+ if (c == '\\') {
+ r++;
+ if (*r == 0)
+ break;
+ c = *r;
}
-#endif
- mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
+ *w = c;
+ w++;
}
+ if (w != r)
+ *w = 0;
+ return identifier;
}
-struct remove_instantiations_user_data
-{
- MonoClass *klass;
- MonoError *error;
-};
+void
+mono_identifier_unescape_info (MonoTypeNameParse* info);
-static gboolean
-remove_instantiations_of_and_ensure_contents (gpointer key,
- gpointer value,
- gpointer user_data)
+static void
+unescape_each_type_argument(void* data, void* user_data)
{
- struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
- MonoType *type = (MonoType*)key;
- MonoClass *klass = data->klass;
- gboolean already_failed = !is_ok (data->error);
- MonoError lerror;
- MonoError *error = already_failed ? &lerror : data->error;
-
- if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
- MonoClass *inst_klass = mono_class_from_mono_type (type);
- //Ensure it's safe to use it.
- if (!fix_partial_generic_class (inst_klass, error)) {
- mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- // Marked the class with failure, but since some other instantiation already failed,
- // just report that one, and swallow the error from this one.
- if (already_failed)
- mono_error_cleanup (error);
- }
- return TRUE;
- } else
- return FALSE;
+ MonoTypeNameParse* info = (MonoTypeNameParse*)data;
+ mono_identifier_unescape_info (info);
}
static void
-check_array_for_usertypes (MonoArray *arr, MonoError *error)
+unescape_each_nested_name (void* data, void* user_data)
{
- mono_error_init (error);
- int i;
+ char* nested_name = (char*) data;
+ mono_identifier_unescape_type_name_chars(nested_name);
+}
- if (!arr)
+/**
+ * mono_identifier_unescape_info:
+ *
+ * @info: a parsed display form of an (optionally assembly qualified) full type name.
+ *
+ * Returns: nothing.
+ *
+ * Destructively updates the info by unescaping the identifiers that
+ * comprise the type namespace, name, nested types (if any) and
+ * generic type arguments (if any).
+ *
+ * The resulting info has the names in internal form.
+ *
+ */
+void
+mono_identifier_unescape_info (MonoTypeNameParse *info)
+{
+ if (!info)
return;
-
- for (i = 0; i < mono_array_length (arr); ++i) {
- RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
- if (!mono_error_ok (error))
- break;
- }
+ mono_identifier_unescape_type_name_chars(info->name_space);
+ mono_identifier_unescape_type_name_chars(info->name);
+ // but don't escape info->assembly
+ if (info->type_arguments)
+ g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
+ if (info->nested)
+ g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
}
-MonoReflectionType*
-mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
+int
+mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
{
- MonoError error;
- MonoClass *klass;
- MonoDomain* domain;
- MonoReflectionType* res;
- int i, j;
-
- mono_error_init (&error);
-
- domain = mono_object_domain (tb);
- klass = mono_class_from_mono_type (tb->type.type);
-
- /*
- * Check for user defined Type subclasses.
- */
- RESOLVE_TYPE (tb->parent, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (tb->interfaces, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (tb->fields) {
- for (i = 0; i < mono_array_length (tb->fields); ++i) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
- if (fb) {
- RESOLVE_TYPE (fb->type, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (fb->modreq, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (fb->modopt, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
- RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- }
- }
- }
- if (tb->methods) {
- for (i = 0; i < mono_array_length (tb->methods); ++i) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
- if (mb) {
- RESOLVE_TYPE (mb->rtype, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (mb->return_modreq, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (mb->return_modopt, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- check_array_for_usertypes (mb->parameters, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (mb->param_modreq)
- for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- if (mb->param_modopt)
- for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- }
- }
- }
- if (tb->ctors) {
- for (i = 0; i < mono_array_length (tb->ctors); ++i) {
- MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
- if (mb) {
- check_array_for_usertypes (mb->parameters, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- if (mb->param_modreq)
- for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- if (mb->param_modopt)
- for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
- check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
- if (!is_ok (&error))
- goto failure_unlocked;
- }
- }
- }
- }
-
- mono_save_custom_attrs (klass->image, klass, tb->cattrs);
-
- /*
- * we need to lock the domain because the lock will be taken inside
- * So, we need to keep the locking order correct.
- */
- mono_loader_lock ();
- mono_domain_lock (domain);
- if (klass->wastypebuilder) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
-
- res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
- mono_error_set_pending_exception (&error);
-
- return res;
- }
- /*
- * Fields to set in klass:
- * the various flags: delegate/unicode/contextbound etc.
- */
- klass->flags = tb->attrs;
- klass->has_cctor = 1;
-
- mono_class_setup_parent (klass, klass->parent);
- /* fool mono_class_setup_supertypes */
- klass->supertypes = NULL;
- mono_class_setup_supertypes (klass);
- mono_class_setup_mono_type (klass);
-
-#if 0
- if (!((MonoDynamicImage*)klass->image)->run) {
- if (klass->generic_container) {
- /* FIXME: The code below can't handle generic classes */
- klass->wastypebuilder = TRUE;
- mono_loader_unlock ();
- mono_domain_unlock (domain);
-
- res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
- mono_error_set_pending_exception (&error);
-
- return res;
- }
- }
-#endif
-
- /* enums are done right away */
- if (!klass->enumtype)
- if (!ensure_runtime_vtable (klass, &error))
- goto failure;
-
- if (tb->subtypes) {
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
- mono_class_alloc_ext (klass);
- MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
- if (!is_ok (&error)) goto failure;
- klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
- }
- }
-
- klass->nested_classes_inited = TRUE;
-
- /* fields and object layout */
- if (klass->parent) {
- if (!klass->parent->size_inited)
- mono_class_init (klass->parent);
- klass->instance_size = klass->parent->instance_size;
- klass->sizes.class_size = 0;
- klass->min_align = klass->parent->min_align;
- /* if the type has no fields we won't call the field_setup
- * routine which sets up klass->has_references.
- */
- klass->has_references |= klass->parent->has_references;
- } else {
- klass->instance_size = sizeof (MonoObject);
- klass->min_align = 1;
- }
-
- /* FIXME: handle packing_size and instance_size */
- typebuilder_setup_fields (klass, &error);
- if (!mono_error_ok (&error))
- goto failure;
- typebuilder_setup_properties (klass, &error);
- if (!mono_error_ok (&error))
- goto failure;
-
- typebuilder_setup_events (klass, &error);
- if (!mono_error_ok (&error))
- goto failure;
-
- klass->wastypebuilder = TRUE;
-
- /*
- * If we are a generic TypeBuilder, there might be instantiations in the type cache
- * which have type System.Reflection.MonoGenericClass, but after the type is created,
- * we want to return normal System.MonoType objects, so clear these out from the cache.
- *
- * Together with this we must ensure the contents of all instances to match the created type.
- */
- if (domain->type_hash && klass->generic_container) {
- struct remove_instantiations_user_data data;
- data.klass = klass;
- data.error = &error;
- mono_error_assert_ok (&error);
- mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
- if (!is_ok (&error))
- goto failure;
- }
-
- mono_domain_unlock (domain);
- mono_loader_unlock ();
-
- if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
- goto failure_unlocked;
- }
-
- res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
- if (!is_ok (&error))
- goto failure_unlocked;
-
- g_assert (res != (MonoReflectionType*)tb);
-
- return res;
-
-failure:
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- klass->wastypebuilder = TRUE;
- mono_domain_unlock (domain);
- mono_loader_unlock ();
-failure_unlocked:
- mono_error_set_pending_exception (&error);
- return NULL;
+ int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
+ if (ok) {
+ mono_identifier_unescape_info (info);
+ }
+ return ok;
}
-static gboolean
-reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
+static MonoType*
+_mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
{
- MonoGenericParamFull *param;
- MonoImage *image;
- MonoClass *pklass;
+ gboolean type_resolve = FALSE;
+ MonoType *type;
+ MonoImage *rootimage = image;
mono_error_init (error);
- image = &gparam->tbuilder->module->dynamic_image->image;
-
- param = mono_image_new0 (image, MonoGenericParamFull, 1);
-
- param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
- mono_error_assert_ok (error);
- param->param.num = gparam->index;
-
- if (gparam->mbuilder) {
- if (!gparam->mbuilder->generic_container) {
- MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
- return_val_if_nok (error, FALSE);
-
- MonoClass *klass = mono_class_from_mono_type (tb);
- gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
- gparam->mbuilder->generic_container->is_method = TRUE;
+ if (info->assembly.name) {
+ MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
+ if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
/*
- * Cannot set owner.method, since the MonoMethod is not created yet.
- * Set the image field instead, so type_in_image () works.
+ * This could happen in the AOT compiler case when the search hook is not
+ * installed.
*/
- gparam->mbuilder->generic_container->is_anonymous = TRUE;
- gparam->mbuilder->generic_container->owner.image = klass->image;
- }
- param->param.owner = gparam->mbuilder->generic_container;
- } else if (gparam->tbuilder) {
- if (!gparam->tbuilder->generic_container) {
- MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
- return_val_if_nok (error, FALSE);
- MonoClass *klass = mono_class_from_mono_type (tb);
- gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
- gparam->tbuilder->generic_container->owner.klass = klass;
+ assembly = image->assembly;
+ if (!assembly) {
+ /* then we must load the assembly ourselve - see #60439 */
+ assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
+ if (!assembly)
+ return NULL;
}
- param->param.owner = gparam->tbuilder->generic_container;
+ image = assembly->image;
+ } else if (!image) {
+ image = mono_defaults.corlib;
}
- pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
-
- gparam->type.type = &pklass->byval_arg;
-
- mono_class_set_ref_info (pklass, gparam);
- mono_image_append_class_to_reflection_info_set (pklass);
+ type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
+ if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
+ /* ignore the error and try again */
+ mono_error_cleanup (error);
+ mono_error_init (error);
+ image = mono_defaults.corlib;
+ type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
+ }
- return TRUE;
+ return type;
}
-void
-mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+/**
+ * mono_reflection_get_type_internal:
+ *
+ * Returns: may return NULL on success, sets error on failure.
+ */
+static MonoType*
+mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
{
- MonoError error;
- (void) reflection_initialize_generic_parameter (gparam, &error);
- mono_error_set_pending_exception (&error);
-}
+ MonoClass *klass;
+ GList *mod;
+ int modval;
+ gboolean bounded = FALSE;
+
+ mono_error_init (error);
+ if (!image)
+ image = mono_defaults.corlib;
+ if (!rootimage)
+ rootimage = mono_defaults.corlib;
-static MonoArray *
-reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
-{
- MonoReflectionModuleBuilder *module = sig->module;
- MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
- guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
- guint32 buflen, i;
- MonoArray *result;
- SigBuffer buf;
+ if (ignorecase)
+ klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
+ else
+ klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
- mono_error_init (error);
+ if (!klass)
+ return NULL;
- check_array_for_usertypes (sig->arguments, error);
- return_val_if_nok (error, NULL);
+ for (mod = info->nested; mod; mod = mod->next) {
+ gpointer iter = NULL;
+ MonoClass *parent;
+
+ parent = klass;
+ mono_class_init (parent);
+
+ while ((klass = mono_class_get_nested_types (parent, &iter))) {
+ char *lastp;
+ char *nested_name, *nested_nspace;
+ gboolean match = TRUE;
+
+ lastp = strrchr ((const char *)mod->data, '.');
+ if (lastp) {
+ /* Nested classes can have namespaces */
+ int nspace_len;
- sigbuffer_init (&buf, 32);
+ nested_name = g_strdup (lastp + 1);
+ nspace_len = lastp - (char*)mod->data;
+ nested_nspace = (char *)g_malloc (nspace_len + 1);
+ memcpy (nested_nspace, mod->data, nspace_len);
+ nested_nspace [nspace_len] = '\0';
+
+ } else {
+ nested_name = (char *)mod->data;
+ nested_nspace = NULL;
+ }
- sigbuffer_add_value (&buf, 0x07);
- sigbuffer_add_value (&buf, na);
- if (assembly != NULL){
- for (i = 0; i < na; ++i) {
- MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
- encode_reflection_type (assembly, type, &buf, error);
- if (!is_ok (error)) goto fail;
+ if (nested_nspace) {
+ if (ignorecase) {
+ if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
+ match = FALSE;
+ } else {
+ if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
+ match = FALSE;
+ }
+ }
+ if (match) {
+ if (ignorecase) {
+ if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
+ match = FALSE;
+ } else {
+ if (strcmp (klass->name, nested_name) != 0)
+ match = FALSE;
+ }
+ }
+ if (lastp) {
+ g_free (nested_name);
+ g_free (nested_nspace);
+ }
+ if (match)
+ break;
}
+
+ if (!klass)
+ break;
}
+ if (!klass)
+ return NULL;
- buflen = buf.p - buf.buf;
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
- if (!is_ok (error)) goto fail;
- memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
- sigbuffer_free (&buf);
- return result;
-fail:
- sigbuffer_free (&buf);
- return NULL;
-}
+ if (info->type_arguments) {
+ MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
+ MonoReflectionType *the_type;
+ MonoType *instance;
+ int i;
-MonoArray *
-mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
-{
- MonoError error;
- MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
+ for (i = 0; i < info->type_arguments->len; i++) {
+ MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
-static MonoArray *
-reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
-{
- MonoDynamicImage *assembly = sig->module->dynamic_image;
- guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
- guint32 buflen, i;
- MonoArray *result;
- SigBuffer buf;
+ type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
+ if (!type_args [i]) {
+ g_free (type_args);
+ return NULL;
+ }
+ }
- mono_error_init (error);
+ the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
+ if (!the_type)
+ return NULL;
- check_array_for_usertypes (sig->arguments, error);
- return_val_if_nok (error, NULL);
+ instance = mono_reflection_bind_generic_parameters (
+ the_type, info->type_arguments->len, type_args, error);
- sigbuffer_init (&buf, 32);
+ g_free (type_args);
+ if (!instance)
+ return NULL;
- sigbuffer_add_value (&buf, 0x06);
- for (i = 0; i < na; ++i) {
- MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
- encode_reflection_type (assembly, type, &buf, error);
- if (!is_ok (error))
- goto fail;
+ klass = mono_class_from_mono_type (instance);
}
- buflen = buf.p - buf.buf;
- result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
- if (!is_ok (error)) goto fail;
- memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
- sigbuffer_free (&buf);
+ for (mod = info->modifiers; mod; mod = mod->next) {
+ modval = GPOINTER_TO_UINT (mod->data);
+ if (!modval) { /* byref: must be last modifier */
+ return &klass->this_arg;
+ } else if (modval == -1) {
+ klass = mono_ptr_class_get (&klass->byval_arg);
+ } else if (modval == -2) {
+ bounded = TRUE;
+ } else { /* array rank */
+ klass = mono_bounded_array_class_get (klass, modval, bounded);
+ }
+ }
- return result;
-fail:
- sigbuffer_free (&buf);
- return NULL;
+ return &klass->byval_arg;
}
-MonoArray *
-mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
-{
+/*
+ * mono_reflection_get_type:
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ * @type_resolve: whenever type resolve was already tried
+ *
+ * Build a MonoType from the type description in @info.
+ *
+ */
+
+MonoType*
+mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
MonoError error;
- MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
- mono_error_set_pending_exception (&error);
+ MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
+ mono_error_cleanup (&error);
return result;
}
-typedef struct {
- MonoMethod *handle;
- MonoDomain *domain;
-} DynamicMethodReleaseData;
+/**
+ * mono_reflection_get_type_checked:
+ * @rootimage: the image of the currently active managed caller
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ * @type_resolve: whenever type resolve was already tried
+ * @error: set on error.
+ *
+ * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
+ *
+ */
+MonoType*
+mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
+ mono_error_init (error);
+ return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
+}
-/*
- * The runtime automatically clean up those after finalization.
-*/
-static MonoReferenceQueue *dynamic_method_queue;
-static void
-free_dynamic_method (void *dynamic_method)
+static MonoType*
+mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
{
- DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
- MonoDomain *domain = data->domain;
- MonoMethod *method = data->handle;
- guint32 dis_link;
+ MonoReflectionAssemblyBuilder *abuilder;
+ MonoType *type;
+ int i;
- mono_domain_lock (domain);
- dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
- g_hash_table_remove (domain->method_to_dyn_method, method);
- mono_domain_unlock (domain);
- g_assert (dis_link);
- mono_gchandle_free (dis_link);
+ mono_error_init (error);
+ g_assert (assembly_is_dynamic (assembly));
+ abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
+ if (!abuilder)
+ return NULL;
- mono_runtime_free_method (domain, method);
- g_free (data);
-}
+ /* Enumerate all modules */
+
+ type = NULL;
+ if (abuilder->modules) {
+ for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
+ MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
+ type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
+ if (type)
+ break;
+ if (!mono_error_ok (error))
+ return NULL;
+ }
+ }
+
+ if (!type && abuilder->loaded_modules) {
+ for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
+ MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
+ type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
+ if (type)
+ break;
+ if (!mono_error_ok (error))
+ return NULL;
+ }
+ }
-static gboolean
-reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
+ return type;
+}
+
+MonoType*
+mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
{
- MonoReferenceQueue *queue;
- MonoMethod *handle;
- DynamicMethodReleaseData *release_data;
- ReflectionMethodBuilder rmb;
- MonoMethodSignature *sig;
- MonoClass *klass;
- MonoDomain *domain;
- GSList *l;
- int i;
+ MonoType *type;
+ MonoReflectionAssembly *assembly;
+ GString *fullName;
+ GList *mod;
mono_error_init (error);
- if (mono_runtime_is_shutting_down ()) {
- mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
- return FALSE;
+ if (image && image_is_dynamic (image))
+ type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
+ else {
+ type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
}
+ return_val_if_nok (error, NULL);
- if (!(queue = dynamic_method_queue)) {
- mono_loader_lock ();
- if (!(queue = dynamic_method_queue))
- queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
- mono_loader_unlock ();
+ if (type)
+ return type;
+ if (!mono_domain_has_type_resolve (mono_domain_get ()))
+ return NULL;
+
+ if (type_resolve) {
+ if (*type_resolve)
+ return NULL;
+ else
+ *type_resolve = TRUE;
}
+
+ /* Reconstruct the type name */
+ fullName = g_string_new ("");
+ if (info->name_space && (info->name_space [0] != '\0'))
+ g_string_printf (fullName, "%s.%s", info->name_space, info->name);
+ else
+ g_string_printf (fullName, "%s", info->name);
+ for (mod = info->nested; mod; mod = mod->next)
+ g_string_append_printf (fullName, "+%s", (char*)mod->data);
- sig = dynamic_method_to_signature (mb, error);
- return_val_if_nok (error, FALSE);
+ assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
+ if (!is_ok (error)) {
+ g_string_free (fullName, TRUE);
+ return NULL;
+ }
- reflection_methodbuilder_from_dynamic_method (&rmb, mb);
+ if (assembly) {
+ if (assembly_is_dynamic (assembly->assembly))
+ type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
+ info, ignorecase, error);
+ else
+ type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
+ info, ignorecase, error);
+ }
+ g_string_free (fullName, TRUE);
+ return_val_if_nok (error, NULL);
+ return type;
+}
- /*
- * Resolve references.
- */
- /*
- * Every second entry in the refs array is reserved for storing handle_class,
- * which is needed by the ldtoken implementation in the JIT.
- */
- rmb.nrefs = mb->nrefs;
- rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
- for (i = 0; i < mb->nrefs; i += 2) {
- MonoClass *handle_class;
- gpointer ref;
- MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
-
- if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
- MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
- /*
- * The referenced DynamicMethod should already be created by the managed
- * code, except in the case of circular references. In that case, we store
- * method in the refs array, and fix it up later when the referenced
- * DynamicMethod is created.
- */
- if (method->mhandle) {
- ref = method->mhandle;
- } else {
- /* FIXME: GC object stored in unmanaged memory */
- ref = method;
+void
+mono_reflection_free_type_info (MonoTypeNameParse *info)
+{
+ g_list_free (info->modifiers);
+ g_list_free (info->nested);
- /* FIXME: GC object stored in unmanaged memory */
- method->referenced_by = g_slist_append (method->referenced_by, mb);
- }
- handle_class = mono_defaults.methodhandle_class;
- } else {
- MonoException *ex = NULL;
- ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
- if (!is_ok (error)) {
- g_free (rmb.refs);
- return FALSE;
- }
- if (!ref)
- ex = mono_get_exception_type_load (NULL, NULL);
- else if (mono_security_core_clr_enabled ())
- ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
-
- if (ex) {
- g_free (rmb.refs);
- mono_error_set_exception_instance (error, ex);
- return FALSE;
- }
- }
+ if (info->type_arguments) {
+ int i;
- rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
- rmb.refs [i + 1] = handle_class;
- }
+ for (i = 0; i < info->type_arguments->len; i++) {
+ MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
- if (mb->owner) {
- MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
- if (!is_ok (error)) {
- g_free (rmb.refs);
- return FALSE;
+ mono_reflection_free_type_info (subinfo);
+ /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
+ g_free (subinfo);
}
- klass = mono_class_from_mono_type (owner_type);
- } else {
- klass = mono_defaults.object_class;
- }
-
- mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- g_free (rmb.refs);
- return_val_if_nok (error, FALSE);
-
- release_data = g_new (DynamicMethodReleaseData, 1);
- release_data->handle = handle;
- release_data->domain = mono_object_get_domain ((MonoObject*)mb);
- if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
- g_free (release_data);
-
- /* Fix up refs entries pointing at us */
- for (l = mb->referenced_by; l; l = l->next) {
- MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
- MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
- gpointer *data;
-
- g_assert (method->mhandle);
- data = (gpointer*)wrapper->method_data;
- for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
- if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
- data [i + 1] = mb->mhandle;
- }
+ g_ptr_array_free (info->type_arguments, TRUE);
}
- g_slist_free (mb->referenced_by);
-
- /* ilgen is no longer needed */
- mb->ilgen = NULL;
-
- domain = mono_domain_get ();
- mono_domain_lock (domain);
- if (!domain->method_to_dyn_method)
- domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
- g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
- mono_domain_unlock (domain);
-
- return TRUE;
-}
-
-void
-mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
-{
- MonoError error;
- (void) reflection_create_dynamic_method (mb, &error);
- mono_error_set_pending_exception (&error);
}
-#endif /* DISABLE_REFLECTION_EMIT */
-
-/**
- *
- * mono_reflection_is_valid_dynamic_token:
- *
- * Returns TRUE if token is valid.
+/*
+ * mono_reflection_type_from_name:
+ * @name: type name.
+ * @image: a metadata context (can be NULL).
+ *
+ * Retrieves a MonoType from its @name. If the name is not fully qualified,
+ * it defaults to get the type from @image or, if @image is NULL or loading
+ * from it fails, uses corlib.
*
*/
-gboolean
-mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
-{
- return lookup_dyn_token (image, token) != NULL;
-}
-
-MonoMethodSignature *
-mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
+MonoType*
+mono_reflection_type_from_name (char *name, MonoImage *image)
{
- MonoMethodSignature *sig;
- g_assert (image_is_dynamic (image));
-
- mono_error_init (error);
-
- sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
- if (sig)
- return sig;
-
- return mono_method_signature_checked (method, error);
+ MonoError error;
+ MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
+ mono_error_cleanup (&error);
+ return result;
}
-#ifndef DISABLE_REFLECTION_EMIT
-
/**
- * mono_reflection_lookup_dynamic_token:
- *
- * Finish the Builder object pointed to by TOKEN and return the corresponding
- * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
- * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
- * mapping table.
+ * mono_reflection_type_from_name_checked:
+ * @name: type name.
+ * @image: a metadata context (can be NULL).
+ * @error: set on errror.
*
- * LOCKING: Take the loader lock
+ * Retrieves a MonoType from its @name. If the name is not fully qualified,
+ * it defaults to get the type from @image or, if @image is NULL or loading
+ * from it fails, uses corlib. On failure returns NULL and sets @error.
+ *
*/
-gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
+MonoType*
+mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
{
- MonoDynamicImage *assembly = (MonoDynamicImage*)image;
- MonoObject *obj;
- MonoClass *klass;
+ MonoType *type = NULL;
+ MonoTypeNameParse info;
+ char *tmp;
mono_error_init (error);
+ /* Make a copy since parse_type modifies its argument */
+ tmp = g_strdup (name);
- obj = lookup_dyn_token (assembly, token);
- if (!obj) {
- if (valid_token)
- g_error ("Could not find required dynamic token 0x%08x", token);
- else {
- mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
+ /*g_print ("requested type %s\n", str);*/
+ if (mono_reflection_parse_type (tmp, &info)) {
+ type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
+ if (!is_ok (error)) {
+ g_free (tmp);
+ mono_reflection_free_type_info (&info);
return NULL;
}
}
- if (!handle_class)
- handle_class = &klass;
- gpointer result = resolve_object (image, obj, handle_class, context, error);
- return result;
+ g_free (tmp);
+ mono_reflection_free_type_info (&info);
+ return type;
}
/*
- * ensure_complete_type:
+ * mono_reflection_get_token:
*
- * Ensure that KLASS is completed if it is a dynamic type, or references
- * dynamic types.
+ * Return the metadata token of OBJ which should be an object
+ * representing a metadata element.
*/
-static void
-ensure_complete_type (MonoClass *klass, MonoError *error)
+guint32
+mono_reflection_get_token (MonoObject *obj)
{
- mono_error_init (error);
-
- if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
-
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_if_nok (error);
-
- // Asserting here could break a lot of code
- //g_assert (klass->wastypebuilder);
- }
-
- if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
- int i;
-
- for (i = 0; i < inst->type_argc; ++i) {
- ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
- return_if_nok (error);
- }
- }
+ MonoError error;
+ guint32 result = mono_reflection_get_token_checked (obj, &error);
+ mono_error_assert_ok (&error);
+ return result;
}
-static gpointer
-resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
+/**
+ * mono_reflection_get_token_checked:
+ * @obj: the object
+ * @error: set on error
+ *
+ * Return the metadata token of @obj which should be an object
+ * representing a metadata element. On failure sets @error.
+ */
+guint32
+mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
{
- gpointer result = NULL;
+ MonoClass *klass;
+ guint32 token = 0;
mono_error_init (error);
- if (strcmp (obj->vtable->klass->name, "String") == 0) {
- result = mono_string_intern_checked ((MonoString*)obj, error);
- return_val_if_nok (error, NULL);
- *handle_class = mono_defaults.string_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, NULL);
- MonoClass *mc = mono_class_from_mono_type (type);
- if (!mono_class_init (mc)) {
- mono_error_set_for_class_failure (error, mc);
- return NULL;
- }
-
- if (context) {
- MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
-
- result = mono_class_from_mono_type (inflated);
- mono_metadata_free_type (inflated);
- } else {
- result = mono_class_from_mono_type (type);
- }
- *handle_class = mono_defaults.typehandle_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
- strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
- strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
- strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
- result = ((MonoReflectionMethod*)obj)->method;
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
- }
- *handle_class = mono_defaults.methodhandle_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
- MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
- result = mb->mhandle;
- if (!result) {
- /* Type is not yet created */
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
-
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
-
- /*
- * Hopefully this has been filled in by calling CreateType() on the
- * TypeBuilder.
- */
- /*
- * TODO: This won't work if the application finishes another
- * TypeBuilder instance instead of this one.
- */
- result = mb->mhandle;
- }
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
- }
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
- MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
-
- result = cb->mhandle;
- if (!result) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
-
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
- result = cb->mhandle;
- }
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
- }
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
- MonoClassField *field = ((MonoReflectionField*)obj)->field;
-
- ensure_complete_type (field->parent, error);
- return_val_if_nok (error, NULL);
-
- if (context) {
- MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
- return_val_if_nok (error, NULL);
-
- MonoClass *klass = mono_class_from_mono_type (inflated);
- MonoClassField *inflated_field;
- gpointer iter = NULL;
- mono_metadata_free_type (inflated);
- while ((inflated_field = mono_class_get_fields (klass, &iter))) {
- if (!strcmp (field->name, inflated_field->name))
- break;
- }
- g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
- result = inflated_field;
- } else {
- result = field;
- }
- *handle_class = mono_defaults.fieldhandle_class;
- g_assert (result);
- } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
- result = fb->handle;
-
- if (!result) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
-
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
- result = fb->handle;
- }
-
- if (fb->handle && fb->handle->parent->generic_container) {
- MonoClass *klass = fb->handle->parent;
- MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
- return_val_if_nok (error, NULL);
-
- MonoClass *inflated = mono_class_from_mono_type (type);
-
- result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
- g_assert (result);
- mono_metadata_free_type (type);
- }
- *handle_class = mono_defaults.fieldhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
- return_val_if_nok (error, NULL);
- MonoClass *klass;
-
- klass = type->data.klass;
- if (klass->wastypebuilder) {
- /* Already created */
- result = klass;
- }
- else {
- mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
- return_val_if_nok (error, NULL);
- result = type->data.klass;
- g_assert (result);
- }
- *handle_class = mono_defaults.typehandle_class;
- } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
- MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
- MonoMethodSignature *sig;
- int nargs, i;
-
- if (helper->arguments)
- nargs = mono_array_length (helper->arguments);
- else
- nargs = 0;
-
- sig = mono_metadata_signature_alloc (image, nargs);
- sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
- sig->hasthis = helper->call_conv & 32 ? 1 : 0;
-
- if (helper->unmanaged_call_conv) { /* unmanaged */
- sig->call_convention = helper->unmanaged_call_conv - 1;
- sig->pinvoke = TRUE;
- } else if (helper->call_conv & 0x02) {
- sig->call_convention = MONO_CALL_VARARG;
- } else {
- sig->call_convention = MONO_CALL_DEFAULT;
- }
-
- sig->param_count = nargs;
- /* TODO: Copy type ? */
- sig->ret = helper->return_type->type;
- for (i = 0; i < nargs; ++i) {
- sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
- if (!is_ok (error)) {
- image_g_free (image, sig);
- return NULL;
- }
- }
-
- result = sig;
- *handle_class = NULL;
- } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
- MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
- /* Already created by the managed code */
- g_assert (method->mhandle);
- result = method->mhandle;
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, NULL);
- type = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
-
- result = mono_class_from_mono_type (type);
- *handle_class = mono_defaults.typehandle_class;
- g_assert (result);
- mono_metadata_free_type (type);
- } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
- MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
- return_val_if_nok (error, NULL);
- type = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
-
- result = mono_class_from_mono_type (type);
- *handle_class = mono_defaults.typehandle_class;
- g_assert (result);
- mono_metadata_free_type (type);
- } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
- MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
- MonoClass *inflated;
- MonoType *type;
- MonoClassField *field;
-
- if (is_sre_field_builder (mono_object_class (f->fb)))
- field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
- else if (is_sr_mono_field (mono_object_class (f->fb)))
- field = ((MonoReflectionField*)f->fb)->field;
- else
- g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
-
- MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
- return_val_if_nok (error, NULL);
- type = mono_class_inflate_generic_type_checked (finst, context, error);
- return_val_if_nok (error, NULL);
-
- inflated = mono_class_from_mono_type (type);
-
- result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
- ensure_complete_type (field->parent, error);
- if (!is_ok (error)) {
- mono_metadata_free_type (type);
- return NULL;
- }
-
- g_assert (result);
- mono_metadata_free_type (type);
- *handle_class = mono_defaults.fieldhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
- MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
- MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
- return_val_if_nok (error, NULL);
- MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
- return_val_if_nok (error, NULL);
+ klass = obj->vtable->klass;
- MonoClass *inflated_klass = mono_class_from_mono_type (type);
- MonoMethod *method;
+ if (strcmp (klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
- if (is_sre_ctor_builder (mono_object_class (c->cb)))
- method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
- else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
- method = ((MonoReflectionMethod *)c->cb)->method;
- else
- g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
-
- result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
- *handle_class = mono_defaults.methodhandle_class;
- mono_metadata_free_type (type);
- } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
- MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
- if (m->method_args) {
- result = mono_reflection_method_on_tb_inst_get_handle (m, error);
- return_val_if_nok (error, NULL);
- if (context) {
- result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
- mono_error_assert_ok (error);
- }
- } else {
- MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
- return_val_if_nok (error, NULL);
- MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
- return_val_if_nok (error, NULL);
-
- MonoClass *inflated_klass = mono_class_from_mono_type (type);
- MonoMethod *method;
-
- if (is_sre_method_builder (mono_object_class (m->mb)))
- method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
- else if (is_sr_mono_method (mono_object_class (m->mb)))
- method = ((MonoReflectionMethod *)m->mb)->method;
- else
- g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
+ MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
+
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ } else if (strcmp (klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
- result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
- mono_metadata_free_type (type);
+ token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
+ } else if (strcmp (klass->name, "TypeBuilder") == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
+ token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
+ } else if (strcmp (klass->name, "RuntimeType") == 0) {
+ MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+ return_val_if_nok (error, 0);
+ MonoClass *mc = mono_class_from_mono_type (type);
+ if (!mono_class_init (mc)) {
+ mono_error_set_for_class_failure (error, mc);
+ return 0;
}
- *handle_class = mono_defaults.methodhandle_class;
- } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
- MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
- MonoType *mtype;
- MonoClass *klass;
- MonoMethod *method;
- gpointer iter;
- char *name;
- mtype = mono_reflection_type_get_handle (m->parent, error);
- return_val_if_nok (error, NULL);
- klass = mono_class_from_mono_type (mtype);
+ token = mc->type_token;
+ } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
+ strcmp (klass->name, "MonoMethod") == 0) {
+ MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
+ if (m->method->is_inflated) {
+ MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
+ return inflated->declaring->token;
+ } else {
+ token = m->method->token;
+ }
+ } else if (strcmp (klass->name, "MonoField") == 0) {
+ MonoReflectionField *f = (MonoReflectionField*)obj;
- /* Find the method */
+ token = mono_class_get_field_token (f->field);
+ } else if (strcmp (klass->name, "MonoProperty") == 0) {
+ MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
- name = mono_string_to_utf8_checked (m->name, error);
- return_val_if_nok (error, NULL);
- iter = NULL;
- while ((method = mono_class_get_methods (klass, &iter))) {
- if (!strcmp (method->name, name))
- break;
- }
- g_free (name);
+ token = mono_class_get_property_token (p->property);
+ } else if (strcmp (klass->name, "MonoEvent") == 0) {
+ MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
- // FIXME:
- g_assert (method);
- // FIXME: Check parameters/return value etc. match
-
- result = method;
- *handle_class = mono_defaults.methodhandle_class;
- } else if (is_sre_array (mono_object_get_class(obj)) ||
- is_sre_byref (mono_object_get_class(obj)) ||
- is_sre_pointer (mono_object_get_class(obj))) {
- MonoReflectionType *ref_type = (MonoReflectionType *)obj;
- MonoType *type = mono_reflection_type_get_handle (ref_type, error);
- return_val_if_nok (error, NULL);
+ token = mono_class_get_event_token (p->event);
+ } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
+ MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
+ MonoClass *member_class = mono_object_class (p->MemberImpl);
+ g_assert (mono_class_is_reflection_method_or_constructor (member_class));
- if (context) {
- MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
- return_val_if_nok (error, NULL);
+ token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
+ } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
+ MonoReflectionModule *m = (MonoReflectionModule*)obj;
- result = mono_class_from_mono_type (inflated);
- mono_metadata_free_type (inflated);
- } else {
- result = mono_class_from_mono_type (type);
- }
- *handle_class = mono_defaults.typehandle_class;
+ token = m->token;
+ } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
+ token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
} else {
- g_print ("%s\n", obj->vtable->klass->name);
- g_assert_not_reached ();
+ mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
+ klass->name_space, klass->name);
+ return 0;
}
- return result;
+
+ return token;
}
-#else /* DISABLE_REFLECTION_EMIT */
-MonoArray*
-mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+gboolean
+mono_reflection_is_usertype (MonoReflectionType *ref)
{
- g_assert_not_reached ();
- return NULL;
+ MonoClass *klass = mono_object_class (ref);
+ return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
}
-void
-mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
+/**
+ * mono_reflection_bind_generic_parameters:
+ * @type: a managed type object (which should be some kind of generic (instance? definition?))
+ * @type_args: the number of type arguments to bind
+ * @types: array of type arguments
+ * @error: set on error
+ *
+ * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
+ * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
+ */
+MonoType*
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
{
- g_assert_not_reached ();
-}
+ MonoClass *klass;
+ gboolean is_dynamic = FALSE;
+ MonoClass *geninst;
-void
-mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
-{
- g_assert_not_reached ();
-}
+ mono_error_init (error);
+
+ mono_loader_lock ();
-gboolean
-mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
-{
- g_assert_not_reached ();
- return FALSE;
-}
+ if (mono_is_sre_type_builder (mono_object_class (type))) {
+ is_dynamic = TRUE;
+ } else if (mono_is_sre_generic_instance (mono_object_class (type))) {
+ /* Does this ever make sense? what does instantiating a generic instance even mean? */
+ g_assert_not_reached ();
+ MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
+ MonoReflectionType *gtd = rgi->generic_type;
-void
-mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
-{
- g_assert_not_reached ();
-}
+ if (mono_is_sre_type_builder (mono_object_class (gtd)))
+ is_dynamic = TRUE;
+ }
-void
-mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
-{
- g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
-}
+ MonoType *t = mono_reflection_type_get_handle (type, error);
+ if (!is_ok (error)) {
+ mono_loader_unlock ();
+ return NULL;
+ }
-void
-mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
-{
- g_assert_not_reached ();
-}
+ klass = mono_class_from_mono_type (t);
+ if (!mono_class_is_gtd (klass)) {
+ mono_loader_unlock ();
+ mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
+ return NULL;
+ }
-void
-mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
-{
- g_assert_not_reached ();
-}
+ guint gtd_type_argc = mono_class_get_generic_container (klass)->type_argc;
+ if (gtd_type_argc != type_argc) {
+ mono_loader_unlock ();
+ mono_error_set_argument (error, "types", "The generic type definition needs %d type arguments, but was instantiated with %d ", gtd_type_argc, type_argc);
+ return NULL;
+ }
-MonoReflectionModule *
-mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
-{
- g_assert_not_reached ();
- return NULL;
-}
-guint32
-mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
-{
- g_assert_not_reached ();
- return 0;
-}
+ if (klass->wastypebuilder)
+ is_dynamic = TRUE;
-guint32
-mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
-{
- g_assert_not_reached ();
- return 0;
-}
+ mono_loader_unlock ();
-guint32
-mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
- gboolean create_open_instance, gboolean register_token, MonoError *error)
-{
- g_assert_not_reached ();
- return 0;
-}
+ geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
-void
-mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
-{
+ return &geninst->byval_arg;
}
-void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+MonoClass*
+mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
{
- g_assert_not_reached ();
+ MonoGenericClass *gclass;
+ MonoGenericInst *inst;
+
+ g_assert (mono_class_is_gtd (klass));
+
+ inst = mono_metadata_get_generic_inst (type_argc, types);
+ gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
+
+ return mono_generic_class_get_class (gclass);
}
-void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
+static MonoReflectionMethod*
+reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
{
+ MonoClass *klass;
+ MonoMethod *method, *inflated;
+ MonoMethodInflated *imethod;
+ MonoGenericContext tmp_context;
+ MonoGenericInst *ginst;
+ MonoType **type_argv;
+ int count, i;
+
mono_error_init (error);
- *overrides = NULL;
- *num_overrides = 0;
-}
-MonoReflectionEvent *
-mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ g_assert (strcmp (rmethod->object.vtable->klass->name, "MethodBuilder"));
-MonoReflectionType*
-mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ method = rmethod->method;
-void
-mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
-{
- g_assert_not_reached ();
-}
+ klass = method->klass;
-MonoArray *
-mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ if (method->is_inflated)
+ method = ((MonoMethodInflated *) method)->declaring;
-MonoArray *
-mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
-{
- g_assert_not_reached ();
- return NULL;
-}
+ count = mono_method_signature (method)->generic_param_count;
+ if (count != mono_array_length (types))
+ return NULL;
-void
-mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
-{
-}
+ type_argv = g_new0 (MonoType *, count);
+ for (i = 0; i < count; i++) {
+ MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
+ type_argv [i] = mono_reflection_type_get_handle (garg, error);
+ if (!is_ok (error)) {
+ g_free (type_argv);
+ return NULL;
+ }
+ }
+ ginst = mono_metadata_get_generic_inst (count, type_argv);
+ g_free (type_argv);
-gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
-{
- mono_error_init (error);
- return NULL;
-}
+ tmp_context.class_inst = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->context.class_inst : NULL;
+ tmp_context.method_inst = ginst;
-MonoType*
-mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
-{
- mono_error_init (error);
- if (!ref)
+ inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
+ mono_error_assert_ok (error);
+ imethod = (MonoMethodInflated *) inflated;
+
+ /*FIXME but I think this is no longer necessary*/
+ if (image_is_dynamic (method->klass->image)) {
+ MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
+ /*
+ * This table maps metadata structures representing inflated methods/fields
+ * to the reflection objects representing their generic definitions.
+ */
+ mono_image_lock ((MonoImage*)image);
+ mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
+ mono_image_unlock ((MonoImage*)image);
+ }
+
+ if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
+ mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
return NULL;
- return ref->type;
+ }
+
+ return mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
}
-void
-mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
+MonoReflectionMethod*
+ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types)
{
- g_assert_not_reached ();
+ MonoError error;
+ MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
+ mono_error_set_pending_exception (&error);
+ return result;
}
-#endif /* DISABLE_REFLECTION_EMIT */
/* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
const static guint32 declsec_flags_map[] = {
guint32
mono_declsec_flags_from_class (MonoClass *klass)
{
- if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
- if (!klass->ext || !klass->ext->declsec_flags) {
+ if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_HAS_SECURITY) {
+ guint32 flags = mono_class_get_declsec_flags (klass);
+
+ if (!flags) {
guint32 idx;
idx = mono_metadata_token_index (klass->type_token);
idx <<= MONO_HAS_DECL_SECURITY_BITS;
idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
- mono_loader_lock ();
- mono_class_alloc_ext (klass);
- mono_loader_unlock ();
+ flags = mono_declsec_get_flags (klass->image, idx);
/* we cache the flags on classes */
- klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
+ mono_class_set_declsec_flags (klass, flags);
}
- return klass->ext->declsec_flags;
+ return flags;
}
return 0;
}
return refassembly->assembly;
}
+/**
+ * mono_class_from_mono_type_handle:
+ * @reftype: the System.Type handle
+ *
+ * Returns the MonoClass* corresponding to the given type.
+ */
+MonoClass*
+mono_class_from_mono_type_handle (MonoReflectionTypeHandle reftype)
+{
+ return mono_class_from_mono_type (MONO_HANDLE_RAW (reftype)->type);
+}