3 * Routine for saving an image to a file.
7 * Paolo Molaro (lupus@ximian.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011 Rodrigo Kumpera
12 * Copyright 2016 Microsoft
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include "mono/metadata/dynamic-image-internals.h"
21 #include "mono/metadata/dynamic-stream-internals.h"
22 #include "mono/metadata/mono-ptr-array.h"
23 #include "mono/metadata/object-internals.h"
24 #include "mono/metadata/sre-internals.h"
25 #include "mono/metadata/security-manager.h"
26 #include "mono/metadata/tabledefs.h"
27 #include "mono/metadata/tokentype.h"
28 #include "mono/metadata/w32file.h"
29 #include "mono/metadata/w32error.h"
31 #include "mono/utils/checked-build.h"
32 #include "mono/utils/mono-digest.h"
33 #include "mono/utils/mono-error-internals.h"
34 #include "mono/utils/w32api.h"
36 #define TEXT_OFFSET 512
37 #define CLI_H_SIZE 136
38 #define FILE_ALIGN 512
39 #define VIRT_ALIGN 8192
40 #define START_TEXT_RVA 0x00002000
42 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
45 alloc_table (MonoDynamicTable *table, guint nrows)
47 mono_dynimage_alloc_table (table, nrows);
51 string_heap_insert (MonoDynamicStream *sh, const char *str)
53 return mono_dynstream_insert_string (sh, str);
57 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
59 return mono_dynstream_insert_mstring (sh, str, error);
63 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
65 return mono_dynstream_add_data (stream, data, len);
69 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
71 return mono_dynstream_add_zero (stream, len);
75 stream_data_align (MonoDynamicStream *stream)
77 mono_dynstream_data_align (stream);
81 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
83 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
87 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
89 MONO_REQ_GC_NEUTRAL_MODE;
92 MonoDynamicTable *table;
95 table = &assembly->tables [table_idx];
97 g_assert (col < table->columns);
99 values = table->values + table->columns;
100 for (i = 1; i <= table->rows; ++i) {
101 if (values [col] == token)
103 values += table->columns;
109 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
110 * dest may be misaligned.
113 swap_with_size (char *dest, const char* val, int len, int nelem) {
114 MONO_REQ_GC_NEUTRAL_MODE;
115 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
118 for (elem = 0; elem < nelem; ++elem) {
144 g_assert_not_reached ();
150 memcpy (dest, val, len * nelem);
155 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
157 MONO_REQ_GC_UNSAFE_MODE;
161 guint32 idx = 0, len;
163 len = str->length * 2;
164 mono_metadata_encode_value (len, b, &b);
165 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
167 char *swapped = g_malloc (2 * mono_string_length (str));
168 const char *p = (const char*)mono_string_chars (str);
170 swap_with_size (swapped, p, 2, mono_string_length (str));
171 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
175 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
181 image_create_token_raw (MonoDynamicImage *assembly, MonoObject* obj_raw, gboolean create_methodspec, gboolean register_token, MonoError *error)
183 HANDLE_FUNCTION_ENTER (); /* FIXME callers of image_create_token_raw should use handles */
185 MONO_HANDLE_DCL (MonoObject, obj);
186 guint32 result = mono_image_create_token (assembly, obj, create_methodspec, register_token, error);
187 HANDLE_FUNCTION_RETURN_VAL (result);
192 * idx is the table index of the object
193 * type is one of MONO_CUSTOM_ATTR_*
196 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
198 MONO_REQ_GC_UNSAFE_MODE;
200 MonoDynamicTable *table;
201 MonoReflectionCustomAttr *cattr;
203 guint32 count, i, token;
209 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
212 count = mono_array_length (cattrs);
213 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
214 table->rows += count;
215 alloc_table (table, table->rows);
216 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
217 idx <<= MONO_CUSTOM_ATTR_BITS;
219 for (i = 0; i < count; ++i) {
220 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
221 values [MONO_CUSTOM_ATTR_PARENT] = idx;
222 g_assert (cattr->ctor != NULL);
223 if (mono_is_sre_ctor_builder (mono_object_class (cattr->ctor))) {
224 MonoReflectionCtorBuilder *ctor = (MonoReflectionCtorBuilder*)cattr->ctor;
225 MonoMethod *method = ctor->mhandle;
226 if (method->klass->image == &assembly->image)
227 token = MONO_TOKEN_METHOD_DEF | ((MonoReflectionCtorBuilder*)cattr->ctor)->table_idx;
229 token = mono_image_get_methodref_token (assembly, method, FALSE);
231 token = image_create_token_raw (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error); /* FIXME use handles */
232 if (!mono_error_ok (error)) goto fail;
234 type = mono_metadata_token_index (token);
235 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
236 switch (mono_metadata_token_table (token)) {
237 case MONO_TABLE_METHOD:
238 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
240 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
241 * method, not the one returned by mono_image_create_token ().
243 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
245 case MONO_TABLE_MEMBERREF:
246 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
249 g_warning ("got wrong token in custom attr");
252 values [MONO_CUSTOM_ATTR_TYPE] = type;
254 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
255 values [MONO_CUSTOM_ATTR_VALUE] = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, p - blob_size,
256 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
257 values += MONO_CUSTOM_ATTR_SIZE;
268 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
270 MONO_REQ_GC_UNSAFE_MODE;
272 MonoDynamicTable *table;
274 guint32 count, i, idx;
275 MonoReflectionPermissionSet *perm;
280 count = mono_array_length (permissions);
281 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
282 table->rows += count;
283 alloc_table (table, table->rows);
285 for (i = 0; i < mono_array_length (permissions); ++i) {
286 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
288 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
290 idx = mono_metadata_token_index (parent_token);
291 idx <<= MONO_HAS_DECL_SECURITY_BITS;
292 switch (mono_metadata_token_table (parent_token)) {
293 case MONO_TABLE_TYPEDEF:
294 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
296 case MONO_TABLE_METHOD:
297 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
299 case MONO_TABLE_ASSEMBLY:
300 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
303 g_assert_not_reached ();
306 values [MONO_DECL_SECURITY_ACTION] = perm->action;
307 values [MONO_DECL_SECURITY_PARENT] = idx;
308 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
315 * method_encode_code:
317 * @assembly the assembly
318 * @mb the managed MethodBuilder
319 * @error set on error
321 * Note that the return value is not sensible if @error is set.
324 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
326 MONO_REQ_GC_UNSAFE_MODE;
332 gint32 num_locals = 0;
333 gint32 num_exception = 0;
336 char fat_header [12];
339 guint32 local_sig = 0;
340 guint32 header_size = 12;
345 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
346 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
350 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
352 code = mb->ilgen->code;
353 code_size = mb->ilgen->code_len;
354 max_stack = mb->ilgen->max_stack;
355 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
356 if (mb->ilgen->ex_handlers)
357 num_exception = mono_reflection_method_count_clauses (mb->ilgen);
361 MonoError inner_error;
362 char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
363 if (!is_ok (&inner_error)) {
364 name = g_strdup ("");
365 mono_error_cleanup (&inner_error);
367 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
368 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
374 code_size = mono_array_length (code);
375 max_stack = 8; /* we probably need to run a verifier on the code... */
378 stream_data_align (&assembly->code);
380 /* check for exceptions, maxstack, locals */
381 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
383 if (code_size < 64 && !(code_size & 1)) {
384 flags = (code_size << 2) | 0x2;
385 } else if (code_size < 32 && (code_size & 1)) {
386 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
390 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
391 /* add to the fixup todo list */
392 if (mb->ilgen && mb->ilgen->num_token_fixups)
393 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
394 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
395 return assembly->text_rva + idx;
399 local_sig = MONO_TOKEN_SIGNATURE | mono_dynimage_encode_locals (assembly, mb->ilgen, error);
400 return_val_if_nok (error, 0);
403 * FIXME: need to set also the header size in fat_flags.
404 * (and more sects and init locals flags)
408 fat_flags |= METHOD_HEADER_MORE_SECTS;
410 fat_flags |= METHOD_HEADER_INIT_LOCALS;
411 fat_header [0] = fat_flags;
412 fat_header [1] = (header_size / 4 ) << 4;
413 short_value = GUINT16_TO_LE (max_stack);
414 memcpy (fat_header + 2, &short_value, 2);
415 int_value = GUINT32_TO_LE (code_size);
416 memcpy (fat_header + 4, &int_value, 4);
417 int_value = GUINT32_TO_LE (local_sig);
418 memcpy (fat_header + 8, &int_value, 4);
419 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
420 /* add to the fixup todo list */
421 if (mb->ilgen && mb->ilgen->num_token_fixups)
422 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
424 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
426 unsigned char sheader [4];
427 MonoILExceptionInfo * ex_info;
428 MonoILExceptionBlock * ex_block;
431 stream_data_align (&assembly->code);
432 /* always use fat format for now */
433 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
434 num_exception *= 6 * sizeof (guint32);
435 num_exception += 4; /* include the size of the header */
436 sheader [1] = num_exception & 0xff;
437 sheader [2] = (num_exception >> 8) & 0xff;
438 sheader [3] = (num_exception >> 16) & 0xff;
439 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
440 /* fat header, so we are already aligned */
442 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
443 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
444 if (ex_info->handlers) {
445 int finally_start = ex_info->start + ex_info->len;
446 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
448 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
450 val = GUINT32_TO_LE (ex_block->type);
451 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
453 val = GUINT32_TO_LE (ex_info->start);
454 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
455 /* need fault, too, probably */
456 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
457 val = GUINT32_TO_LE (finally_start - ex_info->start);
459 val = GUINT32_TO_LE (ex_info->len);
460 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
462 val = GUINT32_TO_LE (ex_block->start);
463 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
465 val = GUINT32_TO_LE (ex_block->len);
466 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
467 finally_start = ex_block->start + ex_block->len;
468 if (ex_block->extype) {
469 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
470 return_val_if_nok (error, 0);
472 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
474 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
475 val = ex_block->filter_offset;
479 val = GUINT32_TO_LE (val);
480 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
481 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
482 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
485 g_error ("No clauses for ex info block %d", i);
489 return assembly->text_rva + idx;
493 * Fill in the MethodDef and ParamDef tables for a method.
494 * This is used for both normal methods and constructors.
497 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
499 MONO_REQ_GC_UNSAFE_MODE;
501 MonoDynamicTable *table;
507 /* room in this table is already allocated */
508 table = &assembly->tables [MONO_TABLE_METHOD];
509 *mb->table_idx = table->next_idx ++;
510 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
511 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
512 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
513 return_val_if_nok (error, FALSE);
514 values [MONO_METHOD_FLAGS] = mb->attrs;
515 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
516 values [MONO_METHOD_SIGNATURE] = mono_dynimage_encode_method_builder_signature (assembly, mb, error);
517 return_val_if_nok (error, FALSE);
518 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
519 return_val_if_nok (error, FALSE);
521 table = &assembly->tables [MONO_TABLE_PARAM];
522 values [MONO_METHOD_PARAMLIST] = table->next_idx;
524 mono_image_add_decl_security (assembly,
525 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
528 MonoDynamicTable *mtable;
531 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
532 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
535 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
536 if (mono_array_get (mb->pinfo, gpointer, i))
539 table->rows += count;
540 alloc_table (table, table->rows);
541 values = table->values + table->next_idx * MONO_PARAM_SIZE;
542 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
543 MonoReflectionParamBuilder *pb;
544 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
545 values [MONO_PARAM_FLAGS] = pb->attrs;
546 values [MONO_PARAM_SEQUENCE] = i;
547 if (pb->name != NULL) {
548 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
549 return_val_if_nok (error, FALSE);
551 values [MONO_PARAM_NAME] = 0;
553 values += MONO_PARAM_SIZE;
554 if (pb->marshal_info) {
556 alloc_table (mtable, mtable->rows);
557 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
558 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
559 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = mono_dynimage_save_encode_marshal_blob (assembly, pb->marshal_info, error);
560 return_val_if_nok (error, FALSE);
562 pb->table_idx = table->next_idx++;
563 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
564 guint32 field_type = 0;
565 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
567 alloc_table (mtable, mtable->rows);
568 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
569 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
570 mvalues [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, pb->def_value, &field_type);
571 mvalues [MONO_CONSTANT_TYPE] = field_type;
572 mvalues [MONO_CONSTANT_PADDING] = 0;
582 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
584 MONO_REQ_GC_UNSAFE_MODE;
586 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
587 MonoDynamicTable *table;
590 MonoReflectionMethod *m;
595 if (!mb->override_methods)
598 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
599 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
601 table = &assembly->tables [MONO_TABLE_METHODIMPL];
603 alloc_table (table, table->rows);
604 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
605 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
606 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
608 tok = image_create_token_raw (assembly, (MonoObject*)m, FALSE, FALSE, error); /* FIXME use handles */
609 return_val_if_nok (error, FALSE);
611 switch (mono_metadata_token_table (tok)) {
612 case MONO_TABLE_MEMBERREF:
613 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
615 case MONO_TABLE_METHOD:
616 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
619 g_assert_not_reached ();
621 values [MONO_METHODIMPL_DECLARATION] = tok;
627 #ifndef DISABLE_REFLECTION_EMIT
629 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
631 MONO_REQ_GC_UNSAFE_MODE;
633 MonoDynamicTable *table;
635 ReflectionMethodBuilder rmb;
640 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
641 !mono_image_basic_method (&rmb, assembly, error))
644 mb->table_idx = *rmb.table_idx;
646 if (mb->dll) { /* It's a P/Invoke method */
648 /* map CharSet values to on-disk values */
649 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
650 int extra_flags = mb->extra_flags;
651 table = &assembly->tables [MONO_TABLE_IMPLMAP];
653 alloc_table (table, table->rows);
654 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
656 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
657 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
659 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
660 return_val_if_nok (error, FALSE);
662 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
663 return_val_if_nok (error, FALSE);
665 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
666 return_val_if_nok (error, FALSE);
667 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
668 table = &assembly->tables [MONO_TABLE_MODULEREF];
670 alloc_table (table, table->rows);
671 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
672 values [MONO_IMPLMAP_SCOPE] = table->rows;
676 if (mb->generic_params) {
677 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
678 table->rows += mono_array_length (mb->generic_params);
679 alloc_table (table, table->rows);
680 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
681 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
683 mono_image_get_generic_param_info (
684 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
692 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
694 MONO_REQ_GC_UNSAFE_MODE;
696 ReflectionMethodBuilder rmb;
698 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
701 if (!mono_image_basic_method (&rmb, assembly, error))
704 mb->table_idx = *rmb.table_idx;
711 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
713 MONO_REQ_GC_UNSAFE_MODE;
717 MonoDynamicTable *table;
720 /* maybe this fixup should be done in the C# code */
721 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
722 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
723 table = &assembly->tables [MONO_TABLE_FIELD];
724 fb->table_idx = table->next_idx ++;
725 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
726 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
727 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
728 return_if_nok (error);
729 values [MONO_FIELD_FLAGS] = fb->attrs;
730 values [MONO_FIELD_SIGNATURE] = mono_dynimage_encode_field_signature (assembly, fb, error);
731 return_if_nok (error);
733 if (fb->offset != -1) {
734 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
736 alloc_table (table, table->rows);
737 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
738 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
739 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
741 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
742 MonoTypeEnum field_type = (MonoTypeEnum)0;
743 table = &assembly->tables [MONO_TABLE_CONSTANT];
745 alloc_table (table, table->rows);
746 values = table->values + table->rows * MONO_CONSTANT_SIZE;
747 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
748 values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, fb->def_value, &field_type);
749 values [MONO_CONSTANT_TYPE] = field_type;
750 values [MONO_CONSTANT_PADDING] = 0;
752 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
754 table = &assembly->tables [MONO_TABLE_FIELDRVA];
756 alloc_table (table, table->rows);
757 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
758 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
760 * We store it in the code section because it's simpler for now.
763 if (mono_array_length (fb->rva_data) >= 10)
764 stream_data_align (&assembly->code);
765 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
767 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
768 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
770 if (fb->marshal_info) {
771 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
773 alloc_table (table, table->rows);
774 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
775 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
776 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = mono_dynimage_save_encode_marshal_blob (assembly, fb->marshal_info, error);
777 return_if_nok (error);
782 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
784 MONO_REQ_GC_UNSAFE_MODE;
788 MonoDynamicTable *table;
790 guint num_methods = 0;
794 * we need to set things in the following tables:
795 * PROPERTYMAP (info already filled in _get_type_info ())
796 * PROPERTY (rows already preallocated in _get_type_info ())
797 * METHOD (method info already done with the generic method code)
801 table = &assembly->tables [MONO_TABLE_PROPERTY];
802 pb->table_idx = table->next_idx ++;
803 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
804 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
805 return_if_nok (error);
806 values [MONO_PROPERTY_FLAGS] = pb->attrs;
807 values [MONO_PROPERTY_TYPE] = mono_dynimage_save_encode_property_signature (assembly, pb, error);
808 return_if_nok (error);
811 /* FIXME: we still don't handle 'other' methods */
812 if (pb->get_method) num_methods ++;
813 if (pb->set_method) num_methods ++;
815 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
816 table->rows += num_methods;
817 alloc_table (table, table->rows);
819 if (pb->get_method) {
820 semaidx = table->next_idx ++;
821 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
822 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
823 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
824 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
826 if (pb->set_method) {
827 semaidx = table->next_idx ++;
828 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
829 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
830 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
831 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
833 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
834 MonoTypeEnum field_type = (MonoTypeEnum)0;
835 table = &assembly->tables [MONO_TABLE_CONSTANT];
837 alloc_table (table, table->rows);
838 values = table->values + table->rows * MONO_CONSTANT_SIZE;
839 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
840 values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, pb->def_value, &field_type);
841 values [MONO_CONSTANT_TYPE] = field_type;
842 values [MONO_CONSTANT_PADDING] = 0;
847 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
849 MONO_REQ_GC_UNSAFE_MODE;
851 MonoDynamicTable *table;
853 guint num_methods = 0;
857 * we need to set things in the following tables:
858 * EVENTMAP (info already filled in _get_type_info ())
859 * EVENT (rows already preallocated in _get_type_info ())
860 * METHOD (method info already done with the generic method code)
863 table = &assembly->tables [MONO_TABLE_EVENT];
864 eb->table_idx = table->next_idx ++;
865 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
866 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
867 return_if_nok (error);
868 values [MONO_EVENT_FLAGS] = eb->attrs;
869 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
870 return_if_nok (error);
871 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
874 * FIXME: we still don't handle 'other' methods
876 if (eb->add_method) num_methods ++;
877 if (eb->remove_method) num_methods ++;
878 if (eb->raise_method) num_methods ++;
880 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
881 table->rows += num_methods;
882 alloc_table (table, table->rows);
884 if (eb->add_method) {
885 semaidx = table->next_idx ++;
886 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
887 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
888 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
889 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
891 if (eb->remove_method) {
892 semaidx = table->next_idx ++;
893 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
894 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
895 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
896 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
898 if (eb->raise_method) {
899 semaidx = table->next_idx ++;
900 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
901 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
902 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
903 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
908 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
910 MONO_REQ_GC_UNSAFE_MODE;
914 MonoDynamicTable *table;
915 guint32 num_constraints, i;
919 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
920 num_constraints = gparam->iface_constraints ?
921 mono_array_length (gparam->iface_constraints) : 0;
922 table->rows += num_constraints;
923 if (gparam->base_type)
925 alloc_table (table, table->rows);
927 if (gparam->base_type) {
928 table_idx = table->next_idx ++;
929 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
931 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
932 return_if_nok (error);
933 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
934 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
937 for (i = 0; i < num_constraints; i++) {
938 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
939 gparam->iface_constraints, gpointer, i);
941 table_idx = table->next_idx ++;
942 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
944 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
945 return_if_nok (error);
947 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
948 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
953 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
955 MONO_REQ_GC_UNSAFE_MODE;
957 GenericParamTableEntry *entry;
960 * The GenericParam table must be sorted according to the `owner' field.
961 * We need to do this sorting prior to writing the GenericParamConstraint
962 * table, since we have to use the final GenericParam table indices there
963 * and they must also be sorted.
966 entry = g_new0 (GenericParamTableEntry, 1);
967 entry->owner = owner;
968 /* FIXME: track where gen_params should be freed and remove the GC root as well */
969 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
970 entry->gparam = gparam;
972 g_ptr_array_add (assembly->gen_params, entry);
976 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
978 MONO_REQ_GC_UNSAFE_MODE;
980 MonoDynamicTable *table;
981 MonoGenericParam *param;
987 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
988 table_idx = table->next_idx ++;
989 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
991 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
992 return_val_if_nok (error, FALSE);
994 param = gparam_type->data.generic_param;
996 values [MONO_GENERICPARAM_OWNER] = entry->owner;
997 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
998 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
999 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
1001 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
1004 encode_constraints (entry->gparam, table_idx, assembly, error);
1005 return_val_if_nok (error, FALSE);
1011 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
1015 mono_ptr_array_append (*types, type);
1017 if (!type->subtypes)
1020 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
1021 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
1022 collect_types (types, subtype);
1027 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
1029 if ((*type1)->table_idx < (*type2)->table_idx)
1032 if ((*type1)->table_idx > (*type2)->table_idx)
1039 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
1045 for (i = 0; i < mono_array_length (pinfo); ++i) {
1046 MonoReflectionParamBuilder *pb;
1047 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1050 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
1058 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
1063 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
1066 for (i = 0; i < tb->num_fields; ++i) {
1067 MonoReflectionFieldBuilder* fb;
1068 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1069 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
1074 for (i = 0; i < mono_array_length (tb->events); ++i) {
1075 MonoReflectionEventBuilder* eb;
1076 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1077 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
1081 if (tb->properties) {
1082 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1083 MonoReflectionPropertyBuilder* pb;
1084 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1085 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
1090 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1091 MonoReflectionCtorBuilder* cb;
1092 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1093 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
1094 !params_add_cattrs (assembly, cb->pinfo, error))
1100 for (i = 0; i < tb->num_methods; ++i) {
1101 MonoReflectionMethodBuilder* mb;
1102 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1103 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
1104 !params_add_cattrs (assembly, mb->pinfo, error))
1110 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1111 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
1120 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
1126 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
1129 if (moduleb->global_methods) {
1130 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
1131 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
1132 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
1133 !params_add_cattrs (assembly, mb->pinfo, error))
1138 if (moduleb->global_fields) {
1139 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
1140 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
1141 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
1146 if (moduleb->types) {
1147 for (i = 0; i < moduleb->num_types; ++i) {
1148 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
1157 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
1159 MonoDynamicTable *table;
1163 char *b = blob_size;
1168 table = &assembly->tables [MONO_TABLE_FILE];
1170 alloc_table (table, table->rows);
1171 values = table->values + table->next_idx * MONO_FILE_SIZE;
1172 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
1173 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
1174 if (image_is_dynamic (module->image)) {
1175 /* This depends on the fact that the main module is emitted last */
1176 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
1177 return_val_if_nok (error, FALSE);
1178 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
1181 path = g_strdup (module->image->name);
1183 mono_sha1_get_digest_from_file (path, hash);
1186 mono_metadata_encode_value (20, b, &b);
1187 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1188 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1194 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1196 MonoDynamicTable *table;
1201 table = &assembly->tables [MONO_TABLE_MODULE];
1202 mb->table_idx = table->next_idx ++;
1203 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
1204 return_if_nok (error);
1205 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1208 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
1209 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1210 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1211 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1215 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
1216 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
1218 MonoDynamicTable *table;
1222 visib = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1223 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
1226 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
1228 alloc_table (table, table->rows);
1229 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
1231 values [MONO_EXP_TYPE_FLAGS] = mono_class_get_flags (klass);
1232 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
1233 if (klass->nested_in)
1234 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
1236 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
1237 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1238 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1240 res = table->next_idx;
1244 /* Emit nested types */
1245 GList *nested_classes = mono_class_get_nested_classes_property (klass);
1247 for (tmp = nested_classes; tmp; tmp = tmp->next)
1248 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
1254 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
1255 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
1263 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
1264 return_if_nok (error);
1266 klass = mono_class_from_mono_type (t);
1268 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
1270 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
1271 parent_index, assembly);
1275 * We need to do this ourselves since klass->nested_classes is not set up.
1278 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1279 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
1280 return_if_nok (error);
1286 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
1287 guint32 module_index, MonoDynamicImage *assembly)
1289 MonoImage *image = module->image;
1293 t = &image->tables [MONO_TABLE_TYPEDEF];
1295 for (i = 0; i < t->rows; ++i) {
1297 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
1298 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1300 if (mono_class_is_public (klass))
1301 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
1306 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
1308 MonoDynamicTable *table;
1310 guint32 scope, scope_idx, impl, current_idx;
1311 gboolean forwarder = TRUE;
1312 gpointer iter = NULL;
1315 if (klass->nested_in) {
1316 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
1319 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
1320 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
1321 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
1322 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
1325 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
1328 alloc_table (table, table->rows);
1329 current_idx = table->next_idx;
1330 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
1332 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
1333 values [MONO_EXP_TYPE_TYPEDEF] = 0;
1334 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
1335 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1336 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1340 while ((nested = mono_class_get_nested_types (klass, &iter)))
1341 add_exported_type (assemblyb, assembly, nested, current_idx);
1345 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
1351 if (!assemblyb->type_forwarders)
1354 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
1355 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
1360 type = mono_reflection_type_get_handle (t, &error);
1361 mono_error_assert_ok (&error);
1364 klass = mono_class_from_mono_type (type);
1366 add_exported_type (assemblyb, assembly, klass, 0);
1370 #define align_pointer(base,p)\
1372 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1374 (p) += 4 - (__diff & 3);\
1378 compare_constants (const void *a, const void *b)
1380 const guint32 *a_values = (const guint32 *)a;
1381 const guint32 *b_values = (const guint32 *)b;
1382 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
1386 compare_semantics (const void *a, const void *b)
1388 const guint32 *a_values = (const guint32 *)a;
1389 const guint32 *b_values = (const guint32 *)b;
1390 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1393 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1397 compare_custom_attrs (const void *a, const void *b)
1399 const guint32 *a_values = (const guint32 *)a;
1400 const guint32 *b_values = (const guint32 *)b;
1402 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1406 compare_field_marshal (const void *a, const void *b)
1408 const guint32 *a_values = (const guint32 *)a;
1409 const guint32 *b_values = (const guint32 *)b;
1411 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1415 compare_nested (const void *a, const void *b)
1417 const guint32 *a_values = (const guint32 *)a;
1418 const guint32 *b_values = (const guint32 *)b;
1420 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1424 compare_genericparam (const void *a, const void *b)
1427 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
1428 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
1430 if ((*b_entry)->owner == (*a_entry)->owner) {
1431 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
1432 mono_error_assert_ok (&error);
1433 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
1434 mono_error_assert_ok (&error);
1436 mono_type_get_generic_param_num (a_type) -
1437 mono_type_get_generic_param_num (b_type);
1439 return (*a_entry)->owner - (*b_entry)->owner;
1443 compare_declsecurity_attrs (const void *a, const void *b)
1445 const guint32 *a_values = (const guint32 *)a;
1446 const guint32 *b_values = (const guint32 *)b;
1448 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
1452 compare_interface_impl (const void *a, const void *b)
1454 const guint32 *a_values = (const guint32 *)a;
1455 const guint32 *b_values = (const guint32 *)b;
1457 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
1461 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
1466 MonoDynamicStream *stream;
1470 * build_compressed_metadata() fills in the blob of data that represents the
1471 * raw metadata as it will be saved in the PE file. The five streams are output
1472 * and the metadata tables are comnpressed from the guint32 array representation,
1473 * to the compressed on-disk format.
1476 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
1478 MonoDynamicTable *table;
1480 guint64 valid_mask = 0;
1481 guint64 sorted_mask;
1482 guint32 heapt_size = 0;
1483 guint32 meta_size = 256; /* allow for header and other stuff */
1484 guint32 table_offset;
1485 guint32 ntables = 0;
1491 struct StreamDesc stream_desc [5];
1495 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
1496 for (i = 0; i < assembly->gen_params->len; i++) {
1497 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
1498 if (!write_generic_param_entry (assembly, entry, error))
1502 stream_desc [0].name = "#~";
1503 stream_desc [0].stream = &assembly->tstream;
1504 stream_desc [1].name = "#Strings";
1505 stream_desc [1].stream = &assembly->sheap;
1506 stream_desc [2].name = "#US";
1507 stream_desc [2].stream = &assembly->us;
1508 stream_desc [3].name = "#Blob";
1509 stream_desc [3].stream = &assembly->blob;
1510 stream_desc [4].name = "#GUID";
1511 stream_desc [4].stream = &assembly->guid;
1513 /* tables that are sorted */
1514 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1515 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1516 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1517 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1518 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1519 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
1520 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
1522 /* Compute table sizes */
1523 /* the MonoImage has already been created in mono_reflection_dynimage_basic_init() */
1524 meta = &assembly->image;
1526 /* sizes should be multiple of 4 */
1527 mono_dynstream_data_align (&assembly->blob);
1528 mono_dynstream_data_align (&assembly->guid);
1529 mono_dynstream_data_align (&assembly->sheap);
1530 mono_dynstream_data_align (&assembly->us);
1532 /* Setup the info used by compute_sizes () */
1533 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1534 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1535 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1537 meta_size += assembly->blob.index;
1538 meta_size += assembly->guid.index;
1539 meta_size += assembly->sheap.index;
1540 meta_size += assembly->us.index;
1542 for (i=0; i < MONO_TABLE_NUM; ++i)
1543 meta->tables [i].rows = assembly->tables [i].rows;
1545 for (i = 0; i < MONO_TABLE_NUM; i++){
1546 if (meta->tables [i].rows == 0)
1548 valid_mask |= (guint64)1 << i;
1550 meta->tables [i].row_size = mono_metadata_compute_size (
1551 meta, i, &meta->tables [i].size_bitfield);
1552 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1554 heapt_size += 24; /* #~ header size */
1555 heapt_size += ntables * 4;
1556 /* make multiple of 4 */
1559 meta_size += heapt_size;
1560 meta->raw_metadata = (char *)g_malloc0 (meta_size);
1561 p = (unsigned char*)meta->raw_metadata;
1562 /* the metadata signature */
1563 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1564 /* version numbers and 4 bytes reserved */
1565 int16val = (guint16*)p;
1566 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
1567 *int16val = GUINT16_TO_LE (meta->md_version_minor);
1569 /* version string */
1570 int32val = (guint32*)p;
1571 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
1573 memcpy (p, meta->version, strlen (meta->version));
1574 p += GUINT32_FROM_LE (*int32val);
1575 align_pointer (meta->raw_metadata, p);
1576 int16val = (guint16*)p;
1577 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1578 *int16val = GUINT16_TO_LE (5); /* number of streams */
1582 * write the stream info.
1584 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1585 table_offset += 3; table_offset &= ~3;
1587 assembly->tstream.index = heapt_size;
1588 for (i = 0; i < 5; ++i) {
1589 int32val = (guint32*)p;
1590 stream_desc [i].stream->offset = table_offset;
1591 *int32val++ = GUINT32_TO_LE (table_offset);
1592 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1593 table_offset += GUINT32_FROM_LE (*int32val);
1594 table_offset += 3; table_offset &= ~3;
1596 strcpy ((char*)p, stream_desc [i].name);
1597 p += strlen (stream_desc [i].name) + 1;
1598 align_pointer (meta->raw_metadata, p);
1601 * now copy the data, the table stream header and contents goes first.
1603 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1604 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
1605 int32val = (guint32*)p;
1606 *int32val = GUINT32_TO_LE (0); /* reserved */
1609 *p++ = 2; /* version */
1612 if (meta->idx_string_wide)
1614 if (meta->idx_guid_wide)
1616 if (meta->idx_blob_wide)
1619 *p++ = 1; /* reserved */
1620 int64val = (guint64*)p;
1621 *int64val++ = GUINT64_TO_LE (valid_mask);
1622 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
1624 int32val = (guint32*)p;
1625 for (i = 0; i < MONO_TABLE_NUM; i++){
1626 if (meta->tables [i].rows == 0)
1628 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1630 p = (unsigned char*)int32val;
1632 /* sort the tables that still need sorting */
1633 table = &assembly->tables [MONO_TABLE_CONSTANT];
1635 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
1636 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1638 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1639 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1641 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1642 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1644 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1645 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1647 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1648 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
1649 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1651 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
1652 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1654 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
1656 /* compress the tables */
1657 for (i = 0; i < MONO_TABLE_NUM; i++){
1660 guint32 bitfield = meta->tables [i].size_bitfield;
1661 if (!meta->tables [i].rows)
1663 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1664 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1665 meta->tables [i].base = (char*)p;
1666 for (row = 1; row <= meta->tables [i].rows; ++row) {
1667 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1668 for (col = 0; col < assembly->tables [i].columns; ++col) {
1669 switch (mono_metadata_table_size (bitfield, col)) {
1671 *p++ = values [col];
1674 *p++ = values [col] & 0xff;
1675 *p++ = (values [col] >> 8) & 0xff;
1678 *p++ = values [col] & 0xff;
1679 *p++ = (values [col] >> 8) & 0xff;
1680 *p++ = (values [col] >> 16) & 0xff;
1681 *p++ = (values [col] >> 24) & 0xff;
1684 g_assert_not_reached ();
1688 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1691 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1692 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1693 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1694 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1695 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1697 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1703 * Some tables in metadata need to be sorted according to some criteria, but
1704 * when methods and fields are first created with reflection, they may be assigned a token
1705 * that doesn't correspond to the final token they will get assigned after the sorting.
1706 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1707 * with the reflection objects that represent them. Once all the tables are set up, the
1708 * reflection objects will contains the correct table index. fixup_method() will fixup the
1709 * tokens for the method with ILGenerator @ilgen.
1712 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
1714 guint32 code_idx = GPOINTER_TO_UINT (value);
1715 MonoReflectionILTokenInfo *iltoken;
1716 MonoReflectionTypeBuilder *tb;
1717 MonoReflectionArrayMethod *am;
1719 unsigned char *target;
1721 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1722 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1723 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
1724 switch (target [3]) {
1725 case MONO_TABLE_FIELD:
1726 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1727 g_assert_not_reached ();
1728 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1729 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
1730 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
1732 g_assert_not_reached ();
1735 case MONO_TABLE_METHOD:
1736 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1737 g_assert_not_reached ();
1738 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1739 g_assert_not_reached ();
1740 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
1741 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1742 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1743 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1745 g_assert_not_reached ();
1748 case MONO_TABLE_TYPEDEF:
1749 if (!strcmp (iltoken->member->vtable->klass->name, "TypeBuilder")) {
1750 g_assert_not_reached ();
1751 } else if (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType")) {
1752 MonoClass *k = mono_class_from_mono_type (((MonoReflectionType*)iltoken->member)->type);
1753 MonoObject *obj = mono_class_get_ref_info_raw (k); /* FIXME use handles */
1755 g_assert (!strcmp (mono_object_class (obj)->name, "TypeBuilder"));
1756 tb = (MonoReflectionTypeBuilder*)obj;
1757 idx = tb->table_idx;
1759 g_assert_not_reached ();
1762 case MONO_TABLE_TYPEREF:
1763 g_assert (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType"));
1764 MonoClass *k = mono_class_from_mono_type (((MonoReflectionType*)iltoken->member)->type);
1765 MonoObject *obj = mono_class_get_ref_info_raw (k); /* FIXME use handles */
1767 g_assert (!strcmp (mono_object_class (obj)->name, "TypeBuilder"));
1768 g_assert (((MonoReflectionTypeBuilder*)obj)->module->dynamic_image != assembly);
1770 case MONO_TABLE_MEMBERREF:
1771 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
1772 am = (MonoReflectionArrayMethod*)iltoken->member;
1773 idx = am->table_idx;
1774 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
1775 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1776 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1777 g_assert (mono_class_is_ginst (m->klass) || mono_class_is_gtd (m->klass));
1779 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1780 g_assert_not_reached ();
1782 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1784 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
1785 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1786 g_assert_not_reached ();
1788 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
1789 g_assert_not_reached ();
1791 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1792 g_assert_not_reached ();
1794 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
1795 g_assert_not_reached ();
1798 g_assert_not_reached ();
1801 case MONO_TABLE_METHODSPEC:
1802 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
1803 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1804 g_assert (mono_method_signature (m)->generic_param_count);
1806 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1807 g_assert_not_reached ();
1809 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1810 g_assert_not_reached ();
1813 g_assert_not_reached ();
1816 case MONO_TABLE_TYPESPEC:
1817 if (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType")) {
1820 g_assert_not_reached ();
1824 g_error ("got unexpected table 0x%02x in fixup", target [3]);
1826 target [0] = idx & 0xff;
1827 target [1] = (idx >> 8) & 0xff;
1828 target [2] = (idx >> 16) & 0xff;
1835 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
1836 * value is not known when the table is emitted.
1839 fixup_cattrs (MonoDynamicImage *assembly)
1841 MonoDynamicTable *table;
1843 guint32 type, i, idx, token;
1846 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1848 for (i = 0; i < table->rows; ++i) {
1849 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
1851 type = values [MONO_CUSTOM_ATTR_TYPE];
1852 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
1853 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
1854 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
1855 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
1858 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
1859 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
1860 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1861 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1862 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
1863 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
1864 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1865 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1872 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
1874 MonoDynamicTable *table;
1879 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
1881 alloc_table (table, table->rows);
1882 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
1883 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
1884 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
1885 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
1886 return_val_if_nok (error, FALSE);
1887 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
1893 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
1895 MonoDynamicTable *table;
1899 char *b = blob_size;
1901 guint32 idx, offset;
1905 if (rsrc->filename) {
1906 name = mono_string_to_utf8_checked (rsrc->filename, error);
1907 return_val_if_nok (error, FALSE);
1908 sname = g_path_get_basename (name);
1910 table = &assembly->tables [MONO_TABLE_FILE];
1912 alloc_table (table, table->rows);
1913 values = table->values + table->next_idx * MONO_FILE_SIZE;
1914 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
1915 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
1918 mono_sha1_get_digest_from_file (name, hash);
1919 mono_metadata_encode_value (20, b, &b);
1920 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1921 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1923 idx = table->next_idx++;
1925 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
1931 data = mono_array_addr (rsrc->data, char, 0);
1932 len = mono_array_length (rsrc->data);
1938 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
1939 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
1940 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
1941 mono_image_add_stream_data (&assembly->resources, data, len);
1945 * The entry should be emitted into the MANIFESTRESOURCE table of
1946 * the main module, but that needs to reference the FILE table
1947 * which isn't emitted yet.
1954 return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
1958 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
1960 gchar *ver, *p, *str;
1965 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1966 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1967 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1968 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1971 ver = str = mono_string_to_utf8_checked (version, error);
1972 return_val_if_nok (error, FALSE);
1973 for (i = 0; i < 4; ++i) {
1974 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
1980 /* handle Revision and Build */
1991 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
1995 char *b = blob_size;
2000 len = mono_array_length (pkey);
2001 mono_metadata_encode_value (len, b, &b);
2002 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2003 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
2005 assembly->public_key = (guint8 *)g_malloc (len);
2006 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
2007 assembly->public_key_len = len;
2009 /* Special case: check for ECMA key (16 bytes) */
2010 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
2011 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
2012 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
2013 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
2014 /* minimum key size (in 2.0) is 384 bits */
2015 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
2017 /* FIXME - verifier */
2018 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
2019 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
2021 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
2027 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2029 MonoDynamicTable *table;
2030 MonoDynamicImage *assembly;
2031 MonoReflectionAssemblyBuilder *assemblyb;
2035 guint32 module_index;
2039 assemblyb = moduleb->assemblyb;
2040 assembly = moduleb->dynamic_image;
2041 domain = mono_object_domain (assemblyb);
2043 /* Emit ASSEMBLY table */
2044 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2045 alloc_table (table, 1);
2046 values = table->values + MONO_ASSEMBLY_SIZE;
2047 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2048 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
2049 return_val_if_nok (error, FALSE);
2050 if (assemblyb->culture) {
2051 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
2052 return_val_if_nok (error, FALSE);
2054 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2056 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
2057 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2058 if (!set_version_from_string (assemblyb->version, values, error))
2061 /* Emit FILE + EXPORTED_TYPE table */
2063 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2065 MonoReflectionModuleBuilder *file_module =
2066 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2067 if (file_module != moduleb) {
2068 if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
2071 if (file_module->types) {
2072 for (j = 0; j < file_module->num_types; ++j) {
2073 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
2074 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
2075 return_val_if_nok (error, FALSE);
2080 if (assemblyb->loaded_modules) {
2081 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
2082 MonoReflectionModule *file_module =
2083 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
2084 if (!mono_image_fill_file_table (domain, file_module, assembly, error))
2087 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
2090 if (assemblyb->type_forwarders)
2091 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
2093 /* Emit MANIFESTRESOURCE table */
2095 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2097 MonoReflectionModuleBuilder *file_module =
2098 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2099 /* The table for the main module is emitted later */
2100 if (file_module != moduleb) {
2102 if (file_module->resources) {
2103 int len = mono_array_length (file_module->resources);
2104 for (j = 0; j < len; ++j) {
2105 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
2106 if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
2115 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2118 * Insert into the metadata tables all the info about the TypeBuilder tb.
2119 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2122 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
2124 MonoDynamicTable *table;
2126 int i, is_object = 0, is_system = 0;
2131 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2132 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2133 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2134 n = mono_string_to_utf8_checked (tb->name, error);
2135 return_val_if_nok (error, FALSE);
2136 if (strcmp (n, "Object") == 0)
2138 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2140 n = mono_string_to_utf8_checked (tb->nspace, error);
2141 return_val_if_nok (error, FALSE);
2142 if (strcmp (n, "System") == 0)
2144 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2146 if (tb->parent && !(is_system && is_object) &&
2147 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2148 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
2149 return_val_if_nok (error, FALSE);
2150 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
2152 values [MONO_TYPEDEF_EXTENDS] = 0;
2154 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2155 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2158 * if we have explicitlayout or sequentiallayouts, output data in the
2159 * ClassLayout table.
2161 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2162 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2163 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2165 alloc_table (table, table->rows);
2166 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2167 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2168 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2169 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2172 /* handle interfaces */
2173 if (tb->interfaces) {
2174 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2176 table->rows += mono_array_length (tb->interfaces);
2177 alloc_table (table, table->rows);
2178 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2179 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2180 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2181 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
2182 return_val_if_nok (error, FALSE);
2183 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2184 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
2185 values += MONO_INTERFACEIMPL_SIZE;
2191 table = &assembly->tables [MONO_TABLE_FIELD];
2192 table->rows += tb->num_fields;
2193 alloc_table (table, table->rows);
2194 for (i = 0; i < tb->num_fields; ++i) {
2195 mono_image_get_field_info (
2196 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
2197 return_val_if_nok (error, FALSE);
2201 /* handle constructors */
2203 table = &assembly->tables [MONO_TABLE_METHOD];
2204 table->rows += mono_array_length (tb->ctors);
2205 alloc_table (table, table->rows);
2206 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2207 if (!mono_image_get_ctor_info (domain,
2208 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
2214 /* handle methods */
2216 table = &assembly->tables [MONO_TABLE_METHOD];
2217 table->rows += tb->num_methods;
2218 alloc_table (table, table->rows);
2219 for (i = 0; i < tb->num_methods; ++i) {
2220 if (!mono_image_get_method_info (
2221 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
2226 /* Do the same with properties etc.. */
2227 if (tb->events && mono_array_length (tb->events)) {
2228 table = &assembly->tables [MONO_TABLE_EVENT];
2229 table->rows += mono_array_length (tb->events);
2230 alloc_table (table, table->rows);
2231 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2233 alloc_table (table, table->rows);
2234 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2235 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2236 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2237 for (i = 0; i < mono_array_length (tb->events); ++i) {
2238 mono_image_get_event_info (
2239 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
2240 return_val_if_nok (error, FALSE);
2243 if (tb->properties && mono_array_length (tb->properties)) {
2244 table = &assembly->tables [MONO_TABLE_PROPERTY];
2245 table->rows += mono_array_length (tb->properties);
2246 alloc_table (table, table->rows);
2247 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2249 alloc_table (table, table->rows);
2250 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2251 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2252 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2253 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2254 mono_image_get_property_info (
2255 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
2256 return_val_if_nok (error, FALSE);
2260 /* handle generic parameters */
2261 if (tb->generic_params) {
2262 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2263 table->rows += mono_array_length (tb->generic_params);
2264 alloc_table (table, table->rows);
2265 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2266 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2268 mono_image_get_generic_param_info (
2269 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2273 mono_image_add_decl_security (assembly,
2274 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2277 MonoDynamicTable *ntable;
2279 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2280 ntable->rows += mono_array_length (tb->subtypes);
2281 alloc_table (ntable, ntable->rows);
2282 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2284 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2285 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2287 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2288 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2289 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2290 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2291 mono_string_to_utf8 (tb->name), tb->table_idx,
2292 ntable->next_idx, ntable->rows);*/
2293 values += MONO_NESTED_CLASS_SIZE;
2303 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2304 * for the modulebuilder @moduleb.
2305 * At the end of the process, method and field tokens are fixed up and the
2306 * on-disk compressed metadata representation is created.
2307 * Return TRUE on success, or FALSE on failure and sets @error
2310 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2312 MonoDynamicTable *table;
2313 MonoDynamicImage *assembly;
2314 MonoReflectionAssemblyBuilder *assemblyb;
2322 assemblyb = moduleb->assemblyb;
2323 assembly = moduleb->dynamic_image;
2324 domain = mono_object_domain (assemblyb);
2326 if (assembly->text_rva)
2329 assembly->text_rva = START_TEXT_RVA;
2331 if (moduleb->is_main) {
2332 mono_image_emit_manifest (moduleb, error);
2333 return_val_if_nok (error, FALSE);
2336 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2337 table->rows = 1; /* .<Module> */
2339 alloc_table (table, table->rows);
2341 * Set the first entry.
2343 values = table->values + table->columns;
2344 values [MONO_TYPEDEF_FLAGS] = 0;
2345 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2346 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2347 values [MONO_TYPEDEF_EXTENDS] = 0;
2348 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2349 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2352 * handle global methods
2353 * FIXME: test what to do when global methods are defined in multiple modules.
2355 if (moduleb->global_methods) {
2356 table = &assembly->tables [MONO_TABLE_METHOD];
2357 table->rows += mono_array_length (moduleb->global_methods);
2358 alloc_table (table, table->rows);
2359 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2360 if (!mono_image_get_method_info (
2361 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
2365 if (moduleb->global_fields) {
2366 table = &assembly->tables [MONO_TABLE_FIELD];
2367 table->rows += mono_array_length (moduleb->global_fields);
2368 alloc_table (table, table->rows);
2369 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
2370 mono_image_get_field_info (
2371 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
2378 table = &assembly->tables [MONO_TABLE_MODULE];
2379 alloc_table (table, 1);
2380 mono_image_fill_module_table (domain, moduleb, assembly, error);
2384 /* Collect all types into a list sorted by their table_idx */
2385 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
2388 for (i = 0; i < moduleb->num_types; ++i) {
2389 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
2390 collect_types (&types, type);
2393 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
2394 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2395 table->rows += mono_ptr_array_size (types);
2396 alloc_table (table, table->rows);
2399 * Emit type names + namespaces at one place inside the string heap,
2400 * so load_class_names () needs to touch fewer pages.
2402 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2403 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2404 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
2408 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2409 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2410 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
2415 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2416 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2417 if (!mono_image_get_type_info (domain, type, assembly, error))
2422 * table->rows is already set above and in mono_image_fill_module_table.
2424 /* add all the custom attributes at the end, once all the indexes are stable */
2425 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
2428 /* CAS assembly permissions */
2429 if (assemblyb->permissions_minimum)
2430 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
2431 if (assemblyb->permissions_optional)
2432 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
2433 if (assemblyb->permissions_refused)
2434 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
2436 if (!module_add_cattrs (assembly, moduleb, error))
2440 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2442 /* Create the MethodImpl table. We do this after emitting all methods so we already know
2443 * the final tokens and don't need another fixup pass. */
2445 if (moduleb->global_methods) {
2446 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2447 MonoReflectionMethodBuilder *mb = mono_array_get (
2448 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
2449 if (!mono_image_add_methodimpl (assembly, mb, error))
2454 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2455 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2456 if (type->methods) {
2457 for (j = 0; j < type->num_methods; ++j) {
2458 MonoReflectionMethodBuilder *mb = mono_array_get (
2459 type->methods, MonoReflectionMethodBuilder*, j);
2461 if (!mono_image_add_methodimpl (assembly, mb, error))
2467 fixup_cattrs (assembly);
2470 mono_ptr_array_destroy (types);
2473 return mono_error_ok (error);
2476 #else /* DISABLE_REFLECTION_EMIT_SAVE */
2479 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2481 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
2484 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
2486 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2489 calc_section_size (MonoDynamicImage *assembly)
2493 /* alignment constraints */
2494 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
2495 g_assert ((assembly->code.index % 4) == 0);
2496 assembly->meta_size += 3;
2497 assembly->meta_size &= ~3;
2498 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
2499 g_assert ((assembly->resources.index % 4) == 0);
2501 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2502 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2505 if (assembly->win32_res) {
2506 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
2508 assembly->sections [MONO_SECTION_RSRC].size = res_size;
2509 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
2513 assembly->sections [MONO_SECTION_RELOC].size = 12;
2514 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2524 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
2528 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
2530 ResTreeNode *t1 = (ResTreeNode*)a;
2531 ResTreeNode *t2 = (ResTreeNode*)b;
2533 return t1->id - t2->id;
2537 * resource_tree_create:
2539 * Organize the resources into a resource tree.
2541 static ResTreeNode *
2542 resource_tree_create (MonoArray *win32_resources)
2544 ResTreeNode *tree, *res_node, *type_node, *lang_node;
2548 tree = g_new0 (ResTreeNode, 1);
2550 for (i = 0; i < mono_array_length (win32_resources); ++i) {
2551 MonoReflectionWin32Resource *win32_res =
2552 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
2556 /* FIXME: BUG: this stores managed references in unmanaged memory */
2557 lang_node = g_new0 (ResTreeNode, 1);
2558 lang_node->id = win32_res->lang_id;
2559 lang_node->win32_res = win32_res;
2561 /* Create type node if neccesary */
2563 for (l = tree->children; l; l = l->next)
2564 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
2565 type_node = (ResTreeNode*)l->data;
2570 type_node = g_new0 (ResTreeNode, 1);
2571 type_node->id = win32_res->res_type;
2574 * The resource types have to be sorted otherwise
2575 * Windows Explorer can't display the version information.
2577 tree->children = g_slist_insert_sorted (tree->children,
2578 type_node, resource_tree_compare_by_id);
2581 /* Create res node if neccesary */
2583 for (l = type_node->children; l; l = l->next)
2584 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
2585 res_node = (ResTreeNode*)l->data;
2590 res_node = g_new0 (ResTreeNode, 1);
2591 res_node->id = win32_res->res_id;
2592 type_node->children = g_slist_append (type_node->children, res_node);
2595 res_node->children = g_slist_append (res_node->children, lang_node);
2602 * resource_tree_encode:
2604 * Encode the resource tree into the format used in the PE file.
2607 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
2610 MonoPEResourceDir dir;
2611 MonoPEResourceDirEntry dir_entry;
2612 MonoPEResourceDataEntry data_entry;
2614 guint32 res_id_entries;
2617 * For the format of the resource directory, see the article
2618 * "An In-Depth Look into the Win32 Portable Executable File Format" by
2622 memset (&dir, 0, sizeof (dir));
2623 memset (&dir_entry, 0, sizeof (dir_entry));
2624 memset (&data_entry, 0, sizeof (data_entry));
2626 g_assert (sizeof (dir) == 16);
2627 g_assert (sizeof (dir_entry) == 8);
2628 g_assert (sizeof (data_entry) == 16);
2630 node->offset = p - begin;
2632 /* IMAGE_RESOURCE_DIRECTORY */
2633 res_id_entries = g_slist_length (node->children);
2634 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
2636 memcpy (p, &dir, sizeof (dir));
2639 /* Reserve space for entries */
2641 p += sizeof (dir_entry) * res_id_entries;
2643 /* Write children */
2644 for (l = node->children; l; l = l->next) {
2645 ResTreeNode *child = (ResTreeNode*)l->data;
2647 if (child->win32_res) {
2650 child->offset = p - begin;
2652 /* IMAGE_RESOURCE_DATA_ENTRY */
2653 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
2654 size = mono_array_length (child->win32_res->res_data);
2655 data_entry.rde_size = GUINT32_TO_LE (size);
2657 memcpy (p, &data_entry, sizeof (data_entry));
2658 p += sizeof (data_entry);
2660 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
2663 resource_tree_encode (child, begin, p, &p);
2667 /* IMAGE_RESOURCE_ENTRY */
2668 for (l = node->children; l; l = l->next) {
2669 ResTreeNode *child = (ResTreeNode*)l->data;
2671 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
2672 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
2674 memcpy (entries, &dir_entry, sizeof (dir_entry));
2675 entries += sizeof (dir_entry);
2682 resource_tree_free (ResTreeNode * node)
2685 for (list = node->children; list; list = list->next)
2686 resource_tree_free ((ResTreeNode*)list->data);
2687 g_slist_free(node->children);
2692 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
2697 MonoReflectionWin32Resource *win32_res;
2700 if (!assemblyb->win32_resources)
2704 * Resources are stored in a three level tree inside the PE file.
2705 * - level one contains a node for each type of resource
2706 * - level two contains a node for each resource
2707 * - level three contains a node for each instance of a resource for a
2708 * specific language.
2711 tree = resource_tree_create (assemblyb->win32_resources);
2713 /* Estimate the size of the encoded tree */
2715 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
2716 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
2717 size += mono_array_length (win32_res->res_data);
2719 /* Directory structure */
2720 size += mono_array_length (assemblyb->win32_resources) * 256;
2721 p = buf = (char *)g_malloc (size);
2723 resource_tree_encode (tree, p, p, &p);
2725 g_assert (p - buf <= size);
2727 assembly->win32_res = (char *)g_malloc (p - buf);
2728 assembly->win32_res_size = p - buf;
2729 memcpy (assembly->win32_res, buf, p - buf);
2732 resource_tree_free (tree);
2736 fixup_resource_directory (char *res_section, char *p, guint32 rva)
2738 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
2741 p += sizeof (MonoPEResourceDir);
2742 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
2743 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
2744 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
2745 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
2746 fixup_resource_directory (res_section, child, rva);
2748 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
2749 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
2752 p += sizeof (MonoPEResourceDirEntry);
2757 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
2760 if (!mono_w32file_write (f, buffer, numbytes, &dummy))
2761 g_error ("mono_w32file_write returned %d\n", mono_w32error_get_last ());
2765 * mono_image_create_pefile:
2766 * @mb: a module builder object
2768 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
2769 * assembly->pefile where it can be easily retrieved later in chunks.
2772 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
2774 MonoMSDOSHeader *msdos;
2775 MonoDotNetHeader *header;
2776 MonoSectionTable *section;
2777 MonoCLIHeader *cli_header;
2778 guint32 size, image_size, virtual_base, text_offset;
2779 guint32 header_start, section_start, file_offset, virtual_offset;
2780 MonoDynamicImage *assembly;
2781 MonoReflectionAssemblyBuilder *assemblyb;
2782 MonoDynamicStream pefile_stream = {0};
2783 MonoDynamicStream *pefile = &pefile_stream;
2785 guint32 *rva, value;
2787 static const unsigned char msheader[] = {
2788 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2789 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2792 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2793 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2794 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2795 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2800 assemblyb = mb->assemblyb;
2802 mono_reflection_dynimage_basic_init (assemblyb);
2803 assembly = mb->dynamic_image;
2805 assembly->pe_kind = assemblyb->pe_kind;
2806 assembly->machine = assemblyb->machine;
2807 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
2808 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
2810 if (!mono_image_build_metadata (mb, error))
2814 if (mb->is_main && assemblyb->resources) {
2815 int len = mono_array_length (assemblyb->resources);
2816 for (i = 0; i < len; ++i) {
2817 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
2822 if (mb->resources) {
2823 int len = mono_array_length (mb->resources);
2824 for (i = 0; i < len; ++i) {
2825 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
2830 if (!build_compressed_metadata (assembly, error))
2834 assembly_add_win32_resources (assembly, assemblyb);
2836 nsections = calc_section_size (assembly);
2838 /* The DOS header and stub */
2839 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2840 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
2842 /* the dotnet header */
2843 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2845 /* the section tables */
2846 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2848 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2849 virtual_offset = VIRT_ALIGN;
2852 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2853 if (!assembly->sections [i].size)
2856 file_offset += FILE_ALIGN - 1;
2857 file_offset &= ~(FILE_ALIGN - 1);
2858 virtual_offset += VIRT_ALIGN - 1;
2859 virtual_offset &= ~(VIRT_ALIGN - 1);
2861 assembly->sections [i].offset = file_offset;
2862 assembly->sections [i].rva = virtual_offset;
2864 file_offset += assembly->sections [i].size;
2865 virtual_offset += assembly->sections [i].size;
2866 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2869 file_offset += FILE_ALIGN - 1;
2870 file_offset &= ~(FILE_ALIGN - 1);
2872 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2874 /* back-patch info */
2875 msdos = (MonoMSDOSHeader*)pefile->data;
2876 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2878 header = (MonoDotNetHeader*)(pefile->data + header_start);
2879 header->pesig [0] = 'P';
2880 header->pesig [1] = 'E';
2882 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
2883 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2884 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2885 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2886 if (assemblyb->pekind == 1) {
2888 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2891 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2894 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2896 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2897 header->pe.pe_major = 6;
2898 header->pe.pe_minor = 0;
2899 size = assembly->sections [MONO_SECTION_TEXT].size;
2900 size += FILE_ALIGN - 1;
2901 size &= ~(FILE_ALIGN - 1);
2902 header->pe.pe_code_size = GUINT32_FROM_LE(size);
2903 size = assembly->sections [MONO_SECTION_RSRC].size;
2904 size += FILE_ALIGN - 1;
2905 size &= ~(FILE_ALIGN - 1);
2906 header->pe.pe_data_size = GUINT32_FROM_LE(size);
2907 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2908 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2909 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2910 /* pe_rva_entry_point always at the beginning of the text section */
2911 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2913 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2914 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2915 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2916 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2917 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2918 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2919 size = section_start;
2920 size += FILE_ALIGN - 1;
2921 size &= ~(FILE_ALIGN - 1);
2922 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2924 size += VIRT_ALIGN - 1;
2925 size &= ~(VIRT_ALIGN - 1);
2926 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2929 // Translate the PEFileKind value to the value expected by the Windows loader
2935 // PEFileKinds.Dll == 1
2936 // PEFileKinds.ConsoleApplication == 2
2937 // PEFileKinds.WindowApplication == 3
2940 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2941 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2943 if (assemblyb->pekind == 3)
2948 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2950 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2951 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2952 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2953 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2954 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2955 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2957 /* fill data directory entries */
2959 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2960 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2962 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2963 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2965 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2966 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2967 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2968 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2969 /* patch entrypoint name */
2970 if (assemblyb->pekind == 1)
2971 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
2973 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
2974 /* patch imported function RVA name */
2975 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2976 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2978 /* the import table */
2979 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2980 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2981 /* patch imported dll RVA name and other entries in the dir */
2982 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2983 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
2984 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2985 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2986 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2987 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2989 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
2990 value = (assembly->text_rva + assembly->imp_names_offset);
2991 *p++ = (value) & 0xff;
2992 *p++ = (value >> 8) & (0xff);
2993 *p++ = (value >> 16) & (0xff);
2994 *p++ = (value >> 24) & (0xff);
2996 /* the CLI header info */
2997 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2998 cli_header->ch_size = GUINT32_FROM_LE (72);
2999 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3000 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
3001 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
3002 if (assemblyb->entry_point) {
3003 guint32 table_idx = 0;
3004 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
3005 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
3006 table_idx = methodb->table_idx;
3008 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
3010 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
3012 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3014 /* The embedded managed resources */
3015 text_offset = assembly->text_rva + assembly->code.index;
3016 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3017 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3018 text_offset += assembly->resources.index;
3019 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3020 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3021 text_offset += assembly->meta_size;
3022 if (assembly->strong_name_size) {
3023 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3024 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3025 text_offset += assembly->strong_name_size;
3028 /* write the section tables and section content */
3029 section = (MonoSectionTable*)(pefile->data + section_start);
3030 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3031 static const char section_names [][7] = {
3032 ".text", ".rsrc", ".reloc"
3034 if (!assembly->sections [i].size)
3036 strcpy (section->st_name, section_names [i]);
3037 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3038 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3039 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3040 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3041 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3042 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3043 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3047 checked_write_file (file, pefile->data, pefile->index);
3049 mono_dynamic_stream_reset (pefile);
3051 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3052 if (!assembly->sections [i].size)
3055 if (mono_w32file_seek (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3056 g_error ("mono_w32file_seek returned %d\n", mono_w32error_get_last ());
3059 case MONO_SECTION_TEXT:
3060 /* patch entry point */
3061 p = (guchar*)(assembly->code.data + 2);
3062 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3063 *p++ = (value) & 0xff;
3064 *p++ = (value >> 8) & 0xff;
3065 *p++ = (value >> 16) & 0xff;
3066 *p++ = (value >> 24) & 0xff;
3068 checked_write_file (file, assembly->code.data, assembly->code.index);
3069 checked_write_file (file, assembly->resources.data, assembly->resources.index);
3070 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
3071 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
3074 g_free (assembly->image.raw_metadata);
3076 case MONO_SECTION_RELOC: {
3080 guint16 type_and_offset;
3084 g_assert (sizeof (reloc) == 12);
3086 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
3087 reloc.block_size = GUINT32_FROM_LE (12);
3090 * the entrypoint is always at the start of the text section
3091 * 3 is IMAGE_REL_BASED_HIGHLOW
3092 * 2 is patch_size_rva - text_rva
3094 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
3097 checked_write_file (file, &reloc, sizeof (reloc));
3101 case MONO_SECTION_RSRC:
3102 if (assembly->win32_res) {
3104 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
3105 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
3106 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
3110 g_assert_not_reached ();
3114 /* check that the file is properly padded */
3115 if (mono_w32file_seek (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3116 g_error ("mono_w32file_seek returned %d\n", mono_w32error_get_last ());
3117 if (! mono_w32file_truncate (file))
3118 g_error ("mono_w32file_truncate returned %d\n", mono_w32error_get_last ());
3120 mono_dynamic_stream_reset (&assembly->code);
3121 mono_dynamic_stream_reset (&assembly->us);
3122 mono_dynamic_stream_reset (&assembly->blob);
3123 mono_dynamic_stream_reset (&assembly->guid);
3124 mono_dynamic_stream_reset (&assembly->sheap);
3126 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
3127 g_hash_table_destroy (assembly->blob_cache);
3128 assembly->blob_cache = NULL;
3133 #else /* DISABLE_REFLECTION_EMIT_SAVE */
3136 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
3138 g_assert_not_reached ();
3141 #endif /* DISABLE_REFLECTION_EMIT_SAVE */