*
*/
#include <config.h>
+#include "mono/utils/mono-digest.h"
#include "mono/metadata/reflection.h"
#include "mono/metadata/tabledefs.h"
#include "mono/metadata/tokentype.h"
#include "mono/metadata/appdomain.h"
#include "mono/metadata/opcodes.h"
+#include "mono/metadata/assembly.h"
+#include <mono/metadata/exception.h>
#include <stdio.h>
#include <glib.h>
#include <errno.h>
#include <time.h>
#include <string.h>
+#include <ctype.h>
#include "image.h"
#include "cil-coff.h"
#include "rawbuffer.h"
#include "mono-endian.h"
#include "private.h"
-#if HAVE_BOEHM_GC
-#include <gc/gc.h>
-#endif
+#include <mono/os/gc_wrapper.h>
#define TEXT_OFFSET 512
#define CLI_H_SIZE 136
MonoObject *type;
MonoString *name;
MonoBoolean init_locals;
+ MonoMethod *mhandle;
} ReflectionMethodBuilder;
const unsigned char table_sizes [64] = {
0 /* 0x2A */
};
+/**
+ * These macros can be used to allocate long living atomic data so it won't be
+ * tracked by the garbage collector.
+ */
+#ifdef HAVE_BOEHM_GC
+#define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
+#define FREE_ATOMIC(ptr)
+#define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
+#else
+#define ALLOC_ATOMIC(size) g_malloc (size)
+#define FREE_ATOMIC(ptr) g_free (ptr)
+#define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
+#endif
+
static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
+static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
static void
{
table->rows = nrows;
g_assert (table->columns);
- table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
+ 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 = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
+ }
}
+static void
+make_room_in_stream (MonoDynamicStream *stream, int size)
+{
+ while (stream->alloc_size <= size) {
+ if (stream->alloc_size < 4096)
+ stream->alloc_size = 4096;
+ else
+ stream->alloc_size *= 2;
+ }
+ stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
+}
+
static guint32
string_heap_insert (MonoDynamicStream *sh, const char *str)
{
len = strlen (str) + 1;
idx = sh->index;
- if (idx + len > sh->alloc_size) {
- sh->alloc_size += len + 4096;
- sh->data = g_realloc (sh->data, sh->alloc_size);
- }
+ if (idx + len > sh->alloc_size)
+ make_room_in_stream (sh, idx + len);
+
/*
* 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
{
sh->index = 0;
sh->alloc_size = 4096;
- sh->data = g_malloc (4096);
+ sh->data = ALLOC_ATOMIC (4096);
sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
string_heap_insert (sh, "");
}
static void
string_heap_free (MonoDynamicStream *sh)
{
- g_free (sh->data);
+ FREE_ATOMIC (sh->data);
g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
g_hash_table_destroy (sh->hash);
}
mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
{
guint32 idx;
- if (stream->alloc_size < stream->index + len) {
- stream->alloc_size += len + 4096;
- stream->data = g_realloc (stream->data, stream->alloc_size);
- }
+ if (stream->alloc_size < stream->index + len)
+ make_room_in_stream (stream, stream->index + len);
memcpy (stream->data + stream->index, data, len);
idx = stream->index;
stream->index += len;
mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
{
guint32 idx;
- if (stream->alloc_size < stream->index + len) {
- stream->alloc_size += len + 4096;
- stream->data = g_realloc (stream->data, stream->alloc_size);
- }
+ if (stream->alloc_size < stream->index + len)
+ make_room_in_stream (stream, stream->index + len);
memset (stream->data + stream->index, 0, len);
idx = stream->index;
stream->index += len;
mono_image_add_stream_data (stream, buf, 4 - count);
}
+static int
+mono_blob_entry_hash (const char* str)
+{
+ 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) {
+ 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;
+}
+
+static guint32
+add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
+{
+ guint32 idx;
+ char *copy;
+ gpointer oldkey, oldval;
+
+ copy = ALLOC_ATOMIC (s1+s2);
+ memcpy (copy, b1, s1);
+ memcpy (copy + s1, b2, s2);
+ if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
+ FREE_ATOMIC (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);
+ mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
+ }
+ return idx;
+}
+
+/* modified version needed to handle building corlib */
+static MonoClass*
+my_mono_class_from_mono_type (MonoType *type) {
+ switch (type->type) {
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_SZARRAY:
+ return mono_class_from_mono_type (type);
+ default:
+ /* should be always valid when we reach this case... */
+ return type->data.klass;
+ }
+}
+
static void
encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
{
guint32 idx;
char blob_size [6];
char *b = blob_size;
-
+
+ if (!assembly->save)
+ return 0;
+
p = buf = g_malloc (size);
/*
* FIXME: vararg, explicit_this, differenc call_conv values...
/* store length */
g_assert (p - buf < size);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
/* store length */
g_assert (p - buf < size);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
}
g_assert (p - buf < size);
mono_metadata_encode_value (p-buf, b, &b);
- sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
return idx;
}
+static guint32
+method_count_clauses (MonoReflectionILGen *ilgen)
+{
+ 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;
+}
+
+static MonoExceptionClause*
+method_encode_clauses (MonoDynamicAssembly *assembly,
+ MonoReflectionILGen *ilgen, guint32 num_clauses)
+{
+ MonoExceptionClause *clauses;
+ MonoExceptionClause *clause;
+ MonoILExceptionInfo *ex_info;
+ MonoILExceptionBlock *ex_block;
+ guint32 finally_start;
+ int i, j, clause_index;;
+
+ clauses = g_new0 (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;
+ g_assert (ex_info->handlers);
+ 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;
+
+ 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;
+ clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
+ mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
+ if (ex_block->extype) {
+ mono_g_hash_table_insert (assembly->tokens,
+ GUINT_TO_POINTER (clause->token_or_filter),
+ ex_block->extype);
+ }
+ finally_start = ex_block->start + ex_block->len;
+
+ clause_index ++;
+ }
+ }
+
+ return clauses;
+}
+
static guint32
method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
{
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) {
- MonoILExceptionInfo *ex_info;
- for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
- ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
- if (ex_info->handlers)
- num_exception += mono_array_length (ex_info->handlers);
- else
- num_exception++;
- }
- }
+ if (mb->ilgen->ex_handlers)
+ num_exception = method_count_clauses (mb->ilgen);
} else {
code = mb->code;
+ if (code == NULL)
+ mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
+
code_size = mono_array_length (code);
max_stack = 8; /* we probably need to run a verifier on the code... */
}
/* always use fat format for now */
sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
num_exception *= sizeof (MonoExceptionClause);
+ 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;
clause.try_len = GUINT32_TO_LE (ex_info->len);
clause.handler_offset = GUINT32_TO_LE (ex_block->start);
clause.handler_len = GUINT32_TO_LE (ex_block->len);
- finally_start = clause.handler_offset + clause.handler_len;
+ finally_start = ex_block->start + ex_block->len;
clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
for (i = 1; i <= table->rows; ++i) {
if (values [col] == token)
return i;
+ values += table->columns;
}
return 0;
}
+static GHashTable *dynamic_custom_attrs = NULL;
+
+static MonoCustomAttrInfo*
+mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
+{
+ int i, count;
+ MonoCustomAttrInfo *ainfo;
+ MonoReflectionCustomAttr *cattr;
+
+ if (!cattrs)
+ return NULL;
+ /* FIXME: check in assembly the Run flag is set */
+
+ count = mono_array_length (cattrs);
+
+ ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
+
+ ainfo->image = image;
+ ainfo->num_attrs = count;
+ for (i = 0; i < count; ++i) {
+ cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
+ ainfo->attrs [i].ctor = cattr->ctor->method;
+ /* FIXME: might want to memdup the data here */
+ ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
+ ainfo->attrs [i].data_size = mono_array_length (cattr->data);
+ }
+
+ return ainfo;
+}
+
+static void
+mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
+{
+ MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
+
+ if (!ainfo)
+ return;
+
+ if (!dynamic_custom_attrs)
+ dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
+
+ g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
+}
+
+void
+mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
+{
+ /* they are cached, so we don't free them */
+ if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
+ return;
+ g_free (ainfo);
+}
+
/*
* idx is the table index of the object
* type is one of CUSTOM_ATTR_*
type |= CUSTOM_ATTR_TYPE_MEMBERREF;
break;
default:
- g_error ("got wrong token in custom attr");
+ 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] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
- mono_image_add_stream_data (&assembly->blob,
+ 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;
/* room in this table is already allocated */
table = &assembly->tables [MONO_TABLE_METHOD];
*mb->table_idx = table->next_idx ++;
+ mono_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;
if (mb->name) {
name = mono_string_to_utf8 (mb->name);
g_free (name);
} else { /* a constructor */
values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
+ // MS.NET adds this automatically
+ mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
}
values [MONO_METHOD_FLAGS] = mb->attrs;
values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
values [MONO_PARAM_FLAGS] = pb->attrs;
values [MONO_PARAM_SEQUENCE] = i;
- name = mono_string_to_utf8 (pb->name);
- values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
- g_free (name);
+ if (pb->name != NULL) {
+ name = mono_string_to_utf8 (pb->name);
+ values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
+ g_free (name);
+ }
+ else
+ values [MONO_PARAM_NAME] = 0;
values += MONO_PARAM_SIZE;
if (pb->marshal_info) {
mtable->rows++;
mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
}
- table->next_idx++;
+ pb->table_idx = table->next_idx++;
}
}
}
rmb.name = mb->name;
rmb.table_idx = &mb->table_idx;
rmb.init_locals = mb->init_locals;
+ rmb.mhandle = mb->mhandle;
mono_image_basic_method (&rmb, assembly);
table->rows ++;
alloc_table (table, table->rows);
values = table->values + table->rows * MONO_IMPLMAP_SIZE;
- values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
+ /* map CharSet values to on-disk values */
+ values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (mb->charset ? (mb->charset - 1) * 2: 1);
values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
name = mono_string_to_utf8 (mb->dllentry);
values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
values [MONO_IMPLMAP_SCOPE] = table->rows;
}
}
+
if (mb->override_method) {
MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
guint32 tok;
rmb.name = NULL;
rmb.table_idx = &mb->table_idx;
rmb.init_locals = mb->init_locals;
+ rmb.mhandle = mb->mhandle;
mono_image_basic_method (&rmb, assembly);
char *p;
char* buf;
guint32 idx;
-
+
+ if (!assembly->save)
+ return 0;
+
p = buf = g_malloc (64);
mono_metadata_encode_value (0x06, p, &p);
encode_type (assembly, field->type, p, &p);
g_assert (p-buf < 64);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
encode_reflection_type (assembly, fb->type, p, &p);
g_assert (p-buf < 64);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
char *b = blob_size;
char *p, *box_val;
char* buf;
- guint32 idx, len;
+ guint32 idx, len, dummy = 0;
p = buf = g_malloc (64);
-
- box_val = ((char*)val) + sizeof (MonoObject);
- *ret_type = val->vtable->klass->byval_arg.type;
+ 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:
goto handle_enum;
} else
g_error ("we can't encode valuetypes");
+ 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);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
#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->blob, swapped, len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
g_free (swapped);
}
#else
- mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
#endif
g_free (buf);
/* there is no signature */
mono_metadata_encode_value (len, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- swap_with_size (blob_size, val, len, 1);
+ 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
- mono_image_add_stream_data (&assembly->blob, box_val, len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
#endif
g_free (buf);
p = buf = g_malloc (256);
switch (minfo->type) {
- /* FIXME: handle ARRAY and other unmanaged types that need extra info */
+ case MONO_NATIVE_BYVALTSTR:
+ case MONO_NATIVE_BYVALARRAY:
+ mono_metadata_encode_value (minfo->type, p, &p);
+ mono_metadata_encode_value (minfo->count, p, &p);
+ break;
+ /* FIXME: handle ARRAY and other unmanaged types that need extra info */
default:
mono_metadata_encode_value (minfo->type, p, &p);
break;
}
len = p-buf;
mono_metadata_encode_value (len, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
g_free (buf);
return idx;
}
fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
table = &assembly->tables [MONO_TABLE_FIELD];
fb->table_idx = table->next_idx ++;
+ mono_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;
name = mono_string_to_utf8 (fb->name);
values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
/* store length */
g_assert (p - buf < size);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
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;
- mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
+ if (image->assembly->dynamic)
+ /* FIXME: */
+ memset (cols, 0, sizeof (cols));
+ else
+ mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
token = table->next_idx ++;
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_PUBLIC_KEY] = 0;
values [MONO_ASSEMBLYREF_CULTURE] = 0;
values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
+ if ((pubkey = mono_image_get_public_key (image, &publen))) {
+ guchar pubtoken [9];
+ pubtoken [0] = 8;
+ mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
+ values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
+ } else {
+ /*
+ * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
+ * This is currently only a problem with references to System.Xml (see bug#27706),
+ * but there may be other cases that makes this necessary. Note, we need to set
+ * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
+ * recognized by ms, yuck!
+ * FIXME: need to add more assembly names, as needed.
+ */
+ if (strcmp (image->assembly_name, "corlib") == 0 ||
+ strcmp (image->assembly_name, "mscorlib") == 0 ||
+ strcmp (image->assembly_name, "System") == 0 ||
+ strcmp (image->assembly_name, "System.Xml") == 0 ||
+ strcmp (image->assembly_name, "System.Data") == 0 ||
+ strcmp (image->assembly_name, "System.Drawing") == 0 ||
+ strcmp (image->assembly_name, "System.Web") == 0) {
+ static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
+ values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
+ values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
+ values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
+ } else {
+ values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
+ }
+ }
token <<= RESOLTION_SCOPE_BITS;
token |= RESOLTION_SCOPE_ASSEMBLYREF;
g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), image);
return token;
}
default:
return 0;
}
-
- g_assert (p-sig < 128);
- mono_metadata_encode_value (p-sig, b, &b);
- token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, sig, p-sig);
table = &assembly->tables [MONO_TABLE_TYPESPEC];
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
- values [MONO_TYPESPEC_SIGNATURE] = token;
+ if (assembly->save) {
+ g_assert (p-sig < 128);
+ mono_metadata_encode_value (p-sig, b, &b);
+ token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
+ values [MONO_TYPESPEC_SIGNATURE] = token;
+ }
token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
guint32 token, scope, enclosing;
MonoClass *klass;
+#define COMPILE_CORLIB 0
+#if COMPILE_CORLIB
+ /* nasty hack, need to find the proper solution */
+ if (type->type == MONO_TYPE_OBJECT)
+ return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
+#endif
token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
if (token)
return token;
token = create_typespec (assembly, type);
if (token)
return token;
- klass = mono_class_from_mono_type (type);
+ klass = my_mono_class_from_mono_type (type);
+ if (!klass)
+ klass = mono_class_from_mono_type (type);
+
/*
* If it's in the same module:
*/
if (klass->image == assembly->assembly.image) {
MonoReflectionTypeBuilder *tb = klass->reflection_info;
- return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
+ token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
+ return token;
}
if (klass->nested_in) {
scope = resolution_scope_from_image (assembly, klass->image);
}
table = &assembly->tables [MONO_TABLE_TYPEREF];
- 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);
+ 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 = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
table->next_idx ++;
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
return token;
}
case TYPEDEFORREF_TYPEDEF:
/* should never get here */
default:
- g_error ("unknow typeref or def token");
+ g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
+ return 0;
}
/* extract the index */
parent >>= TYPEDEFORREF_BITS;
table = &assembly->tables [MONO_TABLE_MEMBERREF];
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+ values [MONO_MEMBERREF_CLASS] = pclass | (parent << 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 ++;
token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
if (token)
return token;
+ field->parent = klass;
token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
field->name, fieldref_encode_signature (assembly, field));
g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
return token;
}
+static guint32
+mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
+{
+ char *buf;
+ char *p;
+ guint32 nargs;
+ guint32 size;
+ guint32 i, idx;
+ char blob_size [6];
+ char *b = blob_size;
+
+ if (!assembly->save)
+ return 0;
+
+ /* FIXME: */
+ g_assert (helper->type == 2);
+
+ if (helper->arguments)
+ nargs = mono_array_length (helper->arguments);
+ else
+ nargs = 0;
+
+ size = 10 + (nargs * 10);
+
+ p = buf = g_malloc (size);
+
+ /* 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 */
+ *p = helper->unmanaged_call_conv - 1;
+ else {
+ /* Managed */
+ *p = helper->call_conv & 0x60; /* has_this + explicit_this */
+ if (helper->call_conv & 0x02) /* varargs */
+ *p += 0x05;
+ }
+
+ p++;
+ mono_metadata_encode_value (nargs, p, &p);
+ encode_reflection_type (assembly, helper->return_type, p, &p);
+ for (i = 0; i < nargs; ++i) {
+ MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, p, &p);
+ }
+ /* store length */
+ g_assert (p - buf < size);
+ mono_metadata_encode_value (p-buf, b, &b);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
+ g_free (buf);
+
+ return idx;
+}
+
+static guint32
+mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
+{
+ guint32 idx;
+ MonoDynamicTable *table;
+ guint32 *values;
+
+ 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);
+
+ return idx;
+}
+
static int
reflection_cc_to_file (int call_conv) {
switch (call_conv & 0x3) {
mono_metadata_signature_equal (am->sig, sig)) {
g_free (name);
g_free (sig);
+ m->table_idx = am->token & 0xffffff;
return am->token;
}
}
am->sig = sig;
am->parent = m->parent->type;
am->token = mono_image_get_memberref_token (assembly, am->parent,
- name, method_encode_signature (assembly, sig));
+ 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;
{
MonoDynamicTable *table;
guint *values;
- int i;
+ int i, is_object = 0, is_system = 0;
char *n;
table = &assembly->tables [MONO_TABLE_TYPEDEF];
values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
values [MONO_TYPEDEF_FLAGS] = tb->attrs;
- if (tb->parent) { /* interfaces don't have a parent */
- values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
- } else
- values [MONO_TYPEDEF_EXTENDS] = 0;
n = mono_string_to_utf8 (tb->name);
+ 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 (tb->nspace);
+ 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 */
+ values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->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 (tb->subtypes) {
MonoDynamicTable *ntable;
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows += mono_array_length (tb->subtypes);
- alloc_table (table, table->rows);
-
ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
ntable->rows += mono_array_length (tb->subtypes);
alloc_table (ntable, ntable->rows);
values += MONO_NESTED_CLASS_SIZE;
ntable->next_idx++;
}
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
-
- mono_image_get_type_info (domain, subtype, assembly);
- }
}
}
static void
-assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
+collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
{
- int j;
-
- type->table_idx = table->next_idx ++;
+ int i;
+
+ g_ptr_array_add (types, type);
+
if (!type->subtypes)
return;
- for (j = 0; j < mono_array_length (type->subtypes); ++j) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
- assign_type_idx (subtype, table);
+
+ 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 void
params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
int i;
mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
+ /* no types in the module */
+ if (!mb->types)
+ return;
+
for (i = 0; i < mono_array_length (mb->types); ++i)
type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
}
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;
-
- /*
- * fill-in info in other tables as well.
- */
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows += mono_array_length (mb->types);
- alloc_table (table, table->rows);
- /*
- * We assign here the typedef indexes to avoid mismatches if a type that
- * has not yet been stored in the tables is referenced by another type.
- */
- for (i = 0; i < mono_array_length (mb->types); ++i) {
- MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
- assign_type_idx (type, table);
- }
- for (i = 0; i < mono_array_length (mb->types); ++i)
- mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
}
#define align_pointer(base,p)\
*p++ = values [col];
break;
case 2:
- int16val = (guint16*)p;
- *int16val = GUINT16_TO_LE (values [col]);
- p += 2;
+ *p++ = values [col] & 0xff;
+ *p++ = (values [col] >> 8) & 0xff;
break;
case 4:
- int32val = (guint32*)p;
- *int32val = GUINT32_TO_LE (values [col]);
- p += 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 ();
MonoReflectionFieldBuilder *field;
MonoReflectionCtorBuilder *ctor;
MonoReflectionMethodBuilder *method;
+ MonoReflectionTypeBuilder *tb;
+ MonoReflectionArrayMethod *am;
guint32 i, idx;
unsigned char *target;
target = assembly->code.data + code_idx + iltoken->code_pos;
switch (target [3]) {
case MONO_TABLE_FIELD:
- if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
+ 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 (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
+ } else {
g_assert_not_reached ();
- field = (MonoReflectionFieldBuilder *)iltoken->member;
- idx = field->table_idx;
+ }
break;
case MONO_TABLE_METHOD:
if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
} 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")) {
+ MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
+ idx = GPOINTER_TO_UINT (mono_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"))
+ g_assert_not_reached ();
+ am = (MonoReflectionArrayMethod*)iltoken->member;
+ idx = am->table_idx;
+ break;
default:
g_error ("got unexpected table 0x%02x in fixup", target [3]);
}
}
}
-/*
- * mono_image_build_metadata() will fill the info in all the needed metadata tables
- * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
- * and recursively outputs the info for a module. Each module will output all the info
- * about it's types etc.
- * At the end of the process, method and field tokens are fixed up and the on-disk
- * compressed metadata representation is created.
- */
static void
-mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
+assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
{
MonoDynamicTable *table;
- MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
- MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
- guint32 len;
guint32 *values;
- char *name;
- int i;
+ char blob_size [6];
+ guchar hash [20];
+ char *b = blob_size;
+ char *name, *sname;
+ guint32 idx, offset;
+
+ if (rsrc->filename) {
+ name = mono_string_to_utf8 (rsrc->filename);
+ sname = g_path_get_basename (name);
- assembly->text_rva = START_TEXT_RVA;
+ 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, hash, 20);
+ g_free (name);
+ idx = table->next_idx++;
+ idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
+ offset = 0;
+ } else {
+ char sizebuf [4];
+ offset = mono_array_length (rsrc->data);
+ sizebuf [0] = offset; sizebuf [1] = offset >> 8;
+ sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
+ offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
+ mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
+ idx = 0;
+ }
- table = &assembly->tables [MONO_TABLE_ASSEMBLY];
- alloc_table (table, 1);
- values = table->values + MONO_ASSEMBLY_SIZE;
- values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
- name = mono_string_to_utf8 (assemblyb->name);
- values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
+ 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] = offset;
+ values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
+ name = mono_string_to_utf8 (rsrc->name);
+ values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
g_free (name);
- values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
- values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
+ values [MONO_MANIFEST_IMPLEMENTATION] = idx;
+ table->next_idx++;
+}
+
+static void
+set_version_from_string (MonoString *version, guint32 *values)
+{
+ gchar *ver, *p, *str;
+ guint32 i;
+
values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
values [MONO_ASSEMBLY_REV_NUMBER] = 0;
values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
- values [MONO_ASSEMBLY_FLAGS] = 0;
+ if (!version)
+ return;
+ ver = str = mono_string_to_utf8 (version);
+ 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);
+}
+
+static guint32
+load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
+ char *name, *content;
+ gsize len;
+ guint32 token = 0;
+
+ if (!fname)
+ return token;
+ name = mono_string_to_utf8 (fname);
+ if (g_file_get_contents (name, &content, &len, NULL)) {
+ char blob_size [6];
+ char *b = blob_size;
+ /* check it's a public key or keypair */
+ 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, content, len);
+ g_free (content);
+ /* need to get the actual value from the key type... */
+ assembly->strong_name_size = 128;
+ assembly->strong_name = g_malloc0 (assembly->strong_name_size);
+ }
+ /* FIXME: how do we tell mcs if loading fails? */
+ g_free (name);
+ return token;
+}
+
+/*
+ * mono_image_build_metadata() will fill the info in all the needed metadata tables
+ * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
+ * and recursively outputs the info for a module. Each module will output all the info
+ * about it's types etc.
+ * At the end of the process, method and field tokens are fixed up and the on-disk
+ * compressed metadata representation is created.
+ */
+void
+mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
+{
+ MonoDynamicTable *table;
+ MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
+ MonoDomain *domain = mono_object_domain (assemblyb);
+ guint32 len;
+ guint32 *values;
+ char *name;
+ int i;
+
+ if (assembly->text_rva)
+ return;
+
+ assembly->text_rva = START_TEXT_RVA;
+
+ 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;
+ name = mono_string_to_utf8 (assemblyb->name);
+ values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
+ g_free (name);
+ if (assemblyb->culture) {
+ name = mono_string_to_utf8 (assemblyb->culture);
+ values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
+ g_free (name);
+ } else {
+ values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
+ }
+ values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
+ values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
+ set_version_from_string (assemblyb->version, values);
+
+ 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;
- assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
- assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
+ /*
+ * handle global methods
+ * FIXME: test what to do when global methods are defined in multiple modules.
+ */
+ if (assemblyb->modules) {
+ MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
+ if (mod->global_methods) {
+ table = &assembly->tables [MONO_TABLE_METHOD];
+ table->rows += mono_array_length (mod->global_methods);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (mod->global_methods); ++i)
+ mono_image_get_method_info (
+ mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
+ }
+ }
if (assemblyb->modules) {
len = mono_array_length (assemblyb->modules);
table->next_idx ++;
}
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
+ /* Emit types */
+ if (assemblyb->modules) {
+ /* Collect all types into a list sorted by their table_idx */
+ GPtrArray *types = g_ptr_array_new ();
+
+ len = mono_array_length (assemblyb->modules);
+ for (i = 0; i < len; ++i) {
+ MonoReflectionModuleBuilder *mb =
+ mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
+ if (mb->types)
+ for (i = 0; i < mono_array_length (mb->types); ++i) {
+ MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
+ collect_types (types, type);
+ }
+ }
+
+ g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
+ table = &assembly->tables [MONO_TABLE_TYPEDEF];
+ table->rows += types->len;
+ alloc_table (table, table->rows);
+
+ for (i = 0; i < types->len; ++i) {
+ MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
+ mono_image_get_type_info (domain, type, assembly);
+ }
+ g_ptr_array_free (types, TRUE);
+ }
+
/*
* table->rows is already set above and in mono_image_fill_module_table.
*/
- 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;
-
/* add all the custom attributes at the end, once all the indexes are stable */
mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
for (i = 0; i < len; ++i)
module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
}
-
+
/* fixup tokens */
mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
-
- build_compressed_metadata (assembly);
}
/*
char buf [16];
char *b = buf;
+ MONO_ARCH_SAVE_REGS;
+
if (!assembly->dynamic_assembly)
mono_image_basic_init (assembly);
- mono_metadata_encode_value (1 | (str->length * 2), b, &b);
- idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
+
+ if (assembly->dynamic_assembly->save) {
+ mono_metadata_encode_value (1 | (str->length * 2), b, &b);
+ idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
{
char *swapped = g_malloc (2 * mono_string_length (str));
mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
#endif
mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
+ }
+ else
+ idx = assembly->dynamic_assembly->us.index ++;
+
+ mono_g_hash_table_insert (assembly->dynamic_assembly->tokens,
+ GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
+
return MONO_TOKEN_STRING | idx;
}
MonoClass *klass;
guint32 token;
- if (!obj)
- g_error ("System.Array methods not yet supported");
-
klass = obj->vtable->klass;
if (strcmp (klass->name, "MethodBuilder") == 0) {
MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
/*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- return token;
}
- if (strcmp (klass->name, "ConstructorBuilder") == 0) {
+ else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
/*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- return token;
}
- if (strcmp (klass->name, "FieldBuilder") == 0) {
+ else if (strcmp (klass->name, "FieldBuilder") == 0) {
MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
- return mb->table_idx | MONO_TOKEN_FIELD_DEF;
+ token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
}
- if (strcmp (klass->name, "TypeBuilder") == 0) {
+ else if (strcmp (klass->name, "TypeBuilder") == 0) {
MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
- return tb->table_idx | MONO_TOKEN_TYPE_DEF;
+ token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
}
- if (strcmp (klass->name, "MonoType") == 0) {
+ else if (strcmp (klass->name, "MonoType") == 0) {
MonoReflectionType *tb = (MonoReflectionType *)obj;
- return mono_metadata_token_from_dor (
+ token = mono_metadata_token_from_dor (
mono_image_typedef_or_ref (assembly, tb->type));
}
- if (strcmp (klass->name, "MonoCMethod") == 0 ||
+ else if (strcmp (klass->name, "MonoCMethod") == 0 ||
strcmp (klass->name, "MonoMethod") == 0) {
MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
- token = mono_image_get_methodref_token (assembly, m->method);
+ if (m->method->klass->image == assembly->assembly.image) {
+ static guint32 method_table_idx = 0xffffff;
+ /*
+ * 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);
/*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
- return token;
}
- if (strcmp (klass->name, "MonoField") == 0) {
+ else if (strcmp (klass->name, "MonoField") == 0) {
MonoReflectionField *f = (MonoReflectionField *)obj;
- token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
+ if (f->klass->image == assembly->assembly.image) {
+ 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, f->field, f->klass);
/*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
- return token;
}
- if (strcmp (klass->name, "MonoArrayMethod") == 0) {
+ else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
token = mono_image_get_array_token (assembly, m);
- return token;
}
- g_print ("requested token for %s\n", klass->name);
- return 0;
+ else if (strcmp (klass->name, "SignatureHelper") == 0) {
+ MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
+ token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
+ }
+ else
+ g_error ("requested token for %s\n", klass->name);
+
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
+ obj);
+
+ return token;
}
typedef struct {
guint32 flags;
} MonoILT;
+static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
+
+static MonoImage*
+create_dynamic_mono_image (char *assembly_name, char *module_name)
+{
+ MonoImage *image;
+
+ image = g_new0 (MonoImage, 1);
+
+ /* keep in sync with image.c */
+ image->name = assembly_name;
+ image->assembly_name = image->name; /* they may be different */
+ image->module_name = module_name;
+ image->references = g_new0 (MonoAssembly*, 1);
+ image->references [0] = NULL;
+
+ image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+ image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ image->delegate_begin_invoke_cache =
+ g_hash_table_new ((GHashFunc)mono_signature_hash,
+ (GCompareFunc)mono_metadata_signature_equal);
+ image->delegate_end_invoke_cache =
+ g_hash_table_new ((GHashFunc)mono_signature_hash,
+ (GCompareFunc)mono_metadata_signature_equal);
+ image->delegate_invoke_cache =
+ g_hash_table_new ((GHashFunc)mono_signature_hash,
+ (GCompareFunc)mono_metadata_signature_equal);
+
+ image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ image->synchronized_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ return image;
+}
+
/*
- * mono_image_basic_ini:
+ * mono_image_basic_init:
* @assembly: an assembly builder object
*
* Create the MonoImage that represents the assembly builder and setup some
MonoImage *image;
int i;
+ MONO_ARCH_SAVE_REGS;
+
if (assemblyb->dynamic_assembly)
return;
#if HAVE_BOEHM_GC
- assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
+ assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
#else
assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
#endif
+ assembly->assembly.dynamic = assembly;
+ assemblyb->assembly.assembly = (MonoAssembly*)assembly;
assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+ assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+ assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
+ assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
+ assembly->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
string_heap_init (&assembly->sheap);
mono_image_add_stream_data (&assembly->us, "", 1);
- mono_image_add_stream_data (&assembly->blob, "", 1);
+ add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
/* import tables... */
mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
assembly->tables [i].columns = table_sizes [i];
}
- image = g_new0 (MonoImage, 1);
-
- /* keep in sync with image.c */
- image->name = mono_string_to_utf8 (assemblyb->name);
- image->assembly_name = image->name; /* they may be different */
-
- image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
- image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
- image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
- image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ assembly->run = assemblyb->access != 2;
+ assembly->save = assemblyb->access != 1;
+ image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
+ assembly->assembly.aname.name = image->name;
+ image->assembly = (MonoAssembly*)assembly;
assembly->assembly.image = image;
-
+
+ register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
+ mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
}
static int
assembly->code.index &= ~3;
assembly->meta_size += 3;
assembly->meta_size &= ~3;
+ assembly->resources.index += 3;
+ assembly->resources.index &= ~3;
- assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index;
+ 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++;
MonoDotNetHeader *header;
MonoSectionTable *section;
MonoCLIHeader *cli_header;
- guint32 size, image_size, virtual_base;
+ guint32 size, image_size, virtual_base, text_offset;
guint32 header_start, section_start, file_offset, virtual_offset;
MonoDynamicAssembly *assembly;
MonoDynamicStream *pefile;
int i, nsections;
- guint32 *rva;
+ guint32 *rva, value;
guint16 *data16;
+ 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,
return;
mono_image_build_metadata (assemblyb);
+
+ if (assemblyb->resources) {
+ int len = mono_array_length (assemblyb->resources);
+ for (i = 0; i < len; ++i)
+ assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
+ }
+
+
+ build_compressed_metadata (assembly);
+
nsections = calc_section_size (assembly);
pefile = &assembly->pefile;
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);
- /* it's an exe */
- header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
- /* FIXME: it's a dll */
- /*header->coff.coff_attributes = GUINT16_FROM_LE (0x210e); */
+ 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 */
size += VIRT_ALIGN - 1;
size &= ~(VIRT_ALIGN - 1);
header->nt.pe_image_size = GUINT32_FROM_LE (size);
- header->nt.pe_subsys_required = GUINT16_FROM_LE (3); /* 3 -> cmdline app, 2 -> GUI app */
+
+ //
+ // Translate the PEFileKind value to the value expected by the Windows loader
+ //
+ {
+ short kind = assemblyb->pekind;
+
+ //
+ // 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 (kind == 2)
+ kind = 3;
+ else if (kind == 3)
+ kind = 2;
+
+ 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);
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);
- rva = (guint32*)(assembly->code.data + assembly->ilt_offset);
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset - 2);
+ p = (assembly->code.data + assembly->ilt_offset);
+ value = (assembly->text_rva + assembly->imp_names_offset - 2);
+ *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_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
else
cli_header->ch_entry_point = GUINT32_FROM_LE (0);
- cli_header->ch_metadata.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->code.index);
+ /* 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);
switch (i) {
case MONO_SECTION_TEXT:
/* patch entry point */
- rva = (guint32*)(assembly->code.data + 2);
- *rva = GUINT32_FROM_LE (virtual_base + assembly->text_rva + assembly->iat_offset);
- memcpy (pefile->data + assembly->sections [i].offset, assembly->code.data, assembly->code.index);
- memcpy (pefile->data + assembly->sections [i].offset + assembly->code.index, assembly->assembly.image->raw_metadata, assembly->meta_size);
+ p = (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;
+
+ text_offset = assembly->sections [i].offset;
+ memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
+ text_offset += assembly->code.index;
+ memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
+ text_offset += assembly->resources.index;
+ memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
+ text_offset += assembly->meta_size;
+ memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
+
+ g_free (assembly->assembly.image->raw_metadata);
break;
case MONO_SECTION_RELOC:
rva = (guint32*)(pefile->data + assembly->sections [i].offset);
/*
* 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.
*/
-static MonoGHashTable *object_cache = NULL;
-static MonoGHashTable *type_cache = NULL;
-#define CHECK_OBJECT(t,p) \
+typedef struct {
+ gpointer item;
+ MonoClass *refclass;
+} ReflectedEntry;
+
+static gboolean
+reflected_equal (gconstpointer a, gconstpointer b) {
+ const ReflectedEntry *ea = a;
+ const ReflectedEntry *eb = b;
+
+ return (ea->item == eb->item) && (ea->refclass == eb->refclass);
+}
+
+static guint
+reflected_hash (gconstpointer a) {
+ const ReflectedEntry *ea = a;
+ return GPOINTER_TO_UINT (ea->item);
+}
+
+#define CHECK_OBJECT(t,p,k) \
do { \
t _obj; \
- if (!object_cache) \
- object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal); \
- if ((_obj = mono_g_hash_table_lookup (object_cache, (p)))) \
+ ReflectedEntry e; \
+ e.item = (p); \
+ e.refclass = (k); \
+ mono_domain_lock (domain); \
+ if (!domain->refobject_hash) \
+ domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
+ if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
+ mono_domain_unlock (domain); \
return _obj; \
+ } \
} while (0)
-#define CACHE_OBJECT(p,o) \
+#if HAVE_BOEHM_GC
+#define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
+#else
+#define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
+#endif
+
+#define CACHE_OBJECT(p,o,k) \
do { \
- mono_g_hash_table_insert (object_cache, p,o); \
+ ReflectedEntry *e = ALLOC_REFENTRY; \
+ e->item = (p); \
+ e->refclass = (k); \
+ mono_g_hash_table_insert (domain->refobject_hash, e,o); \
+ mono_domain_unlock (domain); \
} while (0)
+static void
+register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
+{
+ /* this is done only once */
+ mono_domain_lock (domain);
+ CACHE_OBJECT (assembly, res, NULL);
+}
+
+static void
+register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
+{
+ /* this is done only once */
+ mono_domain_lock (domain);
+ CACHE_OBJECT (module, res, NULL);
+}
+
+void
+mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
+{
+ MonoImage *image = moduleb->module.image;
+ MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
+ if (!image) {
+ if (!ab->modules) {
+ /* a MonoImage was already created in mono_image_basic_init () */
+ image = ab->dynamic_assembly->assembly.image;
+ } else {
+ image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
+ }
+ moduleb->module.image = image;
+ register_module (mono_object_domain (moduleb), moduleb, image);
+ }
+}
+
/*
* mono_assembly_get_object:
* @domain: an app domain
static MonoClass *System_Reflection_Assembly;
MonoReflectionAssembly *res;
- CHECK_OBJECT (MonoReflectionAssembly *, assembly);
+ CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
if (!System_Reflection_Assembly)
System_Reflection_Assembly = mono_class_from_name (
mono_defaults.corlib, "System.Reflection", "Assembly");
res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
res->assembly = assembly;
- CACHE_OBJECT (assembly, res);
+ CACHE_OBJECT (assembly, res, NULL);
+ return res;
+}
+
+
+MonoReflectionModule*
+mono_module_get_object (MonoDomain *domain, MonoImage *image)
+{
+ static MonoClass *System_Reflection_Module;
+ MonoReflectionModule *res;
+
+ CHECK_OBJECT (MonoReflectionModule *, image, NULL);
+ if (!System_Reflection_Module)
+ System_Reflection_Module = mono_class_from_name (
+ mono_defaults.corlib, "System.Reflection", "Module");
+ res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
+
+ res->image = image;
+ res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
+
+ res->fqname = mono_string_new (domain, image->name);
+ res->name = mono_string_new (domain, image->name);
+ res->scopename = mono_string_new (domain, image->module_name);
+
+ CACHE_OBJECT (image, res, NULL);
return res;
}
+
static gboolean
mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
{
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_OBJECT:
+ case MONO_TYPE_TYPEDBYREF:
return TRUE;
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
return t1->data.klass == t2->data.klass;
case MONO_TYPE_PTR:
+ return mymono_metadata_type_equal (t1->data.type, t2->data.type);
case MONO_TYPE_SZARRAY:
+retry_sz:
+ if (t1->data.type->type != t2->data.type->type)
+ return FALSE;
+ if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
+ return t1->data.type->data.klass == t2->data.type->data.klass;
+ if (t1->data.type->type == MONO_TYPE_SZARRAY) {
+ t1 = t1->data.type;
+ t2 = t2->data.type;
+ goto retry_sz;
+ }
return mymono_metadata_type_equal (t1->data.type, t2->data.type);
case MONO_TYPE_ARRAY:
if (t1->data.array->rank != t2->data.array->rank)
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
/* check if the distribution is good enough */
- return hash << 7 | g_str_hash (t1->data.klass->name);
+ return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
case MONO_TYPE_PTR:
case MONO_TYPE_SZARRAY:
- return hash << 7 | mymono_metadata_type_hash (t1->data.type);
+ return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
}
return hash;
}
MonoReflectionType *res;
MonoClass *klass = mono_class_from_mono_type (type);
- if (!type_cache)
- type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
+ mono_domain_lock (domain);
+ if (!domain->type_hash)
+ domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
(GCompareFunc)mymono_metadata_type_equal);
- if ((res = mono_g_hash_table_lookup (type_cache, type)))
+ if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
+ mono_domain_unlock (domain);
return res;
- if (klass->reflection_info) {
+ }
+ if (klass->reflection_info && !klass->wastypebuilder) {
+ //g_assert_not_reached ();
/* should this be considered an error condition? */
- if (!type->byref)
+ if (!type->byref) {
+ mono_domain_unlock (domain);
return klass->reflection_info;
+ }
}
mono_class_init (klass);
res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
res->type = type;
- mono_g_hash_table_insert (type_cache, type, res);
+ mono_g_hash_table_insert (domain->type_hash, type, res);
+ mono_domain_unlock (domain);
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)
+mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
{
/*
* We use the same C representation for methods and constructors, but the type
MonoClass *klass;
MonoReflectionMethod *ret;
- CHECK_OBJECT (MonoReflectionMethod *, method);
+ if (!refclass)
+ refclass = method->klass;
+
+ CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
cname = "MonoCMethod";
else
ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
ret->method = method;
ret->name = mono_string_new (domain, method->name);
- CACHE_OBJECT (method, ret);
+ ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
+ CACHE_OBJECT (method, ret, refclass);
return ret;
}
MonoReflectionField *res;
MonoClass *oklass;
- CHECK_OBJECT (MonoReflectionField *, field);
+ CHECK_OBJECT (MonoReflectionField *, field, klass);
oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
res = (MonoReflectionField *)mono_object_new (domain, oklass);
res->klass = klass;
res->field = field;
- CACHE_OBJECT (field, res);
+ CACHE_OBJECT (field, res, klass);
return res;
}
MonoReflectionProperty *res;
MonoClass *oklass;
- CHECK_OBJECT (MonoReflectionProperty *, property);
+ CHECK_OBJECT (MonoReflectionProperty *, property, klass);
oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
res->klass = klass;
res->property = property;
- CACHE_OBJECT (property, res);
+ CACHE_OBJECT (property, res, klass);
return res;
}
MonoReflectionEvent *res;
MonoClass *oklass;
- CHECK_OBJECT (MonoReflectionEvent *, event);
+ CHECK_OBJECT (MonoReflectionEvent *, event, klass);
oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
res->klass = klass;
res->event = event;
- CACHE_OBJECT (event, res);
+ CACHE_OBJECT (event, res, klass);
return res;
}
if (!method->signature->param_count)
return NULL;
- member = mono_method_get_object (domain, method);
- names = g_new (char *, method->signature->param_count);
- mono_method_get_param_names (method, (const char **) names);
-
/* 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 (MonoReflectionParameter**, &(method->signature));
+ CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
+
+ member = mono_method_get_object (domain, method, NULL);
+ names = g_new (char *, method->signature->param_count);
+ mono_method_get_param_names (method, (const char **) names);
+
oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
#if HAVE_BOEHM_GC
- res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
+ res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
#else
res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
#endif
res [i]->AttrsImpl = method->signature->params [i]->attrs;
}
g_free (names);
- CACHE_OBJECT (&(method->signature), res);
+ CACHE_OBJECT (&(method->signature), res, NULL);
return res;
}
+static int
+assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
+ int found_sep;
+ char *s;
+
+ memset (assembly, 0, sizeof (MonoAssemblyName));
+ assembly->name = p;
+ assembly->culture = "";
+
+ while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
+ p++;
+ found_sep = 0;
+ while (*p == ' ' || *p == ',') {
+ *p++ = 0;
+ found_sep = 1;
+ continue;
+ }
+ /* failed */
+ if (!found_sep)
+ return 1;
+ while (*p) {
+ if (*p == 'V' && strncmp (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;
+ } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
+ p += 8;
+ if (strncmp (p, "neutral", 7) == 0) {
+ assembly->culture = "";
+ p += 7;
+ } else {
+ assembly->culture = p;
+ while (*p && *p != ',') {
+ p++;
+ }
+ }
+ } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
+ p += 15;
+ s = p;
+ while (*s && isxdigit (*s)) {
+ *s = tolower (*s);
+ s++;
+ }
+ assembly->hash_len = s - p;
+ if (!(s-p) || ((s-p) & 1))
+ return 1;
+ assembly->hash_value = s = p;
+ while (*s && isxdigit (*s)) {
+ int val;
+ val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
+ s++;
+ *p = val << 4;
+ *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
+ p++;
+ }
+ p = s;
+ } else {
+ while (*p && *p != ',')
+ p++;
+ }
+ found_sep = 0;
+ while (*p == ' ' || *p == ',') {
+ *p++ = 0;
+ found_sep = 1;
+ continue;
+ }
+ /* failed */
+ if (!found_sep)
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* mono_reflection_parse_type:
* @name: type name
start = p = w = name;
- info->name = info->name_space = info->assembly = NULL;
+ memset (&info->assembly, 0, sizeof (MonoAssemblyName));
+ info->name = info->name_space = NULL;
info->nested = NULL;
info->modifiers = NULL;
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) {
- info->nested = g_list_append (info->nested, startn);
+ if (info->name)
break;
- }
if (last_point) {
info->name_space = start;
*last_point = 0;
*w++ = *p++;
}
- if (info->name) {
- info->nested = g_list_append (info->nested, startn);
- } else {
+ if (!info->name) {
if (last_point) {
info->name_space = start;
*last_point = 0;
}
if (!*p)
return 0; /* missing assembly name */
- info->assembly = p;
+ if (!assembly_name_to_aname (&info->assembly, p))
+ return 0;
break;
default:
break;
}
- if (info->assembly)
+ if (info->assembly.name)
break;
}
*w = 0; /* terminate class name */
return g_string_free (result, FALSE);
}
-/*
- * mono_reflection_get_type:
- * @image: a metadata context
- * @info: type description structure
- * @ignorecase: flag for case-insensitive string compares
- *
- * Build a MonoType from the type description in @info.
- *
- */
-MonoType*
-mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
+static MonoType*
+mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
{
MonoClass *klass;
GList *mod;
}
mono_class_init (klass);
}
+
return &klass->byval_arg;
}
/*
- * Optimization we could avoid mallocing() an little-endian archs that
- * don't crash with unaligned accesses.
- */
-static void
-fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
- int len, i, slen, type;
- const char *p = mono_metadata_blob_heap (image, blobidx);
+ * mono_reflection_get_type:
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ *
+ * Build a MonoType from the type description in @info.
+ *
+ */
- len = mono_metadata_decode_value (p, &p);
- if (len < 2 || read16 (p) != 0x0001) /* Prolog */
- return;
+MonoType*
+mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
+{
+ MonoType *type;
+ MonoReflectionAssembly *assembly;
+ GString *fullName;
+ GList *mod;
- /* skip prolog */
- p += 2;
- for (i = 0; i < sig->param_count; ++i) {
- type = sig->params [i]->type;
-handle_enum:
- switch (type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN: {
- MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
- *bval = *p;
- ++p;
- break;
- }
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2: {
- guint16 *val = params [i] = g_malloc (sizeof (guint16));
- *val = read16 (p);
- p += 2;
- break;
+ type = mono_reflection_get_type_internal (image, info, ignorecase);
+ if (type)
+ return type;
+ if (!mono_domain_has_type_resolve (mono_domain_get ()))
+ return NULL;
+
+ // 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, 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 (
+ mono_domain_get (), fullName->str, NULL);
+ if (assembly && (!image || (assembly->assembly->image == image)))
+ type = mono_reflection_get_type_internal (assembly->assembly->image,
+ info, ignorecase);
+ g_string_free (fullName, TRUE);
+ return type;
+}
+
+/*
+ * 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)
+{
+ MonoType *type;
+ MonoTypeNameParse info;
+
+ /*g_print ("requested type %s\n", str);*/
+ if (!mono_reflection_parse_type (name, &info)) {
+ g_list_free (info.modifiers);
+ g_list_free (info.nested);
+ return NULL;
+ }
+
+ if (info.assembly.name) {
+ image = mono_image_loaded (info.assembly.name);
+ /* do we need to load if it's not already loaded? */
+ if (!image) {
+ g_list_free (info.modifiers);
+ g_list_free (info.nested);
+ return NULL;
}
+ } else if (image == NULL) {
+ image = mono_defaults.corlib;
+ }
+
+ type = mono_reflection_get_type (image, &info, FALSE);
+ if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
+ image = mono_defaults.corlib;
+ type = mono_reflection_get_type (image, &info, FALSE);
+ }
+
+ g_list_free (info.modifiers);
+ g_list_free (info.nested);
+ return type;
+}
+
+static void*
+load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
+{
+ int slen, type = t->type;
+handle_enum:
+ switch (type) {
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_BOOLEAN: {
+ MonoBoolean *bval = 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 = 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:
+ case MONO_TYPE_U:
+ case MONO_TYPE_I:
#endif
- case MONO_TYPE_R4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4: {
- guint32 *val = params [i] = g_malloc (sizeof (guint32));
- *val = read32 (p);
- p += 4;
- break;
- }
+ case MONO_TYPE_R4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4: {
+ guint32 *val = 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:
+ case MONO_TYPE_U: /* error out instead? this should probably not happen */
+ case MONO_TYPE_I:
#endif
- case MONO_TYPE_R8:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8: {
- guint64 *val = params [i] = g_malloc (sizeof (guint64));
- *val = read64 (p);
- p += 8;
- break;
+ case MONO_TYPE_R8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8: {
+ guint64 *val = g_malloc (sizeof (guint64));
+ *val = read64 (p);
+ *end = p + 8;
+ return val;
+ }
+ case MONO_TYPE_VALUETYPE:
+ if (t->data.klass->enumtype) {
+ type = t->data.klass->enum_basetype->type;
+ goto handle_enum;
+ } else {
+ g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
}
- case MONO_TYPE_VALUETYPE:
- if (sig->params [i]->data.klass->enumtype) {
- type = sig->params [i]->data.klass->enum_basetype->type;
- goto handle_enum;
- } else {
- g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
- }
- break;
- case MONO_TYPE_STRING: {
+ 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 (mono_domain_get (), p, slen);
+ case MONO_TYPE_CLASS: {
+ char *n;
+ MonoType *t;
+ if (*p == (char)0xFF) {
+ *end = p + 1;
+ return NULL;
+ }
+handle_type:
+ slen = mono_metadata_decode_value (p, &p);
+ n = g_memdup (p, slen + 1);
+ n [slen] = 0;
+ t = mono_reflection_type_from_name (n, image);
+ if (!t)
+ g_warning ("Cannot load type '%s'", n);
+ g_free (n);
+ *end = p + slen;
+ return mono_type_get_object (mono_domain_get (), t);
+ }
+ case MONO_TYPE_OBJECT: {
+ char subt = *p++;
+ MonoObject *obj;
+ MonoClass *subc;
+ void *val;
+
+ if (subt == 0x50) {
+ goto handle_type;
+ } else if (subt == 0x0E) {
+ type = MONO_TYPE_STRING;
+ goto handle_enum;
+ } else if (subt == 0x55) {
+ char *n;
+ MonoType *t;
slen = mono_metadata_decode_value (p, &p);
- params [i] = mono_string_new_len (mono_domain_get (), p, slen);
+ n = g_memdup (p, slen + 1);
+ n [slen] = 0;
+ t = mono_reflection_type_from_name (n, image);
+ if (!t)
+ g_warning ("Cannot load type '%s'", n);
+ g_free (n);
p += slen;
- break;
+ subc = mono_class_from_mono_type (t);
+ } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
+ MonoType simple_type = {{0}};
+ simple_type.type = subt;
+ subc = mono_class_from_mono_type (&simple_type);
+ } else {
+ g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
}
- default:
- g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
- break;
+ val = load_cattr_value (image, &subc->byval_arg, p, end);
+ obj = mono_object_new (mono_domain_get (), subc);
+ memcpy ((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;
+ alen = read32 (p);
+ p += 4;
+ if (alen == 0xffffffff) {
+ *end = p;
+ return NULL;
}
+ arr = mono_array_new (mono_domain_get(), mono_class_from_mono_type (t->data.type), alen);
+ switch (t->data.type->type)
+ {
+ 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:
+ 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_STRING:
+ for (i = 0; i < alen; i++) {
+ MonoObject *item = load_cattr_value (image, t->data.type, p, &p);
+ mono_array_set (arr, gpointer, i, item);
+ }
+ break;
+ default:
+ g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
+ }
+ *end=p;
+ return arr;
+ }
+ default:
+ g_error ("Type 0x%02x not handled in custom attr value decoding", type);
+ }
+ return NULL;
+}
+
+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;
}
}
free_param_data (MonoMethodSignature *sig, void **params) {
int i;
for (i = 0; i < sig->param_count; ++i) {
- switch (sig->params [i]->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:
+ if (!type_is_reference (sig->params [i]))
g_free (params [i]);
- break;
- default:
- break;
- }
}
}
return 0;
}
+static MonoObject*
+create_custom_attr (MonoImage *image, MonoMethod *method,
+ const char *data, guint32 len)
+{
+ const char *p = data;
+ const char *named;
+ guint32 i, j, num_named;
+ MonoObject *attr;
+ void **params;
+
+ if (len < 2 || read16 (p) != 0x0001) /* Prolog */
+ return NULL;
+
+ mono_class_init (method->klass);
+ /*g_print ("got attr %s\n", method->klass->name);*/
+
+ params = g_new (void*, method->signature->param_count);
+
+ /* skip prolog */
+ p += 2;
+ for (i = 0; i < method->signature->param_count; ++i) {
+ params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
+ }
+
+ named = p;
+ attr = mono_object_new (mono_domain_get (), method->klass);
+ mono_runtime_invoke (method, attr, params, NULL);
+ free_param_data (method->signature, params);
+ g_free (params);
+ 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 == 0x55) {
+ gint type_len;
+ char *type_name;
+ if ((unsigned char) *named == 0x80) /* no idea what this is, but it looks optional */
+ named++;
+ type_len = mono_metadata_decode_blob_size (named, &named);
+ type_name = 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 */
+ }
+ name_len = mono_metadata_decode_blob_size (named, &named);
+ name = g_malloc (name_len + 1);
+ memcpy (name, named, name_len);
+ name [name_len] = 0;
+ named += name_len;
+ if (named_type == 0x53) {
+ MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
+ void *val = load_cattr_value (image, field->type, named, &named);
+ 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);
+ /* can we have more that 1 arg in a custom attr named property? */
+ prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
+ pparams [0] = load_cattr_value (image, prop_type, named, &named);
+ mono_property_set_value (prop, attr, pparams, NULL);
+ if (!type_is_reference (prop_type))
+ g_free (pparams [0]);
+ }
+ g_free (name);
+ }
+
+ return attr;
+}
+
+MonoArray*
+mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
+{
+ MonoArray *result;
+ MonoClass *klass;
+ MonoObject *attr;
+ int i;
+
+ klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
+ result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
+ for (i = 0; i < cinfo->num_attrs; ++i) {
+ attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
+ mono_array_set (result, gpointer, i, attr);
+ }
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
+{
+ guint32 mtoken, i, len;
+ guint32 cols [MONO_CUSTOM_ATTR_SIZE];
+ MonoTableInfo *ca;
+ MonoCustomAttrInfo *ainfo;
+ GList *tmp, *list = NULL;
+ const char *data;
+
+ ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+ /* the table is not sorted */
+ for (i = 0; i < ca->rows; ++i) {
+ if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
+ continue;
+ list = g_list_prepend (list, GUINT_TO_POINTER (i));
+ }
+ len = g_list_length (list);
+ if (!len)
+ return NULL;
+ ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
+ ainfo->num_attrs = len;
+ ainfo->image = image;
+ for (i = 0, tmp = list; i < len; ++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] >> CUSTOM_ATTR_TYPE_BITS;
+ switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
+ case CUSTOM_ATTR_TYPE_METHODDEF:
+ mtoken |= MONO_TOKEN_METHOD_DEF;
+ break;
+ case 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;
+ }
+ ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
+ if (!ainfo->attrs [i].ctor)
+ g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
+ data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
+ ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
+ ainfo->attrs [i].data = data;
+ }
+ g_list_free (list);
+
+ return ainfo;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_method (MonoMethod *method)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
+ return cinfo;
+ idx = find_method_index (method);
+ idx <<= CUSTOM_ATTR_BITS;
+ idx |= CUSTOM_ATTR_METHODDEF;
+ return mono_custom_attrs_from_index (method->klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_class (MonoClass *klass)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
+ return cinfo;
+ idx = mono_metadata_token_index (klass->type_token);
+ idx <<= CUSTOM_ATTR_BITS;
+ idx |= CUSTOM_ATTR_TYPEDEF;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_assembly (MonoAssembly *assembly)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
+ return cinfo;
+ idx = 1; /* there is only one assembly */
+ idx <<= CUSTOM_ATTR_BITS;
+ idx |= CUSTOM_ATTR_ASSEMBLY;
+ return mono_custom_attrs_from_index (assembly->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
+ return cinfo;
+ idx = find_property_index (klass, property);
+ idx <<= CUSTOM_ATTR_BITS;
+ idx |= CUSTOM_ATTR_PROPERTY;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
+ return cinfo;
+ idx = find_event_index (klass, event);
+ idx <<= CUSTOM_ATTR_BITS;
+ idx |= CUSTOM_ATTR_EVENT;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
+ return cinfo;
+ idx = find_field_index (klass, field);
+ idx <<= CUSTOM_ATTR_BITS;
+ idx |= CUSTOM_ATTR_FIELDDEF;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
+{
+ MonoTableInfo *ca;
+ guint32 i, idx, method_index;
+ guint32 param_list, param_last, param_pos, found;
+ MonoImage *image;
+
+ /* FIXME: handle dynamic custom attrs for parameters */
+ /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
+ return cinfo;*/
+ image = method->klass->image;
+ method_index = find_method_index (method);
+ 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 <<= CUSTOM_ATTR_BITS;
+ idx |= CUSTOM_ATTR_PARAMDEF;
+ return mono_custom_attrs_from_index (image, idx);
+}
+
/*
* mono_reflection_get_custom_attrs:
* @obj: a reflection object handle
MonoArray*
mono_reflection_get_custom_attrs (MonoObject *obj)
{
- guint32 idx, mtoken, i, len;
- guint32 cols [MONO_CUSTOM_ATTR_SIZE];
MonoClass *klass;
- MonoImage *image;
- MonoTableInfo *ca;
- MonoMethod *method;
- MonoObject *attr;
MonoArray *result;
- GList *list = NULL;
- void **params;
+ MonoCustomAttrInfo *cinfo;
+ MONO_ARCH_SAVE_REGS;
+
klass = obj->vtable->klass;
/* FIXME: need to handle: Module */
if (klass == mono_defaults.monotype_class) {
MonoReflectionType *rtype = (MonoReflectionType*)obj;
klass = mono_class_from_mono_type (rtype->type);
- idx = mono_metadata_token_index (klass->type_token);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_TYPEDEF;
- image = klass->image;
+ cinfo = mono_custom_attrs_from_class (klass);
} else if (strcmp ("Assembly", klass->name) == 0) {
MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
- idx = 1; /* there is only one assembly */
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_ASSEMBLY;
- image = rassembly->assembly->image;
+ cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
} else if (strcmp ("MonoProperty", klass->name) == 0) {
MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
- idx = find_property_index (rprop->klass, rprop->property);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_PROPERTY;
- image = rprop->klass->image;
+ cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
} else if (strcmp ("MonoEvent", klass->name) == 0) {
MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
- idx = find_event_index (revent->klass, revent->event);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_EVENT;
- image = revent->klass->image;
+ cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
} else if (strcmp ("MonoField", klass->name) == 0) {
MonoReflectionField *rfield = (MonoReflectionField*)obj;
- idx = find_field_index (rfield->klass, rfield->field);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_FIELDDEF;
- image = rfield->klass->image;
+ cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
} else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
- idx = find_method_index (rmethod->method);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_METHODDEF;
- image = rmethod->method->klass->image;
+ cinfo = mono_custom_attrs_from_method (rmethod->method);
} else if (strcmp ("ParameterInfo", klass->name) == 0) {
MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
- guint32 method_index = find_method_index (rmethod->method);
- guint32 param_list, param_last, param_pos, found;
-
- image = rmethod->method->klass->image;
- 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 = 0;
- 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->PositionImpl) {
- found = 1;
- break;
- }
- }
- if (!found)
- return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
- idx = i;
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_PARAMDEF;
+ cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl);
+ } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
+ MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
+ cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
} else { /* handle other types here... */
g_error ("get custom attrs not yet supported for %s", klass->name);
}
- /* at this point image and index are set correctly for searching the custom attr */
- ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
- /* the table is not sorted */
- for (i = 0; i < ca->rows; ++i) {
- mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
- if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
- continue;
- mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
- switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
- case CUSTOM_ATTR_TYPE_METHODDEF:
- mtoken |= MONO_TOKEN_METHOD_DEF;
- break;
- case 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;
- }
- method = mono_get_method (image, mtoken, NULL);
- if (!method)
- g_error ("Can't find custom attr constructor");
- mono_class_init (method->klass);
- /*g_print ("got attr %s\n", method->klass->name);*/
- params = g_new (void*, method->signature->param_count);
- fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
- attr = mono_object_new (mono_domain_get (), method->klass);
- mono_runtime_invoke (method, attr, params, NULL);
- list = g_list_prepend (list, attr);
- free_param_data (method->signature, params);
- g_free (params);
- }
-
- len = g_list_length (list);
- /*
- * The return type is really object[], but System/Attribute.cs does a cast
- * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
- * probably fix that.
- */
- klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
- result = mono_array_new (mono_domain_get (), klass, len);
- for (i = 0; i < len; ++i) {
- mono_array_set (result, gpointer, i, list->data);
- list = list->next;
+ if (cinfo) {
+ result = mono_custom_attrs_construct (cinfo);
+ } else {
+ klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
+ result = mono_array_new (mono_domain_get (), klass, 0);
}
- g_list_free (g_list_first (list));
return result;
}
static MonoMethodSignature*
-ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
+parameters_to_signature (MonoArray *parameters) {
MonoMethodSignature *sig;
int count, i;
- count = ctor->parameters? mono_array_length (ctor->parameters): 0;
+ count = parameters? mono_array_length (parameters): 0;
sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
- sig->hasthis = 1;
sig->param_count = count;
sig->sentinelpos = -1; /* FIXME */
for (i = 0; i < count; ++i) {
- MonoReflectionType *pt = mono_array_get (ctor->parameters, MonoReflectionType*, i);
+ MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
sig->params [i] = pt->type;
}
return sig;
}
+static MonoMethodSignature*
+ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
+ MonoMethodSignature *sig;
+
+ sig = parameters_to_signature (ctor->parameters);
+ sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ return sig;
+}
+
+static MonoMethodSignature*
+method_builder_to_signature (MonoReflectionMethodBuilder *method) {
+ MonoMethodSignature *sig;
+
+ sig = parameters_to_signature (method->parameters);
+ sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
+ sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
+ return sig;
+}
+
static void
get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
{
MonoAssembly *ta;
name = mono_type_get_name (type);
- klass = mono_class_from_mono_type (type);
+ klass = my_mono_class_from_mono_type (type);
ta = klass->image->assembly;
if (ta == ass || klass->image == mono_defaults.corlib)
return name;
/* missing public key */
- result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
+ result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
name, ta->aname.name,
ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
}
break;
case MONO_TYPE_STRING: {
- char *str = mono_string_to_utf8 ((MonoString*)arg);
- guint32 slen = strlen (str);
+ char *str;
+ guint32 slen;
+ if (!arg) {
+ *p++ = 0xFF;
+ break;
+ }
+ str = mono_string_to_utf8 ((MonoString*)arg);
+ slen = strlen (str);
if ((p-buffer) + 10 + slen >= *buflen) {
char *newbuf;
*buflen *= 2;
case MONO_TYPE_CLASS: {
char *str;
guint32 slen;
- MonoClass *k = mono_object_class (arg);
+ MonoClass *k;
+ if (!arg) {
+ *p++ = 0xFF;
+ break;
+ }
+ k = mono_object_class (arg);
if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
(strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
g_error ("only types allowed, not %s.%s", k->name_space, k->name);
g_free (str);
break;
}
+ case MONO_TYPE_SZARRAY: {
+ int len, i;
+ MonoClass *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 = mono_class_from_mono_type (type)->element_class;
+ for (i = 0; i < len; ++i) {
+ encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
+ }
+ break;
+ }
/* it may be a boxed value or a Type */
case MONO_TYPE_OBJECT: {
MonoClass *klass = mono_object_class (arg);
goto handle_type;
} else 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->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
*p++ = simple_type = klass->byval_arg.type;
goto handle_enum;
* Returns: a Byte array representing the blob of data.
*/
MonoArray*
-mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
+mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+{
MonoArray *result;
MonoMethodSignature *sig;
MonoObject *arg;
char *buffer, *p;
guint32 buflen, i;
+ MONO_ARCH_SAVE_REGS;
+
if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
} else {
sig = ((MonoReflectionMethod*)ctor)->method->signature;
}
+ g_assert (mono_array_length (ctorArgs) == sig->param_count);
buflen = 256;
p = buffer = g_malloc (buflen);
/* write the prolog */
*p++ = 1;
*p++ = 0;
for (i = 0; i < sig->param_count; ++i) {
- arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
+ arg = mono_array_get (ctorArgs, MonoObject*, i);
encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
}
i = 0;
prop = mono_array_get (properties, gpointer, i);
get_prop_name_and_type (prop, &pname, &ptype);
*p++ = 0x54; /* PROPERTY signature */
+ if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
+ char *str = type_get_qualified_name (ptype, NULL);
+ int slen = strlen (str);
+ if ((p-buffer) + 10 + slen >= buflen) {
+ char *newbuf;
+ buflen *= 2;
+ buflen += slen;
+ newbuf = g_realloc (buffer, buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+ *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 {
+ mono_metadata_encode_value (ptype->type, p, &p);
+ }
len = strlen (pname);
mono_metadata_encode_value (len, p, &p);
memcpy (p, pname, len);
field = mono_array_get (fields, gpointer, i);
get_field_name_and_type (field, &fname, &ftype);
*p++ = 0x53; /* FIELD signature */
+ if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
+ char *str = type_get_qualified_name (ftype, NULL);
+ int slen = strlen (str);
+ if ((p-buffer) + 10 + slen >= buflen) {
+ char *newbuf;
+ buflen *= 2;
+ buflen += slen;
+ newbuf = g_realloc (buffer, buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+ *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 {
+ mono_metadata_encode_value (ftype->type, p, &p);
+ }
len = strlen (fname);
mono_metadata_encode_value (len, p, &p);
memcpy (p, fname, len);
{
MonoClass *klass, *parent;
+ MONO_ARCH_SAVE_REGS;
+
klass = g_new0 (MonoClass, 1);
klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
- if (tb->parent)
- parent = mono_class_from_mono_type (tb->parent->type);
- else
+ if (tb->parent) {
+ /* 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 = tb->parent->type->data.klass;
+ } else
+ parent = my_mono_class_from_mono_type (tb->parent->type);
+ } else
parent = NULL;
klass->inited = 1; /* we lie to the runtime */
klass->element_class = klass;
klass->reflection_info = tb; /* need to pin. */
+ /* Put into cache so mono_class_get () will find it */
+ mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
+ tb->table_idx);
+
+ mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
+ GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
+ 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;
+ }
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);
+ klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
+ }
+
/*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
}
{
MonoClass *klass;
- klass = mono_class_from_mono_type (tb->type.type);
+ MONO_ARCH_SAVE_REGS;
+
+ klass = my_mono_class_from_mono_type (tb->type.type);
if (klass->enumtype && klass->enum_basetype == NULL) {
MonoReflectionFieldBuilder *fb;
fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
klass->enum_basetype = fb->type->type;
- klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
+ klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
+ if (!klass->element_class)
+ klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
+ klass->instance_size = klass->element_class->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 (klass, NULL, 0);
+ }
+}
+
+static MonoMethod*
+reflection_methodbuilder_to_mono_method (MonoClass *klass,
+ ReflectionMethodBuilder *rmb,
+ MonoMethodSignature *sig)
+{
+ MonoMethod *m;
+ MonoMethodNormal *pm;
+
+ if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+ m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
+ else
+ m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
+
+ pm = (MonoMethodNormal*)m;
+
+ m->slot = -1;
+ m->flags = rmb->attrs;
+ m->iflags = rmb->iattrs;
+ m->name = mono_string_to_utf8 (rmb->name);
+ m->klass = klass;
+ m->signature = sig;
+ 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->addr = mono_lookup_internal_call (m);
+ m->signature->pinvoke = 1;
+ } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ /* TODO */
+ m->signature->pinvoke = 1;
+ return m;
+ } else if (!m->klass->dummy &&
+ !(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 = g_malloc0 (sizeof (MonoMethodHeader) +
+ (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ header->code_size = code_size;
+ header->code = g_malloc (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] = g_new0 (MonoType, 1);
+ memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
+ }
+
+ header->num_clauses = num_clauses;
+ if (num_clauses) {
+ header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
+ rmb->ilgen,
+ num_clauses);
+ }
+
+ pm->header = header;
+ }
+
+ return m;
+}
+
+static MonoMethod*
+ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
+{
+ ReflectionMethodBuilder rmb;
+ const char *name;
+ MonoMethodSignature *sig;
+
+ name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
+
+ sig = ctor_builder_to_signature (mb);
+
+ rmb.ilgen = mb->ilgen;
+ rmb.parameters = mb->parameters;
+ rmb.pinfo = mb->pinfo;
+ rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
+ rmb.iattrs = mb->iattrs;
+ rmb.call_conv = mb->call_conv;
+ 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.code = NULL;
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+
+ return mb->mhandle;
+}
+
+static MonoMethod*
+methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
+{
+ ReflectionMethodBuilder rmb;
+ MonoMethodSignature *sig;
+
+ sig = method_builder_to_signature (mb);
+
+ rmb.ilgen = mb->ilgen;
+ rmb.parameters = mb->parameters;
+ rmb.pinfo = mb->pinfo;
+ rmb.attrs = mb->attrs;
+ rmb.iattrs = mb->iattrs;
+ rmb.call_conv = mb->call_conv;
+ rmb.type = mb->type;
+ rmb.name = mb->name;
+ rmb.table_idx = &mb->table_idx;
+ rmb.init_locals = mb->init_locals;
+ rmb.code = mb->code;
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+ return mb->mhandle;
+}
+
+static void
+ensure_runtime_vtable (MonoClass *klass)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ int i, num, j, onum;
+ MonoMethod **overrides;
+
+ if (!tb || klass->wastypebuilder)
+ return;
+ if (klass->parent)
+ ensure_runtime_vtable (klass->parent);
+
+ num = tb->ctors? mono_array_length (tb->ctors): 0;
+ num += tb->methods? mono_array_length (tb->methods): 0;
+ klass->method.count = num;
+ klass->methods = g_new (MonoMethod*, num);
+ num = tb->ctors? mono_array_length (tb->ctors): 0;
+ for (i = 0; i < num; ++i)
+ klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
+ num = tb->methods? mono_array_length (tb->methods): 0;
+ j = i;
+ for (i = 0; i < num; ++i)
+ klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
+
+ klass->wastypebuilder = TRUE;
+ if (tb->interfaces) {
+ klass->interface_count = mono_array_length (tb->interfaces);
+ klass->interfaces = g_new (MonoClass*, klass->interface_count);
+ for (i = 0; i < klass->interface_count; ++i) {
+ MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
+ klass->interfaces [i] = mono_class_from_mono_type (iface->type);
+ }
+ }
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+ for (i = 0; i < klass->method.count; ++i)
+ klass->methods [i]->slot = i;
+
+ /* Overrides */
+ onum = 0;
+ if (tb->methods) {
+ for (i = 0; i < mono_array_length (tb->methods); ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_method)
+ onum ++;
+ }
+ }
+
+ overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
+
+ if (tb->methods) {
+ onum = 0;
+ for (i = 0; i < mono_array_length (tb->methods); ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_method) {
+ /* FIXME: What if 'override_method' is a MethodBuilder ? */
+ overrides [onum * 2] =
+ mb->override_method->method;
+ overrides [onum * 2 + 1] =
+ mb->mhandle;
+
+ g_assert (mb->mhandle);
+
+ onum ++;
+ }
+ }
+ }
+
+ mono_class_setup_vtable (klass, overrides, onum);
+}
+
+static void
+typebuilder_setup_fields (MonoClass *klass)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionFieldBuilder *fb;
+ MonoClassField *field;
+ const char *p, *p2;
+ int i;
+ guint32 len, idx;
+
+ klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
+ klass->field.first = 0;
+ klass->field.last = klass->field.count;
+
+ if (!klass->field.count)
+ return;
+
+ klass->fields = g_new0 (MonoClassField, klass->field.count);
+
+ for (i = 0; i < klass->field.count; ++i) {
+ fb = mono_array_get (tb->fields, gpointer, i);
+ field = &klass->fields [i];
+ field->name = mono_string_to_utf8 (fb->name);
+ if (fb->attrs) {
+ /* FIXME: handle type modifiers */
+ field->type = g_memdup (fb->type->type, sizeof (MonoType));
+ field->type->attrs = fb->attrs;
+ } else {
+ field->type = fb->type->type;
+ }
+ if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
+ field->data = mono_array_addr (fb->rva_data, char, 0);
+ if (fb->offset != -1)
+ field->offset = fb->offset;
+ field->parent = klass;
+ fb->handle = field;
+ mono_save_custom_attrs (klass->image, field, fb->cattrs);
+
+ if (fb->def_value) {
+ field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+ MonoDynamicAssembly *assembly = klass->image->assembly->dynamic;
+ field->def_value = g_new0 (MonoConstant, 1);
+ idx = encode_constant (assembly, fb->def_value, &field->def_value->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;
+ field->def_value->value = g_malloc (len);
+ memcpy (field->def_value->value, p, len);
+ }
+ }
+ mono_class_layout_fields (klass);
+}
+
+MonoReflectionType*
+mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoClass *klass;
+ MonoReflectionType* res;
+
+ MONO_ARCH_SAVE_REGS;
+
+ klass = my_mono_class_from_mono_type (tb->type.type);
+
+ mono_save_custom_attrs (klass->image, klass, tb->cattrs);
+
+ /*
+ * Fields to set in klass:
+ * the various flags: delegate/unicode/contextbound etc.
+ * nested_classes
+ * properties
+ * events
+ */
+ klass->flags = tb->attrs;
+ klass->element_class = klass;
+
+ if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->run)
+ /* No need to fully construct the type */
+ return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+
+ /* enums are done right away */
+ if (!klass->enumtype)
+ ensure_runtime_vtable (klass);
+
+ /* 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->class_size += klass->parent->class_size;
+ klass->min_align = klass->parent->min_align;
+ } else {
+ klass->instance_size = sizeof (MonoObject);
+ klass->min_align = 1;
}
+
+ /* FIXME: handle packing_size and instance_size */
+ typebuilder_setup_fields (klass);
+
+ /* FIXME: properties */
+
+ res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+ /* with enums res == tb: need to fix that. */
+ if (!klass->enumtype)
+ g_assert (res != (MonoReflectionType*)tb);
+ return res;
}
MonoArray *
MonoArray *result;
char *buf, *p;
+ MONO_ARCH_SAVE_REGS;
+
p = buf = g_malloc (10 + na * 10);
mono_metadata_encode_value (0x07, p, &p);
MonoArray *result;
char *buf, *p;
+ MONO_ARCH_SAVE_REGS;
+
p = buf = g_malloc (10 + na * 10);
mono_metadata_encode_value (0x06, p, &p);
return result;
}
+gpointer
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
+{
+ MonoDynamicAssembly *assembly = image->assembly->dynamic;
+ MonoObject *obj;
+ gpointer result;
+
+ obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
+ g_assert (obj);
+
+ if (strcmp (obj->vtable->klass->name, "String") == 0) {
+ result = obj;
+ g_assert (result);
+ }
+ else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
+ MonoReflectionType *tb = (MonoReflectionType*)obj;
+ result = mono_class_from_mono_type (tb->type);
+ g_assert (result);
+ }
+ else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
+ result = ((MonoReflectionMethod*)obj)->method;
+ g_assert (result);
+ }
+ else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
+ result = ((MonoReflectionMethod*)obj)->method;
+ 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 (mono_domain_get (), NULL, (MonoObject*)tb);
+
+ /*
+ * 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;
+ }
+ }
+ 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 (mono_domain_get (), NULL, (MonoObject*)tb);
+ result = cb->mhandle;
+ }
+ }
+ else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
+ result = ((MonoReflectionField*)obj)->field;
+ 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 (mono_domain_get (), NULL, (MonoObject*)tb);
+ result = fb->handle;
+ }
+ }
+ else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
+ MonoClass *klass;
+
+ klass = tb->type.type->data.klass;
+ if (klass->wastypebuilder) {
+ /* Already created */
+ result = klass;
+ }
+ else {
+ mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
+ result = tb->type.type->data.klass;
+ g_assert (result);
+ }
+ }
+ 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;
+ sig->hasthis = helper->call_conv & 32;
+
+ if (helper->call_conv == 0) /* unmanaged */
+ sig->call_convention = helper->unmanaged_call_conv - 1;
+ 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) {
+ MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
+ sig->params [i] = rt->type;
+ }
+
+ result = sig;
+ }
+ else {
+ g_print (obj->vtable->klass->name);
+ g_assert_not_reached ();
+ }
+ return result;
+}
+
+
+
+